//- TODO

//- https://mathiasbynens.be/notes/javascript-unicode
//- https://mathiasbynens.be/notes/javascript-encoding
//- https://mathiasbynens.be/notes/javascript-escapes

//- Punycode
//- https://en.wikipedia.org/wiki/Punycode
//- https://github.com/bestiejs/punycode.js
//- https://www.punycoder.com/

//- More Unicode chars
//- http://qaz.wtf/u/convert.cgi?text=ABCDEFGHIJKLMNOPQRSTUVWXYZ
//- http://qaz.wtf/u/braille.cgi?text=AAABB
//- http://www.fileformat.info/info/unicode/char/283f/fontsupport.htm
//- https://jrgraphix.net/r/Unicode/
//- http://jkorpela.fi/chars/spaces.html

//- https://css-tricks.com/snippets/html/glyphs/
//- http://www.evotech.net/articles/testjsentities.html

//- https://codebeautify.org/

//- https://www.webtoolkitonline.com/

//- https://passwordsgenerator.net/
//- https://passwordsgenerator.net/qr-code-generator/
//- https://passwordsgenerator.net/base64-decode/
//- https://passwordsgenerator.net/md5-hash-generator/
//- https://passwordsgenerator.net/sha1-hash-generator/
//- https://passwordsgenerator.net/sha256-hash-generator/
//- https://passwordsgenerator.net/sha512-hash-generator/

//- https://github.com/indutny/hash.js

//- https://www.papaparse.com/

//- https://vis4.net/chromajs/

//- http://www.convertcsv.com/

//- https://github.com/nodeca/js-yaml
//- https://github.com/uglyog/clientside-haml-js

//- http://beautifytools.com/

//- CSV to HTML Table
//- HTML Table to CSV

//- JSON to HTML Table
//- HTML Table to JSON (Done)

//- CSV To XML
// XML to CSV

//- Sample GPX file
//- GPX to CSV
//- CSV to GPX

main
    textarea#main-textarea.main-textarea(placeholder="Paste or type your text here\u2026")
    p.textarea-options-wrapper
        div.word-wrap-wrapper
            input(type="checkbox")#word-wrap-checkbox
            label(for="word-wrap-checkbox") Word wrap
aside
    fieldset.general-fieldset
        legend General
        div.fieldset-content.general-fieldset-content
            button.btn#btn-clear-textarea Clear text
            button.btn#btn-collapse-panels Collapse panels
            button.btn#btn-expand-panels Expand panels
    fieldset
        legend Clipboard
        div.fieldset-content.clipboard-fieldset-content
            button.btn#btn-clipboard-select-all Select all
            button.btn#btn-clipboard-copy(data-clipboard-action="copy" data-clipboard-target="#main-textarea") Copy text
            button.btn#btn-clipboard-cut(data-clipboard-action="copy" data-clipboard-target="#main-textarea") Cut text
    fieldset
        legend#history-legend History
        div.fieldset-content
            button.btn#btn-history-undo(disabled) Undo (Ctrl+Z)
            button.btn#btn-history-redo(disabled) Redo (Ctrl+Y)
            button.btn#btn-history-clear(disabled) Clear history (Ctrl+H)
    fieldset
        legend Font
        div.fieldset-content
            p.font-subheading Family
            select#font-family
                option.font-family-monospaced(value="Source Code Pro") Source Code Pro
                option.font-family-monospaced(value="'Roboto Mono', Consolas, monaco, monospace" selected) Monospaced
                option.font-family-sansserif(value="'Helvetica Neue', Helvetica, Arial, sans-serif") Sans-serif
                option.font-family-serif(value="TimesNewRoman, 'Times New Roman', Times, Baskerville, Georgia, serif") Serif
            p.font-subheading Size
            select#font-size
                option(value="1px") 1px
                option(value="2px") 2px
                option(value="3px") 3px
                option(value="4px") 4px
                option(value="5px") 5px
                option(value="6px") 6px
                option(value="7px") 7px
                option(value="8px") 8px
                option(value="9px") 9px
                option(value="10px") 10px
                option(value="11px") 11px
                option(value="12px") 12px
                option(value="13px") 13px
                option(value="14px") 14px
                option(value="15px") 15px
                option(value="16px") 16px
                option(value="17px") 17px
                option(value="18px" selected) 18px
                option(value="20px") 20px
                option(value="22px") 22px
                option(value="24px") 24px
                option(value="26px") 26px
                option(value="28px") 28px
                option(value="30px") 30px
                option(value="32px") 32px
                option(value="34px") 34px
                option(value="36px") 36px
                option(value="38px") 38px
                option(value="40px") 40px
                option(value="42px") 42px
                option(value="44px") 44px
                option(value="46px") 46px
                option(value="48px") 48px
                option(value="50px") 50px
                option(value="52px") 52px
                option(value="54px") 54px
                option(value="56px") 56px
                option(value="58px") 58px
                option(value="60px") 60px
                option(value="62px") 62px
                option(value="64px") 64px
                option(value="66px") 66px
                option(value="68px") 68px
                option(value="70px") 70px
                option(value="80px") 80px
                option(value="90px") 90px
                option(value="100px") 100px
                option(value="110px") 110px
                option(value="120px") 120px
                option(value="130px") 130px
                option(value="140px") 140px
                option(value="150px") 150px
            p.font-subheading Weight
            select#font-weight
                option(value="lighter" selected) Lighter
                option(value="normal") Normal
                option(value="bolder") Bolder
                option(value="bold") Bold
            p.font-subheading Line height
            select#line-height
                option(value="0") 0
                option(value="0.1") 0.1
                option(value="0.2") 0.2
                option(value="0.3") 0.3
                option(value="0.4") 0.4
                option(value="0.5") 0.5
                option(value="0.6") 0.6
                option(value="0.7") 0.7
                option(value="0.8") 0.8
                option(value="0.9") 0.9
                option(value="1.0") 1.0
                option(value="1.1") 1.1
                option(value="1.2") 1.2
                option(value="1.3") 1.3
                option(value="1.4" selected) 1.4
                option(value="1.5") 1.5
                option(value="2.0") 2.0
                option(value="3.0") 3.0
                option(value="4.0") 4.0
            p.font-subheading Letter spacing
            select#letter-spacing
                option(value="-0.2em") -0.2em
                option(value="-0.1em") -0.1em
                option(value="0px" selected) 0px (normal)
                option(value="0.1em") 0.1em
                option(value="0.2em") 0.2em
                option(value="0.3em") 0.3em
                option(value="0.4em") 0.4em
                option(value="0.5em") 0.5em
                option(value="0.6em") 0.6em
                option(value="0.7em") 0.7em
                option(value="0.8em") 0.8em
                option(value="0.9em") 0.9em
                option(value="1.0em") 1.0em
                option(value="1.5em") 1.5em
                option(value="2.0em") 2.0em
            p.font-subheading Theme
            select#color-theme
                option(value="green-on-black") Green on black
                option(value="white-on-black") White on black
                option(value="light-on-dark" selected) Light on dark
                option(value="dark-on-light") Dark on light
                option(value="black-on-white") Black on white
    fieldset
        legend Save / Restore text
        div.fieldset-content
            button.btn#btn-save-text Save text to localStorage
            button.btn#btn-restore-text Restore text from localStorage
            button.btn#btn-save-text-to-file Save to .txt file
    fieldset
        legend Scroll to…
        div.fieldset-content
            button.btn#btn-scroll-to-top-left Top left ↖
            button.btn#btn-scroll-to-bottom-left Bottom left ↙
            button.btn#btn-scroll-to-top Top ↑
            button.btn#btn-scroll-to-bottom Bottom ↓
            button.btn#btn-scroll-to-left ← Left
            button.btn#btn-scroll-to-right Right →
    fieldset
        legend Sample content
        div.fieldset-content
            button.btn#btn-sample-hello-world hello world
            button.btn#btn-sample-accent déjà vu
            button.btn#btn-sample-simple-url Simple URL
            button.btn#btn-sample-complex-url Complex URL
            button.btn#btn-sample-text Text
            button.btn#btn-sample-html-emmet-starter Emmet HTML 5 starter
            button.btn#btn-sample-html Simple HTML
            button.btn#btn-sample-html-5-boilerplate HTML 5 Boilerplate
            button.btn#btn-sample-html-5-kitchen-sink HTML 5 Kitchen Sink
            button.btn#btn-sample-html-table HTML Table
            button.btn#btn-sample-xml XML
            button.btn#btn-sample-js-with-comments JavaScript with comments
            button.btn#btn-sample-js-jquery-unminified jQuery Unminified
            button.btn#btn-sample-bootstrap-css-unminified Bootstrap CSS Unminified
            button.btn#btn-sample-wordpress-directory-structure WordPress Directory Structure
            button.btn#btn-sample-markdown Markdown
            button.btn#btn-sample-alice-extract Alice In Wonderland (Extract)
            button.btn#btn-sample-alice-full Alice In Wonderland (Full)
            button.btn#btn-sample-quote Quote
            button.btn#btn-sample-pangrams Pangrams
            button.btn#btn-sample-boys-names Top 100 boys names
            button.btn#btn-sample-girls-names Top 100 girls names
            button.btn#btn-sample-466k-english-words 466k English words
            button.btn#btn-sample-reserved Reserved characters
            button.btn#btn-sample-unreserved Unreserved characters
            button.btn#btn-sample-az a-z
            button.btn#btn-sample-special-chars Special characters
            button.btn#btn-sample-character-mapping Character mapping
            button.btn#btn-sample-emoticons Emoticons
            button.btn#btn-sample-phonetic Phonetic alphabet
            button.btn#btn-sample-lorem-ipsum Lorem Ipsum (static)
            button.btn#btn-sample-lorem-ipsum-generated Lorem Ipsum (generated)
            button.btn#btn-sample-number-column-n-n Number column (n-n)
            button.btn#btn-sample-number-column-01-99 Number column (01-99)
            button.btn#btn-sample-number-column-01-999 Number column (01-999)
            button.btn#btn-sample-number-column-01-9999 Number column (01-9999)
            button.btn#btn-sample-curly-quotes Curly quotes
            button.btn#btn-sample-ascii-image ASCII image
            button.btn#btn-sample-diamond-of-bullets Diamond of bullets
            button.btn#btn-sample-csv-data CSV data
            button.btn#btn-sample-tab-delimited-data Tab delimited values (TSV)
            button.btn#btn-sample-lined-up-tab-delimited-data Lined up TSV data
            button.btn#btn-sample-json-formatted JSON (Formatted) 1
            button.btn#btn-sample-json-formatted-2 JSON (Formatted) 2
            button.btn#btn-sample-json-simple-formatted Simple JSON (Formatted)
            button.btn#btn-sample-json-simple-unformatted Simple JSON (Unformatted)
            button.btn#btn-sample-json-complex-unformatted Complex JSON (Unformatted)
            button.btn#btn-sample-yaml-simple-1 Simple YAML 1
            button.btn#btn-sample-yaml-simple-2 Simple YAML 2
            button.btn#btn-sample-yaml-complex Complex YAML
            button.btn#btn-sample-regular-array Simple regular array
            button.btn#btn-sample-associative-array Simple associative array
            button.btn#btn-sample-data-string Data string
            button.btn#btn-sample-repeating-data-string Repeating data string
            button.btn#btn-sample-data-to-be-lined-up Data to be lined up
            button.btn#btn-sample-merge-bottom-into-top Merge bottom into top
            button.btn#btn-sample-uuids-with-duplicates UUIDs (with duplicates)
            button.btn#btn-sample-indentation-tabs Indentation (Tabs)
            button.btn#btn-sample-indentation-two-spaces Indentation (2 spaces)
            button.btn#btn-sample-indentation-four-spaces Indentation (4 spaces)
            button.btn#btn-sample-extract-data Data for extraction
            button.btn#btn-sample-svg-markup-simple SVG markup (Simple)
            button.btn#btn-sample-svg-markup-complex SVG markup (Complex)
            button.btn#btn-sample-date-now Date.now() / date-fns
            button.btn#btn-sample-geometric-shapes Geometric Shapes
            button.btn#btn-sample-arrow-symbols Arrow symbols
            button.btn#btn-sample-heart-symbols Heart symbols
            button.btn#btn-sample-special-symbols Special symbols
            button.btn#btn-sample-flower-symbols Flower symbols
            button.btn#btn-sample-quotation-marks Quotation marks
            button.btn#btn-sample-star-symbols Star symbols
            button.btn#btn-sample-emoji-symbols Emoji symbols
            button.btn#btn-sample-zodiac-symbols Zodiac symbols
            button.btn#btn-sample-currency-symbols Currency symbols
            button.btn#btn-sample-greek-symbols Greek symbols
            button.btn#btn-sample-roman-numerals Roman numerals
            button.btn#btn-sample-suits-of-the-cards Suits of the cards
            button.btn#btn-sample-punctuation-marks Punctuation marks
    fieldset
        legend Random content…
        div.fieldset-content
            p.num-random-items.visually-hidden Number of items…
            select#num-random-items-select.num-random-items-select
                option(value="1") 1 item
                option(value="2") 2 items
                option(value="5") 5 items
                option(value="10") 10 items
                option(value="20") 20 items
                option(value="50") 50 items
                option(value="100" selected) 100 items
                option(value="200") 200 items
                option(value="500") 500 items
                option(value="1000") 1000 items
                option(value="2000") 2000 items
                option(value="5000") 5000 items
                option(value="10000") 10000 items
            button.btn#btn-random-passwords-length-8 Passwords (Length 8)
            button.btn#btn-random-passwords-length-16 Passwords (Length 16)
            button.btn#btn-random-passwords-length-24 Passwords (Length 24)
            button.btn#btn-random-passwords-length-32 Passwords (Length 32)
            button.btn#btn-random-passwords-length-64 Passwords (Length 64)
            button.btn#btn-random-uuids UUIDs
            button.btn#btn-random-booleans Booleans
            button.btn#btn-random-characters-all Characters (All)
            button.btn#btn-random-characters-lowercase Characters (Lowercase)
            button.btn#btn-random-characters-uppercase Characters (Uppercase)
            button.btn#btn-random-characters-ABCD Characters (ABCD)
            button.btn#btn-random-floating Floating point numbers
            button.btn#btn-random-floating-positive Floating (Positive)
            button.btn#btn-random-integers Integers
            button.btn#btn-random-integers-positive Integers (Positive)
            button.btn#btn-random-integers-plus-minus-100 Integers (-100 → 100)
            button.btn#btn-random-integers-0-to-1000 Integers (0 → 1000)
            button.btn#btn-random-integers-0-to-100 Integers (0 → 100)
            button.btn#btn-random-integers-0-to-10 Integers (0 → 10)
            button.btn#btn-random-integers-0-to-1 Integers (0 → 1)
            button.btn#btn-random-strings Strings 
            button.btn#btn-random-strings-length-8 Strings (Length 8)
            button.btn#btn-random-strings-length-16 Strings (Length 16)
            button.btn#btn-random-strings-length-32 Strings (Length 32)
            button.btn#btn-random-strings-length-64 Strings (Length 64)
            button.btn#btn-random-strings-length-128 Strings (Length 128)
            button.btn#btn-random-strings-uppercase Strings (Uppercase)
            button.btn#btn-random-strings-lowercase Strings (Lowercase)
            button.btn#btn-random-strings-digits Strings (Digits)
            button.btn#btn-random-strings-slashes Unicode slashes
            button.btn#btn-random-paragraphs Paragraphs
            button.btn#btn-random-sentences Sentence
            button.btn#btn-random-sentences-5-words Sentence (5 words)
            button.btn#btn-random-sentences-10-words Sentence (10 words)
            button.btn#btn-random-sentences-15-words Sentence (15 words)
            button.btn#btn-random-sentences-20-words Sentence (20 words)
            button.btn#btn-random-syllables Syllables
            button.btn#btn-random-words Words (Nonsense)
            button.btn#btn-random-dates-last-10-years Dates (In last 10 years)
            button.btn#btn-random-dates-last-100-years Dates (In last 100 years)
            button.btn#btn-random-dates-formatted Dates (Formatted)
            button.btn#btn-random-names-first Names (First)
            button.btn#btn-random-names-last Last (Last)
            button.btn#btn-random-names-first-last Names (First Last)
            button.btn#btn-random-names-male Names (Male)
            button.btn#btn-random-names-female Names (Female)
            //- button.btn#btn-random-animals Animals //- Not working
            button.btn#btn-random-color-hex Colors (Hex)
            button.btn#btn-random-color-rgb Colors (RGB)
            //- button.btn#btn-random-company Companies
            button.btn#btn-random-domain Domains
            button.btn#btn-random-email Emails
            button.btn#btn-random-email-domain-com Emails (domain.com)
            button.btn#btn-random-ip-address IP Addresses (IPv4)
            button.btn#btn-random-ipv6 IP Addresses (IPv6)
            //- button.btn#btn-random-profession Professions
            button.btn#btn-random-url URLs
            button.btn#btn-random-address Addresses
            button.btn#btn-random-city-world Cities (World)
            button.btn#btn-random-city-uk Cities (UK)
            button.btn#btn-random-coordinates Coordinates
            button.btn#btn-random-country Countries
            button.btn#btn-random-phone Phone numbers
            button.btn#btn-random-phone-uk Phone numbers (UK)
            button.btn#btn-random-phone-uk-mobile Phone numbers (UK mobiles)
            //- button.btn#btn-random-postcode Postcodes
            button.btn#btn-random-timestamp Timestamps
            button.btn#btn-random-weekday Weekdays
            button.btn#btn-random-credit-card-visa Credit Card (Visa)
            button.btn#btn-random-dollar Dollars
            button.btn#btn-random-euro Euros
            button.btn#btn-random-coin-toss Coin Toss
            button.btn#btn-random-dice-6 Dice (6 sides)
            button.btn#btn-random-hash Hashes
    fieldset
        legend Count…
        div.fieldset-content
            button.btn#btn-count-chars Characters (All)
            button.btn#btn-count-chars-alphanumeric Characters (Alphanumeric)
            button.btn#btn-count-words Words (All)
            button.btn#btn-count-words-alphanumeric Words (Alphanumeric)
            button.btn#btn-count-lines Lines (All)
            button.btn#btn-count-lines-empty Lines (Empty)
            button.btn#btn-count-lines-non-empty Lines (Non-Empty)
            button.btn#btn-count-average-per-line Characters per line (Average)
            button.btn#btn-count-longest-line Num chars on longest line
            button.btn#btn-count-selected-chars Selected characters
            button.btn#btn-count-selected-words Selected words
            button.btn#btn-count-filesize Filesize
            button.btn#btn-count-word-frequency Word frequency
            button.btn#btn-count-uuids UUIDs
            button.btn#btn-count-array-length Array length
            button.btn#btn-count-associative-array-length Associative Array (Object) length
            p.substring-frequency Frequency of substring…
            input(type="text")#substring-frequency-value.substring-frequency-value
            button.btn#btn-count-substring-frequency(disabled) Count substring frequency
    fieldset
        legend Remove…
        div.fieldset-content
            button.btn#btn-remove-linebreaks Linebreaks (All)
            button.btn#btn-remove-linebreaks-keep-empty Linebreaks (Keep empty)
            button.btn#btn-remove-whitespace-all Whitespace (All)
            button.btn#btn-remove-trim-each-line Trim whitespace (Each line)
            button.btn#btn-remove-whitespace-from-start Trim whitespace (From start)
            button.btn#btn-remove-whitespace-from-end Trim whitespace (From end)
            button.btn#btn-remove-spaces-multiple Spaces (Multiple)
            button.btn#btn-remove-spaces-all Spaces (All)
            button.btn#btn-remove-non-alpha-chars Non-alpha chars
            button.btn#btn-remove-az-lowercase a-z
            button.btn#btn-remove-az-uppercase A-Z
            button.btn#btn-remove-numbers Numbers
            button.btn#btn-remove-special-chars Special characters
            button.btn#btn-remove-vowels Vowels
            button.btn#btn-remove-html-markup HTML markup
            button.btn#btn-remove-html-inline-styles HTML inline styles
            button.btn#btn-remove-empty-lines-all Empty lines (All)
            button.btn#btn-remove-empty-lines-top-bottom Empty lines (Top & Bottom)
            button.btn#btn-remove-empty-lines-multiple Empty lines (Multiple)
            button.btn#btn-remove-lines-that-only-contain-special-chars Only special char lines
            button.btn#btn-remove-uuids UUIDs
            button.btn#btn-remove-tabs-all Tabs (All)
            button.btn#btn-remove-tabs-multiple Tabs (Multiple)
            button.btn#btn-remove-duplicate-words Duplicate words
            button.btn#btn-remove-duplicate-lines Duplicate lines
            button.btn#btn-remove-random-chars Random characters
            button.btn#btn-remove-random-words Random words
            button.btn#btn-remove-random-lines Random lines
            button.btn#btn-remove-alternate-lines-odd Alternate lines (Odd)
            button.btn#btn-remove-alternate-lines-even Alternate lines (Even)
            button.btn#btn-remove-reverse-line-feed Reverse Line feed (U+008D)
            button.btn#btn-remove-console-logs console.log()
            button.btn#btn-remove-javascript-comments JavaScript comments
       
            button.btn#btn-remove-html-comments HTML comments
            button.btn#btn-remove-head-tag <head> tag
            button.btn#btn-remove-body-tag <body> tag
            button.btn#btn-remove-script-tags <script> tags
            button.btn#btn-remove-style-tags <style> tags
            
            p.lines-that Lines that…
            select#select-lines-that.select-lines-that
                option(value="match-exactly") Match exacly
                option(value="start-with") Start with
                option(value="contain") Contain
                option(value="end-with") End with
                option(value="dont-start-with") Don't start with
                option(value="dont-contain") Don't contain
                option(value="dont-end-with") Don't end with
                option(value="dont-match-exactly") Don't match exacly
            input(type="text")#lines-that-value.lines-that-value
            button.btn#btn-lines-that.btn-lines-that(disabled) Remove lines
            p.remove-text-on-each-line Remove text on each line…
            select#select-text-on-each-line
                option(value="before") Before
                option(value="before-and-including") Before and including
                option(value="including-and-after") Including and after
                option(value="after") After…
            p.remove-text-on-each-line-the …the…
            select#select-text-on-each-line-position
                option(value="first") First instance of
                option(value="last") Last instance of
            input(type="text")#instance-of-text-value.instance-of-text-value
            button.btn#btn-instance-of.btn-instance-of(disabled) Remove text
            p.remove-chars-from-position Remove …
            select#select-remove-chars-from-position-num-chars
                option(value="1") 1 char
                option(value="2") 2 chars
                option(value="3") 3 chars
                option(value="4") 4 chars
                option(value="5") 5 chars
                option(value="6") 6 chars
                option(value="7") 7 chars
                option(value="8") 8 chars
                option(value="9") 9 chars
                option(value="10") 10 chars
                option(value="11") 11 chars
                option(value="12") 12 chars
                option(value="13") 13 chars
                option(value="14") 14 chars
                option(value="15") 15 chars
                option(value="16") 16 chars
                option(value="17") 17 chars
                option(value="18") 18 chars
                option(value="19") 19 chars
                option(value="20") 20 chars
            p.remove-chars-from-position-from-the …from the…
            select#select-remove-chars-from-position
                option(value="beginning") Beginning
                option(value="end") End
                option(value="nth-position") nth Position
            input(type="text")#input-remove-chars-from-nth-position.input-remove-chars-from-nth-position
            p#remove-chars-from-position-from-the-nth-position.remove-chars-from-position-from-the …from the…
            select#select-remove-chars-from-nth-position-beginning-end
                option(value="beginning") Beginning
                option(value="end") End
            p.remove-chars-from-position-from-the …of each line
            button.btn#btn-remove-chars-from-position Remove chars
            p.remove-lines-by-length Remove lines that are…
            select#select-remove-lines-by-length-type.select-remove-lines-by-length-type
                option(value="less-than") less than
                option(value="less-than-or-equal-to") less than or equal to
                option(value="equal-to") equal to
                option(value="not-equal-to") not equal to
                option(value="more-than-or-equal-to") more than or equal to
                option(value="more-than") more than
            select#select-remove-lines-by-length-num-chars.select-remove-lines-by-length-num-chars
                option(value="0") 0 chars
                option(value="1") 1 char
                option(value="2") 2 chars
                option(value="3") 3 chars
                option(value="4") 4 chars
                option(value="5") 5 chars
                option(value="6") 6 chars
                option(value="7") 7 chars
                option(value="8") 8 chars
                option(value="9") 9 chars
                option(value="10") 10 chars
                option(value="11") 11 chars
                option(value="12") 12 chars
                option(value="13") 13 chars
                option(value="14") 14 chars
                option(value="15") 15 chars
                option(value="16") 16 chars
                option(value="17") 17 chars
                option(value="18") 18 chars
                option(value="19") 19 chars
                option(value="20") 20 chars
                option(value="21") 21 chars
                option(value="22") 22 chars
                option(value="23") 23 chars
                option(value="24") 24 chars
                option(value="25") 25 chars
                option(value="26") 26 chars
                option(value="27") 27 chars
                option(value="28") 28 chars
                option(value="29") 29 chars
                option(value="30") 30 chars
                option(value="31") 31 chars
                option(value="32") 32 chars
                option(value="33") 33 chars
                option(value="35") 35 chars
                option(value="36") 36 chars
                option(value="37") 37 chars
                option(value="38") 38 chars
                option(value="39") 39 chars
                option(value="40") 40 chars
                option(value="41") 41 chars
                option(value="42") 42 chars
                option(value="43") 43 chars
                option(value="44") 44 chars
                option(value="45") 45 chars
                option(value="46") 46 chars
                option(value="47") 47 chars
                option(value="48") 48 chars
                option(value="49") 49 chars
                option(value="50") 50 chars
                option(value="51") 51 chars
                option(value="52") 52 chars
                option(value="53") 53 chars
                option(value="54") 54 chars
                option(value="55") 55 chars
                option(value="56") 56 chars
                option(value="57") 57 chars
                option(value="58") 58 chars
                option(value="59") 59 chars
                option(value="60") 60 chars
            button.btn#btn-remove-lines-by-length Remove lines
    fieldset
        legend Replace…
        div.fieldset-content
            select#select-replace-1.select-replace-1
                option(value="linebreaks") Linebreaks
                option(value="tabs") Tabs
                option(value="two-tabs") Two Tabs
                option(value="spaces") Spaces
                option(value="two-spaces") Two spaces
                option(value="four-spaces") Four spaces
                option(value="hyphen") Hyphen
                option(value="underscore") Underscore
                option(value="commas") Commas
                option(value="commas-space") Comma space
                option(value="full-stops") Full stops
                option(value="full-stop-space") Full stop space
                option(value="colon") Colon
                option(value="semicolon") Semicolon
                option(value="single-quotes") Single quotes (')
                option(value="double-quotes") Double quotes (")
                option(value="backticks") Backticks (`)
                option(value="array-single") Array ['x']
                option(value="array-double") Array ["x"]
                option(value="pipe") Pipe
                option(value="other") Other…
            input(type="text")#replace-1-other.replace-1-other
            p.replace-with with
            select#select-replace-2.select-replace-2
                option(value="linebreaks") Linebreaks
                option(value="tabs") Tabs
                option(value="two-tabs") Two Tabs
                option(value="spaces") Spaces
                option(value="two-spaces") Two spaces
                option(value="four-spaces") Four spaces
                option(value="hyphen") Hyphen
                option(value="underscore") Underscore
                option(value="commas") Commas
                option(value="commas-space") Comma space
                option(value="full-stops") Full stops
                option(value="full-stop-space") Full stop space
                option(value="full-stop-linebreak") Full stop linebreak
                option(value="colon") Colon
                option(value="semicolon") Semicolon
                option(value="single-quotes") Single quotes (')
                option(value="double-quotes") Double quotes (")
                option(value="backticks") Backticks (`)
                option(value="array-single") Array ['x']
                option(value="array-double") Array ["x"]
                option(value="pipe") Pipe
                option(value="nothing") Nothing ''
                option(value="other") Other…
            input(type="text")#replace-2-other.replace-2-other
            button.btn.btn-replace#btn-replace Replace
    fieldset
        legend Split on string…
        div.fieldset-content
            input(type="text")#split-on-string.split-on-string
            button.btn.btn-split-on-string#btn-split-on-string Split
    fieldset
        legend Case…
        div.fieldset-content
            button.btn#btn-case-invert iNVERT cASE
            button.btn#btn-case-uppercase UPPERCASE
            button.btn#btn-case-lowercase lowercase
            button.btn#btn-case-titlecase-words Titlecase Words
            button.btn#btn-case-titlecase-lines Titlecase lines
            button.btn#btn-case-random RaNDoM
            button.btn#btn-case-alternate AlTeRnAtE
            button.btn#btn-case-uppercase-first-letter-each-line Uppercase first letter of each line
            button.btn#btn-case-lowercase-first-letter-each-line Lowercase first letter of each line
    fieldset
        legend Modify…
        div.fieldset-content
            button.btn#btn-modify-leetspeak Leetspeak
            button.btn#btn-modify-reverse-chars Reverse chars
            button.btn#btn-modify-scramble-chars Scramble chars
            button.btn#btn-modify-order-chars Order chars (alphabetically)
            button.btn#btn-modify-reverse-words Reverse words
            button.btn#btn-modify-scramble-words Scramble words (simple)
            button.btn#btn-modify-order-words Order words (alphabetically)
            button.btn#btn-modify-order-words-by-length Order words (by length)
            button.btn#btn-modify-reverse-lines Reverse lines
            button.btn#btn-modify-scramble-lines Scramble lines (simple)
            button.btn#btn-modify-scramble-lines-fisher-yates Scramble lines (Fisher Yates x5)
            button.btn#btn-modify-order-lines Order lines (alphabetically)
            button.btn#btn-modify-order-lines-by-length Order lines (by length)
            button.btn#btn-modify-straighten-quotes Straighten curly quotes
            button.btn#btn-modify-upside-down To uʍop ǝpısdn
            button.btn#btn-modify-from-upside-down From uʍop ǝpısdn
            button.btn#btn-modify-insert-line-numbers Insert line numbers
            button.btn#btn-modify-pad-left Pad left
            button.btn#btn-modify-pad-right Pad right
            button.btn#btn-modify-pad-left-and-right Pad left and right (Centre)
            button.btn#btn-modify-line-up-first-instance-of-char Line up first instance of char
            button.btn#btn-modify-line-up-last-instance-of-char Line up last instance of char
            button.btn#btn-modify-transpose Transpose (90°)
            button.btn#btn-modify-trim-each-line Trim each line
            button.btn#btn-modify-one-char-per-line One character per line
            button.btn#btn-modify-duplicate-text Duplicate text
            button.btn#btn-modify-duplicate-each-line-horizontally Duplicate each line (Horizontally)
            button.btn#btn-modify-duplicate-each-line-vertically Duplicate each line (Vertically)
            button.btn#btn-modify-merge-bottom-into-top Merge bottom into top
            button.btn#btn-modify-insert-linebreak-every-n-chars Insert linebreak every n chars
            button.btn#btn-modify-insert-n-linebreak-after-each-line Insert n linebreaks after each line
            button.btn#btn-modify-insert-n-linebreaks-after-every-n-lines Insert n linebreaks after every n lines
            button.btn#btn-modify-insert-text-at-position-n Insert text at position n
            button.btn#btn-modify-insert-prefix-and-suffix Add prefix and suffix
            button.btn#btn-modify-html-table-to-json HTML Table to JSON
            button.btn#btn-modify-data-string-to-json Data string to JSON
            button.btn#btn-modify-populate-uuid Populate "uuid": ""
            button.btn#btn-modify-replace-uuids Replace UUIDs
    fieldset
        legend Switch format
        div.fieldset-content
            button.btn#btn-switch-format-json-to-csv-with-quotes JSON to CSV (with quotes)
            button.btn#btn-switch-format-json-to-csv-without-quotes JSON to CSV (without quotes)
            button.btn#btn-switch-format-csv-to-json CSV to JSON
            button.btn#btn-switch-format-yaml-to-json YAML to JSON
    fieldset
        legend Create lookup table
        div.fieldset-content
            button.btn#btn-create-lookup-table-encode-formatted Encode (Formatted)
            button.btn#btn-create-lookup-table-encode-unformatted Encode (Unformatted)
            button.btn#btn-create-lookup-table-decode-formatted Decode (Formatted)
            button.btn#btn-create-lookup-table-decode-unformatted Decode (Unformatted)
    fieldset
        legend Convert to comment block
        div.fieldset-content
            button.btn#btn-comments-html HTML Comments
            button.btn#btn-comments-css CSS Comments
            button.btn#btn-comments-js JS Comments
            button.btn#btn-comments-js-dont-minify JS Comments (Don't minify)
            button.btn#btn-comments-react-jsx React JSX Comments
            button.btn#btn-comments-php PHP Comments
            button.btn#btn-comments-blade-template Blade Template Comments
            button.btn#btn-comments-python Python Comments
            button.btn#btn-comments-yaml YAML Comments
            button.btn#btn-comments-pug Pug Comments
    fieldset
        legend Extract data
        div.fieldset-content
            button.btn#btn-extract-email-addresses Email addresses
            button.btn#btn-extract-urls-inc-args URLs (inc. Query String)
            button.btn#btn-extract-urls-exc-args URLs (ex. Query String)
            button.btn#btn-extract-non-ascii Non-ASCII chars
            button.btn#btn-extract-hex-colors Hex colors
            button.btn#btn-extract-ip-addresses IP addresses
            button.btn#btn-extract-phone-numbers Phone numbers
            button.btn#btn-extract-uk-postcodes UK postcodes
            button.btn#btn-extract-uuids UUIDs
    fieldset
        legend Find duplicate
        div.fieldset-content
            button.btn#btn-find-duplicate-uuids UUIDs
    fieldset
        legend Prepend/append to line…
        div.fieldset-content
            select#prepend-append.select-prepend-append-1
                option(value="prepend") Prepend
                option(value="append" selected) Append
            p.prepend-append-with with
            select#prepend-append-value.select-prepend-append-2
                option(value="linebreak") Linebreak
                option(value="tab") Tab
                option(value="space") Space
                option(value="two-spaces") Two spaces
                option(value="four-spaces") Four spaces
                option(value="comma") Comma
                option(value="comma-space") Comma space
                option(value="full-stop") Full stop
                option(value="full-stop-space") Full stop space
                option(value="br" selected) <br/>
                option(value="bullet") Bulletpoint
                option(value="right-arrow") Rightwards arrow
                option(value="long-right-arrow") Long rightwards arrow
                option(value="other") Other…
            input(type="text")#prepend-append-other.prepend-append-other
            button.btn#btn-prepend-append-action.btn-prepend-append-action Append
    fieldset
        legend Repeating data to tabular data
        div.fieldset-content
            p.repeats-after Data repeats after…
            select#repeats-after-select.repeats-after-select
                option(value="2") 2 lines
                option(value="3") 3 lines
                option(value="4") 4 lines
                option(value="5") 5 lines
                option(value="6") 6 lines
                option(value="7") 7 lines
                option(value="8") 8 lines
                option(value="9") 9 lines
                option(value="10") 10 lines
                option(value="11") 11 lines
                option(value="12") 12 lines
                option(value="13") 13 lines
                option(value="14") 14 lines
                option(value="15") 15 lines
                option(value="16") 16 lines
                option(value="17") 17 lines
                option(value="18") 18 lines
                option(value="19") 19 lines
                option(value="20") 20 lines
            p.repeats-after-delimeter Delimiter…
            select#repeats-after-delimeter-select.repeats-after-delimeter-select
                option(value="comma") Comma
                option(value="comma-space") Comma space
                option(value="tab") Tab
                option(value="space") Space
                option(value="colon") Colon
                option(value="semicolon") Semicolon
                option(value="pipe") Pipe
            button.btn#btn-repeats-to-table.btn-repeats-to-table Convert to table
    fieldset
        legend Tabular data…
        div.fieldset-content
            input(type='checkbox', checked='checked')#tabular-data-first-row-headings-checkbox.tabular-data-first-row-headings-checkbox
            label(for='tabular-data-first-row-headings-checkbox').tabular-data-first-row-headings First row is headings
            p.tabular-data-delimeter Delimeter
            select#tabular-data-delimeter-value.tabular-data-delimeter-value
                option(value="comma") Comma
                option(value="comma-space") Comma space
                option(value="tab") Tab
                option(value="space") Space
                option(value="colon") Colon
                option(value="semicolon") Semicolon
                option(value="pipe") Pipe
                option(value="other") Other…
            input(type='text')#tabular-data-other-delimeter-value.tabular-data-other-delimeter-value
            button.btn.btn-tabular-data-analyse#btn-tabular-data-analyse Analyse data
            div#tabular-data-analysed-wrapper
                p#tabular-data-num-rows-columns.tabular-data-num-rows-columns X rows, X columns
                p.tabular-data-column Column
                select#tabular-data-column-select.tabular-data-column-select
                    option(value='' disabled) Please select…
                p.tabular-data-action Action
                select#tabular-data-action-select.tabular-data-action-select
                    option(value='delete-this') Delete this column
                    option(value='delete-others') Delete other columns
                    option(value='delete-before') Delete columns before this
                    option(value='delete-after') Delete columns after this
                    option(value='move-left') Move left
                    option(value='move-right') Move right
                    option(value='move-to-beginning') Move to beginning
                    option(value='move-to-end') Move to end
                button.btn#btn-tabular-data-perform-action Delete column
                div#tabular-data-convert-wrapper
                    p.tabular-data-convert Convert data to…
                    select#tabular-data-convert-select.tabular-data-convert-select
                        option(value='' disabled) Please select…
                        option(value='json') JSON
                        option(value='html') HTML Table
                    button.btn.btn-tabular-data-convert#btn-tabular-data-convert Convert
    fieldset
        legend Add HTML markup…
        div.fieldset-content
            button.btn#btn-html-ol Convert to <ol>
            button.btn#btn-html-ul Convert to <ul>
            button.btn#btn-html-br Linebreaks to <br/>
            button.btn#btn-html-p Paragraphs to <p>
            button.btn#btn-html-wrap-lines Wrap lines with tag
            p.view-html-css-prompt Preview HTML with CSS library…
            select#view-html-css-select.view-html-css-select
                option(value='' selected) None
                option(value='meyer-reset') Eric Meyer CSS reset
                option(value='normalize') Normalize
                option(value='bootstrap3') Bootstrap 3
                option(value='bootstrap4') Bootstrap 4
                option(value='foundation5') Foundation 5
                option(value='foundation6') Foundation 6
                option(value='bulma') Bulma
                option(value='semantic-ui') Semantic-UI
                option(value='materialize') Materialize
                option(value='pure') Pure
                option(value='skeleton') Skeleton
                option(value='uikit') UIKit
                option(value='milligram') Milligram
                option(value='spectre') Spectre
                option(value='mustard-ui') Mustard UI
                option(value='mui') MUI
                option(value='animate') Animate
                option(value='tailwind') Tailwind
                option(value='tachyons') Tachyons
            button.btn#btn-html-open-new-window View HTML in new window
    fieldset
        legend Data URIs
        div.fieldset-content
            button.btn#btn-data-uri-svg-to-background-image SVG to CSS background-image
            button.btn#btn-data-uri-background-image-to-svg CSS background-image to SVG
    fieldset
        legend Encode/Decode…
        div.fieldset-content
            div.input-row.encode-decode-each-line-radio-input-row
                input(type='radio', checked='checked', name='encode-decode-radio-group')#encode-decode-each-line-radio.encode-decode-each-line-radio
                label(for='encode-decode-each-line-radio').encode-decode-each-line-label Each line
            div.input-row.encode-decode-whole-document-radio-input-row
                input(type='radio', name='encode-decode-radio-group')#encode-decode-whole-document-radio.encode-decode-whole-document-radio
                label(for='encode-decode-whole-document-radio').encode-decode-each-line-label Whole document
            button.btn#btn-modify-encodeURI encodeURI()
            button.btn#btn-modify-decodeURI decodeURI()
            button.btn#btn-modify-encodeURIComponent encodeURIComponent()
            button.btn#btn-modify-decodeURIComponent decodeURIComponent()
            button.btn#btn-modify-toUnicode To Unicode (\u)
            button.btn#btn-modify-fromUnicode From Unicode (\u)
            button.btn#btn-modify-toUnicode-zerox To Unicode (0x)
            button.btn#btn-modify-fromUnicode-zerox From Unicode (0x)
            button.btn#btn-modify-toUnicode-uplus To Unicode (U+)
            button.btn#btn-modify-fromUnicode-uplus From Unicode (U+)
            button.btn#btn-modify-to-binary-unicode To Unicode (Binary)
            button.btn#btn-modify-from-binary-unicode From Unicode (Binary)
            button.btn#btn-modify-to-hex-unicode To Unicode (Hex)
            button.btn#btn-modify-from-hex-unicode From Unicode (Hex)
            
            button.btn#btn-modify-to-hex-escape-sequence To Hex Escape Sequence (\x)
            button.btn#btn-modify-from-hex-escape-sequence From Hex Escape Sequence (\x)
            
            
            
            button.btn#btn-modify-to-css-pseudo-content To CSS Pseudo content (Hex)
            button.btn#btn-modify-toUTF8 To UTF8
            button.btn#btn-modify-fromUTF8 From UTF8
            button.btn#btn-modify-toCharCode To CharCode
            button.btn#btn-modify-fromCharCode From CharCode
            button.btn#btn-modify-toHtmlEntityNumber To HTML Entity numbers
            button.btn#btn-modify-fromHtmlEntityNumber From HTML Entity numbers
            button.btn#btn-modify-toHtmlEntityNamed To HTML Named Entities
            button.btn#btn-modify-fromHtmlEntityNamed From HTML Named Entities
            button.btn#btn-modify-toBase64 To Base64 values
            button.btn#btn-modify-fromBase64 From Base64 values
            button.btn#btn-modify-toMorse To Morse code
            button.btn#btn-modify-fromMorse From Morse code
            button.btn#btn-modify-to-json-string To safe JSON string \n\t
            button.btn#btn-modify-from-json-string From safe JSON string \n\t
            button.btn#btn-modify-to-textarea-value To <textarea> value (JS)
            button.btn#btn-modify-to-pre-inner-html To <pre> innerHTML (JS)
            button.btn#btn-modify-to-dna-string To DNA string
            button.btn#btn-modify-from-dna-string From DNA string
            button.btn#btn-modify-to-fanda To Fanda
            button.btn#btn-modify-from-fanda From Fanda
            button.btn#btn-modify-toMD5 To MD5 Hash
    fieldset
        legend ROT
        div.fieldset-content
            select#rot-number-select.rot-number-select
                option(value='1') ROT1
                option(value='2') ROT2
                option(value='3') ROT3
                option(value='4') ROT4
                option(value='5') ROT5
                option(value='6') ROT6
                option(value='7') ROT7
                option(value='8') ROT8
                option(value='9') ROT9
                option(value='10') ROT10
                option(value='11') ROT11
                option(value='12') ROT12
                option(value='13' selected) ROT13 (Default)
                option(value='14') ROT14
                option(value='15') ROT15
                option(value='16') ROT16
                option(value='17') ROT17
                option(value='18') ROT18
                option(value='19') ROT19
                option(value='20') ROT20
                option(value='21') ROT21
                option(value='22') ROT22
                option(value='23') ROT23
                option(value='24') ROT24
                option(value='25') ROT25
            button.btn#btn-to-rot To ROT13
            button.btn#btn-from-rot From ROT13
    fieldset
        legend Vigenère cipher
        div.fieldset-content
            input(type="text" placeholder="Enter a key")#vigenere-key.vigenere-key
            button.btn#btn-vigenere-cipher-encode Encode
            button.btn#btn-vigenere-cipher-decode Decode
    fieldset
        legend Mathematical Unicode
        div.fieldset-content
            button.btn#btn-to-mathematical-double-struck To Double-Struck
            //- button.btn#btn-from-mathematical-double-struck From Double-Struck
            button.btn#btn-to-mathematical-fraktur To Fraktur
            //- button.btn#btn-from-mathematical-fraktur From Fraktur
            button.btn#btn-to-mathematical-bold-fraktur To Bold Fraktur
            //- button.btn#btn-from-mathematical-bold-fraktur From Bold Fraktur
            button.btn#btn-to-mathematical-bold To Bold
            //- button.btn#btn-from-mathematical-bold From Bold
            button.btn#btn-to-mathematical-italic To Italic
            //- button.btn#btn-from-mathematical-italic From Italic
            button.btn#btn-to-mathematical-bold-italic To Bold Italic
            //- button.btn#btn-from-mathematical-bold-italic From Bold Italic
            button.btn#btn-to-mathematical-script To Script
            //- button.btn#btn-from-mathematical-script From Script
            button.btn#btn-to-mathematical-bold-script To Bold Script
            //- button.btn#btn-from-mathematical-bold-script From Bold Script
            button.btn#btn-to-mathematical-sans-serif To Sans-Serif
            //- button.btn#btn-from-mathematical-sans-serif From Sans-Serif
            button.btn#btn-to-mathematical-sans-serif-bold To Sans-Serif Bold
            //- button.btn#btn-from-mathematical-sans-serif-bold From Sans-Serif Bold
            button.btn#btn-to-mathematical-sans-serif-italic To Sans-Serif Italic
            //- button.btn#btn-from-mathematical-sans-serif-italic From Sans-Serif Italic
            button.btn#btn-to-mathematical-sans-serif-bold-italic To Sans-Serif Bold Italic
            //- button.btn#btn-from-mathematical-sans-serif-bold-italic From Sans-Serif Bold Italic
            button.btn#btn-to-mathematical-monospace To Monospace
            //- button.btn#btn-from-mathematical-monospace From Monospace
    fieldset
        legend Lodash…
        div.fieldset-content
            div.input-row.lodash-each-line-radio-input-row
                input(type='radio', checked='checked', name='lodash-radio-group')#lodash-each-line-radio.lodash-each-line-radio
                label(for='lodash-each-line-radio').lodash-each-line-label Each line
            div.input-row.lodash-whole-document-radio-input-row
                input(type='radio', name='lodash-radio-group')#lodash-whole-document-radio.lodash-whole-document-radio
                label(for='lodash-whole-document-radio').lodash-each-line-label Whole document
            button.btn#btn-lodash-camelcase _.camelCase
            button.btn#btn-lodash-capitalize _.capitalize
            button.btn#btn-lodash-deburr _.deburr (Remove accents)
            button.btn#btn-lodash-escape _.escape
            button.btn#btn-lodash-escapeRegExp _.escapeRegExp
            button.btn#btn-lodash-kebabCase _.kebabCase
            button.btn#btn-lodash-lowerCase _.lowerCase
            button.btn#btn-lodash-lowerFirst _.lowerFirst
            button.btn#btn-lodash-snakeCase _.snakeCase
            button.btn#btn-lodash-startCase _.startCase
            button.btn#btn-lodash-trim _.trim
            button.btn#btn-lodash-unescape _.unescape
            button.btn#btn-lodash-upperCase _.upperCase
            button.btn#btn-lodash-upperFirst _.upperFirst
    fieldset
        legend Voca…
        div.fieldset-content
            button.btn#btn-voca-escapeHtml v.escapeHtml
            button.btn#btn-voca-escapeRegExp v.escapeRegExp
            button.btn#btn-voca-unescapeHtml v.unescapeHtml
            button.btn#btn-voca-slugify v.slugify
            button.btn#btn-voca-stripTags v.stripTags
    fieldset
        legend Indentation
        div.fieldset-content
            button.btn#btn-indentation-tabs-to-two-spaces Tabs to 2 spaces
            button.btn#btn-indentation-tabs-to-four-spaces Tabs to 4 spaces
            button.btn#btn-indentation-four-spaces-to-two-spaces 4 spaces to 2 spaces
            button.btn#btn-indentation-four-spaces-to-tabs 4 spaces to tabs
            button.btn#btn-indentation-two-spaces-to-four-spaces 2 spaces to 4 spaces
            button.btn#btn-indentation-two-spaces-to-tabs 2 spaces to tabs
            button.btn#btn-indent-one-space Indent by 1 space
            button.btn#btn-indent-two-spaces Indent by 2 spaces
            button.btn#btn-indent-four-spaces Indent by 4 spaces
            button.btn#btn-indent-tab Indent by 1 tab
            button.btn#btn-unindent-one-space Unindent by 1 space
            button.btn#btn-unindent-two-spaces Unindent by 2 spaces
            button.btn#btn-unindent-four-spaces Unindent by 4 spaces
            button.btn#btn-unindent-tab Unindent by 1 tab
    fieldset
        legend Beautify…
        div.fieldset-content
            button.btn#btn-beautify-html Beautify HTML
            button.btn#btn-beautify-css Beautify CSS
            button.btn#btn-beautify-js Beautify JS
            button.btn#btn-beautify-json Beautify JSON
            button.btn#btn-beautify-xml Beautify XML
    fieldset
        legend Minify/Uglify…
        div.fieldset-content
            button.btn#btn-minify-css Minify CSS
            button.btn#btn-uglify-js(disabled) Minify JS
            button.btn#btn-uglify-json Minify JSON
            button.btn#btn-uglify-xml Minify XML
    fieldset
        legend Markdown…
        div.fieldset-content
            button.btn#btn-markdown-to-html Convert to HTML
    fieldset
        legend Validate…
        div.fieldset-content
            button.btn#btn-validate-xml XML
            button.btn#btn-validate-json JSON
    fieldset
        legend Console…
        div.fieldset-content
            button.btn#btn-console-log-text .log(text)
            button.btn#btn-console-log-json .log(JSON Object)
            button.btn#btn-console-table-json .table(Simple JSON Object)
            button.btn#btn-console-dirxml .dirxml(DOM Element)
    fieldset
        legend External tools…
        div.fieldset-content
            a.btn(href='https://onlinecsvtools.com', target='_blank') Online CSV Tools
            a.btn(href='https://onlinetsvtools.com', target='_blank') Online TSV Tools
            a.btn(href='https://onlinejsontools.com', target='_blank') Online JSON Tools
            a.btn(href='https://onlineyamltools.com', target='_blank') Online YAML Tools
            a.btn(href='https://onlinexmltools.com', target='_blank') Online XML Tools
            a.btn(href='https://onlinemathtools.com', target='_blank') Online MATH Tools
            a.btn(href='https://onlinenumbertools.com', target='_blank') Online NUMBER Tools
            a.btn(href='https://onlineasciitools.com', target='_blank') Online ASCII Tools
            a.btn(href='https://onlineutf8tools.com', target='_blank') Online UTF8 Tools
            a.btn(href='https://onlinebinarytools.com', target='_blank') Online BINARY Tools
            a.btn(href='https://onlinehextools.com', target='_blank') Online HEX Tools
            a.btn(href='https://onlinetexttools.com', target='_blank') Online TEXT Tools
            a.btn(href='https://onlinestringtools.com', target='_blank') Online STRING Tools
            a.btn(href='https://onlinerandomtools.com', target='_blank') Online RANDOM Tools
            a.btn(href='https://onlineimagetools.com', target='_blank') Online IMAGE Tools
            a.btn(href='https://onlinejpgtools.com', target='_blank') Online JPG Tools
            a.btn(href='https://onlinepngtools.com', target='_blank') Online PNG Tools
            a.btn(href='https://onlinefractaltools.com', target='_blank') Online FRACTAL Tools
            //- a.btn(href='https://onlinepdftools.com', target='_blank') Online PDF Tools
            //- a.btn(href='https://onlineaudiotools.com', target='_blank') Online AUDIO Tools
            //- a.btn(href='https://onlinebrowsertools.com', target='_blank') Online BROWSER Tools
            //- a.btn(href='https://onlinecsstools.com', target='_blank') Online CSS Tools
            //- a.btn(href='https://onlinejstools.com', target='_blank') Online JS Tools
            //- a.btn(href='https://onlinecryptotools.com', target='_blank') Online CRYPTO Tools
            //- a.btn(href='https://onlinefiletools.com', target='_blank') Online FILE Tools
            //- a.btn(href='https://onlinetimetools.com', target='_blank') Online TIME Tools
View Compiled
$color-placeholder: #888;

/* https://snook.ca/archives/html_and_css/hiding-content-for-accessibility */
.visually-hidden { 
    position: absolute !important;
    height: 1px; width: 1px;
    overflow: hidden;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
    clip: rect(1px, 1px, 1px, 1px);
}

*,
*:before,
*:after {
    box-sizing: inherit;
}
html {
    box-sizing: border-box;
    font-size: 16px;
    height: 100%;
    overflow: hidden;
}
body {
    align-items: flex-start;
    background-color: #4e4e4e;
    display: flex;
    flex-direction: row;
    align-items: stretch;
    justify-content: flex-start;
    height: 100%;
    color: #e8e8e8;
    &.cursor-wait {
        cursor: wait;
        * {
            cursor: wait;
        }
    }
}
aside {
    background-color: transparent;
    padding: 1rem;
    width: 23rem;
    overflow-y: scroll;
}
main {
    background-color: transparent;
    padding: 1rem;
    flex: 2;
    height: 100%;
}
.main-textarea {
    color: #e8e8e8;
    background-color: hsl(0, 0%, 15%);
    display: block;
    font-family: "Roboto Mono", Consolas, monaco, monospace;
    font-size: 18px;
    font-weight: lighter;
    line-height: 1.4;
    width: 100%;
    height: calc(100% - 2rem);
    padding: 1rem;
    resize: none;
    white-space: nowrap;
    overflow: auto;
    margin: 0;
    &.wordwrap {
        white-space: normal;
    }
}
.textarea-options-wrapper {
}
.word-wrap-wrapper {
    display: inline-block;
}
.btn {
    color: #000;
    text-align: center;
    background-color: #d4d4d4;
    text-decoration: none;
    border: 0;
    display: block;
    width: 100%;
    padding: 0.2rem 0.1rem;
    cursor: pointer;
    margin-bottom: 0.5rem;
    &:last-child {
        margin-bottom: 0;
    }
    &:disabled {
        color: #7f7f7f;
        background-color: #636363;
        cursor: default;
        &:hover {
            background-color: #636363;
        }
    }
    &:hover {
        border: 0;
        background-color: #fff;
    }
    &:focus,
    &:active,
    &:active:hover {
        outline-color: rgb(59, 153, 252);
        outline-offset: 0px;
        outline-style: auto;
        outline-width: 5px;
    }
}
fieldset {
    border-color: #6d6d6d;
    margin-bottom: 1rem;
    &.to-do {
        background-color: red;
    }
    &.collapsed {
        legend {
            cursor: s-resize;
        }
    }
    legend {
        cursor: n-resize;
        font-size: 0.8rem;
        padding: 0 0.5rem;
    }
    .fieldset-content {
        display: block;
    }
    select {
        border-radius: 0;
        display: block;
        height: 1.8rem;
        width: 100%;
    }
    option {
        &.font-family-monospaced {
            font-family: "Roboto Mono", Consolas, monaco, monospace;
        }
        &.font-family-sansserif {
            font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
        }
        &.font-family-serif {
            font-family: TimesNewRoman, "Times New Roman", Times, Baskerville,
                Georgia, serif;
        }
    }
}

.font-subheading {
    font-size: 0.8rem;
    text-align: left;
    margin: 0.3rem 0;
    padding-left: 0.3rem;
}

.replace-with,
.prepend-append-with {
    font-size: 0.8rem;
    text-align: left;
    margin: 0.3rem 0;
    padding-left: 0.3rem;
}

.select-prepend-append-2 {
    margin-bottom: 0;
}

.rot-number-select {
    margin: 0 0 0.5rem 0;
}

.select-replace-2 {
    margin-bottom: 0;
}

.tabular-data-delimeter {
    font-size: 0.8rem;
    margin: 0.3rem 0;
}

.tabular-data-delimeter-value {
    //margin-bottom: 0.5rem;
}

.replace-1-other,
.replace-2-other {
    padding-left: 4px;
    width: 100%;
}

.btn-prepend-append-action {
    margin-top: 0.5rem;
}

.prepend-append-other {
    padding-left: 4px;
    width: 100%;
}

.split-on-string {
    padding-left: 4px;
    margin-bottom: 0.5rem;
    width: 100%;
}

.btn-replace {
    margin-top: 0.5rem;
}

.tabular-data-other-delimeter-value {
    padding-left: 4px;
    width: 100%;
    margin-bottom: 0.5rem;
}

.btn-tabular-data-analyse {
    margin-top: 0.5rem;
}

.tabular-data-first-row-headings-checkbox {
    position: relative;
}

.tabular-data-first-row-headings {
    font-size: 0.8rem;
}

.view-html-css-prompt {
    font-size: 0.8rem;
    text-align: left;
    margin: 1rem 0 0.3rem 0;
    padding-left: 0.3rem;
}

.view-html-css-select {
    margin-top: 0.5rem;
}

.tabular-data-num-rows-columns {
    font-size: 0.8rem;
    margin: 0.3rem 0;
    text-align: center;
}

.tabular-data-column {
    font-size: 0.8rem;
    margin: 0.3rem 0;
}

.tabular-data-action {
    font-size: 0.8rem;
    margin: 0.6rem 0 0.3rem 0;
}

.tabular-data-action-select {
    margin-bottom: 0.5rem;
}

.tabular-data-convert {
    font-size: 0.8rem;
    margin: 0.6rem 0 0.3rem 0;
}

.tabular-data-convert-select {
    margin-bottom: 0.5rem;
}

.lines-that {
    font-size: 0.8rem;
    text-align: left;
    margin: 1rem 0 0.3rem 0;
    padding-left: 0.3rem;
}

.select-lines-that {
}

.num-random-items {
    font-size: 0.8rem;
    text-align: left;
    margin: 0 0 0.3rem 0;
    padding-left: 0.5rem;
}

.num-random-items-select {
    margin-bottom: 0.5rem;
}

.lines-that-value {
    padding-left: 4px;
    margin-bottom: 0.5rem;
    width: 100%;
}

.remove-text-on-each-line {
    font-size: 0.8rem;
    text-align: left;
    margin: 1rem 0 0.3rem 0;
    padding-left: 0.3rem;
}

.remove-text-on-each-line-the {
    font-size: 0.8rem;
    text-align: left;
    margin: 0.3rem 0;
    padding-left: 0.3rem;
}

.remove-chars-from-position,
.remove-chars-from-position-from-the,
.remove-chars-from-position-from-the {
    font-size: 0.8rem;
    text-align: left;
    margin: 0.3rem 0;
    padding-left: 0.3rem;
}

.remove-lines-by-length {
    font-size: 0.8rem;
    text-align: left;
    margin: 0.3rem 0;
    padding-left: 0.3rem;
}

.remove-lines-by-length {
    margin: 1rem 0 0.3rem 0;
}

.select-remove-lines-by-length-num-chars {
    padding-left: 4px;
    margin-bottom: 0.5rem;
    width: 100%;
}

.instance-of-text-value {
    padding-left: 4px;
    margin-bottom: 0.5rem;
    width: 100%;
}

.input-remove-chars-from-nth-position {
    padding-left: 4px;
    margin-bottom: 0;
    width: 100%;
}

.substring-frequency {
    font-size: 0.8rem;
    text-align: left;
    margin: 1rem 0 0.3rem 0;
    padding-left: 0.3rem;
}

.substring-frequency-value {
    padding-left: 4px;
    margin-bottom: 0.5rem;
    width: 100%;
}

.vigenere-key {
    padding-left: 4px;
    margin-bottom: 0.5rem;
    width: 100%;
}

.repeats-after {
    font-size: 0.8rem;
    text-align: left;
    margin: 0.3rem 0;
    padding-left: 0.3rem;
}

.repeats-after-delimeter {
    font-size: 0.8rem;
    text-align: left;
    margin: 0.3rem 0;
    padding-left: 0.3rem;
}

.mathematical-unicode {
    font-size: 0.8rem;
    text-align: left;
    margin: 1rem 0 0.3rem 0;
    padding-left: 0.3rem;
}

.btn-repeats-to-table {
    margin-top: 0.5rem;
}

.input-row {
    font-size: 0.8rem;
    margin-bottom: 0.2rem;
}

.lodash-whole-document-radio-input-row {
    margin-bottom: 0.4rem;
}

.encode-decode-whole-document-radio-input-row {
    margin-bottom: 0.4rem;
}

::-webkit-input-placeholder {
    /* Chrome/Opera/Safari */
    color: $color-placeholder;
}
::-moz-placeholder {
    /* Firefox 19+ */
    color: $color-placeholder;
}
:-ms-input-placeholder {
    /* IE 10+ */
    color: $color-placeholder;
}
:-moz-placeholder {
    /* Firefox 18- */
    color: $color-placeholder;
}
// =========================================================
// Constants
// =========================================================

const citiesUk = ['Aberdeen', 'Armagh', 'Bangor', 'Bath', 'Belfast', 'Birmingham', 'Bradford', 'Brighton & Hove', 'Bristol', 'Cambridge', 'Canterbury', 'Christ', 'Cardiff', 'Carlisle', 'Chelmsford', 'Chester', 'Chichester', 'Coventry', 'Derby', 'Derry ', 'Dundee', 'Durham', 'Edinburgh', 'Ely', 'Exeter', 'Glasgow', 'Gloucester', 'Hereford', 'Inverness', 'Kingston upon Hull', 'Lancaster', 'Leeds', 'Leicester', 'Lichfield', 'Lincoln', 'Lisburn', 'Liverpool', 'London', 'Manchester', 'Newcastle upon Tyne', 'Newport', 'Newry', 'Norwich', 'Nottingham', 'Oxford', 'Perth', 'Peterborough', 'Plymouth', 'Portsmouth', 'Preston', 'Ripon', 'St Albans', 'St Asaph', 'St Davids', 'Salford', 'Salisbury', 'Sheffield', 'Southampton', 'Stirling', 'Stoke-on-Trent', 'Sunderland', 'Swansea', 'Truro', 'Wakefield', 'Wells', 'Westminster', 'Winchester', 'Wolverhampton', 'Worcester', 'York'];

let citiesWorld = ['Chongqing', 'Shanghai', 'Beijing', 'Lagos', 'Dhaka', 'Mumbai', 'Chengdu', 'Karachi', 'Guangzhou', 'Istanbul', 'Tokyo', 'Tianjin', 'Moscow', 'São Paulo', 'Kinshasa', 'Delhi', 'Baoding', 'Lahore', 'Cairo', 'Seoul', 'Jakarta', 'Wenzhou', 'Lima', 'Mexico City', 'London', 'Bangkok', 'Xi\'an', 'Chennai', 'Bangalore', 'New York City', 'Ho Chi Minh City', 'Hyderabad', 'Shenzhen', 'Suzhou', 'Nanjing', 'Dongguan', 'Tehran', 'Quanzhou', 'Shenyang', 'Bogotá', 'Hong Kong', 'Baghdad', 'Fuzhou', 'Changsha', 'Wuhan', 'Hanoi', 'Rio de Janeiro', 'Qingdao', 'Foshan', 'Zunyi', 'Santiago', 'Riyadh', 'Ahmedabad', 'Singapore', 'Shantou', 'Ankara', 'Yangon', 'Saint Petersburg', 'Sydney', 'Casablanca', 'Melbourne', 'Abidjan', 'Alexandria', 'Kolkata', 'Surat', 'Johannesburg', 'Dar es Salaam', 'Shijiazhuang', 'Harbin', 'Giza', 'İzmir', 'Zhengzhou', 'New Taipei City', 'Los Angeles', 'Changchun', 'Cape Town', 'Yokohama', 'Khartoum', 'Guayaquil', 'Hangzhou', 'Xiamen', 'Berlin', 'Busan', 'Ningbo', 'Jeddah', 'Durban', 'Algiers', 'Kabul', 'Hefei', 'Mashhad', 'Pyongyang', 'Madrid', 'Faisalabad', 'Baku', 'Tangshan', 'Ekurhuleni', 'Nairobi', 'Zhongshan', 'Pune', 'Addis Ababa', 'Jaipur', 'Buenos Aires', 'Incheon', 'Quezon City', 'Toronto', 'Kiev', 'Salvador', 'Rome', 'Dubai', 'Luanda', 'Lucknow', 'Kaohsiung', 'Kanpur', 'Surabaya', 'Taichung', 'Basra', 'Taipei', 'Chicago', 'Osaka', 'Quito', 'Chaozhou', 'Fortaleza', 'Chittagong', 'Bandung', 'Managua', 'Brasília', 'Belo Horizonte', 'Daegu', 'Houston', 'Douala', 'Medellin', 'Yaoundé', 'Nagpur', 'Cali', 'Tashkent', 'Nagoya', 'Isfahan', 'Phnom Penh', 'Paris', 'Ouagadougou', 'Lanzhou', 'Kano', 'Dalian', 'Guatemala City', 'Havana', 'Rawalpindi', 'Medan', 'Accra', 'Visakhapatnam', 'Gujranwala', 'Jinan', 'Karaj', 'Peshawar', 'Minsk', 'Caracas', 'Sapporo', 'Tainan', 'Bucharest', 'Curitiba', 'Multan', 'Shiraz', 'Vienna', 'Brazzaville', 'Bhopal', 'Almaty', 'Hamburg', 'Manila', 'Kuala Lumpur', 'Maputo', 'Budapest', 'Warsaw', 'Lusaka', 'Kathmandu', 'Tabriz', 'Hyderabad', 'Palembang', 'Tijuana', 'Patna', 'Montreal', 'Davao City', 'Harare', 'Barcelona', 'Maracaibo', 'Caloocan', 'Philadelphia', 'Novosibirsk', 'Phoenix', 'Oran', 'Semarang', 'Recife', 'Kobe', 'Daejeon', 'Kampala', 'Kawasaki', 'Guadalajara', 'Auckland', 'Vijayawada', 'Fukuoka', 'Gwangju', 'Porto Alegre', 'Kyoto', 'San Antonio', 'Santa Cruz de la Sierra', 'Munich', 'Kharkiv', 'Yekaterinburg', 'San Diego', 'Barranquilla', 'Milan', 'Ibadan', 'Makassar', 'Córdoba', 'Prague', 'Mandalay', 'Dallas', 'Montevideo', 'Qom', 'Ahvaz', 'Sofia', 'Nizhny Novgorod', 'Abuja', 'Calgary', 'Saitama', 'Suwon', 'Hiroshima', 'Rosario', 'Brisbane', 'Allahabad', 'Belgrade', 'Campinas', 'Ulsan', 'Omsk', 'Dakar', 'Abu Dhabi', 'Monterrey', 'Tripoli', 'Rostov-on-Don', 'T\'bilisi', 'Fez', 'Birmingham', 'Yerevan', 'Cologne', 'Tunis', 'Bulawayo', 'Astana', 'Islamabad', 'Cartagena'];

const dataString = 'first:Adrian;last:Parr;age:43;gender:Male;location:Poole, UK';

const repeatingDataString = 'first:Adrian; last:Parr; age:43; gender:Male; location:Poole; first:Sarah; last:Smith; age:38; gender:Female; location:Bristol; first:Jenny; last:Windsor; age:14; gender:Female; location:London; first:Dave; last:Kinworth; age:62; gender:Male; location:Cardiff; first:Robert; last:Connor; age:24; gender:Male; location:Liverpool; first:Micheal; last:Oldfield; age:44; gender:Male; location:Exeter; first:Fred; last:Rosen; age:11; gender:Male; location:Coventry; first:Trudy; last:Jones; age:3; gender:Female; location:Birmingham; first:Betty; last:Boo; age:56; gender:Female; location:Kettering; first:Maureen; last:Lipman; age:90; gender:Female; location:Brigton; first:Diane; last:Spencer; age:38; gender:Female; location:Ashford; first:Jack; last:Jones; age:25; gender:Male; location:Manchester; first:Albert; last:Ellis; age:29; gender:Male; location:York; first:Leo; last:Rodgers; age:31; gender:Male; location:Leeds; first:Kersten; last:Adams; age:72; gender:Female; location:Nottingham; first:Philippa; last:Gregory; age:8; gender:Female; location:Glasgow; first:Victor; last:Hugo; age:58; gender:Male; location:Dublin;';

const dataToBeLinedUp = `Delivered-To: joe.bloggs@gmail.com
Received: by 2002:a67:edca:0:0:0:0:0 with SMTP id e10csp4074100vsp;Wed, 29 May 2019 03:02:31 -0700 (PDT)
X-Google-Smtp-Source: APXvYqyJ9DjuiCwPpOgNy4krHzNoKJQpgNzL6APOsstCwIC+iu8J6wdz8d8jS9ZjAeJPOms4gdBr
X-Received: by 2002:a50:ad2b:: with SMTP id y40mr133503832edc.237.1559124151566;Wed, 29 May 2019 03:02:31 -0700 (PDT)
MIME-Version: 1.0
From: "John Doe" <john.doe@hotmail.com>
To: joe.bloggs@gmail.com
Reply-To: john.doe@hotmail.com
Date: 29 May 2019 11:01:38 +0100
Subject: Subject line would go in here
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable
Message-ID: <TJGAMUP509XNx3m4vOy0b20df95@tjgmail.app.tjgprod.ds>
X-OriginalArrivalTime: 29 May 2019 10:01:38.0901 (UTC) FILETIME=[82006850:01D51605]`;


// http://xahlee.info/comp/unicode_math_font.html

const charToMathematicalDoubleStruckLookupTable = {'A':'𝔸','B':'𝔹','C':'ℂ','D':'𝔻','E':'𝔼','F':'𝔽','G':'𝔾','H':'ℍ','I':'𝕀','J':'𝕁','K':'𝕂','L':'𝕃','M':'𝕄','N':'ℕ','O':'𝕆','P':'ℙ','Q':'ℚ','R':'ℝ','S':'𝕊','T':'𝕋','U':'𝕌','V':'𝕍','W':'𝕎','X':'𝕏','Y':'𝕐','Z':'ℤ','a':'𝕒','b':'𝕓','c':'𝕔','d':'𝕕','e':'𝕖','f':'𝕗','g':'𝕘','h':'𝕙','i':'𝕚','j':'𝕛','k':'𝕜','l':'𝕝','m':'𝕞','n':'𝕟','o':'𝕠','p':'𝕡','q':'𝕢','r':'𝕣','s':'𝕤','t':'𝕥','u':'𝕦','v':'𝕧','w':'𝕨','x':'𝕩','y':'𝕪','z':'𝕫','0':'𝟘','1':'𝟙','2':'𝟚','3':'𝟛','4':'𝟜','5':'𝟝','6':'𝟞','7':'𝟟','8':'𝟠','9':'𝟡'};

const mathematicalDoubleStruckToCharLookupTable = {'𝔸':'A','𝔹':'B','ℂ':'C','𝔻':'D','𝔼':'E','𝔽':'F','𝔾':'G','ℍ':'H','𝕀':'I','𝕁':'J','𝕂':'K','𝕃':'L','𝕄':'M','ℕ':'N','𝕆':'O','ℙ':'P','ℚ':'Q','ℝ':'R','𝕊':'S','𝕋':'T','𝕌':'U','𝕍':'V','𝕎':'W','𝕏':'X','𝕐':'Y','ℤ':'Z','𝕒':'a','𝕓':'b','𝕔':'c','𝕕':'d','𝕖':'e','𝕗':'f','𝕘':'g','𝕙':'h','𝕚':'i','𝕛':'j','𝕜':'k','𝕝':'l','𝕞':'m','𝕟':'n','𝕠':'o','𝕡':'p','𝕢':'q','𝕣':'r','𝕤':'s','𝕥':'t','𝕦':'u','𝕧':'v','𝕨':'w','𝕩':'x','𝕪':'y','𝕫':'z','𝟘':'0','𝟙':'1','𝟚':'2','𝟛':'3','𝟜':'4','𝟝':'5','𝟞':'6','𝟟':'7','𝟠':'8','𝟡':'9'};

const charToMathematicalFrakturLookupTable = {'A':'𝔄','B':'𝔅','C':'ℭ','D':'𝔇','E':'𝔈','F':'𝔉','G':'𝔊','H':'ℌ','I':'ℑ','J':'𝔍','K':'𝔎','L':'𝔏','M':'𝔐','N':'𝔑','O':'𝔒','P':'𝔓','Q':'𝔔','R':'ℜ','S':'𝔖','T':'𝔗','U':'𝔘','V':'𝔙','W':'𝔚','X':'𝔛','Y':'𝔜','Z':'ℨ','a':'𝔞','b':'𝔟','c':'𝔠','d':'𝔡','e':'𝔢','f':'𝔣','g':'𝔤','h':'𝔥','i':'𝔦','j':'𝔧','k':'𝔨','l':'𝔩','m':'𝔪','n':'𝔫','o':'𝔬','p':'𝔭','q':'𝔮','r':'𝔯','s':'𝔰','t':'𝔱','u':'𝔲','v':'𝔳','w':'𝔴','x':'𝔵','y':'𝔶','z':'𝔷'};

const mathematicalFrakturToCharLookupTable = {'𝔄':'A','𝔅':'B','ℭ':'C','𝔇':'D','𝔈':'E','𝔉':'F','𝔊':'G','ℌ':'H','ℑ':'I','𝔍':'J','𝔎':'K','𝔏':'L','𝔐':'M','𝔑':'N','𝔒':'O','𝔓':'P','𝔔':'Q','ℜ':'R','𝔖':'S','𝔗':'T','𝔘':'U','𝔙':'V','𝔚':'W','𝔛':'X','𝔜':'Y','ℨ':'Z','𝔞':'a','𝔟':'b','𝔠':'c','𝔡':'d','𝔢':'e','𝔣':'f','𝔤':'g','𝔥':'h','𝔦':'i','𝔧':'j','𝔨':'k','𝔩':'l','𝔪':'m','𝔫':'n','𝔬':'o','𝔭':'p','𝔮':'q','𝔯':'r','𝔰':'s','𝔱':'t','𝔲':'u','𝔳':'v','𝔴':'w','𝔵':'x','𝔶':'y','𝔷':'z'};

const charToMathematicalBoldFrakturLookupTable = {'A':'𝕬','B':'𝕭','C':'𝕮','D':'𝕯','E':'𝕰','F':'𝕱','G':'𝕲','H':'𝕳','I':'𝕴','J':'𝕵','K':'𝕶','L':'𝕷','M':'𝕸','N':'𝕹','O':'𝕺','P':'𝕻','Q':'𝕼','R':'𝕽','S':'𝕾','T':'𝕿','U':'𝖀','V':'𝖁','W':'𝖂','X':'𝖃','Y':'𝖄','Z':'𝖅','a':'𝖆','b':'𝖇','c':'𝖈','d':'𝖉','e':'𝖊','f':'𝖋','g':'𝖌','h':'𝖍','i':'𝖎','j':'𝖏','k':'𝖐','l':'𝖑','m':'𝖒','n':'𝖓','o':'𝖔','p':'𝖕','q':'𝖖','r':'𝖗','s':'𝖘','t':'𝖙','u':'𝖚','v':'𝖛','w':'𝖜','x':'𝖝','y':'𝖞','z':'𝖟'};

const mathematicalBoldFrakturToCharLookupTable = {'𝕬':'A','𝕭':'B','𝕮':'C','𝕯':'D','𝕰':'E','𝕱':'F','𝕲':'G','𝕳':'H','𝕴':'I','𝕵':'J','𝕶':'K','𝕷':'L','𝕸':'M','𝕹':'N','𝕺':'O','𝕻':'P','𝕼':'Q','𝕽':'R','𝕾':'S','𝕿':'T','𝖀':'U','𝖁':'V','𝖂':'W','𝖃':'X','𝖄':'Y','𝖅':'Z','𝖆':'a','𝖇':'b','𝖈':'c','𝖉':'d','𝖊':'e','𝖋':'f','𝖌':'g','𝖍':'h','𝖎':'i','𝖏':'j','𝖐':'k','𝖑':'l','𝖒':'m','𝖓':'n','𝖔':'o','𝖕':'p','𝖖':'q','𝖗':'r','𝖘':'s','𝖙':'t','𝖚':'u','𝖛':'v','𝖜':'w','𝖝':'x','𝖞':'y','𝖟':'z'};

const charToMathematicalBoldLookupTable = {'A':'𝐀','B':'𝐁','C':'𝐂','D':'𝐃','E':'𝐄','F':'𝐅','G':'𝐆','H':'𝐇','I':'𝐈','J':'𝐉','K':'𝐊','L':'𝐋','M':'𝐌','N':'𝐍','O':'𝐎','P':'𝐏','Q':'𝐐','R':'𝐑','S':'𝐒','T':'𝐓','U':'𝐔','V':'𝐕','W':'𝐖','X':'𝐗','Y':'𝐘','Z':'𝐙','a':'𝐚','b':'𝐛','c':'𝐜','d':'𝐝','e':'𝐞','f':'𝐟','g':'𝐠','h':'𝐡','i':'𝐢','j':'𝐣','k':'𝐤','l':'𝐥','m':'𝐦','n':'𝐧','o':'𝐨','p':'𝐩','q':'𝐪','r':'𝐫','s':'𝐬','t':'𝐭','u':'𝐮','v':'𝐯','w':'𝐰','x':'𝐱','y':'𝐲','z':'𝐳','0':'𝟎','1':'𝟏','2':'𝟐','3':'𝟑','4':'𝟒','5':'𝟓','6':'𝟔','7':'𝟕','8':'𝟖','9':'𝟗'};

const mathematicalBoldToCharLookupTable = {'𝐀':'A','𝐁':'B','𝐂':'C','𝐃':'D','𝐄':'E','𝐅':'F','𝐆':'G','𝐇':'H','𝐈':'I','𝐉':'J','𝐊':'K','𝐋':'L','𝐌':'M','𝐍':'N','𝐎':'O','𝐏':'P','𝐐':'Q','𝐑':'R','𝐒':'S','𝐓':'T','𝐔':'U','𝐕':'V','𝐖':'W','𝐗':'X','𝐘':'Y','𝐙':'Z','𝐚':'a','𝐛':'b','𝐜':'c','𝐝':'d','𝐞':'e','𝐟':'f','𝐠':'g','𝐡':'h','𝐢':'i','𝐣':'j','𝐤':'k','𝐥':'l','𝐦':'m','𝐧':'n','𝐨':'o','𝐩':'p','𝐪':'q','𝐫':'r','𝐬':'s','𝐭':'t','𝐮':'u','𝐯':'v','𝐰':'w','𝐱':'x','𝐲':'y','𝐳':'z','𝟎':'0','𝟏':'1','𝟐':'2','𝟑':'3','𝟒':'4','𝟓':'5','𝟔':'6','𝟕':'7','𝟖':'8','𝟗':'9'};

const charToMathematicalItalicLookupTable = {'A':'𝐴','B':'𝐵','C':'𝐶','D':'𝐷','E':'𝐸','F':'𝐹','G':'𝐺','H':'𝐻','I':'𝐼','J':'𝐽','K':'𝐾','L':'𝐿','M':'𝑀','N':'𝑁','O':'𝑂','P':'𝑃','Q':'𝑄','R':'𝑅','S':'𝑆','T':'𝑇','U':'𝑈','V':'𝑉','W':'𝑊','X':'𝑋','Y':'𝑌','Z':'𝑍','a':'𝑎','b':'𝑏','c':'𝑐','d':'𝑑','e':'𝑒','f':'𝑓','g':'𝑔','h':'ℎ','i':'𝑖','j':'𝑗','k':'𝑘','l':'𝑙','m':'𝑚','n':'𝑛','o':'𝑜','p':'𝑝','q':'𝑞','r':'𝑟','s':'𝑠','t':'𝑡','u':'𝑢','v':'𝑣','w':'𝑤','x':'𝑥','y':'𝑦','z':'𝑧'};

const mathematicalItalicToCharLookupTable = {'𝐴':'A','𝐵':'B','𝐶':'C','𝐷':'D','𝐸':'E','𝐹':'F','𝐺':'G','𝐻':'H','𝐼':'I','𝐽':'J','𝐾':'K','𝐿':'L','𝑀':'M','𝑁':'N','𝑂':'O','𝑃':'P','𝑄':'Q','𝑅':'R','𝑆':'S','𝑇':'T','𝑈':'U','𝑉':'V','𝑊':'W','𝑋':'X','𝑌':'Y','𝑍':'Z','𝑎':'a','𝑏':'b','𝑐':'c','𝑑':'d','𝑒':'e','𝑓':'f','𝑔':'g','ℎ':'h','𝑖':'i','𝑗':'j','𝑘':'k','𝑙':'l','𝑚':'m','𝑛':'n','𝑜':'o','𝑝':'p','𝑞':'q','𝑟':'r','𝑠':'s','𝑡':'t','𝑢':'u','𝑣':'v','𝑤':'w','𝑥':'x','𝑦':'y','𝑧':'z'};

const charToMathematicalBoldItalicLookupTable = {'A':'𝑨','B':'𝑩','C':'𝑪','D':'𝑫','E':'𝑬','F':'𝑭','G':'𝑮','H':'𝑯','I':'𝑰','J':'𝑱','K':'𝑲','L':'𝑳','M':'𝑴','N':'𝑵','O':'𝑶','P':'𝑷','Q':'𝑸','R':'𝑹','S':'𝑺','T':'𝑻','U':'𝑼','V':'𝑽','W':'𝑾','X':'𝑿','Y':'𝒀','Z':'𝒁','a':'𝒂','b':'𝒃','c':'𝒄','d':'𝒅','e':'𝒆','f':'𝒇','g':'𝒈','h':'𝒉','i':'𝒊','j':'𝒋','k':'𝒌','l':'𝒍','m':'𝒎','n':'𝒏','o':'𝒐','p':'𝒑','q':'𝒒','r':'𝒓','s':'𝒔','t':'𝒕','u':'𝒖','v':'𝒗','w':'𝒘','x':'𝒙','y':'𝒚','z':'𝒛'};

const mathematicalBoldItalicToCharLookupTable = {'𝑨':'A','𝑩':'B','𝑪':'C','𝑫':'D','𝑬':'E','𝑭':'F','𝑮':'G','𝑯':'H','𝑰':'I','𝑱':'J','𝑲':'K','𝑳':'L','𝑴':'M','𝑵':'N','𝑶':'O','𝑷':'P','𝑸':'Q','𝑹':'R','𝑺':'S','𝑻':'T','𝑼':'U','𝑽':'V','𝑾':'W','𝑿':'X','𝒀':'Y','𝒁':'Z','𝒂':'a','𝒃':'b','𝒄':'c','𝒅':'d','𝒆':'e','𝒇':'f','𝒈':'g','𝒉':'h','𝒊':'i','𝒋':'j','𝒌':'k','𝒍':'l','𝒎':'m','𝒏':'n','𝒐':'o','𝒑':'p','𝒒':'q','𝒓':'r','𝒔':'s','𝒕':'t','𝒖':'u','𝒗':'v','𝒘':'w','𝒙':'x','𝒚':'y','𝒛':'z'};

const charToMathematicalScriptLookupTable = {'A':'𝒜','B':'ℬ','C':'𝒞','D':'𝒟','E':'ℰ','F':'ℱ','G':'𝒢','H':'ℋ','I':'ℐ','J':'𝒥','K':'𝒦','L':'ℒ','M':'ℳ','N':'𝒩','O':'𝒪','P':'𝒫','Q':'𝒬','R':'ℛ','S':'𝒮','T':'𝒯','U':'𝒰','V':'𝒱','W':'𝒲','X':'𝒳','Y':'𝒴','Z':'𝒵','a':'𝒶','b':'𝒷','c':'𝒸','d':'𝒹','e':'ℯ','f':'𝒻','g':'ℊ','h':'𝒽','i':'𝒾','j':'𝒿','k':'𝓀','l':'𝓁','m':'𝓂','n':'𝓃','o':'ℴ','p':'𝓅','q':'𝓆','r':'𝓇','s':'𝓈','t':'𝓉','u':'𝓊','v':'𝓋','w':'𝓌','x':'𝓍','y':'𝓎','z':'𝓏'};

const mathematicalScriptToCharLookupTable = {'𝒜':'A','ℬ':'B','𝒞':'C','𝒟':'D','ℰ':'E','ℱ':'F','𝒢':'G','ℋ':'H','ℐ':'I','𝒥':'J','𝒦':'K','ℒ':'L','ℳ':'M','𝒩':'N','𝒪':'O','𝒫':'P','𝒬':'Q','ℛ':'R','𝒮':'S','𝒯':'T','𝒰':'U','𝒱':'V','𝒲':'W','𝒳':'X','𝒴':'Y','𝒵':'Z','𝒶':'a','𝒷':'b','𝒸':'c','𝒹':'d','ℯ':'e','𝒻':'f','ℊ':'g','𝒽':'h','𝒾':'i','𝒿':'j','𝓀':'k','𝓁':'l','𝓂':'m','𝓃':'n','ℴ':'o','𝓅':'p','𝓆':'q','𝓇':'r','𝓈':'s','𝓉':'t','𝓊':'u','𝓋':'v','𝓌':'w','𝓍':'x','𝓎':'y','𝓏':'z'};

const charToMathematicalBoldScriptLookupTable = {'A':'𝓐','B':'𝓑','C':'𝓒','D':'𝓓','E':'𝓔','F':'𝓕','G':'𝓖','H':'𝓗','I':'𝓘','J':'𝓙','K':'𝓚','L':'𝓛','M':'𝓜','N':'𝓝','O':'𝓞','P':'𝓟','Q':'𝓠','R':'𝓡','S':'𝓢','T':'𝓣','U':'𝓤','V':'𝓥','W':'𝓦','X':'𝓧','Y':'𝓨','Z':'𝓩','a':'𝓪','b':'𝓫','c':'𝓬','d':'𝓭','e':'𝓮','f':'𝓯','g':'𝓰','h':'𝓱','i':'𝓲','j':'𝓳','k':'𝓴','l':'𝓵','m':'𝓶','n':'𝓷','o':'𝓸','p':'𝓹','q':'𝓺','r':'𝓻','s':'𝓼','t':'𝓽','u':'𝓾','v':'𝓿','w':'𝔀','x':'𝔁','y':'𝔂','z':'𝔃'};

const mathematicalBoldScriptToCharLookupTable = {'𝓐':'A','𝓑':'B','𝓒':'C','𝓓':'D','𝓔':'E','𝓕':'F','𝓖':'G','𝓗':'H','𝓘':'I','𝓙':'J','𝓚':'K','𝓛':'L','𝓜':'M','𝓝':'N','𝓞':'O','𝓟':'P','𝓠':'Q','𝓡':'R','𝓢':'S','𝓣':'T','𝓤':'U','𝓥':'V','𝓦':'W','𝓧':'X','𝓨':'Y','𝓩':'Z','𝓪':'a','𝓫':'b','𝓬':'c','𝓭':'d','𝓮':'e','𝓯':'f','𝓰':'g','𝓱':'h','𝓲':'i','𝓳':'j','𝓴':'k','𝓵':'l','𝓶':'m','𝓷':'n','𝓸':'o','𝓹':'p','𝓺':'q','𝓻':'r','𝓼':'s','𝓽':'t','𝓾':'u','𝓿':'v','𝔀':'w','𝔁':'x','𝔂':'y','𝔃':'z'};

const charToMathematicalSansSerifLookupTable = {'A':'𝖠','B':'𝖡','C':'𝖢','D':'𝖣','E':'𝖤','F':'𝖥','G':'𝖦','H':'𝖧','I':'𝖨','J':'𝖩','K':'𝖪','L':'𝖫','M':'𝖬','N':'𝖭','O':'𝖮','P':'𝖯','Q':'𝖰','R':'𝖱','S':'𝖲','T':'𝖳','U':'𝖴','V':'𝖵','W':'𝖶','X':'𝖷','Y':'𝖸','Z':'𝖹','a':'𝖺','b':'𝖻','c':'𝖼','d':'𝖽','e':'𝖾','f':'𝖿','g':'𝗀','h':'𝗁','i':'𝗂','j':'𝗃','k':'𝗄','l':'𝗅','m':'𝗆','n':'𝗇','o':'𝗈','p':'𝗉','q':'𝗊','r':'𝗋','s':'𝗌','t':'𝗍','u':'𝗎','v':'𝗏','w':'𝗐','x':'𝗑','y':'𝗒','z':'𝗓','0':'𝟢','1':'𝟣','2':'𝟤','3':'𝟥','4':'𝟦','5':'𝟧','6':'𝟨','7':'𝟩','8':'𝟪','9':'𝟫'};

const mathematicalSansSerifToCharLookupTable = {'𝖠':'A','𝖡':'B','𝖢':'C','𝖣':'D','𝖤':'E','𝖥':'F','𝖦':'G','𝖧':'H','𝖨':'I','𝖩':'J','𝖪':'K','𝖫':'L','𝖬':'M','𝖭':'N','𝖮':'O','𝖯':'P','𝖰':'Q','𝖱':'R','𝖲':'S','𝖳':'T','𝖴':'U','𝖵':'V','𝖶':'W','𝖷':'X','𝖸':'Y','𝖹':'Z','𝖺':'a','𝖻':'b','𝖼':'c','𝖽':'d','𝖾':'e','𝖿':'f','𝗀':'g','𝗁':'h','𝗂':'i','𝗃':'j','𝗄':'k','𝗅':'l','𝗆':'m','𝗇':'n','𝗈':'o','𝗉':'p','𝗊':'q','𝗋':'r','𝗌':'s','𝗍':'t','𝗎':'u','𝗏':'v','𝗐':'w','𝗑':'x','𝗒':'y','𝗓':'z','𝟢':'0','𝟣':'1','𝟤':'2','𝟥':'3','𝟦':'4','𝟧':'5','𝟨':'6','𝟩':'7','𝟪':'8','𝟫':'9'};

const charToMathematicalSansSerifBoldLookupTable = {'A':'𝗔','B':'𝗕','C':'𝗖','D':'𝗗','E':'𝗘','F':'𝗙','G':'𝗚','H':'𝗛','I':'𝗜','J':'𝗝','K':'𝗞','L':'𝗟','M':'𝗠','N':'𝗡','O':'𝗢','P':'𝗣','Q':'𝗤','R':'𝗥','S':'𝗦','T':'𝗧','U':'𝗨','V':'𝗩','W':'𝗪','X':'𝗫','Y':'𝗬','Z':'𝗭','a':'𝗮','b':'𝗯','c':'𝗰','d':'𝗱','e':'𝗲','f':'𝗳','g':'𝗴','h':'𝗵','i':'𝗶','j':'𝗷','k':'𝗸','l':'𝗹','m':'𝗺','n':'𝗻','o':'𝗼','p':'𝗽','q':'𝗾','r':'𝗿','s':'𝘀','t':'𝘁','u':'𝘂','v':'𝘃','w':'𝘄','x':'𝘅','y':'𝘆','z':'𝘇','0':'𝟬','1':'𝟭','2':'𝟮','3':'𝟯','4':'𝟰','5':'𝟱','6':'𝟲','7':'𝟳','8':'𝟴','9':'𝟵'};

const mathematicalSansSerifBoldToCharLookupTable = {'𝗔':'A','𝗕':'B','𝗖':'C','𝗗':'D','𝗘':'E','𝗙':'F','𝗚':'G','𝗛':'H','𝗜':'I','𝗝':'J','𝗞':'K','𝗟':'L','𝗠':'M','𝗡':'N','𝗢':'O','𝗣':'P','𝗤':'Q','𝗥':'R','𝗦':'S','𝗧':'T','𝗨':'U','𝗩':'V','𝗪':'W','𝗫':'X','𝗬':'Y','𝗭':'Z','𝗮':'a','𝗯':'b','𝗰':'c','𝗱':'d','𝗲':'e','𝗳':'f','𝗴':'g','𝗵':'h','𝗶':'i','𝗷':'j','𝗸':'k','𝗹':'l','𝗺':'m','𝗻':'n','𝗼':'o','𝗽':'p','𝗾':'q','𝗿':'r','𝘀':'s','𝘁':'t','𝘂':'u','𝘃':'v','𝘄':'w','𝘅':'x','𝘆':'y','𝘇':'z','𝟬':'0','𝟭':'1','𝟮':'2','𝟯':'3','𝟰':'4','𝟱':'5','𝟲':'6','𝟳':'7','𝟴':'8','𝟵':'9'};

const charToMathematicalSansSerifItalicLookupTable = {'A':'𝘈','B':'𝘉','C':'𝘊','D':'𝘋','E':'𝘌','F':'𝘍','G':'𝘎','H':'𝘏','I':'𝘐','J':'𝘑','K':'𝘒','L':'𝘓','M':'𝘔','N':'𝘕','O':'𝘖','P':'𝘗','Q':'𝘘','R':'𝘙','S':'𝘚','T':'𝘛','U':'𝘜','V':'𝘝','W':'𝘞','X':'𝘟','Y':'𝘠','Z':'𝘡','a':'𝘢','b':'𝘣','c':'𝘤','d':'𝘥','e':'𝘦','f':'𝘧','g':'𝘨','h':'𝘩','i':'𝘪','j':'𝘫','k':'𝘬','l':'𝘭','m':'𝘮','n':'𝘯','o':'𝘰','p':'𝘱','q':'𝘲','r':'𝘳','s':'𝘴','t':'𝘵','u':'𝘶','v':'𝘷','w':'𝘸','x':'𝘹','y':'𝘺','z':'𝘻'};

const mathematicalSansSerifItalicToCharLookupTable = {'𝘈':'A','𝘉':'B','𝘊':'C','𝘋':'D','𝘌':'E','𝘍':'F','𝘎':'G','𝘏':'H','𝘐':'I','𝘑':'J','𝘒':'K','𝘓':'L','𝘔':'M','𝘕':'N','𝘖':'O','𝘗':'P','𝘘':'Q','𝘙':'R','𝘚':'S','𝘛':'T','𝘜':'U','𝘝':'V','𝘞':'W','𝘟':'X','𝘠':'Y','𝘡':'Z','𝘢':'a','𝘣':'b','𝘤':'c','𝘥':'d','𝘦':'e','𝘧':'f','𝘨':'g','𝘩':'h','𝘪':'i','𝘫':'j','𝘬':'k','𝘭':'l','𝘮':'m','𝘯':'n','𝘰':'o','𝘱':'p','𝘲':'q','𝘳':'r','𝘴':'s','𝘵':'t','𝘶':'u','𝘷':'v','𝘸':'w','𝘹':'x','𝘺':'y','𝘻':'z'};

const charToMathematicalSansSerifBoldItalicLookupTable = {'A':'𝘼','B':'𝘽','C':'𝘾','D':'𝘿','E':'𝙀','F':'𝙁','G':'𝙂','H':'𝙃','I':'𝙄','J':'𝙅','K':'𝙆','L':'𝙇','M':'𝙈','N':'𝙉','O':'𝙊','P':'𝙋','Q':'𝙌','R':'𝙍','S':'𝙎','T':'𝙏','U':'𝙐','V':'𝙑','W':'𝙒','X':'𝙓','Y':'𝙔','Z':'𝙕','a':'𝙖','b':'𝙗','c':'𝙘','d':'𝙙','e':'𝙚','f':'𝙛','g':'𝙜','h':'𝙝','i':'𝙞','j':'𝙟','k':'𝙠','l':'𝙡','m':'𝙢','n':'𝙣','o':'𝙤','p':'𝙥','q':'𝙦','r':'𝙧','s':'𝙨','t':'𝙩','u':'𝙪','v':'𝙫','w':'𝙬','x':'𝙭','y':'𝙮','z':'𝙯'};

const mathematicalSansSerifBoldItalicToCharLookupTable = {'𝘼':'A','𝘽':'B','𝘾':'C','𝘿':'D','𝙀':'E','𝙁':'F','𝙂':'G','𝙃':'H','𝙄':'I','𝙅':'J','𝙆':'K','𝙇':'L','𝙈':'M','𝙉':'N','𝙊':'O','𝙋':'P','𝙌':'Q','𝙍':'R','𝙎':'S','𝙏':'T','𝙐':'U','𝙑':'V','𝙒':'W','𝙓':'X','𝙔':'Y','𝙕':'Z','𝙖':'a','𝙗':'b','𝙘':'c','𝙙':'d','𝙚':'e','𝙛':'f','𝙜':'g','𝙝':'h','𝙞':'i','𝙟':'j','𝙠':'k','𝙡':'l','𝙢':'m','𝙣':'n','𝙤':'o','𝙥':'p','𝙦':'q','𝙧':'r','𝙨':'s','𝙩':'t','𝙪':'u','𝙫':'v','𝙬':'w','𝙭':'x','𝙮':'y','𝙯':'z'};

const charToMathematicalMonospaceLookupTable = {'A':'𝙰','B':'𝙱','C':'𝙲','D':'𝙳','E':'𝙴','F':'𝙵','G':'𝙶','H':'𝙷','I':'𝙸','J':'𝙹','K':'𝙺','L':'𝙻','M':'𝙼','N':'𝙽','O':'𝙾','P':'𝙿','Q':'𝚀','R':'𝚁','S':'𝚂','T':'𝚃','U':'𝚄','V':'𝚅','W':'𝚆','X':'𝚇','Y':'𝚈','Z':'𝚉','a':'𝚊','b':'𝚋','c':'𝚌','d':'𝚍','e':'𝚎','f':'𝚏','g':'𝚐','h':'𝚑','i':'𝚒','j':'𝚓','k':'𝚔','l':'𝚕','m':'𝚖','n':'𝚗','o':'𝚘','p':'𝚙','q':'𝚚','r':'𝚛','s':'𝚜','t':'𝚝','u':'𝚞','v':'𝚟','w':'𝚠','x':'𝚡','y':'𝚢','z':'𝚣','0':'𝟶','1':'𝟷','2':'𝟸','3':'𝟹','4':'𝟺','5':'𝟻','6':'𝟼','7':'𝟽','8':'𝟾','9':'𝟿'};

const mathematicalMonospaceToCharLookupTable = {'𝙰':'A','𝙱':'B','𝙲':'C','𝙳':'D','𝙴':'E','𝙵':'F','𝙶':'G','𝙷':'H','𝙸':'I','𝙹':'J','𝙺':'K','𝙻':'L','𝙼':'M','𝙽':'N','𝙾':'O','𝙿':'P','𝚀':'Q','𝚁':'R','𝚂':'S','𝚃':'T','𝚄':'U','𝚅':'V','𝚆':'W','𝚇':'X','𝚈':'Y','𝚉':'Z','𝚊':'a','𝚋':'b','𝚌':'c','𝚍':'d','𝚎':'e','𝚏':'f','𝚐':'g','𝚑':'h','𝚒':'i','𝚓':'j','𝚔':'k','𝚕':'l','𝚖':'m','𝚗':'n','𝚘':'o','𝚙':'p','𝚚':'q','𝚛':'r','𝚜':'s','𝚝':'t','𝚞':'u','𝚟':'v','𝚠':'w','𝚡':'x','𝚢':'y','𝚣':'z','𝟶':'0','𝟷':'1','𝟸':'2','𝟹':'3','𝟺':'4','𝟻':'5','𝟼':'6','𝟽':'7','𝟾':'8','𝟿':'9'};

const charToFandaLookupTable = {'a':'e','b':'n','c':'b','d':'m','e':'o','f':'r','g':'x','h':'v','i':'u','j':'w','k':'l','l':'y','m':'g','n':'s','o':'a','p':'k','q':'p','r':'d','s':'z','t':'q','u':'i','v':'f','w':'t','x':'j','y':'c','z':'h'};

const fandaToCharLookupTable = {'e':'a','n':'b','b':'c','m':'d','o':'e','r':'f','x':'g','v':'h','u':'i','w':'j','l':'k','y':'l','g':'m','s':'n','a':'o','k':'p','p':'q','d':'r','z':'s','q':'t','i':'u','f':'v','t':'w','j':'x','c':'y','h':'z'};

const charToDnaLookupTable = {'0':'ATA','1':'TCT','2':'GCG','3':'GTG','4':'AGA','5':'CGC','6':'ATT','7':'ACC','8':'AGG','9':'CAA','A':'ACT','B':'CAT','C':'TCA','D':'TAC','E':'CTA','F':'GCT','G':'GTC','H':'CGT','I':'CTG','J':'TGC','K':'TCG','L':'ATC','M':'ACA','N':'CTC','O':'TGT','P':'GAG','Q':'TAT','R':'CAC','S':'TGA','T':'TAG','U':'GAT','V':'GTA','W':'ATG','X':'AGT','Y':'GAC','Z':'GCA','':'AGC','.':'ACG'};

const dnaToCharLookupTable = {'ATA':'0','TCT':'1','GCG':'2','GTG':'3','AGA':'4','CGC':'5','ATT':'6','ACC':'7','AGG':'8','CAA':'9','ACT':'A','CAT':'B','TCA':'C','TAC':'D','CTA':'E','GCT':'F','GTC':'G','CGT':'H','CTG':'I','TGC':'J','TCG':'K','ATC':'L','ACA':'M','CTC':'N','TGT':'O','GAG':'P','TAT':'Q','CAC':'R','TGA':'S','TAG':'T','GAT':'U','GTA':'V','ATG':'W','AGT':'X','GAC':'Y','GCA':'Z','AGC':'','ACG':'.'};

const sampleCharacterMapping = `A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nU\nV\nW\nX\nY\nZ\na\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np\nq\nr\ns\nt\nu\nv\nw\nx\ny\nz\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n𝐀\n𝐁\n𝐂\n𝐃\n𝐄\n𝐅\n𝐆\n𝐇\n𝐈\n𝐉\n𝐊\n𝐋\n𝐌\n𝐍\n𝐎\n𝐏\n𝐐\n𝐑\n𝐒\n𝐓\n𝐔\n𝐕\n𝐖\n𝐗\n𝐘\n𝐙\n𝐚\n𝐛\n𝐜\n𝐝\n𝐞\n𝐟\n𝐠\n𝐡\n𝐢\n𝐣\n𝐤\n𝐥\n𝐦\n𝐧\n𝐨\n𝐩\n𝐪\n𝐫\n𝐬\n𝐭\n𝐮\n𝐯\n𝐰\n𝐱\n𝐲\n𝐳\n𝟎\n𝟏\n𝟐\n𝟑\n𝟒\n𝟓\n𝟔\n𝟕\n𝟖\n𝟗`;

const sampleMergeBottomIntoTop = `1)
2)
3)
4)
Item number one
Item number two
Item number three
Item number four`;

const sampleText = `0123456789
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
a	b	c	d	e	f	g
a,b,c,d,e,f,g

abc def ghi jkl mno pqrs tuv wxyz ABC DEF GHI JKL MNO PQRS TUV WXYZ ! "§ $%& /() =? * '<>

|; ²³~ @ ©«» ¤¼× {} abc def ghi jkl mno pqrs tuv wxyz ABC DEF GHI JKL MNO PQRS TUV WXYZ ! "§ $%& /() =? * '

|; ²³~ @´ ©«» ¤¼× {} abc def ghi jkl mno pqrs tuv wxyz ABC DEF GHI JKL MNO PQRS TUV WXYZ ! "§ $%& /() =? * '<

|; ²³~ @´ ©«» ¤¼× {} abc def ghi jkl mno pqrs tuv wxyz ABC DEF GHI JKL MNO PQRS TUV WXYZ ! "§ $%& /() =? * '<> |; ²³~ @´ ©«» ¤¼× {} abc def ghi jkl mno pqrs tuv wxyz ABC DEF GHI JKL MNO PQRS TUV WXYZ !

"§ $%& /() =? * '<> |; ²³~ @´ ©«» ¤¼× {} abc def ghi jkl mno pqrs tuv wxyz ABC DEF GHI JKL MNO PQRS TUV WXYZ ! "§ $%& /() =? * '<> |; ²³~ @´ ©«» ¤¼× {} abc def ghi jkl mno pqrs tuv wxyz ABC DEF GHI JKL MNO PQRS TUV WXYZ ! "§ $%& /() =? * '<> |; ²³~ @´ ©«» ¤¼× {}abc def ghi jkl mno pqrs tuv wxyz ABC DEF GHI`;

const sampleEmmetHtml = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  
</body>
</html>`;

const sampleDiamondOfBullets = `        ◦        
       ◦◦◦       
      ◦◦◦◦◦      
     ◦◦◦◦◦◦◦     
    ◦◦◦◦◦◦◦◦◦    
   ◦◦◦◦◦◦◦◦◦◦◦   
  ◦◦◦◦◦◦◦◦◦◦◦◦◦  
 ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ 
◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦
 ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ 
  ◦◦◦◦◦◦◦◦◦◦◦◦◦  
   ◦◦◦◦◦◦◦◦◦◦◦   
    ◦◦◦◦◦◦◦◦◦    
     ◦◦◦◦◦◦◦     
      ◦◦◦◦◦      
       ◦◦◦       
        ◦        `;

const sampleHtml = `<h1>Lorem ipsum dolor sit amet consectetuer adipiscing 
elit</h1>

<p>Lorem ipsum dolor sit amet, consectetuer adipiscing 
elit. Aenean commodo ligula eget dolor. Aenean massa 
<strong>strong</strong>. Cum sociis natoque penatibus 
et magnis dis parturient montes, nascetur ridiculus 
mus. Donec quam felis, ultricies nec, pellentesque 
eu, pretium quis, sem. Nulla consequat massa quis 
enim. Donec pede justo, fringilla vel, aliquet nec, 
vulputate eget, arcu. In enim justo, rhoncus ut, 
imperdiet a, venenatis vitae, justo. Nullam dictum 
felis eu pede <a class="external ext" href="#">link</a> 
mollis pretium. Integer tincidunt. Cras dapibus. 
Vivamus elementum semper nisi. Aenean vulputate 
eleifend tellus. Aenean leo ligula, porttitor eu, 
consequat vitae, eleifend ac, enim. Aliquam lorem ante, 
dapibus in, viverra quis, feugiat a, tellus. Phasellus 
viverra nulla ut metus varius laoreet. Quisque rutrum. 
Aenean imperdiet. Etiam ultricies nisi vel augue. 
Curabitur ullamcorper ultricies nisi.</p>

<h1>Lorem ipsum dolor sit amet consectetuer adipiscing 
elit</h1>

<h2>Aenean commodo ligula eget dolor aenean massa</h2>

<p>Lorem ipsum dolor sit amet, consectetuer adipiscing 
elit. Aenean commodo ligula eget dolor. Aenean massa. 
Cum sociis natoque penatibus et magnis dis parturient 
montes, nascetur ridiculus mus. Donec quam felis, 
ultricies nec, pellentesque eu, pretium quis, sem.</p>

<h2>Aenean commodo ligula eget dolor aenean massa</h2>

<p>Lorem ipsum dolor sit amet, consectetuer adipiscing 
elit. Aenean commodo ligula eget dolor. Aenean massa. 
Cum sociis natoque penatibus et magnis dis parturient 
montes, nascetur ridiculus mus. Donec quam felis, 
ultricies nec, pellentesque eu, pretium quis, sem.</p>

<ul>
  <li>Lorem ipsum dolor sit amet consectetuer.</li>
  <li>Aenean commodo ligula eget dolor.</li>
  <li>Aenean massa cum sociis natoque penatibus.</li>
</ul>

<p>Lorem ipsum dolor sit amet, consectetuer adipiscing 
elit. Aenean commodo ligula eget dolor. Aenean massa. 
Cum sociis natoque penatibus et magnis dis parturient 
montes, nascetur ridiculus mus. Donec quam felis, 
ultricies nec, pellentesque eu, pretium quis, sem.</p>

<form action="#" method="post">
  <fieldset>
    <label for="name">Name:</label>
    <input type="text" id="name" placeholder="Enter your 
full name" />

    <label for="email">Email:</label>
    <input type="email" id="email" placeholder="Enter 
your email address" />

    <label for="message">Message:</label>
    <textarea id="message" placeholder="What's on your 
mind?"></textarea>

    <input type="submit" value="Send message" />

  </fieldset>
</form>

<p>Lorem ipsum dolor sit amet, consectetuer adipiscing 
elit. Aenean commodo ligula eget dolor. Aenean massa. 
Cum sociis natoque penatibus et magnis dis parturient 
montes, nascetur ridiculus mus. Donec quam felis, 
ultricies nec, pellentesque eu, pretium quis, sem.</p>

<table class="data">
  <tr>
    <th>Entry Header 1</th>
    <th>Entry Header 2</th>
    <th>Entry Header 3</th>
    <th>Entry Header 4</th>
  </tr>
  <tr>
    <td>Entry First Line 1</td>
    <td>Entry First Line 2</td>
    <td>Entry First Line 3</td>
    <td>Entry First Line 4</td>
  </tr>
  <tr>
    <td>Entry Line 1</td>
    <td>Entry Line 2</td>
    <td>Entry Line 3</td>
    <td>Entry Line 4</td>
  </tr>
  <tr>
    <td>Entry Last Line 1</td>
    <td>Entry Last Line 2</td>
    <td>Entry Last Line 3</td>
    <td>Entry Last Line 4</td>
  </tr>
</table>

<p>Lorem ipsum dolor sit amet, consectetuer adipiscing 
elit. Aenean commodo ligula eget dolor. Aenean massa. 
Cum sociis natoque penatibus et magnis dis parturient 
montes, nascetur ridiculus mus. Donec quam felis, 
ultricies nec, pellentesque eu, pretium quis, sem.</p>`;

const sampleHtml5Boilerplate = `%3C!doctype%20html%3E
%3Chtml%20class%3D%22no-js%22%20lang%3D%22%22%3E

%3Chead%3E
%20%20%3Cmeta%20charset%3D%22utf-8%22%3E
%20%20%3Cmeta%20http-equiv%3D%22x-ua-compatible%22%20content%3D%22ie%3Dedge%22%3E
%20%20%3Ctitle%3E%3C%2Ftitle%3E
%20%20%3Cmeta%20name%3D%22description%22%20content%3D%22%22%3E
%20%20%3Cmeta%20name%3D%22viewport%22%20content%3D%22width%3Ddevice-width%2C%20initial-scale%3D1%2C%20shrink-to-fit%3Dno%22%3E

%20%20%3Clink%20rel%3D%22manifest%22%20href%3D%22site.webmanifest%22%3E
%20%20%3Clink%20rel%3D%22apple-touch-icon%22%20href%3D%22icon.png%22%3E
%20%20%3C!--%20Place%20favicon.ico%20in%20the%20root%20directory%20--%3E

%20%20%3Clink%20rel%3D%22stylesheet%22%20href%3D%22css%2Fnormalize.css%22%3E
%20%20%3Clink%20rel%3D%22stylesheet%22%20href%3D%22css%2Fmain.css%22%3E

%20%20%3Cstyle%3E
%20%20%20%20body%20%7B
%20%20%20%20%20%20background-color%3A%20%23fff%3B
%20%20%20%20%7D
%20%20%3C%2Fstyle%3E
%3C%2Fhead%3E

%3Cbody%3E
%20%20%3C!--%5Bif%20lte%20IE%209%5D%3E
%20%20%20%20%3Cp%20class%3D%22browserupgrade%22%3EYou%20are%20using%20an%20%3Cstrong%3Eoutdated%3C%2Fstrong%3E%20browser.%20Please%20%3Ca%20href%3D%22https%3A%2F%2Fbrowsehappy.com%2F%22%3Eupgrade%20your%20browser%3C%2Fa%3E%20to%20improve%20your%20experience%20and%20security.%3C%2Fp%3E
%20%20%3C!%5Bendif%5D--%3E

%20%20%3C!--%20Add%20your%20site%20or%20application%20content%20here%20--%3E
%20%20%3Cp%3EHello%20world!%20This%20is%20HTML5%20Boilerplate.%3C%2Fp%3E
%20%20%3Cscript%20src%3D%22js%2Fvendor%2Fmodernizr-3.6.0.min.js%22%3E%3C%2Fscript%3E
%20%20%3Cscript%20src%3D%22https%3A%2F%2Fcode.jquery.com%2Fjquery-3.3.1.min.js%22%20integrity%3D%22sha256-FgpCb%2FKJQlLNfOu91ta32o%2FNMZxltwRo8QtmkMRdAu8%3D%22%20crossorigin%3D%22anonymous%22%3E%3C%2Fscript%3E
%20%20%3Cscript%3Ewindow.jQuery%20%7C%7C%20document.write('%3Cscript%20src%3D%22js%2Fvendor%2Fjquery-3.3.1.min.js%22%3E%3C%5C%2Fscript%3E')%3C%2Fscript%3E
%20%20%3Cscript%20src%3D%22js%2Fplugins.js%22%3E%3C%2Fscript%3E
%20%20%3Cscript%20src%3D%22js%2Fmain.js%22%3E%3C%2Fscript%3E

%20%20%3C!--%20Google%20Analytics%3A%20change%20UA-XXXXX-Y%20to%20be%20your%20site's%20ID.%20--%3E
%20%20%3Cscript%3E
%20%20%20%20window.ga%20%3D%20function%20()%20%7B%20ga.q.push(arguments)%20%7D%3B%20ga.q%20%3D%20%5B%5D%3B%20ga.l%20%3D%20%2Bnew%20Date%3B
%20%20%20%20ga('create'%2C%20'UA-XXXXX-Y'%2C%20'auto')%3B%20ga('send'%2C%20'pageview')
%20%20%3C%2Fscript%3E
%20%20%3Cscript%20src%3D%22https%3A%2F%2Fwww.google-analytics.com%2Fanalytics.js%22%20async%20defer%3E%3C%2Fscript%3E
%3C%2Fbody%3E

%3C%2Fhtml%3E`;

const sampleHtmlTable = `<table class="js-html-table table table-striped">
  <thead class="thead-dark">
    <tr>
      <th>id</th>
      <th>first_name</th>
      <th>last_name</th>
      <th>email</th>
      <th>gender</th>
      <th>ip_address</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>Vanna</td>
      <td>Dollman</td>
      <td>vdollman0@slate.com</td>
      <td>Female</td>
      <td>2.17.2.105</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Claudine</td>
      <td>Cay</td>
      <td>ccay1@shop-pro.jp</td>
      <td>Female</td>
      <td>178.247.67.77</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Rock</td>
      <td>Hartshorne</td>
      <td>rhartshorne2@etsy.com</td>
      <td>Male</td>
      <td>215.134.12.25</td>
    </tr>
    <tr>
      <td>4</td>
      <td>Udall</td>
      <td>Roux</td>
      <td>uroux3@china.com.cn</td>
      <td>Male</td>
      <td>175.224.102.238</td>
    </tr>
    <tr>
      <td>5</td>
      <td>Wainwright</td>
      <td>Havesides</td>
      <td>whavesides4@chicagotribune.com</td>
      <td>Male</td>
      <td>34.209.202.79</td>
    </tr>
    <tr>
      <td>6</td>
      <td>Harli</td>
      <td>Gerdes</td>
      <td>hgerdes5@utexas.edu</td>
      <td>Female</td>
      <td>22.51.251.103</td>
    </tr>
    <tr>
      <td>7</td>
      <td>Kathie</td>
      <td>Kubach</td>
      <td>kkubach6@last.fm</td>
      <td>Female</td>
      <td>249.168.126.71</td>
    </tr>
    <tr>
      <td>8</td>
      <td>Selinda</td>
      <td>Edgeon</td>
      <td>sedgeon7@senate.gov</td>
      <td>Female</td>
      <td>32.74.77.87</td>
    </tr>
    <tr>
      <td>9</td>
      <td>Mignon</td>
      <td>Tokell</td>
      <td>mtokell8@state.gov</td>
      <td>Female</td>
      <td>45.50.224.157</td>
    </tr>
    <tr>
      <td>10</td>
      <td>Benjamin</td>
      <td>Tackley</td>
      <td>btackley9@merriam-webster.com</td>
      <td>Male</td>
      <td>204.6.156.203</td>
    </tr>
    <tr>
      <td>11</td>
      <td>Norri</td>
      <td>Eytel</td>
      <td>neytela@quantcast.com</td>
      <td>Female</td>
      <td>169.231.202.128</td>
    </tr>
    <tr>
      <td>12</td>
      <td>Birgit</td>
      <td>Akister</td>
      <td>bakisterb@spiegel.de</td>
      <td>Female</td>
      <td>167.113.138.96</td>
    </tr>
    <tr>
      <td>13</td>
      <td>Izabel</td>
      <td>Mowen</td>
      <td>imowenc@miitbeian.gov.cn</td>
      <td>Female</td>
      <td>47.170.120.34</td>
    </tr>
    <tr>
      <td>14</td>
      <td>Ingmar</td>
      <td>Ziemke</td>
      <td>iziemked@theglobeandmail.com</td>
      <td>Male</td>
      <td>69.125.254.167</td>
    </tr>
    <tr>
      <td>15</td>
      <td>Chicky</td>
      <td>Locke</td>
      <td>clockee@usnews.com</td>
      <td>Male</td>
      <td>147.2.214.70</td>
    </tr>
    <tr>
      <td>16</td>
      <td>Clarice</td>
      <td>Brocket</td>
      <td>cbrocketf@nps.gov</td>
      <td>Female</td>
      <td>73.87.11.132</td>
    </tr>
    <tr>
      <td>17</td>
      <td>Hatti</td>
      <td>Simons</td>
      <td>hsimonsg@sphinn.com</td>
      <td>Female</td>
      <td>194.106.153.61</td>
    </tr>
    <tr>
      <td>18</td>
      <td>Stephanus</td>
      <td>Haquin</td>
      <td>shaquinh@zdnet.com</td>
      <td>Male</td>
      <td>61.194.139.255</td>
    </tr>
    <tr>
      <td>19</td>
      <td>Ashli</td>
      <td>Westraw</td>
      <td>awestrawi@hao123.com</td>
      <td>Female</td>
      <td>14.93.76.64</td>
    </tr>
    <tr>
      <td>20</td>
      <td>Edouard</td>
      <td>Naish</td>
      <td>enaishj@businessinsider.com</td>
      <td>Male</td>
      <td>126.234.124.15</td>
    </tr>
  </tbody>
</table>`;

const sampleAlice = `Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, \`and what is the use of a book,’ thought Alice \`without pictures or conversation?’

So she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.

There was nothing so VERY remarkable in that; nor did Alice think it so VERY much out of the way to hear the Rabbit say to itself, \`Oh dear! Oh dear! I shall be late!’ (when she thought it over afterwards, it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT- POCKET, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fortunately was just in time to see it pop down a large rabbit-hole under the hedge.

In another moment down went Alice after it, never once considering how in the world she was to get out again.

The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down a very deep well.

Either the well was very deep, or she fell very slowly, for she had plenty of time as she went down to look about her and to wonder what was going to happen next. First, she tried to look down and make out what she was coming to, but it was too dark to see anything; then she looked at the sides of the well, and noticed that they were filled with cupboards and book-shelves; here and there she saw maps and pictures hung upon pegs. She took down a jar from one of the shelves as she passed; it was labelled \`ORANGE MARMALADE’, but to her great disappointment it was empty: she did not like to drop the jar for fear of killing somebody, so managed to put it into one of the cupboards as she fell past it.

\`Well!’ thought Alice to herself, \`after such a fall as this, I shall think nothing of tumbling down stairs! How brave they’ll all think me at home! Why, I wouldn’t say anything about it, even if I fell off the top of the house!’ (Which was very likely true.)

Down, down, down. Would the fall NEVER come to an end! \`I wonder how many miles I’ve fallen by this time?’ she said aloud. \`I must be getting somewhere near the centre of the earth. Let me see: that would be four thousand miles down, I think–‘ (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a VERY good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) \`–yes, that’s about the right distance–but then I wonder what Latitude or Longitude I’ve got to?’ (Alice had no idea what Latitude was, or Longitude either, but thought they were nice grand words to say.)
`;

const samplePangrams = `We promptly judged antique ivory buckles for the next prize.
How razorback jumping frogs can level six piqued gymnasts.
Sixty zippers were quickly picked from the woven jute bag.
Crazy Fredrick bought many very exquisite opal jewels.
Jump by vow of quick, lazy strength in Oxford.
The quick brown fox jumps over a lazy dog.
Pack my box with five dozen liquor jugs.
How quickly daft jumping zebras vex.
Sphinx of black quartz: judge my vow.
Quick zephyrs blow, vexing daft Jim.
Waltz, nymph, for quick jigs vex bud.`;

const phoneticAlphabet = `Alpha Bravo Charlie Delta Echo Foxtrot Golf Hotel India Juliet Kilo Lima Mike November Oscar Papa Quebec Romeo Sierra Tango Uniform Victor Whiskey X-Ray Yankee Zulu`;

const loremIpsum = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sit amet mauris vitae eros mattis tempus. Praesent vestibulum euismod nulla at sollicitudin. Aliquam dolor ipsum, finibus eget mauris at, varius semper sem. Morbi molestie pretium lectus at gravida. Phasellus id imperdiet mi, eget condimentum libero. Etiam auctor sollicitudin imperdiet. Curabitur efficitur accumsan quam, sit amet tristique sem dignissim at. Vivamus maximus velit sed erat porttitor eleifend. Nam maximus consequat ornare.

Duis rhoncus at turpis sit amet imperdiet. Suspendisse sapien dolor, condimentum id finibus eu, euismod in arcu. Aenean ut tristique neque. Vivamus vel sem dui. Pellentesque vitae elementum libero, sit amet condimentum dolor. Suspendisse ut venenatis massa. Quisque sit amet urna consectetur justo gravida mattis. Nunc molestie nisl non mauris facilisis imperdiet. Integer ornare nibh nec ultrices tincidunt. Donec sit amet felis auctor, facilisis augue in, viverra dolor. Praesent sit amet dui efficitur, laoreet velit ut, pharetra quam. Fusce lacus arcu, interdum et pulvinar ac, vestibulum a mi. Maecenas convallis accumsan nunc. Mauris volutpat pretium lacus eget tristique. Morbi tempus viverra tincidunt.

Phasellus finibus lorem vulputate ligula fringilla faucibus. Morbi scelerisque nibh non lacus venenatis malesuada. Nullam aliquet odio ut ante lobortis, et porttitor orci rhoncus. Proin mi mauris, sagittis quis turpis eu, placerat pulvinar massa. Suspendisse turpis erat, vulputate vel urna in, blandit suscipit est. Morbi ultricies ultrices ante a dictum. Maecenas bibendum risus et ligula condimentum, at placerat elit tincidunt. Aenean in viverra turpis, eget tincidunt sem. Maecenas pharetra fermentum tellus quis semper.

Morbi mauris arcu, tristique ut ligula ut, feugiat convallis lorem. Nullam iaculis efficitur ligula quis pharetra. Vestibulum bibendum, arcu ac sagittis suscipit, nisi urna gravida turpis, blandit commodo nibh quam vel erat. Aenean at consequat orci. Praesent nunc elit, facilisis ut vestibulum nec, posuere nec nisi. Sed aliquam purus at massa sollicitudin, id vulputate elit luctus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec lacus augue, faucibus vitae laoreet vitae, efficitur vel dui. Duis fringilla lorem ut magna tincidunt, in dictum augue maximus. Proin sit amet arcu ornare, tristique leo ut, vehicula massa. Mauris ut ligula sit amet ante suscipit sagittis. Nullam ornare faucibus nunc quis sodales. Praesent elementum aliquet pulvinar. Nunc condimentum, turpis nec gravida dictum, odio turpis convallis erat, eget bibendum justo metus molestie est. Aliquam nec quam lacinia, volutpat ante id, eleifend ipsum.

Sed quis tempus sem. Suspendisse potenti. Nullam in gravida quam. Pellentesque sit amet arcu odio. Integer condimentum quis augue eget cursus. Morbi efficitur rutrum est non laoreet. Pellentesque faucibus lectus nisl, eu accumsan magna molestie a. In quis sem quis tellus condimentum sagittis. Pellentesque ultrices finibus tristique. Sed sit amet dui mollis, accumsan erat venenatis, consectetur tortor. Donec semper ut leo vitae tristique. Nunc eu mi at orci vulputate mollis non sit amet nibh.`;

const curlyQuotes = `‘Single curly quotes’
“Double curly quotes”`;

const formattedJson = `{
	"markers": [
		{
			"name": "Rixos The Palm Dubai",
			"position": [25.1212, 55.1535]
		},
		{
			"name": "Shangri-La Hotel",
			"location": [25.2084, 55.2719]
		},
		{
			"name": "Grand Hyatt",
			"location": [25.2285, 55.3273]
		}
	]
}`;

const formattedJson2 = '%7B%0A%20%20%22uuid%22%3A%20%22305c9744-b114-4cac-9884-8a02eb170d29%22%2C%0A%20%20%22title%22%3A%20%22Main%20Menu%22%2C%0A%20%20%22children%22%3A%20%5B%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22uuid%22%3A%20%2221cc96d4-d059-4aaa-af10-eb4f449dbb2d%22%2C%0A%20%20%20%20%20%20%22title%22%3A%20%220%22%2C%0A%20%20%20%20%20%20%22children%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22fdb1a733-1732-49cc-8d23-d0e6747e9161%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%2200%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22children%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%227d58f5d3-156a-4748-b98f-4a6565cef527%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22000%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%221310c506-21e8-4dc0-b5ab-c67b72881e6b%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22001%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22d01ce8d4-4019-45a2-a4c4-f5b95f0a23dd%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22002%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%2288f48994-e94c-4d8a-9a1b-8303bb31682f%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%2201%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22children%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22af85377f-1b82-4dd5-93c6-0f548990b2e9%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22010%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22f5c1be14-1ee8-4df8-b089-dfcae2ac1896%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22011%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%226da8072e-4f13-41fe-bd18-7a393fb8cc88%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22012%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%2223a12649-099e-4609-b2c9-d3a679c7542c%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%2202%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22children%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22bd8f82cb-f1cb-4a9c-b74c-fc69e54036ca%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22020%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%221342ca92-6e18-4cd3-b435-3481bbb856e0%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22021%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%2205c8b998-e119-4626-9587-b3e4a013aaab%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22022%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%5D%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22uuid%22%3A%20%227809878b-310f-4f31-90ec-c7d60f0d3476%22%2C%0A%20%20%20%20%20%20%22title%22%3A%20%221%22%2C%0A%20%20%20%20%20%20%22children%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22a9d5469a-6e9c-4638-86b9-6f17b67f7476%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%2210%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22children%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22761c9b4c-2836-4ed5-a1e2-ba2f2c403035%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22100%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22d3a1aa6a-9336-402e-8773-0f4dfbc5eae4%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22101%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22982a4040-d24f-402a-bbff-6261f04b223f%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22102%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22b28fd4b0-e432-4afa-97b5-b48138c2b347%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%2211%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22children%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22bd5db2a7-494f-4c67-bedb-8370c74f454f%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22110%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22e2fecd42-d02a-4ce5-93a5-c0f8468086fa%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22111%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22b9800028-c124-44d6-9f52-78e464f2553f%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22112%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%229c4fd127-0bc0-4f18-b4b7-724372af6d71%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%2212%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22children%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%225deae917-cae6-433f-b7ab-5b5426ad8738%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22120%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22ecb27a7f-3ffa-499d-a27d-6a2639c34f72%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22121%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%220917d3dc-cf34-4ece-b68c-244056a0aa49%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22122%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%5D%0A%20%20%20%20%7D%2C%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%22uuid%22%3A%20%22009d5d48-03be-4869-9e16-4aa9b558f4fe%22%2C%0A%20%20%20%20%20%20%22title%22%3A%20%222%22%2C%0A%20%20%20%20%20%20%22children%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%2204f57c55-a3b4-44a2-af69-be53fce8dc0a%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%2220%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22children%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22301d322c-aa09-4a40-b777-ab6085d8cced%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22200%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%2267f6985f-72bc-40b3-a084-310ed5705ab9%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22201%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%227ddcbe00-f0f4-490e-a247-5810b0cc64cb%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22202%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22fe3a1b54-e6fa-4fae-a076-a3099bf55de3%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%2221%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22children%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%2288796b5c-371a-47e6-bea8-bbff55fdf5ca%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22210%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%2271d37589-af66-4744-85cd-b2bd78703ef3%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22211%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%226f06d4bb-6bea-4198-894d-92de5d482d0d%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22212%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22afb5179c-cbc4-4f41-ac8e-1bb363ee58a7%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%2222%22%2C%0A%20%20%20%20%20%20%20%20%20%20%22children%22%3A%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22f3d10ca5-f6e4-4661-af1e-0daeacceba80%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22220%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%22f88fda70-c206-4989-bf40-bb9ad69aa4f8%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22221%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22uuid%22%3A%20%2252fc4a0c-1b34-47b9-a9a8-c25df2e85731%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22title%22%3A%20%22222%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%5D%0A%20%20%20%20%7D%0A%20%20%5D%0A%7D';

const unformattedJson = `[ { "_id": "5a1445d6c8761a3d490346d8", "index": 0, "uuid": "026e97e1-47bb-43f6-b689-9d0b67611fb6", "isActive": true, "balance": "$3,139.91", "picture": "http://placehold.it/32x32", "age": 34, "eyeColor": "blue", "name": "Claudine Alford", "gender": "female", "company": "XINWARE", "email": "claudinealford@xinware.com", "phone": "+1 (847) 543-3226", "address": "130 Forest Place, Escondida, Kentucky, 2888", "about": "Mollit aute ad magna enim labore eu duis et. Voluptate ea Lorem mollit labore minim. Magna elit exercitation nostrud eiusmod voluptate pariatur sit pariatur labore dolor aliquip.", "registered": "2015-03-14T09:21:19 -00:00", "latitude": 22.150505, "longitude": 120.339377, "tags": [ "est", "laboris", "pariatur", "quis", "ex", "duis", "eu" ], "friends": [ { "id": 0, "name": "Gayle Byers" }, { "id": 1, "name": "Rose Walters" }, { "id": 2, "name": "Laura Combs" } ], "greeting": "Hello, Claudine Alford! You have 5 unread messages.", "favoriteFruit": "apple" }, { "_id": "5a1445d6480c1528a1034790", "index": 1, "uuid": "2366425a-08c6-4435-a8a8-9c6306195136", "isActive": false, "balance": "$2,926.49", "picture": "http://placehold.it/32x32", "age": 21, "eyeColor": "green", "name": "Mcmahon Day", "gender": "male", "company": "EARBANG", "email": "mcmahonday@earbang.com", "phone": "+1 (837) 403-3989", "address": "165 Jodie Court, Leola, Louisiana, 4119", "about": "Laborum consectetur id ut pariatur in excepteur et qui commodo enim minim. Qui irure excepteur sit occaecat magna. Ea pariatur laboris labore velit exercitation ut quis aliqua exercitation magna mollit. Ut magna voluptate consectetur aliqua dolor eiusmod fugiat irure magna. Ipsum sint eu ea officia eiusmod cillum proident amet excepteur proident anim. Ex ipsum elit veniam irure ipsum culpa mollit.", "registered": "2016-09-29T04:08:39 -01:00", "latitude": -44.416236, "longitude": -109.22046, "tags": [ "duis", "in", "exercitation", "do", "duis", "do", "sunt" ], "friends": [ { "id": 0, "name": "Delia Richards" }, { "id": 1, "name": "Stout Head" }, { "id": 2, "name": "Kris Dunn" } ], "greeting": "Hello, Mcmahon Day! You have 2 unread messages.", "favoriteFruit": "banana" }, { "_id": "5a1445d6726e19c2a1cfdb22", "index": 2, "uuid": "974e1047-4787-4459-8408-b3b206873810", "isActive": true, "balance": "$2,068.30", "picture": "http://placehold.it/32x32", "age": 24, "eyeColor": "brown", "name": "Roberts Cross", "gender": "male", "company": "NETPLODE", "email": "robertscross@netplode.com", "phone": "+1 (991) 473-3635", "address": "519 Orient Avenue, Dana, Oklahoma, 6048", "about": "Ex id esse mollit qui qui irure sint eiusmod dolore ad duis. Officia consectetur fugiat laborum incididunt aute exercitation. Nostrud eiusmod et enim ipsum consequat. Fugiat culpa aute magna culpa esse anim aliqua et elit Lorem eu exercitation eu. Et incididunt tempor fugiat ad ut sunt. Qui nostrud minim laborum fugiat ad anim. Excepteur amet nostrud irure do.", "registered": "2015-07-14T03:11:59 -01:00", "latitude": 45.144461, "longitude": 179.257259, "tags": [ "consectetur", "aute", "enim", "aliqua", "consequat", "deserunt", "adipisicing" ], "friends": [ { "id": 0, "name": "Simon Greene" }, { "id": 1, "name": "Ginger Gibson" }, { "id": 2, "name": "Lindsay Bell" } ], "greeting": "Hello, Roberts Cross! You have 6 unread messages.", "favoriteFruit": "strawberry" }, { "_id": "5a1445d6a49b2deca2be6400", "index": 3, "uuid": "bf5b1607-6f79-4598-a765-1229a19fd74a", "isActive": true, "balance": "$2,843.42", "picture": "http://placehold.it/32x32", "age": 35, "eyeColor": "blue", "name": "Benton Mcbride", "gender": "male", "company": "VELOS", "email": "bentonmcbride@velos.com", "phone": "+1 (819) 420-3682", "address": "153 King Street, Bainbridge, New Jersey, 5241", "about": "Minim elit anim enim non qui dolore commodo velit voluptate adipisicing proident. Esse voluptate enim officia eu amet anim velit ex deserunt ad occaecat et aliqua anim. Incididunt deserunt nisi occaecat magna sit sint officia minim. Officia est adipisicing in proident do veniam do commodo laboris fugiat. Occaecat mollit commodo magna consequat eu anim laborum pariatur. Excepteur do dolore excepteur mollit quis qui ullamco commodo sint consequat commodo tempor. Sit fugiat tempor excepteur sint sunt ex fugiat aliquip exercitation quis elit consectetur.", "registered": "2016-06-18T02:17:35 -01:00", "latitude": -32.294358, "longitude": 100.985165, "tags": [ "qui", "irure", "ipsum", "non", "Lorem", "aute", "nostrud" ], "friends": [ { "id": 0, "name": "Moses Pearson" }, { "id": 1, "name": "Vang Orr" }, { "id": 2, "name": "Tamera Skinner" } ], "greeting": "Hello, Benton Mcbride! You have 1 unread messages.", "favoriteFruit": "strawberry" }, { "_id": "5a1445d613b66022b39ddc25", "index": 4, "uuid": "22f5e4ac-fd36-47b3-becd-968d66cc35f2", "isActive": false, "balance": "$2,936.29", "picture": "http://placehold.it/32x32", "age": 32, "eyeColor": "brown", "name": "Madeline Solomon", "gender": "female", "company": "FUTURITY", "email": "madelinesolomon@futurity.com", "phone": "+1 (899) 408-2748", "address": "857 Harrison Place, Glenville, Hawaii, 2241", "about": "Sit veniam mollit dolor cupidatat est pariatur pariatur dolore eiusmod eiusmod magna. Eu sint commodo adipisicing et ullamco deserunt do ea dolore voluptate. Magna aute cillum quis anim consectetur. Consequat ad velit cillum sit sint culpa amet aute proident sit officia velit anim. Occaecat dolor incididunt adipisicing minim veniam aliqua ut laboris duis esse. Mollit id proident sunt ipsum amet eu anim.", "registered": "2014-10-03T01:23:39 -01:00", "latitude": 72.263167, "longitude": 174.397736, "tags": [ "occaecat", "incididunt", "cillum", "non", "qui", "elit", "id" ], "friends": [ { "id": 0, "name": "Rasmussen Tran" }, { "id": 1, "name": "Clements Chase" }, { "id": 2, "name": "Tasha Fuller" } ], "greeting": "Hello, Madeline Solomon! You have 9 unread messages.", "favoriteFruit": "apple" }]`;

const simpleYaml1 = `# Comment can go here
invoice: 34843
date   : 2001-01-23
bill-to: &id001
    given  : Chris
    family : Dumars
    address:
        lines: |
            458 Walkman Dr.
            Suite #292
        city    : Royal Oak
        state   : MI
        postal  : 48046
ship-to: *id001
product:
    - sku         : BL394D
      quantity    : 4
      description : Basketball
      price       : 450.00
    - sku         : BL4438H
      quantity    : 1
      description : Super Hoop
      price       : 2392.00
tax  : 251.42
total: 4443.52
comments: >
    Late afternoon is best.
    Backup contact is Nancy
    Billsmer @ 338-4338.`;

const simpleYaml2 = `json:
  - rigid
  - better for data interchange
yaml:
  - slim and flexible
  - better for configuration
object:
  key: value
  array:
    - null_value:
    - boolean: true
    - integer: 1
paragraph: >
  Blank lines denote

  paragraph breaks
content: |-
  Or we
  can auto
  convert line breaks
  to save space
jsoncode:
  - { foo: 'bar' }`;

const complexYaml = `---
# Collection Types #############################################################
################################################################################

# http://yaml.org/type/map.html -----------------------------------------------#

map:
  # Unordered set of key: value pairs.
  Block style: !!map
    Clark : Evans
    Ingy  : döt Net
    Oren  : Ben-Kiki
  Flow style: !!map { Clark: Evans, Ingy: döt Net, Oren: Ben-Kiki }

# http://yaml.org/type/omap.html ----------------------------------------------#

omap:
  # Explicitly typed ordered map (dictionary).
  Bestiary: !!omap
    - aardvark: African pig-like ant eater. Ugly.
    - anteater: South-American ant eater. Two species.
    - anaconda: South-American constrictor snake. Scaly.
    # Etc.
  # Flow style
  Numbers: !!omap [ one: 1, two: 2, three : 3 ]

# http://yaml.org/type/pairs.html ---------------------------------------------#

pairs:
  # Explicitly typed pairs.
  Block tasks: !!pairs
    - meeting: with team.
    - meeting: with boss.
    - break: lunch.
    - meeting: with client.
  Flow tasks: !!pairs [ meeting: with team, meeting: with boss ]

# http://yaml.org/type/set.html -----------------------------------------------#

set:
  # Explicitly typed set.
  baseball players: !!set
    ? Mark McGwire
    ? Sammy Sosa
    ? Ken Griffey
  # Flow style
  baseball teams: !!set { Boston Red Sox, Detroit Tigers, New York Yankees }

# http://yaml.org/type/seq.html -----------------------------------------------#

seq:
  # Ordered sequence of nodes
  Block style: !!seq
  - Mercury   # Rotates - no light/dark sides.
  - Venus     # Deadliest. Aptly named.
  - Earth     # Mostly dirt.
  - Mars      # Seems empty.
  - Jupiter   # The king.
  - Saturn    # Pretty.
  - Uranus    # Where the sun hardly shines.
  - Neptune   # Boring. No rings.
  - Pluto     # You call this a planet?
  Flow style: !!seq [ Mercury, Venus, Earth, Mars,      # Rocks
                      Jupiter, Saturn, Uranus, Neptune, # Gas
                      Pluto ]                           # Overrated


# Scalar Types #################################################################
################################################################################

# http://yaml.org/type/bool.html ----------------------------------------------#

bool:
  - true
  - True
  - TRUE
  - false
  - False
  - FALSE

# http://yaml.org/type/float.html ---------------------------------------------#

float:
  canonical: 6.8523015e+5
  exponentioal: 685.230_15e+03
  fixed: 685_230.15
  sexagesimal: 190:20:30.15
  negative infinity: -.inf
  not a number: .NaN

# http://yaml.org/type/int.html -----------------------------------------------#

int:
  canonical: 685230
  decimal: +685_230
  octal: 02472256
  hexadecimal: 0x_0A_74_AE
  binary: 0b1010_0111_0100_1010_1110
  sexagesimal: 190:20:30

# http://yaml.org/type/merge.html ---------------------------------------------#

merge:
  - &CENTER { x: 1, y: 2 }
  - &LEFT { x: 0, y: 2 }
  - &BIG { r: 10 }
  - &SMALL { r: 1 }
  
  # All the following maps are equal:
  
  - # Explicit keys
    x: 1
    y: 2
    r: 10
    label: nothing
  
  - # Merge one map
    << : *CENTER
    r: 10
    label: center
  
  - # Merge multiple maps
    << : [ *CENTER, *BIG ]
    label: center/big
  
  - # Override
    << : [ *BIG, *LEFT, *SMALL ]
    x: 1
    label: big/left/small

# http://yaml.org/type/null.html ----------------------------------------------#

null:
  # This mapping has four keys,
  # one has a value.
  empty:
  canonical: ~
  english: null
  ~: null key
  # This sequence has five
  # entries, two have values.
  sparse:
    - ~
    - 2nd entry
    -
    - 4th entry
    - Null

# http://yaml.org/type/str.html -----------------------------------------------#

string: abcd

# http://yaml.org/type/timestamp.html -----------------------------------------#

timestamp:
  canonical:        2001-12-15T02:59:43.1Z
  valid iso8601:    2001-12-14t21:59:43.10-05:00
  space separated:  2001-12-14 21:59:43.10 -5
  no time zone (Z): 2001-12-15 2:59:43.10
  date (00:00:00Z): 2002-12-14


# JavaScript Specific Types ####################################################
################################################################################

# https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp

regexp:
  simple: !!js/regexp      foobar
  modifiers: !!js/regexp   /foobar/mi

# https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/undefined

undefined: !!js/undefined ~

# https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function

function: !!js/function >
  function foobar() {
    return 'Wow! JS-YAML Rocks!';
  }


# Custom types #################################################################
################################################################################


# JS-YAML allows you to specify a custom YAML types for your structures.
# This is a simple example of custom constructor defined in \`js/demo.js\` for
# custom \`!sexy\` type:
#
# var SexyYamlType = new jsyaml.Type('!sexy', {
#   kind: 'sequence',
#   construct: function (data) {
#     return data.map(function (string) { return 'sexy ' + string; });
#   }
# });
#
# var SEXY_SCHEMA = jsyaml.Schema.create([ SexyYamlType ]);
#
# result = jsyaml.load(yourData, { schema: SEXY_SCHEMA });

foobar: !sexy
  - bunny
  - chocolate`;

const simpleRegularArray = `['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']`;

const simpleAssociativeArray = `{
  "zero": 0,
  "one": 1,
  "two": 2,
  "three": 3,
  "four": 4,
  "five": 5,
  "six": 6,
  "seven": 7,
  "eight": 8,
  "nine": 9
}`;

const charsWithNamedEntities = `© ¶ ° ® ² ³ ± ¥ & ¢ £ ¤ ¼ ½ ¾ × ÷ † ← ⇔ ♥ ≠`;

const ascii = `     .-''-.
    / ,    \\
 .-'\`(o)    ;
'-==.       |
     \`._...-;-.
      )--"""   \`-.
     /   .        \`-.
    /   /      \`.    \`-.
    |   \    ;   \      \`-._________
    |    \    \`.\`.;          -------\`.
     \    \`-.   \\\\          \`---...|
      \`.     \`-. \`\`\`\.--'._   \`---...|
        \`-.....7\`-.))\     \`-._\`-.. /
          \`._\ /   \`-\`         \`-.,'
            / /
           /=(_
        -./--' \`
      ,^-(_
      ,--' \``;

const csvData = `Firstname,Surname,Age,Hobby,Nationality
Alison,Smith,23,Swimming,British
Bob,Parker,16,Music,French
Caroline,Davies,29,Gymnastics,American
Dave,Major,37,Art,Italian
Edward,Phillips,54,Football,Spanish
Freya,Adams,12,Drama,Swedish
George,White,40,Hockey,Dutch
Howard,Christie,45,Rugby,Indian
Isabelle,Bennet,21,Singing,Polish`;

const duplicateUuids = '7ddcbe00-f0f4-490e-a247-5810b0cc64cb\n0917d3dc-cf34-4ece-b68c-244056a0aa49\nafb5179c-cbc4-4f41-ac8e-1bb363ee58a7\n305c9744-b114-4cac-9884-8a02eb170d29\nb9800028-c124-44d6-9f52-78e464f2553f\n7d58f5d3-156a-4748-b98f-4a6565cef527\n1310c506-21e8-4dc0-b5ab-c67b72881e6b\n1342ca92-6e18-4cd3-b435-3481bbb856e0\n5deae917-cae6-433f-b7ab-5b5426ad8738\nb9800028-c124-44d6-9f52-78e464f2553f\na9d5469a-6e9c-4638-86b9-6f17b67f7476\n305c9744-b114-4cac-9884-8a02eb170d29\n009d5d48-03be-4869-9e16-4aa9b558f4fe\n52fc4a0c-1b34-47b9-a9a8-c25df2e85731\nfe3a1b54-e6fa-4fae-a076-a3099bf55de3\n7809878b-310f-4f31-90ec-c7d60f0d3476\nbd5db2a7-494f-4c67-bedb-8370c74f454f\n9c4fd127-0bc0-4f18-b4b7-724372af6d71\n6f06d4bb-6bea-4198-894d-92de5d482d0d\n88f48994-e94c-4d8a-9a1b-8303bb31682f\nf5c1be14-1ee8-4df8-b089-dfcae2ac1896\ne2fecd42-d02a-4ce5-93a5-c0f8468086fa\n04f57c55-a3b4-44a2-af69-be53fce8dc0a\nf88fda70-c206-4989-bf40-bb9ad69aa4f8\necb27a7f-3ffa-499d-a27d-6a2639c34f72\n761c9b4c-2836-4ed5-a1e2-ba2f2c403035\n88796b5c-371a-47e6-bea8-bbff55fdf5ca\n982a4040-d24f-402a-bbff-6261f04b223f\nb9800028-c124-44d6-9f52-78e464f2553f\naf85377f-1b82-4dd5-93c6-0f548990b2e9\n21cc96d4-d059-4aaa-af10-eb4f449dbb2d\n05c8b998-e119-4626-9587-b3e4a013aaab\nfdb1a733-1732-49cc-8d23-d0e6747e9161\n6da8072e-4f13-41fe-bd18-7a393fb8cc88\nbd8f82cb-f1cb-4a9c-b74c-fc69e54036ca\n305c9744-b114-4cac-9884-8a02eb170d29\nb9800028-c124-44d6-9f52-78e464f2553f\n6da8072e-4f13-41fe-bd18-7a393fb8cc88\n71d37589-af66-4744-85cd-b2bd78703ef3\nb9800028-c124-44d6-9f52-78e464f2553f\n67f6985f-72bc-40b3-a084-310ed5705ab9\nb28fd4b0-e432-4afa-97b5-b48138c2b347\nd01ce8d4-4019-45a2-a4c4-f5b95f0a23dd\n301d322c-aa09-4a40-b777-ab6085d8cced';

const tabDelimitedData = `Firstname	Surname	Age	Hobby	Nationality
Alison	Smith	23	Swimming	British
Bob	Parker	16	Music	French
Caroline	Davies	29	Gymnastics	American
Dave	Major	37	Art	Italian
Edward	Phillips	54	Football	Spanish
Freya	Adams	12	Drama	Swedish
George	White	40	Hockey	Dutch
Howard	Christie	45	Rugby	Indian
Isabelle	Bennet	21	Singing	Polish`;

const linedUpTabDelimitedData = `Firstname	Surname		Age		Hobby		Nationality
Alison		Smith		23		Swimming	British
Bob		Parker		16		Music		French
Caroline	Davies		29		Gymnastics	American
Dave		Major		37		Art		Italian
Edward		Phillips	54		Football	Spanish
Freya		Adams		12		Drama		Swedish
George		White		40		Hockey		Dutch
Howard		Christie	45		Rugby		Indian
Isabelle	Bennet		21		Singing		Polish`;

const boysNames = `Oliver\nHarry\nGeorge\nJack\nJacob\nNoah\nCharlie\nMuhammad\nThomas\nOscar\nWilliam\nJames\nLeo\nAlfie\nHenry\nJoshua\nFreddie\nArchie\nEthan\nIsaac\nAlexander\nJoseph\nEdward\nSamuel\nMax\nLogan\nLucas\nDaniel\nTheo\nArthur\nMohammed\nHarrison\nBenjamin\nMason\nFinley\nSebastian\nAdam\nDylan\nZachary\nRiley\nTeddy\nTheodore\nDavid\nElijah\nJake\nToby\nLouie\nReuben\nArlo\nHugo\nJaxon\nLuca\nMatthew\nHarvey\nHarley\nReggie\nTommy\nJenson\nLuke\nMichael\nJayden\nJude\nFrankie\nAlbert\nStanley\nElliot\nGabriel\nMohammad\nOllie\nRonnie\nLouis\nCharles\nBlake\nElliott\nLewis\nFrederick\nNathan\nTyler\nJackson\nRory\nRyan\nCarter\nDexter\nAlex\nAustin\nCaleb\nKai\nAlbie\nEllis\nBobby\nEzra\nLeon\nRoman\nJesse\nAaron\nIbrahim\nLiam\nJasper\nFelix\nFinn`;

const girlsNames = `Olivia\nAmelia\nEmily\nIsla\nAva\nIsabella\nLily\nJessica\nElla\nMia\nSophia\nCharlotte\nPoppy\nSophie\nGrace\nEvie\nAlice\nScarlett\nFreya\nFlorence\nIsabelle\nDaisy\nChloe\nPhoebe\nMatilda\nRuby\nEvelyn\nSienna\nSofia\nEva\nElsie\nWillow\nIvy\nMillie\nEsme\nRosie\nImogen\nElizabeth\nMaya\nLayla\nEmilia\nLola\nLucy\nHarper\nEliza\nErin\nEleanor\nEllie\nHarriet\nThea\nMaisie\nHolly\nEmma\nGeorgia\nAmber\nMolly\nHannah\nAbigail\nJasmine\nLilly\nAnnabelle\nRose\nPenelope\nAmelie\nViolet\nBella\nAria\nZara\nMaria\nNancy\nDarcie\nLottie\nAnna\nSummer\nMartha\nHeidi\nGracie\nLuna\nMaryam\nBeatrice\nMila\nDarcey\nMegan\nIris\nLexi\nRobyn\nAisha\nClara\nFrancesca\nSara\nVictoria\nZoe\nJulia\nArabella\nMaddison\nSarah\nFelicity\nDarcy\nLeah\nLydia`;

const emoticons = `🌀🌁🌂🌃🌄🌅🌆🌇🌈🌉🌊🌋🌌🌏🌑🌓🌔🌕🌙🌛🌟🌠🌷🌸🌹🌺🌻🌼🌽🌾🌿🍀🍁🍂🍃🍄🍅🍆🍇🍈🍉🍊🎠🎡🎢🎣🎤🎥🎦🎧🎨🎩🎪🎫🎬🎭🎮🎯🎰🎱🎲🎳🎴🎵🎶🎷🎸🎹🎺🎻🎼🎽🎾🎿🏀🏁🏂🏃🏄🏆🏈🏊🏠🏡🏢🏣🏤🏥🏦🏧🏨🏩🏪🏫🏬🏭🏮🏯🏰👀👂👃👄👅👆👇👈👉👊👋👌👍👎👏👐👑👒👓👔👕👖👗👘👙👚👛👜👝👞👟👠👡👢👣👤👦👧👨👩👪👫👮👯👰👱👲👳👴👵👶👷👸👹👺👻👼👽👾👿💀💁💂💃💄💅💆💇💈💉💊💋💌💍💎💏💐💑💒💓💔💕💖💗💘💙💚💛💜💝💞💟💠💡💢💣💤💥💦💧💨💩💪💫💬💮💯💰💱💲💳💴💵💸💹💺💻💼💽💾💿📀📁📂📃📄📅📆📇📈📉📊📋📌📍📎📏📐📑📒📓📔📕📖📗📘📙📚📛📜📝📞📟📠📡📢📣📤📥📦📧📨📩📪📫📮📰📱📲📳📴📶📷📸📹📺📻📼🔲🔳🔴🔵🔶🔷🔸🔹🔺🔻🔼🔽🕐🕑🕒🕓🕔🕕🕖🕗🕘🕙🕚🕛🗻🗼🗽🗾🗿`;

const markdown = `An h1 header\n============\n\nParagraphs are separated by a blank line.\n\n2nd paragraph. *Italic*, **bold**, and \`monospace\`. Itemized lists\nlook like:\n\n  * this one\n  * that one\n  * the other one\n\nNote that --- not considering the asterisk --- the actual text\ncontent starts at 4-columns in.\n\n> Block quotes are\n> written like so.\n>\n> They can span multiple paragraphs,\n> if you like.\n\nUse 3 dashes for an em-dash. Use 2 dashes for ranges (ex., "it's all\nin chapters 12--14"). Three dots ... will be converted to an ellipsis.\nUnicode is supported. ☺\n\n\n\nAn h2 header\n------------\n\nHere's a numbered list:\n\n 1. first item\n 2. second item\n 3. third item\n\nNote again how the actual text starts at 4 columns in (4 characters\nfrom the left side). Here's a code sample:\n\n    # Let me re-iterate ...\n    for i in 1 .. 10 { do-something(i) }\n\nAs you probably guessed, indented 4 spaces. By the way, instead of\nindenting the block, you can use delimited blocks, if you like:\n\n~~~\ndefine foobar() {\n    print "Welcome to flavor country!";\n}\n~~~\n\n(which makes copying & pasting easier). You can optionally mark the\ndelimited block for Pandoc to syntax highlight it:\n\n~~~python\nimport time\n# Quick, count to ten!\nfor i in range(10):\n    # (but not *too* quick)\n    time.sleep(0.5)\n    print i\n~~~\n\n\n\n### An h3 header ###\n\nNow a nested list:\n\n 1. First, get these ingredients:\n\n      * carrots\n      * celery\n      * lentils\n\n 2. Boil some water.\n\n 3. Dump everything in the pot and follow\n    this algorithm:\n\n        find wooden spoon\n        uncover pot\n        stir\n        cover pot\n        balance wooden spoon precariously on pot handle\n        wait 10 minutes\n        goto first step (or shut off burner when done)\n\n    Do not bump wooden spoon or it will fall.\n\nNotice again how text always lines up on 4-space indents (including\nthat last line which continues item 3 above).\n\nHere's a link to [a website](http://foo.bar), to a [local\ndoc](local-doc.html), and to a [section heading in the current\ndoc](#an-h2-header). Here's a footnote [^1].\n\n[^1]: Footnote text goes here.\n\nTables can look like this:\n\nsize  material      color\n----  ------------  ------------\n9     leather       brown\n10    hemp canvas   natural\n11    glass         transparent\n\nTable: Shoes, their sizes, and what they're made of\n\n(The above is the caption for the table.) Pandoc also supports\nmulti-line tables:\n\n--------  -----------------------\nkeyword   text\n--------  -----------------------\nred       Sunsets, apples, and\n          other red or reddish\n          things.\n\ngreen     Leaves, grass, frogs\n          and other things it's\n          not easy being.\n--------  -----------------------\n\nA horizontal rule follows.\n\n***\n\nHere's a definition list:\n\napples\n  : Good for making applesauce.\noranges\n  : Citrus!\ntomatoes\n  : There's no "e" in tomatoe.\n\nAgain, text is indented 4 spaces. (Put a blank line between each\nterm/definition pair to spread things out more.)\n\nHere's a "line block":\n\n| Line one\n|   Line too\n| Line tree\n\nand images can be specified like so:\n\n![example image](http://www.unexpected-vortices.com/sw/rippledoc/example-image.jpg "An exemplary image")\n\nInline math equations go in like so: $\omega = d\phi / dt$. Display\nmath should get its own line and be put in in double-dollarsigns:\n\n$$I = \int \rho R^{2} dV$$\n\nAnd note that you can backslash-escape any punctuation characters\nwhich you wish to be displayed literally, ex.: \`foo\`, \*bar\*, etc.`;

const jsWithComments = `var sample    = 0;
var new       = 1;
var my_string = "Hello World!";

// This is a comment!

function do_stuff(){
	alert(my_string);//another comment
}

/* This is
 * a multiline
 * comment!
 */

var something;

/* programs/applications 16/*(4*2)=2 */

if(sample > new){
  do_stuff(/* arguments here */);
}

//

/**/`;

const sampleXml = `<?xml version="1.0"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
   <book id="bk103">
      <author>Corets, Eva</author>
      <title>Maeve Ascendant</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-11-17</publish_date>
      <description>After the collapse of a nanotechnology 
      society in England, the young survivors lay the 
      foundation for a new society.</description>
   </book>
</catalog>`;

const indentationWithTabs = `Line 1
	Line 2
		Line 3
			Line 4
		Line 5
	Line 6
Line 7`;

const indentationWithTwoSpaces = `Line 1
  Line 2
    Line 3
      Line 4
    Line 5
  Line 6
Line 7`;

const indentationWithFourSpaces = `Line 1
    Line 2
        Line 3
            Line 4
        Line 5
    Line 6
Line 7`;

const sampleExtractData = `Email addresses
--------------------
abc1.1@domain.com
abc.abc@domain.com
abc_41.15768@domain.com
12345@domain.com
12.12.23@domain.com
ABC.ABC.ABC.ABC0046@domain.com
abc_123_4595@domain.com
abc@asdas.co.in
abc@insta123.com
abc@inta.co.in

URLs
--------------------
www.domain.com
https://www.google.com:80/dir/1/2/search.html#hash
https://www.google.com:80/dir/1/2/search.html?arg=0-a&arg1=1-b&arg3-c#hash
https://www.youtube.com/watch?feature=something&v=videoid1&embed=something
http://www.youtube.com/watch?feature=something&v=videoid2&embed=something
www.youtube.com/watch?feature=something&v=videoid3&embed=something
youtube.com/watch?feature=something&v=videoid4&embed=something
http://user:pass@www.google.com:8000/foo/bar?st=1&lt=10
mailto://name@domain.com

Non-ASCII chars
--------------------
前に来た時は北側からで、当時の光景はいまでも思い出せる。
青竜山脈から流れる川が湖へと流れこむ様、でいて、川沿いに者ギルドが建っていた。
そして町を囲むように配置された七つの塔と、大きく広がる草原地帯。
……あ。
テスト
テスト。
Õ×ë
テスト。
-Τα εννέα πουλιά -
MIRROR

Hex colors
--------------------
#ff0000
#00FF00
#FAFAFA
ff0000

IP addresses
--------------------
0.0.0.0
1.2.3.4
8.8.8.8
123.123.123.123
255.255.255.255
127.0.0.1

Phone numbers
--------------------
+42 555.123.4567
+1-(800)-123-4567
+7 555 1234567
+7(926)1234567
(926) 1234567
+79261234567
926 1234567
9261234567
1234567
123-4567
123-89-01
495 1234567
469 123 45 67
89261234567
8 (926) 1234567
926.123.4567
415-555-1234
650-555-2345
(416)555-3456
202 555 4567
4035555678
1 416 555 9292

UK postcodes
--------------------
M1 1AA
m60 1NW
CR2 6XH
DN55 1PT
W1A 1HQ
EC1A 1BB
CW3 9SS
SE5 0EG
se5 0eg
WC2H7LT
BH11 9ep

UUIDs
--------------------
b7a1d0b6-d7b7-4c6e-93ee-77c5b49b8b92
98047616-7891-4226-b870-9dd58050d529
5d7c8a52-f709-43f5-9fcb-e6b5cb857d07
0ceb1cbe-98e2-4e7d-9a10-12e5914f991b
00e97ba5-ef09-4f1e-b908-e8cc799bb0ee
aa834731-9fd6-412d-ba78-9d36dfb9b9b2
ee835824-59fa-46c7-b4ff-31b42724d410
58ca1586-ff27-4b1d-9c59-abd636f7467e
943c014a-5dde-4274-a138-620402b5d337
6c747618-0d03-4f82-9149-5b03b767e8b3
`;

const sampleSvgMarkup = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
  <path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/>
</svg>`;

const sampleGeometricShapes = `Unicode range 25: Box Drawing, Block Elements, Geometric Shapes

https://en.wikipedia.org/wiki/Box-drawing_character
http://www.alanflavell.org.uk/unicode/unidata25.html
https://jrgraphix.net/r/Unicode/2500-257F
https://www.fileformat.info/info/unicode/block/geometric_shapes/list.htm


Single box

┏━┓
┃    ┃
┗━┛

Quad box

┏━┳━┓
┃    ┃    ┃
┣━╋━┫
┃    ┃    ┃
┗━┻━┛

┏━┳━┓
┃▉┃▉┃ 
┣━╋━┫
┃▉┃▉┃  
┗━┻━┛

Circle

╭╮
╰╯

◠
◡

◦

◐
◐
◐
◍



◼◼◼◼◼◼◼
◼◼◼◼◼◼◼
◼◼◼◼◼◼◼
◼◼◼◼◼◼◼
`;

const sampleArrowSymbols = `←
↑
→
↓
↔
↕
↖
↗
↘
↙
▲
▼
◀
▶
➔
➘
➙
➚
➛
➜
➝
➞
➟
➠
➡
➢
➣
➤
➥
➦
↪
↩
↚
↛
↜
↝
↞
↟
↠
↡
↢
↣
↤
↦
↥
↧
↨
↫
↬
↭
↮
↯
↰
↱
↲
↴
↳
↵
↶
↷
↸
↹
↺
↻
⟲
⟳
↼
↽
↾
↿
⇀
⇁
⇂
⇃
⇄
⇅
⇆
⇇
⇐
⇑
⇒
⇓
⇔
⇌
⇍
⇏
⇕
⇖
⇗
⇘
⇙
⇙
⇳
⇚
⇛
⇜
⇝
⇞
⇟
⇟
⇟
⇠
⇡
⇢
⇣
⇤
⇥
⇦
⇨
⇩
⇪
⇧
⇫
⇬
⇭
⇮
⇯
⇰
⇱
⇲
⇴
⇵
⇶
⇷
⇸
⇹
⇺
⇺
⇻
⇼
⇽
⇾
⇿
⟰
⟱
⟴
⟵
⟶
⟷
⟸
⟹
⟽
⟾
⟺
⟻
⟼
⟿
⤀
⤁
⤅
⤂
⤃
⤄
⤆
⤇
⤈
⤉
⤊
⤋
⤌
⤍
⤎
⤏
⤐
⤑
⤒
⤓
⤔
⤕
⤖
⤗
⤘
⤙
⤙
⤚
⤛
⤜
⤝
⤞
⤡
⤢
⤣
⤤
⤥
⤦
⤧
⤨
⤩
⤪
⤭
⤮
⤯
⤰
⤱
⤲
⤳
⤻
⤸
⤾
⤿
⤺
⤼
⤽
⤴
⤵
⤶
⤷
⤹
⥀
⥁
⥂
⥃
⥄
⥅
⥆
⥇
⥈
⥉
⥒
⥓
⥔
⥕
⥖
⥗
⥘
⥙
⥚
⥛
⥜
⥝
⥞
⥟
⥠
⥡
⥢
⥣
⥤
⥥
⥦
⥧
⥨
⥩
⥪
⥫
⥬
⥭
⥮
⥯
⥰
⥱
⥲
⥳
⥴
⥵
⥶
⥷
⥸
⥹
⥺
⥻
➧
➨
➩
➪
➫
➬
➭
➮
➯
➱
➲
➳
➴
➵
➶
➷
➸
➹
➺
➻
➼
➽
➾
⬅
⬆
⬇
⏎
⬎
⬏
⬐
⬑
☈
☇
⍃
⍄
⍇
⍈
⍐
⍗
⍌
⍓
⍍
⍔
⍏
⍖
⍅
⍆
⬈
⬉
⬊
⬋
⬌
⬍
⬀
⬁
⬂
⬃
⬄`;

const sampleHeartSymbols = `❦
❧
☙
❥
❣
♡
♥
❤
➳
ღ
💌
🏩
💓
💔
💕
💖
💗
💘
💙
💚
💛
💜
🖤
💝
💞
💟
💑`;

const sampleSpecialSymbols = `«
»
❝
❞
×
⦂
⁃
‐
‑
‒
�
–
⎯
—
―
~
⁓
•
°
%
‰
‱
&
⅋
§
÷
±
‼
¡
¿
⸮
⁇
⁉
⁈
‽
⸘
¼
½
¾
²
³
⅕
⅙
⅛
©
®
™
℠
℻
℅
℁
⅍
¶
⁋
≠
√
�
∛
∜
∞
β
Φ
Σ
€
₤
$
♀
♂
⚢
⚣
⌘
♲
♻
☺
★
↑
↓`;

const sampleFlowerSymbols = `⚜
✥
✤
✻
✼
✽
✾
❀
✿
❁
❃
❇
❈
❉
❊
❋
⚘
⁕
ꙮ
ꕤ
ꕥ
☘
᪥
🍀
🌼
🌻
🌺
🌹
🌸
🌷
💐`;

const sampleQuotationMarks = `«
‹
»
›
„
‚
“
‟
‘
‛
”
’
"
❛
❜
❟
❝
❞
❮
❯
⹂
〝
〞
〟
"`;

const sampleStarSymbols = `★
☆
✪
✫
✯
✡
⚝
⚹
✵
❉
❋
✺
✹
✸
✶
✷
✵
✴
✳
✲
✱
✧
✦
⍟
⊛
⁕
🔯
🌠
🌟
﹡
❃
❂
✼
✻
✰
⍣
✭
≛
*
٭`;

const sampleEmojiSymbols = `☺
☹
☻
😀
😁
😂
😃
😄
😅
😆
😇
😈
😉
😊
😋
😌
😍
😎
😏
😐
😑
😒
😓
😔
😕
😖
😗
😘
😙
😚
😛
😜
😝
😞
😟
😠
😡
😢
😣
😤
😥
😦
😧
😨
😩
😪
😫
😬
😭
😮
😯
😰
😱
😲
😳
😴
😵
😶
😷
😸
😹
😺
😻
😼
😽
😾
😿
🙀
🙅
🙆
🙇
🙈
🙉
🙊
🙋
🙌
🙍
🙎
🙏
🚀
🚁
🚂
🚃
🚄
🚅
🚆
🚇
🚈
🚉
🚊
🚋
🚌
🚍
🚎
🚏
🚐
🚑
🚒
🚓
🚔
🚕
🚖
🚗
🚘
🚙
🚚
🚛
🚜
🚝
🚞
🚟
🚠
🚡
🚢
🚣
🚤
🚥
🚦
🚧
🚨
🚩
🚪
🚫
🚬
🚭
🚮
🚯
🚰
🚱
🚲
🚳
🚴
🚵
🚶
🚷
🚸
🚹
🚺
🚻
🚼
🚽
🚾
🚿
🛀
🛁
🛂
🛃
🛄
🛅`;

const sampleZodiacSymbols = `♈
♉
♊
♋
♌
♍
♎
♏
♐
♑
♒
♓
⛎`;

const sampleCurrencySymbols = `₳
฿
₿
¢
₡
¢
₢
₵
₫
€
£
£
₤
₣
ƒ
₲
₭
Ł
₥
₦
₽
₱
$
$
₮
ℳ
₶
₩
₩
¥
¥
₴
₸
¤
₰
៛
₪
₯
₠
₧
﷼
円
元
圓
㍐
원
৳
₹
₨
৲
௹`;

const sampleGreekSymbols = `Α
Β
Γ
Δ
Ε
Ζ
Η
Θ
Ι
Κ
Λ
Μ
Ν
Ξ
Ο
Π
Ρ
Σ
Τ
Υ
Φ
Χ
Ψ
Ω
α
β
γ
δ
ε
ζ
η
θ
ι
κ
λ
μ
ν
ξ
ο
π
ρ
ς
σ
τ
υ
φ
χ
ψ
ω`;

const sampleRomanNumerals = `Ⅰ
Ⅱ
Ⅲ
Ⅳ
Ⅴ
Ⅵ
Ⅶ
Ⅷ
Ⅸ
Ⅹ
Ⅺ
Ⅻ
Ⅼ
Ⅽ
Ⅾ
Ⅿ
ↀ
ↁ
ↂ
ↇ
ↈ
ⅰ
ⅱ
ⅲ
ⅳ
ⅴ
ⅵ
ⅶ
ⅷ
ⅸ
ⅹ
ⅺ
ⅻ
ⅼ
ⅽ
ⅾ
ⅿ
ↅ
ↆ
Ↄ`;

const sampleSuitsOfTheCards = `♠
♤
♥
♡
♣
♧
♦
♢`;

const samplePunctuationMarks = `.
।
։
。
۔
⳹
܁
።
᙮
᠃
⳾
꓿
꘎
꛳
࠽
᭟
,
،
、
՝
߸
፣
᠈
꓾
꘍
꛵
᭞
?
;
¿
؟
՞
܆
፧
⳺
⳻
꘏
꛷
𑅃
꫱
!
¡
߹
᥄
·
𐎟
𐏐
𒑰
፡
 
𐤟
࠰
—
–
‒
‐
⁃
﹣
-
֊
᠆
;
·
؛
፤
꛶
․
:
፥
꛴
᭝
…
︙
ຯ
«
‹
»
›
„
‚
“
‟
‘
‛
”
’
"`;




// =========================================================
// Global variables 
// =========================================================

let savedText = '';
let history = [];
let historyIndex = undefined;


// =========================================================
// Init 
// =========================================================

function init() {
    $('#main-textarea').val('');
    updateHistory();
}


// =========================================================
// History functions 
// =========================================================

function updateHistory() {
    if (historyIndex < history.length-1) {
        history = history.slice(0, historyIndex+1);
    }
    history.push($('#main-textarea').val());
    if (history.length > 1) {
        $('#btn-history-undo, #btn-history-clear').prop('disabled', false);
    } else {
        $('#btn-history-undo').prop('disabled', true);
    }
    $('#btn-history-redo').prop('disabled', true);
    historyIndex = history.length-1;
    $('#history-legend').text('History ('+ (historyIndex+1) +' of '+ history.length +')');
    //logHistory();
}

function clearHistory() {
    history = [];
    updateHistory();
    $('#btn-history-undo, #btn-history-redo, #btn-history-clear').prop('disabled', true);
}

function undo() {
    historyIndex--;
    if (historyIndex <= 0) {
        historyIndex = 0;
        $('#btn-history-undo').prop('disabled', true);
    }
    $('#main-textarea').val(history[historyIndex]);
    $('#btn-history-redo').prop('disabled', false);
    $('#history-legend').text('History ('+ (historyIndex+1) +' of '+ history.length +')');
    //logHistory();
}

function redo() {
    historyIndex++;
    if (historyIndex >= history.length-1) {
        historyIndex = history.length-1;
        $('#btn-history-redo').prop('disabled', true);
    }
    $('#main-textarea').val(history[historyIndex]);
    $('#btn-history-undo').prop('disabled', false);
    $('#history-legend').text('History ('+ (historyIndex+1) +' of '+ history.length +')');
    //logHistory();
}

$('#main-textarea').on('change', function(event) {
    updateHistory();
});

$('#main-textarea').on('keyup', function(event) {
    let ignoreWhichKeys = [16,17,18,27,91,93,37,38,39,40];
    if (ignoreWhichKeys.indexOf(event.which) === -1) {
        updateHistory();
    }
});

function logHistory() {
    console.clear();
    console.log(history);
    console.log('historyIndex:', historyIndex);
    console.log('history['+historyIndex+']:', history[historyIndex]);
}


// =========================================================
// Wordwrap checkbox
// =========================================================

$('#word-wrap-checkbox').on('change', function(event) {
    if ($(this).prop('checked')) {
        $('#main-textarea').addClass('wordwrap');
    } else {
        $('#main-textarea').removeClass('wordwrap');
    }
});



// =========================================================
// Event handler for clicking on legends
// =========================================================

$('legend').click(function() {
    let $fieldset = $(this).closest('fieldset');
    let $content = $fieldset.find('.fieldset-content');
    $content.slideToggle('fast');
    $fieldset.toggleClass('collapsed');
});


// =========================================================
// General fieldset
// =========================================================

$('#btn-clear-textarea').click(function() {
    $('#main-textarea').val('');
    updateHistory();
});

$('#btn-collapse-panels').click(function() {
    let $fieldsetContent, $fieldset;
    let $fieldsetContents = $('.fieldset-content').not('.general-fieldset-content');
    $fieldsetContents.each(function() {
        $fieldsetContent = $(this);
        $fieldsetContent.slideUp('fast');
        $fieldset = $fieldsetContent.closest('fieldset');
        $fieldset.addClass('collapsed');
    });
});

$('#btn-expand-panels').click(function() {
    let $fieldsetContent, $fieldset;
    let $fieldsetContents = $('.fieldset-content').not('.general-fieldset-content');
    $fieldsetContents.each(function() {
        $fieldsetContent = $(this);
        $fieldsetContent.slideDown('fast');
        $fieldset = $fieldsetContent.closest('fieldset');
        $fieldset.removeClass('collapsed');
    });
});


// =========================================================
// Clipboard fieldset
// =========================================================

$('#btn-clipboard-select-all').click(function() {
    $('#main-textarea').select();
});

// $('#btn-clipboard-copy').click(function() {
   
// });

$('#btn-clipboard-cut').click(function() {
   setTimeout(function(){
        $('#main-textarea').val('');
        updateHistory();
   }, 200);
});


// =========================================================
// History fieldset
// =========================================================

$('#btn-history-undo').click(function() {
    undo();
});

$('#btn-history-redo').click(function() {
    redo();
});

$('#btn-history-clear').click(function() {
    clearHistory();
});


// =========================================================
// Font fieldset
// =========================================================

$('#font-family').change(function() {
    $('#main-textarea').css('font-family', $(this).val());
});

$('#font-size').change(function() {
    $('#main-textarea').css('font-size', $(this).val());
});

$('#font-weight').change(function() {
    $('#main-textarea').css('font-weight', $(this).val());
});

$('#line-height').change(function() {
    $('#main-textarea').css('line-height', $(this).val());
});

$('#letter-spacing').change(function() {
    $('#main-textarea').css('letter-spacing', $(this).val());
});

$('#color-theme').change(function() {
    let colorTheme = $(this).val();
    switch(colorTheme) {
        case 'green-on-black':
            $('#main-textarea').css('color', '#009c0f');
            $('#main-textarea').css('background-color', '#000');
            break;
        case 'white-on-black':
            $('#main-textarea').css('color', '#fff');
            $('#main-textarea').css('background-color', '#000');
            break;
        case 'light-on-dark':
            $('#main-textarea').css('color', '#e8e8e8');
            $('#main-textarea').css('background-color', '#252525');
            break;
        case 'dark-on-light':
            $('#main-textarea').css('color', '#4e4e4e');
            $('#main-textarea').css('background-color', '#e8e8e8');
            break;
        case 'black-on-white':
            $('#main-textarea').css('color', '#000');
            $('#main-textarea').css('background-color', '#fff');
            break;
        default:
            break;
    }
});


// =========================================================
// Save/restore fieldset
// =========================================================

$('#btn-save-text').click(function() {
    localStorage.setItem('savedText', $('#main-textarea').val());
    $('#btn-restore-text').prop('disabled', false);
});

$('#btn-restore-text').click(function() {
    let savedText = localStorage.getItem('savedText');
    if (savedText) {
        $('#main-textarea').val(savedText);
        updateHistory();
    }
});

$('#btn-save-text-to-file').click(function() {
    let now = new Date();
    let year = now.getFullYear();
    let month = now.getMonth() + 1 < 10 ? '0' + (now.getMonth() + 1) : now.getMonth() + 1;
    let date = now.getDate() < 10 ? '0' + now.getDate() : now.getDate();
    let hour = now.getHours() < 10 ? '0' + now.getHours() : now.getHours();
    let min = now.getMinutes() < 10 ? '0' + now.getMinutes() : now.getMinutes();
    let formattedDate = year + '-' + month + '-' + date + '_' + hour + '-' + min;
    let $textarea = $('#main-textarea');
    let blob = new Blob([$textarea.val()], {type: 'text/plain;charset=utf-8'});
    window.saveAs(blob, 'text_' + formattedDate + '.txt');
});



// =========================================================
// Save/restore fieldset
// =========================================================

$('#btn-scroll-to-top-left').click(function() {
    let $textarea = $('#main-textarea');
    $textarea.scrollTop(0).scrollLeft(0);
});

$('#btn-scroll-to-bottom-left').click(function() {
    let $textarea = $('#main-textarea');
    $textarea.scrollTop($textarea[0].scrollHeight).scrollLeft(0);
});

$('#btn-scroll-to-top').click(function() {
    let $textarea = $('#main-textarea');
    $textarea.scrollTop(0);
});

$('#btn-scroll-to-bottom').click(function() {
    let $textarea = $('#main-textarea');
    $textarea.scrollTop($textarea[0].scrollHeight);
});

$('#btn-scroll-to-left').click(function() {
    let $textarea = $('#main-textarea');
    $textarea.scrollLeft(0);
});

$('#btn-scroll-to-right').click(function() {
    let $textarea = $('#main-textarea');
    $textarea.scrollLeft($textarea[0].scrollWidth);
});

// =========================================================
// Sample text fieldset
// =========================================================

$('#btn-sample-hello-world').click(function() {
    $('#main-textarea').val(`hello world`);
    updateHistory();
});

$('#btn-sample-accent').click(function() {
    $('#main-textarea').val(`déjà vu`);
    updateHistory();
});

$('#btn-sample-simple-url').click(function() {
    $('#main-textarea').val(`http://www.example.com/`);
    updateHistory();
});

$('#btn-sample-complex-url').click(function() {
    $('#main-textarea').val(`http://username:password@www.example.com:80/path/to/file.php?foo=316&bar=this+has+spaces#anchor`);
    updateHistory();
});

$('#btn-sample-text').click(function() {
    $('#main-textarea').val(sampleText);
    updateHistory();
});

$('#btn-sample-html-emmet-starter').click(function() {
    $('#main-textarea').val(sampleEmmetHtml);
    updateHistory();
});

$('#btn-sample-html').click(function() {
    $('#main-textarea').val(sampleHtml);
    updateHistory();
});

$('#btn-sample-html-5-boilerplate').click(function() {
    $('#main-textarea').val(decodeURIComponent(sampleHtml5Boilerplate));
    updateHistory();
});

$('#btn-sample-html-5-kitchen-sink').click(function() {
    $('body').addClass('cursor-wait');
    axios.get('https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/html-5-kitchen-sink.html')
        .then(function(response) {
            $('#main-textarea').val(response.data);
            updateHistory();
            $('body').removeClass('cursor-wait');
        })
        .catch(function(error) {
            alert('Oops! An error occurred: ' + error);
        });
});

$('#btn-sample-html-table').click(function() {
    $('#main-textarea').val(sampleHtmlTable);
    updateHistory();
});

$('#btn-sample-xml').click(function() {
    $('#main-textarea').val(sampleXml);
    updateHistory();
});

$('#btn-sample-js-with-comments').click(function() {
    $('#main-textarea').val(jsWithComments);
    updateHistory();
});

$('#btn-sample-js-jquery-unminified').click(function() {
    $('body').addClass('cursor-wait');
    axios.get('https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/jquery-3.3.1.js')
        .then(function(response) {
            $('#main-textarea').val(response.data);
            updateHistory();
            $('body').removeClass('cursor-wait');
        })
        .catch(function(error) {
            alert('Oops! An error occurred: ' + error);
        });
});

$('#btn-sample-bootstrap-css-unminified').click(function() {
    $('body').addClass('cursor-wait');
    axios.get('https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/bootstrap.css')
        .then(function(response) {
            $('#main-textarea').val(response.data);
            updateHistory();
            $('body').removeClass('cursor-wait');
        })
        .catch(function(error) {
            alert('Oops! An error occurred: ' + error);
        });
});

$('#btn-sample-wordpress-directory-structure').click(function() {
    $('body').addClass('cursor-wait');
    axios.get('https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/wordpress-directory-structure.txt')
        .then(function(response) {
            $('#main-textarea').val(response.data);
            updateHistory();
            $('body').removeClass('cursor-wait');
        })
        .catch(function(error) {
            alert('Oops! An error occurred: ' + error);
        });
});

$('#btn-sample-markdown').click(function() {
    $('#main-textarea').val(markdown);
    updateHistory();
});

$('#btn-sample-alice-extract').click(function() {
    $('#main-textarea').val(sampleAlice);
    updateHistory();
});

$('#btn-sample-alice-full').click(function() {
    $('body').addClass('cursor-wait');
    axios.get('https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/alice-in-wonderland.txt')
        .then(function(response) {
            $('#main-textarea').val(response.data);
            updateHistory();
            $('body').removeClass('cursor-wait');
        })
        .catch(function(error) {
            alert('Oops! An error occurred: ' + error);
        });
});

$('#btn-sample-quote').click(function() {
    $('#main-textarea').val(`And in the end, the love you take is equal to the love you make`);
    updateHistory();
});

$('#btn-sample-pangrams').click(function() {
    $('#main-textarea').val(samplePangrams);
    updateHistory();
});

$('#btn-sample-boys-names').click(function() {
    $('#main-textarea').val(boysNames);
    updateHistory();
});

$('#btn-sample-girls-names').click(function() {
    $('#main-textarea').val(girlsNames);
    updateHistory();
});

$('#btn-sample-466k-english-words').click(function() {
    if (confirm('This list is VERY large and may take a while to load and render. Do you wish to continue?')) {
        $('body').addClass('cursor-wait');
        axios.get('https://www.adrianparr.com/codepen/466k-english-words.txt')
            .then(function(response) {
                $('#main-textarea').val(response.data);
                updateHistory();
                $('body').removeClass('cursor-wait');
            })
            .catch(function(error) {
                alert('Oops! An error occurred: ' + error);
            });
    } else {
        return;
    }
});

$('#btn-sample-reserved').click(function() {
    $('#main-textarea').val(`;,/?:@&=+$#`);
    updateHistory();
});

$('#btn-sample-unreserved').click(function() {
    $('#main-textarea').val(`-_.!~*'()`);
    updateHistory();
});

$('#btn-sample-az').click(function() {
    $('#main-textarea').val(`abcdefghijklmnopqrstuvwxyz`);
    updateHistory();
});

$('#btn-sample-special-chars').click(function() {
    $('#main-textarea').val(charsWithNamedEntities);
    updateHistory();
});

$('#btn-sample-character-mapping').click(function() {
    $('#main-textarea').val(sampleCharacterMapping);
    updateHistory();
});

$('#btn-sample-emoticons').click(function() {
    $('#main-textarea').val(emoticons);
    updateHistory();
});

$('#btn-sample-phonetic').click(function() {
    $('#main-textarea').val(phoneticAlphabet);
    updateHistory();
});

$('#btn-sample-lorem-ipsum').click(function() {
    $('#main-textarea').val(loremIpsum);
    updateHistory();
});

$('#btn-sample-lorem-ipsum-generated').click(function() {
    const maxNumWords = 181;
    let numWords = prompt("How many words do you want?", '100');
    if (numWords !== undefined && numWords !== '') {
        numWords = parseInt(numWords, 10);
        let loremIpsumWords = '';
        if (parseInt(numWords, 10) <= maxNumWords) {
            loremIpsumWords = HolderIpsum.words(numWords, true);
        } else {
            let remainder = numWords%maxNumWords;
            let multiple = (numWords - remainder) / maxNumWords;
            for (var i=0; i<multiple; i++) {
                loremIpsumWords += HolderIpsum.words(maxNumWords, true);
                if (i < multiple-1) {
                    loremIpsumWords += ' ';
                }
            }
            if (remainder > 0) {
                loremIpsumWords += ' ' + HolderIpsum.words(remainder, true);
            }
        }
        loremIpsumWords = loremIpsumWords.charAt(0).toUpperCase() + loremIpsumWords.slice(1) + '.';
        $('#main-textarea').val(loremIpsumWords);
        updateHistory();
    }
});

$('#btn-sample-number-column-n-n').click(function() {
    let numbersArray = [];
    let startNum = prompt("Starting number?", '1');
    let endNum = prompt("Ending number?", '100');
    if (startNum !== '' && endNum !== '') {
        startNum = parseInt(startNum, 10);
        endNum = parseInt(endNum, 10);
        if (!isNaN(startNum) && !isNaN(endNum)) {
            if (startNum !== endNum) {
                if (startNum < endNum) {
                    for (let i=startNum; i<=endNum; i++) {
                        numbersArray.push(i);
                    }
                } else if (startNum > endNum) {
                    for (let i=startNum; i>=endNum; i--) {
                        numbersArray.push(i);
                    }
                }
                let output = numbersArray.join('\n');
                $('#main-textarea').val(output);
                updateHistory();
            }
        }
    }
});


$('#btn-sample-number-column-01-99').click(function() {
    let numbersArray = [];
    for (let i=1; i<=99; i++) {
        numbersArray.push(_.padStart(i, 2, '0'));
    }
    let output = numbersArray.join('\n');
    $('#main-textarea').val(output);
    updateHistory();
});

$('#btn-sample-number-column-01-999').click(function() {
    let numbersArray = [];
    for (let i=1; i<=999; i++) {
        numbersArray.push(_.padStart(i, 3, '0'));
    }
    let output = numbersArray.join('\n');
    $('#main-textarea').val(output);
    updateHistory();
});

$('#btn-sample-number-column-01-9999').click(function() {
    let numbersArray = [];
    for (let i=1; i<=9999; i++) {
        numbersArray.push(_.padStart(i, 4, '0'));
    }
    let output = numbersArray.join('\n');
    $('#main-textarea').val(output);
    updateHistory();
});

$('#btn-sample-curly-quotes').click(function() {
    $('#main-textarea').val(curlyQuotes);
    updateHistory();
});

$('#btn-sample-ascii-image').click(function() {
    $('#main-textarea').val(ascii);
    updateHistory();
});

$('#btn-sample-diamond-of-bullets').click(function() {
    $('#main-textarea').val(sampleDiamondOfBullets);
    updateHistory();
});

$('#btn-sample-csv-data').click(function() {
    $('#main-textarea').val(csvData);
    updateHistory();
});

$('#btn-sample-tab-delimited-data').click(function() {
    $('#main-textarea').val(tabDelimitedData);
    updateHistory();
});

$('#btn-sample-lined-up-tab-delimited-data').click(function() {
    $('#main-textarea').val(linedUpTabDelimitedData);
    updateHistory();
});

$('#btn-sample-json-formatted').click(function() {
    $('#main-textarea').val(formattedJson);
    updateHistory();
});

$('#btn-sample-json-formatted-2').click(function() {
    $('#main-textarea').val(decodeURIComponent(formattedJson2));
    updateHistory();
});

$('#btn-sample-json-simple-formatted').click(function() {
    $('body').addClass('cursor-wait');
    axios.get('https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/simple-people-data.json')
        .then(function(response) {
            let output = JSON.stringify(response.data, null, 2);
            $('#main-textarea').val(output);
            updateHistory();
            $('body').removeClass('cursor-wait');
        })
        .catch(function(error) {
            alert('Oops! An error occurred: ' + error);
        });
});

$('#btn-sample-json-simple-unformatted').click(function() {
    $('body').addClass('cursor-wait');
    axios.get('https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/simple-people-data.json')
        .then(function(response) {
            let output = JSON.stringify(response.data);
            $('#main-textarea').val(output);
            updateHistory();
            $('body').removeClass('cursor-wait');
        })
        .catch(function(error) {
            alert('Oops! An error occurred: ' + error);
        });
});

$('#btn-sample-json-complex-unformatted').click(function() {
    $('#main-textarea').val(unformattedJson);
    updateHistory();
});

$('#btn-sample-yaml-simple-1').click(function() {
    $('#main-textarea').val(simpleYaml1);
    updateHistory();
});

$('#btn-sample-yaml-simple-2').click(function() {
    $('#main-textarea').val(simpleYaml2);
    updateHistory();
});

$('#btn-sample-yaml-complex').click(function() {
    $('#main-textarea').val(complexYaml);
    updateHistory();
});

$('#btn-sample-regular-array').click(function() {
    $('#main-textarea').val(simpleRegularArray);
    updateHistory();
});

$('#btn-sample-associative-array').click(function() {
    $('#main-textarea').val(simpleAssociativeArray);
    updateHistory();
});

$('#btn-sample-data-string').click(function() {
    $('#main-textarea').val(dataString);
    updateHistory();
});

$('#btn-sample-repeating-data-string').click(function() {
    $('#main-textarea').val(repeatingDataString);
    updateHistory();
});

$('#btn-sample-data-to-be-lined-up').click(function() {
    $('#main-textarea').val(dataToBeLinedUp);
    updateHistory();
});

$('#btn-sample-merge-bottom-into-top').click(function() {
    $('#main-textarea').val(sampleMergeBottomIntoTop);
    updateHistory();
});

$('#btn-sample-uuids-with-duplicates').click(function() {
    $('#main-textarea').val(duplicateUuids);
    updateHistory();
});

$('#btn-sample-indentation-tabs').click(function() {
    $('#main-textarea').val(indentationWithTabs);
    updateHistory();
});

$('#btn-sample-indentation-two-spaces').click(function() {
    $('#main-textarea').val(indentationWithTwoSpaces);
    updateHistory();
});

$('#btn-sample-indentation-four-spaces').click(function() {
    $('#main-textarea').val(indentationWithFourSpaces);
    updateHistory();
});

$('#btn-sample-extract-data').click(function() {
    $('#main-textarea').val(sampleExtractData);
    updateHistory();
});

$('#btn-sample-svg-markup-simple').click(function() {
    $('#main-textarea').val(sampleSvgMarkup);
    updateHistory();
});

$('#btn-sample-svg-markup-complex').click(function() {
    $('body').addClass('cursor-wait');
    axios.get('https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/tiger_copy.svg')
        .then(function(response) {
        $('#main-textarea').val(response.data);
        updateHistory();
        $('body').removeClass('cursor-wait');
    })
        .catch(function(error) {
        alert('Oops! An error occurred: ' + error);
    });
});

$('#btn-sample-date-now').click(function() {
    let newDate = new Date();
    let iso8601 = dateFns.format(newDate, 'YYYY-MM-DDTHH:mm:ss');
    let text = `import { parse, format } from 'date-fns'

Date.now()\t\t\t\t\t\t\t${Date.now()}
new Date().toString()\t\t\t\t\t\t${newDate}
dateFns.parse('${iso8601}')\t\t\t\t${dateFns.parse(iso8601)}
dateFns.format(new Date())\t\t\t\t\t${dateFns.format(newDate)}
dateFns.format(new Date(), 'YYYY-MM-DDTHH:mm:ss.SSSZ')\t\t${dateFns.format(newDate, 'YYYY-MM-DDTHH:mm:ss.SSSZ')}
dateFns.format(new Date(), 'YYYY-MM-DDTHH:mm:ss')\t\t${dateFns.format(newDate, 'YYYY-MM-DDTHH:mm:ss')}
dateFns.format(new Date(), 'dddd Do MMMM YYYY')\t\t\t${dateFns.format(newDate, 'dddd Do MMMM YYYY')}
dateFns.format(new Date(), 'Do MMMM YYYY')\t\t\t${dateFns.format(newDate, 'Do MMMM YYYY')}
dateFns.format(new Date(), 'Do MMM ‘YY')\t\t\t${dateFns.format(newDate, 'Do MMM ‘YY')}
dateFns.format(new Date(), 'MM/DD/YYYY')\t\t\t${dateFns.format(newDate, 'MM/DD/YYYY')}
dateFns.format(new Date(), 'YYYY-MM-DD')\t\t\t${dateFns.format(newDate, 'YYYY-MM-DD')}
dateFns.format(new Date(), 'HH:mm')\t\t\t\t${dateFns.format(newDate, 'HH:mm')}
dateFns.format(new Date(), 'ddd HH:mm')\t\t\t\t${dateFns.format(newDate, 'ddd HH:mm')}
dateFns.format(new Date(), 'HH:mm:ss')\t\t\t\t${dateFns.format(newDate, 'HH:mm:ss')}
dateFns.format(new Date(), 'h:mma')\t\t\t\t${dateFns.format(newDate, 'h:mma')}
dateFns.format(new Date(), 'HH[h] mm[m] ss[s] SSS[ms]')\t\t${dateFns.format(newDate, 'HH[h] mm[m] ss[s] SSS[ms]')}
dateFns.format(new Date(), 'M')\t\t\t\t\t${dateFns.format(newDate, 'M')}
dateFns.format(new Date(), 'Mo')\t\t\t\t${dateFns.format(newDate, 'Mo')}
dateFns.format(new Date(), 'MM')\t\t\t\t${dateFns.format(newDate, 'MM')}
dateFns.format(new Date(), 'MMM')\t\t\t\t${dateFns.format(newDate, 'MMM')}
dateFns.format(new Date(), 'MMMM')\t\t\t\t${dateFns.format(newDate, 'MMMM')}
dateFns.format(new Date(), 'Q')\t\t\t\t\t${dateFns.format(newDate, 'Q')}
dateFns.format(new Date(), 'Qo')\t\t\t\t${dateFns.format(newDate, 'Qo')}
dateFns.format(new Date(), 'D')\t\t\t\t\t${dateFns.format(newDate, 'D')}
dateFns.format(new Date(), 'Do')\t\t\t\t${dateFns.format(newDate, 'Do')}
dateFns.format(new Date(), 'DD')\t\t\t\t${dateFns.format(newDate, 'DD')}
dateFns.format(new Date(), 'DDD')\t\t\t\t${dateFns.format(newDate, 'DDD')}
dateFns.format(new Date(), 'DDDo')\t\t\t\t${dateFns.format(newDate, 'DDDo')}
dateFns.format(new Date(), 'DDDD')\t\t\t\t${dateFns.format(newDate, 'DDDD')}
dateFns.format(new Date(), 'd')\t\t\t\t\t${dateFns.format(newDate, 'd')}
dateFns.format(new Date(), 'do')\t\t\t\t${dateFns.format(newDate, 'do')}
dateFns.format(new Date(), 'dd')\t\t\t\t${dateFns.format(newDate, 'dd')}
dateFns.format(new Date(), 'ddd')\t\t\t\t${dateFns.format(newDate, 'ddd')}
dateFns.format(new Date(), 'dddd')\t\t\t\t${dateFns.format(newDate, 'dddd')}
dateFns.format(new Date(), 'E')\t\t\t\t\t${dateFns.format(newDate, 'E')}
dateFns.format(new Date(), 'W')\t\t\t\t\t${dateFns.format(newDate, 'W')}
dateFns.format(new Date(), 'Wo')\t\t\t\t${dateFns.format(newDate, 'Wo')}
dateFns.format(new Date(), 'WW')\t\t\t\t${dateFns.format(newDate, 'WW')}
dateFns.format(new Date(), 'YY')\t\t\t\t${dateFns.format(newDate, 'YY')}
dateFns.format(new Date(), 'YYYY')\t\t\t\t${dateFns.format(newDate, 'YYYY')}
dateFns.format(new Date(), 'GG')\t\t\t\t${dateFns.format(newDate, 'GG')}
dateFns.format(new Date(), 'GGGG')\t\t\t\t${dateFns.format(newDate, 'GGGG')}
dateFns.format(new Date(), 'A')\t\t\t\t\t${dateFns.format(newDate, 'A')}
dateFns.format(new Date(), 'a')\t\t\t\t\t${dateFns.format(newDate, 'a')}
dateFns.format(new Date(), 'aa')\t\t\t\t${dateFns.format(newDate, 'aa')}
dateFns.format(new Date(), 'H')\t\t\t\t\t${dateFns.format(newDate, 'H')}
dateFns.format(new Date(), 'HH')\t\t\t\t${dateFns.format(newDate, 'HH')}
dateFns.format(new Date(), 'h')\t\t\t\t\t${dateFns.format(newDate, 'h')}
dateFns.format(new Date(), 'hh')\t\t\t\t${dateFns.format(newDate, 'hh')}
dateFns.format(new Date(), 'm')\t\t\t\t\t${dateFns.format(newDate, 'm')}
dateFns.format(new Date(), 'mm')\t\t\t\t${dateFns.format(newDate, 'mm')}
dateFns.format(new Date(), 's')\t\t\t\t\t${dateFns.format(newDate, 's')}
dateFns.format(new Date(), 'ss')\t\t\t\t${dateFns.format(newDate, 'ss')}
dateFns.format(new Date(), 'S')\t\t\t\t\t${dateFns.format(newDate, 'S')}
dateFns.format(new Date(), 'SS')\t\t\t\t${dateFns.format(newDate, 'SS')}
dateFns.format(new Date(), 'SSS')\t\t\t\t${dateFns.format(newDate, 'SSS')}
dateFns.format(new Date(), 'Z')\t\t\t\t\t${dateFns.format(newDate, 'Z')}
dateFns.format(new Date(), 'ZZ')\t\t\t\t${dateFns.format(newDate, 'ZZ')}
dateFns.format(new Date(), 'X')\t\t\t\t\t${dateFns.format(newDate, 'X')}
dateFns.format(new Date(), 'x')\t\t\t\t\t${dateFns.format(newDate, 'x')}
`;
    $('#main-textarea').val(text);
    updateHistory();
});

$('#btn-sample-geometric-shapes').click(function() {
    $('#main-textarea').val(sampleGeometricShapes);
    updateHistory();
});

$('#btn-sample-arrow-symbols').click(function() {
    $('#main-textarea').val(sampleArrowSymbols);
    updateHistory();
});

$('#btn-sample-heart-symbols').click(function() {
    $('#main-textarea').val(sampleHeartSymbols);
    updateHistory();
});

$('#btn-sample-special-symbols').click(function() {
    $('#main-textarea').val(sampleSpecialSymbols);
    updateHistory();
});

$('#btn-sample-flower-symbols').click(function() {
    $('#main-textarea').val(sampleFlowerSymbols);
    updateHistory();
});

$('#btn-sample-quotation-marks').click(function() {
    $('#main-textarea').val(sampleQuotationMarks);
    updateHistory();
});

$('#btn-sample-star-symbols').click(function() {
    $('#main-textarea').val(sampleStarSymbols);
    updateHistory();
});

$('#btn-sample-emoji-symbols').click(function() {
    $('#main-textarea').val(sampleEmojiSymbols);
    updateHistory();
});

$('#btn-sample-zodiac-symbols').click(function() {
    $('#main-textarea').val(sampleZodiacSymbols);
    updateHistory();
});

$('#btn-sample-currency-symbols').click(function() {
    $('#main-textarea').val(sampleCurrencySymbols);
    updateHistory();
});

$('#btn-sample-greek-symbols').click(function() {
    $('#main-textarea').val(sampleGreekSymbols);
    updateHistory();
});

$('#btn-sample-roman-numerals').click(function() {
    $('#main-textarea').val(sampleRomanNumerals);
    updateHistory();
});

$('#btn-sample-suits-of-the-cards').click(function() {
    $('#main-textarea').val(sampleSuitsOfTheCards);
    updateHistory();
});

$('#btn-sample-punctuation-marks').click(function() {
    $('#main-textarea').val(samplePunctuationMarks);
    updateHistory();
});

// =========================================================
// Random content fieldset
// =========================================================

$('#btn-random-passwords-length-8').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push('$' + chance.string({ length: 6, pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' }) + '!');
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-passwords-length-16').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push('$' + chance.string({ length: 14, pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' }) + '!');
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-passwords-length-24').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push('$' + chance.string({ length: 22, pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' }) + '!');
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-passwords-length-32').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push('$' + chance.string({ length: 30, pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' }) + '!');
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-passwords-length-64').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push('$' + chance.string({ length: 62, pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' }) + '!');
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-uuids').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(uuidv4());
    }
    let uuidsStr = array.join('\n');
    $('#main-textarea').val(uuidsStr);
    updateHistory();
});

$('#btn-random-booleans').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.bool());
    }
    let booleanStr = array.join('\n');
    $('#main-textarea').val(booleanStr);
    updateHistory();
});

$('#btn-random-characters-all').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.character());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-characters-lowercase').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.character({ casing: 'lower', alpha: true }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-characters-uppercase').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.character({ casing: 'upper', alpha: true }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-characters-ABCD').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.character({ pool: 'ABCD' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-floating').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.floating());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-floating-positive').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.floating({ min: 0, max: 1000000, fixed: 1 }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-integers').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.integer());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-integers-positive').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.integer({ min: 1000000000000000, max: 9999999999999999 }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-integers-plus-minus-100').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.integer({ min: -100, max: 100 }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-integers-0-to-1000').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.integer({ min: 0, max: 1000 }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-integers-0-to-100').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.integer({ min: 0, max: 100 }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-integers-0-to-10').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.integer({ min: 0, max: 10 }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-integers-0-to-1').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.integer({ min: 0, max: 1 }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-strings').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.string());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-strings-length-8').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.string({ length: 8, pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()[]' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-strings-length-16').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.string({ length: 16, pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()[]' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-strings-length-32').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.string({ length: 32, pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()[]' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-strings-length-64').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.string({ length: 64, pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()[]' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-strings-length-128').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.string({ length: 128, pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()[]' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-strings-uppercase').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.string({ length: 128, pool: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-strings-lowercase').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.string({ length: 128, pool: 'abcdefghijklmnopqrstuvwxyz' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-strings-digits').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.string({ length: 128, pool: '0123456789' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-strings-slashes').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.string({ length: 128, pool: '╱╲' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-paragraphs').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.paragraph());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-sentences').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.sentence());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-sentences-5-words').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.sentence({ words: 5 }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-sentences-10-words').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.sentence({ words: 10 }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-sentences-15-words').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.sentence({ words: 15 }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-sentences-20-words').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.sentence({ words: 20 }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-syllables').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.syllable());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-words').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.word({ syllables: 3 }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-dates-last-10-years').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    let maxYear = parseInt(dateFns.format(new Date(), 'YYYY'), 10) - 1;
    let minYear = maxYear - 10;
    let randomYear;
    for (let i=0; i<numItems; i++) {
        randomYear = chance.year({ min: minYear, max: maxYear });
        array.push(chance.birthday({ year: randomYear }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-dates-last-100-years').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    let maxYear = parseInt(dateFns.format(new Date(), 'YYYY'), 10) - 1;
    let minYear = maxYear - 100;
    let randomYear;
    for (let i=0; i<numItems; i++) {
        randomYear = chance.year({ min: minYear, max: maxYear });
        array.push(chance.birthday({ year: randomYear }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-dates-formatted').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.birthday({ string: true, american: false }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-names-first').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.first());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-names-last').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.last());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-names-first-last').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.first() + ' ' + chance.last());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-names-male').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.name({ gender: 'male' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-names-female').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.name({ gender: 'female' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

// Doesn't appear to work
// $('#btn-random-animals').click(function() {
//     let array = [];
//     let numItems = parseInt($('#num-random-items-select').val(), 10);
//     for (let i=0; i<numItems; i++) {
//         array.push(chance.animal());
//     }
//     let charsStr = array.join('\n');
//     $('#main-textarea').val(charsStr);
//     updateHistory();
// });

$('#btn-random-color-hex').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.color({format: 'hex'}));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});
  
$('#btn-random-color-rgb').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.color({format: 'rgb'}));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

// $('#btn-random-company').click(function() {
//     let array = [];
//     let numItems = parseInt($('#num-random-items-select').val(), 10);
//     for (let i=0; i<numItems; i++) {
//         array.push(chance.company());
//     }
//     let charsStr = array.join('\n');
//     $('#main-textarea').val(charsStr);
//     updateHistory();
// });

$('#btn-random-domain').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.domain());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-email').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.email());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-email-domain-com').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.email({domain: 'domain.com'}));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-ip-address').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.ip());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-ipv6').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.ipv6());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

// $('#btn-random-profession').click(function() {
//     let array = [];
//     let numItems = parseInt($('#num-random-items-select').val(), 10);
//     for (let i=0; i<numItems; i++) {
//         array.push(chance.profession());
//     }
//     let charsStr = array.join('\n');
//     $('#main-textarea').val(charsStr);
//     updateHistory();
// });

$('#btn-random-url').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.url());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-address').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.address());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-city-world').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    let city;
    for (let i=0; i<numItems; i++) {
        city = chance.pickset(citiesWorld, 1);
        array.push(city);
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-city-uk').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    let city;
    for (let i=0; i<numItems; i++) {
        city = chance.pickset(citiesUk, 1);
        array.push(city);
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-coordinates').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.coordinates());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-country').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.country({ full: true }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-phone').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.phone());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-phone-uk').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.phone({ country: 'uk' }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-phone-uk-mobile').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.phone({ country: 'uk', mobile: true }));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

// $('#btn-random-postcode').click(function() {
//     let array = [];
//     let numItems = parseInt($('#num-random-items-select').val(), 10);
//     for (let i=0; i<numItems; i++) {
//         array.push(chance.postcode());
//     }
//     let charsStr = array.join('\n');
//     $('#main-textarea').val(charsStr);
//     updateHistory();
// });

$('#btn-random-timestamp').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.timestamp());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-weekday').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.weekday());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-credit-card-visa').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.cc({type: 'Visa'}));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-dollar').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.dollar({max: 299}));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-euro').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.euro({max: 299}));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-coin-toss').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.pickset(['Heads', 'Tails'], 1));
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-dice-6').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.d6());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

$('#btn-random-hash').click(function() {
    let array = [];
    let numItems = parseInt($('#num-random-items-select').val(), 10);
    for (let i=0; i<numItems; i++) {
        array.push(chance.hash());
    }
    let charsStr = array.join('\n');
    $('#main-textarea').val(charsStr);
    updateHistory();
});

// =========================================================
// Count fieldset
// =========================================================

$('#btn-count-chars').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let count = input.length;
    alert(count.toLocaleString() + ' characters');
});

$('#btn-count-chars-alphanumeric').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let count = v.countWhere(input, v.isAlpha);
    alert(count.toLocaleString() + ' characters');
});

$('#btn-count-words').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.replace(/\r?\n|\r/g, ' ');
    input = input.replace(/\t/g, ' ');
    let array = input.split(' ');
    array = array.filter(Boolean);
    let count = array.length;
    alert(count.toLocaleString() + ' words');
});

$('#btn-count-words-alphanumeric').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let count = v.countWords(input);
    alert(count.toLocaleString() + ' words');
});

$('#btn-count-lines').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let count = input.split(/\r?\n|\r/).length;
    alert(count.toLocaleString() + ' lines');
});

$('#btn-count-lines-empty').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    let linesAllCount = array.length;
    let trimmedArray = array.filter(function(entry) {
        return entry.trim() != '';
    });
    let linesNonEmptyCount = trimmedArray.length;
    let linesEmptyCount = linesAllCount - linesNonEmptyCount;
    let percent = linesEmptyCount / linesAllCount;
    let percentFormatted = Math.round(percent * 100);
    alert(linesEmptyCount.toLocaleString() + ' empty lines ('+percentFormatted+'%)');
});

$('#btn-count-lines-non-empty').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    let linesAllCount = array.length;
    let trimmedArray = array.filter(function(entry) {
        return entry.trim() != '';
    });
    let linesNonEmptyCount = trimmedArray.length;
    let percent = linesNonEmptyCount / linesAllCount;
    let percentFormatted = Math.round(percent * 100);
    alert(linesNonEmptyCount.toLocaleString() + ' non-empty lines ('+percentFormatted+'%)');
});

$('#btn-count-average-per-line').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let numChars = input.length;
    let numLines = input.split(/\r?\n|\r/).length
    let averageCharsPerLine = Math.round(numChars / numLines);
    alert(averageCharsPerLine.toLocaleString() + ' characters per line (average)');
});

$('#btn-count-longest-line').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let longest = 0;
    for (let item of array) {
        if (item.length > longest) {
            longest = item.length;
        }
    }
    alert('Num chars on longest line: ' + longest);
});

$('#btn-count-selected-chars').click(function() {
    let $textarea = $('#main-textarea');
    let input = getSelectionText();
    let count = input.length;
    alert(count + ' characters in selected text');
});

$('#btn-count-selected-words').click(function() {
    let input = getSelectionText();
    input = input.replace(/\r?\n|\r/g, ' ');
    input = input.replace(/\t/g, ' ');
    let array = input.split(' ');
    array = array.filter(Boolean);
    let count = array.length;
    alert(count.toLocaleString() + ' words in selected text');
});

$('#btn-count-filesize').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    // if ($('#myCheckbox').prop('checked')) {
    //     input = input.replace(/\s/g, '');
    // }
    let bytes = countByteSize(input);
    let formattedBytes = formatByteSize(bytes);
    alert(`${formattedBytes} (${bytes.toLocaleString()} bytes)`);
});

$('#btn-count-word-frequency').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let textArray = [],
        words = {},
        sortedArray = [],
        output = 'Word\tCount\n';
    input = input.toLowerCase();
    input = input.replace('.', ' ');
    input = input.replace(/[\n\r]/g, ' ');
    input = input.replace(/[^0-9a-zA-Z -]/g, '');
    input = input.replace(/--/g, ' ');
    textArray = input.split(' ');
    textArray = textArray.filter((n) => { return n != '' });
    words = textArray.reduce(function(obj, item) {
        if (!obj[item]) {
            obj[item] = 0;
        }
        obj[item]++;
        return obj;
    }, {});
    for (var word in words) {
        sortedArray.push(
            {'word': word,
             'count': words[word]
            }
        );
    }
    sortedArray.sort(function(a, b) {
        return b.count - a.count;
    });
    for (var i = 0; i < sortedArray.length; i++) {
        output += sortedArray[i].word + '\t' + sortedArray[i].count.toString() + '\n';
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-count-uuids').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let regExp = new RegExp(/[\da-zA-Z]{8}-([\da-zA-Z]{4}-){3}[\da-zA-Z]{12}/, 'gim');
    let foundArray = input.match(regExp);
    let count = foundArray.length;
    alert(count.toLocaleString() + ' UUIDs');
});

$('#btn-count-array-length').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    try {
      let array = eval(input)
      alert('Array length: ' + array.length);
    } catch {
      alert('Unable to evaluate the array. Please check the syntax.')
    } 
});

$('#btn-count-associative-array-length').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    try {
      let associativeArray = eval('(' + input + ')')
      alert('Associative array length: ' + Object.keys(associativeArray).length);
    } catch {
      alert('Unable to evaluate the associative array. Please check the syntax.')
    } 
});

$('#substring-frequency-value').on('change input', function() {
    if ($(this).val() === '') {
        $('#btn-count-substring-frequency').prop('disabled', true);
    } else {
        $('#btn-count-substring-frequency').prop('disabled', false);
    }
});

$('#btn-count-substring-frequency').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let count = v.countSubstrings(input, $('#substring-frequency-value').val());
    alert(count.toLocaleString() + ' occurrences of the string \''+$('#substring-frequency-value').val()+'\'');
});



// =========================================================
// Remove fieldset
// =========================================================

$('#btn-remove-linebreaks').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/\r?\n|\r/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-linebreaks-keep-empty').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    array = array.map(function(line) {
        if (line.trim() === '') {
            return '<emptyline>';
        } else {
            return line;
        }
    });
    input = array.join('\n');
    input = input.replace(/\n/g, ' ');
    input = input.replace(/<emptyline>/g, '\n\n');
    let output = input;
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-whitespace-all').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/\s/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-trim-each-line').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return _.trim(line);
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-whitespace-from-start').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return _.trimStart(line);
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-whitespace-from-end').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return _.trimEnd(line);
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-spaces-multiple').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/  +/g, ' ').trim();
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-spaces-all').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/ /g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-non-alpha-chars').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.replace(/ /g,'');
    input = input.replace(/[^a-z0-9\s]/gi, '');
    let output = input.toLowerCase();
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-az-lowercase').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/[a-z]/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-az-uppercase').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/[A-Z]/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-numbers').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/[0-9]/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-special-chars').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/[^\na-zA-Z0-9 ]/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-vowels').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/[aeiouAEIOU]/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-html-markup').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = $(input).text();
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-html-inline-styles').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let regexp = new RegExp(/<[/]?(span|o:p|font)[^>]*>|(class|style)="[^>]*"||| |(width)="([0-9]+)"/, 'g');
    let output = input.replace(regexp, '');
    output = output.replace(/ >/g, '>');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-empty-lines-all').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    array = array.filter(entry => entry.trim() != '');
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-empty-lines-top-bottom').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let startIndex = 0,
        endIndex = 0;
    for (let i=0; i<array.length; i++) {
        if (array[i].trim() != '') {
            startIndex = i;
            break;
        }
    }
    for (let i=array.length-1; i>=0; i--) {
        if (array[i].trim() != '') {
            endIndex = i;
            break;
        }
    }
    array = array.slice(startIndex, endIndex+1);
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-empty-lines-multiple').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/^(\n{2,})/gm, '\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-lines-that-only-contain-special-chars').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        if (_.trim(line) === '') {
            return line;
        } else {
            if (_.trim(line.replace(/[^\na-zA-Z0-9 ]/g, '')) !== '') {
                return line;
            }
        }
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-uuids').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let regExp = new RegExp(/[\da-zA-Z]{8}-([\da-zA-Z]{4}-){3}[\da-zA-Z]{12}/, 'gim');
    let output = input.replace(regExp, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-tabs-all').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/\t/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-tabs-multiple').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/\t\t+/g, '\t').trim();
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-duplicate-words').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(' ');
    array = _.compact(array);
    array = _.uniq(array);
    let output = array.join(' ');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-duplicate-lines').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    array = _.compact(array);
    array = _.uniq(array);
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-random-chars').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('');
    if (array.length > 1) {
        array = array.filter(function (item, index) {
            if (Math.random() < 0.5) {
                return true;
            } else {
                if (item === '\n') {
                    return true;
                } else {
                    return false;
                }
            }
        });
    }
    let output = array.join('');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-random-words').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(' ');
    if (array.length > 1) {
        array = array.filter(function (item, index) {
            if (Math.random() < 0.5) {
                return true;
            } else {
                return false;
            }
        });
    }
    let output = array.join(' ');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-random-lines').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    if (array.length > 1) {
        array = array.filter(function (item, index) {
            if (Math.random() < 0.5) {
                return true;
            } else {
                return false;
            }
        });
    }
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-alternate-lines-odd').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    if (array.length > 1) {
        array = array.filter(function (item, index) {
            return isOdd(index);
        });
    }
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-alternate-lines-even').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    if (array.length > 1) {
        array = array.filter(function (item, index) {
            return isEven(index);
        });
    }
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-reverse-line-feed').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.toUnicode();
    input = input.replace(/\\u008D/g, '');
    let output = input.replace(/\\u([\d\w]{4})/gi, function (match, grp) {
        return String.fromCharCode(parseInt(grp, 16));
    });
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-console-logs').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/console.log.*/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-javascript-comments').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-html-comments').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/<!--(.|\s)*?-->/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-head-tag').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/<head\b[^<]*(?:(?!<\/head>)<[^<]*)*<\/head>/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-body-tag').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/<body\b[^<]*(?:(?!<\/body>)<[^<]*)*<\/body>/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-script-tags').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-style-tags').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/g, '');
    $textarea.val(output);
    updateHistory();
});

$('#lines-that-value').on('change input', function() {
    if ($(this).val() === '') {
        $('#btn-lines-that').prop('disabled', true);
    } else {
        $('#btn-lines-that').prop('disabled', false);
    }
});

$('#btn-lines-that').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let linesThatValue = $('#lines-that-value').val();
    switch($('#select-lines-that').val()) {
        case 'match-exactly':
            array = array.filter(function (line, index) {
                return line !== linesThatValue;
            });
            break; 
        case 'start-with':
            array = array.filter(function (line, index) {
                return !_.startsWith(line, linesThatValue);
            });
            break;
        case 'contain':
            array = array.filter(function (line, index) {
                return !v.includes(line, linesThatValue);
            });
            break;
        case 'end-with':
            array = array.filter(function (line, index) {
                return !_.endsWith(line, linesThatValue);
            });
            break;
        case 'dont-start-with':
            array = array.filter(function (line, index) {
                return _.startsWith(line, linesThatValue);
            });
            break;
        case 'dont-contain':
            array = array.filter(function (line, index) {
                return v.includes(line, linesThatValue);
            });
            break;
        case 'dont-end-with':
            array = array.filter(function (line, index) {
                return _.endsWith(line, linesThatValue);
            });
            break;
        case 'dont-match-exactly':
            array = array.filter(function (line, index) {
                return line === linesThatValue;
            });
            break;
        default:
            break;
    }
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#instance-of-text-value').on('change input', function() {
    if ($(this).val() === '') {
        $('#btn-instance-of').prop('disabled', true);
    } else {
        $('#btn-instance-of').prop('disabled', false);
    }
});

$('#btn-instance-of').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let searchText = $('#instance-of-text-value').val();
    let searchTextLength = searchText.length;
    array = array.map(function(line) {
        if (v.includes(line, searchText)) {
            var index = 0;
            switch($('#select-text-on-each-line-position').val()) {
                case 'first':
                    index = line.indexOf(searchText);
                    break;
                case 'last':
                    index = line.lastIndexOf(searchText);
                    break;
                default:
                    break;
            }
            switch($('#select-text-on-each-line').val()) {
                case 'before':
                    return line.substring(index, line.length);
                    break;
                case 'before-and-including':
                    return line.substring(index+searchTextLength, line.length);
                    break;
                case 'including-and-after':
                    return line.substring(0, index);
                    break;
                case 'after':
                    return line.substring(0, index+searchTextLength);
                    break;
                default:
                    return line;
                    break;  
            }
        } else {
            return line;
        }
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#input-remove-chars-from-nth-position').hide();
$('#remove-chars-from-position-from-the-nth-position').hide();
$('#select-remove-chars-from-nth-position-beginning-end').hide();

$('#input-remove-chars-from-nth-position').on('blur', function() {
    $(this).val( $(this).val().trim() );
});

$('#select-remove-chars-from-position').change(function() {
    if ($(this).val() === 'nth-position') {
        $('#input-remove-chars-from-nth-position').show();
        $('#remove-chars-from-position-from-the-nth-position').show();
        $('#select-remove-chars-from-nth-position-beginning-end').show();
    } else {
        $('#input-remove-chars-from-nth-position').hide();
        $('#remove-chars-from-position-from-the-nth-position').hide();
        $('#select-remove-chars-from-nth-position-beginning-end').hide();
    }
});

$('#btn-remove-chars-from-position').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let lineArray = input.split(/\r?\n|\r/);
    let numChars = $('#select-remove-chars-from-position-num-chars').val();
    numChars = parseInt(numChars, 10);
    let fromPosition = $('#select-remove-chars-from-position').val();
    if (fromPosition === 'beginning') {
        lineArray =  lineArray.map(function(line) {
            return line.substring(numChars);
        });
    } else if (fromPosition === 'end') {
        lineArray =  lineArray.map(function(line) {
            let lineLength = line.length;
            return line.substring(0, lineLength-numChars);
        });
    } else {
        let nthPos = $('#input-remove-chars-from-nth-position').val();
        let fromBeginningEnd = $('#select-remove-chars-from-nth-position-beginning-end').val();
        nthPos = parseInt(nthPos, 10);
        if (!isNaN(nthPos)) {
            let lineLength, part1, part2;
            lineArray =  lineArray.map(function(line) {
                if (fromBeginningEnd === 'beginning') {
                    lineLength = line.length;
                    part1 = line.substring(0, nthPos);
                    part2 = line.substring(nthPos + numChars, lineLength);
                    return (part1 + part2);
                } else if (fromBeginningEnd === 'end') {
                    lineLength = line.length;
                    part1 = line.substring(0, lineLength - nthPos);
                    part2 = line.substring(lineLength - nthPos + numChars, lineLength);
                    return (part1 + part2);
                }
            });
        }
    }
    let output = lineArray.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-remove-lines-by-length').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let lineArray = input.split(/\r?\n|\r/);
    let type = $('#select-remove-lines-by-length-type').val();
    let numChars = $('#select-remove-lines-by-length-num-chars').val();
    numChars = parseInt(numChars, 10);
    switch(type) {
        case 'less-than':
            lineArray = lineArray.filter(function(line) {
                if (line.length >= numChars) {
                    return true;
                }
            });
            break;
        case 'less-than-or-equal-to':
            lineArray = lineArray.filter(function(line) {
                if (line.length > numChars) {
                    return true;
                }
            });
            break;
            break;
        case 'equal-to':
            lineArray = lineArray.filter(function(line) {
                if (line.length !== numChars) {
                    return true;
                }
            });
            break;
        case 'not-equal-to':
            lineArray = lineArray.filter(function(line) {
                if (line.length === numChars) {
                    return true;
                }
            });
            break;
        case 'more-than-or-equal-to':
            lineArray = lineArray.filter(function(line) {
                if (line.length < numChars) {
                    return true;
                }
            });
            break;
        case 'more-than':
            lineArray = lineArray.filter(function(line) {
                if (line.length <= numChars) {
                    return true;
                }
            });
            break;
        default:
            break;  
    }
    let output = lineArray.join('\n');
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// Replace fieldset
// =========================================================

$('#replace-1-other, #replace-2-other').hide();

$('#select-replace-1').change(function() {
    if ($(this).val() === 'other') {
        $('#replace-1-other').show();
    } else {
        $('#replace-1-other').hide();
    }
});

$('#select-replace-2').change(function() {
    if ($(this).val() === 'other') {
        $('#replace-2-other').show();
    } else {
        $('#replace-2-other').hide();
    }
});

$('#btn-replace').click(function() {
    let output = '',
        array = [];
    
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    
    let replace1 = '';
    switch($('#select-replace-1').val()) {
        case 'linebreaks':
            array = input.split(/\r?\n|\r/);
            replace1 = '\n\r';
            break;
        case 'tabs':
            array = input.split('\t');
            replace1 = '\t';
            break;
        case 'two-tabs':
            array = input.split('\t\t');
            replace1 = '\t\t';
            break;
        case 'spaces':
            array = input.split(' ');
            replace1 = ' ';
            break;
        case 'two-spaces':
            array = input.split('  ');
            replace1 = '  ';
            break;
        case 'four-spaces':
            array = input.split('    ');
            replace1 = '    ';
            break;
        case 'hyphen':
            array = input.split('-');
            replace1 = '-';
            break;
        case 'underscore':
            array = input.split('_');
            replace1 = '_';
            break;
        case 'commas':
            array = input.split(',');
            replace1 = ',';
            break;
        case 'commas-space':
            array = input.split(', ');
            replace1 = ', ';
            break;
        case 'full-stops':
            array = input.split('.');
            replace1 = '.';
            break;
        case 'full-stop-space':
            array = input.split('. ');
            replace1 = '. ';
            break;
        case 'colon':
            array = input.split(':');
            replace1 = ':';
            break;
        case 'semicolon':
            array = input.split(';');
            replace1 = ';';
            break;
        case 'single-quotes':
            array = input.split('\'');
            replace1 = '\'';
            break;
        case 'double-quotes':
            array = input.split('"');
            replace1 = '"';
            break;
        case 'backticks':
            array = input.split('``');
            replace1 = '`';
            break;
        case 'array-single':
            array = input.split(', ');
            replace1 = 'array-single';
            break;
        case 'array-double':
            array = input.split(', ');
            replace1 = 'array-double';
            break;
        case 'pipe':
            array = input.split('|');
            replace1 = '|';
            break;
        case 'between-each-char':
            array = input.split('');
            replace1 = '';
            break;
        case 'other':
            array = input.split($('#replace-1-other').val());
            replace1 = $('#replace-1-other').val();
            break;
        default:
            break;
    }
    
    let replace2 = '';
    switch($('#select-replace-2').val()) {
        case 'linebreaks':
            replace2 = '\n';
            break;
        case 'tabs':
            replace2 = '\t';
            break;
        case 'two-tabs':
            replace2 = '\t\t';
            break;
        case 'spaces':
            replace2 = ' ';
            break;
        case 'two-spaces':
            replace2 = '  ';
            break;
        case 'four-spaces':
            replace2 = '    ';
            break;
        case 'hyphen':
            replace2 = '-';
            break;
        case 'underscore':
            replace2 = '_';
            break;
        case 'commas':
            replace2 = ',';
            break;
        case 'commas-space':
            replace2 = ', ';
            break;
        case 'full-stops':
            replace2 = '.';
            break;
        case 'full-stop-space':
            replace2 = '. ';
            break;
        case 'full-stop-linebreak':
            replace2 = '.\n';
            break;
        case 'colon':
            replace2 = ':';
            break;
        case 'semicolon':
            replace2 = ';';
            break;
        case 'single-quotes':
            replace2 = '\'';
            break;
        case 'double-quotes':
            replace2 = '"';
            break;
        case 'backticks':
            replace2 = '`';
            break;
        case 'array-single':
            replace2 = 'array-single';
            break;
        case 'array-double':
            replace2 = 'array-double';
            break;
        case 'pipe':
            replace2 = '|';
            break;
        case 'nothing':
            replace2 = '';
            break;
        case 'other':
            replace2 = $('#replace-2-other').val();
            break;
        default:
            break;
    }
    
    if (replace1 === 'array-single' || replace1 === 'array-double') {
        input = _.trim(input);
        if (input.charAt(0) === '[') {
            input = removeFirstChar(input);
        }
        if (input.charAt(input.length-1) === ']') {
            input = removeLastChar(input);
        }
        array = input.split(', ');
        array =  array.map(function(item) {
            item = removeFirstChar(item);
            item = removeLastChar(item);
            return item;
        });
    } else {
        let regExp1 = new RegExp(replace1, 'g');
    }
    
    if (replace2 === 'array-single' || replace2 === 'array-double') {
        output += '[';
        let quoteChar;
        if (replace2 === 'array-single') {
            quoteChar = '\'';
        } else if (replace2 === 'array-double') {
            quoteChar = '"';
        }
        array = array.map(function(char) {
            return quoteChar + char + quoteChar;
        });
        output += array.join(', ');
        output += ']';
    } else {
        output = array.join(replace2);
    }
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// Replace fieldset
// =========================================================

$('#btn-split-on-string').click(function() {
    let $textarea = $('#main-textarea');
    let splitStr = $('#split-on-string').val();
    let input = $textarea.val();
    input = input.replace(/\r?\n|\r/g, '');
    let re = new RegExp(splitStr, 'g');
    input = input.replace(re, '\n'+splitStr);
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line, index) {
        return _.trim(line);
    });
    array = array.filter(function(line) {
        if (line !== undefined && line.length > 0) {
            return true;
        }
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// Case fieldset
// =========================================================

$('#btn-case-invert').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array =  input.split('').map(function(char) {
        let tempChar = char.toUpperCase()
        if (char === tempChar) {
            return char.toLowerCase();
        } else {
            return char.toUpperCase();
        }
    });
    let output = array.join('');
    $textarea.val(output);
    updateHistory();
});

$('#btn-case-uppercase').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.toUpperCase();
    $textarea.val(output);
    updateHistory();
});

$('#btn-case-lowercase').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.toLowerCase();
    $textarea.val(output);
    updateHistory();
});

$('#btn-case-titlecase-words').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.toLowerCase();
    let array = input.split(' ');
    array = array.map(function(word) {
        return (word.charAt(0).toUpperCase() + word.slice(1));
    });
    let output = array.join(' ');
    $textarea.val(output);
    updateHistory();
});

$('#btn-case-titlecase-lines').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.toLowerCase();
    let array = input.split('\n');
    array = array.map(function(line) {
        return line.charAt(0).toUpperCase() + line.slice(1);
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-case-random').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array =  input.split('').map(function(char) {
        if(Math.random() < 0.5) {
            return char.toLowerCase();
        } else {
            return char.toUpperCase();
        }
    });
    let output = array.join('');
    $textarea.val(output);
    updateHistory();
});

$('#btn-case-alternate').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array =  input.split('').map(function(char, index) {
        if(isEven(index)) {
            return char.toUpperCase();
        } else {
            return char.toLowerCase();
        }
    });
    let output = array.join('');
    $textarea.val(output);
    updateHistory();
});

$('#btn-case-uppercase-first-letter-each-line').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let lineArray = input.split(/\r?\n|\r/);
    lineArray = lineArray.map(function(line) {
      return line.charAt(0).toUpperCase() + line.slice(1);
    });
    let output = lineArray.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-case-lowercase-first-letter-each-line').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let lineArray = input.split(/\r?\n|\r/);
    lineArray = lineArray.map(function(line) {
      return line.charAt(0).toLowerCase() + line.slice(1);
    });
    let output = lineArray.join('\n');
    $textarea.val(output);
    updateHistory();
});


// =========================================================
// Modify fieldset
// =========================================================

$('#btn-modify-leetspeak').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.replace(/[a-z]/g,function f(a){return "4BCD3F6H1JKLMN0PQR57"[parseInt(a, 36)-10] || a.replace(/[a-t]/gi,f)});
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-reverse-chars').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.split('').reverse().join('');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-scramble-chars').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('');
    array = array.sort(function() {return 0.5 - Math.random()});
    let output = array.join('');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-order-chars').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('');
    array =  array.map(function(char) {
        return char.charCodeAt(0);
    });
    array = array.sort(function(a, b) {
        return a - b;
    });
    array = array.map(function(charCode) {
        return String.fromCharCode(charCode);
    });
    let output = array.join('');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-reverse-words').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.split(' ').reverse().join(' ');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-scramble-words').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(' ');
    array = array.sort(function() {return 0.5 - Math.random()});
    let output = array.join(' ');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-order-words').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(' ');
    array =  array.sort();
    let output = array.join(' ');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-order-words-by-length').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(' ');
    array =  array.sort();
    array.sort(function(a,b){
        return a.length - b.length;
    });
    let output = array.join(' ');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-reverse-lines').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.split(/\r?\n|\r/).reverse().join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-scramble-lines').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.sort(function() {return 0.5 - Math.random()});
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-scramble-lines-fisher-yates').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = shuffleFisherYates(array);
    array = shuffleFisherYates(array);
    array = shuffleFisherYates(array);
    array = shuffleFisherYates(array);
    array = shuffleFisherYates(array);
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-order-lines').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array =  array.sort();
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-order-lines-by-length').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array =  array.sort();
    array.sort(function(a,b){
        return a.length - b.length;
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-straighten-quotes').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = v.tr(input, '‘’“”', '\'\'""');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-upside-down').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.toLowerCase();
    input = input.split('').reverse().join('');
    let output = v.tr(input, 'abcdefghijklmnopqrstuvwxyz?!<>', 'ɐqɔpǝɟƃɥıɾʞןɯuodbɹsʇnʌʍxʎz¿¡><');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-from-upside-down').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.toLowerCase();
    input = input.split('').reverse().join('');
    let output = v.tr(input, 'ɐqɔpǝɟƃɥıɾʞןɯuodbɹsʇnʌʍxʎz¿¡<>', 'abcdefghijklmnopqrstuvwxyz?!><');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-insert-line-numbers').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    let numLines = array.length;
    let padSize = numLines.toString().length;
    array = array.map(function(line, index) {
        return _.padStart(index+1, padSize, '0') + '\t' + line;
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-pad-left').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    let longestLineLength = 0;
    let numLines = array.length;
    let padChar = prompt("What character do you want to pad with?", '0');
    if (padChar !== '') {
        for (let i=0; i<numLines; i++) {
	        if (array[i].length > longestLineLength) {
	            longestLineLength = array[i].length;
	        }
	    }
	    array = array.map(function(line, index) {
	        return _.padStart(line, longestLineLength, padChar);
	    });
	    let output = array.join('\n');
	    $textarea.val(output);
	    updateHistory();
    }
});

$('#btn-modify-pad-right').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    let longestLineLength = 0;
    let numLines = array.length;
    let padChar = prompt("What character do you want to pad with?", '0');
    if (padChar !== '') {
        for (let i=0; i<numLines; i++) {
	        if (array[i].length > longestLineLength) {
	            longestLineLength = array[i].length;
	        }
	    }
	    array = array.map(function(line, index) {
	        return _.padEnd(line, longestLineLength, padChar);
	    });
	    let output = array.join('\n');
	    $textarea.val(output);
	    updateHistory();
    }
});

$('#btn-modify-pad-left-and-right').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    let longestLineLength = 0;
    let numLines = array.length;
    let padChar = prompt("What character do you want to pad with?", '0');
    if (padChar !== '') {
        for (let i=0; i<numLines; i++) {
	        if (array[i].length > longestLineLength) {
	            longestLineLength = array[i].length;
	        }
	    }
	    array = array.map(function(line, index) {
            let padStartLength = Math.floor((longestLineLength - line.length) / 2) + line.length;
	        return _.padStart(line, padStartLength, padChar);
	    });
        array = array.map(function(line, index) {
	        return _.padEnd(line, longestLineLength, padChar);
	    });
	    let output = array.join('\n');
	    $textarea.val(output);
	    updateHistory();
    }
});

$('#btn-modify-line-up-first-instance-of-char').click(function() {
    let str = prompt("Which character or string do you want to line up?", ':');
    if (str != '' && str != null) {
        let $textarea = $('#main-textarea');
        let input = $textarea.val();
        let array = input.split(/\r?\n|\r/);
        let laregestIndexOfStr = 0;
        for (let i=0; i<array.length; i++) {
            if (array[i].indexOf(str) > laregestIndexOfStr) {
                laregestIndexOfStr = array[i].indexOf(str)
            }
        }
        array = array.map(line => {
            if (line.indexOf(str) > -1) {
                let lineLength = line.length;
                let offset = laregestIndexOfStr - line.indexOf(str)
                let newLine = _.padStart(line, offset + lineLength, ' ');
                return newLine;
            } else {
                return line;
            }
        })
        let output = array.join('\n');
        $textarea.val(output);
        updateHistory();
    }
});

$('#btn-modify-line-up-last-instance-of-char').click(function() {
    let str = prompt("Which character or string do you want to line up?", ':');
    if (str != '' && str != null) {
        let $textarea = $('#main-textarea');
        let input = $textarea.val();
        let array = input.split(/\r?\n|\r/);
        let laregestIndexOfStr = 0;
        for (let i=0; i<array.length; i++) {
            if (array[i].lastIndexOf(str) > laregestIndexOfStr) {
                laregestIndexOfStr = array[i].indexOf(str)
            }
        }
        array = array.map(line => {
            if (line.lastIndexOf(str) > -1) {
                let lineLength = line.length;
                let offset = laregestIndexOfStr - line.lastIndexOf(str)
                let newLine = _.padStart(line, offset + lineLength, ' ');
                return newLine;
            } else {
                return line;
            }
        })
        let output = array.join('\n');
        $textarea.val(output);
        updateHistory();
    }
});

$('#btn-modify-transpose').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let lineArray = input.split(/\r?\n|\r/);
    let longestLineLength = 0;
    for (let i=0; i<lineArray.length; i++) {
      if (lineArray[i].length > longestLineLength) {
        longestLineLength = lineArray[i].length;
      }
    }
    lineArray = lineArray.map(function(line) {
      return _.padEnd(line, longestLineLength, ' ').split('');
    });
    let transposedLineArray = Array.from({ length: lineArray[0].length }, function(x, row) {
      return Array.from({ length: lineArray.length }, function(x, col) {
        return lineArray[col][row];
      });
    });
    let output = '';
    for (let i=0; i<transposedLineArray.length; i++) {
      let line = transposedLineArray[i];
      if (i < transposedLineArray.length-1) {
        output += line.join('') + '\n';
      } else {
        output += line.join('');
      }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-trim-each-line').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line, index) {
        return _.trim(line);
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-one-char-per-line').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = input.split('').join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-duplicate-text').click(function() {
    let numTimes = prompt("How many duplications do you want?", '1');
    if (numTimes != '' && numTimes != null) {
        numTimes = parseInt(numTimes, 10);
        let $textarea = $('#main-textarea');
        let input = $textarea.val();
        let output = '';
        for (let i=0; i<=numTimes; i++) {
            if (i<numTimes-1) {
                output += input + '\n';
            } else {
                output += input;
            }
        }
        $textarea.val(output);
        updateHistory();
    }
});

$('#btn-modify-duplicate-each-line-horizontally').click(function() {
    let numTimes = prompt("How many duplications do you want of each line?", '1');
    if (numTimes != '' && numTimes != null) {
        numTimes = parseInt(numTimes, 10);
        let $textarea = $('#main-textarea');
        let input = $textarea.val();
        let lineArray = input.split(/\r?\n|\r/);
        lineArray =  lineArray.map(function(line) {
            return line.repeat(numTimes+1);
        });
        let output = lineArray.join('\n');
        $textarea.val(output);
        updateHistory();
    }
});

$('#btn-modify-duplicate-each-line-vertically').click(function() {
    let numTimes = prompt("How many duplications do you want of each line?", '1');
    if (numTimes != '' && numTimes != null) {
        numTimes = parseInt(numTimes, 10);
        let $textarea = $('#main-textarea');
        let input = $textarea.val();
        let lineArray = input.split(/\r?\n|\r/);
        let newArray=[];
        for (let i = 0; i<lineArray.length; ++i) {
          for (let j = 0; j<=numTimes; ++j) {
             newArray.push(lineArray[i]);
          }
        }
        let output = newArray.join('\n');
        $textarea.val(output);
        updateHistory();
    }
});

$('#btn-modify-merge-bottom-into-top').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let lineArray = input.split(/\r?\n|\r/);
    if (!isEven(lineArray.length)) {
        alert('There must be an even number of lines.');
        return false;
    }
    let joinStr = prompt("Which character or string do you want to use to join them together?", ' ');
    if (joinStr != null) {
        let startArray = lineArray.slice(0, lineArray.length/2);
        let endArray = lineArray.slice(lineArray.length/2);
        let mergedArray = [];
        for (let i=0; i<lineArray.length/2; i++) {
            mergedArray.push(`${startArray[i]}${joinStr}${endArray[i]}`);
        }
        let output = `${mergedArray.join('\n')}`;  
        $textarea.val(output);
        updateHistory();
    }
});

$('#btn-modify-insert-linebreak-every-n-chars').click(function() {
    let charCount = prompt('Insert a linebreak after how many characters?', '8');
    if (charCount != '' && charCount != null) {
        charCount = parseInt(charCount, 10);
        let $textarea = $('#main-textarea');
        let input = $textarea.val();
        let regexStr = "(.{" + charCount + "}|.*)";   
        let regex = new RegExp(regexStr,'g');
        let output = input.match(regex).join('\n');        
        $textarea.val(output);
        updateHistory();
    }
});

$('#btn-modify-insert-n-linebreak-after-each-line').click(function() {
    let linebreakCount = prompt('Insert how many linebreaks after each line?', '2');
    if (linebreakCount != '' && linebreakCount != null) {
        let $textarea = $('#main-textarea');
        let input = $textarea.val();
        let lineArray = input.split(/\r?\n|\r/);
        linebreakCount = parseInt(linebreakCount, 10);
        let linebreaksArray = [];
        for (var i=0; i<linebreakCount; i++) {
          linebreaksArray.push('\n');
        }
        const linebreaksStr = linebreaksArray.join('');
        const output = lineArray.join(linebreaksStr);       
        $textarea.val(output);
        updateHistory();
    }
});

$('#btn-modify-insert-n-linebreaks-after-every-n-lines').click(function() {
    let linebreakCount = prompt('Insert how many linebreaks do you want to insert?', '1');
    let linebreakPos = prompt('Insert linebreaks after how many lines?', '10');
    
    if (linebreakCount != '' && linebreakCount != null && linebreakPos != '' && linebreakPos != null) {
        let $textarea = $('#main-textarea');
        let input = $textarea.val();
        let lineArray = input.split(/\r?\n|\r/);
        linebreakCount = parseInt(linebreakCount, 10);
        linebreakCount = linebreakCount - 1;
        linebreakPos = parseInt(linebreakPos, 10);
        var numInserts = (lineArray.length - (lineArray.length % linebreakPos)) / linebreakPos;
        let textToInsert = _.repeat('\n', linebreakCount);
        var count = 1;
        for (var i=0; i<numInserts; i++) {
          lineArray.splice((linebreakPos * count)+(count-1), 0, textToInsert);
          count++;
        }
        const output = lineArray.join('\n');       
        $textarea.val(output);
        updateHistory();
    }
});

$('#btn-modify-insert-text-at-position-n').click(function() {
    let insertStr = prompt('Text to be inserted \u2026', '');
    let position =  prompt('After character position \u2026', '0');
    if (insertStr != '' && insertStr != null && position != '' && position != null) {
        position = parseInt(position, 10);
        let $textarea = $('#main-textarea');
        let input = $textarea.val();
        let lineArray = input.split(/\r?\n|\r/);
        let lineLength = 0;
        lineArray = lineArray.map(function(line, index) {
            lineLength = line.length;
            if (lineLength >= position) {
                return line.substr(0, position) + insertStr + line.substr(position);
            } else {
                return line;
            }
        });
        let output = lineArray.join('\n');  
        $textarea.val(output);
        updateHistory();
    }
});

$('#btn-modify-insert-prefix-and-suffix').click(function() {
    let prefixStr = prompt('Prefix text \u2026', '');
    let suffixStr =  prompt('Suffix \u2026', '');
    if (prefixStr === null) {
        prefixStr = '';
    }
    if (suffixStr === null) {
        suffixStr = '';
    }
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let lineArray = input.split(/\r?\n|\r/);
    let lineLength = 0;
    lineArray = lineArray.map(function(line, index) {
        lineLength = line.length;
        if (lineLength > 0) {
            return prefixStr + line + suffixStr;
        } else {
            return line;
        }
    });
    let output = lineArray.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-html-table-to-json').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    var $tableElement = $(input);
    $('body').append($tableElement);
    let tableJson = $tableElement.tableToJSON();
    $tableElement.remove();
    let output = JSON.stringify(tableJson, null, 2);
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-data-string-to-json').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let dataObj = input.split(';')
        .map(x => x.split(':'))
        .reduce((data, [key, value]) => {
            if (isNaN(value)) {
                data[key] = String(value);
            } else {
                data[key] = Number(value);
            }
                return data;
            }, {});
    let dataJson = JSON.stringify(dataObj, null, 2);

    let output = dataJson;  
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-populate-uuid').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.replace(/'uuid': ''/g, function() {
        let newUuid = uuidv4()
        return `'uuid': '${newUuid}'`;
    });
    input = input.replace(/"uuid": ""/g, function() {
        let newUuid = uuidv4()
        return `"uuid": "${newUuid}"`;
    });
    let output = input;  
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-replace-uuids').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let regExp = new RegExp(/[\da-zA-Z]{8}-([\da-zA-Z]{4}-){3}[\da-zA-Z]{12}/, 'gim');
    input = input.replace(regExp, function() {
        return uuidv4();
    })
    let output = input;  
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// Switch format fieldset
// =========================================================

$('#btn-switch-format-json-to-csv-with-quotes').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    try {
        let json = $.parseJSON(input);
        let output = json2csv(json, true, true);
        $textarea.val(output);
        updateHistory();
    } catch {
        alert('Unable to parse JSON string! Please check it is formatted correctly.')
    }
});

$('#btn-switch-format-json-to-csv-without-quotes').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    try {
        let json = $.parseJSON(input);
        let output = json2csv(json, false, true);
        $textarea.val(output);
        updateHistory();
    } catch {
        alert('Unable to parse JSON string! Please check it is formatted correctly.')
    }
});

$('#btn-switch-format-csv-to-json').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.replace(/"/g,'')
    let array = input.split('\n');
    array = array.filter(entry => entry.trim() != '');
    input = array.join('\n');
    input = csv2json(input);
    
    try {
        const jsonObj = JSON.parse(input);
        console.dir(jsonObj, {depth: null, colors: true});
        let output = JSON.stringify(JSON.parse(input), null, 2);
        $textarea.val(output);
        updateHistory();
        $textarea.scrollTop(0).scrollLeft(0);
    }
    catch (error) {
        alert('Unable to parse JSON string! Please check it is formatted correctly.');
        console.error(error);
    }
});

$('#btn-switch-format-yaml-to-json').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    if (input === '') return;
    try {
        let SexyYamlType = new jsyaml.Type('!sexy', {
            kind: 'sequence',
            construct: function (data) {
            return data.map(function (string) { return 'sexy ' + string; });
        }
        });
        let SEXY_SCHEMA = jsyaml.Schema.create([ SexyYamlType ]);
        let jsonObj = jsyaml.load(input, { schema: SEXY_SCHEMA });
        let output = JSON.stringify(jsonObj, null, 2);
        console.dir(JSON.parse(output), {depth: null, colors: true});
        $textarea.val(output);
        updateHistory();
        $textarea.scrollTop(0).scrollLeft(0);
    }
    catch (error) {
        alert('Unable to parse YAML string! Please check it is formatted correctly.');
        alert(error.message);
        console.error(error);
    }
});

// =========================================================
// Create lookup table fieldset
// =========================================================

$('#btn-create-lookup-table-encode-formatted').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let lineArray = input.split(/\r?\n|\r/);
    lineArray = lineArray.filter(entry => entry.trim() != '');
    if (!isEven(lineArray.length)) {
        alert('There must be an even number of lines.');
        return false;
    }  
    let fromArray = lineArray.slice(0, lineArray.length/2);
    let toArray = lineArray.slice(lineArray.length/2);
    let comma, mappingArray = [];
    for (let i=0; i<lineArray.length/2; i++) {
        if (i < (lineArray.length/2)-1) {
            comma = ',';
        } else {
            comma = '';
        }
        mappingArray.push(`    '${fromArray[i]}': '${toArray[i]}'${comma}`);
    }
    let output = `const encodeLookupTable = {\n${mappingArray.join('\n')}\n};`;  
    $textarea.val(output);
    updateHistory();
});

$('#btn-create-lookup-table-encode-unformatted').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let lineArray = input.split(/\r?\n|\r/);
    lineArray = lineArray.filter(entry => entry.trim() != '');
    if (!isEven(lineArray.length)) {
        alert('There must be an even number of lines.');
        return false;
    }  
    let fromArray = lineArray.slice(0, lineArray.length/2);
    let toArray = lineArray.slice(lineArray.length/2);
    let comma, mappingStr = '';
    for (let i=0; i<lineArray.length/2; i++) {
        if (i < (lineArray.length/2)-1) {
            comma = ',';
        } else {
            comma = '';
        }
        mappingStr += `'${fromArray[i]}':'${toArray[i]}'${comma}`;
    }
    let output = `const encodeLookupTable = {${mappingStr}};`;  
    $textarea.val(output);
    updateHistory();
});

$('#btn-create-lookup-table-decode-formatted').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let lineArray = input.split(/\r?\n|\r/);
    lineArray = lineArray.filter(entry => entry.trim() != '');
    if (!isEven(lineArray.length)) {
        alert('There must be an even number of lines.');
        return false;
    }  
    let fromArray = lineArray.slice(lineArray.length/2);
    let toArray = lineArray.slice(0, lineArray.length/2);
    let comma, mappingArray = [];
    for (let i=0; i<lineArray.length/2; i++) {
        if (i < (lineArray.length/2)-1) {
            comma = ',';
        } else {
            comma = '';
        }
        mappingArray.push(`    '${fromArray[i]}': '${toArray[i]}'${comma}`);
    }
    let output = `const decodeLookupTable = {\n${mappingArray.join('\n')}\n};`;  
    $textarea.val(output);
    updateHistory();
});

$('#btn-create-lookup-table-decode-unformatted').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let lineArray = input.split(/\r?\n|\r/);
    lineArray = lineArray.filter(entry => entry.trim() != '');
    if (!isEven(lineArray.length)) {
        alert('There must be an even number of lines.');
        return false;
    }  
    let fromArray = lineArray.slice(lineArray.length/2);
    let toArray = lineArray.slice(0, lineArray.length/2);
    let comma, mappingStr = '';
    for (let i=0; i<lineArray.length/2; i++) {
        if (i < (lineArray.length/2)-1) {
            comma = ',';
        } else {
            comma = '';
        }
        mappingStr += `'${fromArray[i]}':'${toArray[i]}'${comma}`;
    }
    let output = `const decodeLookupTable = {${mappingStr}};`;  
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// Convert to comment block fieldset
// =========================================================

$('#btn-comments-html').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let longest = 0;
    for (let item of array) {
        if (item.length > longest) {
            longest = item.length;
        }
    }
    array = array.map(function(line) {
        return line +  _.repeat(' ', longest - line.length);
    });
    array.unshift(_.repeat('=', longest));
    array.push(_.repeat('=', longest));
    array = array.map(function(line) {
        return '<!-- ' + line + ' -->';
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-comments-css').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let longest = 0;
    for (let item of array) {
        if (item.length > longest) {
            longest = item.length;
        }
    }
    array = array.map(function(line) {
        return line +  _.repeat(' ', longest - line.length);
    });
    array.unshift(_.repeat('=', longest));
    array.push(_.repeat('=', longest));
    array = array.map(function(line) {
        return '/* ' + line + ' */';
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-comments-js').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let longest = 0;
    for (let item of array) {
        if (item.length > longest) {
            longest = item.length;
        }
    }
    array.unshift(_.repeat('=', longest));
    array.push(_.repeat('=', longest));
    array = array.map(function(line) {
        return '// ' + line;
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-comments-js-dont-minify').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    array = array.map(function(line) {
        return ' * ' + line;
    });
    array.unshift('/*!');
    array.push(' */');
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-comments-react-jsx').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let longest = 0;
    for (let item of array) {
        if (item.length > longest) {
            longest = item.length;
        }
    }
    array = array.map(function(line) {
        return line +  _.repeat(' ', longest - line.length);
    });
    array.unshift(_.repeat('=', longest));
    array.push(_.repeat('=', longest));
    array = array.map(function(line) {
        return '{/*  ' + line + '  */}';
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-comments-php').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let longest = 0;
    for (let item of array) {
        if (item.length > longest) {
            longest = item.length;
        }
    }
    array.unshift(_.repeat('=', longest));
    array.push(_.repeat('=', longest));
    array = array.map(function(line) {
        return '// ' + line;
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-comments-blade-template').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let longest = 0;
    for (let item of array) {
        if (item.length > longest) {
            longest = item.length;
        }
    }
    array = array.map(function(line) {
        return line +  _.repeat(' ', longest - line.length);
    });
    array.unshift(_.repeat('=', longest));
    array.push(_.repeat('=', longest));
    array = array.map(function(line) {
        return '{{-- ' + line + ' --}}';
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-comments-python').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let longest = 0;
    for (let item of array) {
        if (item.length > longest) {
            longest = item.length;
        }
    }
    array.unshift(_.repeat('=', longest));
    array.push(_.repeat('=', longest));
    array = array.map(function(line) {
        return '# ' + line;
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-comments-yaml').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let longest = 0;
    for (let item of array) {
        if (item.length > longest) {
            longest = item.length;
        }
    }
    array.unshift(_.repeat('=', longest));
    array.push(_.repeat('=', longest));
    array = array.map(function(line) {
        return '# ' + line;
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-comments-pug').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split('\n');
    let longest = 0;
    for (let item of array) {
        if (item.length > longest) {
            longest = item.length;
        }
    }
    array.unshift(_.repeat('=', longest));
    array.push(_.repeat('=', longest));
    array = array.map(function(line) {
        return '//- ' + line;
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});


// =========================================================
// Extract data fieldset
// =========================================================

$('#btn-extract-email-addresses').click(function() {
    let regExp = new RegExp(/^([A-Z|a-z|0-9](\.|_){0,1})+[A-Z|a-z|0-9]\@([A-Z|a-z|0-9])+((\.){0,1}[A-Z|a-z|0-9]){2}\.[a-z]{2,3}$/, 'gm');
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.match(regExp);
    if (array) {
        let output = array.join('\n');
        $textarea.val(output);
        updateHistory();
    } else {
        alert('No email addresses found!');
    }
});

$('#btn-extract-urls-inc-args').click(function() {
    let regExp = new RegExp(/[(http(s)?):\/\/(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/, 'ig');
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.match(regExp);
    if (array) {
        let output = array.join('\n');
        $textarea.val(output);
        updateHistory();
    } else {
        alert('No URLs found!');
    }
});

$('#btn-extract-urls-exc-args').click(function() {
    let regExp = new RegExp(/[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/, 'ig');
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.match(regExp);
    if (array) {
        let output = array.join('\n');
        $textarea.val(output);
        updateHistory();
    } else {
        alert('No URLs found!');
    }
});

$('#btn-extract-non-ascii').click(function() {
    let regExp = new RegExp(/[^\x00-\x7F]+\ *(?:[^\x00-\x7F]| )*/, 'g');
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.match(regExp);
    if (array) {
        let output = array.join('\n');
        $textarea.val(output);
        updateHistory();
    } else {
        alert('No Non-ASCII characters found!');
    }
});

$('#btn-extract-hex-colors').click(function() {
    let regExp = new RegExp(/#?([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})/, 'g');
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.match(regExp);
    if (array) {
        let output = array.join('\n');
        $textarea.val(output);
        updateHistory();
    } else {
        alert('No Hex colors found!');
    }
});

$('#btn-extract-ip-addresses').click(function() {
    let regExp = new RegExp(/\b(?:(?:2(?:[0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9])\.){3}(?:(?:2([0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9]))\b/, 'ig');
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.match(regExp);
    if (array) {
        let output = array.join('\n');
        $textarea.val(output);
        updateHistory();
    } else {
        alert('No IP addresses found!');
    }
});

$('#btn-extract-phone-numbers').click(function() {
    let regExp = new RegExp(/^\s*(?:\+?(\d{1,3}))?([-. (]*(\d{3})[-. )]*)?((\d{3})[-. ]*(\d{2,4})(?:[-.x ]*(\d+))?)\s*$/, 'gm');
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.match(regExp);
    if (array) {
        let output = array.join('\n');
        $textarea.val(output);
        updateHistory();
    } else {
        alert('No phone numbers found!');
    }
});

$('#btn-extract-uk-postcodes').click(function() {
    let regExp = new RegExp(/\b(GIR ?0AA|SAN ?TA1|(?:[A-PR-UWYZ](?:\d{0,2}|[A-HK-Y]\d|[A-HK-Y]\d\d|\d[A-HJKSTUW]|[A-HK-Y]\d[ABEHMNPRV-Y])) ?\d[ABD-HJLNP-UW-Z]{2})\b/, 'gim');
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.match(regExp);
    if (array) {
        let output = array.join('\n');
        $textarea.val(output);
        updateHistory();
    } else {
        alert('No UK postcodes found!');
    }
});

$('#btn-extract-uuids').click(function() {
    let regExp = new RegExp(/[\da-zA-Z]{8}-([\da-zA-Z]{4}-){3}[\da-zA-Z]{12}/, 'gim');
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.match(regExp);
    if (array) {
        let output = array.join('\n');
        $textarea.val(output);
        updateHistory();
    } else {
        alert('No UUIDs found!');
    }
});

// =========================================================
// Find duplicate fieldset
// =========================================================

$('#btn-find-duplicate-uuids').click(function() {
    let regExp = new RegExp(/[\da-zA-Z]{8}-([\da-zA-Z]{4}-){3}[\da-zA-Z]{12}/, 'gim');
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.match(regExp);
    if (array.length > 0) {
        array.sort();
        var countObjs = compressArray(array, 2);
        if (countObjs.length > 0) {
            countObjs = _.orderBy(countObjs, 'count', 'desc');
            let outputArray = countObjs.map(function(obj) {
                return `${obj.count}×\t${obj.value}`;
            });
            let output = outputArray.join('\n');
            $textarea.val(output);
            updateHistory();
        } else {
            alert('No duplicate UUIDs found!');
        }
    } else {
        alert('No UUIDs found!');
    }
});

// =========================================================
// Prepend/append fieldset
// =========================================================

$('#prepend-append-other').hide();

$('#prepend-append').change(function() {
    let value = $(this).val();
    let $btnAction = $('#btn-prepend-append-action');
    switch (value) {
        case 'prepend':
            $btnAction.text('Prepend');
            break;
        case 'append':
            $btnAction.text('Append');
            break;  
        default:
            break;
    }
});

$('#prepend-append-value').change(function() {
    let value = $(this).val();
    if (value === 'other') {
        $('#prepend-append-other').show();
    } else {
        $('#prepend-append-other').hide();
    }
});

$('#btn-prepend-append-action').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    let value;
    switch($('#prepend-append-value').val()) {
        case 'linebreak':
            value = '\n';
            break;
        case 'tab':
            value = '\t';
            break;
        case 'space':
            value = ' ';
            break;
        case 'two-spaces':
            value = '  ';
            break;
        case 'four-spaces':
            value = '    ';
            break;
        case 'comma':
            value = ',';
            break;
        case 'comma-space':
            value = ', ';
            break;
        case 'full-stop':
            value = '.';
            break;
        case 'full-stop-space':
            value = '. ';
            break;
        case 'br':
            value = '<br/>';
            break;
        case 'bullet':
            value = '\u2022 ';
            break;
        case 'right-arrow':
            value = '\u2192 ';
            break;
        case 'long-right-arrow':
            value = '\u27FC ';
            break;
        case 'other':
            value = $('#prepend-append-other').val();
            break;
        default:
            value = '';
            break;
    }
    if ($('#prepend-append').val() === 'prepend') {
        array = array.map(function(line) {
            return value + line;
        });
    } else if ($('#prepend-append').val() === 'append') {
        array = array.map(function(line) {
            return line + value;
        });    
    }
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// Repeating data to tabular data fieldset
// =========================================================

$('#btn-repeats-to-table').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    let nthLine = parseInt($('#repeats-after-select').val(), 10);
    let delimiter;
    switch($('#repeats-after-delimeter-select').val()) {
        case 'comma':
            delimiter = ',';
            break;
        case 'comma-space':
            delimiter = ', ';
            break;
         case 'tab':
            delimiter = '\t';
            break;
        case 'space':
            delimiter = ' ';
            break;
        case 'colon':
            delimiter = ':';
            break;
        case 'semicolon':
            delimiter = ';';
            break;
        case 'pipe':
            delimiter = '|';
            break;
        default:
            delimiter = '';
            break;
    }
    array = array.map(function(line, index) {
        if ((index+1) % nthLine === 0) {
            if (index < array.length-1) {
                return line + '\n';
            } else {
                return line;
            }
        } else {
            return line + delimiter;
        }
    });
    let output = array.join('');
    $textarea.val(output);
    updateHistory();
});



// =========================================================
// Tabular data fieldset
// =========================================================

$('#tabular-data-other-delimeter-value, #tabular-data-analysed-wrapper').hide();
$('#btn-tabular-data-perform-action').prop('disabled', true);

$('#tabular-data-delimeter-value').change(function() {
    if ($(this).val() === 'other') {
        $('#tabular-data-other-delimeter-value').show();
    } else {
        $('#tabular-data-other-delimeter-value').hide();
    }
});

$('#tabular-data-column-select').change(function() {
    if ($(this).val() === '') {
        $('#btn-tabular-data-perform-action').prop('disabled', true);
    } else {
        $('#btn-tabular-data-perform-action').prop('disabled', false);
    }
});

$('#tabular-data-convert-select').change(function() {
    if ($(this).val() === '') {
        $('#btn-tabular-data-convert').prop('disabled', true);
    } else {
        $('#btn-tabular-data-convert').prop('disabled', false);
    }
});

$('#tabular-data-action-select').change(function() {
    let actionBtnText = '';
    switch($(this).val()) {
        case 'delete-this':
            actionBtnText = 'Delete column';
            break;
        case 'delete-others':
            actionBtnText = 'Delete others';
            break;
        case 'delete-before':
            actionBtnText = 'Delete columns';
            break;
        case 'delete-after':
            actionBtnText = 'Delete columns';
            break;
        case 'move-left':
            actionBtnText = 'Move column';
            break;
        case 'move-right':
            actionBtnText = 'Move column';
            break;  
        case 'move-to-beginning':
            actionBtnText = 'Move column';
            break;
        case 'move-to-end':
            actionBtnText = 'Move column';
            break;
        default:
            actionBtnText = 'Perform action';
            break;
    }
    $('#btn-tabular-data-perform-action').text(actionBtnText);
});

function analyseTabularData() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let linesArray = input.split(/\r?\n|\r/);
    let numRows = linesArray.length;
    let firstRowIsHeadings = $('#tabular-data-first-row-headings-checkbox').prop('checked');
    if (firstRowIsHeadings) {
        numRows -= 1;
    }
    let numCols = 0;
    let delimiter;
    switch($('#tabular-data-delimeter-value').val()) {
        case 'linebreak':
            delimiter = '\n';
            break;
        case 'tab':
            delimiter = '\t';
            break;
        case 'space':
            delimiter = ' ';
            break;
        case 'comma':
            delimiter = ',';
            break;
        case 'comma-space':
            delimiter = ', ';
            break;
        case 'colon':
            delimiter = ':';
            break;
        case 'semicolon':
            delimiter = ';';
            break;
        case 'pipe':
            delimiter = '|';
            break;
        case 'other':
            delimiter = $('#tabular-data-other-delimeter-value').val();
            break;
        default:
            delimiter = '';
            break;
    }
    let dataArray = linesArray.map(function(line) {
        let rowArray = line.split(delimiter);
        if (rowArray.length > numCols) {
            numCols = rowArray.length;
        }
        return rowArray;
    });
    if (input === '') {
        numRows = 0;
        numCols = 0;
    }
    $('#tabular-data-num-rows-columns').text(numRows + ' rows, ' + numCols + ' columns');
    $('#tabular-data-column-select').children('option:not(:first)').remove();
    for (let i=0; i<numCols; i++) {
        let optionText;
        if (firstRowIsHeadings) {
            optionText = String.fromCharCode(65+i) + ' &ndash; ' + dataArray[0][i];
        } else {
            optionText = String.fromCharCode(65+i);
        }
        $('#tabular-data-column-select').append('<option value=\'' + (i) + '\'>' + optionText + '</option>');
    }
    $('#tabular-data-analysed-wrapper').show();
    $('#btn-tabular-data-perform-action, #btn-tabular-data-convert').prop('disabled', true);
}

$('#tabular-data-first-row-headings-checkbox').change(function() {
    if ($('#tabular-data-analysed-wrapper').is(':visible')) {
        analyseTabularData();
        if ($(this).prop('checked')) {
            $('#tabular-data-convert-select option[value=json]').prop('disabled', false);
            $("#tabular-data-convert-select")[0].selectedIndex = 0;
        } else {
            $('#tabular-data-convert-select option[value=json]').prop('disabled', true);
            $("#tabular-data-convert-select")[0].selectedIndex = 0;
        }
    }
});

$('#btn-tabular-data-analyse').click(function() {
    analyseTabularData();
});

$('#btn-tabular-data-perform-action').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let linesArray = input.split(/\r?\n|\r/);
    let delimiter;
    switch($('#tabular-data-delimeter-value').val()) {
        case 'linebreak':
            delimiter = '\n';
            break;
        case 'tab':
            delimiter = '\t';
            break;
        case 'space':
            delimiter = ' ';
            break;
        case 'comma':
            delimiter = ',';
            break;
        case 'comma-space':
            delimiter = ', ';
            break;
        case 'colon':
            delimiter = ':';
            break;
        case 'semicolon':
            delimiter = ';';
            break;
        case 'pipe':
            delimiter = '|';
            break;
        case 'other':
            delimiter = $('#tabular-data-other-delimeter-value').val();
            break;
        default:
            delimiter = '';
            break;
    }
    let dataArray = linesArray.map(function(line) {
        return line.split(delimiter);
    });
    let action = $('#tabular-data-action-select').val();
    let columnIndex = parseInt($('#tabular-data-column-select').val(), 10);
    if (action === 'delete-this') {
        dataArray = dataArray.map(function(rowArray) {
            return rowArray.filter(function (item, index) {
                return index != columnIndex;
            });
        });
    } else if (action === 'delete-others') {
        dataArray = dataArray.map(function(rowArray) {
            return rowArray.splice(columnIndex, 1);
        });
    } else if (action === 'delete-before') {
        dataArray = dataArray.map(function(rowArray) {
            return rowArray.filter(function (item, index) {
                return index >= columnIndex;
            });
        });
    } else if (action === 'delete-after') {
        dataArray = dataArray.map(function(rowArray) {
            return rowArray.filter(function (item, index) {
                return index <= columnIndex;
            });
        });
    } else if (action === 'move-left') {
        if (columnIndex > 0) {
            dataArray = dataArray.map(function(rowArray) {
                return moveArrayEntry(rowArray, columnIndex, columnIndex-1);
            });
        }
    } else if (action === 'move-right') {
        if (columnIndex < dataArray[0].length-1) {
            dataArray = dataArray.map(function(rowArray) {
                return moveArrayEntry(rowArray, columnIndex, columnIndex+1);
            });
        }
    } else if (action === 'move-to-beginning') {
        dataArray = dataArray.map(function(rowArray) {
            let valueToMove = rowArray[columnIndex];
            let modifiedArray = rowArray;
            modifiedArray.splice(columnIndex, 1);
            modifiedArray.unshift(valueToMove);
            return modifiedArray;
        });
    } else if (action === 'move-to-end') {
        dataArray = dataArray.map(function(rowArray) {
            let valueToMove = rowArray[columnIndex];
            let modifiedArray = rowArray;
            modifiedArray.splice(columnIndex, 1);
            modifiedArray.push(valueToMove);
            return modifiedArray;
        });
    }
    linesArray = dataArray.map(function(rowArray) {
        return rowArray.join(delimiter);
    });
    let output = linesArray.join('\n');
    $textarea.val(output);
    updateHistory();
    analyseTabularData();
});

$('#btn-tabular-data-convert').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let delimiter;
    switch($('#tabular-data-delimeter-value').val()) {
        case 'linebreak':
            delimiter = '\n';
            break;
        case 'tab':
            delimiter = '\t';
            break;
        case 'space':
            delimiter = ' ';
            break;
        case 'comma':
            delimiter = ',';
            break;
        case 'comma-space':
            delimiter = ', ';
            break;
        case 'colon':
            delimiter = ':';
            break;
        case 'semicolon':
            delimiter = ';';
            break;
        case 'pipe':
            delimiter = '|';
            break;
        case 'other':
            delimiter = $('#tabular-data-other-delimeter-value').val();
            break;
        default:
            delimiter = '';
            break;
    }
    let convertTo = $('#tabular-data-convert-select').val();
    if (convertTo === 'json') {
        input = convertToJson(input, delimiter)
    } else if (convertTo === 'html') {
        let options = {
            seperator: delimiter,
			hasHeader: $('#tabular-data-first-row-headings-checkbox').prop('checked'),
			headerPrefix: "COL"
        };
        input = convertToHtmlTable(input, options);
    }
    let output = input;
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// Add HTML markup fieldset
// =========================================================

$('#btn-html-ol').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.replace(/^(\n{2,})/gm, '\n');
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return '    <li>' + _.trim(line) + '</li>';
    });
    input = '<ol>\n' + array.join('\n') + '\n</ol>';
    input = input.split('<li></li>').join('');
    let output = input;
    $textarea.val(output);
    updateHistory();
});

$('#btn-html-ul').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.replace(/^(\n{2,})/gm, '\n');
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return '    <li>' + _.trim(line) + '</li>';
    });
    input = '<ul>\n' + array.join('\n') + '\n</ul>';
    input = input.split('<li></li>').join('');
    let output = input;
    $textarea.val(output);
    updateHistory();
});

$('#btn-html-br').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return line + '<br/>';
    });
    let output = array.join('');
    $textarea.val(output);
    updateHistory();
});

$('#btn-html-p').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.replace(/^(\n{2,})/gm, '\n');
    input = input.replace(/\n/g, '<br/>');
    $textarea.val(input);
    input = $textarea.val();
    let array = input.split('<br/><br/>');
    array = array.map(function(line) {
        return '<p>' + line + '</p>\n';
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-html-wrap-lines').click(function() {
    let tagName = prompt("Enter the tag name:", 'h3');
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    if (tagName === null) {
        tagName = '';
    }
    array = array.map(function(line) {
        if (line !== '') {
            return '<'+tagName+'>' + line + '</'+tagName+'>';
        } else {
            return line;
        }
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-html-open-new-window').click(function() {
    let $textarea = $('#main-textarea');
    let html = '';
    switch ($('#view-html-css-select').val()) {
        case '':
            break;
        case 'meyer-reset':
            html += '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css" />';
            break;
        case 'normalize':
            html += '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" />';
            break;
        case 'bootstrap3':
            html += '<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">';
            break;
        case 'bootstrap4':
            html += '<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">';
            break;
        case 'foundation5':
            html += '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/5.5.3/css/foundation.min.css" integrity="sha256-NTds7atVCDeolLUzbcl45lx4gJYO+hNXCaX1wC2HQHc=" crossorigin="anonymous" />';
            break;
        case 'foundation6':
            html += '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.5.1/css/foundation.min.css" integrity="sha256-1mcRjtAxlSjp6XJBgrBeeCORfBp/ppyX4tsvpQVCcpA=" crossorigin="anonymous" />';
            break;
        case 'bulma':
            html += '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" />';
            break;
        case 'semantic-ui':
            html += '<link rel="stylesheet" href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/semantic.min.css" />';
            break;
        case 'materialize':
            html += '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css" />';
            break;
        case 'pure':
            html += '<link rel="stylesheet" href="https://unpkg.com/purecss@1.0.0/build/pure-min.css" integrity="sha384-nn4HPE8lTHyVtfCBi5yW9d20FjT8BJwUXyWZT9InLYax14RDjBj46LmSztkmNP9w" crossorigin="anonymous">';
            break;
        case 'skeleton':
            html += '<link rel="stylesheet" href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/skeleton.css" />';
            break;
        case 'uikit':
            html += '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/2.27.5/css/uikit.min.css" integrity="sha256-iyi99z0YCXphPJKgycNSwgYQwMV9qvCJLC8tlBHvBO0=" crossorigin="anonymous" />';
            break;
        case 'milligram':
            html += '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.3.0/milligram.min.css" />';
            break;
        case 'spectre':
            html += '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/spectre.css/0.5.7/spectre.min.css" />';
            break;
        case 'mustard-ui':
            html += '<link rel="stylesheet" href="https://unpkg.com/mustard-ui@latest/dist/css/mustard-ui.min.css">';
            break;
        case 'mui':
            html += '<link href="//cdn.muicss.com/mui-0.9.41/css/mui.min.css" rel="stylesheet" type="text/css" />';
            break;
        case 'animate':
            html += '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css" integrity="sha256-HtCCUh9Hkh//8U1OwcbD8epVEUdBvuI8wj1KtqMhNkI=" crossorigin="anonymous" />';
            break;
        case 'tailwind':
            html += `<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/1.0.1/base.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/1.0.1/components.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/1.0.1/tailwind.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/1.0.1/utilities.min.css" rel="stylesheet">`;
            break;
        case 'tachyons':
            html += '<link rel="stylesheet" href="https://unpkg.com/tachyons@4.10.0/css/tachyons.min.css"/>';
            break;
    }
    html += $textarea.val();
    let win = popupCenter('', 'HTML Preview', 800, 600);
    win.document.body.innerHTML = html;
});

// =========================================================
// Data URIs
// =========================================================

$('#btn-data-uri-svg-to-background-image').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.replace(/\t/g, ' ');
    input = vkbeautify.xmlmin(input, true);
    input = input.replace(/  +/g, ' ').trim();
    input = input.replace(/\r?\n|\r/g, '');
    input = input.replace(/  +/g, ' ').trim();
    // let array = input.split(/\r?\n|\r/);
    // array = array.map(function(line) {
    //     return _.trim(line);
    // });
    // let output = array.join('');
    //output = encodeURIComponent(output);
    let output = input;
    output = output.replace(/  +/g, ' ')
    output = output.replace(/"/g, '\'');
    output = output.replace(/#/g, '%23');
    output = output.replace(/</g, '%3C');
    output = output.replace(/>/g, '%3E');
    output = 'background-repeat: no-repeat;\nbackground-position: center center;\nbackground-size: contain;\nbackground-image: url("data:image/svg+xml;charset=utf8,' + output + '");';
    $textarea.val(output);
    updateHistory();
});

$('#btn-data-uri-background-image-to-svg').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.replace(/\r?\n|\r/g, '');
    let output = input;
    let firstIndex = output.indexOf('%3Csvg');
    let lastIndex = output.lastIndexOf('svg%3E');
    output = output.substring(firstIndex, lastIndex + 6);
    output = decodeURI(output);
    $textarea.val(output);
    updateHistory();
});



// =========================================================
// Encode/decode fieldset
// =========================================================

$('#btn-modify-encodeURI').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return encodeURI(line);
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = encodeURI(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-decodeURI').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return decodeURI(line);
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = decodeURI(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-encodeURIComponent').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return encodeURIComponent(line);
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = encodeURIComponent(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-decodeURIComponent').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return decodeURIComponent(line);
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = decodeURIComponent(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-toUnicode').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return line.toUnicode();
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.toUnicode()
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-fromUnicode').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return line.replace(/\\u([\d\w]{4})/gi, function (match, grp) {
                return String.fromCharCode(parseInt(grp, 16));
            });
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.replace(/\\u([\d\w]{4})/gi, function (match, grp) {
            return String.fromCharCode(parseInt(grp, 16));
        });
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-toUnicode-zerox').click(function() {    
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return line.toUnicode().replace(/\\u/g, '0x');
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.toUnicode().replace(/\\u/g, '0x');
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-fromUnicode-zerox').click(function() {    
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return line.replace(/0x([\d\w]{4})/gi, function (match, grp) {
                return String.fromCharCode(parseInt(grp, 16));
            });
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.replace(/0x([\d\w]{4})/gi, function (match, grp) {
            return String.fromCharCode(parseInt(grp, 16));
        });
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-toUnicode-uplus').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return line.toUnicode().replace(/\\u/g, 'U+');
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.toUnicode().replace(/\\u/g, 'U+');
    }
    $textarea.val(output);
    updateHistory();
});

// TODO: Fix this function
$('#btn-modify-fromUnicode-uplus').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return line.replace(/U+([\d\w]{4})/gi, function (match, grp) {
                return String.fromCharCode(parseInt(grp, 16));
            });
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.replace(/U+([\d\w]{4})/gi, function (match, grp) {
            return String.fromCharCode(parseInt(grp, 16));
        });
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-to-binary-unicode').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output, charArray;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            charArray = line.split('');
            charArray = charArray.map(function(char) {
                return v.padLeft(char.charCodeAt(0).toString(2), 8, '0');
            });
            return charArray.join('');
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        charArray = input.split('');
        charArray = charArray.map(function(char) {
            return v.padLeft(char.charCodeAt(0).toString(2), 8, '0');
        });
        output = charArray.join('');
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-from-binary-unicode').click(function() {    
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output, array = [], index = 0;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            array = [];
            index = 0;
            while (index < line.length) {
                array.push(line.substring(index, Math.min(index + 8, line.length)));
                index += 8;
            }
            array = array.map(function(char) {
                return String.fromCharCode(parseInt(char, 2));
            });
            return array.join('');
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        while (index < input.length) {
            array.push(input.substring(index, Math.min(index + 8, input.length)));
            index += 8;
        }
        array = array.map(function(char) {
            return String.fromCharCode(parseInt(char, 2));
        });
        output = array.join('');
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-to-hex-unicode').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return line.hexEncode();
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.hexEncode();
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-from-hex-unicode').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return line.hexDecode();
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.hexDecode();
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-to-hex-escape-sequence').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return line.toHexEscapeSequence()
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.toHexEscapeSequence();
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-from-hex-escape-sequence').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
     if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return line.replace(/\\x/g, '00').hexDecode();
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.replace(/\\x/g, '00').hexDecode();
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-to-css-pseudo-content').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output, charArray;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            charArray = line.split('');
            charArray = charArray.map(function(char, index) {
                return '\\' + char.hexEncode();
            });
            return 'content: \''+ charArray.join().replace(/,/g, '') + '\';';
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        charArray = input.split('');
        charArray = charArray.map(function(char, index) {
            return '\\' + char.hexEncode();
        });
        output = 'content: \''+ charArray.join().replace(/,/g, '') + '\';';
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-toUTF8').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return utf8.encode(line);
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = utf8.encode(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-fromUTF8').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return utf8.decode(line);
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = utf8.decode(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-toCharCode').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output, charArray;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            charArray = line.split('');
            charArray = charArray.map(function(char) {
                return char.charCodeAt(0);
            });
            return charArray.join(' ');
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        charArray = input.split('');
        charArray = charArray.map(function(char) {
            return char.charCodeAt(0);
        });
        output = charArray.join(' ');
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-fromCharCode').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output, wordArray;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            wordArray = line.split(' ');
            wordArray = wordArray.map(function(char) {
                return String.fromCharCode(char);
            });
            return wordArray.join('');
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        wordArray = input.split(' ');
        wordArray = wordArray.map(function(char) {
            return String.fromCharCode(char);
        });
        output = wordArray.join('');
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-toHtmlEntityNumber').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output, charArray;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            charArray = line.split('');
            charArray = charArray.map(function(char) {
                return '&#' + char.charCodeAt(0) + ';';
            });
            return charArray.join('');
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        charArray = input.split('');
        charArray = charArray.map(function(char) {
            return '&#' + char.charCodeAt(0) + ';';
        });
        output = charArray.join('');
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-fromHtmlEntityNumber').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output, entityArray, charCode;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            entityArray = line.split('&#');
            entityArray = entityArray.map(function(htmlEntity) {
                htmlEntity = '&#' + htmlEntity;
                charCode = htmlEntity.substring(2, htmlEntity.length-1);
                return String.fromCharCode(charCode);
            });
            return entityArray.join('');
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        entityArray = input.split('&#');
        entityArray = entityArray.map(function(htmlEntity) {
            htmlEntity = '&#' + htmlEntity;
            charCode = htmlEntity.substring(2, htmlEntity.length-1);
            return String.fromCharCode(charCode);
        });
        output = entityArray.join('');
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-toHtmlEntityNamed').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return he.encode(line, {
                'encodeEverything': false,
                'useNamedReferences': true
            });
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = he.encode(input, {
            'encodeEverything': false,
            'useNamedReferences': true
        });
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-fromHtmlEntityNamed').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return he.decode(line);
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = he.decode(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-toBase64').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return b64EncodeUnicode(line);
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = b64EncodeUnicode(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-fromBase64').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return b64DecodeUnicode(line);
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = b64DecodeUnicode(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-toMorse').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return morjs.encode(line, {mode: 'simple'});
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = morjs.encode(input, {mode: 'simple'});
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-fromMorse').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return morjs.decode(line, {mode: 'simple'});
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = morjs.decode(input, {mode: 'simple'});
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-to-json-string').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output, tempStr;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            tempStr = line.replace(/\\/g, '\\\\');
            tempStr = tempStr.replace(/"/g, '\\"');
            tempStr = tempStr.replace(/\r?\n|\r/g, '\\n');
            tempStr = tempStr.replace(/\t/g, '\\t');
            return tempStr;
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.replace(/\\/g, '\\\\');
        output = output.replace(/"/g, '\\"');
        output = output.replace(/\r?\n|\r/g, '\\n');
        output = output.replace(/\t/g, '\\t');
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-from-json-string').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output, tmpStr;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            tmpStr = line.replace(/\\t/g, '\t');
            tmpStr = tmpStr.replace(/\\n/g, '\n');
            tmpStr = tmpStr.replace(/\\"/g, '"');
            tmpStr = tmpStr.replace(/\\\\/g, '\\');
            return tmpStr;
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.replace(/\\t/g, '\t');
        output = output.replace(/\\n/g, '\n');
        output = output.replace(/\\"/g, '"');
        output = output.replace(/\\\\/g, '\\');
    }
    $textarea.val(output);
    updateHistory();
});



$('#btn-modify-to-textarea-value').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output, tempStr;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            tempStr = line.replace(/\\/g, '\\\\');
            tempStr = tempStr.replace(/"/g, '\\"');
            tempStr = tempStr.replace(/\r?\n|\r/g, '\\n');
            tempStr = tempStr.replace(/\t/g, '\\t');
            return "document.getElementById('myTextarea').value = '" + tempStr.replace(/'/g, "\\'") + "';";
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.replace(/\\/g, '\\\\');
        output = output.replace(/"/g, '\\"');
        output = output.replace(/\r?\n|\r/g, '\\n');
        output = output.replace(/\t/g, '\\t');
        output = "// JavaScript code to populate textarea\nvar textarea = document.getElementById('myTextarea');\ntextarea.value = '" + output.replace(/'/g, "\\'") + "';\ntextarea.style.fontFamily = 'Consolas,monaco,monospace';";
    }
    $textarea.val(output);
    updateHistory();
});


$('#btn-modify-to-pre-inner-html').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output, tempStr;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            tempStr = line.replace(/\\/g, '\\\\');
            tempStr = tempStr.replace(/"/g, '\\"');
            tempStr = tempStr.replace(/\r?\n|\r/g, '\\n');
            tempStr = tempStr.replace(/\t/g, '\\t');
            return "document.getElementById('myPre').innerHTML = '" + tempStr.replace(/'/g, "\\'") + "';";
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = input.replace(/\\/g, '\\\\');
        output = output.replace(/"/g, '\\"');
        output = output.replace(/\r?\n|\r/g, '\\n');
        output = output.replace(/\t/g, '\\t');
        output = "// JavaScript code to populate pre element\nvar newPre = document.createElement('pre');\nnewPre.id = 'myPre';\ndocument.body.appendChild(newPre);\n\ndocument.getElementById('myPre').innerHTML = '" + output.replace(/'/g, "\\'") + "';";
    }
    $textarea.val(output);
    updateHistory();
});


$('#btn-modify-to-dna-string').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output, char, charCode, tempStr;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            tempStr = '';
            for (let i=0; i<line.length; i++) {
                char = line.charAt(i).toUpperCase();
                charCode = charToDnaLookupTable[char];
                if (charCode && charCode !== '') {
                    tempStr += charCode;
                }
            }
            return tempStr;
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        for (let i=0; i<input.length; i++) {
            charCode = charToDnaLookupTable[input.charAt(i).toUpperCase()];
            if (charCode && charCode !== '') {
                output += charCode;
            }
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-from-dna-string').click(function() {   
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    if (input !== '') {
        let output = '', dnaArray, char, tempStr;
        if ($('#encode-decode-each-line-radio').is(':checked')) {
            let lineArray = input.split(/\r?\n|\r/);
            lineArray = lineArray.map(function(line, index) {
                tempStr = '';
                dnaArray = line.match(/.{1,3}/g);
                for (let i=0; i<dnaArray.length; i++) {
                    char = dnaToCharLookupTable[dnaArray[i].toUpperCase()];
                    if (char) {
                        tempStr += char.toLowerCase();
                    }
                }
                tempStr = v.titleCase(tempStr);
                return tempStr;
            });
            output = lineArray.join('\n');
        } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
            dnaArray = input.match(/.{1,3}/g);
            for (let i=0; i<dnaArray.length; i++) {
                char = dnaToCharLookupTable[dnaArray[i].toUpperCase()];
                if (char) {
                    output += char.toLowerCase();
                }
            }
            output = v.titleCase(output);
        }
        $textarea.val(output);
        updateHistory();
    }
});

$('#btn-modify-to-fanda').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', char, isUpperCase, tempStr;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            tempStr = '';
            for (let i=0; i<line.length; i++) {
                isUpperCase = v.isUpperCase(line.charAt(i));
                char = charToFandaLookupTable[line.charAt(i).toLowerCase()];
                if (char) {
                    if (isUpperCase) {
                        char = char.toUpperCase();
                    }
                    tempStr += char;
                } else {
                    tempStr += line.charAt(i);
                }
            }
            return tempStr;
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        for (let i=0; i<input.length; i++) {
            isUpperCase = v.isUpperCase(input.charAt(i));
            char = charToFandaLookupTable[input.charAt(i).toLowerCase()];
            if (char) {
                if (isUpperCase) {
                    char = char.toUpperCase();
                }
                output += char;
            } else {
                output += input.charAt(i);
            }
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-from-fanda').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', char, isUpperCase, tempStr;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            tempStr = '';
            for (let i=0; i<line.length; i++) {
                isUpperCase = v.isUpperCase(line.charAt(i));
                char = fandaToCharLookupTable[line.charAt(i).toLowerCase()];
                if (char) {
                    if (isUpperCase) {
                        char = char.toUpperCase();
                    }
                    tempStr += char;
                } else {
                    tempStr += line.charAt(i);
                }
            }
            return tempStr;
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        for (let i=0; i<input.length; i++) {
            isUpperCase = v.isUpperCase(input.charAt(i));
            char = charToFandaLookupTable[input.charAt(i).toLowerCase()];
            if (char) {
                if (isUpperCase) {
                    char = char.toUpperCase();
                }
                output += char;
            } else {
                output += input.charAt(i);
            }
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-modify-toMD5').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#encode-decode-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return SparkMD5.hash(line);
        });
        output = lineArray.join('\n');
    } else if ($('#encode-decode-whole-document-radio').is(':checked')) {
        output = SparkMD5.hash(input);
    }
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// ROT fieldset
// =========================================================

$('#rot-number-select').change(function() {
    let rotNumber = parseInt($(this).val(), 10);
    console.log('rotNumber:', rotNumber);
    $('#btn-to-rot').text('To ROT'+rotNumber);
    $('#btn-from-rot').text('From ROT'+rotNumber);
});

$('#btn-to-rot').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let rotNumber = parseInt($('#rot-number-select').val(), 10);
    let output = rot(input, rotNumber)
    $textarea.val(output);
    updateHistory();
});

$('#btn-from-rot').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let rotNumber = parseInt($('#rot-number-select').val(), 10);
    let output = rot(input, rotNumber * -1)
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// Vigenère cipher fieldset
// =========================================================

$('#btn-vigenere-cipher-encode').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let key = $('#vigenere-key').val();
    if (key === '') {
        alert('You must enter a key for the Vigenère cipher to work, eg \'abc\'.');
        return;
    }
    key = vigenereFilterKey(key);
    let output = vigenereCrypt(input, key);
    $textarea.val(output);
    updateHistory();
});

$('#btn-vigenere-cipher-decode').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let key = $('#vigenere-key').val();
    if (key === '') {
        alert('You must enter a key for the Vigenère cipher to work, eg \'abc\'.');
        return;
    }
    key = vigenereFilterKey(key);
	for (var i = 0; i < key.length; i++) {
        key[i] = (26 - key[i]) % 26;
    }
    let output = vigenereCrypt(input, key);
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// Mathematical Unicode fieldset
// =========================================================

$('#btn-to-mathematical-double-struck').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalDoubleStruckLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-from-mathematical-double-struck').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = mathematicalDoubleStruckToCharLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-to-mathematical-fraktur').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalFrakturLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-to-mathematical-bold-fraktur').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalBoldFrakturLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-to-mathematical-bold').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalBoldLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-to-mathematical-italic').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalItalicLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-to-mathematical-bold-italic').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalBoldItalicLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-to-mathematical-script').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalScriptLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-to-mathematical-bold-script').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalBoldScriptLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-to-mathematical-sans-serif').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalSansSerifLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-to-mathematical-sans-serif-bold').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalSansSerifBoldLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-to-mathematical-sans-serif-italic').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalSansSerifItalicLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-to-mathematical-sans-serif-bold-italic').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalSansSerifBoldItalicLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-to-mathematical-monospace').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = '', charCode;
    for (let i=0; i<input.length; i++) {
        charCode = charToMathematicalMonospaceLookupTable[input.charAt(i)];
        if (charCode && charCode !== '') {
            output += charCode;
        } else {
            output += input.charAt(i)
        }
    }
    $textarea.val(output);
    updateHistory();
});





// =========================================================
// Lodash fieldset
// =========================================================

$('#btn-lodash-camelcase').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.camelCase(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.camelCase(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-capitalize').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.capitalize(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.capitalize(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-deburr').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.deburr(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.deburr(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-escape').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.escape(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.escape(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-escapeRegExp').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.escapeRegExp(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.escapeRegExp(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-kebabCase').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.kebabCase(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.kebabCase(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-lowerCase').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.lowerCase(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.lowerCase(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-lowerFirst').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.lowerFirst(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.lowerFirst(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-snakeCase').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.snakeCase(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.snakeCase(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-startCase').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.startCase(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.startCase(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-trim').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.trim(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.trim(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-unescape').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.unescape(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.unescape(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-upperCase').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.upperCase(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.upperCase(input);
    }
    $textarea.val(output);
    updateHistory();
});

$('#btn-lodash-upperFirst').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output;
    if ($('#lodash-each-line-radio').is(':checked')) {
        let lineArray = input.split(/\r?\n|\r/);
        lineArray = lineArray.map(function(line, index) {
            return _.upperFirst(line);
        });
        output = lineArray.join('\n');
    } else if ($('#lodash-whole-document-radio').is(':checked')) {
        output = _.upperFirst(input);
    }
    $textarea.val(output);
    updateHistory();
});


// =========================================================
// Voca fieldset
// =========================================================

$('#btn-voca-escapeHtml').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = v.escapeHtml(input);
    $textarea.val(output);
    updateHistory();
});

$('#btn-voca-escapeRegExp').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = v.escapeRegExp(input);
    $textarea.val(output);
    updateHistory();
});

$('#btn-voca-unescapeHtml').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = v.unescapeHtml(input);
    $textarea.val(output);
    updateHistory();
});

$('#btn-voca-slugify').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = v.slugify(input);
    $textarea.val(output);
    updateHistory();
});

$('#btn-voca-stripTags').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let output = v.stripTags(input);
    $textarea.val(output);
    updateHistory();
});


// =========================================================
// Beautify fieldset
// =========================================================

$('#btn-beautify-html').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let postUrl = 'https://www.10bestdesign.com/dirtymarkup/api/html';
    $('body').addClass('cursor-wait');
    
    $.post(postUrl, { 
        'code': $textarea.val(),
        'indent': 2,
        'line-length': 10000,
        'output': 'full-page',
        'indent-style': 'auto',
        'add-empty-lines': false,
        'allow-proprietary-attribs': false,
        'optimize-for-ms-word': false
    }).done(function(response) {
        let output = response.clean;
        let linesArray = output.split(/\r?\n|\r/);
        let length = linesArray.length;
        linesArray = linesArray.slice(6, length-2);
        linesArray = linesArray.map(function(line) {
            if (_.startsWith(line, '  ')) {
                return line.substring(2, line.length);
            } else {
                return line;
            }
        });
        output = linesArray.join('\n');
        $textarea.val(output);
        updateHistory();
        $('body').removeClass('cursor-wait');
        $textarea.scrollTop(0).scrollLeft(0);
    });
});

$('#btn-beautify-css').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let postUrl = 'https://www.10bestdesign.com/dirtymarkup/api/css';
    $('body').addClass('cursor-wait');
    
    $.post(postUrl, { 
        'code': $textarea.val(),
        'indent': 2,
        'newline-between-rules': true,
        'newline-between-selectors': false
    }).done(function(response) {
        $textarea.val(response.clean);
        updateHistory();
        $('body').removeClass('cursor-wait');
        $textarea.scrollTop(0).scrollLeft(0);
    });
});

$('#btn-beautify-js').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let postUrl = 'https://www.10bestdesign.com/dirtymarkup/api/js';
    $('body').addClass('cursor-wait');
    
    $.post(postUrl, { 
        'code': $textarea.val(),
        'indent': 4,
        'line-length': 10000,
        'brace-style': 'collapse',
        'spaces-in-parenthesis': false,
        'break-chained-methods': false,
        'commas-at-beginning': false,
        'keep-array-indentation': false,
        'preserve-empty-lines': false
    }).done(function(response) {
        $textarea.val(response.clean);
        updateHistory();
        $('body').removeClass('cursor-wait');
        $textarea.scrollTop(0).scrollLeft(0);
    });
});

$('#btn-beautify-json').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    
    try {
        const jsonObj = JSON.parse(input);
        console.dir(jsonObj, {depth: null, colors: true});
        let output = JSON.stringify(JSON.parse(input), null, 2);
        $textarea.val(output);
        updateHistory();
        $textarea.scrollTop(0).scrollLeft(0);
    }
    catch (error) {
        alert('Unable to parse JSON string! Please check it is formatted correctly.');
        console.error(error);
    }
});

$('#btn-beautify-xml').click(function() {
    const numSpacesPerIndentLevel = 2;
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return convertIndentationTabsToSpaces(line, numSpacesPerIndentLevel);
    });
    input = array.join('\n');
    input = input.replace(/\r?\n|\r/g, '');
    input.replace(/  +/g, ' ').trim();
    input  = vkbeautify.xml(input, 2);
    input = input.replace(/  +/g, ' ').trim();
    input  = vkbeautify.xml(input, 2);
    let output = input;
    $textarea.val(output);
    updateHistory();
    $textarea.scrollTop(0).scrollLeft(0);
});

// =========================================================
// Indentation fieldset
// =========================================================

$('#btn-indentation-tabs-to-four-spaces').click(function() {
    const numSpacesPerIndentLevel = 4;
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return convertIndentationTabsToSpaces(line, numSpacesPerIndentLevel);
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-indentation-tabs-to-two-spaces').click(function() {
    const numSpacesPerIndentLevel = 2;
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return convertIndentationTabsToSpaces(line, numSpacesPerIndentLevel);
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-indentation-four-spaces-to-two-spaces').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return convertIndentationSpacesToSpaces(line, 4, 2);
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-indentation-four-spaces-to-tabs').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return convertIndentationSpacesToTabs(line, 4);
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-indentation-two-spaces-to-four-spaces').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return convertIndentationSpacesToSpaces(line, 2, 4);
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-indentation-two-spaces-to-tabs').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return convertIndentationSpacesToTabs(line, 2);
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-indent-one-space').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return ` ${line}`;
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-indent-two-spaces').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return `  ${line}`;
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-indent-four-spaces').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return `    ${line}`;
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-indent-tab').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    array = array.map(function(line) {
        return `\t${line}`;
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-unindent-one-space').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    let startsWithString = ' ';
    array = array.map(function(line) {
        if (v.startsWith(line, startsWithString)) {
            return line.substring(startsWithString.length, line.length);
        } else {
            return line;
        }
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-unindent-two-spaces').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    let startsWithString = '  ';
    array = array.map(function(line) {
        if (v.startsWith(line, startsWithString)) {
            return line.substring(startsWithString.length, line.length);
        } else {
            return line;
        }
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-unindent-four-spaces').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    let startsWithString = '    ';
    array = array.map(function(line) {
        if (v.startsWith(line, startsWithString)) {
            return line.substring(startsWithString.length, line.length);
        } else {
            return line;
        }
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

$('#btn-unindent-tab').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let array = input.split(/\r?\n|\r/);
    let startsWithString = '\t'
    array = array.map(function(line) {
        if (v.startsWith(line, startsWithString)) {
            return line.substring(startsWithString.length, line.length);
        } else {
            return line;
        }
    });
    let output = array.join('\n');
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// Minify/Uglify fieldset
// =========================================================

$('#btn-minify-css').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    if (input === '') {
      alert('Please enter some CSS to minify');
      return false;
    }
    let output = input
      .replace(/\/\*.*\*\/|\/\*[\s\S]*?\*\/|\n|\t|\v|\s{2,}/g, '')
      .replace(/\s*\{\s*/g, '{')
      .replace(/\s*\}\s*/g, '}')
      .replace(/\s*\:\s*/g, ':')
      .replace(/\s*\;\s*/g, ';')
      .replace(/\s*\,\s*/g, ',')
      .replace(/\s*\~\s*/g, '~')
      .replace(/\s*\>\s*/g, '>')
      .replace(/\s*\+\s*/g, '+')
      .replace(/\s*\!\s*/g, ' !')
      .replace(/\s*\;\}\s*/g, '}');
    $textarea.val(output);
    updateHistory();
});

$('#btn-minify-js').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    if (input === '') {
      alert('Please enter some JavaScript to minify');
      return false;
    }
    // To-Do: Do JS minification here
    let output = input;
    $textarea.val(output);
    updateHistory();
});

$('#btn-uglify-json').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    if (input === '') {
      alert('Please enter some JSON to minify');
      return false;
    }
    try {
        const jsonObj = JSON.parse(input);
        let output = JSON.stringify(JSON.parse(input));
        $textarea.val(output);
        updateHistory();
    }
    catch (error) {
        alert('Unable to parse JSON string! Please check it is formatted correctly.');
        console.error(error);
    }
});

$('#btn-uglify-xml').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    input = input.replace(/\t/g, ' ');
    input = vkbeautify.xmlmin(input, true);
    input = input.replace(/  +/g, ' ').trim();
    input = input.replace(/\r?\n|\r/g, '');
    input = input.replace(/  +/g, ' ').trim();
    let output = input;
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// Markdown fieldset
// =========================================================

$('#btn-markdown-to-html').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    var converter = new showdown.Converter();
    let output = converter.makeHtml(input);
    $textarea.val(output);
    updateHistory();
});

// =========================================================
// Validate fieldset
// =========================================================

$('#btn-validate-xml').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    var domParser = new DOMParser();
    var xmlDocument = domParser.parseFromString(input, 'text/xml');
    console.log(xmlDocument);
    var selializedXml = (new XMLSerializer()).serializeToString(xmlDocument);
    if (selializedXml.indexOf('</parsererror>') === -1) {
        alert('The XML is valid!');
        let win = popupCenter('', 'XML Preview', 800, 600);
        win.document.body.innerHTML = selializedXml;
    } else {
        alert('The XML is NOT valid!');
    }
});

$('#btn-validate-json').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    try {
        let jsonObj = JSON.parse(input);
        alert('The JSON is valid!');
    } catch(err) {
        alert('The JSON is NOT valid!');
    }
});

// =========================================================
// Console fieldset
// =========================================================

$('#btn-console-log-text').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    console.log(input);
});

$('#btn-console-log-json').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    try {
        let jsonObj = JSON.parse(input);
        console.log(jsonObj);
    } catch(err) {
        alert('The JSON is NOT valid!');
    }
});

$('#btn-console-table-json').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    try {
        let jsonObj = JSON.parse(input);
        console.table(jsonObj);
    } catch(err) {
        alert('The JSON is NOT valid!');
    }
});

$('#btn-console-dirxml').click(function() {
    let $textarea = $('#main-textarea');
    let input = $textarea.val();
    let $newDomElement = $(input);
    if ($newDomElement.length === 0) {
        alert('No DOM elements found!');
    } else if ($newDomElement.length === 1) {
        console.dirxml($newDomElement[0]);
    } else if ($newDomElement.length >= 2) {
        let $wrapper = $('<div></div>');
        $wrapper.append($newDomElement);
        console.dirxml($wrapper[0]);
    }
});

// =========================================================
// Helper functions  
// =========================================================

function compressArray(original, minCount) {
  var compressed = [];
  var copy = original.slice(0);
  for (var i = 0; i < original.length; i++) {
    var myCount = 0;
    for (var w = 0; w < copy.length; w++) {
      if (original[i] == copy[w]) {
        myCount++;
        delete copy[w];
      }
    }
    if (myCount > 0 && myCount >= minCount) {
      var a = new Object();
      a.value = original[i];
      a.count = myCount;
      compressed.push(a);
    }
  }
  return compressed;
};

function shuffleFisherYates(array) {
  var m = array.length, t, i;
  while (m) {
    i = Math.floor(Math.random() * m--);
    t = array[m];
    array[m] = array[i];
    array[i] = t;
  }
  return array;
}

function uuidv4() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}

function roundDecimal(value, decimals) {
    return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
}

function countByteSize(text) {
    var crlf = /(\r?\n|\r)/g;
    var length = text.length,
        nonAscii = length - text.replace(/[\u0100-\uFFFF]/g, '').length,
        lineBreaks = length - text.replace(crlf, '').length; 
    return length + nonAscii + Math.max(0, (lineBreaks - 1));
}

function formatByteSize(size) {
    var level = 0;
    while (size > 1024) {
        size /= 1024;
        level++;
    }
    size = roundDecimal(size, 1);
    if (level === 0 || level === 1) {
        size = Math.round(size);
    }
    level = ['', 'K', 'M', 'G', 'T'][level];
    return size + ' ' + level + 'B';
}

function convertIndentationTabsToSpaces(str, numSpacesPerIndentLevel) {
    let indentationLevel = countCharsAtStart(str, '\t');
    let spaceIndentStr = repeatingChar(' ', numSpacesPerIndentLevel);
    str = str.substring(indentationLevel, str.length);
    str = Array(indentationLevel+1).join(spaceIndentStr) + str;
    return str;
}

function convertIndentationSpacesToSpaces(str, inputNumSpacesPerIndentLevel, outputNumSpacesPerIndentLevel) {
    let spaceIndentStr = repeatingChar(' ', outputNumSpacesPerIndentLevel);
    let numSpacesAtStart = countCharsAtStart(str, ' ');
    let indentationLevel = (numSpacesAtStart - (numSpacesAtStart%inputNumSpacesPerIndentLevel)) / inputNumSpacesPerIndentLevel;
    str = str.substring(numSpacesAtStart, str.length);
    str = Array(indentationLevel+1).join(spaceIndentStr) + str;
    return str;
}

function convertIndentationSpacesToTabs(str, inputNumSpacesPerIndentLevel) {
    let numSpacesAtStart = countCharsAtStart(str, ' ');
    let indentationLevel = (numSpacesAtStart - (numSpacesAtStart%inputNumSpacesPerIndentLevel)) / inputNumSpacesPerIndentLevel;
    str = str.substring(numSpacesAtStart, str.length);
    str = Array(indentationLevel+1).join('\t') + str;
    return str;
}

function repeatingChar(char, numTimes) {
    return Array(numTimes+1).join(char);
}

function countCharsAtStart(str, char) {
    var count = 0;
    var index = 0;
    while (str.charAt(index++) === char) {
        count++;
    }
    return count;
}

function isEven(n) {
   return n % 2 == 0;
}

function isOdd(n) {
   return Math.abs(n % 2) == 1;
}

function removeFirstChar(str) {
    return str.substr(1);
}

function removeLastChar(str) {
    return str.substr(0, str.length-1);
}

function b64EncodeUnicode(str) {
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
        function toSolidBytes(match, p1) {
            return String.fromCharCode('0x' + p1);
    }));
}

function b64DecodeUnicode(str) {
    return decodeURIComponent(atob(str).split('').map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}

function popupCenter(url, title, w, h) {
    // Fixes dual-screen position                         Most browsers      Firefox
    var dualScreenLeft = window.screenLeft != undefined ? window.screenLeft : screen.left;
    var dualScreenTop = window.screenTop != undefined ? window.screenTop : screen.top;

    var width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
    var height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

    var left = ((width / 2) - (w / 2)) + dualScreenLeft;
    var top = ((height / 2) - (h / 2)) + dualScreenTop;
    var newWindow = window.open(url, title, 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);

    // Puts focus on the newWindow
    if (window.focus) {
        newWindow.focus();
    }
    
    return newWindow;
}


function convertToJson(text, delimiter){
    let lines = text.split("\n"),
        result = [];
    let headers = lines[0].split(delimiter);
    for (var i=1;i<lines.length;i++) {
        var obj = {};
	    var currentline=lines[i].split(delimiter);
	    for(var j=0;j<headers.length;j++){
		    obj[headers[j]] = currentline[j];
	    }
	    result.push(obj);
    }
    return JSON.stringify(result);
}

function convertToHtmlTable(text, options) {
    let result = convertToArray(text, options);
    return toHTML(result.rows, options);
}

function convertToArray(sCSV, options) {
    let result = {
            headers: null,
			rows: null
        },
        firstRowAt = 0,
        tds,
        first,
        cols;

	tds = sCSV.split("\x0a");
	first = tds[0].split(options.seperator);
	if (options.hasHeader) {
        result.headers = first;
		result.headers = result.headers.map(function(header) {
		    return header.replace(/\//g, "_");
		});
        firstRowAt = 1;
	} else {
		result.headers = first.map(function(header, i) {
		    return options.headerPrefix + i;
		});
	}
	cols = result.headers.length;
	result.rows = tds.map(function(row, i) {
        return row.split(options.seperator);
    });
    return result;
}

function tag(element, value) {
    return "<" + element + ">" + value + "</" + element + ">";
}

function toHTML(arr, options) {
    let sTable;
    if (options.hasHeader) {
        sTable = "<table class=\"table table-striped\">\n"+indentLevel1()+"<thead>";
    } else {
        sTable = "<table class=\"table table-striped\">";
    }
	arr.map(function(row, i) {
        var sRow = "";
		row.map(function(cell, ii) {
            if (i === 0 && options.hasHeader) {
                sRow += tag('th', cell);
            } else {
                sRow += tag('td', cell);
            }
		});
        console.log(sRow);
        if (options.hasHeader) {
            sTable += '\n'+indentLevel2()+tag("tr", sRow) + ((i === 0) ? "\n"+indentLevel1()+"</thead>\n"+indentLevel1()+"<tbody>" : "");
        } else {
            if (i === 0) {
                sTable += '\n'+indentLevel1()+'<tbody>\n'+indentLevel2()+tag("tr", sRow);
            } else {
                sTable += '\n'+indentLevel2()+tag("tr", sRow);
            }
        }
	});
	return sTable + "\n"+indentLevel1()+"</tbody>\n</table>";
}

function indentLevel1() {
    return '    ';
}

function indentLevel2() {
    return '        ';
}

function indentLevel3() {
    return '            ';
}

function moveArrayEntry(array, oldIndex, newIndex) {
    if (newIndex >= array.length) {
        var k = newIndex - array.length;
        while ((k--) + 1) {
            array.push(undefined);
        }
    }
    array.splice(newIndex, 0, array.splice(oldIndex, 1)[0]);
    return array;
};

function getSelectionText() {
    var text = '';
    if (window.getSelection) {
        text = window.getSelection().toString();
    } else if (document.selection && document.selection.type != 'Control') {
        text = document.selection.createRange().text;
    }
    return text;
}

var encodeJavaScriptString = function f(a, b) {
  return ++b                                 //`b` is a number (including 0) when `replace` calls the function
    ? '\\' + (                               //all escape sequences start with a backslash
      (a = a.charCodeAt()) >> 12             //all characters from U+1000 and above
        ? 'u'                                //must start with `\u`
        : a >> 8                             //all characters from U+0100 to U+0FFF
          ? 'u0'                             //must start with `\u0`
          : 'x'                              //characters from U+007F to U+00FF can start with `\u00` or `\x`
      ) + a.toString(16).toUpperCase()       //add the upper case hex string (it does not contain leading zeros)
    : a.replace(/[^\0-~]/g, f)               //else call the function for all non-ASCII characters (all except U+0000 to U+007E)
}

String.prototype.hexEncode = function(){
    var hex, i;
    var result = '';
    for (i=0; i<this.length; i++) {
        hex = this.charCodeAt(i).toString(16);
        result += ("000"+hex).slice(-4);
    }
    return result;
}

String.prototype.hexDecode = function(){
    var j;
    var hexes = this.match(/.{1,4}/g) || [];
    var back = '';
    for(j = 0; j<hexes.length; j++) {
        back += String.fromCharCode(parseInt(hexes[j], 16));
    }
    return back;
}

String.prototype.toUnicode = function() {
    var result = '';
    for(var i = 0; i < this.length; i++){
        result += "\\u" + (("000" + this[i].charCodeAt(0).toString(16)).substr(-4)).toUpperCase();
    }
    return result;
};

String.prototype.toHexEscapeSequence = function() {
    var char, hex, prefixed, sliced, i;
    var result = '';
    for (i=0; i<this.length; i++) {
        result += '\\x'+(('000'+this.charCodeAt(i).toString(16)).slice(-2)).toUpperCase();   
    }
    return result;
};


/* 
 * Returns the result the Vigenère encryption on the given text with the given key.
 */
function vigenereCrypt(input, key) {
	var output = "";
	for (var i = 0, j = 0; i < input.length; i++) {
		var c = input.charCodeAt(i);
		if (isUppercase(c)) {
			output += String.fromCharCode((c - 65 + key[j % key.length]) % 26 + 65);
			j++;
		} else if (isLowercase(c)) {
			output += String.fromCharCode((c - 97 + key[j % key.length]) % 26 + 97);
			j++;
		} else {
			output += input.charAt(i);
		}
	}
	return output;
}


/* 
 * Returns an array of numbers, each in the range [0, 26), representing the given key.
 * The key is case-insensitive, and non-letters are ignored.
 * Examples:
 * - filterKey("AAA") = [0, 0, 0].
 * - filterKey("abc") = [0, 1, 2].
 * - filterKey("the $123# EHT") = [19, 7, 4, 4, 7, 19].
 */
function vigenereFilterKey(key) {
	var result = [];
	for (var i = 0; i < key.length; i++) {
		var c = key.charCodeAt(i);
		if (isLetter(c))
			result.push((c - 65) % 32);
	}
	return result;
}


// Tests whether the specified character code is a letter.
function isLetter(c) {
	return isUppercase(c) || isLowercase(c);
}

// Tests whether the specified character code is an uppercase letter.
function isUppercase(c) {
	return 65 <= c && c <= 90;  // 65 is character code for 'A'. 90 is 'Z'.
}

// Tests whether the specified character code is a lowercase letter.
function isLowercase(c) {
	return 97 <= c && c <= 122;  // 97 is character code for 'a'. 122 is 'z'.
}


// =========================================================
// Clipboard 
// =========================================================

var clipboard = new Clipboard('.btn');

clipboard.on('success', function(e) {
    console.info('Action:', e.action);
    console.info('Text:', e.text);
    console.info('Trigger:', e.trigger);

    e.clearSelection();
});

clipboard.on('error', function(e) {
    console.error('Action:', e.action);
    console.error('Trigger:', e.trigger);
});


// =========================================================
// Keyboard shortcuts
// =========================================================

function KeyPress(event) {
    // Ctrl+Y or Cmd+Y
    if ((event.code === 'KeyY' && event.ctrlKey) || (event.code === 'KeyY' && event.metaKey)) {
        event.preventDefault();
        if ( $('#btn-history-redo').prop('disabled') === false ) {
            redo();
        }
        
    }
    // Ctrl+Z or Cmd+Z
    if ((event.code === 'KeyZ' && event.ctrlKey) || (event.code === 'KeyZ' && event.metaKey)) {
        event.preventDefault();
         if ( $('#btn-history-undo').prop('disabled') === false ) {
             undo();
        }
    }
    // Ctrl+H or Cmd+H
    if ((event.code === 'KeyH' && event.ctrlKey) || (event.code === 'KeyH' && event.metaKey)) {
        event.preventDefault();
        if ( $('#btn-history-undo').prop('disabled') === false ) {
            clearHistory();
        }
    }
}
document.onkeydown = KeyPress;

// =========================================================
// json2csv function
// =========================================================

function json2csv(objArray, wrapValues, includeLabels) {
  let array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
  let str = '';
  let line = '';
  if (includeLabels) {
    let head = array[0];
    if (wrapValues) {
      for (let index in array[0]) {
        let value = index + "";
        line += '"' + value.replace(/"/g, '""') + '",';
      }
    } else {
      for (let index in array[0]) {
        line += index + ',';
      }
    }
    line = line.slice(0, -1);
    str += line + '\r\n';
  }

  for (let i = 0; i < array.length; i++) {
    let line = '';
    if (wrapValues) {
      for (let index in array[i]) {
        let value = array[i][index] + "";
        line += '"' + value.replace(/"/g, '""') + '",';
      }
    } else {
      for (let index in array[i]) {
        line += array[i][index] + ',';
      }
    }
    line = line.slice(0, -1);
    str += line + '\r\n';
  }
  return str;
}

// =========================================================
// csv2json function
// =========================================================

function csv2json(csv) {
    let array = CSVToArray(csv);
    let objArray = [];
    for (let i = 1; i < array.length; i++) {
        objArray[i - 1] = {};
        for (let k = 0; k < array[0].length && k < array[i].length; k++) {
            let key = array[0][k];
            objArray[i - 1][key] = array[i][k]
        }
    }
    let json = JSON.stringify(objArray);
    let str = json.replace(/},/g, "},\r\n");
    return str;
}

// =========================================================
// CSVToArray function
// =========================================================

function CSVToArray(strData, strDelimiter) {
    strDelimiter = (strDelimiter || ",");
    let objPattern = new RegExp(("(\\" + strDelimiter + "|\\r?\\n|\\r|^)" + "(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" + "([^\"\\" + strDelimiter + "\\r\\n]*))"), "gi");
    let arrData = [[]];
    let arrMatches = null;
    while (arrMatches = objPattern.exec(strData)) {
        let strMatchedDelimiter = arrMatches[1];
        if (strMatchedDelimiter.length && (strMatchedDelimiter != strDelimiter)) {
            arrData.push([]);
        }
        if (arrMatches[2]) {
            let strMatchedValue = arrMatches[2].replace(
            new RegExp("\"\"", "g"), "\"");
        } else {
            var strMatchedValue = arrMatches[3];
        }
        arrData[arrData.length - 1].push(strMatchedValue);
    }
    return arrData;
}

// =========================================================
// Call init()
// =========================================================

init();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js
  2. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/showdown.min.js
  3. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/mor.min.js
  4. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/unibabel.js
  5. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/spark-md5.js
  6. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/clipboard.min.js
  7. https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js
  8. https://cdn.rawgit.com/mathiasbynens/he/670991a4/he.js
  9. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/voca.min.js
  10. https://cdnjs.cloudflare.com/ajax/libs/utf8/3.0.0/utf8.js
  11. https://cdnjs.cloudflare.com/ajax/libs/strman/1.3.1/strman.js
  12. https://unpkg.com/axios/dist/axios.min.js
  13. https://jquerypp.com/release/latest/jquerypp.js
  14. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/holder-ipsum.js
  15. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/punycode-client-side.js
  16. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/rot.js
  17. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/chance.min.js
  18. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/date_fns.min.js
  19. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/jquery.tabletojson.js
  20. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/FileSaver.min.js
  21. https://s3-us-west-2.amazonaws.com/s.cdpn.io/9487/vkbeautify.js
  22. https://cdn.jsdelivr.net/npm/json2csv
  23. https://cdnjs.cloudflare.com/ajax/libs/clientside-haml-js/5.4/haml.min.js
  24. https://cdnjs.cloudflare.com/ajax/libs/esprima/2.7.3/esprima.min.js
  25. https://cdnjs.cloudflare.com/ajax/libs/js-yaml/3.13.1/js-yaml.min.js