[
  {
    "path": ".eslintrc",
    "content": "{\n    \"rules\": {\n        \"arrow-spacing\": \"error\",\n        \"brace-style\": [\"error\", \"stroustrup\"],\n        \"camelcase\": \"error\",\n        \"comma-dangle\": [\"error\", \"always-multiline\"],\n        \"comma-spacing\": \"error\",\n        \"constructor-super\": \"error\",\n        \"curly\": [\"error\", \"multi-or-nest\", \"consistent\"],\n        \"eol-last\": \"error\",\n        \"eqeqeq\": [\"error\", \"always\"],\n        \"guard-for-in\": \"off\",\n        \"indent\": [\"error\", 4, {\n            \"CallExpression\": {\"arguments\": \"first\"},\n            \"FunctionExpression\": {\"parameters\": \"first\"},\n            \"flatTernaryExpressions\": true,\n            \"SwitchCase\": 1\n        }],\n        \"keyword-spacing\": \"error\",\n        \"linebreak-style\": [\"error\", \"unix\"],\n        \"max-len\": [\"error\", 128, 2, {\n            \"ignoreUrls\": true,\n            \"ignorePattern\": \"\\\\brequire\\\\([\\\"']|eslint-disable\",\n            \"ignoreComments\": true\n        }],\n        \"no-alert\": \"error\",\n        \"no-array-constructor\": \"error\",\n        \"no-console\": \"off\",\n        \"no-const-assign\": \"error\",\n        \"no-constant-condition\": \"off\",\n        \"no-debugger\": \"error\",\n        \"no-dupe-class-members\": \"error\",\n        \"no-dupe-keys\": \"error\",\n        \"no-duplicate-imports\": \"error\",\n        \"no-extra-bind\": \"error\",\n        \"no-new\": \"error\",\n        \"no-new-func\": \"error\",\n        \"no-new-object\": \"error\",\n        \"no-spaced-func\": \"error\",\n        \"no-this-before-super\": \"error\",\n        \"no-throw-literal\": \"error\",\n        \"no-trailing-spaces\": \"error\",\n        \"no-undef\": \"off\",\n        \"no-unexpected-multiline\": \"error\",\n        \"no-unreachable\": \"error\",\n        \"no-unused-vars\": [\"error\", {\"args\": \"none\", \"varsIgnorePattern\": \"^_*$\"}],\n        \"no-useless-call\": \"error\",\n        \"no-with\": \"error\",\n        \"one-var\": [\"error\", \"never\"],\n        \"prefer-const\": \"error\",\n        \"prefer-spread\": \"error\",\n        \"semi\": [\"error\", \"always\"],\n        \"space-before-blocks\": \"error\",\n        \"space-before-function-paren\": [\"error\", \"always\"],\n        \"space-infix-ops\": \"error\",\n        \"space-unary-ops\": \"error\",\n        \"prefer-template\": \"error\",\n        \"no-template-curly-in-string\": \"error\",\n        \"template-curly-spacing\": [\"error\", \"never\"],\n        \"arrow-parens\": [\"error\", \"always\"],\n        \"arrow-body-style\": \"error\",\n        \"prefer-arrow-callback\": \"error\",\n        \"object-curly-spacing\": [\"error\", \"always\"]\n    },\n    \"env\": {\n        \"es6\": true,\n        \"node\": true,\n        \"browser\": true\n    },\n    \"extends\": \"eslint:recommended\",\n    \"root\": true\n}\n"
  },
  {
    "path": ".gitignore",
    "content": "_site\ntex/\nbuild/\nnode_modules/\nstatic/katex/\nstatic/fonts/\nnpm-debug.log\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2020-2023 Saswat Padhi (saswat.sourav@gmail.com)\nCopyright (c) 2015-2019 Tate Tian (tatetian@gmail.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": ".PHONY: all build clean docs default lint release\n\nVERSION=2.4.1\n\n# Building tools\nBROWSERIFY = $(realpath ./node_modules/.bin/browserify)\nCLEANCSS = $(realpath ./node_modules/.bin/cleancss)\nESLINT = $(realpath ./node_modules/.bin/eslint)\nWATCHIFY = $(realpath ./node_modules/.bin/watchify)\nUGLIFYJS = $(realpath ./node_modules/.bin/uglifyjs) \\\n\t--mangle \\\n\t--beautify \\\n\tascii_only=true,beautify=false\n\nSAMPLES = build/katex-samples.html build/mathjax-v2-samples.html build/mathjax-v3-samples.html build/mathjax-v4-samples.html\n\n\ndefault: build\n\n\nall : clean\n\t@$(MAKE) --no-print-directory release\n\n\nwatch-js: pseudocode.js $(wildcard src/*.js)\n\t$(WATCHIFY) $< --standalone pseudocode -o build/pseudocode.js\n\n\n\nbuild: build/pseudocode.js build/pseudocode.css $(SAMPLES)\n\t@echo \"> Building succeeded\\n\"\n\nbuild/pseudocode.js: pseudocode.js $(wildcard src/*.js)\n\t@$(MAKE) --no-print-directory lint\n\t$(BROWSERIFY) $< --exclude mathjax --exclude katex --standalone pseudocode -o $@\n\nbuild/pseudocode.css: static/pseudocode.css\n\tcp static/pseudocode.css build/pseudocode.css\n\nbuild/%-samples.html: static/%.html.part static/body.html.part static/footer.html.part\n\tcat $^ > $@\n\n\n\nlint: pseudocode.js $(wildcard src/*.js)\n\t$(ESLINT) $^\n\nfix-lint: pseudocode.js $(wildcard src/*.js)\n\t$(ESLINT) --fix $^\n\n\n\nrelease: build docs build/pseudocode-js.tar.gz build/pseudocode-js.zip\n\t@echo \"> Release package generated\\n\"\n\nRELEASE_DIR=pseudocode.js-$(VERSION)/\nbuild/pseudocode-js.tar.gz: build/$(RELEASE_DIR)\n\tcd build && tar czf pseudocode-js.tar.gz $(RELEASE_DIR)\n\nbuild/pseudocode-js.zip: build/$(RELEASE_DIR)\n\tcd build && zip -rq pseudocode-js.zip $(RELEASE_DIR) || \\\n                7z a -r pseudocode-js.zip $(RELEASE_DIR)\n\nbuild/$(RELEASE_DIR): build/pseudocode.js build/pseudocode.min.js build/pseudocode.css build/pseudocode.min.css $(SAMPLES) README.md\n\tmkdir -p build/$(RELEASE_DIR)\n\tcp -r $^ build/$(RELEASE_DIR)\n\nbuild/pseudocode.min.js: build/pseudocode.js\n\t$(UGLIFYJS) < $< > $@\n\nbuild/pseudocode.min.css: build/pseudocode.css\n\t$(CLEANCSS) -o $@ $<\n\n\n\ndocs: build/pseudocode.min.js build/pseudocode.min.css $(SAMPLES)\n\tcp build/pseudocode.min.css docs/pseudocode.css\n\tcp build/pseudocode.min.js docs/pseudocode.js\n\tcp $(SAMPLES) docs/\n\n\n\nclean:\n\t@rm -rf build/*\n"
  },
  {
    "path": "README.md",
    "content": "# pseudocode.js\n\n<img align=\"right\" width=\"40%\" src=\"docs/screenshot.png\">\n\n**pseudocode.js** is a JavaScript library that typesets pseudocode beautifully to \nHTML.\n\n* _Intuitive grammar:_ Pseudocode.js takes a LaTeX-style input that supports \n  the algorithmic constructs from LaTeX's algorithm packages. With or without \n  LaTeX experience, a user should find the grammar fairly intuitive. \n* _Print quality:_ The HTML output produced by pseudocode.js is (almost) \n  identical with the pretty algorithms printed on publications that are \n  typeset by LaTeX.\n* _Math formula support:_ Inserting math formulas in pseudocode.js is as easy \n  as LaTeX. Just enclose math expression in `$...$` or `\\(...\\)`.\n\nIt supports all modern browsers, including Chrome, Safari, Firefox, Edge, and Edge.\n\nVisit the [project website](https://saswatpadhi.github.io/pseudocode.js) for a demo.\n\n\n## Usage\n\n### Quick Start\n\npseudocode.js can render math formulas using either\n[KaTeX](https://github.com/Khan/KaTeX), or [MathJax](https://www.mathjax.org/).\n\n#### Step 1A &middot; For KaTeX users\nInclude the following in the `<head>` of your page:\n\n```html\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js\"\n        integrity=\"sha512-EKW5YvKU3hpyyOcN6jQnAxO/L8gts+YdYV6Yymtl8pk9YlYFtqJgihORuRoBXK8/cOIlappdU6Ms8KdK6yBCgA==\"\n        crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\">\n</script>\n```\n\n#### Step 1B &middot; For MathJax 2.x users\nInclude the following in the `<head>` of your page:\n\n```html\n<script src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.9/MathJax.js?config=TeX-AMS_CHTML-full\"\n        integrity=\"sha256-DViIOMYdwlM/axqoGDPeUyf0urLoHMN4QACBKyB58Uw=\"\n        crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\">\n</script>\n<script type=\"text/x-mathjax-config\">\n    MathJax.Hub.Config({\n        tex2jax: {\n            inlineMath: [['$','$'], ['\\\\(','\\\\)']],\n            displayMath: [['$$','$$'], ['\\\\[','\\\\]']],\n            processEscapes: true,\n            processEnvironments: true,\n        }\n    });\n</script>\n```\n\n> **Note**\n> The `-full` configuration is larger and loads more extensions,\n> but I recommend using it it just to avoid any hiccups later.\n> You may want to use the standard configuration instead\n> if you do not require additional packages.\n\n#### Step 1C &middot; For MathJax 3.x users\nInclude the following in the `<head>` of your page:\n\n```html\n<script>\n    MathJax = {\n        tex: {\n            inlineMath: [['$','$'], ['\\\\(','\\\\)']],\n            displayMath: [['$$','$$'], ['\\\\[','\\\\]']],\n            processEscapes: true,\n            processEnvironments: true,\n        }\n    }\n</script>\n<script src=\"https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/tex-chtml-full.js\"\n        integrity=\"sha256-kbAFUDxdHwlYv01zraGjvjNZayxKtdoiJ38bDTFJtaQ=\"\n        crossorigin=\"anonymous\">\n</script>\n```\n\n> **Note**\n> The `-full` configuration is larger and loads more extensions,\n> but I recommend using it it just to avoid any hiccups later.\n> You may want to use the standard configuration instead\n> if you do not require additional packages, such as `color`.\n\n#### Step 2 &middot; Grab pseudocode.js\nInclude the following in the `<head>` of your page:\n\n```html\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/pseudocode@2.4.1/build/pseudocode.min.css\">\n<script src=\"https://cdn.jsdelivr.net/npm/pseudocode@2.4.1/build/pseudocode.min.js\">\n</script>\n```\n\nYou may also use the `latest` tag for pseudocode instead,\nbut jsDelivr might be delayed in updating the pointer for this tag.\n\n```html\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/pseudocode@latest/build/pseudocode.min.css\">\n<script src=\"https://cdn.jsdelivr.net/npm/pseudocode@latest/build/pseudocode.min.js\">\n</script>\n```\n\n#### Step 3 &middot; Write your pseudocode inside a `<pre>`\nWe assume the pseudocode to be rendered is in a `<pre>` DOM element.\nHere is an example that illustrates a quicksort algorithm:\n\n```html\n<pre id=\"quicksort\" class=\"pseudocode\">\n    % This quicksort algorithm is extracted from Chapter 7, Introduction to Algorithms (3rd edition)\n    \\begin{algorithm}\n    \\caption{Quicksort}\n    \\begin{algorithmic}\n    \\PROCEDURE{Quicksort}{$A, p, r$}\n        \\IF{$p < r$} \n            \\STATE $q = $ \\CALL{Partition}{$A, p, r$}\n            \\STATE \\CALL{Quicksort}{$A, p, q - 1$}\n            \\STATE \\CALL{Quicksort}{$A, q + 1, r$}\n        \\ENDIF\n    \\ENDPROCEDURE\n    \\PROCEDURE{Partition}{$A, p, r$}\n        \\STATE $x = A[r]$\n        \\STATE $i = p - 1$\n        \\FOR{$j = p$ \\TO $r - 1$}\n            \\IF{$A[j] < x$}\n                \\STATE $i = i + 1$\n                \\STATE exchange\n                $A[i]$ with $A[j]$\n            \\ENDIF\n            \\STATE exchange $A[i]$ with $A[r]$\n        \\ENDFOR\n    \\ENDPROCEDURE\n    \\end{algorithmic}\n    \\end{algorithm}\n</pre>\n```\n\n#### Step 4A &middot; Render the element using pseudocode.js\nInsert the following Javascript snippet at the end of your document:\n\n```html\n<script>\n    pseudocode.renderElement(document.getElementById(\"quicksort\"));\n</script>\n```\n\n#### Step 4B &middot; Render all elements of the class using pseudocode.js\nInsert the following Javascript snippet at the end of your document:\n\n```html\n<script>\n    pseudocode.renderClass(\"pseudocode\");\n</script>\n```\n\n### Grammar\nThere are several packages for typesetting algorithms in LaTeX, among which \n[`algorithmic`](http://mirror.ctan.org/tex-archive/macros/latex/contrib/algorithms/algorithms.pdf)\npackage is the most simple and intuitive, and is chosen by IEEE in its \n[LaTeX template file](http://www.ctan.org/tex-archive/macros/latex/contrib/IEEEtran). \nThe grammar of pseudocode.js is mostly compatible with `algorithmic` package with \na few improvement to make it even more easier to use.\n\nCommands for typesetting algorithms must be enclosed in an `algorithmic` environment:\n```tex\n\\begin{algorithmic}\n# A precondition is optional\n\\REQUIRE <text>\n# A postcondition is optional\n\\ENSURE <text>\n# An input is optional\n\\INPUT <text>\n# An output is optional\n\\OUTPUT <text>\n# The body of your code is a <block>\n\\STATE ...\n\\end{algorithmic}\n```\n\n`<block>` can include zero or more `<statement>`, `<control>`,  `<comment>` \nand `<function>`:\n```tex\n# A <statement> can be:\n\\STATE <text>\n\\RETURN <text>\n\\PRINT <text>\n\n# A <control> can be:\n# A conditional\n\\IF{<condition>}\n    <block>\n\\ELIF{<condition>}\n    <block>\n\\ELSE\n    <block>\n\\ENDIF\n# Or a loop: \\WHILE, \\FOR or \\FORALL\n\\WHILE{<condition>}\n    <block>\n\\ENDWHILE\n# Or a repeat: \\REPEAT <block> \\UNTIL{<cond>}\n\\REPEAT\n    <block>\n\\UNTIL{<cond>}\n\n# A <function> can by defined by either \\FUNCTION or \\PROCEDURE\n# Both are exactly the same\n\\FUNCTION{<name>}{<params>}\n    <block> \n\\ENDFUNCTION\n\n# A <comment> is:\n\\COMMENT{<text>}\n```\n\nA `<text>`, `<block>`, or `<condition>` may include the following:\n```tex\n% Normal characters\nHello world\n% Escaped characters\n\\\\, \\{, \\}, \\$, \\&, \\#, \\% and \\_\n% Math formula\n$i \\gets i + 1$\n% Function call\n\\CALL{<func>}{<args>}\n% Keywords\n\\AND, \\OR, \\XOR, \\NOT, \\TO, \\DOWNTO, \\TRUE, \\FALSE, \\BREAK, \\CONTINUE\n% LaTeX's sizing commands\n\\tiny, \\scriptsize, \\footnotesize, \\small \\normalsize, \\large, \\Large, \\LARGE, \n\\huge, \\HUGE\n% LaTeX's font declarations\n\\rmfamily, \\sffamily, \\ttfamily\n\\upshape, \\itshape, \\slshape, \\scshape\n\\bfseries, \\mdseries, \\lfseries\n% LaTeX's font commands\n\\textnormal{<text>}, \\textrm{<text>}, \\textsf{<text>}, \\texttt{<text>}\n\\textup{<text>}, \\textit{<text>}, \\textsl{<text>}, \\textsc{<text>}\n\\uppercase{<text>}, \\lowercase{<text>}\n\\textbf, \\textmd, \\textlf\n% And it's possible to group text with braces\nnormal text {\\small the size gets smaller} back to normal again\n```\n\n> **Note**\n> Although pseudocode.js recognizes some LaTeX commands, it is by no means a full-featured LaTeX implementation in JavaScript.\n> It only support a subset of LaTeX commands that are most relevant to typesetting algorithms.\n\n\nTo display the caption of an algorithm, use `algorithm` environment as a 'float' wrapper :\n```tex\n\\begin{algorithm}\n\\caption{The caption of your algorithm}\n\\begin{algorithmic}\n\\STATE ...\n\\end{algorithmic}\n\\end{algorithm}\n```\n\n### Options\n\n#### Global Options\n\n`pseudocode.renderElement` can accept an option object as the last argument, such as\n\n```js\npseudocode.renderElement(document.getElementById(\"quicksort\"),\n                         { lineNumber: true });\n```\n\nThe following options are currently supported:\n\n * `captionCount`:\n   Reset the caption counter to this number, if defined.\n * `commentDelimiter`:\n   The delimiters used to start and end a comment region.\n   Note that only line comments are supported.\n * `indentSize`:\n   The indent size of inside a control block, e.g. if, for etc.\n   The unit must be in 'em'.\n * `lineNumber`:\n   Whether line numbering is enabled.\n * `lineNumberPunc`:\n   The punctuation that follows line number.\n * `noEnd`:\n   Whether block ending, like `end if`, end procedure`, etc.\n   are shown.\n * `scopeLines`:\n   Whether vertical lines indicating the scopes of nested blocks\n   are drawn.\n * `titlePrefix`:\n   The title prefix (defaults to \"Algorithm\") for captions.\n\nThe default values of these options are:\n\n```js\nvar DEFAULT_OPTIONS = {\n    captionCount: undefined,\n    commentDelimiter: '//',\n    indentSize: '1.2em',\n    lineNumber: false,\n    lineNumberPunc: ':',\n    noEnd: false,\n    scopeLines: false,\n    titlePrefix: 'Algorithm'\n};\n```\n\n#### Per-Element Options\n\nThe above-mentioned global options may be overridden on a per-element basis\nusing [HTML `data-*` attributes](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset)\non the `<pre>` DOM element.\n\nThe following example demonstrates how to enable line numbers and change title prefix:\n\n```html\n<pre id=\"quicksort\" class=\"pseudocode\"\n     data-line-number=true data-title-prefix=\"Algo\">\n   ...\n</pre>\n```\n\n## Build and Test\npseudocode.js is written in JavaScript and built with [Node.js](https://nodejs.org).\nSo, make sure you have Node.js installed before building pseudocode.js.\n\nTo compile the project on Ubuntu Linux, run the following commands in terminal:\n\n```bash\ncd pseudocode.js/\nnpm install\nmake\n```\n\nThen, open one of the sample documents:\n- `build/katex-samples.html`, or\n- `build/mathjax-v2-samples.html`, or\n- `build/mathjax-v3-samples.html`\nin your favorite browser to check if the algorithms are typeset correctly.\n\n\n## Author\npseudocode.js was originally written by Tate Tian ([@tatetian](https://github.com/tatetian)).\nTogether with [@ZJUGuoShuai](https://github.com/ZJUGuoShuai),\nI ([@SaswatPadhi](https://github.com/SaswatPadhi)) added the MathJax support,\nand I am the current maintainer of this project.\nSuggestions, bug reports and pull requests are most welcome.\n\n## Acknowledgement\npseudocode.js is partially inspired by [KaTeX](http://khan.github.io/KaTeX/).\nThanks Emily Eisenberg([@xymostech](https://github.com/xymostech))\nand other contributors for building such a wonderful project.\n"
  },
  {
    "path": "docs/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\">\n\n    <title>pseudocode.js</title>\n\n    <link rel=\"stylesheet\" href=\"stylesheets/styles.css\">\n    <link rel=\"stylesheet\" href=\"stylesheets/pygment_trac.css\">\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css\"\n          integrity=\"sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==\"\n          crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\" />\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/default.min.css\"\n          integrity=\"sha512-hasIneQUHlh06VNBe7f6ZcHmeRTLIaQWFd43YriJ0UND19bvYRauxthDg8E4eVNPm9bRUhr5JGeqH7FRFXQu5g==\"\n          crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\" />\n    <link rel=\"stylesheet\" href=\"pseudocode.css\">\n\n    <script src=\"javascripts/autosize.min.js\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js\"\n            integrity=\"sha512-rdhY3cbXURo13l/WU9VlaRyaIYeJ/KBakckXIvJNAQde8DgpOmE+eZf7ha4vdqVjTtwQt69bD2wH2LXob/LB7Q==\"\n            crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\">\n    </script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js\"\n            integrity=\"sha512-EKW5YvKU3hpyyOcN6jQnAxO/L8gts+YdYV6Yymtl8pk9YlYFtqJgihORuRoBXK8/cOIlappdU6Ms8KdK6yBCgA==\"\n            crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\">\n    </script>\n    <script src=\"pseudocode.js\"></script>\n\n    <style type=\"text/css\">\n        body {\n            color: #333;\n            font-size: 18px;\n        }\n        h1 {\n            font-size: 2em;\n        }\n        .demo-container {\n            font-size: 1.2em;\n            position: relative;\n            padding-right: 2.4em;\n        }\n        .button {\n            position: absolute;\n            right: 0;\n            top: -0.1em;\n            font-size: 1.6em;\n            color: #39c;\n        }\n        .demo-editor {\n            width: 100%;\n            min-height: 60px;\n            border: none;\n            vertical-align: top;\n            font-size: 0.8em;\n            margin: 0.8em 0;\n            border-top: 3px solid #000;\n            border-bottom: 3px solid #000;\n            font-family: Courier New,Courier,Lucida Sans Typewriter,Lucida Typewriter,monospace; \n        }\n        .demo-editor{\n            font-size: 0.7em;\n            display: none;\n        }\n        .demo-container.editing .btn-edit {\n            display: none;\n        }\n        .btn-done {\n            display: none;\n        }\n        .demo-container.editing .btn-done {\n            display: inline;\n        }\n        .demo-container.editing .demo-editor {\n            display: block;\n        }\n        .demo-container.editing .demo-result {\n            display: none;\n        }\n    </style>\n</head>\n<body>\n<div class=\"wrapper\">\n    <header>\n        <h1>\n            <a href=\"https://saswatpadhi.github.io/pseudocode.js/\">pseudocode.js</a>\n        </h1>\n        <p>Beautiful pseudocode for the Web</p>\n\n        <p class=\"view\">\n            <a href=\"https://github.com/SaswatPadhi/pseudocode.js\">\n                View the Project on GitHub \n                <small>SaswatPadhi/pseudocode.js</small>\n            </a>\n        </p>\n\n        <ul>\n            <li></li>\n            <li>\n                <a onclick=\"load('katex-samples.html')\">\n                    <strong>KaTeX</strong> Samples\n                </a>\n            </li>\n            <li></li>\n        </ul>\n\n        <ul>\n            <li>\n                <a onclick=\"load('mathjax-v2-samples.html')\">\n                    <strong>MathJax 2</strong> Samples\n                </a>\n            </li>\n            <li>\n                <a onclick=\"load('mathjax-v3-samples.html')\">\n                    <strong>MathJax 3</strong> Samples\n                </a>\n            </li>\n            <li>\n                <a onclick=\"load('mathjax-v4-samples.html')\">\n                    <strong>MathJax 4</strong> Samples\n                </a>\n            </li>\n        </ul>\n\n        <ul>\n            <li>\n                <a href=\"https://github.com/SaswatPadhi/pseudocode.js/releases\">\n                    Download <strong>Releases</strong>\n                </a>\n            </li>\n            <li>\n                <a href=\"https://github.com/SaswatPadhi/pseudocode.js/zipball/master\">\n                    Download <strong>Source</strong>\n                </a>\n            </li>\n            <li>\n                <a href=\"https://github.com/SaswatPadhi/pseudocode.js\">\n                    View On <strong>GitHub</strong>\n                </a>\n            </li>\n        </ul>\n    </header>\n\n    <section id='samples' style='display: none; padding-bottom: 0;'>\n        <iframe id='samples-frame'>\n        </iframe>\n    </section>\n\n    <section id='content'>\n        <p>pseudocode.js enables JavaScript to typeset algorithms as <em>beautifully</em>\n        as LaTeX does: </p>\n\n        <div class=\"demo-container\">\n            <a class=\"btn-edit\" href=\"#\" onClick=\"toggleEdit(event)\"><div class=\"fas fa-edit button\"></div></a>\n            <a class=\"btn-done\" href=\"#\" onClick=\"toggleEdit(event)\"><div class=\"fas fa-caret-square-right button\"></div></a>\n            <div class=\"demo-result\">\n            </div>\n            <textarea class=\"demo-editor\">\n% This quicksort algorithm is extracted from Chapter 7, Introduction to Algorithms (3rd edition)\n\\begin{algorithm}\n\\caption{Quicksort}\n\\begin{algorithmic}\n\\PROCEDURE{Quicksort}{$A, p, r$}\n    \\IF{$p < r$} \n        \\STATE $q = $ \\CALL{Partition}{$A, p, r$}\n        \\STATE \\CALL{Quicksort}{$A, p, q - 1$}\n        \\STATE \\CALL{Quicksort}{$A, q + 1, r$}\n    \\ENDIF\n\\ENDPROCEDURE\n\\PROCEDURE{Partition}{$A, p, r$}\n    \\STATE $x = A[r]$\n    \\STATE $i = p - 1$\n    \\FOR{$j = p$ \\TO $r - 1$}\n        \\IF{$A[j] < x$}\n            \\STATE $i = i + 1$\n            \\STATE exchange\n            $A[i]$ with     $A[j]$\n        \\ENDIF\n        \\STATE exchange $A[i]$ with $A[r]$\n    \\ENDFOR\n\\ENDPROCEDURE\n\\end{algorithmic}\n\\end{algorithm}</textarea>\n        </div>\n        \n        <p> The demo above is editable. Feel free to experiment with it by clicking \n        on the edit button. </p>\n        \n        <h3>Features</h3>\n\n        <p>pseudocode.js is a JavaScript library that typesets pseudocode \n        beautifully to HTML: </p>\n        \n        <ul>\n            <li><strong>Intuitive grammar:</strong>\n            pseudocode.js takes a LaTeX-style input that supports the \n            algorithmic constructs from LaTeX's algorithm packages. With or \n            without LaTeX experience, a user should find the grammar fairly intuitive. \n            </li>\n            <li><strong>Print quality:</strong>\n            The HTML output produced by pseudocode.js is (almost) identical \n            with the pretty algorithms printed on publications that\n            are typeset by LaTeX.</li>\n            <li><strong>Math formula support:</strong>\n            Inserting math formulas in pseudocode.js is as easy as LaTeX. Just\n            enclose math expression in <code>$...$</code> or \n            <code>\\(...\\)</code>.\n            </li>\n        </ul>\n        </p>\n\n        <p>It supports all modern browsers, including Chrome, Safari, Firefox, Opera, and Edge. </p>\n        \n        <h3>Usage</h3>\n\n        <p style='text-align: justify;'>\n            Pseudocode.js supports multiple backends to render math formulas.\n            If you want to include any math formulas in your pseudocode,\n            please make sure that either <a href=\"https://github.com/Khan/KaTeX#usage\">KaTeX</a>\n            or <a href=\"https://www.mathjax.org/#gettingstarted\">MathJax</a>\n            is properly setup in your document.\n        </p>\n\n        <p>\n            Download <a href=\"https://github.com/SaswatPadhi/pseudocode.js/releases\">pseudocode.js</a>,\n            and host the files on your server. And then include the js and css files in your HTML files:\n        </p>\n\n        <pre><code class=\"language-html\">&lt;link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/pseudocode@latest/build/pseudocode.min.css\"&gt;\n&lt;script src=\"https://cdn.jsdelivr.net/npm/pseudocode@latest/build/pseudocode.min.js\"&gt;&lt;/script&gt;</code></pre>\n\n        <p>Place the pseudocode to be rendered in a <code>&lt;pre&gt;</code> element:</p>\n        \n        <pre><code class=\"language-html\">&lt;pre id=\"hello-world-code\"&gt;\n    \\begin{algorithmic}\n    \\PRINT \\texttt{'hello world'}\n    \\end{algorithmic}\n&lt;/pre&gt;</code></pre>\n\n        <p>\n            Finally, call <code>pseudocode.render</code> by placing the following Javascript snippet\n            at the end of your document body:\n        </p>\n\n        <pre><code class=\"language-html\">&lt;script&gt;\n    pseudocode.renderElement(document.getElementById(\"hello-world-code\"));\n&lt;/script&gt;</code></pre>\n\n        <p>\n            For more details on available options and backends, please see the\n            <a href=\"https://github.com/SaswatPadhi/pseudocode.js#usage\">usage section of README</a>.\n        </p>\n\n        <h3>Author</h3>\n        <p style='text-align: justify;'>\n            pseudocode.js was originally written by Tate Tian (<a href=\"https://github.com/tatetian\">@tatetian</a>).\n            Together with <a href=\"https://github.com/ZJUGuoShuai\">@ZJUGuoShuai</a>,\n            I (<a href=\"https://github.com/SaswatPadhi\">@SaswatPadhi</a>) added the MathJax support,\n            and I am the current maintainer of this project.\n            Suggestions, bug reports and pull requests are most welcome.\n        </p>\n\n        <h3>Acknowledgement</h3>\n        <p style='text-align: justify;'>\n            Pseudocode.js is partially inspired by <a href=\"http://khan.github.io/KaTeX/\">KaTeX</a>\n            and relies on it to render math formulas.\n            Thanks Emily Eisenberg(<a href=\"https://github.com/xymostech\">@xymostech</a>)\n            and other contributers for building such a wonderful project.\n        </p>\n    </section>\n\n    <footer>\n        <p>Project Maintainer:\n            <a href=\"https://github.com/SaswatPadhi\">Saswat Padhi</a>\n        </p>\n        <p>\n            <small>Hosted on GitHub Pages &mdash; Theme by \n                <a href=\"https://github.com/orderedlist\">orderedlist</a>\n            </small>\n        </p>\n    </footer>\n</div>\n<script src=\"javascripts/scale.fix.js\"></script>\n<script>\n    hljs.highlightAll();\n\n    function load(page) {\n        document.getElementById('content').style.display = 'none';\n        document.getElementById('samples').style.display = 'block';\n        \n        var frame = document.getElementById('samples-frame');\n        frame.setAttribute('src', page);\n        frame.height = window.innerHeight - frame.offsetTop - 32 + 'px';\n    }\n\n    var editorEl = document.getElementsByClassName('demo-editor')[0];\n\n    function renderPseudocode() {\n        var resultEl = document.getElementsByClassName('demo-result')[0];\n        resultEl.innerHTML = '';\n        var options = {\n            captionCount: 0,\n            lineNumber: true\n        };\n        pseudocode.render(editorEl.value, resultEl, options);\n    }\n\n    function toggleEdit(e) {\n        if (e) e.preventDefault();\n\n        var demoContainerEl = document.getElementsByClassName('demo-container')[0];\n        var editing = demoContainerEl.classList.contains('editing');\n        if (editing) {\n            try {\n                renderPseudocode();\n            } catch(e) {\n                console.log(e);\n                return;\n            }\n            demoContainerEl.classList.remove('editing');\n        }\n        else {\n            demoContainerEl.classList.add('editing');\n            autosize(editorEl);\n        }\n    }\n\n    renderPseudocode();\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/javascripts/scale.fix.js",
    "content": "var metas = document.getElementsByTagName('meta');\nvar i;\nif (navigator.userAgent.match(/iPhone/i)) {\n  for (i=0; i<metas.length; i++) {\n    if (metas[i].name == \"viewport\") {\n      metas[i].content = \"width=device-width, minimum-scale=1.0, maximum-scale=1.0\";\n    }\n  }\n  document.addEventListener(\"gesturestart\", gestureStart, false);\n}\nfunction gestureStart() {\n  for (i=0; i<metas.length; i++) {\n    if (metas[i].name == \"viewport\") {\n      metas[i].content = \"width=device-width, minimum-scale=0.25, maximum-scale=1.6\";\n    }\n  }\n}"
  },
  {
    "path": "docs/katex-samples.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n    <meta charset=\"utf-8\">\n    <title>pseudocode.js Samples with KaTeX</title>\n\n    <!-- Setup KaTeX -->\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js\"\n            integrity=\"sha512-EKW5YvKU3hpyyOcN6jQnAxO/L8gts+YdYV6Yymtl8pk9YlYFtqJgihORuRoBXK8/cOIlappdU6Ms8KdK6yBCgA==\"\n            crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\">\n    </script>\n\n    <!-- Pseudocode -->\n    <link rel=\"stylesheet\" href=\"pseudocode.css\" type=\"text/css\">\n    <script src=\"pseudocode.js\" type=\"text/javascript\"></script>\n</head>\n\n<body>\n    <pre id=\"test-basics\" data-line-number=true>\n        \\begin{algorithm}\n        \\caption{Test text-style}\n        \\begin{algorithmic}\n        \\REQUIRE some preconditions\n        \\ENSURE some postconditions\n        \\INPUT some inputs\n        \\OUTPUT some outputs\n        \\PROCEDURE{Test-Declarations}{}\n            \\STATE font families: {\\sffamily sffamily, \\ttfamily ttfamily, \\normalfont normalfont, \\rmfamily rmfamily.}\n            \\STATE font weights: {normal weight, \\bfseries bold, \\mdseries\n            medium, \\lfseries lighter. }\n            \\STATE font shapes: {\\itshape itshape \\scshape Small-Caps \\slshape slshape \\upshape upshape.}\n            \\STATE font sizes: \\tiny tiny \\scriptsize scriptsize \\footnotesize\n            footnotesize \\small small \\normalsize normal \\large large \\Large Large\n            \\LARGE LARGE \\huge huge \\Huge Huge \\normalsize\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Commands}{}\n            \\STATE \\textnormal{textnormal,} \\textrm{textrm,} \\textsf{textsf,} \\texttt{texttt.}\n            \\STATE \\textbf{textbf,} \\textmd{textmd,} \\textlf{textlf.}\n            \\STATE \\textup{textup,} \\textit{textit,} \\textsc{textsc,} \\textsl{textsl.}\n            \\STATE \\uppercase{uppercase,} \\lowercase{LOWERCASE.}\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Colors}{}\n            \\STATE colors: $\\color{red}{red}$, $\\color{green}{green}$, $\\color{blue}{blue}$\n            \\STATE colors: $\\color{yellow}{yellow}$, $\\color{cyan}{cyan}$, $\\color{magenta}{magenta}$\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n\n        \\begin{algorithm}\n        \\caption{Test atoms}\n        \\begin{algorithmic}\n        \\STATE \\textbf{Specials:} \\{ \\} \\$ \\& \\# \\% \\_\n        \\STATE \\textbf{Bools:} \\AND \\OR \\NOT \\TRUE \\FALSE\n        \\STATE \\textbf{Carriage return:} first line \\\\ second line\n        \\STATE \\textbf{Text-symbols:} \\textbackslash\n        \\STATE \\textbf{Quote-symbols:} `single quotes', ``double quotes''\n        \\STATE \\textbf{Math:} $(\\mathcal{C}_m)$, $i \\gets i + 1$, $E=mc^2$, \\( x^n + y^n = z^n \\), $\\$$, \\(\\$\\)\n        \\END{ALGORITHMIC}\n        \\END{ALGORITHM}\n    </pre>\n    <pre id=\"test-codes\">\n        \\begin{algorithm}\n        \\caption{Test control blocks}\n        \\begin{algorithmic}\n        \\PROCEDURE{Test-If}{}\n            \\IF{&lt;cond&gt;}\n                \\STATE &lt;block&gt;\n            \\ELIF{&lt;cond&gt;}\n                \\STATE &lt;block&gt;\n            \\ELSE\n                \\STATE &lt;block&gt;\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For}{$n$}\n            \\STATE $i \\gets 0$\n            \\FOR{$i < n$}\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-To}{$n$}\n            \\STATE $i \\gets 0$\n            \\FOR{$i$ \\TO $n$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-DownTo}{$n$}\n            \\FOR{$i \\gets n$ \\DOWNTO $0$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-All}{$n$}\n            \\FORALL{$i \\in \\{0, 1, \\cdots, n\\}$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-While}{$n$}\n            \\STATE $i \\gets 0$\n            \\WHILE{$i < n$}\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\ENDWHILE\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Repeat}{$n$}\n            \\STATE $i \\gets 0$\n            \\REPEAT\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\UNTIL{$i>n$}\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Break-Continue}{$n$}\n            \\FOR{$i = 0$ \\TO $2n$}\n                \\IF{$i < n/2$}\n                    \\CONTINUE\n                \\ELIF{$i > n$}\n                    \\BREAK\n                \\ENDIF\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n        \\begin{algorithm}\n        \\caption{Test statements and comments}\n        \\begin{algorithmic}\n        \\PROCEDURE{Test-Statements}{}\n            \\STATE This line is a normal statement\n            \\PRINT \\texttt{`this is print statement'}\n            \\RETURN $retval$\n        \\ENDPROCEDURE\n\n        \\PROCEDURE{Test-Comments}{} \\COMMENT{comment for procedure}\n            \\STATE a statement \\COMMENT{inline comment}\n            \\STATE \\COMMENT{line comment}\n            \\IF{some condition}\\COMMENT{comment for if}\n                \\RETURN \\TRUE \\COMMENT{another inline comment}\n            \\ELSE \\COMMENT{comment for else}\n                \\RETURN \\FALSE \\COMMENT{yet another inline comment}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre id=\"test-examples\" data-title-prefix=\"Procedure\">\n        % This quicksort algorithm is extracted from Chapter 7, Introduction\n        % to Algorithms (3rd edition)\n        \\begin{algorithm}\n        \\caption{Quicksort}\n        \\begin{algorithmic}\n        \\PROCEDURE{Quicksort}{$A, p, r$}\n            \\IF{$p < r$}\n                \\STATE $q = $ \\CALL{Partition}{$A, p, r$}\n                \\STATE \\CALL{Quicksort}{$A, p, q - 1$}\n                \\STATE \\CALL{Quicksort}{$A, q + 1, r$}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Partition}{$A, p, r$}\n            \\STATE $x = A[r]$\n            \\STATE $i = p - 1$\n            \\FOR{$j = p$ \\TO $r - 1$}\n                \\IF{$A[j] < x$}\n                    \\STATE $i = i + 1$\n                    \\STATE exchange\n                    $A[i]$ with $A[j]$\n                \\ENDIF\n                \\STATE exchange $A[i]$ with $A[r]$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre id=\"test-examples-custom-title\">\n        % This quicksort algorithm is extracted from Chapter 7, Introduction \n        % to Algorithms (3rd edition)\n        \\begin{algorithm}\n        \\caption{Quicksort}\n        \\begin{algorithmic}\n        \\PROCEDURE{Quicksort}{$A, p, r$}\n            \\IF{$p < r$} \n                \\STATE $q = $ \\CALL{Partition}{$A, p, r$}\n                \\STATE \\CALL{Quicksort}{$A, p, q - 1$}\n                \\STATE \\CALL{Quicksort}{$A, q + 1, r$}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Partition}{$A, p, r$}\n            \\STATE $x = A[r]$\n            \\STATE $i = p - 1$\n            \\FOR{$j = p$ \\TO $r - 1$}\n                \\IF{$A[j] < x$}\n                    \\STATE $i = i + 1$\n                    \\STATE exchange\n                    $A[i]$ with $A[j]$\n                \\ENDIF\n                \\STATE exchange $A[i]$ with $A[r]$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre class=\"scopeline-pseudocode\" data-line-number=true>\n        \\begin{algorithm}\n        \\caption{Classical Euclidean Algorithm}\n        \\begin{algorithmic}\n            \\PROCEDURE{Euclid}{$a,b$}\n                \\WHILE{$a \\neq b$}\n                    \\IF{$a > b$}\n                        \\STATE $a \\gets a - b$\n                    \\ELSE\n                        \\STATE $b \\gets b - a$\n                    \\ENDIF\n                \\ENDWHILE\n                \\RETURN $a$\n            \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre class=\"scopeline-pseudocode\" data-no-end=true>\n        \\begin{algorithm}\n        \\caption{DBSCAN}\n        \\begin{algorithmic}\n        \\INPUT A dataset $D$, the $\\varepsilon$ distance threshold, and the minimum number of points $minPts$\n        \\OUTPUT A set of clusters $K$\n        \\PROCEDURE{DBSCAN}{$D, \\varepsilon, minPts$}\n            \\STATE $K \\gets \\emptyset$\n            \\FORALL{$p \\in D$}\n                \\IF{$p$ has not been visited}\n                    \\STATE mark $p$ as visited\n                    \\STATE $N_{\\varepsilon}(p) \\gets $ \\textsc{RangeQuery}$(p, \\varepsilon, D)$\n                    \\IF{$N_{\\varepsilon}(p) < minPts$}\n                        \\STATE mark $p$ as noise\n                    \\ELSE\n                        \\COMMENT{p is a core object}\n                        \\STATE $C \\gets $ \\textsc{ExpandCluster}$(p, N_{\\varepsilon}(p))$\n                        \\STATE $K \\gets K \\cup \\{C\\}$\n                    \\ENDIF\n                \\ENDIF\n            \\ENDFOR\n            \\RETURN $K$\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <script>\n        pseudocode.renderElement(document.getElementById(\"test-basics\"),\n                                 {\n                                     lineNumber: false,\n                                     noEnd: true\n                                 });\n        pseudocode.renderElement(document.getElementById(\"test-codes\"));\n        pseudocode.renderElement(document.getElementById(\"test-examples\"),\n                                 {\n                                     lineNumber: true,\n                                     noEnd: false\n                                 });\n        pseudocode.renderElement(document.getElementById(\"test-examples-custom-title\"),\n                                 {\n                                     lineNumber: true,\n                                     noEnd: false,\n                                     titlePrefix: \"My pretty Algorithm\"\n                                 });                                   \n        pseudocode.renderClass(\"scopeline-pseudocode\", { scopeLines: true });\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/mathjax-v2-samples.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n    <meta charset=\"utf-8\">\n    <title>pseudocode.js Samples with MathJax</title>\n\n    <!-- Setup MathJax -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.9/MathJax.js?config=TeX-AMS_CHTML-full\"\n            integrity=\"sha256-DViIOMYdwlM/axqoGDPeUyf0urLoHMN4QACBKyB58Uw=\"\n            crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\">\n    </script>\n    <script type=\"text/x-mathjax-config\">\n        MathJax.Hub.Config({\n            tex2jax: {\n                inlineMath: [['$','$'], ['\\\\(','\\\\)']],\n                displayMath: [['$$','$$'], ['\\\\[','\\\\]']],\n                processEscapes: true,\n                processEnvironments: true,\n                skipTags: ['code', 'script', 'noscript', 'style', 'textarea', 'pre'],\n            }\n        });\n    </script>\n\n    <!-- Pseudocode -->\n    <link rel=\"stylesheet\" href=\"pseudocode.css\" type=\"text/css\">\n    <script src=\"pseudocode.js\" type=\"text/javascript\"></script>\n</head>\n\n<body>\n    <pre id=\"test-basics\" data-line-number=true>\n        \\begin{algorithm}\n        \\caption{Test text-style}\n        \\begin{algorithmic}\n        \\REQUIRE some preconditions\n        \\ENSURE some postconditions\n        \\INPUT some inputs\n        \\OUTPUT some outputs\n        \\PROCEDURE{Test-Declarations}{}\n            \\STATE font families: {\\sffamily sffamily, \\ttfamily ttfamily, \\normalfont normalfont, \\rmfamily rmfamily.}\n            \\STATE font weights: {normal weight, \\bfseries bold, \\mdseries\n            medium, \\lfseries lighter. }\n            \\STATE font shapes: {\\itshape itshape \\scshape Small-Caps \\slshape slshape \\upshape upshape.}\n            \\STATE font sizes: \\tiny tiny \\scriptsize scriptsize \\footnotesize\n            footnotesize \\small small \\normalsize normal \\large large \\Large Large\n            \\LARGE LARGE \\huge huge \\Huge Huge \\normalsize\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Commands}{}\n            \\STATE \\textnormal{textnormal,} \\textrm{textrm,} \\textsf{textsf,} \\texttt{texttt.}\n            \\STATE \\textbf{textbf,} \\textmd{textmd,} \\textlf{textlf.}\n            \\STATE \\textup{textup,} \\textit{textit,} \\textsc{textsc,} \\textsl{textsl.}\n            \\STATE \\uppercase{uppercase,} \\lowercase{LOWERCASE.}\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Colors}{}\n            \\STATE colors: $\\color{red}{red}$, $\\color{green}{green}$, $\\color{blue}{blue}$\n            \\STATE colors: $\\color{yellow}{yellow}$, $\\color{cyan}{cyan}$, $\\color{magenta}{magenta}$\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n\n        \\begin{algorithm}\n        \\caption{Test atoms}\n        \\begin{algorithmic}\n        \\STATE \\textbf{Specials:} \\{ \\} \\$ \\& \\# \\% \\_\n        \\STATE \\textbf{Bools:} \\AND \\OR \\NOT \\TRUE \\FALSE\n        \\STATE \\textbf{Carriage return:} first line \\\\ second line\n        \\STATE \\textbf{Text-symbols:} \\textbackslash\n        \\STATE \\textbf{Quote-symbols:} `single quotes', ``double quotes''\n        \\STATE \\textbf{Math:} $(\\mathcal{C}_m)$, $i \\gets i + 1$, $E=mc^2$, \\( x^n + y^n = z^n \\), $\\$$, \\(\\$\\)\n        \\END{ALGORITHMIC}\n        \\END{ALGORITHM}\n    </pre>\n    <pre id=\"test-codes\">\n        \\begin{algorithm}\n        \\caption{Test control blocks}\n        \\begin{algorithmic}\n        \\PROCEDURE{Test-If}{}\n            \\IF{&lt;cond&gt;}\n                \\STATE &lt;block&gt;\n            \\ELIF{&lt;cond&gt;}\n                \\STATE &lt;block&gt;\n            \\ELSE\n                \\STATE &lt;block&gt;\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For}{$n$}\n            \\STATE $i \\gets 0$\n            \\FOR{$i < n$}\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-To}{$n$}\n            \\STATE $i \\gets 0$\n            \\FOR{$i$ \\TO $n$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-DownTo}{$n$}\n            \\FOR{$i \\gets n$ \\DOWNTO $0$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-All}{$n$}\n            \\FORALL{$i \\in \\{0, 1, \\cdots, n\\}$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-While}{$n$}\n            \\STATE $i \\gets 0$\n            \\WHILE{$i < n$}\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\ENDWHILE\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Repeat}{$n$}\n            \\STATE $i \\gets 0$\n            \\REPEAT\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\UNTIL{$i>n$}\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Break-Continue}{$n$}\n            \\FOR{$i = 0$ \\TO $2n$}\n                \\IF{$i < n/2$}\n                    \\CONTINUE\n                \\ELIF{$i > n$}\n                    \\BREAK\n                \\ENDIF\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n        \\begin{algorithm}\n        \\caption{Test statements and comments}\n        \\begin{algorithmic}\n        \\PROCEDURE{Test-Statements}{}\n            \\STATE This line is a normal statement\n            \\PRINT \\texttt{`this is print statement'}\n            \\RETURN $retval$\n        \\ENDPROCEDURE\n\n        \\PROCEDURE{Test-Comments}{} \\COMMENT{comment for procedure}\n            \\STATE a statement \\COMMENT{inline comment}\n            \\STATE \\COMMENT{line comment}\n            \\IF{some condition}\\COMMENT{comment for if}\n                \\RETURN \\TRUE \\COMMENT{another inline comment}\n            \\ELSE \\COMMENT{comment for else}\n                \\RETURN \\FALSE \\COMMENT{yet another inline comment}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre id=\"test-examples\" data-title-prefix=\"Procedure\">\n        % This quicksort algorithm is extracted from Chapter 7, Introduction\n        % to Algorithms (3rd edition)\n        \\begin{algorithm}\n        \\caption{Quicksort}\n        \\begin{algorithmic}\n        \\PROCEDURE{Quicksort}{$A, p, r$}\n            \\IF{$p < r$}\n                \\STATE $q = $ \\CALL{Partition}{$A, p, r$}\n                \\STATE \\CALL{Quicksort}{$A, p, q - 1$}\n                \\STATE \\CALL{Quicksort}{$A, q + 1, r$}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Partition}{$A, p, r$}\n            \\STATE $x = A[r]$\n            \\STATE $i = p - 1$\n            \\FOR{$j = p$ \\TO $r - 1$}\n                \\IF{$A[j] < x$}\n                    \\STATE $i = i + 1$\n                    \\STATE exchange\n                    $A[i]$ with $A[j]$\n                \\ENDIF\n                \\STATE exchange $A[i]$ with $A[r]$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre id=\"test-examples-custom-title\">\n        % This quicksort algorithm is extracted from Chapter 7, Introduction \n        % to Algorithms (3rd edition)\n        \\begin{algorithm}\n        \\caption{Quicksort}\n        \\begin{algorithmic}\n        \\PROCEDURE{Quicksort}{$A, p, r$}\n            \\IF{$p < r$} \n                \\STATE $q = $ \\CALL{Partition}{$A, p, r$}\n                \\STATE \\CALL{Quicksort}{$A, p, q - 1$}\n                \\STATE \\CALL{Quicksort}{$A, q + 1, r$}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Partition}{$A, p, r$}\n            \\STATE $x = A[r]$\n            \\STATE $i = p - 1$\n            \\FOR{$j = p$ \\TO $r - 1$}\n                \\IF{$A[j] < x$}\n                    \\STATE $i = i + 1$\n                    \\STATE exchange\n                    $A[i]$ with $A[j]$\n                \\ENDIF\n                \\STATE exchange $A[i]$ with $A[r]$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre class=\"scopeline-pseudocode\" data-line-number=true>\n        \\begin{algorithm}\n        \\caption{Classical Euclidean Algorithm}\n        \\begin{algorithmic}\n            \\PROCEDURE{Euclid}{$a,b$}\n                \\WHILE{$a \\neq b$}\n                    \\IF{$a > b$}\n                        \\STATE $a \\gets a - b$\n                    \\ELSE\n                        \\STATE $b \\gets b - a$\n                    \\ENDIF\n                \\ENDWHILE\n                \\RETURN $a$\n            \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre class=\"scopeline-pseudocode\" data-no-end=true>\n        \\begin{algorithm}\n        \\caption{DBSCAN}\n        \\begin{algorithmic}\n        \\INPUT A dataset $D$, the $\\varepsilon$ distance threshold, and the minimum number of points $minPts$\n        \\OUTPUT A set of clusters $K$\n        \\PROCEDURE{DBSCAN}{$D, \\varepsilon, minPts$}\n            \\STATE $K \\gets \\emptyset$\n            \\FORALL{$p \\in D$}\n                \\IF{$p$ has not been visited}\n                    \\STATE mark $p$ as visited\n                    \\STATE $N_{\\varepsilon}(p) \\gets $ \\textsc{RangeQuery}$(p, \\varepsilon, D)$\n                    \\IF{$N_{\\varepsilon}(p) < minPts$}\n                        \\STATE mark $p$ as noise\n                    \\ELSE\n                        \\COMMENT{p is a core object}\n                        \\STATE $C \\gets $ \\textsc{ExpandCluster}$(p, N_{\\varepsilon}(p))$\n                        \\STATE $K \\gets K \\cup \\{C\\}$\n                    \\ENDIF\n                \\ENDIF\n            \\ENDFOR\n            \\RETURN $K$\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <script>\n        pseudocode.renderElement(document.getElementById(\"test-basics\"),\n                                 {\n                                     lineNumber: false,\n                                     noEnd: true\n                                 });\n        pseudocode.renderElement(document.getElementById(\"test-codes\"));\n        pseudocode.renderElement(document.getElementById(\"test-examples\"),\n                                 {\n                                     lineNumber: true,\n                                     noEnd: false\n                                 });\n        pseudocode.renderElement(document.getElementById(\"test-examples-custom-title\"),\n                                 {\n                                     lineNumber: true,\n                                     noEnd: false,\n                                     titlePrefix: \"My pretty Algorithm\"\n                                 });                                   \n        pseudocode.renderClass(\"scopeline-pseudocode\", { scopeLines: true });\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/mathjax-v3-samples.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n    <meta charset=\"utf-8\">\n    <title>pseudocode.js Samples with MathJax</title>\n\n    <!-- Setup MathJax -->\n    <script>\n        MathJax = {\n            tex: {\n                inlineMath: [['$','$'], ['\\\\(','\\\\)']],\n                displayMath: [['$$','$$'], ['\\\\[','\\\\]']],\n                processEscapes: true,\n                processEnvironments: true,\n            }\n        }\n    </script>\n    <script src=\"https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/tex-chtml-full.js\"\n            integrity=\"sha256-kbAFUDxdHwlYv01zraGjvjNZayxKtdoiJ38bDTFJtaQ=\"\n            crossorigin=\"anonymous\">\n    </script>\n\n    <!-- Pseudocode -->\n    <link rel=\"stylesheet\" href=\"pseudocode.css\" type=\"text/css\">\n    <script src=\"pseudocode.js\" type=\"text/javascript\"></script>\n</head>\n\n<body>\n    <pre id=\"test-basics\" data-line-number=true>\n        \\begin{algorithm}\n        \\caption{Test text-style}\n        \\begin{algorithmic}\n        \\REQUIRE some preconditions\n        \\ENSURE some postconditions\n        \\INPUT some inputs\n        \\OUTPUT some outputs\n        \\PROCEDURE{Test-Declarations}{}\n            \\STATE font families: {\\sffamily sffamily, \\ttfamily ttfamily, \\normalfont normalfont, \\rmfamily rmfamily.}\n            \\STATE font weights: {normal weight, \\bfseries bold, \\mdseries\n            medium, \\lfseries lighter. }\n            \\STATE font shapes: {\\itshape itshape \\scshape Small-Caps \\slshape slshape \\upshape upshape.}\n            \\STATE font sizes: \\tiny tiny \\scriptsize scriptsize \\footnotesize\n            footnotesize \\small small \\normalsize normal \\large large \\Large Large\n            \\LARGE LARGE \\huge huge \\Huge Huge \\normalsize\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Commands}{}\n            \\STATE \\textnormal{textnormal,} \\textrm{textrm,} \\textsf{textsf,} \\texttt{texttt.}\n            \\STATE \\textbf{textbf,} \\textmd{textmd,} \\textlf{textlf.}\n            \\STATE \\textup{textup,} \\textit{textit,} \\textsc{textsc,} \\textsl{textsl.}\n            \\STATE \\uppercase{uppercase,} \\lowercase{LOWERCASE.}\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Colors}{}\n            \\STATE colors: $\\color{red}{red}$, $\\color{green}{green}$, $\\color{blue}{blue}$\n            \\STATE colors: $\\color{yellow}{yellow}$, $\\color{cyan}{cyan}$, $\\color{magenta}{magenta}$\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n\n        \\begin{algorithm}\n        \\caption{Test atoms}\n        \\begin{algorithmic}\n        \\STATE \\textbf{Specials:} \\{ \\} \\$ \\& \\# \\% \\_\n        \\STATE \\textbf{Bools:} \\AND \\OR \\NOT \\TRUE \\FALSE\n        \\STATE \\textbf{Carriage return:} first line \\\\ second line\n        \\STATE \\textbf{Text-symbols:} \\textbackslash\n        \\STATE \\textbf{Quote-symbols:} `single quotes', ``double quotes''\n        \\STATE \\textbf{Math:} $(\\mathcal{C}_m)$, $i \\gets i + 1$, $E=mc^2$, \\( x^n + y^n = z^n \\), $\\$$, \\(\\$\\)\n        \\END{ALGORITHMIC}\n        \\END{ALGORITHM}\n    </pre>\n    <pre id=\"test-codes\">\n        \\begin{algorithm}\n        \\caption{Test control blocks}\n        \\begin{algorithmic}\n        \\PROCEDURE{Test-If}{}\n            \\IF{&lt;cond&gt;}\n                \\STATE &lt;block&gt;\n            \\ELIF{&lt;cond&gt;}\n                \\STATE &lt;block&gt;\n            \\ELSE\n                \\STATE &lt;block&gt;\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For}{$n$}\n            \\STATE $i \\gets 0$\n            \\FOR{$i < n$}\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-To}{$n$}\n            \\STATE $i \\gets 0$\n            \\FOR{$i$ \\TO $n$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-DownTo}{$n$}\n            \\FOR{$i \\gets n$ \\DOWNTO $0$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-All}{$n$}\n            \\FORALL{$i \\in \\{0, 1, \\cdots, n\\}$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-While}{$n$}\n            \\STATE $i \\gets 0$\n            \\WHILE{$i < n$}\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\ENDWHILE\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Repeat}{$n$}\n            \\STATE $i \\gets 0$\n            \\REPEAT\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\UNTIL{$i>n$}\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Break-Continue}{$n$}\n            \\FOR{$i = 0$ \\TO $2n$}\n                \\IF{$i < n/2$}\n                    \\CONTINUE\n                \\ELIF{$i > n$}\n                    \\BREAK\n                \\ENDIF\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n        \\begin{algorithm}\n        \\caption{Test statements and comments}\n        \\begin{algorithmic}\n        \\PROCEDURE{Test-Statements}{}\n            \\STATE This line is a normal statement\n            \\PRINT \\texttt{`this is print statement'}\n            \\RETURN $retval$\n        \\ENDPROCEDURE\n\n        \\PROCEDURE{Test-Comments}{} \\COMMENT{comment for procedure}\n            \\STATE a statement \\COMMENT{inline comment}\n            \\STATE \\COMMENT{line comment}\n            \\IF{some condition}\\COMMENT{comment for if}\n                \\RETURN \\TRUE \\COMMENT{another inline comment}\n            \\ELSE \\COMMENT{comment for else}\n                \\RETURN \\FALSE \\COMMENT{yet another inline comment}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre id=\"test-examples\" data-title-prefix=\"Procedure\">\n        % This quicksort algorithm is extracted from Chapter 7, Introduction\n        % to Algorithms (3rd edition)\n        \\begin{algorithm}\n        \\caption{Quicksort}\n        \\begin{algorithmic}\n        \\PROCEDURE{Quicksort}{$A, p, r$}\n            \\IF{$p < r$}\n                \\STATE $q = $ \\CALL{Partition}{$A, p, r$}\n                \\STATE \\CALL{Quicksort}{$A, p, q - 1$}\n                \\STATE \\CALL{Quicksort}{$A, q + 1, r$}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Partition}{$A, p, r$}\n            \\STATE $x = A[r]$\n            \\STATE $i = p - 1$\n            \\FOR{$j = p$ \\TO $r - 1$}\n                \\IF{$A[j] < x$}\n                    \\STATE $i = i + 1$\n                    \\STATE exchange\n                    $A[i]$ with $A[j]$\n                \\ENDIF\n                \\STATE exchange $A[i]$ with $A[r]$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre id=\"test-examples-custom-title\">\n        % This quicksort algorithm is extracted from Chapter 7, Introduction \n        % to Algorithms (3rd edition)\n        \\begin{algorithm}\n        \\caption{Quicksort}\n        \\begin{algorithmic}\n        \\PROCEDURE{Quicksort}{$A, p, r$}\n            \\IF{$p < r$} \n                \\STATE $q = $ \\CALL{Partition}{$A, p, r$}\n                \\STATE \\CALL{Quicksort}{$A, p, q - 1$}\n                \\STATE \\CALL{Quicksort}{$A, q + 1, r$}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Partition}{$A, p, r$}\n            \\STATE $x = A[r]$\n            \\STATE $i = p - 1$\n            \\FOR{$j = p$ \\TO $r - 1$}\n                \\IF{$A[j] < x$}\n                    \\STATE $i = i + 1$\n                    \\STATE exchange\n                    $A[i]$ with $A[j]$\n                \\ENDIF\n                \\STATE exchange $A[i]$ with $A[r]$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre class=\"scopeline-pseudocode\" data-line-number=true>\n        \\begin{algorithm}\n        \\caption{Classical Euclidean Algorithm}\n        \\begin{algorithmic}\n            \\PROCEDURE{Euclid}{$a,b$}\n                \\WHILE{$a \\neq b$}\n                    \\IF{$a > b$}\n                        \\STATE $a \\gets a - b$\n                    \\ELSE\n                        \\STATE $b \\gets b - a$\n                    \\ENDIF\n                \\ENDWHILE\n                \\RETURN $a$\n            \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre class=\"scopeline-pseudocode\" data-no-end=true>\n        \\begin{algorithm}\n        \\caption{DBSCAN}\n        \\begin{algorithmic}\n        \\INPUT A dataset $D$, the $\\varepsilon$ distance threshold, and the minimum number of points $minPts$\n        \\OUTPUT A set of clusters $K$\n        \\PROCEDURE{DBSCAN}{$D, \\varepsilon, minPts$}\n            \\STATE $K \\gets \\emptyset$\n            \\FORALL{$p \\in D$}\n                \\IF{$p$ has not been visited}\n                    \\STATE mark $p$ as visited\n                    \\STATE $N_{\\varepsilon}(p) \\gets $ \\textsc{RangeQuery}$(p, \\varepsilon, D)$\n                    \\IF{$N_{\\varepsilon}(p) < minPts$}\n                        \\STATE mark $p$ as noise\n                    \\ELSE\n                        \\COMMENT{p is a core object}\n                        \\STATE $C \\gets $ \\textsc{ExpandCluster}$(p, N_{\\varepsilon}(p))$\n                        \\STATE $K \\gets K \\cup \\{C\\}$\n                    \\ENDIF\n                \\ENDIF\n            \\ENDFOR\n            \\RETURN $K$\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <script>\n        pseudocode.renderElement(document.getElementById(\"test-basics\"),\n                                 {\n                                     lineNumber: false,\n                                     noEnd: true\n                                 });\n        pseudocode.renderElement(document.getElementById(\"test-codes\"));\n        pseudocode.renderElement(document.getElementById(\"test-examples\"),\n                                 {\n                                     lineNumber: true,\n                                     noEnd: false\n                                 });\n        pseudocode.renderElement(document.getElementById(\"test-examples-custom-title\"),\n                                 {\n                                     lineNumber: true,\n                                     noEnd: false,\n                                     titlePrefix: \"My pretty Algorithm\"\n                                 });                                   \n        pseudocode.renderClass(\"scopeline-pseudocode\", { scopeLines: true });\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/mathjax-v4-samples.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n    <meta charset=\"utf-8\">\n    <title>pseudocode.js Samples with MathJax</title>\n\n    <!-- Setup MathJax -->\n    <script>\n        MathJax = {\n            tex: {\n                inlineMath: [['$','$'], ['\\\\(','\\\\)']],\n                displayMath: [['$$','$$'], ['\\\\[','\\\\]']],\n                processEscapes: true,\n                processEnvironments: true,\n            }\n        }\n    </script>\n    <script src=\"https://cdn.jsdelivr.net/npm/mathjax@4.0.0-beta.3/tex-chtml.js\"\n            integrity=\"sha256-ljPODBK7Jf/VfUrVqec63xzZbysEmwB9Ab20TWRMQRU=\"\n            crossorigin=\"anonymous\">\n    </script>\n\n    <!-- Pseudocode -->\n    <link rel=\"stylesheet\" href=\"pseudocode.css\" type=\"text/css\">\n    <script src=\"pseudocode.js\" type=\"text/javascript\"></script>\n</head>\n\n<body>\n    <pre id=\"test-basics\" data-line-number=true>\n        \\begin{algorithm}\n        \\caption{Test text-style}\n        \\begin{algorithmic}\n        \\REQUIRE some preconditions\n        \\ENSURE some postconditions\n        \\INPUT some inputs\n        \\OUTPUT some outputs\n        \\PROCEDURE{Test-Declarations}{}\n            \\STATE font families: {\\sffamily sffamily, \\ttfamily ttfamily, \\normalfont normalfont, \\rmfamily rmfamily.}\n            \\STATE font weights: {normal weight, \\bfseries bold, \\mdseries\n            medium, \\lfseries lighter. }\n            \\STATE font shapes: {\\itshape itshape \\scshape Small-Caps \\slshape slshape \\upshape upshape.}\n            \\STATE font sizes: \\tiny tiny \\scriptsize scriptsize \\footnotesize\n            footnotesize \\small small \\normalsize normal \\large large \\Large Large\n            \\LARGE LARGE \\huge huge \\Huge Huge \\normalsize\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Commands}{}\n            \\STATE \\textnormal{textnormal,} \\textrm{textrm,} \\textsf{textsf,} \\texttt{texttt.}\n            \\STATE \\textbf{textbf,} \\textmd{textmd,} \\textlf{textlf.}\n            \\STATE \\textup{textup,} \\textit{textit,} \\textsc{textsc,} \\textsl{textsl.}\n            \\STATE \\uppercase{uppercase,} \\lowercase{LOWERCASE.}\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Colors}{}\n            \\STATE colors: $\\color{red}{red}$, $\\color{green}{green}$, $\\color{blue}{blue}$\n            \\STATE colors: $\\color{yellow}{yellow}$, $\\color{cyan}{cyan}$, $\\color{magenta}{magenta}$\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n\n        \\begin{algorithm}\n        \\caption{Test atoms}\n        \\begin{algorithmic}\n        \\STATE \\textbf{Specials:} \\{ \\} \\$ \\& \\# \\% \\_\n        \\STATE \\textbf{Bools:} \\AND \\OR \\NOT \\TRUE \\FALSE\n        \\STATE \\textbf{Carriage return:} first line \\\\ second line\n        \\STATE \\textbf{Text-symbols:} \\textbackslash\n        \\STATE \\textbf{Quote-symbols:} `single quotes', ``double quotes''\n        \\STATE \\textbf{Math:} $(\\mathcal{C}_m)$, $i \\gets i + 1$, $E=mc^2$, \\( x^n + y^n = z^n \\), $\\$$, \\(\\$\\)\n        \\END{ALGORITHMIC}\n        \\END{ALGORITHM}\n    </pre>\n    <pre id=\"test-codes\">\n        \\begin{algorithm}\n        \\caption{Test control blocks}\n        \\begin{algorithmic}\n        \\PROCEDURE{Test-If}{}\n            \\IF{&lt;cond&gt;}\n                \\STATE &lt;block&gt;\n            \\ELIF{&lt;cond&gt;}\n                \\STATE &lt;block&gt;\n            \\ELSE\n                \\STATE &lt;block&gt;\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For}{$n$}\n            \\STATE $i \\gets 0$\n            \\FOR{$i < n$}\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-To}{$n$}\n            \\STATE $i \\gets 0$\n            \\FOR{$i$ \\TO $n$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-DownTo}{$n$}\n            \\FOR{$i \\gets n$ \\DOWNTO $0$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-All}{$n$}\n            \\FORALL{$i \\in \\{0, 1, \\cdots, n\\}$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-While}{$n$}\n            \\STATE $i \\gets 0$\n            \\WHILE{$i < n$}\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\ENDWHILE\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Repeat}{$n$}\n            \\STATE $i \\gets 0$\n            \\REPEAT\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\UNTIL{$i>n$}\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Break-Continue}{$n$}\n            \\FOR{$i = 0$ \\TO $2n$}\n                \\IF{$i < n/2$}\n                    \\CONTINUE\n                \\ELIF{$i > n$}\n                    \\BREAK\n                \\ENDIF\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n        \\begin{algorithm}\n        \\caption{Test statements and comments}\n        \\begin{algorithmic}\n        \\PROCEDURE{Test-Statements}{}\n            \\STATE This line is a normal statement\n            \\PRINT \\texttt{`this is print statement'}\n            \\RETURN $retval$\n        \\ENDPROCEDURE\n\n        \\PROCEDURE{Test-Comments}{} \\COMMENT{comment for procedure}\n            \\STATE a statement \\COMMENT{inline comment}\n            \\STATE \\COMMENT{line comment}\n            \\IF{some condition}\\COMMENT{comment for if}\n                \\RETURN \\TRUE \\COMMENT{another inline comment}\n            \\ELSE \\COMMENT{comment for else}\n                \\RETURN \\FALSE \\COMMENT{yet another inline comment}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre id=\"test-examples\" data-title-prefix=\"Procedure\">\n        % This quicksort algorithm is extracted from Chapter 7, Introduction\n        % to Algorithms (3rd edition)\n        \\begin{algorithm}\n        \\caption{Quicksort}\n        \\begin{algorithmic}\n        \\PROCEDURE{Quicksort}{$A, p, r$}\n            \\IF{$p < r$}\n                \\STATE $q = $ \\CALL{Partition}{$A, p, r$}\n                \\STATE \\CALL{Quicksort}{$A, p, q - 1$}\n                \\STATE \\CALL{Quicksort}{$A, q + 1, r$}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Partition}{$A, p, r$}\n            \\STATE $x = A[r]$\n            \\STATE $i = p - 1$\n            \\FOR{$j = p$ \\TO $r - 1$}\n                \\IF{$A[j] < x$}\n                    \\STATE $i = i + 1$\n                    \\STATE exchange\n                    $A[i]$ with $A[j]$\n                \\ENDIF\n                \\STATE exchange $A[i]$ with $A[r]$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre id=\"test-examples-custom-title\">\n        % This quicksort algorithm is extracted from Chapter 7, Introduction \n        % to Algorithms (3rd edition)\n        \\begin{algorithm}\n        \\caption{Quicksort}\n        \\begin{algorithmic}\n        \\PROCEDURE{Quicksort}{$A, p, r$}\n            \\IF{$p < r$} \n                \\STATE $q = $ \\CALL{Partition}{$A, p, r$}\n                \\STATE \\CALL{Quicksort}{$A, p, q - 1$}\n                \\STATE \\CALL{Quicksort}{$A, q + 1, r$}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Partition}{$A, p, r$}\n            \\STATE $x = A[r]$\n            \\STATE $i = p - 1$\n            \\FOR{$j = p$ \\TO $r - 1$}\n                \\IF{$A[j] < x$}\n                    \\STATE $i = i + 1$\n                    \\STATE exchange\n                    $A[i]$ with $A[j]$\n                \\ENDIF\n                \\STATE exchange $A[i]$ with $A[r]$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre class=\"scopeline-pseudocode\" data-line-number=true>\n        \\begin{algorithm}\n        \\caption{Classical Euclidean Algorithm}\n        \\begin{algorithmic}\n            \\PROCEDURE{Euclid}{$a,b$}\n                \\WHILE{$a \\neq b$}\n                    \\IF{$a > b$}\n                        \\STATE $a \\gets a - b$\n                    \\ELSE\n                        \\STATE $b \\gets b - a$\n                    \\ENDIF\n                \\ENDWHILE\n                \\RETURN $a$\n            \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre class=\"scopeline-pseudocode\" data-no-end=true>\n        \\begin{algorithm}\n        \\caption{DBSCAN}\n        \\begin{algorithmic}\n        \\INPUT A dataset $D$, the $\\varepsilon$ distance threshold, and the minimum number of points $minPts$\n        \\OUTPUT A set of clusters $K$\n        \\PROCEDURE{DBSCAN}{$D, \\varepsilon, minPts$}\n            \\STATE $K \\gets \\emptyset$\n            \\FORALL{$p \\in D$}\n                \\IF{$p$ has not been visited}\n                    \\STATE mark $p$ as visited\n                    \\STATE $N_{\\varepsilon}(p) \\gets $ \\textsc{RangeQuery}$(p, \\varepsilon, D)$\n                    \\IF{$N_{\\varepsilon}(p) < minPts$}\n                        \\STATE mark $p$ as noise\n                    \\ELSE\n                        \\COMMENT{p is a core object}\n                        \\STATE $C \\gets $ \\textsc{ExpandCluster}$(p, N_{\\varepsilon}(p))$\n                        \\STATE $K \\gets K \\cup \\{C\\}$\n                    \\ENDIF\n                \\ENDIF\n            \\ENDFOR\n            \\RETURN $K$\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <script>\n        pseudocode.renderElement(document.getElementById(\"test-basics\"),\n                                 {\n                                     lineNumber: false,\n                                     noEnd: true\n                                 });\n        pseudocode.renderElement(document.getElementById(\"test-codes\"));\n        pseudocode.renderElement(document.getElementById(\"test-examples\"),\n                                 {\n                                     lineNumber: true,\n                                     noEnd: false\n                                 });\n        pseudocode.renderElement(document.getElementById(\"test-examples-custom-title\"),\n                                 {\n                                     lineNumber: true,\n                                     noEnd: false,\n                                     titlePrefix: \"My pretty Algorithm\"\n                                 });                                   \n        pseudocode.renderClass(\"scopeline-pseudocode\", { scopeLines: true });\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "docs/params.json",
    "content": "{\n    \"name\": \"pseudocode.js\",\n    \"tagline\": \"Beautiful TeX-style pseudocode for the Web\",\n    \"body\": \"### Welcome to GitHub Pages.\\r\\nThis automatic page generator is the easiest way to create beautiful pages for all of your projects. Author your page content here using GitHub Flavored Markdown, select a template crafted by a designer, and publish. After your page is generated, you can check out the new branch:\\r\\n\\r\\n```\\r\\n$ cd your_repo_root/repo_name\\r\\n$ git fetch origin\\r\\n$ git checkout gh-pages\\r\\n```\\r\\n\\r\\nIf you're using the GitHub for Mac, simply sync your repository and you'll see the new branch.\\r\\n\\r\\n### Designer Templates\\r\\nWe've crafted some handsome templates for you to use. Go ahead and continue to layouts to browse through them. You can easily go back to edit your page before publishing. After publishing your page, you can revisit the page generator and switch to another theme. Your Page content will be preserved if it remained markdown format.\\r\\n\\r\\n### Rather Drive Stick?\\r\\nIf you prefer to not use the automatic generator, push a branch named `gh-pages` to your repository to create a page manually. In addition to supporting regular HTML content, GitHub Pages support Jekyll, a simple, blog aware static site generator written by our own Tom Preston-Werner. Jekyll makes it easy to create site-wide headers and footers without having to copy them across every page. It also offers intelligent blog support and other advanced templating features.\\r\\n\\r\\n### Authors and Contributors\\r\\nYou can @mention a GitHub username to generate a link to their profile. The resulting `<a>` element will link to the contributor's GitHub Profile. For example: In 2007, Chris Wanstrath (@defunkt), PJ Hyett (@pjhyett), and Tom Preston-Werner (@mojombo) founded GitHub.\\r\\n\\r\\n### Support or Contact\\r\\nHaving trouble with Pages? Check out the documentation at https://help.github.com/pages or contact support@github.com and we’ll help you sort it out.\\r\\n\",\n    \"google\": \"\",\n    \"note\": \"Don't delete this file! It's used internally to help with page regeneration.\"\n}"
  },
  {
    "path": "docs/pseudocode.css",
    "content": "@import url(https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.css);.ps-root{font-family:KaTeX_Main,'Times New Roman',Times,serif;font-size:1em;font-weight:100;-webkit-font-smoothing:antialiased!important}.ps-root .ps-algorithm{margin:.8em 0;border-top:3px solid #000;border-bottom:2px solid #000}.ps-root .ps-algorithm.with-caption>.ps-line:first-child{border-bottom:2px solid #000}.ps-root .katex{text-indent:0;font-size:1em}.ps-root .MathJax,.ps-root .MathJax_CHTML{text-indent:0;font-size:1em!important}.ps-root .ps-line{margin:0;padding:0;line-height:1.2}.ps-root .ps-funcname{font-family:KaTeX_Main,'Times New Roman',Times,serif;font-weight:400;font-variant:small-caps;font-style:normal;text-transform:none}.ps-root .ps-keyword{font-family:KaTeX_Main,'Times New Roman',Times,serif;font-weight:700;font-variant:normal;font-style:normal;text-transform:none}.ps-root .ps-comment{font-family:KaTeX_Main,'Times New Roman',Times,serif;font-weight:400;font-variant:normal;font-style:normal;text-transform:none}.ps-root .ps-linenum{font-size:.8em;line-height:1em;width:1.6em;text-align:right;display:inline-block;position:relative;padding-right:.3em}.ps-root .ps-algorithmic.with-linenum .ps-line.ps-code{text-indent:-1.6em}.ps-root .ps-algorithmic.with-linenum .ps-line.ps-code>span{text-indent:0}.ps-root .ps-algorithmic.with-scopelines div.ps-block{border-left-style:solid;border-left-width:.1em;padding-left:.6em}.ps-root .ps-algorithmic.with-scopelines>div.ps-block{border-left:none}"
  },
  {
    "path": "docs/pseudocode.js",
    "content": "(function(e){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=e()}else if(typeof define===\"function\"&&define.amd){define([],e)}else{var t;if(typeof window!==\"undefined\"){t=window}else if(typeof global!==\"undefined\"){t=global}else if(typeof self!==\"undefined\"){t=self}else{t=this}t.pseudocode=e()}})(function(){var e,t,n;return function(){function p(o,s,a){function l(n,e){if(!s[n]){if(!o[n]){var t=\"function\"==typeof require&&require;if(!e&&t)return t(n,!0);if(h)return h(n,!0);var i=new Error(\"Cannot find module '\"+n+\"'\");throw i.code=\"MODULE_NOT_FOUND\",i}var r=s[n]={exports:{}};o[n][0].call(r.exports,function(e){var t=o[n][1][e];return l(t||e)},r,r.exports,p,o,s,a)}return s[n].exports}for(var h=\"function\"==typeof require&&require,e=0;e<a.length;e++)l(a[e]);return l}return p}()({1:[function(e,t,n){var i=e(\"./src/ParseError\");var r=e(\"./src/Lexer\");var o=e(\"./src/Parser\");var s=e(\"./src/Renderer\");function a(e,t){var n=new r(e);var i=new o(n);return new s(i,t)}t.exports={ParseError:i,render:function(e,t,n){if(e===null||e===undefined)throw new ReferenceError(\"Input cannot be empty\");var i=a(e,n);var r=i.toDOM();if(t)t.appendChild(r);if(i.backend&&i.backend.name===\"mathjax\"){if(MathJax.version<3)MathJax.Hub.Queue([\"Typeset\",MathJax.Hub,r]);else if(MathJax.version>3)MathJax.typeset()}return r},renderToString:function(e,t){if(e===null||e===undefined)throw new ReferenceError(\"Input cannot be empty\");var n=a(e,t);if(n.backend&&n.backend.name===\"mathjax\"&&n.backend.version<3){console.warn(\"`renderToString` is fully supported only on MathJax backend 3.x.\\n\"+\"Math ($...$) will not be rendered to HTML and will be left as is.\")}return n.toMarkup()},renderElement:function(e,t){if(!(e instanceof Element))throw new ReferenceError(\"A DOM element is required\");e.style.display=\"none\";var n=JSON.parse(JSON.stringify(t||{}));for(const o in e.dataset)n[o]=e.dataset[o];var i=a(e.textContent,n);var r=i.toDOM();e.replaceWith(r);if(i.backend&&i.backend.name===\"mathjax\"){if(MathJax.version<3)MathJax.Hub.Queue([\"Typeset\",MathJax.Hub,e]);else if(MathJax.version>3)MathJax.typeset()}},renderClass:function(e,t){[...document.getElementsByClassName(e)].forEach(e=>this.renderElement(e,t))}}},{\"./src/Lexer\":2,\"./src/ParseError\":3,\"./src/Parser\":4,\"./src/Renderer\":5}],2:[function(e,t,n){var i=e(\"./utils\");var u=e(\"./ParseError\");var r=function(e){this._input=e;this._remain=e;this._pos=0;this._nextAtom=this._currentAtom=null;this._next()};r.prototype.accept=function(e,t){if(this._nextAtom.type===e&&this._matchText(t)){this._next();return this._currentAtom.text}return null};r.prototype.expect=function(e,t){var n=this._nextAtom;if(n.type!==e){throw new u(`Expected an atom of ${e} but received ${n.type}`,this._pos,this._input)}if(!this._matchText(t)){throw new u(`Expected \\`${t}\\` but received \\`${n.text}\\``,this._pos,this._input)}this._next();return this._currentAtom.text};r.prototype.get=function(){return this._currentAtom};var o={exec:function(e){var t=[{start:\"$\",end:\"$\"},{start:\"\\\\(\",end:\"\\\\)\"}];var n=e.length;for(var i=0;i<t.length;i++){var r=t[i].start;if(e.indexOf(r)!==0)continue;var o=t[i].end;var s=r.length;var a=e.slice(s);while(s<n){var l=a.indexOf(o);if(l<0){throw new u(\"Math environment is not closed\",this._pos,this._input)}if(l>0&&a[l-1]===\"\\\\\"){var h=l+o.length;a=a.slice(h);s+=h;continue}var p=[e.slice(0,s+l+o.length),e.slice(r.length,s+l)];return p}}return null}};var p={special:/^(\\\\\\\\|\\\\{|\\\\}|\\\\\\$|\\\\&|\\\\#|\\\\%|\\\\_)/,math:o,func:/^\\\\([a-zA-Z]+)/,open:/^\\{/,close:/^\\}/,quote:/^(`|``|'|'')/,ordinary:/^[^\\\\{}$&#%_\\s]+/};var c=/^%.*/;var f=/^\\s+/;r.prototype._skip=function(e){this._pos+=e;this._remain=this._remain.slice(e)};r.prototype._next=function(){var e=false;while(1){var t=f.exec(this._remain);if(t){e=true;var n=t[0].length;this._skip(n)}var i=c.exec(this._remain);if(!i)break;var r=i[0].length;this._skip(r)}this._currentAtom=this._nextAtom;if(this._remain===\"\"){this._nextAtom={type:\"EOF\",text:null,whitespace:false};return false}for(var o in p){var s=p[o];var a=s.exec(this._remain);if(!a)continue;var l=a[0];var h=a[1]?a[1]:l;this._nextAtom={type:o,text:h,whitespace:e};this._pos+=l.length;this._remain=this._remain.slice(a[0].length);return true}throw new u(\"Unrecoganizable atom\",this._pos,this._input)};r.prototype._matchText=function(e){if(e===null||e===undefined)return true;if(i.isString(e))return e.toLowerCase()===this._nextAtom.text.toLowerCase();else return e.some(e=>e.toLowerCase()===this._nextAtom.text.toLowerCase())};t.exports=r},{\"./ParseError\":3,\"./utils\":6}],3:[function(e,t,n){function i(e,t,n){var i=`Error: ${e}`;if(t!==undefined&&n!==undefined){i+=` at position ${t}: \\``;n=`${n.slice(0,t)}\\u21B1${n.slice(t)}`;var r=Math.max(0,t-15);var o=t+15;i+=`${n.slice(r,o)}\\``}this.message=i}i.prototype=Object.create(Error.prototype);i.prototype.constructor=i;t.exports=i},{}],4:[function(e,t,n){var s=e(\"./utils\");var r=e(\"./ParseError\");var a=function(e,t){this.type=e;this.value=t;this.children=[]};a.prototype.toString=function(e){if(!e)e=0;var t=\"\";for(var n=0;n<e;n++)t+=\"  \";var i=`${t}<${this.type}>`;if(this.value)i+=` (${s.toString(this.value)})`;i+=\"\\n\";if(this.children){for(var r=0;r<this.children.length;r++){var o=this.children[r];i+=o.toString(e+1)}}return i};a.prototype.addChild=function(e){if(!e)throw new Error(\"Argument must not be null\");this.children.push(e)};var o=function(e,t,n){this.type=e;this.value=t;this.children=null;this.whitespace=!!n};o.prototype=a.prototype;var i=function(e){this._lexer=e};i.prototype.parse=function(){var e=new a(\"root\");while(true){var t=this._acceptEnvironment();if(t===null)break;var n;if(t===\"algorithm\")n=this._parseAlgorithmInner();else if(t===\"algorithmic\")n=this._parseAlgorithmicInner();else throw new r(`Unexpected environment ${t}`);this._closeEnvironment(t);e.addChild(n)}this._lexer.expect(\"EOF\");return e};i.prototype._acceptEnvironment=function(){var e=this._lexer;if(!e.accept(\"func\",\"begin\"))return null;e.expect(\"open\");var t=e.expect(\"ordinary\");e.expect(\"close\");return t};i.prototype._closeEnvironment=function(e){var t=this._lexer;t.expect(\"func\",\"end\");t.expect(\"open\");t.expect(\"ordinary\",e);t.expect(\"close\")};i.prototype._parseAlgorithmInner=function(){var e=new a(\"algorithm\");while(true){var t=this._acceptEnvironment();if(t!==null){if(t!==\"algorithmic\")throw new r(`Unexpected environment ${t}`);var n=this._parseAlgorithmicInner();this._closeEnvironment();e.addChild(n);continue}var i=this._parseCaption();if(i){e.addChild(i);continue}break}return e};i.prototype._parseAlgorithmicInner=function(){var e=new a(\"algorithmic\");var t;while(true){t=this._parseStatement(l);if(t){e.addChild(t);continue}t=this._parseBlock();if(t.children.length>0){e.addChild(t);continue}break}return e};i.prototype._parseCaption=function(){var e=this._lexer;if(!e.accept(\"func\",\"caption\"))return null;var t=new a(\"caption\");e.expect(\"open\");t.addChild(this._parseCloseText());e.expect(\"close\");return t};i.prototype._parseBlock=function(){var e=new a(\"block\");while(true){var t=this._parseControl();if(t){e.addChild(t);continue}var n=this._parseFunction();if(n){e.addChild(n);continue}var i=this._parseStatement(h);if(i){e.addChild(i);continue}var r=this._parseCommand(p);if(r){e.addChild(r);continue}var o=this._parseComment();if(o){e.addChild(o);continue}break}return e};i.prototype._parseControl=function(){var e;if(e=this._parseIf())return e;if(e=this._parseLoop())return e;if(e=this._parseRepeat())return e;if(e=this._parseUpon())return e};i.prototype._parseFunction=function(){var e=this._lexer;if(!e.accept(\"func\",[\"function\",\"procedure\"]))return null;var t=this._lexer.get().text;e.expect(\"open\");var n=e.expect(\"ordinary\");e.expect(\"close\");e.expect(\"open\");var i=this._parseCloseText();e.expect(\"close\");var r=this._parseBlock();e.expect(\"func\",`end${t}`);var o=new a(\"function\",{type:t,name:n});o.addChild(i);o.addChild(r);return o};i.prototype._parseIf=function(){if(!this._lexer.accept(\"func\",\"if\"))return null;var e=new a(\"if\");this._lexer.expect(\"open\");e.addChild(this._parseCond());this._lexer.expect(\"close\");e.addChild(this._parseBlock());var t=0;while(this._lexer.accept(\"func\",[\"elif\",\"elsif\",\"elseif\"])){this._lexer.expect(\"open\");e.addChild(this._parseCond());this._lexer.expect(\"close\");e.addChild(this._parseBlock());t++}var n=false;if(this._lexer.accept(\"func\",\"else\")){n=true;e.addChild(this._parseBlock())}this._lexer.expect(\"func\",\"endif\");e.value={numElif:t,hasElse:n};return e};i.prototype._parseLoop=function(){if(!this._lexer.accept(\"func\",[\"FOR\",\"FORALL\",\"WHILE\"]))return null;var e=this._lexer.get().text.toLowerCase();var t=new a(\"loop\",e);this._lexer.expect(\"open\");t.addChild(this._parseCond());this._lexer.expect(\"close\");t.addChild(this._parseBlock());var n=e!==\"forall\"?`end${e}`:\"endfor\";this._lexer.expect(\"func\",n);return t};i.prototype._parseRepeat=function(){if(!this._lexer.accept(\"func\",[\"REPEAT\"]))return null;var e=this._lexer.get().text.toLowerCase();var t=new a(\"repeat\",e);t.addChild(this._parseBlock());this._lexer.expect(\"func\",\"until\");this._lexer.expect(\"open\");t.addChild(this._parseCond());this._lexer.expect(\"close\");return t};i.prototype._parseUpon=function(){if(!this._lexer.accept(\"func\",\"upon\"))return null;var e=new a(\"upon\");this._lexer.expect(\"open\");e.addChild(this._parseCond());this._lexer.expect(\"close\");e.addChild(this._parseBlock());this._lexer.expect(\"func\",\"endupon\");return e};var l=[\"ensure\",\"require\",\"input\",\"output\"];var h=[\"state\",\"print\",\"return\"];i.prototype._parseStatement=function(e){if(!this._lexer.accept(\"func\",e))return null;var t=this._lexer.get().text.toLowerCase();var n=new a(\"statement\",t);n.addChild(this._parseOpenText());return n};var p=[\"break\",\"continue\"];i.prototype._parseCommand=function(e){if(!this._lexer.accept(\"func\",e))return null;var t=this._lexer.get().text.toLowerCase();var n=new a(\"command\",t);return n};i.prototype._parseComment=function(){if(!this._lexer.accept(\"func\",\"comment\"))return null;var e=new a(\"comment\");this._lexer.expect(\"open\");e.addChild(this._parseCloseText());this._lexer.expect(\"close\");return e};i.prototype._parseCall=function(){var e=this._lexer;if(!e.accept(\"func\",\"call\"))return null;var t=e.get().whitespace;e.expect(\"open\");var n=e.expect(\"ordinary\");e.expect(\"close\");var i=new a(\"call\");i.whitespace=t;i.value=n;e.expect(\"open\");var r=this._parseCloseText();i.addChild(r);e.expect(\"close\");return i};i.prototype._parseCond=i.prototype._parseCloseText=function(){return this._parseText(\"close\")};i.prototype._parseOpenText=function(){return this._parseText(\"open\")};i.prototype._parseText=function(e){var t=new a(`${e}-text`);var n=false;var i;while(true){i=this._parseAtom()||this._parseCall();if(i){if(n)i.whitespace|=n;t.addChild(i);continue}if(this._lexer.accept(\"open\")){i=this._parseCloseText();n=this._lexer.get().whitespace;i.whitespace=n;t.addChild(i);this._lexer.expect(\"close\");n=this._lexer.get().whitespace;continue}break}return t};var u={ordinary:{tokenType:\"ordinary\"},math:{tokenType:\"math\"},special:{tokenType:\"special\"},\"cond-symbol\":{tokenType:\"func\",tokenValues:[\"and\",\"or\",\"not\",\"true\",\"false\",\"to\",\"downto\"]},\"quote-symbol\":{tokenType:\"quote\"},\"sizing-dclr\":{tokenType:\"func\",tokenValues:[\"tiny\",\"scriptsize\",\"footnotesize\",\"small\",\"normalsize\",\"large\",\"Large\",\"LARGE\",\"huge\",\"Huge\"]},\"font-dclr\":{tokenType:\"func\",tokenValues:[\"normalfont\",\"rmfamily\",\"sffamily\",\"ttfamily\",\"upshape\",\"itshape\",\"slshape\",\"scshape\",\"bfseries\",\"mdseries\",\"lfseries\"]},\"font-cmd\":{tokenType:\"func\",tokenValues:[\"textnormal\",\"textrm\",\"textsf\",\"texttt\",\"textup\",\"textit\",\"textsl\",\"textsc\",\"uppercase\",\"lowercase\",\"textbf\",\"textmd\",\"textlf\"]},\"text-symbol\":{tokenType:\"func\",tokenValues:[\"textbackslash\"]}};i.prototype._parseAtom=function(){for(var e in u){var t=u[e];var n=this._lexer.accept(t.tokenType,t.tokenValues);if(n===null)continue;var i=this._lexer.get().whitespace;if(e!==\"ordinary\"&&e!==\"math\")n=n.toLowerCase();return new o(e,n,i)}return null};t.exports=i},{\"./ParseError\":3,\"./utils\":6}],5:[function(n,e,t){var a=n(\"./utils\");function A(e){this._css={};this._fontSize=this._outerFontSize=e!==undefined?e:1}A.prototype.outerFontSize=function(e){if(e!==undefined)this._outerFontSize=e;return this._outerFontSize};A.prototype.fontSize=function(){return this._fontSize};A.prototype._fontCommandTable={normalfont:{\"font-family\":\"KaTeX_Main\"},rmfamily:{\"font-family\":\"KaTeX_Main\"},sffamily:{\"font-family\":\"KaTeX_SansSerif\"},ttfamily:{\"font-family\":\"KaTeX_Typewriter\"},bfseries:{\"font-weight\":\"bold\"},mdseries:{\"font-weight\":\"medium\"},lfseries:{\"font-weight\":\"lighter\"},upshape:{\"font-style\":\"normal\",\"font-variant\":\"normal\"},itshape:{\"font-style\":\"italic\",\"font-variant\":\"normal\"},scshape:{\"font-style\":\"normal\",\"font-variant\":\"small-caps\"},slshape:{\"font-style\":\"oblique\",\"font-variant\":\"normal\"},textnormal:{\"font-family\":\"KaTeX_Main\"},textrm:{\"font-family\":\"KaTeX_Main\"},textsf:{\"font-family\":\"KaTeX_SansSerif\"},texttt:{\"font-family\":\"KaTeX_Typewriter\"},textbf:{\"font-weight\":\"bold\"},textmd:{\"font-weight\":\"medium\"},textlf:{\"font-weight\":\"lighter\"},textup:{\"font-style\":\"normal\",\"font-variant\":\"normal\"},textit:{\"font-style\":\"italic\",\"font-variant\":\"normal\"},textsc:{\"font-style\":\"normal\",\"font-variant\":\"small-caps\"},textsl:{\"font-style\":\"oblique\",\"font-variant\":\"normal\"},uppercase:{\"text-transform\":\"uppercase\"},lowercase:{\"text-transform\":\"lowercase\"}};A.prototype._sizingScalesTable={tiny:.68,scriptsize:.8,footnotesize:.85,small:.92,normalsize:1,large:1.17,Large:1.41,LARGE:1.58,huge:1.9,Huge:2.28};A.prototype.updateByCommand=function(e){var t=this._fontCommandTable[e];if(t!==undefined){for(var n in t)this._css[n]=t[n];return}var i=this._sizingScalesTable[e];if(i!==undefined){this._outerFontSize=this._fontSize;this._fontSize=i;return}throw new ParserError(\"Unrecognized `text-style` command\")};A.prototype.toCSS=function(){var e=\"\";for(var t in this._css){var n=this._css[t];if(n===undefined)continue;e+=`${t}:${n};`}if(this._fontSize!==this._outerFontSize)e+=`font-size:${this._fontSize/this._outerFontSize}em;`;return e};function B(e,t){this._nodes=e;this._textStyle=t}B.prototype._renderCloseText=function(e,t){var n=new A(this._textStyle.fontSize());var i=new B(e.children,n);if(e.whitespace)this._html.putText(\" \");this._html.putHTML(i.renderToHTML(t))};B.prototype.renderToHTML=function(e){this._html=new _;var t;while((t=this._nodes.shift())!==undefined){var n=t.type;var i=t.value;if(t.whitespace)this._html.putText(\" \");switch(n){case\"ordinary\":this._html.putText(i);break;case\"math\":if(typeof e===\"undefined\"){throw EvalError(\"No math backend found. Please setup KaTeX or MathJax.\")}else if(e.name===\"katex\"){this._html.putHTML(e.driver.renderToString(i))}else if(e.name===\"mathjax\"){if(e.version===3){this._html.putHTML(e.driver.tex2chtml(i,{display:false}).outerHTML)}else{this._html.putText(`$${i}$`)}}else{throw new EvalError(`Unknown math backend ${e}`)}break;case\"cond-symbol\":this._html.beginSpan(\"ps-keyword\").putText(i.toLowerCase()).endSpan();break;case\"special\":if(i===\"\\\\\\\\\"){this._html.putHTML(\"<br/>\");break}var r={\"\\\\{\":\"{\",\"\\\\}\":\"}\",\"\\\\$\":\"$\",\"\\\\&\":\"&\",\"\\\\#\":\"#\",\"\\\\%\":\"%\",\"\\\\_\":\"_\"};var o=r[i];this._html.putText(o);break;case\"text-symbol\":var s={textbackslash:\"\\\\\"};var a=s[i];this._html.putText(a);break;case\"quote-symbol\":var l={\"`\":\"\\u2018\",\"``\":\"\\u201c\",\"'\":\"\\u2019\",\"''\":\"\\u201d\"};var h=l[i];this._html.putText(h);break;case\"call\":this._html.beginSpan(\"ps-funcname\").putText(i).endSpan();this._html.write(\"(\");var p=t.children[0];this._renderCloseText(p,e);this._html.write(\")\");break;case\"close-text\":this._renderCloseText(t,e);break;case\"font-dclr\":case\"sizing-dclr\":this._textStyle.updateByCommand(i);this._html.beginSpan(null,this._textStyle.toCSS());var u=new B(this._nodes,this._textStyle);this._html.putHTML(u.renderToHTML(e));this._html.endSpan();break;case\"font-cmd\":var c=this._nodes[0];if(c.type!==\"close-text\")continue;var f=new A(this._textStyle.fontSize());f.updateByCommand(i);this._html.beginSpan(null,f.toCSS());var d=new B(c.children,f);this._html.putHTML(d.renderToHTML(e));this._html.endSpan();break;default:throw new ParseError(`Unexpected ParseNode of type ${t.type}`)}}return this._html.toMarkup()};function _(){this._body=[];this._textBuf=[]}_.prototype.beginDiv=function(e,t,n){this._beginTag(\"div\",e,t,n);this._body.push(\"\\n\");return this};_.prototype.endDiv=function(){this._endTag(\"div\");this._body.push(\"\\n\");return this};_.prototype.beginP=function(e,t,n){this._beginTag(\"p\",e,t,n);this._body.push(\"\\n\");return this};_.prototype.endP=function(){this._flushText();this._endTag(\"p\");this._body.push(\"\\n\");return this};_.prototype.beginSpan=function(e,t,n){this._flushText();return this._beginTag(\"span\",e,t,n)};_.prototype.endSpan=function(){this._flushText();return this._endTag(\"span\")};_.prototype.putHTML=function(e){this._flushText();this._body.push(e);return this};_.prototype.putText=function(e){this._textBuf.push(e);return this};_.prototype.write=function(e){this._body.push(e)};_.prototype.toMarkup=function(){this._flushText();var e=this._body.join(\"\");return e.trim()};_.prototype.toDOM=function(){var e=this.toMarkup();var t=document.createElement(\"div\");t.innerHTML=e;return t.firstChild};_.prototype._flushText=function(){if(this._textBuf.length===0)return;var e=this._textBuf.join(\"\");this._body.push(this._escapeHtml(e));this._textBuf=[]};_.prototype._beginTag=function(e,t,n,i){var r=`<${e}`;if(t)r+=` class=\"${t}\"`;if(n){var o;if(a.isString(n)){o=n}else{o=\"\";for(var s in n){attrVal=n[s];o+=`${s}:${attrVal};`}}if(i)o+=i;r+=` style=\"${o}\"`}r+=\">\";this._body.push(r);return this};_.prototype._endTag=function(e){this._body.push(`</${e}>`);return this};var i={\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#39;\",\"/\":\"&#x2F;\"};_.prototype._escapeHtml=function(e){return String(e).replace(/[&<>\"'/]/g,e=>i[e])};function r(e){e=e||{};this.indentSize=e.indentSize?this._parseEmVal(e.indentSize):1.2;this.commentDelimiter=e.commentDelimiter!==undefined?e.commentDelimiter:\" // \";this.lineNumberPunc=e.lineNumberPunc!==undefined?e.lineNumberPunc:\":\";this.lineNumber=e.lineNumber!==undefined?e.lineNumber:false;this.noEnd=e.noEnd!==undefined?e.noEnd:false;this.scopeLines=e.scopeLines!==undefined?e.scopeLines:false;if(e.captionCount!==undefined)F.captionCount=e.captionCount;this.titlePrefix=e.titlePrefix!==undefined?e.titlePrefix:\"Algorithm\"}r.prototype._parseEmVal=function(e){e=e.trim();if(e.indexOf(\"em\")!==e.length-2)throw new TypeError(\"Unit error; expected `em` suffix\");return Number(e.substring(0,e.length-2))};function F(e,t){this._root=e.parse();this._options=new r(t);this._openLine=false;this._blockLevel=0;this._textLevel=-1;this._globalTextStyle=new A;this.backend=undefined;try{if(typeof katex===\"undefined\")katex=n(\"katex\")}catch(e){}try{if(typeof MathJax===\"undefined\")MathJax=n(\"mathjax\")}catch(e){}if(typeof katex!==\"undefined\"){this.backend={name:\"katex\",driver:katex}}else if(typeof MathJax!==\"undefined\"){this.backend={name:\"mathjax\",version:parseInt(MathJax.version.split(\".\")[0]),driver:MathJax}}}F.captionCount=0;F.prototype.toMarkup=function(){var e=this._html=new _;this._buildTree(this._root);delete this._html;return e.toMarkup()};F.prototype.toDOM=function(){var e=this.toMarkup();var t=document.createElement(\"div\");t.innerHTML=e;return t.firstChild};F.prototype._beginGroup=function(e,t,n){this._closeLineIfAny();this._html.beginDiv(`ps-${e}${t?` ${t}`:\"\"}`,n)};F.prototype._endGroup=function(e){this._closeLineIfAny();this._html.endDiv()};F.prototype._beginBlock=function(){var e=this._options.lineNumber&&this._blockLevel===0?.6:0;var t=this._options.indentSize+e;if(this._options.scopeLines)t/=2;this._beginGroup(\"block\",null,{\"margin-left\":`${t}em`});this._blockLevel++};F.prototype._endBlock=function(){this._closeLineIfAny();this._endGroup();this._blockLevel--};F.prototype._newLine=function(){this._closeLineIfAny();this._openLine=true;this._globalTextStyle.outerFontSize(1);var e=this._options.indentSize;if(this._blockLevel>0){this._numLOC++;this._html.beginP(\"ps-line ps-code\",this._globalTextStyle.toCSS());var t=this._options.lineNumber?e*1.25:0;t+=this._options.scopeLines?e*.1:0;if(this._options.lineNumber){this._html.beginSpan(\"ps-linenum\",{left:`${-((this._blockLevel-1)*t)}em`}).putText(this._numLOC+this._options.lineNumberPunc).endSpan()}}else{this._html.beginP(\"ps-line\",{\"text-indent\":`${-e}em`,\"padding-left\":`${e}em`},this._globalTextStyle.toCSS())}};F.prototype._closeLineIfAny=function(){if(!this._openLine)return;this._html.endP();this._openLine=false};F.prototype._typeKeyword=function(e){this._html.beginSpan(\"ps-keyword\").putText(e).endSpan()};F.prototype._typeFuncName=function(e){this._html.beginSpan(\"ps-funcname\").putText(e).endSpan()};F.prototype._typeText=function(e){this._html.write(e)};F.prototype._buildTreeForAllChildren=function(e){var t=e.children;for(var n=0;n<t.length;n++)this._buildTree(t[n])};F.prototype._buildCommentsFromBlock=function(e){var t=e.children;while(t.length>0&&t[0].type===\"comment\"){var n=t.shift();this._buildTree(n)}};F.prototype._buildTree=function(e){var t;var n;var i;switch(e.type){case\"root\":this._beginGroup(\"root\");this._buildTreeForAllChildren(e);this._endGroup();break;case\"algorithm\":var r;for(t=0;t<e.children.length;t++){n=e.children[t];if(n.type!==\"caption\")continue;r=n;F.captionCount++}if(r){this._beginGroup(\"algorithm\",\"with-caption\");this._buildTree(r)}else{this._beginGroup(\"algorithm\")}for(t=0;t<e.children.length;t++){n=e.children[t];if(n.type===\"caption\")continue;this._buildTree(n)}this._endGroup();break;case\"algorithmic\":var o=this._options.lineNumber?\" with-linenum \":\"\";o+=this._options.scopeLines?\" with-scopelines \":\"\";if(o){this._beginGroup(\"algorithmic\",o);this._numLOC=0}else{this._beginGroup(\"algorithmic\")}this._buildTreeForAllChildren(e);this._endGroup();break;case\"block\":this._beginBlock();this._buildTreeForAllChildren(e);this._endBlock();break;case\"function\":var s=e.value.type.toLowerCase();var a=e.value.name;i=e.children[0];var l=e.children[1];this._newLine();this._typeKeyword(`${s} `);this._typeFuncName(a);this._typeText(\"(\");this._buildTree(i);this._typeText(\")\");this._buildCommentsFromBlock(l);this._buildTree(l);if(!this._options.noEnd){this._newLine();this._typeKeyword(`end ${s}`)}break;case\"if\":this._newLine();this._typeKeyword(\"if \");ifCond=e.children[0];this._buildTree(ifCond);this._typeKeyword(\" then\");var h=e.children[1];this._buildCommentsFromBlock(h);this._buildTree(h);var p=e.value.numElif;for(var u=0;u<p;u++){this._newLine();this._typeKeyword(\"else if \");var c=e.children[2+2*u];this._buildTree(c);this._typeKeyword(\" then\");var f=e.children[2+2*u+1];this._buildCommentsFromBlock(f);this._buildTree(f)}var d=e.value.hasElse;if(d){this._newLine();this._typeKeyword(\"else\");var _=e.children[e.children.length-1];this._buildCommentsFromBlock(_);this._buildTree(_)}if(!this._options.noEnd){this._newLine();this._typeKeyword(\"end if\")}break;case\"loop\":this._newLine();var m=e.value;var x={for:\"for\",forall:\"for all\",while:\"while\"};this._typeKeyword(`${x[m]} `);var v=e.children[0];this._buildTree(v);this._typeKeyword(\" do\");var y=e.children[1];this._buildCommentsFromBlock(y);this._buildTree(y);if(!this._options.noEnd){this._newLine();var b=m===\"while\"?\"end while\":\"end for\";this._typeKeyword(b)}break;case\"repeat\":this._newLine();this._typeKeyword(\"repeat\");var w=e.children[0];this._buildCommentsFromBlock(w);this._buildTree(w);this._newLine();this._typeKeyword(\"until \");var T=e.children[1];this._buildTree(T);break;case\"upon\":this._newLine();this._typeKeyword(\"upon \");uponCond=e.children[0];this._buildTree(uponCond);var g=e.children[1];this._buildCommentsFromBlock(g);this._buildTree(g);if(!this._options.noEnd){this._newLine();this._typeKeyword(\"end upon\")}break;case\"command\":var k=e.value;var C={break:\"break\",continue:\"continue\"}[k];this._newLine();if(C)this._typeKeyword(C);break;case\"caption\":this._newLine();this._typeKeyword(`${this._options.titlePrefix} ${F.captionCount} `);i=e.children[0];this._buildTree(i);break;case\"comment\":i=e.children[0];this._html.beginSpan(\"ps-comment\");this._html.putText(this._options.commentDelimiter);this._buildTree(i);this._html.endSpan();break;case\"statement\":var S=e.value;var L={state:\"\",ensure:\"Ensure: \",require:\"Require: \",input:\"Input: \",output:\"Output: \",print:\"print \",return:\"return \"}[S];this._newLine();if(L)this._typeKeyword(L);i=e.children[0];this._buildTree(i);break;case\"open-text\":var E=new B(e.children,this._globalTextStyle);this._html.putHTML(E.renderToHTML(this.backend));break;case\"close-text\":var M=this._globalTextStyle.fontSize();var $=new A(M);var z=new B(e.children,$);this._html.putHTML(z.renderToHTML(this.backend));break;default:throw new ParseError(`Unexpected ParseNode of type ${e.type}`)}};e.exports=F},{\"./utils\":6,katex:undefined,mathjax:undefined}],6:[function(e,t,n){t.exports={isString:e=>typeof e===\"string\"||e instanceof String,isObject:e=>typeof e===\"object\"&&e instanceof Object,toString:function(e){if(!this.isObject(e))return`${e}`;var t=[];for(var n in e)t.push(`${n}: ${this.toString(e[n])}`);return t.join(\", \")}}},{}]},{},[1])(1)});\n"
  },
  {
    "path": "docs/stylesheets/styles.css",
    "content": "body {\n  padding:50px;\n  font:14px/1.5 \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  color:#777;\n  font-weight:300;\n}\n\niframe {\n  border: none;\n  width: 115%;\n}\n\nh1, h2, h3, h4, h5, h6 {\n  color:#222;\n  margin:0 0 20px;\n  font-weight: bold;\n}\n\np, ul, ol, table, pre, dl {\n  margin:0 0 20px;\n}\n\nh1, h2, h3 {\n  line-height:1.1;\n}\n\nh1 {\n  font-size:28px;\n}\n\nh2 {\n  color:#393939;\n}\n\nh3, h4, h5, h6 {\n  color:#494949;\n}\n\na {\n  color:#39c;\n  font-weight:400;\n  text-decoration:none;\n}\n\na small {\n  font-size:11px;\n  color:#777;\n  margin-top:-0.6em;\n  display:block;\n}\n\n.wrapper {\n  width:860px;\n  margin:0 auto;\n}\n\nblockquote {\n  border-left:1px solid #e5e5e5;\n  margin:0;\n  padding:0 0 0 20px;\n  font-style:italic;\n}\n\ncode, pre {\n  font-family:Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal;\n  color:#333;\n  font-size:0.85em;\n}\n\npre {\n  border-radius:5px;\n  border:1px solid #e5e5e5;\n  font-size:0.75em;\n}\n\ntable {\n  width:100%;\n  border-collapse:collapse;\n}\n\nth, td {\n  text-align:left;\n  padding:5px 10px;\n  border-bottom:1px solid #e5e5e5;\n}\n\ndt {\n  color:#444;\n  font-weight:700;\n}\n\nth {\n  color:#444;\n}\n\nimg {\n  max-width:100%;\n}\n\nheader {\n  width:270px;\n  float:left;\n  position:fixed;\n}\n\nheader ul {\n  list-style:none;\n  height:40px;\n  \n  padding:0;\n  \n  background: #eee;\n  background: -moz-linear-gradient(top, #f8f8f8 0%, #dddddd 100%);\n  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd));\n  background: -webkit-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);\n  background: -o-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);\n  background: -ms-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);\n  background: linear-gradient(top, #f8f8f8 0%,#dddddd 100%);\n  \n  border-radius:5px;\n  border:1px solid #d2d2d2;\n  box-shadow:inset #fff 0 1px 0, inset rgba(0,0,0,0.03) 0 -1px 0;\n  width:270px;\n}\n\nheader li {\n  width:89px;\n  float:left;\n  border-right:1px solid #d2d2d2;\n  height:40px;\n}\n\nheader ul a {\n  line-height:1.15;\n  font-size:11px;\n  color:#999;\n  display:block;\n  text-align:center;\n  padding-top:6px;\n  height:40px;\n}\n\nstrong {\n  color:#222;\n  font-weight:700;\n}\n\nheader ul li:first-child{\n  width:88px;\n  border-left:1px solid #fff;\n}\n\nheader ul li:last-child {\n  border-right:none;\n  width:89px;\n}\n\nheader ul a strong {\n  font-size:14px;\n  display:block;\n  color:#222;\n}\n\nsection {\n  width:500px;\n  float:right;\n  padding-bottom:50px;\n}\n\nsmall {\n  font-size:11px;\n}\n\nhr {\n  border:0;\n  background:#e5e5e5;\n  height:1px;\n  margin:0 0 20px;\n}\n\nfooter {\n  width:270px;\n  float:left;\n  position:fixed;\n  bottom:50px;\n}\n\n@media print, screen and (max-width: 960px) {\n  \n  div.wrapper {\n    width:auto;\n    margin:0;\n  }\n  \n  header, section, footer {\n    float:none;\n    position:static;\n    width:auto;\n  }\n  \n  header {\n    padding-right:320px;\n  }\n  \n  section {\n    border:1px solid #e5e5e5;\n    border-width:1px 0;\n    padding:20px 0;\n    margin:0 0 20px;\n  }\n  \n  header a small {\n    display:inline;\n  }\n  \n  header ul {\n    position:absolute;\n    right:50px;\n    top:52px;\n  }\n}\n\n@media print, screen and (max-width: 720px) {\n  body {\n    word-wrap:break-word;\n  }\n  \n  header {\n    padding:0;\n  }\n  \n  header ul, header p.view {\n    position:static;\n  }\n  \n  pre, code {\n    word-wrap:normal;\n  }\n}\n\n@media print, screen and (max-width: 480px) {\n  body {\n    padding:15px;\n  }\n  \n  header ul {\n    display:none;\n  }\n}\n\n@media print {\n  body {\n    padding:0.4in;\n    font-size:12pt;\n    color:#444;\n  }\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n    \"name\": \"pseudocode\",\n    \"version\": \"2.4.1\",\n    \"author\": {\n        \"name\": \"Saswat Padhi\",\n        \"email\": \"saswat.sourav@gmail.com\",\n        \"url\": \"https://saswatpadhi.github.io/\"\n    },\n    \"description\": \"Beautiful pseudocode for the Web\",\n    \"main\": \"pseudocode.js\",\n    \"repository\": {\n        \"type\": \"git\",\n        \"url\": \"git://github.com/SaswatPadhi/pseudocode.js\"\n    },\n    \"files\": [\n        \"pseudocode.js\",\n        \"src/\",\n        \"build/pseudocode.min.css\",\n        \"build/pseudocode.min.js\"\n    ],\n    \"dependencies\": {\n        \"katex\": \"^0.16.7\"\n    },\n    \"devDependencies\": {\n        \"browserify\": \"^17.0.0\",\n        \"clean-css-cli\": \"^5.3.0\",\n        \"eslint\": \"^8.45.0\",\n        \"uglify-js\": \"^3.17.4\",\n        \"watchify\": \"^4.0.0\",\n        \"clean-css\": \"^5.2.4\"\n    },\n    \"optionalDependencies\": {\n        \"mathjax\": \"^3.2.2\"\n    },\n    \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "pseudocode.js",
    "content": "/*\n * The entry points of pseudocode-js\n **/\n\nvar ParseError = require('./src/ParseError');\nvar Lexer = require('./src/Lexer');\nvar Parser = require('./src/Parser');\nvar Renderer = require('./src/Renderer');\n\nfunction makeRenderer (data, options) {\n    var lexer = new Lexer(data);\n    var parser = new Parser(lexer);\n    return new Renderer(parser, options);\n}\n\nmodule.exports = {\n    ParseError: ParseError,\n\n    render: function (input, baseDomEle, options) {\n        if (input === null || input === undefined)\n            throw new ReferenceError('Input cannot be empty');\n\n        var R = makeRenderer(input, options);\n        var elem = R.toDOM();\n        if (baseDomEle)\n            baseDomEle.appendChild(elem);\n\n        if (R.backend && R.backend.name === 'mathjax') {\n            if (MathJax.version < 3)\n                MathJax.Hub.Queue([\"Typeset\", MathJax.Hub, elem]);\n            else if (MathJax.version > 3)\n                MathJax.typeset();\n            // We use synchronous conversion in MathJax 3.x\n        }\n\n        return elem;\n    },\n\n    renderToString: function (input, options) {\n        if (input === null || input === undefined)\n            throw new ReferenceError('Input cannot be empty');\n\n        var R = makeRenderer(input, options);\n        if (R.backend && R.backend.name === 'mathjax' && R.backend.version < 3) {\n            console.warn('`renderToString` is fully supported only on MathJax backend 3.x.\\n' +\n                         'Math ($...$) will not be rendered to HTML and will be left as is.');\n        }\n\n        return R.toMarkup();\n    },\n\n    renderElement: function (elem, options) {\n        if (!(elem instanceof Element))\n            throw new ReferenceError('A DOM element is required');\n\n        elem.style.display = 'none';\n\n        var elemOptions = JSON.parse(JSON.stringify(options || {}));\n        for (const dataProp in elem.dataset)\n            elemOptions[dataProp] = elem.dataset[dataProp];\n        var R = makeRenderer(elem.textContent, elemOptions);\n\n        var newElem = R.toDOM();\n        elem.replaceWith(newElem);\n\n        if (R.backend && R.backend.name === 'mathjax') {\n            if (MathJax.version < 3)\n                MathJax.Hub.Queue([\"Typeset\", MathJax.Hub, elem]);\n            else if (MathJax.version > 3)\n                MathJax.typeset();\n            // We use synchronous conversion in MathJax 3.x\n        }\n    },\n\n    renderClass: function (className, options) {\n        [...document.getElementsByClassName(className)].forEach(\n            (el) => this.renderElement(el, options)\n        );\n    },\n};\n"
  },
  {
    "path": "src/Lexer.js",
    "content": "/**\n * The Lexer class tokenizes the input sequentially, looking ahead only one\n * token.\n */\nvar utils = require('./utils');\nvar ParseError = require('./ParseError');\n\nvar Lexer = function (input) {\n    this._input = input;\n    this._remain = input;\n    this._pos = 0;\n    this._nextAtom = this._currentAtom = null;\n    this._next(); // get the next atom\n};\n\nLexer.prototype.accept = function (type, text) {\n    if (this._nextAtom.type === type && this._matchText(text)) {\n        this._next();\n        return this._currentAtom.text;\n    }\n    return null;\n};\n\nLexer.prototype.expect = function (type, text) {\n    var nextAtom = this._nextAtom;\n    // The next atom is NOT of the right type\n    if (nextAtom.type !== type) {\n        throw new ParseError(\n            `Expected an atom of ${type} but received ${nextAtom.type}`,\n            this._pos,\n            this._input\n        );\n    }\n    // Check whether the text is exactly the same\n    if (!this._matchText(text)) {\n        throw new ParseError(\n            `Expected \\`${text}\\` but received \\`${nextAtom.text}\\``,\n            this._pos,\n            this._input\n        );\n    }\n\n    this._next();\n    return this._currentAtom.text;\n};\n\nLexer.prototype.get = function () {\n    return this._currentAtom;\n};\n\n/* Math pattern\n    Math environtment like $ $ or \\( \\) cannot be matched using regular\n    expression. This object simulates a RegEx object\n*/\nvar mathPattern = {\n    exec: function (str) {\n        var delimiters = [\n            { start: '$', end: '$' },\n            { start: '\\\\(', end: '\\\\)' },\n        ];\n        var totalLen = str.length;\n\n        for (var di = 0; di < delimiters.length; di++) {\n            var startDel = delimiters[di].start;\n            if (str.indexOf(startDel) !== 0) continue;\n\n            var endDel = delimiters[di].end;\n            var endPos = startDel.length;\n            var remain = str.slice(endPos);\n            while (endPos < totalLen) {\n                var pos = remain.indexOf(endDel);\n                if (pos < 0) {\n                    throw new ParseError('Math environment is not closed',\n                                         this._pos, this._input);\n                }\n\n                // false positive, it's escaped, not a match\n                if (pos > 0 && remain[pos - 1] === '\\\\') {\n                    var skipLen = pos + endDel.length;\n                    remain = remain.slice(skipLen);\n                    endPos += skipLen;\n                    continue;\n                }\n\n                var res = [str.slice(0, endPos + pos + endDel.length),\n                    str.slice(startDel.length, endPos + pos)];\n                return res;\n            }\n        }\n\n        return null;\n    },\n};\nvar atomRegex = {\n    // TODO: which is correct? func: /^\\\\(?:[a-zA-Z]+|.)/,\n    special: /^(\\\\\\\\|\\\\{|\\\\}|\\\\\\$|\\\\&|\\\\#|\\\\%|\\\\_)/,\n    math: mathPattern, ///^\\$.*\\$/\n    func: /^\\\\([a-zA-Z]+)/,\n    open: /^\\{/,\n    close: /^\\}/,\n    quote: /^(`|``|'|'')/,\n    ordinary: /^[^\\\\{}$&#%_\\s]+/,\n};\nvar commentRegex = /^%.*/;\nvar whitespaceRegex = /^\\s+/;\n\nLexer.prototype._skip = function (len) {\n    this._pos += len;\n    this._remain = this._remain.slice(len);\n};\n\n/* Get the next atom */\nLexer.prototype._next = function () {\n    var anyWhitespace = false;\n    while (1) {\n        // Skip whitespace (one or more)\n        var whitespaceMatch = whitespaceRegex.exec(this._remain);\n        if (whitespaceMatch) {\n            anyWhitespace = true;\n            var whitespaceLen = whitespaceMatch[0].length;\n            this._skip(whitespaceLen);\n        }\n\n        // Skip comment\n        var commentMatch = commentRegex.exec(this._remain);\n        if (!commentMatch) break;\n        var commentLen = commentMatch[0].length;\n        this._skip(commentLen);\n    }\n\n    // Remember the current atom\n    this._currentAtom = this._nextAtom;\n\n    // Reach the end of string\n    if (this._remain === '') {\n        this._nextAtom = {\n            type: 'EOF',\n            text: null,\n            whitespace: false,\n        };\n        return false;\n    }\n\n    // Try all kinds of atoms\n    for (var type in atomRegex) {\n        var regex = atomRegex[type];\n\n        var match = regex.exec(this._remain);\n        if (!match) continue; // not matched\n\n        // match[1] is the useful part, e.g. '123' of '$123$', 'it' of '\\\\it'\n        var matchText = match[0];\n        var usefulText = match[1] ? match[1] : matchText;\n\n        this._nextAtom = {\n            type: type, /* special, func, open, close, ordinary, math */\n            text: usefulText, /* the text value of the atom */\n            whitespace: anyWhitespace, /* any whitespace before the atom */\n        };\n\n        this._pos += matchText.length;\n        this._remain = this._remain.slice(match[0].length);\n\n        return true;\n    }\n\n    throw new ParseError('Unrecoganizable atom', this._pos, this._input);\n};\n\n/* Check whether the text of the next atom matches */\nLexer.prototype._matchText = function (text) {\n    // don't need to match\n    if (text === null || text === undefined) return true;\n\n    // using case-insensitive comparisons,\n    // check if text is the same as next atom,\n    // or if text is an array that contains the next atom\n    if (utils.isString(text))\n        return text.toLowerCase() === this._nextAtom.text.toLowerCase();\n    else\n        return text.some((str) => str.toLowerCase() === this._nextAtom.text.toLowerCase());\n};\n\nmodule.exports = Lexer;\n"
  },
  {
    "path": "src/ParseError.js",
    "content": "function ParseError (message, pos, input) {\n    var error = `Error: ${message}`;\n    // If we have the input and a position, make the error a bit fancier\n    if (pos !== undefined && input !== undefined) {\n        error += ` at position ${pos}: \\``;\n\n        // Insert a combining underscore at the correct position\n        input = `${input.slice(0, pos)}\\u21B1${input.slice(pos)}`;\n\n        // Extract some context from the input and add it to the error\n        var begin = Math.max(0, pos - 15);\n        var end = pos + 15;\n        error += `${input.slice(begin, end)}\\``;\n    }\n\n    this.message = error;\n}\nParseError.prototype = Object.create(Error.prototype);\nParseError.prototype.constructor = ParseError;\n\nmodule.exports = ParseError;\n"
  },
  {
    "path": "src/Parser.js",
    "content": "/**\n * The Parser class parses the token stream from Lexer into an abstract syntax\n * tree, represented by ParseNode.\n *\n * The grammar of pseudocode required by Pseudocode.js mimics that of TeX/Latex\n * and its algorithm packages. It is designed intentionally to be less powerful\n * than Tex/LaTeX for the convinience of implementation. As a consequence, the\n * grammar is context-free, which can be expressed in production rules:\n *\n *     <pseudo>        :== ( <algorithm> | <algorithmic> )[0..n]\n *\n *     <algorithm>     :== \\begin{algorithm}\n *                           ( <caption> | <algorithmic> )[0..n]\n *                         \\end{algorithm}\n *     <caption>       :== \\caption{ <close-text> }\n *\n *     <algorithmic>   :== \\begin{algorithmic}\n *                           ( <ensure> | <require> | <block> )[0..n]\n *                         \\end{algorithmic}\n *     <require>       :== \\REQUIRE <open-text>\n *     <ensure>        :== \\ENSURE <open-text>\n *\n *     <block>         :== ( <comment> | <command> | <control> | <function> |\n *                           <statement> )[0..n]\n *\n *     <control>       :== <if> | <for> | <while> | <repeat> | <upon>\n *     <if>            :== \\IF{<cond>} <block>\n *                         ( \\ELIF{<cond>} <block> )[0..n]\n *                         ( \\ELSE <block> )[0..1]\n *                         \\ENDIF\n *\n *     <for>           :== \\FOR{<cond>} <block> \\ENDFOR\n *     <while>         :== \\WHILE{<cond>} <block> \\ENDWHILE\n *     <repeat>        :== \\REPEAT <block> \\UNTIL{<cond>}\n *     <upon>          :== \\UPON{<cond>} <block> \\EDNUPON\n *\n *     <function>      :== \\FUNCTION{<name>}{<params>} <block> \\ENDFUNCTION\n *                         (same for <procedure>)\n *\n *     <statement>     :== <state> | <return> | <print>\n *     <state>         :== \\STATE <open-text>\n *     <return>        :== \\RETURN <open-text>\n *     <print>         :== \\PRINT <open-text>\n *\n *     <commands>      :== <break> | <continue>\n *     <break>         :== \\BREAK\n *     <continue>      :== \\CONTINUE\n *\n *     <comment>       :== \\COMMENT{<close-text>}\n *\n *     <cond>          :== <close-text>\n *     <open-text>     :== ( <atom> | <call> ) <open-text> |\n *                         { <close-text> } | <empty>\n *     <close-text>    :== ( <atom> | <call> ) <close-text> |\n *                         { <close-text> } | <empty>\n *\n *     <atom>          :== <ordinary>[1..n] | <special> | <symbol>\n *                         | <size> | <font> | <bool> | <math>\n *     <name>          :== <ordinary>\n *\n *     <call>          :== \\CALL{<name>}({<close-text>})\n *     <special>       :== \\\\ | \\{ | \\} | \\$ | \\& | \\# | \\% | \\_\n *     <cond-symbol>   :== \\AND | \\OR | \\NOT | \\TRUE | \\FALSE | \\TO | \\DOWNTO\n *     <text-symbol>   :== \\textbackslash\n *     <quote-symbol>  :== ` | `` | ' | ''\n *     (More LaTeX symbols can be added if necessary. See\n *     http://tug.ctan.org/info/symbols/comprehensive/symbols-a4.pdf)\n *     <math>          :== \\( ... \\) | $ ... $\n *     (Math is handled by a backend, KaTeX or MathJax)\n *     <size>          :== \\tiny | \\scriptsize | \\footnotesize | \\small\n *                         | \\normalsize | \\large | \\Large | \\LARGE | \\huge\n *                         | \\HUGE\n *     <font>          :== \\rmfamily | \\sffamily | \\ttfamily\n *                         | \\upshape | \\itshape | \\slshape | \\scshape\n *     <ordinary>      :== not any of \\ { } $ & # % _\n *     <empty>         :==\n *\n * There are many well-known ways to parse a context-free grammar, like the\n * top-down approach LL(k) or the bottom-up approach like LR(k). Both methods\n * are usually implemented in a table-driven fashion, which is not suitable to\n * write by hand. As our grammar is simple enough and its input is not expected\n * to be large, the performance wouldn't be a problem. Thus, I choose to write\n * the parser in the most natural form--- a (predictive) recursive descent\n * parser. The major benefit of a recursive descent parser is **simplity** for\n * the structure of resulting program closely mirrors that of the grammar. *\n *\n */\nvar utils = require('./utils');\nvar ParseError = require('./ParseError');\n\nvar ParseNode = function (type, val) {\n    this.type = type;\n    this.value = val;\n    this.children = [];\n};\n\nParseNode.prototype.toString = function (level) {\n    if (!level) level = 0;\n\n    var indent = '';\n    for (var i = 0; i < level; i++) indent += '  ';\n\n    var res = `${indent}<${this.type}>`;\n    if (this.value) res += ` (${utils.toString(this.value)})`;\n    res += '\\n';\n\n    if (this.children) {\n        for (var ci = 0; ci < this.children.length; ci++) {\n            var child = this.children[ci];\n            res += child.toString(level + 1);\n        }\n    }\n\n    return res;\n};\n\nParseNode.prototype.addChild = function (childNode) {\n    if (!childNode)\n        throw new Error('Argument must not be null');\n\n    this.children.push(childNode);\n};\n\n/* AtomNode is the leaf node of parse tree */\nvar AtomNode = function (type, value, whitespace) {\n    // ParseNode.call(this, type, val);\n    this.type = type;\n    this.value = value;\n    this.children = null; // leaf node, thus no children\n    this.whitespace = !!whitespace; // is there any whitespace before the atom\n};\nAtomNode.prototype = ParseNode.prototype;\n\nvar Parser = function (lexer) {\n    this._lexer = lexer;\n};\n\nParser.prototype.parse = function () {\n    var root = new ParseNode('root');\n\n    while (true) {\n        var envName = this._acceptEnvironment();\n        if (envName === null) break;\n\n        var envNode;\n        if (envName === 'algorithm')\n            envNode = this._parseAlgorithmInner();\n        else if (envName === 'algorithmic')\n            envNode = this._parseAlgorithmicInner();\n        else\n            throw new ParseError(`Unexpected environment ${envName}`);\n\n        this._closeEnvironment(envName);\n        root.addChild(envNode);\n    }\n    this._lexer.expect('EOF');\n    return root;\n};\n\nParser.prototype._acceptEnvironment = function () {\n    var lexer = this._lexer;\n    // \\begin{XXXXX}\n    if (!lexer.accept('func', 'begin')) return null;\n\n    lexer.expect('open');\n    var envName = lexer.expect('ordinary');\n    lexer.expect('close');\n    return envName;\n};\n\nParser.prototype._closeEnvironment = function (envName) {\n    // \\close{XXXXX}\n    var lexer = this._lexer;\n    lexer.expect('func', 'end');\n    lexer.expect('open');\n    lexer.expect('ordinary', envName);\n    lexer.expect('close');\n};\n\nParser.prototype._parseAlgorithmInner = function () {\n    var algNode = new ParseNode('algorithm');\n    while (true) {\n        var envName = this._acceptEnvironment();\n        if (envName !== null) {\n            if (envName !== 'algorithmic')\n                throw new ParseError(`Unexpected environment ${envName}`);\n            var algmicNode = this._parseAlgorithmicInner();\n            this._closeEnvironment();\n            algNode.addChild(algmicNode);\n            continue;\n        }\n\n        var captionNode = this._parseCaption();\n        if (captionNode) {\n            algNode.addChild(captionNode);\n            continue;\n        }\n\n        break;\n    }\n    return algNode;\n};\n\nParser.prototype._parseAlgorithmicInner = function () {\n    var algmicNode = new ParseNode('algorithmic');\n    var node;\n    while (true) {\n        node = this._parseStatement(IO_STATEMENTS);\n        if (node) {\n            algmicNode.addChild(node);\n            continue;\n        }\n\n        node = this._parseBlock();\n        if (node.children.length > 0) {\n            algmicNode.addChild(node);\n            continue;\n        }\n\n        break;\n    }\n    return algmicNode;\n};\n\nParser.prototype._parseCaption = function () {\n    var lexer = this._lexer;\n    if (!lexer.accept('func', 'caption')) return null;\n\n    var captionNode = new ParseNode('caption');\n    lexer.expect('open');\n    captionNode.addChild(this._parseCloseText());\n    lexer.expect('close');\n\n    return captionNode;\n};\n\nParser.prototype._parseBlock = function () {\n    var blockNode = new ParseNode('block');\n\n    while (true) {\n        var controlNode = this._parseControl();\n        if (controlNode) {\n            blockNode.addChild(controlNode);\n            continue;\n        }\n\n        var functionNode = this._parseFunction();\n        if (functionNode) {\n            blockNode.addChild(functionNode);\n            continue;\n        }\n\n        var statementNode = this._parseStatement(STATEMENTS);\n        if (statementNode) {\n            blockNode.addChild(statementNode);\n            continue;\n        }\n\n        var commandNode = this._parseCommand(COMMANDS);\n        if (commandNode) {\n            blockNode.addChild(commandNode);\n            continue;\n        }\n\n        var commentNode = this._parseComment();\n        if (commentNode) {\n            blockNode.addChild(commentNode);\n            continue;\n        }\n\n        break;\n    }\n\n    return blockNode;\n};\n\nParser.prototype._parseControl = function () {\n    var controlNode;\n    if ((controlNode = this._parseIf())) return controlNode;\n    if ((controlNode = this._parseLoop())) return controlNode;\n    if ((controlNode = this._parseRepeat())) return controlNode;\n    if ((controlNode = this._parseUpon())) return controlNode;\n};\n\nParser.prototype._parseFunction = function () {\n    var lexer = this._lexer;\n    if (!lexer.accept('func', ['function', 'procedure'])) return null;\n\n    // \\FUNCTION{funcName}{funcArgs}\n    var funcType = this._lexer.get().text; // FUNCTION or PROCEDURE\n    lexer.expect('open');\n    var funcName = lexer.expect('ordinary');\n    lexer.expect('close');\n    lexer.expect('open');\n    var argsNode = this._parseCloseText();\n    lexer.expect('close');\n    // <block>\n    var blockNode = this._parseBlock();\n    // \\ENDFUNCTION\n    lexer.expect('func', `end${funcType}`);\n\n    var functionNode = new ParseNode('function',\n                                     { type: funcType, name: funcName });\n    functionNode.addChild(argsNode);\n    functionNode.addChild(blockNode);\n    return functionNode;\n};\n\nParser.prototype._parseIf = function () {\n    if (!this._lexer.accept('func', 'if')) return null;\n\n    var ifNode = new ParseNode('if');\n\n    // { <cond> } <block>\n    this._lexer.expect('open');\n    ifNode.addChild(this._parseCond());\n    this._lexer.expect('close');\n    ifNode.addChild(this._parseBlock());\n\n    // ( \\ELIF { <cond> } <block> )[0...n]\n    var numElif = 0;\n    while (this._lexer.accept('func', ['elif', 'elsif', 'elseif'])) {\n        this._lexer.expect('open');\n        ifNode.addChild(this._parseCond());\n        this._lexer.expect('close');\n        ifNode.addChild(this._parseBlock());\n        numElif++;\n    }\n\n    // ( \\ELSE <block> )[0..1]\n    var hasElse = false;\n    if (this._lexer.accept('func', 'else')) {\n        hasElse = true;\n        ifNode.addChild(this._parseBlock());\n    }\n\n    // \\ENDIF\n    this._lexer.expect('func', 'endif');\n\n    ifNode.value = { numElif: numElif, hasElse: hasElse };\n    return ifNode;\n};\n\nParser.prototype._parseLoop = function () {\n    if (!this._lexer.accept('func', ['FOR', 'FORALL', 'WHILE'])) return null;\n\n    var loopName = this._lexer.get().text.toLowerCase();\n    var loopNode = new ParseNode('loop', loopName);\n\n    // { <cond> } <block>\n    this._lexer.expect('open');\n    loopNode.addChild(this._parseCond());\n    this._lexer.expect('close');\n    loopNode.addChild(this._parseBlock());\n\n    // \\ENDFOR\n    var endLoop = loopName !== 'forall' ? `end${loopName}` : 'endfor';\n    this._lexer.expect('func', endLoop);\n\n    return loopNode;\n};\n\nParser.prototype._parseRepeat = function () {\n    if (!this._lexer.accept('func', ['REPEAT'])) return null;\n\n    var repeatName = this._lexer.get().text.toLowerCase();\n    var repeatNode = new ParseNode('repeat', repeatName);\n\n    // <block>\n    repeatNode.addChild(this._parseBlock());\n\n    // \\UNTIL\n    this._lexer.expect('func', 'until');\n\n    // {<cond>}\n    this._lexer.expect('open');\n    repeatNode.addChild(this._parseCond());\n    this._lexer.expect('close');\n\n    return repeatNode;\n};\n\nParser.prototype._parseUpon = function () {\n    if (!this._lexer.accept('func', 'upon')) return null;\n\n    var uponNode = new ParseNode('upon');\n\n    // { <cond> } <block>\n    this._lexer.expect('open');\n    uponNode.addChild(this._parseCond());\n    this._lexer.expect('close');\n    uponNode.addChild(this._parseBlock());\n\n    // \\ENDUPON\n    this._lexer.expect('func', 'endupon');\n\n    return uponNode;\n};\n\nvar IO_STATEMENTS = ['ensure', 'require', 'input', 'output'];\nvar STATEMENTS = ['state', 'print', 'return'];\nParser.prototype._parseStatement = function (acceptStatements) {\n    if (!this._lexer.accept('func', acceptStatements)) return null;\n\n    var stmtName = this._lexer.get().text.toLowerCase();\n    var stmtNode = new ParseNode('statement', stmtName);\n\n    stmtNode.addChild(this._parseOpenText());\n\n    return stmtNode;\n};\n\nvar COMMANDS = ['break', 'continue'];\nParser.prototype._parseCommand = function (acceptCommands) {\n    if (!this._lexer.accept('func', acceptCommands)) return null;\n\n    var cmdName = this._lexer.get().text.toLowerCase();\n    var cmdNode = new ParseNode('command', cmdName);\n\n    return cmdNode;\n};\n\nParser.prototype._parseComment = function () {\n    if (!this._lexer.accept('func', 'comment')) return null;\n\n    var commentNode = new ParseNode('comment');\n\n    // { \\text }\n    this._lexer.expect('open');\n    commentNode.addChild(this._parseCloseText());\n    this._lexer.expect('close');\n\n    return commentNode;\n};\n\nParser.prototype._parseCall = function () {\n    var lexer = this._lexer;\n    if (!lexer.accept('func', 'call')) return null;\n\n    var anyWhitespace = lexer.get().whitespace;\n\n    // \\CALL { <ordinary> } ({ <text> })[0..1]\n    lexer.expect('open');\n    var funcName = lexer.expect('ordinary');\n    lexer.expect('close');\n\n    var callNode = new ParseNode('call');\n    callNode.whitespace = anyWhitespace;\n    callNode.value = funcName;\n\n    lexer.expect('open');\n    var argsNode = this._parseCloseText();\n    callNode.addChild(argsNode);\n    lexer.expect('close');\n    return callNode;\n};\n\nParser.prototype._parseCond =\nParser.prototype._parseCloseText = function () {\n    return this._parseText('close');\n};\nParser.prototype._parseOpenText = function () {\n    return this._parseText('open');\n};\n\nParser.prototype._parseText = function (openOrClose) {\n    var textNode = new ParseNode(`${openOrClose}-text`);\n    // any whitespace between Atom and CloseText\n    var anyWhitespace = false;\n    var subTextNode;\n    while (true) {\n        // atom or call\n        subTextNode = this._parseAtom() || this._parseCall();\n        if (subTextNode) {\n            if (anyWhitespace) subTextNode.whitespace |= anyWhitespace;\n            textNode.addChild(subTextNode);\n            continue;\n        }\n\n        // or close text\n        if (this._lexer.accept('open')) {\n            subTextNode = this._parseCloseText();\n\n            anyWhitespace = this._lexer.get().whitespace;\n            subTextNode.whitespace = anyWhitespace;\n\n            textNode.addChild(subTextNode);\n            this._lexer.expect('close');\n            anyWhitespace = this._lexer.get().whitespace;\n            continue;\n        }\n\n        break;\n    }\n\n    return textNode;\n};\n\n/* The token accepted by atom of specific type */\nvar ACCEPTED_TOKEN_BY_ATOM = {\n    'ordinary': { tokenType: 'ordinary' },\n    'math': { tokenType: 'math' },\n    'special': { tokenType: 'special' },\n    'cond-symbol': {\n        tokenType: 'func',\n        tokenValues: ['and', 'or', 'not', 'true', 'false', 'to', 'downto'],\n    },\n    'quote-symbol': {\n        tokenType: 'quote',\n    },\n    'sizing-dclr': {\n        tokenType: 'func',\n        tokenValues: ['tiny', 'scriptsize', 'footnotesize', 'small', 'normalsize',\n            'large', 'Large', 'LARGE', 'huge', 'Huge'],\n    },\n    'font-dclr': {\n        tokenType: 'func',\n        tokenValues: ['normalfont', 'rmfamily', 'sffamily', 'ttfamily',\n            'upshape', 'itshape', 'slshape', 'scshape',\n            'bfseries', 'mdseries', 'lfseries'],\n    },\n    'font-cmd': {\n        tokenType: 'func',\n        tokenValues: ['textnormal', 'textrm', 'textsf', 'texttt', 'textup',\n            'textit', 'textsl', 'textsc', 'uppercase', 'lowercase', 'textbf',\n            'textmd', 'textlf'],\n    },\n    'text-symbol': {\n        tokenType: 'func',\n        tokenValues: ['textbackslash'],\n    },\n};\n\nParser.prototype._parseAtom = function () {\n    for (var atomType in ACCEPTED_TOKEN_BY_ATOM) {\n        var acceptToken = ACCEPTED_TOKEN_BY_ATOM[atomType];\n        var tokenText = this._lexer.accept(acceptToken.tokenType,\n                                           acceptToken.tokenValues);\n        if (tokenText === null) continue;\n\n        var anyWhitespace = this._lexer.get().whitespace;\n        if (atomType !== 'ordinary' && atomType !== 'math')\n            tokenText = tokenText.toLowerCase();\n        return new AtomNode(atomType, tokenText, anyWhitespace);\n    }\n    return null;\n};\n\nmodule.exports = Parser;\n"
  },
  {
    "path": "src/Renderer.js",
    "content": "/*\n* */\nvar utils = require('./utils');\n\n/*\n * TextStyle - used by TextEnvironment class to handle LaTeX text-style\n * commands or declarations.\n *\n * The font declarations are:\n *  \\normalfont, \\rmfamily, \\sffamily, \\ttfamily,\n *  \\bfseries, \\mdseries, \\lfseries,\n *  \\upshape, \\itshape, \\scshape, \\slshape.\n *\n * The font commands are:\n *  \\textnormal{}, \\textrm{}, \\textsf{}, \\texttt{},\n *  \\textbf{}, \\textmd{}, \\textlf{},\n *  \\textup{}, \\textit{}, \\textsc{}, \\textsl{},\n *  \\uppercase{}, \\lowercase{}.\n *\n * The sizing commands are:\n *  \\tiny, \\scriptsize, \\footnotesize, \\small, \\normalsize,\n *  \\large, \\Large, \\LARGE, \\huge, \\Huge.\n **/\nfunction TextStyle (outerFontSize) {\n    this._css = {};\n\n    this._fontSize = this._outerFontSize =\n        outerFontSize !== undefined ? outerFontSize : 1.0;\n}\n\n/*\n * Remember the font size of outer TextStyle object.\n *\n * As we use relative font size 'em', the outer span (has its own TextStyle\n * object) affects the size of the span to which this TextStyle object attached.\n * */\nTextStyle.prototype.outerFontSize = function (size) {\n    if (size !== undefined) this._outerFontSize = size;\n    return this._outerFontSize;\n};\n\nTextStyle.prototype.fontSize = function () {\n    return this._fontSize;\n};\n\n/* Update the font state by TeX command\n    cmd - the name of TeX command that alters current font\n*/\nTextStyle.prototype._fontCommandTable = {\n    // -------------- declaration --------------\n    // font-family\n    normalfont: { 'font-family': 'KaTeX_Main' },\n    rmfamily: { 'font-family': 'KaTeX_Main' },\n    sffamily: { 'font-family': 'KaTeX_SansSerif' },\n    ttfamily: { 'font-family': 'KaTeX_Typewriter' },\n    // weight\n    bfseries: { 'font-weight': 'bold' },\n    mdseries: { 'font-weight': 'medium' },\n    lfseries: { 'font-weight': 'lighter' },\n    // shape\n    upshape: { 'font-style': 'normal', 'font-variant': 'normal' },\n    itshape: { 'font-style': 'italic', 'font-variant': 'normal' },\n    scshape: { 'font-style': 'normal', 'font-variant': 'small-caps' },\n    slshape: { 'font-style': 'oblique', 'font-variant': 'normal' },\n    // -------------- command --------------\n    // font-family\n    textnormal: { 'font-family': 'KaTeX_Main' },\n    textrm: { 'font-family': 'KaTeX_Main' },\n    textsf: { 'font-family': 'KaTeX_SansSerif' },\n    texttt: { 'font-family': 'KaTeX_Typewriter' },\n    // weight\n    textbf: { 'font-weight': 'bold' },\n    textmd: { 'font-weight': 'medium' },\n    textlf: { 'font-weight': 'lighter' },\n    // shape\n    textup: { 'font-style': 'normal', 'font-variant': 'normal' },\n    textit: { 'font-style': 'italic', 'font-variant': 'normal' },\n    textsc: { 'font-style': 'normal', 'font-variant': 'small-caps' },\n    textsl: { 'font-style': 'oblique', 'font-variant': 'normal' },\n    // case\n    uppercase: { 'text-transform': 'uppercase' },\n    lowercase: { 'text-transform': 'lowercase' },\n};\n\nTextStyle.prototype._sizingScalesTable = {\n    tiny:           0.68,\n    scriptsize:     0.80,\n    footnotesize:   0.85,\n    small:          0.92,\n    normalsize:     1.00,\n    large:          1.17,\n    Large:          1.41,\n    LARGE:          1.58,\n    huge:           1.90,\n    Huge:           2.28,\n};\n\nTextStyle.prototype.updateByCommand = function (cmd) {\n    // Font command\n    var cmdStyles = this._fontCommandTable[cmd];\n    if (cmdStyles !== undefined) {\n        for (var attr in cmdStyles)\n            this._css[attr] = cmdStyles[attr];\n        return;\n    }\n\n    // Sizing command\n    var fontSize = this._sizingScalesTable[cmd];\n    if (fontSize !== undefined) {\n        this._outerFontSize = this._fontSize;\n        this._fontSize = fontSize;\n        return;\n    }\n\n    throw new ParserError('Unrecognized `text-style` command');\n};\n\nTextStyle.prototype.toCSS = function () {\n    var cssStr = '';\n    for (var attr in this._css) {\n        var val = this._css[attr];\n        if (val === undefined) continue;\n        cssStr += `${attr}:${val};`;\n    }\n    if (this._fontSize !== this._outerFontSize)\n        cssStr += `font-size:${this._fontSize / this._outerFontSize}em;`;\n\n    return cssStr;\n};\n\n/*\n * TextEnvironment - renders the children nodes in a ParseNode of type\n * 'close-text' or 'open-text' to HTML.\n **/\nfunction TextEnvironment (nodes, textStyle) {\n    this._nodes = nodes;\n    this._textStyle = textStyle;\n}\n\nTextEnvironment.prototype._renderCloseText = function (node, backend) {\n    var newTextStyle = new TextStyle(this._textStyle.fontSize());\n    var closeTextEnv = new TextEnvironment(node.children, newTextStyle);\n    if (node.whitespace) this._html.putText(' ');\n    this._html.putHTML(closeTextEnv.renderToHTML(backend));\n};\n\nTextEnvironment.prototype.renderToHTML = function (backend) {\n    this._html = new HTMLBuilder();\n\n    var node;\n    while ((node = this._nodes.shift()) !== undefined) {\n        var type = node.type;\n        var text = node.value;\n\n        // Insert whitespace before the atom if necessary\n        if (node.whitespace) this._html.putText(' ');\n\n        switch (type) {\n            case 'ordinary':\n                this._html.putText(text);\n                break;\n            case 'math':\n                if (typeof backend === 'undefined') {\n                    throw EvalError('No math backend found. Please setup KaTeX or MathJax.');\n                }\n                else if (backend.name === 'katex') {\n                    this._html.putHTML(backend.driver.renderToString(text));\n                }\n                else if (backend.name === 'mathjax') {\n                    if (backend.version === 3) {\n                        // use synchronous conversion available in 3.x\n                        this._html.putHTML(backend.driver.tex2chtml(text, { display: false }).outerHTML);\n                    }\n                    else {\n                        // keep math text, typeset later\n                        this._html.putText(`$${text}$`);\n                    }\n                }\n                else {\n                    throw new EvalError(`Unknown math backend ${backend}`);\n                }\n                break;\n            case 'cond-symbol':\n                this._html\n                    .beginSpan('ps-keyword')\n                    .putText(text.toLowerCase())\n                    .endSpan();\n                break;\n            case 'special':\n                if (text === '\\\\\\\\') {\n                    this._html.putHTML('<br/>');\n                    break;\n                }\n                var replace = {\n                    '\\\\{': '{',\n                    '\\\\}': '}',\n                    '\\\\$': '$',\n                    '\\\\&': '&',\n                    '\\\\#': '#',\n                    '\\\\%': '%',\n                    '\\\\_': '_',\n                };\n                var replaceStr = replace[text];\n                this._html.putText(replaceStr);\n                break;\n            case 'text-symbol':\n                var name2Values = {\n                    'textbackslash': '\\\\',\n                };\n                var symbolValue = name2Values[text];\n                this._html.putText(symbolValue);\n                break;\n            case 'quote-symbol':\n                var quoteReplace = {\n                    '`': '‘',\n                    '``': '“',\n                    '\\'': '’',\n                    '\\'\\'': '”',\n                };\n                var realQuote = quoteReplace[text];\n                this._html.putText(realQuote);\n                break;\n            case 'call':\n                // \\CALL{funcName}{funcArgs}\n                // ==>\n                // funcName(funcArgs)\n                this._html.beginSpan('ps-funcname').putText(text).endSpan();\n                this._html.write('(');\n                var argsTextNode = node.children[0];\n                this._renderCloseText(argsTextNode, backend);\n                this._html.write(')');\n                break;\n            case 'close-text':\n                this._renderCloseText(node, backend);\n                break;\n            // There are two kinds of typestyle commands:\n            //      command (e.g. \\textrm{...}).\n            // and\n            //      declaration (e.g. { ... \\rmfamily ... })\n            //\n            // For typestyle commands, it works as following:\n            //      \\textsf     --> create a new typestyle\n            //      {           --> save the current typestyle, and then use the new one\n            //      ...         --> the new typestyle is in use\n            //      }           --> restore the last typestyle\n            //\n            // For typestyle declaration, it works a little bit diferrently:\n            //      {           --> save the current typestyle, and then create and use\n            //                      an identical one\n            //      ...         --> the new typestyle is in use\n            //      \\rmfamily   --> create a new typestyle\n            //      ...         --> the new typestyle is in use\n            //      }           --> restore the last typestyle\n            case 'font-dclr':\n            case 'sizing-dclr':\n                this._textStyle.updateByCommand(text);\n                this._html.beginSpan(null, this._textStyle.toCSS());\n                var textEnvForDclr = new TextEnvironment(this._nodes,\n                                                         this._textStyle);\n                this._html.putHTML(textEnvForDclr.renderToHTML(backend));\n                this._html.endSpan();\n                break;\n            case 'font-cmd':\n                var textNode = this._nodes[0];\n                if (textNode.type !== 'close-text') continue;\n\n                var innerTextStyle = new TextStyle(this._textStyle.fontSize());\n                innerTextStyle.updateByCommand(text);\n                this._html.beginSpan(null, innerTextStyle.toCSS());\n                var textEnvForCmd = new TextEnvironment(textNode.children,\n                                                        innerTextStyle);\n                this._html.putHTML(textEnvForCmd.renderToHTML(backend));\n                this._html.endSpan();\n                break;\n            default:\n                throw new ParseError(`Unexpected ParseNode of type ${node.type}`);\n        }\n    }\n\n    return this._html.toMarkup();\n};\n\n/* HTMLBuilder - A helper class for constructing HTML */\nfunction HTMLBuilder () {\n    this._body = [];\n    this._textBuf = [];\n}\n\nHTMLBuilder.prototype.beginDiv = function (className, style, extraStyle) {\n    this._beginTag('div', className, style, extraStyle);\n    this._body.push('\\n'); // make the generated HTML more human friendly\n    return this;\n};\n\nHTMLBuilder.prototype.endDiv = function () {\n    this._endTag('div');\n    this._body.push('\\n'); // make the generated HTML more human friendly\n    return this;\n};\n\nHTMLBuilder.prototype.beginP = function (className, style, extraStyle) {\n    this._beginTag('p', className, style, extraStyle);\n    this._body.push('\\n'); // make the generated HTML more human friendly\n    return this;\n};\n\nHTMLBuilder.prototype.endP = function () {\n    this._flushText();\n    this._endTag('p');\n    this._body.push('\\n'); // make the generated HTML more human friendly\n    return this;\n};\n\nHTMLBuilder.prototype.beginSpan = function (className, style, extraStyle) {\n    this._flushText();\n    return this._beginTag('span', className, style, extraStyle);\n};\n\nHTMLBuilder.prototype.endSpan = function () {\n    this._flushText();\n    return this._endTag('span');\n};\n\nHTMLBuilder.prototype.putHTML = function (html) {\n    this._flushText();\n    this._body.push(html);\n    return this;\n};\n\nHTMLBuilder.prototype.putText = function (text) {\n    this._textBuf.push(text);\n    return this;\n};\n\nHTMLBuilder.prototype.write = function (html) {\n    this._body.push(html);\n};\n\nHTMLBuilder.prototype.toMarkup = function () {\n    this._flushText();\n    var html = this._body.join('');\n    return html.trim();\n};\n\nHTMLBuilder.prototype.toDOM = function () {\n    var html = this.toMarkup();\n    var div = document.createElement('div');\n    div.innerHTML = html;\n    return div.firstChild;\n};\n\nHTMLBuilder.prototype._flushText = function () {\n    if (this._textBuf.length === 0) return;\n\n    var text = this._textBuf.join('');\n    this._body.push(this._escapeHtml(text));\n    // this._body.push(text);\n    this._textBuf = [];\n};\n\n/* Write the beginning of a DOM element\n    tag - the tag of the element\n    className - the className for the tag\n    style - CSS style that applies directly on the tag. This parameter can be\n            either a string, e.g., 'color:red', or an object, e.g.\n            { color: 'red', margin-left: '1em'}\n*/\nHTMLBuilder.prototype._beginTag = function (tag, className, style, extraStyle) {\n    var spanHTML = `<${tag}`;\n    if (className) spanHTML += ` class=\"${className}\"`;\n    if (style) {\n        var styleCode;\n        if (utils.isString(style)) {\n            styleCode = style;\n        }\n        else { // style\n            styleCode = '';\n            for (var attrName in style) {\n                attrVal = style[attrName];\n                styleCode += `${attrName}:${attrVal};`;\n            }\n        }\n        if (extraStyle) styleCode += extraStyle;\n        spanHTML += ` style=\"${styleCode}\"`;\n    }\n    spanHTML += '>';\n    this._body.push(spanHTML);\n    return this;\n};\n\nHTMLBuilder.prototype._endTag = function (tag) {\n    this._body.push(`</${tag}>`);\n    return this;\n};\n\nvar entityMap = {\n    \"&\": \"&amp;\",\n    \"<\": \"&lt;\",\n    \">\": \"&gt;\",\n    '\"': '&quot;',\n    \"'\": '&#39;',\n    \"/\": '&#x2F;',\n};\n\nHTMLBuilder.prototype._escapeHtml = function (string) {\n    return String(string).replace(\n        /[&<>\"'/]/g,\n        (s) => entityMap[s]\n    );\n};\n\n/*\n * RendererOptions - represents options that Renderer accepts.\n *\n * The following are possible options:\n *      indentSize - The indent size of inside a control block, e.g. if, for,\n *          etc. The unit must be in 'em'. Default value: '1.2em'.\n *      commentDelimiter  - The delimiters used to start and end a comment region.\n *          Note that only line comments are supported. Default value: '//'.\n *      lineNumber - Whether line numbering is enabled. Default value: false.\n *      lineNumberPunc - The punctuation that follows line number. Default\n *          value: ':'.\n *      noEnd - Whether block ending, like `end if`, end procedure`, etc., are\n *          showned. Default value: false.\n *      captionCount - Set the caption counter to this new value.\n *      titlePrefix - The prefix in the title of the algorithm. Default value: 'Algorithm'.\n *\n **/\nfunction RendererOptions (options) {\n    options = options || {};\n    this.indentSize =\n        options.indentSize ? this._parseEmVal(options.indentSize) : 1.2;\n    this.commentDelimiter  = options.commentDelimiter !== undefined ? options.commentDelimiter : ' // ';\n    this.lineNumberPunc = options.lineNumberPunc !== undefined ? options.lineNumberPunc : ':';\n    this.lineNumber = options.lineNumber !== undefined ? options.lineNumber : false;\n    this.noEnd = options.noEnd !== undefined ? options.noEnd : false;\n    this.scopeLines = options.scopeLines !== undefined ? options.scopeLines : false;\n    if (options.captionCount !== undefined)\n        Renderer.captionCount = options.captionCount;\n    this.titlePrefix = options.titlePrefix !== undefined ? options.titlePrefix : 'Algorithm';\n}\n\nRendererOptions.prototype._parseEmVal = function (emVal) {\n    emVal = emVal.trim();\n    if (emVal.indexOf('em') !== emVal.length - 2)\n        throw new TypeError('Unit error; expected `em` suffix');\n\n    return Number(emVal.substring(0, emVal.length - 2));\n};\n\n/*\n * Renderer - Converts a parse tree to HTML\n *\n * There are three levels for renderer: Group (Block), Line and Segment,\n * which are rendered to HTML tag, <div>, <p>, and <span>, respectively.\n **/\nfunction Renderer (parser, options) {\n    this._root = parser.parse();\n    this._options = new RendererOptions(options);\n    this._openLine = false;\n    this._blockLevel = 0;\n    this._textLevel = -1;\n    this._globalTextStyle = new TextStyle();\n    this.backend = undefined;\n\n    try {\n        if (typeof katex === 'undefined')\n            katex = require('katex');\n    }\n    catch (_) { /* ignore */ }\n\n    try {\n        if (typeof MathJax === 'undefined')\n            MathJax = require('mathjax');\n    }\n    catch (_) { /* ignore */ }\n\n    if (typeof katex !== 'undefined') {\n        this.backend = {\n            'name' : 'katex',\n            'driver' : katex,\n        };\n    }\n    else if (typeof MathJax !== 'undefined') {\n        this.backend = {\n            'name' : 'mathjax',\n            'version': parseInt(MathJax.version.split('.')[0]),\n            'driver' : MathJax,\n        };\n    }\n}\n\n/*  The global counter for the numbering of the algorithm environment */\nRenderer.captionCount = 0;\n\nRenderer.prototype.toMarkup = function () {\n    var html = this._html = new HTMLBuilder();\n    this._buildTree(this._root);\n    delete this._html;\n    return html.toMarkup();\n};\n\nRenderer.prototype.toDOM = function () {\n    var html = this.toMarkup();\n    var div = document.createElement('div');\n    div.innerHTML = html;\n    return div.firstChild;\n};\n\nRenderer.prototype._beginGroup = function (name, extraClass, style) {\n    this._closeLineIfAny();\n    this._html.beginDiv(`ps-${name}${extraClass ? ` ${extraClass}` : ''}`,\n                        style);\n};\n\nRenderer.prototype._endGroup = function (name) {\n    this._closeLineIfAny();\n    this._html.endDiv();\n};\n\nRenderer.prototype._beginBlock = function () {\n    // The first block have to extra left margin when line number are displayed\n    var extraIndentForFirstBlock =\n        this._options.lineNumber && this._blockLevel === 0 ? 0.6 : 0;\n    var blockIndent = this._options.indentSize + extraIndentForFirstBlock;\n\n    // We also need to handle the extra margin for scope lines\n    // We divide the block indent by 2 because the other margin will be after the indent symbol\n    if (this._options.scopeLines)\n        blockIndent /= 2;\n\n    this._beginGroup('block', null, {\n        'margin-left': `${blockIndent}em`,\n    });\n    this._blockLevel++;\n};\n\nRenderer.prototype._endBlock = function () {\n    this._closeLineIfAny();\n    this._endGroup();\n    this._blockLevel--;\n};\n\nRenderer.prototype._newLine = function () {\n    this._closeLineIfAny();\n\n    this._openLine = true;\n\n    // For every new line, reset the relative sizing of text style\n    this._globalTextStyle.outerFontSize(1.0);\n\n    var indentSize = this._options.indentSize;\n    // if this line is for code (e.g. \\STATE)\n    if (this._blockLevel > 0) {\n        this._numLOC++;\n\n        this._html.beginP('ps-line ps-code', this._globalTextStyle.toCSS());\n\n        // We need to consider the indent width for linenumbers and scopelines\n        var extraIndentSize = this._options.lineNumber ? indentSize * 1.25 : 0;\n        extraIndentSize += this._options.scopeLines ? indentSize * 0.1 : 0;\n\n        // We add this width if we need to pad the line (e.g., with linenumber).\n        // We don't need to handle scope lines here, as they do not add any extra text in the line.\n        if (this._options.lineNumber) {\n            this._html\n                .beginSpan('ps-linenum', {\n                    'left': `${-((this._blockLevel - 1) * (extraIndentSize))}em`,\n                })\n                .putText(this._numLOC + this._options.lineNumberPunc)\n                .endSpan();\n        }\n    }\n    // if this line is for pre-conditions (e.g. \\REQUIRE)\n    else {\n        this._html.beginP('ps-line', {\n            'text-indent': `${-indentSize}em`,\n            'padding-left': `${indentSize}em`,\n        }, this._globalTextStyle.toCSS());\n    }\n};\n\nRenderer.prototype._closeLineIfAny = function () {\n    if (!this._openLine) return;\n\n    this._html.endP();\n\n    this._openLine = false;\n};\n\nRenderer.prototype._typeKeyword = function (keyword) {\n    this._html.beginSpan('ps-keyword').putText(keyword).endSpan();\n};\n\nRenderer.prototype._typeFuncName = function (funcName) {\n    this._html.beginSpan('ps-funcname').putText(funcName).endSpan();\n};\n\nRenderer.prototype._typeText = function (text) {\n    this._html.write(text);\n};\n\nRenderer.prototype._buildTreeForAllChildren = function (node) {\n    var children = node.children;\n    for (var ci = 0; ci < children.length; ci++)\n        this._buildTree(children[ci]);\n};\n\n// The comment nodes at the beginning of blockNode are comments for controls\n// Thus they should be rendered out of block\nRenderer.prototype._buildCommentsFromBlock = function (blockNode) {\n    var children = blockNode.children;\n    while (children.length > 0 && children[0].type === 'comment') {\n        var commentNode = children.shift();\n        this._buildTree(commentNode);\n    }\n};\n\nRenderer.prototype._buildTree = function (node) {\n    var ci; var child; var textNode;\n    switch (node.type) {\n        // The hierarchicy of build tree: Group (Block) > Line > Text\n        // ----------------- Groups -------------------------------------\n        case 'root':\n            this._beginGroup('root');\n            this._buildTreeForAllChildren(node);\n            this._endGroup();\n            break;\n        case 'algorithm':\n            // First, decide the caption if any\n            var lastCaptionNode;\n            for (ci = 0; ci < node.children.length; ci++) {\n                child = node.children[ci];\n                if (child.type !== 'caption') continue;\n                lastCaptionNode = child;\n                Renderer.captionCount++;\n            }\n            // Then, build the header for algorithm\n            if (lastCaptionNode) {\n                this._beginGroup('algorithm', 'with-caption');\n                this._buildTree(lastCaptionNode);\n            }\n            else {\n                this._beginGroup('algorithm');\n            }\n            // Then, build other nodes\n            for (ci = 0; ci < node.children.length; ci++) {\n                child = node.children[ci];\n                if (child.type === 'caption') continue;\n                this._buildTree(child);\n            }\n            this._endGroup();\n            break;\n        case 'algorithmic':\n            // Check if we need to add additional classes for the provided options\n            var divClasses = this._options.lineNumber ? ' with-linenum ' : '';\n            divClasses += this._options.scopeLines ? ' with-scopelines ' : '';\n\n            if (divClasses) {\n                this._beginGroup('algorithmic', divClasses);\n                this._numLOC = 0;\n            }\n            else {\n                this._beginGroup('algorithmic');\n            }\n            this._buildTreeForAllChildren(node);\n            this._endGroup();\n            break;\n        case 'block':\n            // node: <block>\n            // ==>\n            // HTML: <div class=\"ps-block\"> ... </div>\n            this._beginBlock();\n            this._buildTreeForAllChildren(node);\n            this._endBlock();\n            break;\n        // ----------------- Mixture (Groups + Lines) -------------------\n        case 'function':\n            // \\FUNCTION{<ordinary>}{<text>} <block> \\ENDFUNCTION\n            // ==>\n            // function <ordinary>(<text>)\n            // ...\n            // end function\n            var funcType = node.value.type.toLowerCase();\n            var defFuncName = node.value.name;\n            textNode = node.children[0];\n            var blockNode = node.children[1];\n            this._newLine();\n            this._typeKeyword(`${funcType} `);\n            this._typeFuncName(defFuncName);\n            this._typeText('(');\n            this._buildTree(textNode);\n            this._typeText(')');\n\n            this._buildCommentsFromBlock(blockNode);\n            this._buildTree(blockNode);\n\n            if (!this._options.noEnd) {\n                this._newLine();\n                this._typeKeyword(`end ${funcType}`);\n            }\n            break;\n        case 'if':\n            // \\IF { <cond> }\n            // ==>\n            // <p class=\"ps-line\">\n            //      <span class=\"ps-keyword\">if</span>\n            //      ...\n            //      <span class=\"ps-keyword\">then</span>\n            // </p>\n            this._newLine();\n            this._typeKeyword('if ');\n            ifCond = node.children[0];\n            this._buildTree(ifCond);\n            this._typeKeyword(' then');\n            // <block>\n            var ifBlock = node.children[1];\n            this._buildCommentsFromBlock(ifBlock);\n            this._buildTree(ifBlock);\n\n            // ( \\ELIF {<cond>} <block> )[0..n]\n            var numElif = node.value.numElif;\n            for (var ei = 0 ; ei < numElif; ei++) {\n                // \\ELIF {<cond>}\n                // ==>\n                // <p class=\"ps-line\">\n                //      <span class=\"ps-keyword\">elif</span>\n                //      ...\n                //      <span class=\"ps-keyword\">then</span>\n                // </p>\n                this._newLine();\n                this._typeKeyword('else if ');\n                var elifCond = node.children[2 + 2 * ei];\n                this._buildTree(elifCond);\n                this._typeKeyword(' then');\n\n                // <block>\n                var elifBlock = node.children[2 + 2 * ei + 1];\n                this._buildCommentsFromBlock(elifBlock);\n                this._buildTree(elifBlock);\n            }\n\n            // ( \\ELSE <block> )[0..1]\n            var hasElse = node.value.hasElse;\n            if (hasElse) {\n                // \\ELSE\n                // ==>\n                // <p class=\"ps-line\">\n                //      <span class=\"ps-keyword\">else</span>\n                // </p>\n                this._newLine();\n                this._typeKeyword('else');\n\n                // <block>\n                var elseBlock = node.children[node.children.length - 1];\n                this._buildCommentsFromBlock(elseBlock);\n                this._buildTree(elseBlock);\n            }\n\n            if (!this._options.noEnd) {\n                // ENDIF\n                this._newLine();\n                this._typeKeyword('end if');\n            }\n            break;\n        case 'loop':\n            // \\FOR{<cond>} or \\WHILE{<cond>}\n            // ==>\n            // <p class=\"ps-line\">\n            //      <span class=\"ps-keyword\">for</span>\n            //      ...\n            //      <span class=\"ps-keyword\">do</span>\n            // </p>\n            this._newLine();\n            var loopType = node.value;\n            var displayLoopName = {\n                'for': 'for',\n                'forall': 'for all',\n                'while': 'while',\n            };\n            this._typeKeyword(`${displayLoopName[loopType]} `);\n            var loopCond = node.children[0];\n            this._buildTree(loopCond);\n            this._typeKeyword(' do');\n\n            // <block>\n            var block = node.children[1];\n            this._buildCommentsFromBlock(block);\n            this._buildTree(block);\n\n            if (!this._options.noEnd) {\n                // \\ENDFOR or \\ENDWHILE\n                // ==>\n                // <p class=\"ps-line\">\n                //      <span class=\"ps-keyword\">end for</span>\n                // </p>\n                this._newLine();\n                var endLoopName = loopType === 'while' ? 'end while' : 'end for';\n                this._typeKeyword(endLoopName);\n            }\n            break;\n        case 'repeat':\n            // \\REPEAT\n            // ==>\n            // <p class=\"ps-line\">\n            //     <span class=\"ps-keyword\">repeat</span>\n            // </p>\n            this._newLine();\n            this._typeKeyword('repeat');\n\n            // block\n            var repeatBlock = node.children[0];\n            this._buildCommentsFromBlock(repeatBlock);\n            this._buildTree(repeatBlock);\n\n\n            // \\UNTIL{<cond>}\n            // ==>\n            // <p class=\"ps-line\">\n            //     <span class=\"ps-keyword\">until</span>\n            // </p>\n            this._newLine();\n            this._typeKeyword('until ');\n            var repeatCond = node.children[1];\n            this._buildTree(repeatCond);\n\n            break;\n        case 'upon':\n            // \\UPON { <cond> }\n            // ==>\n            // <p class=\"ps-line\">\n            //      <span class=\"ps-keyword\">upon</span>\n            // </p>\n            this._newLine();\n            this._typeKeyword('upon ');\n            uponCond = node.children[0];\n            this._buildTree(uponCond);\n            // <block>\n            var uponBlock = node.children[1];\n            this._buildCommentsFromBlock(uponBlock);\n            this._buildTree(uponBlock);\n\n            if (!this._options.noEnd) {\n                // ENDUPON\n                this._newLine();\n                this._typeKeyword('end upon');\n            }\n            break;\n        // ------------------- Lines -------------------\n        case 'command':\n            var cmdName = node.value;\n            var displayCmdName = {\n                'break': 'break',\n                'continue': 'continue',\n            }[cmdName];\n\n            this._newLine();\n            if (displayCmdName) this._typeKeyword(displayCmdName);\n            break;\n        case 'caption':\n            this._newLine();\n            this._typeKeyword(`${this._options.titlePrefix\n            } ${Renderer.captionCount} `);\n            textNode = node.children[0];\n            this._buildTree(textNode);\n            break;\n        case 'comment':\n            textNode = node.children[0];\n            this._html.beginSpan('ps-comment');\n            this._html.putText(this._options.commentDelimiter);\n            this._buildTree(textNode);\n            this._html.endSpan();\n            break;\n        case 'statement':\n            // statements: \\STATE, \\ENSURE, \\PRINT, \\RETURN, etc.\n            var stmtName = node.value;\n            var displayStmtName = {\n                'state': '',\n                'ensure': 'Ensure: ',\n                'require': 'Require: ',\n                'input': 'Input: ',\n                'output': 'Output: ',\n                'print': 'print ',\n                'return': 'return ',\n            }[stmtName];\n\n            this._newLine();\n            if (displayStmtName) this._typeKeyword(displayStmtName);\n            textNode = node.children[0];\n            this._buildTree(textNode);\n            break;\n        // ------------------- Text -------------------\n        case 'open-text':\n            var openTextEnv = new TextEnvironment(node.children,\n                                                  this._globalTextStyle);\n            this._html.putHTML(openTextEnv.renderToHTML(this.backend));\n            break;\n        case 'close-text':\n            var outerFontSize = this._globalTextStyle.fontSize();\n            var newTextStyle = new TextStyle(outerFontSize);\n            var closeTextEnv = new TextEnvironment(node.children, newTextStyle);\n            this._html.putHTML(closeTextEnv.renderToHTML(this.backend));\n            break;\n        default:\n            throw new ParseError(`Unexpected ParseNode of type ${node.type}`);\n    }\n};\n\nmodule.exports = Renderer;\n"
  },
  {
    "path": "src/utils.js",
    "content": "module.exports = {\n    isString: (str) => (typeof str === 'string') || (str instanceof String),\n\n    isObject: (obj) => (typeof obj === 'object' && (obj instanceof Object)),\n\n    toString: function (obj) {\n        if (!this.isObject(obj))\n            return `${obj}`;\n\n        var parts = [];\n        for (var member in obj)\n            parts.push(`${member}: ${this.toString(obj[member])}`);\n\n        return parts.join(', ');\n    },\n};\n"
  },
  {
    "path": "static/body.html.part",
    "content": "</head>\n\n<body>\n    <pre id=\"test-basics\" data-line-number=true>\n        \\begin{algorithm}\n        \\caption{Test text-style}\n        \\begin{algorithmic}\n        \\REQUIRE some preconditions\n        \\ENSURE some postconditions\n        \\INPUT some inputs\n        \\OUTPUT some outputs\n        \\PROCEDURE{Test-Declarations}{}\n            \\STATE font families: {\\sffamily sffamily, \\ttfamily ttfamily, \\normalfont normalfont, \\rmfamily rmfamily.}\n            \\STATE font weights: {normal weight, \\bfseries bold, \\mdseries\n            medium, \\lfseries lighter. }\n            \\STATE font shapes: {\\itshape itshape \\scshape Small-Caps \\slshape slshape \\upshape upshape.}\n            \\STATE font sizes: \\tiny tiny \\scriptsize scriptsize \\footnotesize\n            footnotesize \\small small \\normalsize normal \\large large \\Large Large\n            \\LARGE LARGE \\huge huge \\Huge Huge \\normalsize\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Commands}{}\n            \\STATE \\textnormal{textnormal,} \\textrm{textrm,} \\textsf{textsf,} \\texttt{texttt.}\n            \\STATE \\textbf{textbf,} \\textmd{textmd,} \\textlf{textlf.}\n            \\STATE \\textup{textup,} \\textit{textit,} \\textsc{textsc,} \\textsl{textsl.}\n            \\STATE \\uppercase{uppercase,} \\lowercase{LOWERCASE.}\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Colors}{}\n            \\STATE colors: $\\color{red}{red}$, $\\color{green}{green}$, $\\color{blue}{blue}$\n            \\STATE colors: $\\color{yellow}{yellow}$, $\\color{cyan}{cyan}$, $\\color{magenta}{magenta}$\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n\n        \\begin{algorithm}\n        \\caption{Test atoms}\n        \\begin{algorithmic}\n        \\STATE \\textbf{Specials:} \\{ \\} \\$ \\& \\# \\% \\_\n        \\STATE \\textbf{Bools:} \\AND \\OR \\NOT \\TRUE \\FALSE\n        \\STATE \\textbf{Carriage return:} first line \\\\ second line\n        \\STATE \\textbf{Text-symbols:} \\textbackslash\n        \\STATE \\textbf{Quote-symbols:} `single quotes', ``double quotes''\n        \\STATE \\textbf{Math:} $(\\mathcal{C}_m)$, $i \\gets i + 1$, $E=mc^2$, \\( x^n + y^n = z^n \\), $\\$$, \\(\\$\\)\n        \\END{ALGORITHMIC}\n        \\END{ALGORITHM}\n    </pre>\n    <pre id=\"test-codes\">\n        \\begin{algorithm}\n        \\caption{Test control blocks}\n        \\begin{algorithmic}\n        \\PROCEDURE{Test-If}{}\n            \\IF{&lt;cond&gt;}\n                \\STATE &lt;block&gt;\n            \\ELIF{&lt;cond&gt;}\n                \\STATE &lt;block&gt;\n            \\ELSE\n                \\STATE &lt;block&gt;\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For}{$n$}\n            \\STATE $i \\gets 0$\n            \\FOR{$i < n$}\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-To}{$n$}\n            \\STATE $i \\gets 0$\n            \\FOR{$i$ \\TO $n$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-DownTo}{$n$}\n            \\FOR{$i \\gets n$ \\DOWNTO $0$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-For-All}{$n$}\n            \\FORALL{$i \\in \\{0, 1, \\cdots, n\\}$}\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-While}{$n$}\n            \\STATE $i \\gets 0$\n            \\WHILE{$i < n$}\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\ENDWHILE\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Repeat}{$n$}\n            \\STATE $i \\gets 0$\n            \\REPEAT\n                \\PRINT $i$\n                \\STATE $i \\gets i + 1$\n            \\UNTIL{$i>n$}\n        \\ENDPROCEDURE\n        \\PROCEDURE{Test-Break-Continue}{$n$}\n            \\FOR{$i = 0$ \\TO $2n$}\n                \\IF{$i < n/2$}\n                    \\CONTINUE\n                \\ELIF{$i > n$}\n                    \\BREAK\n                \\ENDIF\n                \\PRINT $i$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n        \\begin{algorithm}\n        \\caption{Test statements and comments}\n        \\begin{algorithmic}\n        \\PROCEDURE{Test-Statements}{}\n            \\STATE This line is a normal statement\n            \\PRINT \\texttt{`this is print statement'}\n            \\RETURN $retval$\n        \\ENDPROCEDURE\n\n        \\PROCEDURE{Test-Comments}{} \\COMMENT{comment for procedure}\n            \\STATE a statement \\COMMENT{inline comment}\n            \\STATE \\COMMENT{line comment}\n            \\IF{some condition}\\COMMENT{comment for if}\n                \\RETURN \\TRUE \\COMMENT{another inline comment}\n            \\ELSE \\COMMENT{comment for else}\n                \\RETURN \\FALSE \\COMMENT{yet another inline comment}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre id=\"test-examples\" data-title-prefix=\"Procedure\">\n        % This quicksort algorithm is extracted from Chapter 7, Introduction\n        % to Algorithms (3rd edition)\n        \\begin{algorithm}\n        \\caption{Quicksort}\n        \\begin{algorithmic}\n        \\PROCEDURE{Quicksort}{$A, p, r$}\n            \\IF{$p < r$}\n                \\STATE $q = $ \\CALL{Partition}{$A, p, r$}\n                \\STATE \\CALL{Quicksort}{$A, p, q - 1$}\n                \\STATE \\CALL{Quicksort}{$A, q + 1, r$}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Partition}{$A, p, r$}\n            \\STATE $x = A[r]$\n            \\STATE $i = p - 1$\n            \\FOR{$j = p$ \\TO $r - 1$}\n                \\IF{$A[j] < x$}\n                    \\STATE $i = i + 1$\n                    \\STATE exchange\n                    $A[i]$ with $A[j]$\n                \\ENDIF\n                \\STATE exchange $A[i]$ with $A[r]$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre id=\"test-examples-custom-title\">\n        % This quicksort algorithm is extracted from Chapter 7, Introduction \n        % to Algorithms (3rd edition)\n        \\begin{algorithm}\n        \\caption{Quicksort}\n        \\begin{algorithmic}\n        \\PROCEDURE{Quicksort}{$A, p, r$}\n            \\IF{$p < r$} \n                \\STATE $q = $ \\CALL{Partition}{$A, p, r$}\n                \\STATE \\CALL{Quicksort}{$A, p, q - 1$}\n                \\STATE \\CALL{Quicksort}{$A, q + 1, r$}\n            \\ENDIF\n        \\ENDPROCEDURE\n        \\PROCEDURE{Partition}{$A, p, r$}\n            \\STATE $x = A[r]$\n            \\STATE $i = p - 1$\n            \\FOR{$j = p$ \\TO $r - 1$}\n                \\IF{$A[j] < x$}\n                    \\STATE $i = i + 1$\n                    \\STATE exchange\n                    $A[i]$ with $A[j]$\n                \\ENDIF\n                \\STATE exchange $A[i]$ with $A[r]$\n            \\ENDFOR\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre class=\"scopeline-pseudocode\" data-line-number=true>\n        \\begin{algorithm}\n        \\caption{Classical Euclidean Algorithm}\n        \\begin{algorithmic}\n            \\PROCEDURE{Euclid}{$a,b$}\n                \\WHILE{$a \\neq b$}\n                    \\IF{$a > b$}\n                        \\STATE $a \\gets a - b$\n                    \\ELSE\n                        \\STATE $b \\gets b - a$\n                    \\ENDIF\n                \\ENDWHILE\n                \\RETURN $a$\n            \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n    <pre class=\"scopeline-pseudocode\" data-no-end=true>\n        \\begin{algorithm}\n        \\caption{DBSCAN}\n        \\begin{algorithmic}\n        \\INPUT A dataset $D$, the $\\varepsilon$ distance threshold, and the minimum number of points $minPts$\n        \\OUTPUT A set of clusters $K$\n        \\PROCEDURE{DBSCAN}{$D, \\varepsilon, minPts$}\n            \\STATE $K \\gets \\emptyset$\n            \\FORALL{$p \\in D$}\n                \\IF{$p$ has not been visited}\n                    \\STATE mark $p$ as visited\n                    \\STATE $N_{\\varepsilon}(p) \\gets $ \\textsc{RangeQuery}$(p, \\varepsilon, D)$\n                    \\IF{$N_{\\varepsilon}(p) < minPts$}\n                        \\STATE mark $p$ as noise\n                    \\ELSE\n                        \\COMMENT{p is a core object}\n                        \\STATE $C \\gets $ \\textsc{ExpandCluster}$(p, N_{\\varepsilon}(p))$\n                        \\STATE $K \\gets K \\cup \\{C\\}$\n                    \\ENDIF\n                \\ENDIF\n            \\ENDFOR\n            \\RETURN $K$\n        \\ENDPROCEDURE\n        \\end{algorithmic}\n        \\end{algorithm}\n    </pre>\n"
  },
  {
    "path": "static/footer.html.part",
    "content": "    <script>\n        pseudocode.renderElement(document.getElementById(\"test-basics\"),\n                                 {\n                                     lineNumber: false,\n                                     noEnd: true\n                                 });\n        pseudocode.renderElement(document.getElementById(\"test-codes\"));\n        pseudocode.renderElement(document.getElementById(\"test-examples\"),\n                                 {\n                                     lineNumber: true,\n                                     noEnd: false\n                                 });\n        pseudocode.renderElement(document.getElementById(\"test-examples-custom-title\"),\n                                 {\n                                     lineNumber: true,\n                                     noEnd: false,\n                                     titlePrefix: \"My pretty Algorithm\"\n                                 });                                   \n        pseudocode.renderClass(\"scopeline-pseudocode\", { scopeLines: true });\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "static/katex.html.part",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n    <meta charset=\"utf-8\">\n    <title>pseudocode.js Samples with KaTeX</title>\n\n    <!-- Setup KaTeX -->\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js\"\n            integrity=\"sha512-EKW5YvKU3hpyyOcN6jQnAxO/L8gts+YdYV6Yymtl8pk9YlYFtqJgihORuRoBXK8/cOIlappdU6Ms8KdK6yBCgA==\"\n            crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\">\n    </script>\n\n    <!-- Pseudocode -->\n    <link rel=\"stylesheet\" href=\"pseudocode.css\" type=\"text/css\">\n    <script src=\"pseudocode.js\" type=\"text/javascript\"></script>\n"
  },
  {
    "path": "static/mathjax-v2.html.part",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n    <meta charset=\"utf-8\">\n    <title>pseudocode.js Samples with MathJax</title>\n\n    <!-- Setup MathJax -->\n    <script src=\"https://cdn.jsdelivr.net/npm/mathjax@2.7.9/MathJax.js?config=TeX-AMS_CHTML-full\"\n            integrity=\"sha256-DViIOMYdwlM/axqoGDPeUyf0urLoHMN4QACBKyB58Uw=\"\n            crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\">\n    </script>\n    <script type=\"text/x-mathjax-config\">\n        MathJax.Hub.Config({\n            tex2jax: {\n                inlineMath: [['$','$'], ['\\\\(','\\\\)']],\n                displayMath: [['$$','$$'], ['\\\\[','\\\\]']],\n                processEscapes: true,\n                processEnvironments: true,\n                skipTags: ['code', 'script', 'noscript', 'style', 'textarea', 'pre'],\n            }\n        });\n    </script>\n\n    <!-- Pseudocode -->\n    <link rel=\"stylesheet\" href=\"pseudocode.css\" type=\"text/css\">\n    <script src=\"pseudocode.js\" type=\"text/javascript\"></script>\n"
  },
  {
    "path": "static/mathjax-v3.html.part",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n    <meta charset=\"utf-8\">\n    <title>pseudocode.js Samples with MathJax</title>\n\n    <!-- Setup MathJax -->\n    <script>\n        MathJax = {\n            tex: {\n                inlineMath: [['$','$'], ['\\\\(','\\\\)']],\n                displayMath: [['$$','$$'], ['\\\\[','\\\\]']],\n                processEscapes: true,\n                processEnvironments: true,\n            }\n        }\n    </script>\n    <script src=\"https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/tex-chtml-full.js\"\n            integrity=\"sha256-kbAFUDxdHwlYv01zraGjvjNZayxKtdoiJ38bDTFJtaQ=\"\n            crossorigin=\"anonymous\">\n    </script>\n\n    <!-- Pseudocode -->\n    <link rel=\"stylesheet\" href=\"pseudocode.css\" type=\"text/css\">\n    <script src=\"pseudocode.js\" type=\"text/javascript\"></script>\n"
  },
  {
    "path": "static/mathjax-v4.html.part",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n    <meta charset=\"utf-8\">\n    <title>pseudocode.js Samples with MathJax</title>\n\n    <!-- Setup MathJax -->\n    <script>\n        MathJax = {\n            tex: {\n                inlineMath: [['$','$'], ['\\\\(','\\\\)']],\n                displayMath: [['$$','$$'], ['\\\\[','\\\\]']],\n                processEscapes: true,\n                processEnvironments: true,\n            }\n        }\n    </script>\n    <script src=\"https://cdn.jsdelivr.net/npm/mathjax@4.0.0-beta.3/tex-chtml.js\"\n            integrity=\"sha256-ljPODBK7Jf/VfUrVqec63xzZbysEmwB9Ab20TWRMQRU=\"\n            crossorigin=\"anonymous\">\n    </script>\n\n    <!-- Pseudocode -->\n    <link rel=\"stylesheet\" href=\"pseudocode.css\" type=\"text/css\">\n    <script src=\"pseudocode.js\" type=\"text/javascript\"></script>\n"
  },
  {
    "path": "static/pseudocode.css",
    "content": "@import url('https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.css');\n\n.ps-root {\n    font-family: KaTeX_Main, 'Times New Roman', Times, serif;\n    font-size: 1em;\n    font-weight: 100;\n    -webkit-font-smoothing: antialiased !important;\n}\n.ps-root .ps-algorithm {\n    margin: 0.8em 0;\n    /* algorithm environment has borders; algorithmic has not */\n    border-top: 3px solid;\n    border-bottom: 2px solid;\n}\n.ps-root .ps-algorithm.with-caption > .ps-line:first-child {\n    border-bottom: 2px solid;\n}\n\n.ps-root .katex {\n    text-indent: 0;\n    font-size: 1em;\n}\n.ps-root .MathJax_CHTML, .ps-root .MathJax {\n    text-indent: 0;\n    font-size: 1em !important;\n}\n\n.ps-root .ps-line {\n    margin: 0; padding: 0;\n    line-height: 1.2;\n}\n.ps-root .ps-funcname {\n    font-family: KaTeX_Main, 'Times New Roman', Times, serif;\n    font-weight: normal;\n    font-variant: small-caps;\n    font-style: normal;\n    text-transform: none;\n}\n.ps-root .ps-keyword {\n    font-family: KaTeX_Main, 'Times New Roman', Times, serif;\n    font-weight: bold;\n    font-variant: normal;\n    font-style: normal;\n    text-transform: none;\n}\n.ps-root .ps-comment {\n    font-family: KaTeX_Main, 'Times New Roman', Times, serif;\n    font-weight: normal;\n    font-variant: normal;\n    font-style: normal;\n    text-transform: none;\n}\n\n/* line number support */\n.ps-root .ps-linenum {\n    font-size: 0.8em;\n    line-height: 1em;\n    width: 1.6em;\n    text-align: right;\n    display: inline-block;\n    position: relative;\n    padding-right: 0.3em;\n}\n.ps-root .ps-algorithmic.with-linenum .ps-line.ps-code {\n    text-indent: -1.6em;\n}\n.ps-root .ps-algorithmic.with-linenum .ps-line.ps-code > span {\n    text-indent: 0em;\n}\n\n/* scope lines support */\n.ps-root .ps-algorithmic.with-scopelines div.ps-block {\n    border-left-style: solid;\n    border-left-width: 0.1em;\n    padding-left: 0.6em;\n}\n\n.ps-root .ps-algorithmic.with-scopelines > div.ps-block {\n    border-left: none;\n}\n"
  }
]