[
  {
    "path": ".buildpacks",
    "content": "https://github.com/Scalingo/apt-buildpack\nhttps://github.com/Scalingo/nodejs-buildpack\n"
  },
  {
    "path": ".devcontainer/Dockerfile",
    "content": "# [Choice] Node.js version: 16, 14\nARG VARIANT=14-bullseye\nFROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT}\n\n# [Optional] Uncomment this section to install additional OS packages.\n# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \\\n#     && apt-get -y install --no-install-recommends <your-package-list-here>\n\n# [Optional] Uncomment if you want to install an additional version of node using nvm\n# ARG EXTRA_NODE_VERSION=10\n# RUN su node -c \"source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}\"\n\n# [Optional] Uncomment if you want to install more global node modules\nRUN su node -c \"npm install -g npm@6\"\n"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "content": "{\n\t\"name\": \"CodiMD\",\n\t\"dockerComposeFile\": \"docker-compose.yml\",\n\t\"service\": \"app\",\n\t\"workspaceFolder\": \"/workspace\",\n\n\t// Set *default* container specific settings.json values on container create.\n\t\"settings\": { \n\t\t\"terminal.integrated.shell.linux\": \"/bin/zsh\",\n\t\t\"sqltools.connections\": [{\n\t\t\t\"name\": \"Container Database\",\n\t\t\t\"driver\": \"PostgreSQL\",\n\t\t\t\"previewLimit\": 50,\n\t\t\t\"server\": \"localhost\",\n\t\t\t\"port\": 5432,\n\t\t\t\"database\": \"codimd\",\n\t\t\t\"username\": \"codimd\",\n\t\t\t\"password\": \"codimd\"\n\t\t}],\n\t},\n\n\t// Add the IDs of extensions you want installed when the container is created.\n\t\"extensions\": [\n\t\t\"dbaeumer.vscode-eslint\",\n\t\t\"visualstudioexptteam.vscodeintellicode\",\n\t\t\"christian-kohler.path-intellisense\",\n\t\t\"standard.vscode-standard\",\n\t\t\"mtxr.sqltools\",\n\t\t\"mtxr.sqltools-driver-pg\",\n\t\t\"eamodio.gitlens\",\n\t\t\"codestream.codestream\", \n\t\t\"github.vscode-pull-request-github\",\n\t\t\"cschleiden.vscode-github-actions\",\n\t\t\"hbenl.vscode-mocha-test-adapter\",\n\t\t\"hbenl.vscode-test-explorer\"\n\t],\n\n\t// Use 'forwardPorts' to make a list of ports inside the container available locally.\n\t// \"forwardPorts\": [],\n\n\t\"portsAttributes\": {\n\t\t\"3000\": {\n\t\t\t\"label\": \"CodiMD server\",\n\t\t\t\"onAutoForward\": \"notify\"\n\t\t},\n\t\t\"5432\": {\n\t\t\t\"label\": \"PostgreSQL\",\n\t\t\t\"onAutoForward\": \"notify\"\n\t\t}\n\t},\n\n\t// Use 'postCreateCommand' to run commands after the container is created.\n\t// \"postCreateCommand\": \"yarn install\",\n\t\"postCreateCommand\": \"sudo chown -R node:node node_modules && /workspace/bin/setup\",\n\n\t// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.\n\t\"remoteUser\": \"node\"\n}"
  },
  {
    "path": ".devcontainer/docker-compose.yml",
    "content": "version: '3'\n\nservices: \n  app:\n    build:\n      context: ..\n      dockerfile: .devcontainer/Dockerfile\n      args:\n        VARIANT: 14-bullseye\n    environment:\n      - CMD_DB_URL=postgres://codimd:codimd@localhost/codimd\n      - CMD_USECDN=false\n    volumes: \n      - ..:/workspace:cached\n      - node_modules:/workspace/node_modules:cached\n\n    # Overrides default command so things don't shut down after the process ends.\n    command: sleep infinity\n\n    # Runs app on the same network as the database container, allows \"forwardPorts\" in devcontainer.json function.\n    network_mode: service:db\n\n    # Runs app on the same network as the database container, allows \"forwardPorts\" in devcontainer.json function.\n\n    # Uncomment the next line to use a non-root user for all processes.\n    # user: vscode\n\n    # Use \"forwardPorts\" in **devcontainer.json** to forward an app port locally.\n    # (Adding the \"ports\" property to this file will not forward from a Codespace.)\n\n  db:\n    image: postgres:12.7-alpine\n    restart: unless-stopped\n    volumes:\n      - postgres-data:/var/lib/postgresql/data\n    environment:\n      - POSTGRES_USER=codimd\n      - POSTGRES_PASSWORD=codimd\n      - POSTGRES_DB=codimd\n\n    # Add \"forwardPorts\": [\"5432\"] to **devcontainer.json** to forward PostgreSQL locally.\n    # (Adding the \"ports\" property to this file will not forward from a Codespace.)\n\nvolumes:\n  node_modules:\n  postgres-data: "
  },
  {
    "path": ".dockerignore",
    "content": ".idea\ncoverage\nnode_modules/\n\n# ignore config files\nconfig.json\n.sequelizerc\n\n# ignore webpack build\npublic/build\npublic/views/build\n\n.nyc_output\ncoverage/\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = space\nindent_size = 2\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[{*.html,*.ejs}]\nindent_style = space\nindent_size = 4\ntrim_trailing_whitespace = true\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[{.travis.yml,npm-shrinkwrap.json,package.json}]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".github/tests/README.md",
    "content": "# Test github actions with act\n\n```bash\nact pull_request --container-architecture linux/arm64 -e .github/tests/pull-request.json -j ch\neck-release-pr -P ubuntu-latest=catthehacker/ubuntu:act-latest\n```\n"
  },
  {
    "path": ".github/tests/pull-request.json",
    "content": "{\n  \"pull_request\": {\n    \"head\": {\n      \"ref\": \"release/1.2.3\"\n    },\n    \"base\": {\n      \"ref\": \"master\"\n    }\n  }\n}\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: 'Test and Build'\n\non:\n  push:\n  pull_request:\n  workflow_dispatch:\n\njobs:\n  test-and-build:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        node-version: [16.x]\n\n    steps:\n    - uses: actions/checkout@v4\n\n    # from https://stackoverflow.com/a/69649733\n    - name: Reconfigure git to use HTTP authentication\n      run: >\n        git config --global url.\"https://github.com/\".insteadOf\n        ssh://git@github.com/\n\n    - uses: actions/cache@v4\n      with:\n        path: ~/.npm\n        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}\n        restore-keys: |\n          ${{ runner.os }}-node-\n\n    - uses: actions/setup-node@v4\n      name: Use Node.js ${{ matrix.node-version }}\n      with:\n        node-version: ${{ matrix.node-version }}\n        check-latest: true\n\n    - run: npm ci\n    - run: npm run test:ci\n    - run: npm run build\n\n  doctoc:\n    runs-on: ubuntu-latest\n    if: github.ref == 'refs/heads/master' || github.event.pull_request\n\n    steps:\n    - uses: actions/checkout@v4\n    - uses: actions/setup-node@v4\n      name: Use Node.js 14\n      with:\n        node-version: 14\n        check-latest: true\n    - name: Install doctoc-check\n      run: |\n        npm install -g doctoc\n        cp README.md README.md.orig\n        npm run doctoc\n        diff -q README.md README.md.orig\n"
  },
  {
    "path": ".github/workflows/check-release.yml",
    "content": "name: Release PR Checks\n\non:\n  workflow_dispatch:\n  pull_request:\n    branches:\n      - master\n\njobs:\n  check-release-pr:\n    if: startsWith(github.head_ref, 'release/')\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - name: Check for release-notes updates\n        run: |\n          if ! git diff --exit-code origin/develop -- public/docs/release-notes.md; then\n            echo \"Release notes updated.\"\n          else\n            echo \"Error: Release notes not updated in the PR.\"\n            exit 1\n          fi\n\n      - name: Compare package.json version with master\n        run: |\n          git fetch origin master\n          MASTER_PACKAGE_VERSION=$(git show origin/master:package.json | jq -r '.version')\n          BRANCH_PACKAGE_VERSION=$(jq -r '.version' package.json)\n\n          if [ \"$BRANCH_PACKAGE_VERSION\" != \"$MASTER_PACKAGE_VERSION\" ]; then\n            echo \"Version bumped in package.json.\"\n          else\n            echo \"Error: Version in package.json has not been bumped.\"\n            exit 1\n          fi\n\n"
  },
  {
    "path": ".github/workflows/push-image.yml",
    "content": "name: Build and push image\n\non:\n  release:\n    types: [published]\n  workflow_dispatch:\n    inputs:\n      runtime:\n        description: 'Runtime image'\n        required: true\n        default: 'hackmdio/runtime:16.20.2-35fe7e39'\n      buildpack:\n        description: 'Buildpack image'\n        required: true\n        default: 'hackmdio/buildpack:16.20.2-35fe7e39'\n\nenv:\n  REGISTRY_IMAGE: hackmdio/hackmd\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: false\n      matrix:\n        platform:\n          - linux/amd64\n          - linux/arm64\n    steps:\n      -\n        name: Prepare\n        run: |\n          platform=${{ matrix.platform }}\n          echo \"PLATFORM_PAIR=${platform//\\//-}\" >> $GITHUB_ENV\n      -\n        name: Checkout\n        uses: actions/checkout@v4\n      -\n        name: Docker meta\n        id: meta\n        uses: docker/metadata-action@v5\n        with:\n          images: ${{ env.REGISTRY_IMAGE }}\n      -\n        name: Set up QEMU\n        uses: docker/setup-qemu-action@v3\n      -\n        name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      -\n        name: Login to Docker Hub\n        uses: docker/login-action@v3\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n      -\n        name: Build and push by digest\n        id: build\n        uses: docker/build-push-action@v5\n        with:\n          context: .\n          file: ./deployments/Dockerfile\n          platforms: ${{ matrix.platform }}\n          labels: ${{ steps.meta.outputs.labels }}\n          outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true\n          build-args: |\n            RUNTIME=${{ github.event.inputs.runtime || 'hackmdio/runtime:16.20.2-35fe7e39' }}\n            BUILDPACK=${{ github.event.inputs.buildpack || 'hackmdio/buildpack:16.20.2-35fe7e39' }}\n      -\n        name: Export digest\n        run: |\n          mkdir -p /tmp/digests\n          digest=\"${{ steps.build.outputs.digest }}\"\n          touch \"/tmp/digests/${digest#sha256:}\"\n      -\n        name: Upload digest\n        uses: actions/upload-artifact@v4\n        with:\n          name: digests-${{ env.PLATFORM_PAIR }}\n          path: /tmp/digests/*\n          if-no-files-found: error\n          retention-days: 1\n\n  merge:\n    runs-on: ubuntu-latest\n    needs:\n      - build\n    steps:\n      -\n        name: Download digests\n        uses: actions/download-artifact@v4\n        with:\n          path: /tmp/digests\n          pattern: digests-*\n          merge-multiple: true\n      -\n        name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n      -\n        name: Docker meta\n        id: meta\n        uses: docker/metadata-action@v5\n        with:\n          images: ${{ env.REGISTRY_IMAGE }}\n          tags: |\n            type=match,pattern=\\d.\\d.\\d\n            type=sha,prefix=\n      -\n        name: Login to Docker Hub\n        uses: docker/login-action@v3\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n      -\n        name: Create manifest list and push\n        working-directory: /tmp/digests\n        run: |\n          docker buildx imagetools create $(jq -cr '.tags | map(\"-t \" + .) | join(\" \")' <<< \"$DOCKER_METADATA_OUTPUT_JSON\") \\\n            $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)\n      -\n        name: Inspect image\n        run: |\n          docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\ncomposer.phar\ncomposer.lock\n.env.*.php\n.env.php\n.DS_Store\n.idea/\nThumbs.db\nnpm-debug.log\nhackmd_io\nnewrelic_agent.log\nlogs/\ntmp/\nbackups/\n*.pid\n*.log\n*.sqlite\n\n# ignore config files\nconfig.json\n.sequelizerc\n\n# ignore webpack build\npublic/build\npublic/views/build\n\npublic/uploads/*\n!public/uploads/.gitkeep\n/.nyc_output\n/coverage/\n\n.vscode/settings.json"
  },
  {
    "path": ".mailmap",
    "content": "Max Wu <jackymaxj@gmail.com>                 Wu Cheng-Han <jacky_cute0808@hotmail.com>\nMax Wu <jackymaxj@gmail.com>                 Cheng-Han, Wu <jackymaxj@gmail.com>\nMax Wu <jackymaxj@gmail.com>                 jackycute <jackymaxj@gmail.com>\nMax Wu <jackymaxj@gmail.com>                 Wu, Cheng-Han <jackymaxj@gmail.com>\nMax Wu <jackymaxj@gmail.com>                 jackycute <jacky_cute0808@hotmail.com>\n\nSheogorath <sheogorath@shivering-isles.com>  Christoph (Sheogorath) Kern <sheogorath@shivering-isles.com>\n\nRaccoon <raccoon@hackmd.io>                  Raccoon Li <a60814billy@gmail.com>\nRaccoon <raccoon@hackmd.io>                  Raccoon <a60814billy@gmail.com>\n\nPeter Dave Hello <hsu@peterdavehello.org>    Peter Dave Hello <PeterDaveHello@users.noreply.github.com>\n\nClaudius Coenen <github@amenthes.de>         Claudius Coenen <opensource@amenthes.de>\n"
  },
  {
    "path": ".nvmrc",
    "content": "v16.20.2\n"
  },
  {
    "path": ".sequelizerc.example",
    "content": "const path = require('path')\nconst config = require('./lib/config')\n\nmodule.exports = {\n  config: path.resolve('config.js'),\n  'migrations-path': path.resolve('lib', 'migrations'),\n  'models-path': path.resolve('lib', 'models'),\n  url: config.dbURL\n}\n"
  },
  {
    "path": "AUTHORS",
    "content": "alecdwm <alec@owls.io>\nbananaappletw <bananaappletw@gmail.com>\nBartlomiej Szala <fenix440@gmail.com>\nBoHong Li <a60814billy@gmail.com>\nBryan Davis <bd808@wikimedia.org>\nbutlerx <butlerx@notthe.cloud>\nCheng-Han, Wu <jackymaxj@gmail.com>\nChristian Schuhmann <madebyherzblut@users.noreply.github.com>\nColin Maudry <colin@maudry.com>\nDmytro Kytsmen <dmitrokytsmen@gmail.com>\nFabien Meghazi <agr@amigrave.com>\nFlorian Rhiem <florian.rhiem@gmail.com>\ngeekyd <singhsince94@gmail.com>\nGhiMax <ghina8@gmail.com>\ngreenkeeperio-bot <support@greenkeeper.io>\nHimura Kazuto <Himura2la@users.noreply.github.com>\nHo33e5 <ho33e5@gmail.com>\nIan Dees <ian.dees@gmail.com>\nIkumi Shimizu <193s@users.noreply.github.com>\nivanorsolic <ivanorsolic@users.noreply.github.com>\njackycute <jacky_cute0808@hotmail.com>\njackycute <jackymaxj@gmail.com>\nJakub Sygnowski <sygnowski@gmail.com>\nJames Stephenson <c4p7.fl1n7@gmail.com>\nJan Kunzmann <jan-github@phobia.de>\nJannik Lorenz <dev@janniklorenz.de>\nJason Croft <jcroft@velocity.org>\nJohannes Weißl <jargon@molb.org>\nJordan Matelsky <j6k4m8@gmail.com>\nJun SAKATA <jun.bj141400@gmail.com>\nKaiyu Shi <skyisno.1@gmail.com>\nknjcode <knjcode@gmail.com>\nKotaro Yamamoto <kota.crk@gmail.com>\nLars Karlsson <lars@kajes.se>\nLaura Kyle <laura.kyle91@gmail.com>\nLluisArevalo <thorin119@gmail.com>\nMarcelo Alencar <marceloalves@ufpa.br>\nMartijnpold <martijntje7@gmail.com>\nMax Wu <jackymaxj@gmail.com>\nneopostmodern <clemens@neopostmodern.com>\nNV <nvsofts@gmail.com>\nÖmer Erdinç Yağmurlu <omeryagmurlu@gmail.com>\np0v1n0m <p0v1n0m@gmail.com>\nPablo Guerrero <pablo.guerrero@gmail.com>\nPablo Guerrero <pablo.guerrero@sap.com>\nParas <paraschadha2052@gmail.com>\nPatrick Andersen <patrick@bacha.dk>\nPeter Dave Hello <hsu@peterdavehello.org>\nPeter Dave Hello <PeterDaveHello@users.noreply.github.com>\nPhilipp Zumstein <zuphilip@users.noreply.github.com>\nRaccoon Li <a60814billy@gmail.com>\nrobert <ahmerov.rt@molodost.bz>\nSergio Valverde <svg153@users.noreply.github.com>\nSheogorath <sheogorath@shivering-isles.com>\nSimon Joda Stößer <SimJoSt@users.noreply.github.com>\nS.Noda <noda@fenrir.co.jp>\nStratos Gerakakis <stratosgear@gmail.com>\nThe Gitter Badger <badger@gitter.im>\ntkqubo <tk.qubo@gmail.com>\ntkykm <tkykm@users.noreply.github.com>\nTom Wyckhuys <tomwyckhuys@gmail.com>\nWonder Chang <iwonder.tw@gmail.com>\nWu Cheng-Han <jacky_cute0808@hotmail.com>\nXavier Marques <xaviermarques4f@gmail.com>\nxnum <s000032001@gmail.com>\nYukai Huang <yukaihuangtw@gmail.com>\nzachariast <zachariastraianos@gmail.com>\nZankio <xxoojoeooxx1@gmail.com>\n蒼時弦也 <elct9620@frost.tw>\n"
  },
  {
    "path": "Aptfile",
    "content": "libvips-dev\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nWhen contributing to this repository, please first discuss the change you wish to make via issue,\nemail, or any other method with the owners of this repository before making a change.\n\nPlease note we have a code of conduct, please follow it in all your interactions with the project.\n\n## Pull Request Process\n1. Ensure you signed all your commits with Developer Certificate of Origin (DCO).\n2. Ensure any install or build dependencies are removed before the end of the layer when doing a\n   build.\n3. Update the README.md with details of changes to the interface, this includes new environment\n   variables, exposed ports, useful file locations and container parameters.\n4. Increase the version numbers in any examples files and the README.md to the new version that this\n   Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).\n5. You may merge the Pull Request in once you have the sign-off of two other developers, or if you\n   do not have permission to do that, you may request the second reviewer to merge it for you.\n\n## Contributor Code of Conduct\n\nAs contributors and maintainers of this project, and in the interest of fostering an open and\nwelcoming community, we pledge to respect all people who contribute through reporting issues,\nposting feature requests, updating documentation, submitting pull requests or patches, and other\nactivities.\n\nWe are committed to making participation in this project a harassment-free experience for everyone,\nregardless of level of experience, gender, gender identity and expression, sexual orientation,\ndisability, personal appearance, body size, race, ethnicity, age, religion, or nationality.\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery\n* Personal attacks\n* Trolling or insulting/derogatory comments\n* Public or private harassment\n* Publishing other's private information, such as physical or electronic addresses, without explicit\n  permission\n* Other unethical or unprofessional conduct.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits,\ncode, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By\nadopting this Code of Conduct, project maintainers commit themselves to fairly and consistently\napplying these principles to every aspect of managing this project. Project maintainers who do not\nfollow or enforce the Code of Conduct may be permanently removed from the project team.\n\nThis code of conduct applies both within project spaces and in public spaces when an individual is\nrepresenting the project or its community.\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an\nissue or contacting one or more of the project maintainers.\n\nThis Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org),\nversion 1.2.0, available at\n[http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)\n\n### Sign your work\n\nWe use the Developer Certificate of Origin (DCO) as a additional safeguard\nfor the CodiMD project. This is a well established and widely used\nmechanism to assure contributors have confirmed their right to license\ntheir contribution under the project's license.\nPlease read [contribute/developer-certificate-of-origin][dcofile].\nIf you can certify it, then just add a line to every git commit message:\n\n````\n  Signed-off-by: Random J Developer <random@developer.example.org>\n````\n\nUse your real name (sorry, no pseudonyms or anonymous contributions).\nIf you set your `user.name` and `user.email` git configs, you can sign your\ncommit automatically with `git commit -s`. You can also use git [aliases](https://git-scm.com/book/tr/v2/Git-Basics-Git-Aliases)\nlike `git config --global alias.ci 'commit -s'`. Now you can commit with\n`git ci` and the commit will be signed.\n\n[dcofile]: https://github.com/hackmdio/codimd/blob/develop/contribute/developer-certificate-of-origin\n"
  },
  {
    "path": "FUNDING.json",
    "content": "{\n  \"drips\": {\n    \"ethereum\": {\n      \"ownedBy\": \"0xEd37B84FD84A834886aC07693aF6A9cd35040002\"\n    }\n  }\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nour General Public Licenses are intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  Developers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.\n\n  A secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate.  Many developers of free software are heartened and\nencouraged by the resulting cooperation.  However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.\n\n  The GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community.  It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server.  Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.\n\n  An older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals.  This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing under\nthis license.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU Affero General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Remote Network Interaction; Use with the GNU General Public License.\n\n  Notwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your version\nsupports such interaction) an opportunity to receive the Corresponding\nSource of your version by providing access to the Corresponding Source\nfrom a network server at no charge, through some standard or customary\nmeans of facilitating copying of software.  This Corresponding Source\nshall include the Corresponding Source for any work covered by version 3\nof the GNU General Public License that is incorporated pursuant to the\nfollowing paragraph.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the work with which it is combined will remain governed by version\n3 of the GNU General Public License.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time.  Such new versions\nwill be similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU Affero General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If your software can interact with users remotely through a computer\nnetwork, you should also make sure that it provides a way for users to\nget its source.  For example, if your program is a web application, its\ninterface could display a \"Source\" link that leads users to an archive\nof the code.  There are many ways you could offer source, and different\nsolutions will be better for different programs; see section 13 for the\nspecific requirements.\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU AGPL, see\n<http://www.gnu.org/licenses/>."
  },
  {
    "path": "Procfile",
    "content": "web: ./bin/heroku_start.sh\n"
  },
  {
    "path": "README.md",
    "content": "CodiMD\n===\n\n[![build status][build-image]][build-url]\n[![version][github-version-badge]][github-release-page]\n[![Gitter][gitter-image]][gitter-url]\n[![Matrix][matrix-image]][matrix-url]\n[![POEditor][poeditor-image]][poeditor-url]\n\nCodiMD lets you collaborate in real-time with markdown.\nBuilt on [HackMD](https://hackmd.io) source code, CodiMD lets you host and control your team's content with speed and ease.\n\n![screenshot](https://raw.githubusercontent.com/hackmdio/codimd/develop/public/screenshot.png)\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n# Table of Contents\n\n- [HackMD](#hackmd)\n- [CodiMD - The Open Source HackMD](#codimd---the-open-source-hackmd)\n- [Documentation](#documentation)\n  - [Deployment](#deployment)\n  - [Configuration](#configuration)\n  - [Upgrading and Migration](#upgrading-and-migration)\n  - [Developer](#developer)\n- [Contribution and Discussion](#contribution-and-discussion)\n- [Browser Support](#browser-support)\n- [License](#license)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## HackMD\n\n[HackMD](https://hackmd.io) helps developers write better documents and build active communities with open collaboration.\nHackMD is built with one promise - **You own and control all your content**:\n- You should be able to easily [download all your online content at once](https://hackmd.io/c/news/%2Fs%2Fr1cx3a3SE).\n- Your content formatting should be portable as well. (That's why we choose [markdown](https://hackmd.io/features#Typography).)\n- You should be able to control your content's presentation with HTML, [slide mode](https://hackmd.io/p/slide-example), or [book mode](https://hackmd.io/c/book-example/).\n\n## CodiMD - The Open Source HackMD\n\nCodiMD is the free software version of [HackMD](https://hackmd.io), developed and open sourced by the HackMD team with reduced features (without book mode), you can use CodiMD for your community and own all your data. *(See the [origin of the name CodiMD](https://github.com/hackmdio/hackmd/issues/720).)* \n\nCodiMD is perfect for open communities, while HackMD emphasizes on permission and access controls for commercial use cases. \n\nHackMD team is committed to keep CodiMD open source. All contributions are welcome!\n\n## Documentation\nYou would find all documentation here: [CodiMD Documentation](https://hackmd.io/c/codimd-documentation)\n\n### Deployment\nIf you want to spin up an instance and start using immediately, see [Docker deployment](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-docker-deployment).\nIf you want to contribute to the project, start with [manual deployment](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-manual-deployment).\n\n### Configuration\nCodiMD is highly customizable, learn about all configuration options of networking, security, performance, resources, privilege, privacy, image storage, and authentication in [CodiMD Configuration](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-configuration).\n\n### Upgrading and Migration\nUpgrade CodiMD from previous version? See [this guide](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-upgrade)<br>\nMigrating from Etherpad? Follow [this guide](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-migration-etherpad)\n\n### Developer\nJoin our contributor community! Start from deploying [CodiMD manually](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-manual-deployment), [connecting to your own database](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-db-connection), [learn about the project structure](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-project-structure), to [build your changes](https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-webpack) with the help of webpack.\n\n## Contribution and Discussion\nAll contributions are welcome! Even asking a question helps.\n\n| Project | Contribution Types | Contribution Venue |\n| ------- | ------------------ | ------------------ |\n|**CodiMD**|:couple: Community chat|[Gitter][gitter-url]|\n||:bug: Issues, bugs, and feature requests|[Issue tracker](https://github.com/hackmdio/codimd/issues)|\n||:books: Improve documentation|[Documentations](https://hackmd.io/c/codimd-documentation)|\n||:pencil: Translation|[POEditor][poeditor-url]|\n||:coffee: Donation|[Buy us coffee](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=KDGS4PREHX6QQ&lc=US&item_name=HackMD&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted)|\n|**HackMD**|:question: Issues related to [HackMD](https://hackmd.io/)|[Issue tracker](https://github.com/hackmdio/hackmd-io-issues/issues)|\n||:pencil2: Translation|[hackmd-locales](https://github.com/hackmdio/hackmd-locales/tree/master/locales)|\n\n## Browser Support\n\nCodiMD is a service that runs on Node.js, while users use the service through browsers. We support your users using the following browsers: \n- <img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png\" alt=\"Chrome\" width=\"24px\" height=\"24px\" /> Chrome >= 47, Chrome for Android >= 47\n- <img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png\" alt=\"Safari\" width=\"24px\" height=\"24px\" /> Safari >= 9, iOS Safari >= 8.4\n- <img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png\" alt=\"Firefox\" width=\"24px\" height=\"24px\" /> Firefox >= 44\n- <img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png\" alt=\"Edge\" width=\"24px\" height=\"24px\" /> Edge >= 12\n- <img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png\" alt=\"Opera\" width=\"24px\" height=\"24px\" /> Opera >= 34, Opera Mini not supported\n- Android Browser >= 4.4\n\nTo stay up to date with your installation it's recommended to subscribe the [release feed][github-release-feed].\n\n## License\n\n**License under AGPL.**\n\n[gitter-image]: https://img.shields.io/badge/gitter-hackmdio/codimd-blue.svg\n[gitter-url]: https://gitter.im/hackmdio/hackmd\n[build-image]: https://github.com/hackmdio/codimd/actions/workflows/build.yml/badge.svg\n[build-url]: https://github.com/hackmdio/codimd/actions/workflows/build.yml\n[github-version-badge]: https://img.shields.io/github/release/hackmdio/codimd.svg\n[github-release-page]: https://github.com/hackmdio/codimd/releases\n[github-release-feed]: https://github.com/hackmdio/codimd/releases.atom\n[poeditor-image]: https://img.shields.io/badge/POEditor-translate-blue.svg\n[poeditor-url]: https://poeditor.com/join/project/q0nuPWyztp\n[matrix-image]: https://img.shields.io/matrix/hackmdio_hackmd:gitter.im?color=blue&logo=matrix\n[matrix-url]: https://matrix.to/#/#hackmdio_hackmd:gitter.im\n"
  },
  {
    "path": "app.js",
    "content": "'use strict'\n// app\n// external modules\nvar express = require('express')\n\nvar ejs = require('ejs')\nvar passport = require('passport')\nvar methodOverride = require('method-override')\nvar cookieParser = require('cookie-parser')\nvar session = require('express-session')\nvar SequelizeStore = require('connect-session-sequelize')(session.Store)\nvar fs = require('fs')\nvar path = require('path')\n\nvar morgan = require('morgan')\nvar passportSocketIo = require('passport.socketio')\nvar helmet = require('helmet')\nvar i18n = require('i18n')\nvar flash = require('connect-flash')\nvar apiMetrics = require('prometheus-api-metrics')\n\n// core\nvar config = require('./lib/config')\nvar logger = require('./lib/logger')\nvar response = require('./lib/response')\nvar models = require('./lib/models')\nvar csp = require('./lib/csp')\nconst { Environment } = require('./lib/config/enum')\n\nconst { versionCheckMiddleware, checkVersion } = require('./lib/web/middleware/checkVersion')\n\nfunction createHttpServer () {\n  if (config.useSSL) {\n    const ca = (function () {\n      let i, len\n      const results = []\n      for (i = 0, len = config.sslCAPath.length; i < len; i++) {\n        results.push(fs.readFileSync(config.sslCAPath[i], 'utf8'))\n      }\n      return results\n    })()\n    const options = {\n      key: fs.readFileSync(config.sslKeyPath, 'utf8'),\n      cert: fs.readFileSync(config.sslCertPath, 'utf8'),\n      ca: ca,\n      dhparam: fs.readFileSync(config.dhParamPath, 'utf8'),\n      requestCert: false,\n      rejectUnauthorized: false\n    }\n    return require('https').createServer(options, app)\n  } else {\n    return require('http').createServer(app)\n  }\n}\n\n// server setup\nvar app = express()\nvar server = createHttpServer()\n\n// API and process monitoring with Prometheus for Node.js micro-service\napp.use(apiMetrics({\n  metricsPath: '/metrics/router',\n  excludeRoutes: ['/metrics/codimd']\n}))\n\n// logger\napp.use(morgan('combined', {\n  stream: logger.stream\n}))\n\n// socket io\nvar io = require('socket.io')(server)\nio.engine.ws = new (require('ws').Server)({\n  noServer: true,\n  perMessageDeflate: false\n})\n\n// others\nvar realtime = require('./lib/realtime/realtime.js')\n\n// assign socket io to realtime\nrealtime.io = io\n\n// methodOverride\napp.use(methodOverride('_method'))\n\n// session store\nvar sessionStore = new SequelizeStore({\n  db: models.sequelize\n})\n\n// use hsts to tell https users stick to this\nif (config.hsts.enable) {\n  app.use(helmet.hsts({\n    maxAge: config.hsts.maxAgeSeconds,\n    includeSubdomains: config.hsts.includeSubdomains,\n    preload: config.hsts.preload\n  }))\n} else if (config.useSSL) {\n  logger.info('Consider enabling HSTS for extra security:')\n  logger.info('https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security')\n}\n\n// Add referrer policy to improve privacy\napp.use(\n  helmet.referrerPolicy({\n    policy: 'same-origin'\n  })\n)\n\n// Generate a random nonce per request, for CSP with inline scripts\napp.use(csp.addNonceToLocals)\n\n// use Content-Security-Policy to limit XSS, dangerous plugins, etc.\n// https://helmetjs.github.io/docs/csp/\nif (config.csp.enable) {\n  app.use(helmet.contentSecurityPolicy({\n    directives: csp.computeDirectives()\n  }))\n} else {\n  logger.info('Content-Security-Policy is disabled. This may be a security risk.')\n}\n\ni18n.configure({\n  locales: ['en', 'zh-CN', 'zh-TW', 'fr', 'de', 'ja', 'es', 'ca', 'el', 'pt', 'it', 'tr', 'ru', 'nl', 'hr', 'pl', 'uk', 'hi', 'sv', 'eo', 'da', 'ko', 'id', 'sr'],\n  cookie: 'locale',\n  directory: path.join(__dirname, '/locales'),\n  updateFiles: config.updateI18nFiles\n})\n\napp.use(cookieParser())\n\napp.use(i18n.init)\n\n// routes without sessions\n// static files\napp.use('/', express.static(path.join(__dirname, '/public'), { maxAge: config.staticCacheTime, index: false }))\napp.use('/docs', express.static(path.resolve(__dirname, config.docsPath), { maxAge: config.staticCacheTime }))\napp.use('/uploads', express.static(path.resolve(__dirname, config.uploadsPath), { maxAge: config.staticCacheTime }))\napp.use('/default.md', express.static(path.resolve(__dirname, config.defaultNotePath), { maxAge: config.staticCacheTime }))\napp.use(require('./lib/metrics').router)\n\n// session\napp.use(session({\n  name: config.sessionName,\n  secret: config.sessionSecret,\n  resave: false, // don't save session if unmodified\n  saveUninitialized: true, // always create session to ensure the origin\n  rolling: true, // reset maxAge on every response\n  cookie: {\n    maxAge: config.sessionLife\n  },\n  store: sessionStore\n}))\n\n// session resumption\nvar tlsSessionStore = {}\nserver.on('newSession', function (id, data, cb) {\n  tlsSessionStore[id.toString('hex')] = data\n  cb()\n})\nserver.on('resumeSession', function (id, cb) {\n  cb(null, tlsSessionStore[id.toString('hex')] || null)\n})\n\n// middleware which blocks requests when we're too busy\napp.use(require('./lib/middleware/tooBusy'))\n\napp.use(flash())\n\n// passport\napp.use(passport.initialize())\napp.use(passport.session())\n\n// check uri is valid before going further\napp.use(require('./lib/middleware/checkURIValid'))\n// redirect url without trailing slashes\napp.use(require('./lib/middleware/redirectWithoutTrailingSlashes'))\napp.use(require('./lib/middleware/codiMDVersion'))\n\nif (config.autoVersionCheck && process.env.NODE_ENV === Environment.production) {\n  checkVersion(app)\n  app.use(versionCheckMiddleware)\n}\n\n// routes need sessions\n// template files\napp.set('views', config.viewPath)\n// set render engine\napp.engine('ejs', ejs.renderFile)\n// set view engine\napp.set('view engine', 'ejs')\n// set generally available variables for all views\napp.locals.useCDN = config.useCDN\napp.locals.serverURL = config.serverURL\napp.locals.sourceURL = config.sourceURL\napp.locals.privacyPolicyURL = config.privacyPolicyURL\napp.locals.allowAnonymous = config.allowAnonymous\napp.locals.allowAnonymousEdits = config.allowAnonymousEdits\napp.locals.permission = config.permission\napp.locals.allowPDFExport = config.allowPDFExport\napp.locals.authProviders = {\n  facebook: config.isFacebookEnable,\n  twitter: config.isTwitterEnable,\n  github: config.isGitHubEnable,\n  bitbucket: config.isBitbucketEnable,\n  gitlab: config.isGitLabEnable,\n  mattermost: config.isMattermostEnable,\n  dropbox: config.isDropboxEnable,\n  google: config.isGoogleEnable,\n  ldap: config.isLDAPEnable,\n  ldapProviderName: config.ldap.providerName,\n  saml: config.isSAMLEnable,\n  oauth2: config.isOAuth2Enable,\n  oauth2ProviderName: config.oauth2.providerName,\n  openID: config.isOpenIDEnable,\n  email: config.isEmailEnable,\n  allowEmailRegister: config.allowEmailRegister\n}\napp.locals.versionInfo = {\n  latest: true,\n  versionItem: null\n}\n\n// Export/Import menu items\napp.locals.enableDropBoxSave = config.isDropboxEnable\napp.locals.enableGitHubGist = config.isGitHubEnable\napp.locals.enableGitlabSnippets = config.isGitlabSnippetsEnable\n\napp.use(require('./lib/routes').router)\n\n// response not found if no any route matxches\napp.get('*', function (req, res) {\n  response.errorNotFound(req, res)\n})\n\n// socket.io secure\nio.use(realtime.secure)\n// socket.io auth\nio.use(passportSocketIo.authorize({\n  cookieParser: cookieParser,\n  key: config.sessionName,\n  secret: config.sessionSecret,\n  store: sessionStore,\n  success: realtime.onAuthorizeSuccess,\n  fail: realtime.onAuthorizeFail\n}))\n// socket.io heartbeat\nio.set('heartbeat interval', config.heartbeatInterval)\nio.set('heartbeat timeout', config.heartbeatTimeout)\n// socket.io connection\nio.sockets.on('connection', realtime.connection)\n\n// listen\nfunction startListen () {\n  var address\n  var listenCallback = function () {\n    var schema = config.useSSL ? 'HTTPS' : 'HTTP'\n    logger.info('%s Server listening at %s', schema, address)\n    realtime.maintenance = false\n  }\n\n  // use unix domain socket if 'path' is specified\n  if (config.path) {\n    address = config.path\n    server.listen(config.path, listenCallback)\n  } else {\n    address = config.host + ':' + config.port\n    server.listen(config.port, config.host, listenCallback)\n  }\n}\n\n// sync db then start listen\nmodels.sequelize.sync().then(function () {\n  // check if realtime is ready\n  if (realtime.isReady()) {\n    models.Revision.checkAllNotesRevision(function (err, notes) {\n      if (err) throw new Error(err)\n      if (!notes || notes.length <= 0) return startListen()\n    })\n  } else {\n    throw new Error('server still not ready after db synced')\n  }\n}).catch(err => {\n  logger.error('Can\\'t sync database')\n  logger.error(err.stack)\n  logger.error('Process will exit now.')\n  process.exit(1)\n})\n\n// log uncaught exception\nprocess.on('uncaughtException', function (err) {\n  logger.error('An uncaught exception has occured.')\n  logger.error(err)\n  console.error(err)\n  logger.error('Process will exit now.')\n  process.exit(1)\n})\n\n// install exit handler\nfunction handleTermSignals () {\n  logger.info('CodiMD has been killed by signal, try to exit gracefully...')\n  realtime.maintenance = true\n  realtime.terminate()\n  // disconnect all socket.io clients\n  Object.keys(io.sockets.sockets).forEach(function (key) {\n    var socket = io.sockets.sockets[key]\n    // notify client server going into maintenance status\n    socket.emit('maintenance')\n    setTimeout(function () {\n      socket.disconnect(true)\n    }, 0)\n  })\n  var checkCleanTimer = setInterval(function () {\n    if (realtime.isReady()) {\n      models.Revision.checkAllNotesRevision(function (err, notes) {\n        if (err) return logger.error(err)\n        if (!notes || notes.length <= 0) {\n          clearInterval(checkCleanTimer)\n          return process.exit(0)\n        }\n      })\n    }\n  }, 100)\n  setTimeout(() => {\n    process.exit(1)\n  }, 5000)\n}\nprocess.on('SIGINT', handleTermSignals)\nprocess.on('SIGTERM', handleTermSignals)\nprocess.on('SIGQUIT', handleTermSignals)\n"
  },
  {
    "path": "app.json",
    "content": "{\n    \"name\": \"CodiMD\",\n    \"description\": \"Realtime collaborative markdown notes on all platforms\",\n    \"keywords\": [\n        \"Collaborative\",\n        \"Markdown\",\n        \"Notes\"\n    ],\n    \"website\": \"https://github.com/hackmdio/codimd\",\n    \"repository\": \"https://github.com/hackmdio/codimd\",\n    \"logo\": \"https://github.com/hackmdio/codimd/raw/master/public/codimd-icon-1024.png\",\n    \"success_url\": \"/\",\n    \"env\": {\n        \"NPM_CONFIG_PRODUCTION\": {\n            \"description\": \"Let npm also install development build tool\",\n            \"value\": \"false\"\n        },\n        \"CMD_SESSION_SECRET\": {\n            \"description\": \"Secret used to secure session cookies.\",\n            \"required\": false\n        },\n        \"CMD_HSTS_ENABLE\": {\n            \"description\": \"whether to also use HSTS if HTTPS is enabled\",\n            \"required\": false\n        },\n        \"CMD_HSTS_MAX_AGE\": {\n            \"description\": \"max duration, in seconds, to tell clients to keep HSTS status\",\n            \"required\": false\n        },\n        \"CMD_HSTS_INCLUDE_SUBDOMAINS\": {\n            \"description\": \"whether to tell clients to also regard subdomains as HSTS hosts\",\n            \"required\": false\n        },\n        \"CMD_HSTS_PRELOAD\": {\n            \"description\": \"whether to allow at all adding of the site to HSTS preloads (e.g. in browsers)\",\n            \"required\": false\n        },\n        \"CMD_DOMAIN\": {\n            \"description\": \"domain name\",\n            \"required\": false\n        },\n        \"CMD_URL_PATH\": {\n            \"description\": \"sub url path, like `www.example.com/<URL_PATH>`\",\n            \"required\": false\n        },\n        \"CMD_ALLOW_ORIGIN\": {\n            \"description\": \"domain name whitelist (use comma to separate)\",\n            \"required\": false,\n            \"value\": \"localhost\"\n        },\n        \"CMD_PROTOCOL_USESSL\": {\n            \"description\": \"set to use ssl protocol for resources path (only applied when domain is set)\",\n            \"required\": false\n        },\n        \"CMD_URL_ADDPORT\": {\n            \"description\": \"set to add port on callback url (port 80 or 443 won't applied) (only applied when domain is set)\",\n            \"required\": false\n        },\n        \"CMD_FACEBOOK_CLIENTID\": {\n            \"description\": \"Facebook API client id\",\n            \"required\": false\n        },\n        \"CMD_FACEBOOK_CLIENTSECRET\": {\n            \"description\": \"Facebook API client secret\",\n            \"required\": false\n        },\n        \"CMD_TWITTER_CONSUMERKEY\": {\n            \"description\": \"Twitter API consumer key\",\n            \"required\": false\n        },\n        \"CMD_TWITTER_CONSUMERSECRET\": {\n            \"description\": \"Twitter API consumer secret\",\n            \"required\": false\n        },\n        \"CMD_GITHUB_CLIENTID\": {\n            \"description\": \"GitHub API client id\",\n            \"required\": false\n        },\n        \"CMD_GITHUB_CLIENTSECRET\": {\n            \"description\": \"GitHub API client secret\",\n            \"required\": false\n        },\n        \"CMD_GITHUB_ORGANIZATIONS\": {\n            \"description\": \"GitHub whitelist of orgs\",\n            \"required\": false\n        },\n        \"CMD_GITHUB_SCOPES\": {\n            \"description\": \"GitHub OAuth API scopes\",\n            \"required\": false\n        },\n        \"CMD_BITBUCKET_CLIENTID\": {\n            \"description\": \"Bitbucket API client id\",\n            \"required\": false\n        },\n        \"CMD_BITBUCKET_CLIENTSECRET\": {\n            \"description\": \"Bitbucket API client secret\",\n            \"required\": false\n        },\n        \"CMD_GITLAB_BASEURL\": {\n            \"description\": \"GitLab authentication endpoint, set to use other endpoint than GitLab.com (optional)\",\n            \"required\": false\n        },\n        \"CMD_GITLAB_CLIENTID\": {\n            \"description\": \"GitLab API client id\",\n            \"required\": false\n        },\n        \"CMD_GITLAB_CLIENTSECRET\": {\n            \"description\": \"GitLab API client secret\",\n            \"required\": false\n        },\n        \"CMD_GITLAB_SCOPE\": {\n            \"description\": \"GitLab API client scope (optional)\",\n            \"required\": false\n        },\n        \"CMD_MATTERMOST_BASEURL\": {\n            \"description\": \"Mattermost authentication endpoint\",\n            \"required\": false\n        },\n        \"CMD_MATTERMOST_CLIENTID\": {\n            \"description\": \"Mattermost API client id\",\n            \"required\": false\n        },\n        \"CMD_MATTERMOST_CLIENTSECRET\": {\n            \"description\": \"Mattermost API client secret\",\n            \"required\": false\n        },\n        \"CMD_DROPBOX_CLIENTID\": {\n            \"description\": \"Dropbox API client id\",\n            \"required\": false\n        },\n        \"CMD_DROPBOX_CLIENTSECRET\": {\n            \"description\": \"Dropbox API client secret\",\n            \"required\": false\n        },\n        \"CMD_DROPBOX_APP_KEY\": {\n            \"description\": \"Dropbox app key (for import/export)\",\n            \"required\": false\n        },\n        \"CMD_GOOGLE_CLIENTID\": {\n            \"description\": \"Google API client id\",\n            \"required\": false\n        },\n        \"CMD_GOOGLE_CLIENTSECRET\": {\n            \"description\": \"Google API client secret\",\n            \"required\": false\n        },\n        \"CMD_IMGUR_CLIENTID\": {\n            \"description\": \"Imgur API client id\",\n            \"required\": false\n        },\n        \"CMD_ALLOW_PDF_EXPORT\": {\n            \"description\": \"Enable or disable PDF exports\",\n            \"required\": false\n        },\n        \"PGSSLMODE\": {\n          \"description\": \"Enforce PG SSL mode\",\n          \"value\": \"require\"\n        }\n    },\n    \"addons\": [\n        \"heroku-postgresql\"\n    ],\n    \"buildpacks\": [\n        {\n            \"url\": \"https://github.com/alex88/heroku-buildpack-vips\"\n        },\n        {\n            \"url\": \"https://github.com/heroku/heroku-buildpack-nodejs\"\n        }\n    ]\n}\n"
  },
  {
    "path": "babel.config.js",
    "content": "module.exports = {\n  presets: [\n    ['@babel/preset-env', {\n      targets: {\n        node: '14'\n      },\n      useBuiltIns: 'usage',\n      corejs: 3,\n      modules: 'auto'\n    }]\n  ],\n  plugins: [\n    ['@babel/plugin-transform-runtime', {\n      corejs: 3\n    }],\n    '@babel/plugin-transform-nullish-coalescing-operator',\n    '@babel/plugin-transform-optional-chaining'\n  ]\n}\n"
  },
  {
    "path": "bin/heroku",
    "content": "#!/bin/bash\n\nset -e\n\nif [ ! -z \"$DYNO\" ]; then\n  # setup config files\n  cp .sequelizerc.example .sequelizerc\n\n    cat << EOF > config.json\n\n{\n  \"production\": {\n  }\n}\n\nEOF\n\nfi\n"
  },
  {
    "path": "bin/heroku_start.sh",
    "content": "#!/bin/bash\n\nset -euo pipefail\n\nCMD_DB_URL=\"$DATABASE_URL\" CMD_PORT=\"$PORT\" npm run start\n"
  },
  {
    "path": "bin/manage_users",
    "content": "#!/usr/bin/env node\n\n// First configure the logger so it does not spam the console\nconst logger = require('../lib/logger')\nlogger.transports.forEach((transport) => {\n  transport.level = 'warning'\n})\n\nconst models = require('../lib/models/')\nconst readline = require('readline-sync')\nconst minimist = require('minimist')\n\nfunction showUsage (tips) {\n  console.log(`${tips}\n\nCommand-line utility to create users for email-signin.\nUsage: bin/manage_users [--pass password] (--add | --del) user-email\n  Options:\n    --add\\tAdd user with the specified user-email\n    --del\\tDelete user with specified user-email\n    --reset\\tReset user password with specified user-email\n    --pass\\tUse password from cmdline rather than prompting\n`)\n  process.exit(1)\n}\n\nfunction getPass (argv, action) {\n  // Find whether we use cmdline or prompt password\n  if (typeof argv['pass'] !== 'string') {\n    return readline.question(`Password for ${argv[action]}:`, { hideEchoBack: true })\n  }\n  console.log('Using password from commandline...')\n  return argv['pass']\n}\n\n// Using an async function to be able to use await inside\nasync function createUser (argv) {\n  const existingUser = await models.User.findOne({ where: { email: argv['add'] } })\n  // Cannot create already-existing users\n  if (existingUser) {\n    console.log(`User with e-mail ${existingUser.email} already exists! Aborting ...`)\n    process.exit(2)\n  }\n\n  const pass = getPass(argv, 'add')\n\n  // Lets try to create, and check success\n  const ref = await models.User.create({ email: argv['add'], password: pass })\n  if (ref === undefined) {\n    console.log(`Could not create user with email ${argv['add']}`)\n    process.exit(1)\n  } else { console.log(`Created user with email ${argv['add']}`) }\n}\n\n// Using an async function to be able to use await inside\nasync function deleteUser (argv) {\n  // Cannot delete non-existing users\n  const existingUser = await models.User.findOne({ where: { email: argv['del'] } })\n  if (!existingUser) {\n    console.log(`User with e-mail ${argv['del']} does not exist, cannot delete`)\n    process.exit(1)\n  }\n\n  // Sadly .destroy() does not return any success value with all\n  // backends. See sequelize #4124\n  await existingUser.destroy()\n  console.log(`Deleted user ${argv['del']} ...`)\n}\n\n// Using an async function to be able to use await inside\nasync function resetUser (argv) {\n  const existingUser = await models.User.findOne({ where: { email: argv['reset'] } })\n  // Cannot reset non-existing users\n  if (!existingUser) {\n    console.log(`User with e-mail ${argv['reset']} does not exist, cannot reset`)\n    process.exit(1)\n  }\n\n  const pass = getPass(argv, 'reset')\n\n  // set password and save\n  existingUser.password = pass\n  await existingUser.save()\n  console.log(`User with email ${argv['reset']} password has been reset`)\n}\n\nconst options = {\n  add: createUser,\n  del: deleteUser,\n  reset: resetUser\n}\n\n// Perform commandline-parsing\nconst argv = minimist(process.argv.slice(2))\n\nconst keys = Object.keys(options)\nconst opts = keys.filter((key) => argv[key] !== undefined)\nconst action = opts[0]\n\n// Check for options missing\nif (opts.length === 0) {\n  showUsage(`You did not specify either ${keys.map((key) => `--${key}`).join(' or ')}!`)\n}\n\n// Check if both are specified\nif (opts.length > 1) {\n  showUsage(`You cannot ${action.join(' and ')} at the same time!`)\n}\n// Check if not string\nif (typeof argv[action] !== 'string') {\n  showUsage(`You must follow an email after --${action}`)\n}\n\n// Call respective processing functions\noptions[action](argv).then(function () {\n  process.exit(0)\n})\n"
  },
  {
    "path": "bin/setup",
    "content": "#!/bin/bash\n\nset -e\n\n# run command at repo root\nCURRENT_PATH=$PWD\nif [ -d .git ]; then\n  cd \"$(git rev-parse --show-toplevel)\"\nfi\n\nif ! type npm > /dev/null\nthen\n  cat << EOF\nnpm is not installed, please install Node.js and npm.\nRead more on Node.js official website: https://nodejs.org\nSetup will not be run\nEOF\n  exit 0\nfi\n\necho \"copy config files\"\nif [ ! -f config.json ]; then\n  cp config.json.example config.json\nfi\n\nif [ ! -f .sequelizerc ]; then\n  cp .sequelizerc.example .sequelizerc\nfi\n\necho \"install packages\"\nnpm install\n\ncat << EOF\n\n\nEdit the following config file to setup CodiMD server and client.\nRead more info at https://hackmd.io/c/codimd-documentation/%2Fs%2Fcodimd-configuration\n\n* config.json           -- CodiMD config\n* .sequelizerc          -- db config\n\nEOF\n\n# change directory back\ncd \"$CURRENT_PATH\"\n"
  },
  {
    "path": "config.js",
    "content": "const config = require('./lib/config')\n\nmodule.exports = config.db\n"
  },
  {
    "path": "config.json.example",
    "content": "{\n    \"test\": {\n        \"db\": {\n            \"dialect\": \"sqlite\",\n            \"storage\": \":memory:\"\n        },\n        \"linkifyHeaderStyle\": \"gfm\"\n    },\n    \"development\": {\n        \"loglevel\": \"debug\",\n        \"hsts\": {\n            \"enable\": false\n        },\n        \"db\": {\n            \"dialect\": \"sqlite\",\n            \"storage\": \"./db.codimd.sqlite\"\n        },\n        \"linkifyHeaderStyle\": \"gfm\"\n    },\n    \"production\": {\n        \"domain\": \"localhost\",\n        \"loglevel\": \"info\",\n        \"hsts\": {\n            \"enable\": true,\n            \"maxAgeSeconds\": 31536000,\n            \"includeSubdomains\": true,\n            \"preload\": true\n        },\n        \"csp\": {\n            \"enable\": true,\n            \"directives\": {\n            },\n            \"upgradeInsecureRequests\": \"auto\",\n            \"addDefaults\": true,\n            \"addDisqus\": true,\n            \"addGoogleAnalytics\": true\n        },\n        \"db\": {\n            \"username\": \"\",\n            \"password\": \"\",\n            \"database\": \"codimd\",\n            \"host\": \"localhost\",\n            \"port\": \"5432\",\n            \"dialect\": \"postgres\"\n        },\n        \"facebook\": {\n            \"clientID\": \"change this\",\n            \"clientSecret\": \"change this\"\n        },\n        \"twitter\": {\n            \"consumerKey\": \"change this\",\n            \"consumerSecret\": \"change this\"\n        },\n        \"github\": {\n            \"clientID\": \"change this\",\n            \"clientSecret\": \"change this\",\n            \"organizations\": [\"names of github organizations allowed, optional\"],\n            \"scopes\": [\"defaults to 'read:user' scope for auth user\"]\n        },\n        \"gitlab\": {\n            \"baseURL\": \"change this\",\n            \"clientID\": \"change this\",\n            \"clientSecret\": \"change this\",\n            \"scope\": \"use 'read_user' scope for auth user only or remove this property if you need gitlab snippet import/export support (will result to be default scope 'api')\",\n            \"version\": \"use 'v4' if gitlab version > 11, 'v3' otherwise. Default to 'v4'\"\n        },\n        \"mattermost\": {\n            \"baseURL\": \"change this\",\n            \"clientID\": \"change this\",\n            \"clientSecret\": \"change this\"\n        },\n        \"dropbox\": {\n            \"clientID\": \"change this\",\n            \"clientSecret\": \"change this\",\n            \"appKey\": \"change this\"\n        },\n        \"google\": {\n            \"clientID\": \"change this\",\n            \"clientSecret\": \"change this\",\n            \"apiKey\": \"change this\"\n        },\n        \"ldap\": {\n            \"url\": \"ldap://change_this\",\n            \"bindDn\": null,\n            \"bindCredentials\": null,\n            \"searchBase\": \"change this\",\n            \"searchFilter\": \"change this\",\n            \"searchAttributes\": [\"change this\"],\n            \"usernameField\": \"change this e.g. cn\",\n            \"useridField\": \"change this e.g. uid\",\n            \"tlsOptions\": {\n                \"changeme\": \"See https://nodejs.org/api/tls.html#tls_tls_connect_options_callback\"\n            }\n        },\n        \"saml\": {\n            \"idpSsoUrl\": \"change: authentication endpoint of IdP\",\n            \"idpCert\": \"change: certificate file path of IdP in PEM format\",\n            \"issuer\": \"change or delete: identity of the service provider (default: serverurl)\",\n            \"identifierFormat\": \"change or delete: name identifier format (default: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress')\",\n            \"disableRequestedAuthnContext\": \"change or delete: true to allow any authentication method, false restricts to password authentication method (default: false)\",\n            \"groupAttribute\": \"change or delete: attribute name for group list (ex: memberOf)\",\n            \"requiredGroups\": [ \"change or delete: group names that allowed\" ],\n            \"externalGroups\": [ \"change or delete: group names that not allowed\" ],\n            \"attribute\": {\n               \"id\": \"change or delete this: attribute map for `id` (default: NameID)\",\n               \"username\": \"change or delete this: attribute map for `username` (default: NameID)\",\n               \"email\": \"change or delete this: attribute map for `email` (default: NameID)\"\n            }\n        },\n        \"imgur\": {\n            \"clientID\": \"change this\"\n        },\n        \"minio\": {\n          \"accessKey\": \"change this\",\n          \"secretKey\": \"change this\",\n          \"endPoint\": \"change this\",\n          \"secure\": true,\n          \"port\": 9000\n        },\n        \"s3\": {\n          \"accessKeyId\": \"change this\",\n          \"secretAccessKey\": \"change this\",\n          \"region\": \"change this\"\n        },\n        \"s3bucket\": \"change this\",\n        \"azure\":\n        {\n          \"connectionString\": \"change this\",\n          \"container\": \"change this\"\n        },\n        \"plantuml\":\n        {\n          \"server\": \"https://www.plantuml.com/plantuml\"\n        },\n        \"linkifyHeaderStyle\": \"gfm\"\n    }\n}\n"
  },
  {
    "path": "contribute/developer-certificate-of-origin",
    "content": "Developer Certificate of Origin\nVersion 1.1\n\nCopyright (C) 2004, 2006 The Linux Foundation and its contributors.\n660 York Street, Suite 102,\nSan Francisco, CA 94110 USA\n\nEveryone is permitted to copy and distribute verbatim copies of this\nlicense document, but changing it is not allowed.\n\nDeveloper's Certificate of Origin 1.1\n\nBy making a contribution to this project, I certify that:\n\n(a) The contribution was created in whole or in part by me and I\n    have the right to submit it under the open source license\n    indicated in the file; or\n\n(b) The contribution is based upon previous work that, to the best\n    of my knowledge, is covered under an appropriate open source\n    license and I have the right under that license to submit that\n    work with modifications, whether created in whole or in part\n    by me, under the same open source license (unless I am\n    permitted to submit under a different license), as indicated\n    in the file; or\n\n(c) The contribution was provided directly to me by some other\n    person who certified (a), (b) or (c) and I have not modified\n    it.\n\n(d) I understand and agree that this project and the contribution\n    are public and that a record of the contribution (including all\n    personal information I submit with it, including my sign-off) is\n    maintained indefinitely and may be redistributed consistent with\n    this project or the open source license(s) involved.\n"
  },
  {
    "path": "deployments/Dockerfile",
    "content": "ARG RUNTIME\nARG BUILDPACK\n\nFROM $BUILDPACK as BUILD\n\nCOPY --chown=hackmd:hackmd . .\nENV QT_QPA_PLATFORM=offscreen\n\nRUN set -xe && \\\n    git reset --hard && \\\n    git clean -fx && \\\n    npm install && \\\n    npm run build && \\\n    cp ./deployments/docker-entrypoint.sh ./ && \\\n    cp .sequelizerc.example .sequelizerc && \\\n    rm -rf .git .gitignore .travis.yml .dockerignore .editorconfig .babelrc .mailmap .sequelizerc.example \\\n        test docs contribute \\\n        package-lock.json webpack.prod.js webpack.htmlexport.js webpack.dev.js webpack.common.js \\\n        config.json.example README.md CONTRIBUTING.md AUTHORS node_modules\n\nFROM $RUNTIME\nUSER hackmd\nENV QT_QPA_PLATFORM=offscreen\nWORKDIR /home/hackmd/app\nCOPY --chown=1500:1500 --from=BUILD /home/hackmd/app .\nRUN npm install --production && npm cache clean --force && rm -rf /tmp/{core-js-banners,phantomjs}\nEXPOSE 3000\nENTRYPOINT [\"/home/hackmd/app/docker-entrypoint.sh\"]\n"
  },
  {
    "path": "deployments/build.sh",
    "content": "#!/usr/bin/env bash\n\nset -eo pipefail\nset -x\n\nif [[ -z $1 || -z $2 ]];then\n    echo \"build.sh [runtime image] [buildpack image]\"\n    exit 1\nfi\n\nCURRENT_DIR=$(dirname \"$BASH_SOURCE\")\n\nGIT_SHA1=\"$(git rev-parse HEAD)\"\nGIT_SHORT_ID=\"${GIT_SHA1:0:8}\"\nGIT_TAG=$(git describe --exact-match --tags $(git log -n1 --pretty='%h') 2>/dev/null || echo \"\")\n\nDOCKER_TAG=\"${GIT_TAG:-$GIT_SHORT_ID}\"\n\ndocker build --build-arg RUNTIME=$1 --build-arg BUILDPACK=$2 -t \"hackmdio/hackmd:$DOCKER_TAG\" -f \"$CURRENT_DIR/Dockerfile\" \"$CURRENT_DIR/..\"\n\n"
  },
  {
    "path": "deployments/docker-compose.yml",
    "content": "version: \"3\"\nservices:\n  database:\n    image: postgres:11.6-alpine\n    environment:\n      - POSTGRES_USER=codimd\n      - POSTGRES_PASSWORD=change_password\n      - POSTGRES_DB=codimd\n    volumes:\n      - \"database-data:/var/lib/postgresql/data\"\n    restart: always\n  codimd:\n    # you can use image or custom build below,\n    image: nabo.codimd.dev/hackmdio/hackmd:2.5.3\n    # Using the following command to trigger the build\n    # docker-compose -f deployments/docker-compose.yml up --build\n    # build:\n    #   context: ..\n    #   dockerfile: ./deployments/Dockerfile\n    #   args:\n    #     RUNTIME: hackmdio/runtime:16.20.2-35fe7e39\n    #     BUILDPACK: hackmdio/buildpack:16.20.2-35fe7e39\n    environment:\n      - CMD_DB_URL=postgres://codimd:change_password@database/codimd\n      - CMD_USECDN=false\n    depends_on:\n      - database\n    ports:\n      - \"3000:3000\"\n    volumes:\n      - upload-data:/home/hackmd/app/public/uploads\n    restart: always\nvolumes:\n  database-data: {}\n  upload-data: {}\n"
  },
  {
    "path": "deployments/docker-entrypoint.sh",
    "content": "#!/usr/bin/env bash\n\nset -euo pipefail\n\nif [[ \"$#\" -gt 0 ]]; then\n    exec \"$@\"\n    exit $?\nfi\n\n# check database and redis is ready\npcheck -env CMD_DB_URL\n\n# run DB migrate\nNEED_MIGRATE=${CMD_AUTO_MIGRATE:=true}\n\nif [[ \"$NEED_MIGRATE\" = \"true\" ]] && [[ -f .sequelizerc ]] ; then\n    npx sequelize db:migrate\nfi\n\n# start application\nnode app.js\n"
  },
  {
    "path": "lib/auth/bitbucket/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst passport = require('passport')\nconst BitbucketStrategy = require('passport-bitbucket-oauth2').Strategy\nconst config = require('../../config')\nconst { setReturnToFromReferer, passportGeneralCallback } = require('../utils')\n\nconst bitbucketAuth = module.exports = Router()\n\npassport.use(new BitbucketStrategy({\n  clientID: config.bitbucket.clientID,\n  clientSecret: config.bitbucket.clientSecret,\n  callbackURL: config.serverURL + '/auth/bitbucket/callback',\n  state: true\n}, passportGeneralCallback))\n\nbitbucketAuth.get('/auth/bitbucket', function (req, res, next) {\n  setReturnToFromReferer(req)\n  passport.authenticate('bitbucket')(req, res, next)\n})\n\n// bitbucket auth callback\nbitbucketAuth.get('/auth/bitbucket/callback',\n  passport.authenticate('bitbucket', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/'\n  })\n)\n"
  },
  {
    "path": "lib/auth/dropbox/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst passport = require('passport')\nconst DropboxStrategy = require('passport-dropbox-oauth2').Strategy\nconst config = require('../../config')\nconst { setReturnToFromReferer, passportGeneralCallback } = require('../utils')\n\nconst dropboxAuth = module.exports = Router()\n\npassport.use(new DropboxStrategy({\n  apiVersion: '2',\n  clientID: config.dropbox.clientID,\n  clientSecret: config.dropbox.clientSecret,\n  callbackURL: config.serverURL + '/auth/dropbox/callback',\n  state: true\n}, passportGeneralCallback))\n\ndropboxAuth.get('/auth/dropbox', function (req, res, next) {\n  setReturnToFromReferer(req)\n  passport.authenticate('dropbox-oauth2')(req, res, next)\n})\n\n// dropbox auth callback\ndropboxAuth.get('/auth/dropbox/callback',\n  passport.authenticate('dropbox-oauth2', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/'\n  })\n)\n"
  },
  {
    "path": "lib/auth/email/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst passport = require('passport')\nconst sequelize = require('sequelize')\nconst validator = require('validator')\nconst LocalStrategy = require('passport-local').Strategy\nconst config = require('../../config')\nconst models = require('../../models')\nconst logger = require('../../logger')\nconst { setReturnToFromReferer } = require('../utils')\nconst { urlencodedParser } = require('../../utils')\nconst response = require('../../response')\n\nconst emailAuth = module.exports = Router()\n\npassport.use(new LocalStrategy({\n  usernameField: 'email'\n}, async function (email, password, done) {\n  if (!validator.isEmail(email)) return done(null, false)\n\n  try {\n    const user = await models.User.findOne({\n      where: {\n        email: sequelize.where(\n          sequelize.fn('LOWER', sequelize.col('email')),\n          email.toLowerCase()\n        )\n      }\n    })\n\n    if (!user) return done(null, false)\n    if (!await user.verifyPassword(password)) return done(null, false)\n    return done(null, user)\n  } catch (err) {\n    logger.error(err)\n    return done(err)\n  }\n}))\n\nif (config.allowEmailRegister) {\n  emailAuth.post('/register', urlencodedParser, async function (req, res, next) {\n    if (!req.body.email || !req.body.password) return response.errorBadRequest(req, res)\n    if (!validator.isEmail(req.body.email)) return response.errorBadRequest(req, res)\n    try {\n      const [user, created] = await models.User.findOrCreate({\n        where: {\n          email: req.body.email\n        },\n        defaults: {\n          password: req.body.password\n        }\n      })\n\n      if (!user) {\n        req.flash('error', 'Failed to register your account, please try again.')\n        return res.redirect(config.serverURL + '/')\n      }\n\n      if (created) {\n        logger.debug('user registered: ' + user.id)\n        req.flash('info', \"You've successfully registered, please signin.\")\n      } else {\n        logger.debug('user found: ' + user.id)\n        req.flash('error', 'This email has been used, please try another one.')\n      }\n      return res.redirect(config.serverURL + '/')\n    } catch (err) {\n      logger.error('auth callback failed: ' + err)\n      return response.errorInternalError(req, res)\n    }\n  })\n}\n\nemailAuth.post('/login', urlencodedParser, function (req, res, next) {\n  if (!req.body.email || !req.body.password) return response.errorBadRequest(req, res)\n  if (!validator.isEmail(req.body.email)) return response.errorBadRequest(req, res)\n  setReturnToFromReferer(req)\n  passport.authenticate('local', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/',\n    failureFlash: 'Invalid email or password.'\n  })(req, res, next)\n})\n"
  },
  {
    "path": "lib/auth/facebook/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst passport = require('passport')\nconst FacebookStrategy = require('passport-facebook').Strategy\n\nconst config = require('../../config')\nconst { setReturnToFromReferer, passportGeneralCallback } = require('../utils')\n\nconst facebookAuth = module.exports = Router()\n\npassport.use(new FacebookStrategy({\n  clientID: config.facebook.clientID,\n  clientSecret: config.facebook.clientSecret,\n  callbackURL: config.serverURL + '/auth/facebook/callback',\n  state: true\n}, passportGeneralCallback))\n\nfacebookAuth.get('/auth/facebook', function (req, res, next) {\n  setReturnToFromReferer(req)\n  passport.authenticate('facebook')(req, res, next)\n})\n\n// facebook auth callback\nfacebookAuth.get('/auth/facebook/callback',\n  passport.authenticate('facebook', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/'\n  })\n)\n"
  },
  {
    "path": "lib/auth/github/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst request = require('request')\nconst passport = require('passport')\nconst GithubStrategy = require('passport-github').Strategy\nconst { InternalOAuthError } = require('passport-oauth2')\nconst config = require('../../config')\nconst response = require('../../response')\nconst { setReturnToFromReferer, passportGeneralCallback } = require('../utils')\nconst { URL } = require('url')\nconst { promisify } = require('util')\n\nconst rp = promisify(request)\n\nconst githubAuth = module.exports = Router()\n\nfunction githubUrl (path) {\n  return config.github.enterpriseURL && new URL(path, config.github.enterpriseURL).toString()\n}\n\npassport.use(new GithubStrategy({\n  scope: (config.github.organizations ? config.github.scopes.concat(['read:org']) : config.github.scope),\n  clientID: config.github.clientID,\n  clientSecret: config.github.clientSecret,\n  callbackURL: config.serverURL + '/auth/github/callback',\n  authorizationURL: githubUrl('login/oauth/authorize'),\n  tokenURL: githubUrl('login/oauth/access_token'),\n  userProfileURL: githubUrl('api/v3/user'),\n  state: true\n}, async (accessToken, refreshToken, profile, done) => {\n  if (!config.github.organizations) {\n    return passportGeneralCallback(accessToken, refreshToken, profile, done)\n  }\n  const { statusCode, body: data } = await rp({\n    url: `https://api.github.com/user/orgs`,\n    method: 'GET',\n    json: true,\n    timeout: 2000,\n    headers: {\n      Authorization: `token ${accessToken}`,\n      'User-Agent': 'nodejs-http'\n    }\n  })\n  if (statusCode !== 200) {\n    return done(InternalOAuthError(\n      `Failed to query organizations for user: ${profile.username}`\n    ))\n  }\n  const orgs = data.map(({ login }) => login)\n  for (const org of orgs) {\n    if (config.github.organizations.includes(org)) {\n      return passportGeneralCallback(accessToken, refreshToken, profile, done)\n    }\n  }\n  return done(InternalOAuthError(\n    `User orgs not whitelisted: ${profile.username} (${orgs.join(',')})`\n  ))\n}))\n\ngithubAuth.get('/auth/github', function (req, res, next) {\n  setReturnToFromReferer(req)\n  passport.authenticate('github')(req, res, next)\n})\n\ngithubAuth.get('/auth/github/callback',\n  passport.authenticate('github', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/'\n  })\n)\n\n// github callback actions\ngithubAuth.get('/auth/github/callback/:noteId/:action', response.githubActions)\n"
  },
  {
    "path": "lib/auth/gitlab/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst passport = require('passport')\nconst GitlabStrategy = require('passport-gitlab2').Strategy\nconst config = require('../../config')\nconst response = require('../../response')\nconst { setReturnToFromReferer, passportGeneralCallback } = require('../utils')\nconst HttpsProxyAgent = require('https-proxy-agent')\n\nconst gitlabAuth = module.exports = Router()\n\nconst gitlabAuthStrategy = new GitlabStrategy({\n  baseURL: config.gitlab.baseURL,\n  clientID: config.gitlab.clientID,\n  clientSecret: config.gitlab.clientSecret,\n  scope: config.gitlab.scope,\n  callbackURL: config.serverURL + '/auth/gitlab/callback',\n  state: true\n}, passportGeneralCallback)\n\nif (process.env.https_proxy) {\n  const httpsProxyAgent = new HttpsProxyAgent(process.env.https_proxy)\n  gitlabAuthStrategy._oauth2.setAgent(httpsProxyAgent)\n}\n\npassport.use(gitlabAuthStrategy)\n\ngitlabAuth.get('/auth/gitlab', function (req, res, next) {\n  setReturnToFromReferer(req)\n  passport.authenticate('gitlab')(req, res, next)\n})\n\n// gitlab auth callback\ngitlabAuth.get('/auth/gitlab/callback',\n  passport.authenticate('gitlab', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/'\n  })\n)\n\nif (!config.gitlab.scope || config.gitlab.scope === 'api') {\n  // gitlab callback actions\n  gitlabAuth.get('/auth/gitlab/callback/:noteId/:action', response.gitlabActions)\n}\n"
  },
  {
    "path": "lib/auth/google/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst passport = require('passport')\nvar GoogleStrategy = require('passport-google-oauth20').Strategy\nconst config = require('../../config')\nconst { setReturnToFromReferer, passportGeneralCallback } = require('../utils')\n\nconst googleAuth = module.exports = Router()\n\npassport.use(new GoogleStrategy({\n  clientID: config.google.clientID,\n  clientSecret: config.google.clientSecret,\n  callbackURL: config.serverURL + '/auth/google/callback',\n  userProfileURL: 'https://www.googleapis.com/oauth2/v3/userinfo',\n  state: true\n}, passportGeneralCallback))\n\ngoogleAuth.get('/auth/google', function (req, res, next) {\n  setReturnToFromReferer(req)\n  passport.authenticate('google', {\n    scope: ['profile'],\n    hostedDomain: config.google.hostedDomain\n  })(req, res, next)\n})\n// google auth callback\ngoogleAuth.get('/auth/google/callback',\n  passport.authenticate('google', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/'\n  })\n)\n"
  },
  {
    "path": "lib/auth/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst passport = require('passport')\n\nconst config = require('../config')\nconst logger = require('../logger')\nconst models = require('../models')\n\nconst authRouter = module.exports = Router()\n\n// serialize and deserialize\npassport.serializeUser(function (user, done) {\n  logger.info('serializeUser: ' + user.id)\n  return done(null, user.id)\n})\n\npassport.deserializeUser(function (id, done) {\n  models.User.findOne({\n    where: {\n      id: id\n    }\n  }).then(function (user) {\n    // Don't die on non-existent user\n    if (user == null) {\n      return done(null, false, { message: 'Invalid UserID' })\n    }\n\n    logger.info('deserializeUser: ' + user.id)\n    return done(null, user)\n  }).catch(function (err) {\n    logger.error(err)\n    return done(err, null)\n  })\n})\n\nif (config.isFacebookEnable) authRouter.use(require('./facebook'))\nif (config.isTwitterEnable) authRouter.use(require('./twitter'))\nif (config.isGitHubEnable) authRouter.use(require('./github'))\nif (config.isBitbucketEnable) authRouter.use(require('./bitbucket'))\nif (config.isGitLabEnable) authRouter.use(require('./gitlab'))\nif (config.isMattermostEnable) authRouter.use(require('./mattermost'))\nif (config.isDropboxEnable) authRouter.use(require('./dropbox'))\nif (config.isGoogleEnable) authRouter.use(require('./google'))\nif (config.isLDAPEnable) authRouter.use(require('./ldap'))\nif (config.isSAMLEnable) authRouter.use(require('./saml'))\nif (config.isOAuth2Enable) authRouter.use(require('./oauth2'))\nif (config.isEmailEnable) authRouter.use(require('./email'))\nif (config.isOpenIDEnable) authRouter.use(require('./openid'))\n\n// logout\nauthRouter.get('/logout', function (req, res, next) {\n  if (config.debug && req.isAuthenticated()) {\n    logger.debug('user logout: ' + req.user.id)\n  }\n\n  req.logout((err) => {\n    if (err) { return next(err) }\n\n    res.redirect(config.serverURL + '/')\n  })\n})\n"
  },
  {
    "path": "lib/auth/ldap/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst passport = require('passport')\nconst LDAPStrategy = require('passport-ldapauth')\nconst config = require('../../config')\nconst models = require('../../models')\nconst logger = require('../../logger')\nconst { setReturnToFromReferer } = require('../utils')\nconst { urlencodedParser } = require('../../utils')\nconst response = require('../../response')\n\nconst ldapAuth = module.exports = Router()\n\npassport.use(new LDAPStrategy({\n  server: {\n    url: config.ldap.url || null,\n    bindDN: config.ldap.bindDn || null,\n    bindCredentials: config.ldap.bindCredentials || null,\n    searchBase: config.ldap.searchBase || null,\n    searchFilter: config.ldap.searchFilter || null,\n    searchAttributes: config.ldap.searchAttributes || null,\n    tlsOptions: config.ldap.tlsOptions || null\n  }\n}, function (user, done) {\n  var uuid = user.uidNumber || user.uid || user.sAMAccountName || undefined\n  if (config.ldap.useridField && user[config.ldap.useridField]) {\n    uuid = user[config.ldap.useridField]\n  }\n\n  if (typeof uuid === 'undefined') {\n    throw new Error('Could not determine UUID for LDAP user. Check that ' +\n    'either uidNumber, uid or sAMAccountName is set in your LDAP directory ' +\n    'or use another unique attribute and configure it using the ' +\n    '\"useridField\" option in ldap settings.')\n  }\n\n  var username = uuid\n  if (config.ldap.usernameField && user[config.ldap.usernameField]) {\n    username = user[config.ldap.usernameField]\n  }\n\n  var profile = {\n    id: 'LDAP-' + uuid,\n    username: username,\n    displayName: user.displayName,\n    emails: user.mail ? Array.isArray(user.mail) ? user.mail : [user.mail] : [],\n    avatarUrl: null,\n    profileUrl: null,\n    provider: 'ldap'\n  }\n  var stringifiedProfile = JSON.stringify(profile)\n  models.User.findOrCreate({\n    where: {\n      profileid: profile.id.toString()\n    },\n    defaults: {\n      profile: stringifiedProfile\n    }\n  }).spread(function (user, created) {\n    if (user) {\n      var needSave = false\n      if (user.profile !== stringifiedProfile) {\n        user.profile = stringifiedProfile\n        needSave = true\n      }\n      if (needSave) {\n        user.save().then(function () {\n          if (config.debug) { logger.debug('user login: ' + user.id) }\n          return done(null, user)\n        })\n      } else {\n        if (config.debug) { logger.debug('user login: ' + user.id) }\n        return done(null, user)\n      }\n    }\n  }).catch(function (err) {\n    logger.error('ldap auth failed: ' + err)\n    return done(err, null)\n  })\n}))\n\nldapAuth.post('/auth/ldap', urlencodedParser, function (req, res, next) {\n  if (!req.body.username || !req.body.password) return response.errorBadRequest(req, res)\n  setReturnToFromReferer(req)\n  passport.authenticate('ldapauth', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/',\n    failureFlash: true\n  })(req, res, next)\n})\n"
  },
  {
    "path": "lib/auth/mattermost/index.js",
    "content": "'use strict'\nrequire('babel-polyfill')\nrequire('isomorphic-fetch')\nconst Router = require('express').Router\nconst passport = require('passport')\nconst { Client4: MattermostClient } = require('@mattermost/client')\nconst OAuthStrategy = require('passport-oauth2').Strategy\nconst config = require('../../config')\nconst { setReturnToFromReferer, passportGeneralCallback } = require('../utils')\n\nconst mattermostAuth = module.exports = Router()\n\nconst mattermostClient = new MattermostClient()\n\nconst mattermostStrategy = new OAuthStrategy({\n  authorizationURL: config.mattermost.baseURL + '/oauth/authorize',\n  tokenURL: config.mattermost.baseURL + '/oauth/access_token',\n  clientID: config.mattermost.clientID,\n  clientSecret: config.mattermost.clientSecret,\n  callbackURL: config.serverURL + '/auth/mattermost/callback'\n}, passportGeneralCallback)\n\nmattermostStrategy.userProfile = (accessToken, done) => {\n  mattermostClient.setUrl(config.mattermost.baseURL)\n  mattermostClient.setToken(accessToken)\n  mattermostClient.getMe()\n    .then((data) => done(null, data))\n    .catch((err) => done(err))\n}\n\npassport.use(mattermostStrategy)\n\nmattermostAuth.get('/auth/mattermost', function (req, res, next) {\n  setReturnToFromReferer(req)\n  passport.authenticate('oauth2')(req, res, next)\n})\n\n// mattermost auth callback\nmattermostAuth.get('/auth/mattermost/callback',\n  passport.authenticate('oauth2', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/'\n  })\n)\n"
  },
  {
    "path": "lib/auth/oauth2/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst passport = require('passport')\n\nconst config = require('../../config')\nconst { setReturnToFromReferer, passportGeneralCallback } = require('../utils')\nconst { OAuth2CustomStrategy } = require('./strategy')\n\nconst oauth2Auth = module.exports = Router()\n\npassport.use(new OAuth2CustomStrategy({\n  authorizationURL: config.oauth2.authorizationURL,\n  tokenURL: config.oauth2.tokenURL,\n  clientID: config.oauth2.clientID,\n  clientSecret: config.oauth2.clientSecret,\n  callbackURL: config.serverURL + '/auth/oauth2/callback',\n  userProfileURL: config.oauth2.userProfileURL,\n  state: config.oauth2.state,\n  scope: config.oauth2.scope\n}, passportGeneralCallback))\n\noauth2Auth.get('/auth/oauth2', function (req, res, next) {\n  setReturnToFromReferer(req)\n  passport.authenticate('oauth2')(req, res, next)\n})\n\n// github auth callback\noauth2Auth.get('/auth/oauth2/callback',\n  passport.authenticate('oauth2', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/'\n  })\n)\n"
  },
  {
    "path": "lib/auth/oauth2/strategy.js",
    "content": "'use strict'\n\nconst { Strategy, InternalOAuthError } = require('passport-oauth2')\nconst config = require('../../config')\n\nfunction parseProfile (data) {\n  const id = extractProfileAttribute(data, config.oauth2.userProfileIdAttr)\n  const username = extractProfileAttribute(data, config.oauth2.userProfileUsernameAttr)\n  const displayName = extractProfileAttribute(data, config.oauth2.userProfileDisplayNameAttr)\n  const email = extractProfileAttribute(data, config.oauth2.userProfileEmailAttr)\n  const photo = extractProfileAttribute(data, config.oauth2.userProfilePhotoAttr)\n\n  if (!username) {\n    throw new Error('cannot fetch username: please set correct CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR')\n  }\n\n  return {\n    id: id || username,\n    username: username,\n    displayName: displayName,\n    email: email,\n    photo: photo\n  }\n}\n\nfunction extractProfileAttribute (data, path) {\n  if (!data) return undefined\n  if (typeof path !== 'string') return undefined\n  // can handle stuff like `attrs[0].name`\n  path = path.split('.')\n  for (const segment of path) {\n    const m = segment.match(/([\\d\\w]+)\\[(.*)\\]/)\n    if (!m) {\n      data = data[segment]\n    } else {\n      if (m.length < 3) return undefined\n      if (!data[m[1]]) return undefined\n      data = data[m[1]][m[2]]\n    }\n    if (!data) return undefined\n  }\n  return data\n}\n\nfunction checkAuthorization (data, done) {\n  const roles = extractProfileAttribute(data, config.oauth2.rolesClaim)\n\n  if (config.oauth2.accessRole && roles) {\n    if (!roles.includes(config.oauth2.accessRole)) {\n      return done('Permission denied', null)\n    }\n  }\n}\n\nclass OAuth2CustomStrategy extends Strategy {\n  constructor (options, verify) {\n    options.customHeaders = options.customHeaders || {}\n    super(options, verify)\n    this.name = 'oauth2'\n    this._userProfileURL = options.userProfileURL\n    this._oauth2.useAuthorizationHeaderforGET(true)\n  }\n\n  userProfile (accessToken, done) {\n    this._oauth2.get(this._userProfileURL, accessToken, function (err, body, res) {\n      if (err) {\n        return done(new InternalOAuthError('Failed to fetch user profile', err))\n      }\n\n      let profile, json\n      try {\n        json = JSON.parse(body)\n        checkAuthorization(json, done)\n        profile = parseProfile(json)\n      } catch (ex) {\n        return done(new InternalOAuthError('Failed to parse user profile' + ex.toString()))\n      }\n\n      profile.provider = 'oauth2'\n\n      done(null, profile)\n    })\n  }\n}\n\nexports.OAuth2CustomStrategy = OAuth2CustomStrategy\nexports.parseProfile = parseProfile\nexports.extractProfileAttribute = extractProfileAttribute\n"
  },
  {
    "path": "lib/auth/openid/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst passport = require('passport')\nconst OpenIDStrategy = require('@passport-next/passport-openid').Strategy\nconst config = require('../../config')\nconst models = require('../../models')\nconst logger = require('../../logger')\nconst { urlencodedParser } = require('../../utils')\nconst { setReturnToFromReferer } = require('../utils')\n\nconst openIDAuth = module.exports = Router()\n\npassport.use(new OpenIDStrategy({\n  returnURL: config.serverURL + '/auth/openid/callback',\n  realm: config.serverURL,\n  profile: true\n}, function (openid, profile, done) {\n  var stringifiedProfile = JSON.stringify(profile)\n  models.User.findOrCreate({\n    where: {\n      profileid: openid\n    },\n    defaults: {\n      profile: stringifiedProfile\n    }\n  }).spread(function (user, created) {\n    if (user) {\n      var needSave = false\n      if (user.profile !== stringifiedProfile) {\n        user.profile = stringifiedProfile\n        needSave = true\n      }\n      if (needSave) {\n        user.save().then(function () {\n          if (config.debug) { logger.info('user login: ' + user.id) }\n          return done(null, user)\n        })\n      } else {\n        if (config.debug) { logger.info('user login: ' + user.id) }\n        return done(null, user)\n      }\n    }\n  }).catch(function (err) {\n    logger.error('auth callback failed: ' + err)\n    return done(err, null)\n  })\n}))\n\nopenIDAuth.post('/auth/openid', urlencodedParser, function (req, res, next) {\n  setReturnToFromReferer(req)\n  passport.authenticate('openid')(req, res, next)\n})\n\n// openID auth callback\nopenIDAuth.get('/auth/openid/callback',\n  passport.authenticate('openid', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/'\n  })\n)\n"
  },
  {
    "path": "lib/auth/saml/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst passport = require('passport')\nconst SamlStrategy = require('passport-saml').Strategy\nconst config = require('../../config')\nconst models = require('../../models')\nconst logger = require('../../logger')\nconst { urlencodedParser } = require('../../utils')\nconst fs = require('fs')\nconst intersection = function (array1, array2) { return array1.filter((n) => array2.includes(n)) }\n\nconst samlAuth = module.exports = Router()\n\npassport.use(new SamlStrategy({\n  callbackUrl: config.serverURL + '/auth/saml/callback',\n  entryPoint: config.saml.idpSsoUrl,\n  issuer: config.saml.issuer || config.serverURL,\n  cert: fs.readFileSync(config.saml.idpCert, 'utf-8'),\n  identifierFormat: config.saml.identifierFormat,\n  disableRequestedAuthnContext: config.saml.disableRequestedAuthnContext\n}, function (user, done) {\n  // check authorization if needed\n  if (config.saml.externalGroups && config.saml.groupAttribute) {\n    var externalGroups = intersection(config.saml.externalGroups, user[config.saml.groupAttribute])\n    if (externalGroups.length > 0) {\n      logger.error('saml permission denied: ' + externalGroups.join(', '))\n      return done('Permission denied', null)\n    }\n  }\n  if (config.saml.requiredGroups && config.saml.groupAttribute) {\n    if (intersection(config.saml.requiredGroups, user[config.saml.groupAttribute]).length === 0) {\n      logger.error('saml permission denied')\n      return done('Permission denied', null)\n    }\n  }\n  // user creation\n  var uuid = user[config.saml.attribute.id] || user.nameID\n  var profile = {\n    provider: 'saml',\n    id: 'SAML-' + uuid,\n    username: user[config.saml.attribute.username] || user.nameID,\n    emails: user[config.saml.attribute.email] ? [user[config.saml.attribute.email]] : []\n  }\n  if (profile.emails.length === 0 && config.saml.identifierFormat === 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress') {\n    profile.emails.push(user.nameID)\n  }\n  var stringifiedProfile = JSON.stringify(profile)\n  models.User.findOrCreate({\n    where: {\n      profileid: profile.id.toString()\n    },\n    defaults: {\n      profile: stringifiedProfile\n    }\n  }).spread(function (user, created) {\n    if (user) {\n      var needSave = false\n      if (user.profile !== stringifiedProfile) {\n        user.profile = stringifiedProfile\n        needSave = true\n      }\n      if (needSave) {\n        user.save().then(function () {\n          if (config.debug) { logger.debug('user login: ' + user.id) }\n          return done(null, user)\n        })\n      } else {\n        if (config.debug) { logger.debug('user login: ' + user.id) }\n        return done(null, user)\n      }\n    }\n  }).catch(function (err) {\n    logger.error('saml auth failed: ' + err)\n    return done(err, null)\n  })\n}))\n\nsamlAuth.get('/auth/saml',\n  passport.authenticate('saml', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/'\n  })\n)\n\nsamlAuth.post('/auth/saml/callback', urlencodedParser,\n  passport.authenticate('saml', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/'\n  })\n)\n\nsamlAuth.get('/auth/saml/metadata', function (req, res) {\n  res.type('application/xml')\n  res.send(passport._strategy('saml').generateServiceProviderMetadata())\n})\n"
  },
  {
    "path": "lib/auth/twitter/index.js",
    "content": "'use strict'\n\nconst Router = require('express').Router\nconst passport = require('passport')\nconst TwitterStrategy = require('passport-twitter').Strategy\n\nconst config = require('../../config')\nconst { setReturnToFromReferer, passportGeneralCallback } = require('../utils')\n\nconst twitterAuth = module.exports = Router()\n\npassport.use(new TwitterStrategy({\n  consumerKey: config.twitter.consumerKey,\n  consumerSecret: config.twitter.consumerSecret,\n  callbackURL: config.serverURL + '/auth/twitter/callback',\n  state: true\n}, passportGeneralCallback))\n\ntwitterAuth.get('/auth/twitter', function (req, res, next) {\n  setReturnToFromReferer(req)\n  passport.authenticate('twitter')(req, res, next)\n})\n\n// twitter auth callback\ntwitterAuth.get('/auth/twitter/callback',\n  passport.authenticate('twitter', {\n    successReturnToOrRedirect: config.serverURL + '/',\n    failureRedirect: config.serverURL + '/'\n  })\n)\n"
  },
  {
    "path": "lib/auth/utils.js",
    "content": "'use strict'\n\nconst models = require('../models')\nconst config = require('../config')\nconst logger = require('../logger')\n\nexports.setReturnToFromReferer = function setReturnToFromReferer (req) {\n  if (!req.session) req.session = {}\n\n  var referer = req.get('referer')\n  var nextURL\n  if (referer) {\n    try {\n      var refererSearchParams = new URLSearchParams(new URL(referer).search)\n      nextURL = refererSearchParams.get('next')\n    } catch (err) {\n      logger.warn(err)\n    }\n  }\n\n  if (nextURL) {\n    var isRelativeNextURL = nextURL.indexOf('://') === -1 && !nextURL.startsWith('//')\n    if (isRelativeNextURL) {\n      req.session.returnTo = (new URL(nextURL, config.serverURL)).toString()\n    } else {\n      req.session.returnTo = config.serverURL\n    }\n  } else {\n    req.session.returnTo = referer\n  }\n}\n\nexports.passportGeneralCallback = function callback (accessToken, refreshToken, profile, done) {\n  var stringifiedProfile = JSON.stringify(profile)\n  models.User.findOrCreate({\n    where: {\n      profileid: profile.id.toString()\n    },\n    defaults: {\n      profile: stringifiedProfile,\n      accessToken: accessToken,\n      refreshToken: refreshToken\n    }\n  }).spread(function (user, created) {\n    if (user) {\n      var needSave = false\n      if (user.profile !== stringifiedProfile) {\n        user.profile = stringifiedProfile\n        needSave = true\n      }\n      if (user.accessToken !== accessToken) {\n        user.accessToken = accessToken\n        needSave = true\n      }\n      if (user.refreshToken !== refreshToken) {\n        user.refreshToken = refreshToken\n        needSave = true\n      }\n      if (needSave) {\n        user.save().then(function () {\n          if (config.debug) { logger.info('user login: ' + user.id) }\n          return done(null, user)\n        })\n      } else {\n        if (config.debug) { logger.info('user login: ' + user.id) }\n        return done(null, user)\n      }\n    }\n  }).catch(function (err) {\n    logger.error('auth callback failed: ' + err)\n    return done(err, null)\n  })\n}\n"
  },
  {
    "path": "lib/config/default.js",
    "content": "'use strict'\n\nconst os = require('os')\n\nmodule.exports = {\n  domain: '',\n  urlPath: '',\n  host: '0.0.0.0',\n  port: 3000,\n  loglevel: 'info',\n  urlAddPort: false,\n  allowOrigin: ['localhost'],\n  useSSL: false,\n  hsts: {\n    enable: true,\n    maxAgeSeconds: 60 * 60 * 24 * 365,\n    includeSubdomains: false,\n    preload: true\n  },\n  csp: {\n    enable: true,\n    directives: {\n    },\n    addDefaults: true,\n    addDisqus: true,\n    addGoogleAnalytics: true,\n    upgradeInsecureRequests: 'auto',\n    reportURI: undefined\n  },\n  protocolUseSSL: false,\n  useCDN: true,\n  allowAnonymous: false,\n  allowAnonymousEdits: true,\n  allowAnonymousViews: true,\n  allowFreeURL: false,\n  forbiddenNoteIDs: ['robots.txt', 'favicon.ico', 'api'],\n  defaultPermission: 'editable',\n  dbURL: '',\n  db: {},\n  privacyPolicyURL: '',\n  // ssl path\n  sslKeyPath: '',\n  sslCertPath: '',\n  sslCAPath: '',\n  dhParamPath: '',\n  // other path\n  viewPath: './public/views',\n  tmpPath: os.tmpdir(),\n  defaultNotePath: './public/default.md',\n  docsPath: './public/docs',\n  uploadsPath: './public/uploads',\n  // session\n  sessionName: 'connect.sid',\n  sessionSecret: 'secret',\n  sessionSecretLen: 128,\n  sessionLife: 14 * 24 * 60 * 60 * 1000, // 14 days\n  staticCacheTime: 1 * 24 * 60 * 60 * 1000, // 1 day\n  // socket.io\n  heartbeatInterval: 5000,\n  heartbeatTimeout: 10000,\n  // toobusy-js\n  responseMaxLag: 70,\n  // document\n  documentMaxLength: 100000,\n  // image upload setting, available options are imgur/s3/filesystem/azure/lutim\n  imageUploadType: 'filesystem',\n  lutim: {\n    url: 'https://framapic.org/'\n  },\n  imgur: {\n    clientID: undefined\n  },\n  s3: {\n    accessKeyId: undefined,\n    secretAccessKey: undefined,\n    region: undefined,\n    endpoint: undefined,\n    baseURL: undefined\n  },\n  minio: {\n    accessKey: undefined,\n    secretKey: undefined,\n    endPoint: undefined,\n    secure: true,\n    port: 9000\n  },\n  s3bucket: undefined,\n  azure: {\n    connectionString: undefined,\n    container: undefined\n  },\n  // authentication\n  oauth2: {\n    providerName: undefined,\n    authorizationURL: undefined,\n    tokenURL: undefined,\n    clientID: undefined,\n    clientSecret: undefined,\n    baseURL: undefined,\n    userProfileURL: undefined,\n    userProfileUsernameAttr: 'username',\n    userProfileDisplayNameAttr: 'displayName',\n    userProfileEmailAttr: 'email',\n    userProfilePhotoAttr: 'photo',\n    state: true,\n    scope: 'email'\n  },\n  facebook: {\n    clientID: undefined,\n    clientSecret: undefined\n  },\n  twitter: {\n    consumerKey: undefined,\n    consumerSecret: undefined\n  },\n  github: {\n    enterpriseURL: undefined, // if you use github.com, not need to specify\n    clientID: undefined,\n    clientSecret: undefined,\n    organizations: [],\n    scopes: ['read:user']\n  },\n  gitlab: {\n    baseURL: undefined,\n    clientID: undefined,\n    clientSecret: undefined,\n    scope: undefined,\n    version: 'v4'\n  },\n  mattermost: {\n    baseURL: undefined,\n    clientID: undefined,\n    clientSecret: undefined\n  },\n  dropbox: {\n    clientID: undefined,\n    clientSecret: undefined,\n    appKey: undefined\n  },\n  google: {\n    clientID: undefined,\n    clientSecret: undefined,\n    hostedDomain: undefined\n  },\n  ldap: {\n    providerName: undefined,\n    url: undefined,\n    bindDn: undefined,\n    bindCredentials: undefined,\n    searchBase: undefined,\n    searchFilter: undefined,\n    searchAttributes: undefined,\n    usernameField: undefined,\n    useridField: undefined,\n    tlsca: undefined\n  },\n  saml: {\n    idpSsoUrl: undefined,\n    idpCert: undefined,\n    issuer: undefined,\n    identifierFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',\n    disableRequestedAuthnContext: false,\n    groupAttribute: undefined,\n    externalGroups: [],\n    requiredGroups: [],\n    attribute: {\n      id: undefined,\n      username: undefined,\n      email: undefined\n    }\n  },\n  plantuml: {\n    server: 'https://www.plantuml.com/plantuml'\n  },\n  email: true,\n  allowEmailRegister: true,\n  allowGravatar: true,\n  allowPDFExport: true,\n  openID: false,\n  defaultUseHardbreak: true,\n  // linkifyHeaderStyle - How is a header text converted into a link id.\n  // Header Example: \"3.1. Good Morning my Friend! - Do you have 5$?\"\n  // * 'keep-case' is the legacy CodiMD value.\n  //    Generated id: \"31-Good-Morning-my-Friend---Do-you-have-5\"\n  // * 'lower-case' is the same like legacy (see above), but converted to lower-case.\n  //    Generated id: \"#31-good-morning-my-friend---do-you-have-5\"\n  // * 'gfm' _GitHub-Flavored Markdown_ style as described here:\n  //    https://gist.github.com/asabaylus/3071099#gistcomment-1593627\n  //    It works like 'lower-case', but making sure the ID is unique.\n  //    This is What GitHub, GitLab and (hopefully) most other tools use.\n  //    Generated id:   \"31-good-morning-my-friend---do-you-have-5\"\n  //    2nd appearance: \"31-good-morning-my-friend---do-you-have-5-1\"\n  //    3rd appearance: \"31-good-morning-my-friend---do-you-have-5-2\"\n  linkifyHeaderStyle: 'keep-case',\n  autoVersionCheck: true,\n  defaultTocDepth: 3\n}\n"
  },
  {
    "path": "lib/config/defaultSSL.js",
    "content": "'use strict'\n\nconst fs = require('fs')\n\nfunction getFile (path) {\n  if (fs.existsSync(path)) {\n    return path\n  }\n  return undefined\n}\n\nmodule.exports = {\n  sslKeyPath: getFile('/run/secrets/key.pem'),\n  sslCertPath: getFile('/run/secrets/cert.pem'),\n  sslCAPath: getFile('/run/secrets/ca.pem') !== undefined ? [getFile('/run/secrets/ca.pem')] : [],\n  dhParamPath: getFile('/run/secrets/dhparam.pem')\n}\n"
  },
  {
    "path": "lib/config/dockerSecret.js",
    "content": "'use strict'\n\nconst fs = require('fs')\nconst path = require('path')\n\nconst basePath = path.resolve('/var/run/secrets/')\n\nfunction getSecret (secret) {\n  const filePath = path.join(basePath, secret)\n  if (fs.existsSync(filePath)) return fs.readFileSync(filePath)\n  return undefined\n}\n\nif (fs.existsSync(basePath)) {\n  module.exports = {\n    dbURL: getSecret('dburl'),\n    // ssl path\n    sslKeyPath: getSecret('sslkeypath'),\n    sslCertPath: getSecret('sslcertpath'),\n    sslCAPath: getSecret('sslcapath'),\n    dhParamPath: getSecret('dhparampath'),\n    // session\n    sessionSecret: getSecret('sessionsecret'),\n    imgur: {\n      clientID: getSecret('imgur_clientid')\n    },\n    s3: {\n      accessKeyId: getSecret('s3_acccessKeyId'),\n      secretAccessKey: getSecret('s3_secretAccessKey')\n    },\n    minio: {\n      accessKey: getSecret('minio_accessKey'),\n      secretKey: getSecret('minio_secretKey')\n    },\n    azure: {\n      connectionString: getSecret('azure_connectionString')\n    },\n    oauth2: {\n      clientID: getSecret('oauth2_clientID'),\n      clientSecret: getSecret('oauth2_clientSecret')\n    },\n    facebook: {\n      clientID: getSecret('facebook_clientID'),\n      clientSecret: getSecret('facebook_clientSecret')\n    },\n    twitter: {\n      consumerKey: getSecret('twitter_consumerKey'),\n      consumerSecret: getSecret('twitter_consumerSecret')\n    },\n    github: {\n      clientID: getSecret('github_clientID'),\n      clientSecret: getSecret('github_clientSecret')\n    },\n    gitlab: {\n      clientID: getSecret('gitlab_clientID'),\n      clientSecret: getSecret('gitlab_clientSecret')\n    },\n    mattermost: {\n      clientID: getSecret('mattermost_clientID'),\n      clientSecret: getSecret('mattermost_clientSecret')\n    },\n    dropbox: {\n      clientID: getSecret('dropbox_clientID'),\n      clientSecret: getSecret('dropbox_clientSecret'),\n      appKey: getSecret('dropbox_appKey')\n    },\n    google: {\n      clientID: getSecret('google_clientID'),\n      clientSecret: getSecret('google_clientSecret')\n    },\n    ldap: {\n      bindCredentials: getSecret('ldap_bindCredentials'),\n      tlsca: getSecret('ldap_tlsca')\n    },\n    saml: {\n      idpCert: getSecret('saml_idpCert')\n    }\n  }\n}\n"
  },
  {
    "path": "lib/config/enum.js",
    "content": "'use strict'\n\nexports.Environment = {\n  development: 'development',\n  production: 'production',\n  test: 'test'\n}\n\nexports.Permission = {\n  freely: 'freely',\n  editable: 'editable',\n  limited: 'limited',\n  locked: 'locked',\n  protected: 'protected',\n  private: 'private'\n}\n"
  },
  {
    "path": "lib/config/environment.js",
    "content": "'use strict'\n\nconst { toBooleanConfig, toArrayConfig, toIntegerConfig } = require('./utils')\n\nmodule.exports = {\n  sourceURL: process.env.CMD_SOURCE_URL,\n  domain: process.env.CMD_DOMAIN,\n  urlPath: process.env.CMD_URL_PATH,\n  host: process.env.CMD_HOST,\n  port: toIntegerConfig(process.env.CMD_PORT),\n  path: process.env.CMD_PATH,\n  loglevel: process.env.CMD_LOGLEVEL,\n  urlAddPort: toBooleanConfig(process.env.CMD_URL_ADDPORT),\n  useSSL: toBooleanConfig(process.env.CMD_USESSL),\n  hsts: {\n    enable: toBooleanConfig(process.env.CMD_HSTS_ENABLE),\n    maxAgeSeconds: toIntegerConfig(process.env.CMD_HSTS_MAX_AGE),\n    includeSubdomains: toBooleanConfig(process.env.CMD_HSTS_INCLUDE_SUBDOMAINS),\n    preload: toBooleanConfig(process.env.CMD_HSTS_PRELOAD)\n  },\n  csp: {\n    enable: toBooleanConfig(process.env.CMD_CSP_ENABLE),\n    reportURI: process.env.CMD_CSP_REPORTURI\n  },\n  protocolUseSSL: toBooleanConfig(process.env.CMD_PROTOCOL_USESSL),\n  allowOrigin: toArrayConfig(process.env.CMD_ALLOW_ORIGIN),\n  useCDN: toBooleanConfig(process.env.CMD_USECDN),\n  allowAnonymous: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS),\n  allowAnonymousEdits: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS_EDITS),\n  allowAnonymousViews: toBooleanConfig(process.env.CMD_ALLOW_ANONYMOUS_VIEWS),\n  allowFreeURL: toBooleanConfig(process.env.CMD_ALLOW_FREEURL),\n  forbiddenNoteIDs: toArrayConfig(process.env.CMD_FORBIDDEN_NOTE_IDS),\n  defaultPermission: process.env.CMD_DEFAULT_PERMISSION,\n  dbURL: process.env.CMD_DB_URL,\n  sessionSecret: process.env.CMD_SESSION_SECRET,\n  sessionLife: toIntegerConfig(process.env.CMD_SESSION_LIFE),\n  responseMaxLag: toIntegerConfig(process.env.CMD_RESPONSE_MAX_LAG),\n  privacyPolicyURL: process.env.CMD_PRIVACY_POLICY_URL,\n  imageUploadType: process.env.CMD_IMAGE_UPLOAD_TYPE,\n  imgur: {\n    clientID: process.env.CMD_IMGUR_CLIENTID\n  },\n  s3: {\n    accessKeyId: process.env.CMD_S3_ACCESS_KEY_ID,\n    secretAccessKey: process.env.CMD_S3_SECRET_ACCESS_KEY,\n    region: process.env.CMD_S3_REGION,\n    endpoint: process.env.CMD_S3_ENDPOINT,\n    baseURL: process.env.CMD_S3_BASEURL\n  },\n  minio: {\n    accessKey: process.env.CMD_MINIO_ACCESS_KEY,\n    secretKey: process.env.CMD_MINIO_SECRET_KEY,\n    endPoint: process.env.CMD_MINIO_ENDPOINT,\n    secure: toBooleanConfig(process.env.CMD_MINIO_SECURE),\n    port: toIntegerConfig(process.env.CMD_MINIO_PORT)\n  },\n  s3bucket: process.env.CMD_S3_BUCKET,\n  azure: {\n    connectionString: process.env.CMD_AZURE_CONNECTION_STRING,\n    container: process.env.CMD_AZURE_CONTAINER\n  },\n  facebook: {\n    clientID: process.env.CMD_FACEBOOK_CLIENTID,\n    clientSecret: process.env.CMD_FACEBOOK_CLIENTSECRET\n  },\n  twitter: {\n    consumerKey: process.env.CMD_TWITTER_CONSUMERKEY,\n    consumerSecret: process.env.CMD_TWITTER_CONSUMERSECRET\n  },\n  github: {\n    enterpriseURL: process.env.CMD_GITHUB_ENTERPRISE_URL,\n    clientID: process.env.CMD_GITHUB_CLIENTID,\n    clientSecret: process.env.CMD_GITHUB_CLIENTSECRET,\n    organizations: toArrayConfig(process.env.CMD_GITHUB_ORGANIZATIONS),\n    scopes: toArrayConfig(process.env.CMD_GITHUB_SCOPES)\n  },\n  bitbucket: {\n    clientID: process.env.CMD_BITBUCKET_CLIENTID,\n    clientSecret: process.env.CMD_BITBUCKET_CLIENTSECRET\n  },\n  gitlab: {\n    baseURL: process.env.CMD_GITLAB_BASEURL,\n    clientID: process.env.CMD_GITLAB_CLIENTID,\n    clientSecret: process.env.CMD_GITLAB_CLIENTSECRET,\n    scope: process.env.CMD_GITLAB_SCOPE\n  },\n  mattermost: {\n    baseURL: process.env.CMD_MATTERMOST_BASEURL,\n    clientID: process.env.CMD_MATTERMOST_CLIENTID,\n    clientSecret: process.env.CMD_MATTERMOST_CLIENTSECRET\n  },\n  oauth2: {\n    providerName: process.env.CMD_OAUTH2_PROVIDERNAME,\n    baseURL: process.env.CMD_OAUTH2_BASEURL,\n    clientID: process.env.CMD_OAUTH2_CLIENT_ID,\n    clientSecret: process.env.CMD_OAUTH2_CLIENT_SECRET,\n    authorizationURL: process.env.CMD_OAUTH2_AUTHORIZATION_URL,\n    tokenURL: process.env.CMD_OAUTH2_TOKEN_URL,\n    userProfileURL: process.env.CMD_OAUTH2_USER_PROFILE_URL,\n    scope: process.env.CMD_OAUTH2_SCOPE,\n    state: process.env.CMD_OAUTH2_STATE,\n    rolesClaim: process.env.CMD_OAUTH2_ROLES_CLAIM,\n    accessRole: process.env.CMD_OAUTH2_ACCESS_ROLE,\n    userProfileIdAttr: process.env.CMD_OAUTH2_USER_PROFILE_ID_ATTR,\n    userProfileUsernameAttr: process.env.CMD_OAUTH2_USER_PROFILE_USERNAME_ATTR,\n    userProfileDisplayNameAttr: process.env.CMD_OAUTH2_USER_PROFILE_DISPLAY_NAME_ATTR,\n    userProfileEmailAttr: process.env.CMD_OAUTH2_USER_PROFILE_EMAIL_ATTR,\n    userProfilePhotoAttr: process.env.CMD_OAUTH2_USER_PROFILE_PHOTO_ATTR\n  },\n  dropbox: {\n    clientID: process.env.CMD_DROPBOX_CLIENTID,\n    clientSecret: process.env.CMD_DROPBOX_CLIENTSECRET,\n    appKey: process.env.CMD_DROPBOX_APPKEY\n  },\n  google: {\n    clientID: process.env.CMD_GOOGLE_CLIENTID,\n    clientSecret: process.env.CMD_GOOGLE_CLIENTSECRET,\n    hostedDomain: process.env.CMD_GOOGLE_HOSTEDDOMAIN\n  },\n  ldap: {\n    providerName: process.env.CMD_LDAP_PROVIDERNAME,\n    url: process.env.CMD_LDAP_URL,\n    bindDn: process.env.CMD_LDAP_BINDDN,\n    bindCredentials: process.env.CMD_LDAP_BINDCREDENTIALS,\n    searchBase: process.env.CMD_LDAP_SEARCHBASE,\n    searchFilter: process.env.CMD_LDAP_SEARCHFILTER,\n    searchAttributes: toArrayConfig(process.env.CMD_LDAP_SEARCHATTRIBUTES),\n    usernameField: process.env.CMD_LDAP_USERNAMEFIELD,\n    useridField: process.env.CMD_LDAP_USERIDFIELD,\n    tlsca: process.env.CMD_LDAP_TLS_CA\n  },\n  saml: {\n    idpSsoUrl: process.env.CMD_SAML_IDPSSOURL,\n    idpCert: process.env.CMD_SAML_IDPCERT,\n    issuer: process.env.CMD_SAML_ISSUER,\n    identifierFormat: process.env.CMD_SAML_IDENTIFIERFORMAT,\n    disableRequestedAuthnContext: toBooleanConfig(process.env.CMD_SAML_DISABLEREQUESTEDAUTHNCONTEXT),\n    groupAttribute: process.env.CMD_SAML_GROUPATTRIBUTE,\n    externalGroups: toArrayConfig(process.env.CMD_SAML_EXTERNALGROUPS, '|', []),\n    requiredGroups: toArrayConfig(process.env.CMD_SAML_REQUIREDGROUPS, '|', []),\n    attribute: {\n      id: process.env.CMD_SAML_ATTRIBUTE_ID,\n      username: process.env.CMD_SAML_ATTRIBUTE_USERNAME,\n      email: process.env.CMD_SAML_ATTRIBUTE_EMAIL\n    }\n  },\n  plantuml: {\n    server: process.env.CMD_PLANTUML_SERVER\n  },\n  email: toBooleanConfig(process.env.CMD_EMAIL),\n  allowEmailRegister: toBooleanConfig(process.env.CMD_ALLOW_EMAIL_REGISTER),\n  allowGravatar: toBooleanConfig(process.env.CMD_ALLOW_GRAVATAR),\n  allowPDFExport: toBooleanConfig(process.env.CMD_ALLOW_PDF_EXPORT),\n  openID: toBooleanConfig(process.env.CMD_OPENID),\n  defaultUseHardbreak: toBooleanConfig(process.env.CMD_DEFAULT_USE_HARD_BREAK),\n  linkifyHeaderStyle: process.env.CMD_LINKIFY_HEADER_STYLE,\n  autoVersionCheck: toBooleanConfig(process.env.CMD_AUTO_VERSION_CHECK),\n  defaultTocDepth: toIntegerConfig(process.env.CMD_DEFAULT_TOC_DEPTH)\n}\n"
  },
  {
    "path": "lib/config/index.js",
    "content": "\n'use strict'\n\nconst crypto = require('crypto')\nconst fs = require('fs')\nconst path = require('path')\nconst { merge } = require('lodash')\nconst deepFreeze = require('deep-freeze')\nconst { Environment, Permission } = require('./enum')\nconst logger = require('../logger')\nconst { getGitCommit, getGitHubURL } = require('./utils')\n\nconst appRootPath = path.resolve(__dirname, '../../')\nconst env = process.env.NODE_ENV || Environment.development\nconst debugConfig = {\n  debug: (env === Environment.development)\n}\n\n// Get version string from package.json\nconst { version, repository } = require(path.join(appRootPath, 'package.json'))\n\nconst commitID = getGitCommit(appRootPath)\nconst sourceURL = getGitHubURL(repository.url, commitID || version)\nconst fullversion = commitID ? `${version}-${commitID}` : version\n\nconst packageConfig = {\n  version: version,\n  minimumCompatibleVersion: '0.5.0',\n  fullversion: fullversion,\n  sourceURL: sourceURL\n}\n\nconst configFilePath = path.resolve(appRootPath, process.env.CMD_CONFIG_FILE ||\n'config.json')\nconst fileConfig = fs.existsSync(configFilePath) ? require(configFilePath)[env] : undefined\n\nlet config = require('./default')\nmerge(config, require('./defaultSSL'))\nmerge(config, debugConfig)\nmerge(config, packageConfig)\nmerge(config, fileConfig)\nmerge(config, require('./environment'))\nmerge(config, require('./dockerSecret'))\n\nif (['debug', 'verbose', 'info', 'warn', 'error'].includes(config.loglevel)) {\n  logger.level = config.loglevel\n} else {\n  logger.error('Selected loglevel %s doesn\\'t exist, using default level \\'debug\\'. Available options: debug, verbose, info, warn, error', config.loglevel)\n}\n\n// load LDAP CA\nif (config.ldap.tlsca) {\n  const certificateAuthorities = config.ldap.tlsca.split(',')\n  const caContent = []\n  for (const ca of certificateAuthorities) {\n    if (fs.existsSync(ca)) {\n      caContent.push(fs.readFileSync(ca, 'utf8'))\n    }\n  }\n  const tlsOptions = {\n    ca: caContent\n  }\n  config.ldap.tlsOptions = config.ldap.tlsOptions ? Object.assign(config.ldap.tlsOptions, tlsOptions) : tlsOptions\n}\n\n// Permission\nconfig.permission = Permission\nlet defaultPermission = config.permission.editable\nif (!config.allowAnonymous && !config.allowAnonymousViews) {\n  delete config.permission.freely\n  delete config.permission.editable\n  delete config.permission.locked\n  defaultPermission = config.permission.limited\n} else if (!config.allowAnonymous && !config.allowAnonymousEdits) {\n  delete config.permission.freely\n}\nif (!(config.defaultPermission in config.permission)) {\n  config.defaultPermission = defaultPermission\n}\n\n// cache result, cannot change config in runtime!!!\nconfig.isStandardHTTPsPort = (function isStandardHTTPsPort () {\n  return config.useSSL && config.port === 443\n})()\nconfig.isStandardHTTPPort = (function isStandardHTTPPort () {\n  return !config.useSSL && config.port === 80\n})()\n\n// cache serverURL\nconfig.serverURL = (function getserverurl () {\n  var url = ''\n  if (config.domain) {\n    var protocol = config.protocolUseSSL ? 'https://' : 'http://'\n    url = protocol + config.domain\n    if (config.urlAddPort) {\n      if (!config.isStandardHTTPPort || !config.isStandardHTTPsPort) {\n        url += ':' + config.port\n      }\n    }\n  }\n  if (config.urlPath) {\n    url += '/' + config.urlPath\n  }\n  return url\n})()\n\nif (config.serverURL === '') {\n  logger.warn('Neither \\'domain\\' nor \\'CMD_DOMAIN\\' is configured. This can cause issues with various components.\\nHint: Make sure \\'protocolUseSSL\\' and \\'urlAddPort\\' or \\'CMD_PROTOCOL_USESSL\\' and \\'CMD_URL_ADDPORT\\' are configured properly.')\n}\n\nconfig.Environment = Environment\n\n// auth method\nconfig.isFacebookEnable = config.facebook.clientID && config.facebook.clientSecret\nconfig.isGoogleEnable = config.google.clientID && config.google.clientSecret\nconfig.isDropboxEnable = config.dropbox.clientID && config.dropbox.clientSecret\nconfig.isTwitterEnable = config.twitter.consumerKey && config.twitter.consumerSecret\nconfig.isEmailEnable = config.email\nconfig.isOpenIDEnable = config.openID\nconfig.isGitHubEnable = config.github.clientID && config.github.clientSecret\nconfig.isBitbucketEnable = config.bitbucket.clientID && config.bitbucket.clientSecret\nconfig.isGitLabEnable = config.gitlab.clientID && config.gitlab.clientSecret\nconfig.isMattermostEnable = config.mattermost.clientID && config.mattermost.clientSecret\nconfig.isLDAPEnable = config.ldap.url\nconfig.isSAMLEnable = config.saml.idpSsoUrl\nconfig.isOAuth2Enable = config.oauth2.clientID && config.oauth2.clientSecret\nconfig.isPDFExportEnable = config.allowPDFExport\n\n// Check gitlab api version\nif (config.gitlab && config.gitlab.version !== 'v4' && config.gitlab.version !== 'v3') {\n  logger.warn('config.js contains wrong version (' + config.gitlab.version + ') for gitlab api; it should be \\'v3\\' or \\'v4\\'. Defaulting to v4')\n  config.gitlab.version = 'v4'\n}\n// If gitlab scope is api, enable snippets Export/import\nconfig.isGitlabSnippetsEnable = (!config.gitlab.scope || config.gitlab.scope === 'api') && config.isGitLabEnable\n\n// Only update i18n files in development setups\nconfig.updateI18nFiles = (env === Environment.development)\n\n// merge legacy values\nconst keys = Object.keys(config)\nconst uppercase = /[A-Z]/\nfor (let i = keys.length; i--;) {\n  const lowercaseKey = keys[i].toLowerCase()\n  // if the config contains uppercase letters\n  // and a lowercase version of this setting exists\n  // and the config with uppercase is not set\n  // we set the new config using the old key.\n  if (uppercase.test(keys[i]) &&\n  config[lowercaseKey] !== undefined &&\n  fileConfig[keys[i]] === undefined) {\n    logger.warn('config.js contains deprecated lowercase setting for ' + keys[i] + '. Please change your config.js file to replace ' + lowercaseKey + ' with ' + keys[i])\n    config[keys[i]] = config[lowercaseKey]\n  }\n}\n\n// Notify users about the prefix change and inform them they use legacy prefix for environment variables\nif (Object.keys(process.env).toString().indexOf('HMD_') !== -1) {\n  logger.warn('Using legacy HMD prefix for environment variables. Please change your variables in future. For details see: https://hackmd.io/c/codimd-documentation/%2F%40codimd%2Fmigrate-2-0#1-Drop-old-environment-variables-support')\n}\n\n// Generate session secret if it stays on default values\nif (config.sessionSecret === 'secret') {\n  logger.warn('Session secret not set. Using random generated one. Please set `sessionSecret` in your config.js file. All users will be logged out.')\n  config.sessionSecret = crypto.randomBytes(Math.ceil(config.sessionSecretLen / 2)) // generate crypto graphic random number\n    .toString('hex') // convert to hexadecimal format\n    .slice(0, config.sessionSecretLen) // return required number of characters\n}\n\n// Validate upload upload providers\nif (['filesystem', 's3', 'minio', 'imgur', 'azure', 'lutim'].indexOf(config.imageUploadType) === -1) {\n  logger.error('\"imageuploadtype\" is not correctly set. Please use \"filesystem\", \"s3\", \"minio\", \"azure\", \"lutim\" or \"imgur\". Defaulting to \"filesystem\"')\n  config.imageUploadType = 'filesystem'\n}\n\n// figure out mime types for image uploads\nswitch (config.imageUploadType) {\n  case 'imgur':\n    config.allowedUploadMimeTypes = [\n      'image/jpeg',\n      'image/png',\n      'image/jpg',\n      'image/gif'\n    ]\n    break\n  default:\n    config.allowedUploadMimeTypes = [\n      'image/jpeg',\n      'image/png',\n      'image/jpg',\n      'image/gif',\n      'image/svg+xml',\n      'image/bmp',\n      'image/tiff'\n    ]\n}\n\n// generate correct path\nconfig.sslCAPath.forEach(function (capath, i, array) {\n  array[i] = path.resolve(appRootPath, capath)\n})\n\nconfig.appRootPath = appRootPath\nconfig.sslCertPath = path.resolve(appRootPath, config.sslCertPath)\nconfig.sslKeyPath = path.resolve(appRootPath, config.sslKeyPath)\nconfig.dhParamPath = path.resolve(appRootPath, config.dhParamPath)\nconfig.viewPath = path.resolve(appRootPath, config.viewPath)\nconfig.tmpPath = path.resolve(appRootPath, config.tmpPath)\nconfig.defaultNotePath = path.resolve(appRootPath, config.defaultNotePath)\nconfig.docsPath = path.resolve(appRootPath, config.docsPath)\nconfig.uploadsPath = path.resolve(appRootPath, config.uploadsPath)\n\n// make config readonly\nconfig = deepFreeze(config)\n\nmodule.exports = config\n"
  },
  {
    "path": "lib/config/utils.js",
    "content": "'use strict'\n\nconst fs = require('fs')\nconst path = require('path')\n\nexports.toBooleanConfig = function toBooleanConfig (configValue) {\n  if (configValue && typeof configValue === 'string') {\n    return (configValue === 'true')\n  }\n  return configValue\n}\n\nexports.toArrayConfig = function toArrayConfig (configValue, separator = ',', fallback) {\n  if (configValue && typeof configValue === 'string') {\n    return (configValue.split(separator).map(arrayItem => arrayItem.trim()))\n  }\n  return fallback\n}\n\nexports.toIntegerConfig = function toIntegerConfig (configValue) {\n  if (configValue && typeof configValue === 'string') {\n    return parseInt(configValue)\n  }\n  return configValue\n}\n\nexports.getGitCommit = function getGitCommit (repodir) {\n  if (!fs.existsSync(repodir + '/.git/HEAD')) {\n    return undefined\n  }\n  let reference = fs.readFileSync(repodir + '/.git/HEAD', 'utf8')\n  if (reference.startsWith('ref: ')) {\n    reference = reference.substr(5).replace('\\n', '')\n    reference = fs.readFileSync(path.resolve(repodir + '/.git', reference), 'utf8')\n  }\n  reference = reference.replace('\\n', '')\n  return reference\n}\n\nexports.getGitHubURL = function getGitHubURL (repo, reference) {\n  // if it's not a github reference, we handle handle that anyway\n  if (!repo.startsWith('https://github.com') && !repo.startsWith('git@github.com')) {\n    return repo\n  }\n  if (repo.startsWith('git@github.com') || repo.startsWith('ssh://git@github.com')) {\n    repo = repo.replace(/^(ssh:\\/\\/)?git@github.com:/, 'https://github.com/')\n  }\n\n  if (repo.endsWith('.git')) {\n    repo = repo.replace(/\\.git$/, '/')\n  } else if (!repo.endsWith('/')) {\n    repo = repo + '/'\n  }\n  return repo + 'tree/' + reference\n}\n"
  },
  {
    "path": "lib/csp.js",
    "content": "var config = require('./config')\nvar uuid = require('uuid')\n\nvar CspStrategy = {}\n\nvar defaultDirectives = {\n  defaultSrc: ['\\'self\\''],\n  scriptSrc: ['\\'self\\'', 'vimeo.com', 'https://gist.github.com', 'www.slideshare.net', 'https://query.yahooapis.com', '\\'unsafe-eval\\''],\n  // ^ TODO: Remove unsafe-eval - webpack script-loader issues https://github.com/hackmdio/codimd/issues/594\n  imgSrc: ['*', 'data:'],\n  styleSrc: ['\\'self\\'', '\\'unsafe-inline\\'', 'https://github.githubassets.com'], // unsafe-inline is required for some libs, plus used in views\n  fontSrc: ['\\'self\\'', 'data:', 'https://public.slidesharecdn.com'],\n  objectSrc: ['*'], // Chrome PDF viewer treats PDFs as objects :/\n  mediaSrc: ['*'],\n  childSrc: ['*'],\n  connectSrc: ['*']\n}\n\nvar dropboxDirectives = {\n  scriptSrc: ['https://www.dropbox.com']\n}\n\nvar cdnDirectives = {\n  scriptSrc: ['https://cdnjs.cloudflare.com', 'https://cdn.jsdelivr.net', 'https://cdn.mathjax.org'],\n  styleSrc: ['https://cdnjs.cloudflare.com', 'https://cdn.jsdelivr.net', 'https://fonts.googleapis.com'],\n  fontSrc: ['https://cdnjs.cloudflare.com', 'https://fonts.gstatic.com']\n}\n\nvar disqusDirectives = {\n  scriptSrc: ['https://disqus.com', 'https://*.disqus.com', 'https://*.disquscdn.com'],\n  styleSrc: ['https://*.disquscdn.com'],\n  fontSrc: ['https://*.disquscdn.com']\n}\n\nvar googleAnalyticsDirectives = {\n  scriptSrc: ['https://www.google-analytics.com']\n}\n\nCspStrategy.computeDirectives = function () {\n  var directives = {}\n  mergeDirectives(directives, config.csp.directives)\n  mergeDirectivesIf(config.csp.addDefaults, directives, defaultDirectives)\n  mergeDirectivesIf(config.useCDN, directives, cdnDirectives)\n  mergeDirectivesIf(config.dropbox && config.dropbox.appKey, directives, dropboxDirectives)\n  mergeDirectivesIf(config.csp.addDisqus, directives, disqusDirectives)\n  mergeDirectivesIf(config.csp.addGoogleAnalytics, directives, googleAnalyticsDirectives)\n  if (!areAllInlineScriptsAllowed(directives)) {\n    addInlineScriptExceptions(directives)\n  }\n  addUpgradeUnsafeRequestsOptionTo(directives)\n  addReportURI(directives)\n  return directives\n}\n\nfunction mergeDirectives (existingDirectives, newDirectives) {\n  for (var propertyName in newDirectives) {\n    var newDirective = newDirectives[propertyName]\n    if (newDirective) {\n      var existingDirective = existingDirectives[propertyName] || []\n      existingDirectives[propertyName] = existingDirective.concat(newDirective)\n    }\n  }\n}\n\nfunction mergeDirectivesIf (condition, existingDirectives, newDirectives) {\n  if (condition) {\n    mergeDirectives(existingDirectives, newDirectives)\n  }\n}\n\nfunction areAllInlineScriptsAllowed (directives) {\n  return directives.scriptSrc.indexOf('\\'unsafe-inline\\'') !== -1\n}\n\nfunction addInlineScriptExceptions (directives) {\n  directives.scriptSrc.push(getCspNonce)\n  // TODO: This is the SHA-256 hash of the inline script in build/reveal.js/plugins/notes/notes.html\n  // Any more clean solution appreciated.\n  directives.scriptSrc.push('\\'sha256-81acLZNZISnyGYZrSuoYhpzwDTTxi7vC1YM4uNxqWaM=\\'')\n}\n\nfunction getCspNonce (req, res) {\n  return \"'nonce-\" + res.locals.nonce + \"'\"\n}\n\nfunction addUpgradeUnsafeRequestsOptionTo (directives) {\n  if (config.csp.upgradeInsecureRequests === 'auto' && config.useSSL) {\n    directives.upgradeInsecureRequests = true\n  } else if (config.csp.upgradeInsecureRequests === true) {\n    directives.upgradeInsecureRequests = true\n  }\n}\n\nfunction addReportURI (directives) {\n  if (config.csp.reportURI) {\n    directives.reportUri = config.csp.reportURI\n  }\n}\n\nCspStrategy.addNonceToLocals = function (req, res, next) {\n  res.locals.nonce = uuid.v4()\n  next()\n}\n\nmodule.exports = CspStrategy\n"
  },
  {
    "path": "lib/errorPage/index.js",
    "content": "'use strict'\n\nconst config = require('../config')\nconst { responseError } = require('../response')\n\nexports.errorForbidden = (req, res) => {\n  if (req.user) {\n    return responseError(res, '403', 'Forbidden', 'oh no.')\n  }\n\n  req.flash('error', 'You are not allowed to access this page. Maybe try logging in?')\n  res.redirect(config.serverURL + '/')\n}\n\nexports.errorNotFound = (req, res) => {\n  responseError(res, '404', 'Not Found', 'oops.')\n}\n\nexports.errorInternalError = (req, res) => {\n  responseError(res, '500', 'Internal Error', 'wtf.')\n}\n"
  },
  {
    "path": "lib/history/index.js",
    "content": "'use strict'\n// history\n// external modules\nvar LZString = require('@hackmd/lz-string')\n\n// core\nvar config = require('../config')\nvar logger = require('../logger')\nvar response = require('../response')\nvar models = require('../models')\n\nfunction getHistory (userid, callback) {\n  models.User.findOne({\n    where: {\n      id: userid\n    }\n  }).then(function (user) {\n    if (!user) {\n      return callback(null, null)\n    }\n    var history = {}\n    if (user.history) {\n      history = JSON.parse(user.history)\n      // migrate LZString encoded note id to base64url encoded note id\n      for (let i = 0, l = history.length; i < l; i++) {\n        // Calculate minimal string length for an UUID that is encoded\n        // base64 encoded and optimize comparsion by using -1\n        // this should make a lot of LZ-String parsing errors obsolete\n        // as we can assume that a nodeId that is 48 chars or longer is a\n        // noteID.\n        const base64UuidLength = ((4 * 36) / 3) - 1\n        if (!(history[i].id.length > base64UuidLength)) {\n          continue\n        }\n        try {\n          const id = LZString.decompressFromBase64(history[i].id)\n          if (id && models.Note.checkNoteIdValid(id)) {\n            history[i].id = models.Note.encodeNoteId(id)\n          }\n        } catch (err) {\n          // most error here comes from LZString, ignore\n          if (err.message === 'Cannot read property \\'charAt\\' of undefined') {\n            logger.warning('Looks like we can not decode \"' + history[i].id + '\" with LZString. Can be ignored.')\n          } else {\n            logger.error(err)\n          }\n        }\n      }\n      history = parseHistoryToObject(history)\n    }\n    if (config.debug) {\n      logger.info('read history success: ' + user.id)\n    }\n    return callback(null, history)\n  }).catch(function (err) {\n    logger.error('read history failed: ' + err)\n    return callback(err, null)\n  })\n}\n\nfunction setHistory (userid, history, callback) {\n  models.User.update({\n    history: JSON.stringify(parseHistoryToArray(history))\n  }, {\n    where: {\n      id: userid\n    }\n  }).then(function (count) {\n    return callback(null, count)\n  }).catch(function (err) {\n    logger.error('set history failed: ' + err)\n    return callback(err, null)\n  })\n}\n\nfunction updateHistory (userid, noteId, document, time) {\n  if (userid && noteId && typeof document !== 'undefined') {\n    getHistory(userid, function (err, history) {\n      if (err || !history) return\n      if (!history[noteId]) {\n        history[noteId] = {}\n      }\n      var noteHistory = history[noteId]\n      var noteInfo = models.Note.parseNoteInfo(document)\n      noteHistory.id = noteId\n      noteHistory.text = noteInfo.title\n      noteHistory.time = time || Date.now()\n      noteHistory.tags = noteInfo.tags\n      setHistory(userid, history, function (err, count) {\n        if (err) {\n          logger.log(err)\n        }\n      })\n    })\n  }\n}\n\nfunction parseHistoryToArray (history) {\n  var _history = []\n  Object.keys(history).forEach(function (key) {\n    var item = history[key]\n    _history.push(item)\n  })\n  return _history\n}\n\nfunction parseHistoryToObject (history) {\n  var _history = {}\n  for (var i = 0, l = history.length; i < l; i++) {\n    var item = history[i]\n    _history[item.id] = item\n  }\n  return _history\n}\n\nfunction historyGet (req, res) {\n  if (req.isAuthenticated()) {\n    getHistory(req.user.id, function (err, history) {\n      if (err) return response.errorInternalError(req, res)\n      if (!history) return response.errorNotFound(req, res)\n      res.send({\n        history: parseHistoryToArray(history)\n      })\n    })\n  } else {\n    return response.errorForbidden(req, res)\n  }\n}\n\nfunction historyPost (req, res) {\n  if (req.isAuthenticated()) {\n    var noteId = req.params.noteId\n    if (!noteId) {\n      if (typeof req.body.history === 'undefined') return response.errorBadRequest(req, res)\n      if (config.debug) { logger.info('SERVER received history from [' + req.user.id + ']: ' + req.body.history) }\n      try {\n        var history = JSON.parse(req.body.history)\n      } catch (err) {\n        return response.errorBadRequest(req, res)\n      }\n      if (Array.isArray(history)) {\n        setHistory(req.user.id, history, function (err, count) {\n          if (err) return response.errorInternalError(req, res)\n          res.end()\n        })\n      } else {\n        return response.errorBadRequest(req, res)\n      }\n    } else {\n      if (typeof req.body.pinned === 'undefined') return response.errorBadRequest(req, res)\n      getHistory(req.user.id, function (err, history) {\n        if (err) return response.errorInternalError(req, res)\n        if (!history) return response.errorNotFound(req, res)\n        if (!history[noteId]) return response.errorNotFound(req, res)\n        if (req.body.pinned === 'true' || req.body.pinned === 'false') {\n          history[noteId].pinned = (req.body.pinned === 'true')\n          setHistory(req.user.id, history, function (err, count) {\n            if (err) return response.errorInternalError(req, res)\n            res.end()\n          })\n        } else {\n          return response.errorBadRequest(req, res)\n        }\n      })\n    }\n  } else {\n    return response.errorForbidden(req, res)\n  }\n}\n\nfunction historyDelete (req, res) {\n  if (req.isAuthenticated()) {\n    var noteId = req.params.noteId\n    if (!noteId) {\n      setHistory(req.user.id, [], function (err, count) {\n        if (err) return response.errorInternalError(req, res)\n        res.end()\n      })\n    } else {\n      getHistory(req.user.id, function (err, history) {\n        if (err) return response.errorInternalError(req, res)\n        if (!history) return response.errorNotFound(req, res)\n        delete history[noteId]\n        setHistory(req.user.id, history, function (err, count) {\n          if (err) return response.errorInternalError(req, res)\n          res.end()\n        })\n      })\n    }\n  } else {\n    return response.errorForbidden(req, res)\n  }\n}\n\n// public\nexports.historyGet = historyGet\nexports.historyPost = historyPost\nexports.historyDelete = historyDelete\nexports.updateHistory = updateHistory\n"
  },
  {
    "path": "lib/homepage/index.js",
    "content": "'use strict'\n\nconst fs = require('fs')\nconst path = require('path')\nconst config = require('../config')\nconst { User } = require('../models')\nconst logger = require('../logger')\n\nexports.showIndex = async (req, res) => {\n  const isLogin = req.isAuthenticated()\n  const deleteToken = ''\n\n  const data = {\n    signin: isLogin,\n    infoMessage: req.flash('info'),\n    errorMessage: req.flash('error'),\n    privacyStatement: fs.existsSync(path.join(config.docsPath, 'privacy.md')),\n    termsOfUse: fs.existsSync(path.join(config.docsPath, 'terms-of-use.md')),\n    deleteToken: deleteToken,\n    csrfToken: req.csrfToken()\n  }\n\n  if (!isLogin) {\n    return res.render('index.ejs', data)\n  }\n\n  const user = await User.findOne({\n    where: {\n      id: req.user.id\n    }\n  })\n  if (user) {\n    data.deleteToken = user.deleteToken\n    return res.render('index.ejs', data)\n  }\n\n  logger.error(`error: user not found with id ${req.user.id}`)\n  return res.render('index.ejs', data)\n}\n"
  },
  {
    "path": "lib/imageRouter/azure.js",
    "content": "'use strict'\nconst path = require('path')\n\nconst config = require('../config')\nconst logger = require('../logger')\n\nconst azure = require('azure-storage')\n\nexports.uploadImage = function (imagePath, callback) {\n  if (!imagePath || typeof imagePath !== 'string') {\n    callback(new Error('Image path is missing or wrong'), null)\n    return\n  }\n\n  if (!callback || typeof callback !== 'function') {\n    logger.error('Callback has to be a function')\n    return\n  }\n\n  var azureBlobService = azure.createBlobService(config.azure.connectionString)\n\n  azureBlobService.createContainerIfNotExists(config.azure.container, { publicAccessLevel: 'blob' }, function (err, result, response) {\n    if (err) {\n      callback(new Error(err.message), null)\n    } else {\n      azureBlobService.createBlockBlobFromLocalFile(config.azure.container, path.basename(imagePath), imagePath, function (err, result, response) {\n        if (err) {\n          callback(new Error(err.message), null)\n        } else {\n          callback(null, azureBlobService.getUrl(config.azure.container, result.name))\n        }\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "lib/imageRouter/filesystem.js",
    "content": "'use strict'\n\nconst crypto = require('crypto')\nconst fs = require('fs')\nconst URL = require('url').URL\nconst path = require('path')\n\nconst config = require('../config')\nconst logger = require('../logger')\n\n/**\n * generate a random filename for uploaded image\n */\nfunction randomFilename () {\n  const buf = crypto.randomBytes(16)\n  return `upload_${buf.toString('hex')}`\n}\n\n/**\n * pick a filename not exist in filesystem\n * maximum attempt 5 times\n */\nfunction pickFilename (defaultFilename) {\n  let retryCounter = 5\n  const extname = path.extname(defaultFilename)\n  let filename = `${randomFilename()}${extname}`\n  while (retryCounter-- > 0) {\n    if (fs.existsSync(path.join(config.uploadsPath, filename))) {\n      filename = `${randomFilename()}${extname}`\n      continue\n    }\n    return filename\n  }\n  throw new Error('file exists.')\n}\n\nexports.uploadImage = function (imagePath, callback) {\n  if (!imagePath || typeof imagePath !== 'string') {\n    callback(new Error('Image path is missing or wrong'), null)\n    return\n  }\n\n  if (!callback || typeof callback !== 'function') {\n    logger.error('Callback has to be a function')\n    return\n  }\n\n  let filename = path.basename(imagePath)\n  try {\n    filename = pickFilename(path.basename(imagePath))\n  } catch (e) {\n    return callback(e, null)\n  }\n\n  try {\n    fs.copyFileSync(imagePath, path.join(config.uploadsPath, filename))\n  } catch (e) {\n    return callback(e, null)\n  }\n\n  let url\n  try {\n    url = (new URL(filename, config.serverURL + '/uploads/')).href\n  } catch (e) {\n    url = config.serverURL + '/uploads/' + filename\n  }\n\n  callback(null, url)\n}\n"
  },
  {
    "path": "lib/imageRouter/imgur.js",
    "content": "'use strict'\nconst config = require('../config')\nconst logger = require('../logger')\n\nconst imgur = require('@hackmd/imgur')\n\nexports.uploadImage = function (imagePath, callback) {\n  if (!imagePath || typeof imagePath !== 'string') {\n    callback(new Error('Image path is missing or wrong'), null)\n    return\n  }\n\n  if (!callback || typeof callback !== 'function') {\n    logger.error('Callback has to be a function')\n    return\n  }\n\n  imgur.setClientId(config.imgur.clientID)\n  imgur.uploadFile(imagePath)\n    .then(function (json) {\n      if (config.debug) {\n        logger.info('SERVER uploadimage success: ' + JSON.stringify(json))\n      }\n      callback(null, json.data.link.replace(/^http:\\/\\//i, 'https://'))\n    }).catch(function (err) {\n      callback(new Error(err), null)\n    })\n}\n"
  },
  {
    "path": "lib/imageRouter/index.js",
    "content": "'use strict'\n\nconst fs = require('fs')\nconst path = require('path')\nconst Router = require('express').Router\nconst formidable = require('formidable')\n\nconst readChunk = require('read-chunk')\nconst imageType = require('image-type')\nconst mime = require('mime-types')\n\nconst config = require('../config')\nconst logger = require('../logger')\nconst response = require('../response')\n\nconst imageRouter = module.exports = Router()\n\nfunction checkImageValid (filepath) {\n  try {\n    const buffer = readChunk.sync(filepath, 0, 12)\n    /** @type {{ ext: string, mime: string } | null} */\n    const mimetypeFromBuf = imageType(buffer)\n    const mimeTypeFromExt = mime.lookup(path.extname(filepath))\n\n    return mimetypeFromBuf && config.allowedUploadMimeTypes.includes(mimetypeFromBuf.mime) &&\n          mimeTypeFromExt && config.allowedUploadMimeTypes.includes(mimeTypeFromExt)\n  } catch (err) {\n    logger.error(err)\n    return false\n  }\n}\n\n// upload image\nimageRouter.post('/uploadimage', function (req, res) {\n  var form = new formidable.IncomingForm({\n    keepExtensions: true\n  })\n\n  form.parse(req, function (err, fields, files) {\n    if (err || !files.image || !files.image.filepath) {\n      response.errorForbidden(req, res)\n    } else {\n      if (config.debug) {\n        logger.info('SERVER received uploadimage: ' + JSON.stringify(files.image))\n      }\n\n      if (!checkImageValid(files.image.filepath)) {\n        return response.errorForbidden(req, res)\n      }\n\n      const uploadProvider = require('./' + config.imageUploadType)\n      uploadProvider.uploadImage(files.image.filepath, function (err, url) {\n        // remove temporary upload file, and ignore any error\n        fs.unlink(files.image.filepath, () => {})\n        if (err !== null) {\n          logger.error(err)\n          return res.status(500).end('upload image error')\n        }\n        res.send({\n          link: url\n        })\n      })\n    }\n  })\n})\n"
  },
  {
    "path": "lib/imageRouter/lutim.js",
    "content": "'use strict'\nconst config = require('../config')\nconst logger = require('../logger')\n\nconst lutim = require('lutim')\n\nexports.uploadImage = function (imagePath, callback) {\n  if (!imagePath || typeof imagePath !== 'string') {\n    callback(new Error('Image path is missing or wrong'), null)\n    return\n  }\n\n  if (!callback || typeof callback !== 'function') {\n    logger.error('Callback has to be a function')\n    return\n  }\n\n  if (config.lutim && config.lutim.url) {\n    lutim.setAPIUrl(config.lutim.url)\n  }\n\n  lutim.uploadImage(imagePath)\n    .then(function (json) {\n      if (config.debug) {\n        logger.info('SERVER uploadimage success: ' + JSON.stringify(json))\n      }\n      callback(null, lutim.getAPIUrl() + json.msg.short)\n    }).catch(function (err) {\n      callback(new Error(err), null)\n    })\n}\n"
  },
  {
    "path": "lib/imageRouter/minio.js",
    "content": "'use strict'\nconst fs = require('fs')\nconst path = require('path')\n\nconst config = require('../config')\nconst { getImageMimeType } = require('../utils')\nconst logger = require('../logger')\n\nconst Minio = require('minio')\nconst minioClient = new Minio.Client({\n  endPoint: config.minio.endPoint,\n  port: config.minio.port,\n  useSSL: config.minio.secure,\n  accessKey: config.minio.accessKey,\n  secretKey: config.minio.secretKey\n})\n\nexports.uploadImage = function (imagePath, callback) {\n  if (!imagePath || typeof imagePath !== 'string') {\n    callback(new Error('Image path is missing or wrong'), null)\n    return\n  }\n\n  if (!callback || typeof callback !== 'function') {\n    logger.error('Callback has to be a function')\n    return\n  }\n\n  fs.readFile(imagePath, function (err, buffer) {\n    if (err) {\n      callback(new Error(err), null)\n      return\n    }\n\n    const key = path.join('uploads', path.basename(imagePath))\n    const protocol = config.minio.secure ? 'https' : 'http'\n\n    minioClient.putObject(config.s3bucket, key, buffer, buffer.size, getImageMimeType(imagePath), function (err, data) {\n      if (err) {\n        callback(new Error(err), null)\n        return\n      }\n      const hidePort = [80, 443].includes(config.minio.port)\n      const urlPort = hidePort ? '' : `:${config.minio.port}`\n      callback(null, `${protocol}://${config.minio.endPoint}${urlPort}/${config.s3bucket}/${key}`)\n    })\n  })\n}\n"
  },
  {
    "path": "lib/imageRouter/s3.js",
    "content": "'use strict'\nconst fs = require('fs')\nconst path = require('path')\n\nconst config = require('../config')\nconst { getImageMimeType } = require('../utils')\nconst logger = require('../logger')\n\nconst { S3Client } = require('@aws-sdk/client-s3-node/S3Client')\nconst { PutObjectCommand } = require('@aws-sdk/client-s3-node/commands/PutObjectCommand')\n\nconst credentials = {\n  accessKeyId: config.s3.accessKeyId,\n  secretAccessKey: config.s3.secretAccessKey\n}\n\nconst s3 = new S3Client({\n  credentials,\n  region: config.s3.region,\n  endpoint: config.s3.endpoint\n})\n\nexports.uploadImage = function (imagePath, callback) {\n  if (!imagePath || typeof imagePath !== 'string') {\n    callback(new Error('Image path is missing or wrong'), null)\n    return\n  }\n\n  if (!callback || typeof callback !== 'function') {\n    logger.error('Callback has to be a function')\n    return\n  }\n\n  fs.readFile(imagePath, function (err, buffer) {\n    if (err) {\n      callback(new Error(err), null)\n      return\n    }\n    const params = {\n      Bucket: config.s3bucket,\n      Key: path.join('uploads', path.basename(imagePath)),\n      Body: buffer,\n      ACL: 'public-read'\n    }\n    const mimeType = getImageMimeType(imagePath)\n    if (mimeType) { params.ContentType = mimeType }\n\n    const command = new PutObjectCommand(params)\n\n    s3.send(command).then(data => {\n      // default scheme settings to https\n      let s3Endpoint = 'https://s3.amazonaws.com'\n      if (config.s3.region && config.s3.region !== 'us-east-1') {\n        s3Endpoint = `https://s3-${config.s3.region}.amazonaws.com`\n      }\n      // rewrite endpoint from config\n      if (config.s3.endpoint) {\n        s3Endpoint = config.s3.endpoint\n      }\n      if (config.s3.baseURL) {\n        callback(null, `${config.s3.baseURL}/${params.Key}`)\n      } else {\n        callback(null, `${s3Endpoint}/${config.s3bucket}/${params.Key}`)\n      }\n    }).catch(err => {\n      if (err) {\n        callback(new Error(err), null)\n      }\n    })\n  })\n}\n"
  },
  {
    "path": "lib/letter-avatars.js",
    "content": "'use strict'\n// external modules\nconst crypto = require('crypto')\nconst randomcolor = require('randomcolor')\nconst config = require('./config')\n\n// core\nexports.generateAvatar = function (name) {\n  const color = randomcolor({\n    seed: name,\n    luminosity: 'dark'\n  })\n  const letter = name.substring(0, 1).toUpperCase()\n\n  let svg = '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>'\n  svg += '<svg xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns=\"http://www.w3.org/2000/svg\" height=\"96\" width=\"96\" version=\"1.1\" viewBox=\"0 0 96 96\">'\n  svg += '<g>'\n  svg += '<rect width=\"96\" height=\"96\" fill=\"' + color + '\" />'\n  svg += '<text font-size=\"64px\" font-family=\"sans-serif\" text-anchor=\"middle\" fill=\"#ffffff\">'\n  svg += '<tspan x=\"48\" y=\"72\" stroke-width=\".26458px\" fill=\"#ffffff\">' + letter + '</tspan>'\n  svg += '</text>'\n  svg += '</g>'\n  svg += '</svg>'\n\n  return svg\n}\n\nexports.generateAvatarURL = function (name, email = '', big = true) {\n  let photo\n  if (typeof email !== 'string') {\n    email = '' + name + '@example.com'\n  }\n  name = encodeURIComponent(name)\n\n  const hash = crypto.createHash('md5')\n  hash.update(email.toLowerCase())\n  const hexDigest = hash.digest('hex')\n\n  if (email !== '' && config.allowGravatar) {\n    photo = 'https://www.gravatar.com/avatar/' + hexDigest\n    if (big) {\n      photo += '?s=400'\n    } else {\n      photo += '?s=96'\n    }\n  } else {\n    photo = config.serverURL + '/user/' + (name || email.substring(0, email.lastIndexOf('@')) || hexDigest) + '/avatar.svg'\n  }\n  return photo\n}\n"
  },
  {
    "path": "lib/logger.js",
    "content": "'use strict'\nconst { createLogger, format, transports } = require('winston')\n\nconst logger = createLogger({\n  level: 'debug',\n  format: format.combine(\n    format.uncolorize(),\n    format.timestamp(),\n    format.align(),\n    format.splat(),\n    format.printf(info => `${info.timestamp} ${info.level}: ${info.message}`)\n  ),\n  transports: [\n    new transports.Console({\n      handleExceptions: true\n    })\n  ],\n  exitOnError: false\n})\n\nlogger.stream = {\n  write: function (message, encoding) {\n    logger.info(message)\n  }\n}\n\nmodule.exports = logger\n"
  },
  {
    "path": "lib/metrics.js",
    "content": "'use strict'\n\nconst { Router } = require('express')\n\nconst { wrap } = require('./utils')\n\n// load controller\nconst statusController = require('./status')\nconst appRouter = Router()\n\n// register route\nappRouter.get('/status', wrap(statusController.getStatus))\nappRouter.get('/metrics/codimd', wrap(statusController.getMetrics))\n\nexports.router = appRouter\n"
  },
  {
    "path": "lib/middleware/checkURIValid.js",
    "content": "'use strict'\n\nconst logger = require('../logger')\nconst response = require('../response')\n\nmodule.exports = function (req, res, next) {\n  try {\n    decodeURIComponent(req.path)\n  } catch (err) {\n    logger.error(err)\n    return response.errorBadRequest(req, res)\n  }\n  next()\n}\n"
  },
  {
    "path": "lib/middleware/codiMDVersion.js",
    "content": "'use strict'\n\nconst config = require('../config')\n\nmodule.exports = function (req, res, next) {\n  res.set({\n    'CodiMD-Version': config.version\n  })\n  return next()\n}\n"
  },
  {
    "path": "lib/middleware/redirectWithoutTrailingSlashes.js",
    "content": "'use strict'\n\nconst config = require('../config')\n\nmodule.exports = function (req, res, next) {\n  if (req.method === 'GET' && req.path.substr(-1) === '/' && req.path.length > 1) {\n    const queryString = req.url.slice(req.path.length)\n    const urlPath = req.path.slice(0, -1)\n    let serverURL = config.serverURL\n    if (config.urlPath) {\n      serverURL = serverURL.slice(0, -(config.urlPath.length + 1))\n    }\n    res.redirect(301, serverURL + urlPath + queryString)\n  } else {\n    next()\n  }\n}\n"
  },
  {
    "path": "lib/middleware/tooBusy.js",
    "content": "'use strict'\n\nconst toobusy = require('toobusy-js')\n\nconst config = require('../config')\nconst response = require('../response')\n\ntoobusy.maxLag(config.responseMaxLag)\n\nmodule.exports = function (req, res, next) {\n  if (toobusy()) {\n    response.errorServiceUnavailable(req, res)\n  } else {\n    next()\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20150504155329-create-users.js",
    "content": "'use strict'\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.createTable('Users', {\n      id: {\n        type: Sequelize.UUID,\n        primaryKey: true,\n        defaultValue: Sequelize.UUIDV4\n      },\n      profileid: {\n        type: Sequelize.STRING,\n        unique: true\n      },\n      profile: Sequelize.TEXT,\n      history: Sequelize.TEXT,\n      createdAt: Sequelize.DATE,\n      updatedAt: Sequelize.DATE\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.dropTable('Users')\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20150508114741-create-notes.js",
    "content": "'use strict'\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.createTable('Notes', {\n      id: {\n        type: Sequelize.UUID,\n        primaryKey: true,\n        defaultValue: Sequelize.UUIDV4\n      },\n      ownerId: Sequelize.UUID,\n      content: Sequelize.TEXT,\n      title: Sequelize.STRING,\n      createdAt: Sequelize.DATE,\n      updatedAt: Sequelize.DATE\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.dropTable('Notes')\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20150515125813-create-temp.js",
    "content": "'use strict'\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.createTable('Temp', {\n      id: {\n        type: Sequelize.STRING,\n        primaryKey: true\n      },\n      date: Sequelize.TEXT,\n      createdAt: Sequelize.DATE,\n      updatedAt: Sequelize.DATE\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.dropTable('Temp')\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20150702001020-update-to-0_3_1.js",
    "content": "'use strict'\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.addColumn('Notes', 'shortid', {\n      type: Sequelize.STRING,\n      defaultValue: '0000000000',\n      allowNull: false\n    }).then(function () {\n      return queryInterface.addIndex('Notes', ['shortid'], {\n        indicesType: 'UNIQUE'\n      })\n    }).then(function () {\n      return queryInterface.addColumn('Notes', 'permission', {\n        type: Sequelize.STRING,\n        defaultValue: 'private',\n        allowNull: false\n      })\n    }).then(function () {\n      return queryInterface.addColumn('Notes', 'viewcount', {\n        type: Sequelize.INTEGER,\n        defaultValue: 0\n      })\n    }).catch(function (error) {\n      if (error.message === 'SQLITE_ERROR: duplicate column name: shortid' || error.message === \"ER_DUP_FIELDNAME: Duplicate column name 'shortid'\" || error.message === 'column \"shortid\" of relation \"Notes\" already exists') {\n        console.log('Migration has already run… ignoring.')\n      } else {\n        throw error\n      }\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.removeColumn('Notes', 'viewcount')\n      .then(function () {\n        return queryInterface.removeColumn('Notes', 'permission')\n      })\n      .then(function () {\n        return queryInterface.removeIndex('Notes', ['shortid'])\n      })\n      .then(function () {\n        return queryInterface.removeColumn('Notes', 'shortid')\n      })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20150915153700-change-notes-title-to-text.js",
    "content": "'use strict'\nconst isSQLite = require('../utils').isSQLite\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.changeColumn('Notes', 'title', {\n      type: Sequelize.TEXT\n    }).then(function () {\n      if (isSQLite(queryInterface.sequelize)) {\n        // manual added index will be removed in sqlite\n        return queryInterface.addIndex('Notes', ['shortid'])\n      }\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.changeColumn('Notes', 'title', {\n      type: Sequelize.STRING\n    }).then(function () {\n      if (isSQLite(queryInterface.sequelize)) {\n        // manual added index will be removed in sqlite\n        return queryInterface.addIndex('Notes', ['shortid'])\n      }\n    })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20160112220142-note-add-lastchange.js",
    "content": "'use strict'\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.addColumn('Notes', 'lastchangeuserId', {\n      type: Sequelize.UUID\n    }).then(function () {\n      return queryInterface.addColumn('Notes', 'lastchangeAt', {\n        type: Sequelize.DATE\n      })\n    }).catch(function (error) {\n      if (error.message === 'SQLITE_ERROR: duplicate column name: lastchangeuserId' || error.message === \"ER_DUP_FIELDNAME: Duplicate column name 'lastchangeuserId'\" || error.message === 'column \"lastchangeuserId\" of relation \"Notes\" already exists') {\n        console.log('Migration has already run… ignoring.')\n      } else {\n        throw error\n      }\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.removeColumn('Notes', 'lastchangeAt')\n      .then(function () {\n        return queryInterface.removeColumn('Notes', 'lastchangeuserId')\n      })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20160420180355-note-add-alias.js",
    "content": "'use strict'\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.addColumn('Notes', 'alias', {\n      type: Sequelize.STRING\n    }).then(function () {\n      return queryInterface.addIndex('Notes', ['alias'], {\n        indicesType: 'UNIQUE'\n      })\n    }).catch(function (error) {\n      if (error.message === 'SQLITE_ERROR: duplicate column name: alias' || error.message === \"ER_DUP_FIELDNAME: Duplicate column name 'alias'\" || error.message === 'column \"alias\" of relation \"Notes\" already exists') {\n        console.log('Migration has already run… ignoring.')\n      } else {\n        throw error\n      }\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.removeColumn('Notes', 'alias').then(function () {\n      return queryInterface.removeIndex('Notes', ['alias'])\n    })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20160515114000-user-add-tokens.js",
    "content": "'use strict'\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.addColumn('Users', 'accessToken', Sequelize.STRING).then(function () {\n      return queryInterface.addColumn('Users', 'refreshToken', Sequelize.STRING)\n    }).catch(function (error) {\n      if (error.message === 'SQLITE_ERROR: duplicate column name: accessToken' || error.message === \"ER_DUP_FIELDNAME: Duplicate column name 'accessToken'\" || error.message === 'column \"accessToken\" of relation \"Users\" already exists') {\n        console.log('Migration has already run… ignoring.')\n      } else {\n        throw error\n      }\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.removeColumn('Users', 'accessToken').then(function () {\n      return queryInterface.removeColumn('Users', 'refreshToken')\n    })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20160607060246-support-revision.js",
    "content": "'use strict'\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.addColumn('Notes', 'savedAt', Sequelize.DATE).then(function () {\n      return queryInterface.createTable('Revisions', {\n        id: {\n          type: Sequelize.UUID,\n          primaryKey: true\n        },\n        noteId: Sequelize.UUID,\n        patch: Sequelize.TEXT,\n        lastContent: Sequelize.TEXT,\n        content: Sequelize.TEXT,\n        length: Sequelize.INTEGER,\n        createdAt: Sequelize.DATE,\n        updatedAt: Sequelize.DATE\n      })\n    }).catch(function (error) {\n      if (error.message === 'SQLITE_ERROR: duplicate column name: savedAt' | error.message === \"ER_DUP_FIELDNAME: Duplicate column name 'savedAt'\" || error.message === 'column \"savedAt\" of relation \"Notes\" already exists') {\n        console.log('Migration has already run… ignoring.')\n      } else {\n        throw error\n      }\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.dropTable('Revisions').then(function () {\n      return queryInterface.removeColumn('Notes', 'savedAt')\n    })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20160703062241-support-authorship.js",
    "content": "'use strict'\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.addColumn('Notes', 'authorship', Sequelize.TEXT).then(function () {\n      return queryInterface.addColumn('Revisions', 'authorship', Sequelize.TEXT)\n    }).then(function () {\n      return queryInterface.createTable('Authors', {\n        id: {\n          type: Sequelize.INTEGER,\n          primaryKey: true,\n          autoIncrement: true\n        },\n        color: Sequelize.STRING,\n        noteId: Sequelize.UUID,\n        userId: Sequelize.UUID,\n        createdAt: Sequelize.DATE,\n        updatedAt: Sequelize.DATE\n      })\n    }).catch(function (error) {\n      if (error.message === 'SQLITE_ERROR: duplicate column name: authorship' || error.message === \"ER_DUP_FIELDNAME: Duplicate column name 'authorship'\" || error.message === 'column \"authorship\" of relation \"Notes\" already exists') {\n        console.log('Migration has already run… ignoring.')\n      } else {\n        throw error\n      }\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.dropTable('Authors').then(function () {\n      return queryInterface.removeColumn('Revisions', 'authorship')\n    }).then(function () {\n      return queryInterface.removeColumn('Notes', 'authorship')\n    })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20161009040430-support-delete-note.js",
    "content": "'use strict'\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.addColumn('Notes', 'deletedAt', Sequelize.DATE).catch(function (error) {\n      if (error.message === 'SQLITE_ERROR: duplicate column name: deletedAt' || error.message === \"ER_DUP_FIELDNAME: Duplicate column name 'deletedAt'\" || error.message === 'column \"deletedAt\" of relation \"Notes\" already exists') {\n        console.log('Migration has already run… ignoring.')\n      } else {\n        throw error\n      }\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.removeColumn('Notes', 'deletedAt')\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20161201050312-support-email-signin.js",
    "content": "'use strict'\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.addColumn('Users', 'email', Sequelize.TEXT).then(function () {\n      return queryInterface.addColumn('Users', 'password', Sequelize.TEXT).catch(function (error) {\n        if (error.message === \"ER_DUP_FIELDNAME: Duplicate column name 'password'\" || error.message === 'column \"password\" of relation \"Users\" already exists') {\n          console.log('Migration has already run… ignoring.')\n        } else {\n          throw error\n        }\n      })\n    }).catch(function (error) {\n      if (error.message === 'SQLITE_ERROR: duplicate column name: email' || error.message === \"ER_DUP_FIELDNAME: Duplicate column name 'email'\" || error.message === 'column \"email\" of relation \"Users\" already exists') {\n        console.log('Migration has already run… ignoring.')\n      } else {\n        throw error\n      }\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.removeColumn('Users', 'email').then(function () {\n      return queryInterface.removeColumn('Users', 'password')\n    })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20171009121200-longtext-for-mysql.js",
    "content": "'use strict'\nmodule.exports = {\n  up: async function (queryInterface, Sequelize) {\n    await queryInterface.changeColumn('Notes', 'content', { type: Sequelize.TEXT('long') })\n    await queryInterface.changeColumn('Revisions', 'patch', { type: Sequelize.TEXT('long') })\n    await queryInterface.changeColumn('Revisions', 'content', { type: Sequelize.TEXT('long') })\n    await queryInterface.changeColumn('Revisions', 'lastContent', { type: Sequelize.TEXT('long') })\n  },\n\n  down: async function (queryInterface, Sequelize) {\n    await queryInterface.changeColumn('Notes', 'content', { type: Sequelize.TEXT })\n    await queryInterface.changeColumn('Revisions', 'patch', { type: Sequelize.TEXT })\n    await queryInterface.changeColumn('Revisions', 'content', { type: Sequelize.TEXT })\n    await queryInterface.changeColumn('Revisions', 'lastContent', { type: Sequelize.TEXT })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20180209120907-longtext-of-authorship.js",
    "content": "'use strict'\n\nmodule.exports = {\n  up: async function (queryInterface, Sequelize) {\n    await queryInterface.changeColumn('Notes', 'authorship', { type: Sequelize.TEXT('long') })\n    await queryInterface.changeColumn('Revisions', 'authorship', { type: Sequelize.TEXT('long') })\n  },\n\n  down: async function (queryInterface, Sequelize) {\n    await queryInterface.changeColumn('Notes', 'authorship', { type: Sequelize.TEXT })\n    await queryInterface.changeColumn('Revisions', 'authorship', { type: Sequelize.TEXT })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20180306150303-fix-enum.js",
    "content": "'use strict'\n\nmodule.exports = {\n  up: async function (queryInterface, Sequelize) {\n    await queryInterface.changeColumn('Notes', 'permission', { type: Sequelize.ENUM('freely', 'editable', 'limited', 'locked', 'protected', 'private') })\n  },\n\n  down: async function (queryInterface, Sequelize) {\n    await queryInterface.changeColumn('Notes', 'permission', { type: Sequelize.ENUM('freely', 'editable', 'locked', 'private') })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20180326103000-use-text-in-tokens.js",
    "content": "'use strict'\n\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.changeColumn('Users', 'accessToken', {\n      type: Sequelize.TEXT\n    }).then(function () {\n      return queryInterface.changeColumn('Users', 'refreshToken', {\n        type: Sequelize.TEXT\n      })\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.changeColumn('Users', 'accessToken', {\n      type: Sequelize.STRING\n    }).then(function () {\n      return queryInterface.changeColumn('Users', 'refreshToken', {\n        type: Sequelize.STRING\n      })\n    })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20180525153000-user-add-delete-token.js",
    "content": "'use strict'\nmodule.exports = {\n  up: function (queryInterface, Sequelize) {\n    return queryInterface.addColumn('Users', 'deleteToken', {\n      type: Sequelize.UUID,\n      defaultValue: Sequelize.UUIDV4\n    })\n  },\n\n  down: function (queryInterface, Sequelize) {\n    return queryInterface.removeColumn('Users', 'deleteToken')\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20200104215332-remove-temp-table.js",
    "content": "'use strict'\n\nmodule.exports = {\n  up: (queryInterface, Sequelize) => {\n    return queryInterface.dropTable('Temp')\n    /*\n      Add altering commands here.\n      Return a promise to correctly handle asynchronicity.\n\n      Example:\n      return queryInterface.createTable('users', { id: Sequelize.INTEGER });\n    */\n  },\n\n  down: (queryInterface, Sequelize) => {\n    return queryInterface.createTable('Temp', {\n      id: {\n        type: Sequelize.STRING,\n        primaryKey: true\n      },\n      date: Sequelize.TEXT,\n      createdAt: Sequelize.DATE,\n      updatedAt: Sequelize.DATE\n    })\n  }\n}\n"
  },
  {
    "path": "lib/migrations/20240114120250-revision-add-index.js",
    "content": "'use strict'\n\nmodule.exports = {\n  up: (queryInterface, Sequelize) => {\n    return queryInterface.addIndex('Revisions', ['noteId'], {})\n  },\n\n  down: (queryInterface, Sequelize) => {\n    return queryInterface.removeIndex('Revisions', 'noteId')\n  }\n}\n"
  },
  {
    "path": "lib/models/author.js",
    "content": "'use strict'\n// external modules\nvar Sequelize = require('sequelize')\n\nmodule.exports = function (sequelize, DataTypes) {\n  var Author = sequelize.define('Author', {\n    id: {\n      type: Sequelize.INTEGER,\n      primaryKey: true,\n      autoIncrement: true\n    },\n    color: {\n      type: DataTypes.STRING\n    }\n  }, {\n    indexes: [\n      {\n        unique: true,\n        fields: ['noteId', 'userId']\n      }\n    ]\n  })\n\n  Author.associate = function (models) {\n    Author.belongsTo(models.Note, {\n      foreignKey: 'noteId',\n      as: 'note',\n      constraints: false,\n      onDelete: 'CASCADE',\n      hooks: true\n    })\n    Author.belongsTo(models.User, {\n      foreignKey: 'userId',\n      as: 'user',\n      constraints: false,\n      onDelete: 'CASCADE',\n      hooks: true\n    })\n  }\n\n  return Author\n}\n"
  },
  {
    "path": "lib/models/index.js",
    "content": "'use strict'\n// external modules\nvar fs = require('fs')\nvar path = require('path')\nvar Sequelize = require('sequelize')\nconst { cloneDeep } = require('lodash')\n\n// core\nvar config = require('../config')\nvar logger = require('../logger')\n\nvar dbconfig = cloneDeep(config.db)\ndbconfig.logging = config.debug ? (data) => {\n  logger.info(data)\n} : false\n\nvar sequelize = null\n\n// Heroku specific\nif (config.dbURL) {\n  sequelize = new Sequelize(config.dbURL, dbconfig)\n} else {\n  sequelize = new Sequelize(dbconfig.database, dbconfig.username, dbconfig.password, dbconfig)\n}\n\n// [Postgres] Handling NULL bytes\n// https://github.com/sequelize/sequelize/issues/6485\nfunction stripNullByte (value) {\n  value = '' + value\n  // eslint-disable-next-line no-control-regex\n  return value ? value.replace(/\\u0000/g, '') : value\n}\nsequelize.stripNullByte = stripNullByte\n\nfunction processData (data, _default, process) {\n  if (data === undefined) return data\n  else return data === null ? _default : (process ? process(data) : data)\n}\nsequelize.processData = processData\n\nvar db = {}\n\nfs.readdirSync(__dirname)\n  .filter(function (file) {\n    return (file.indexOf('.') !== 0) && (file !== 'index.js')\n  })\n  .forEach(function (file) {\n    var model = require(path.join(__dirname, file))(sequelize, Sequelize)\n    db[model.name] = model\n  })\n\nObject.keys(db).forEach(function (modelName) {\n  if ('associate' in db[modelName]) {\n    db[modelName].associate(db)\n  }\n})\n\ndb.sequelize = sequelize\ndb.Sequelize = Sequelize\n\nmodule.exports = db\n"
  },
  {
    "path": "lib/models/note.js",
    "content": "'use strict'\n// external modules\nvar fs = require('fs')\nvar path = require('path')\nvar LZString = require('@hackmd/lz-string')\nvar base64url = require('base64url')\nvar md = require('markdown-it')()\nvar metaMarked = require('@hackmd/meta-marked')\nvar cheerio = require('cheerio')\nvar shortId = require('shortid')\nvar Sequelize = require('sequelize')\nvar async = require('async')\nvar moment = require('moment')\nvar DiffMatchPatch = require('@hackmd/diff-match-patch')\nvar dmp = new DiffMatchPatch()\n\nconst { stripTags } = require('../../utils/string')\n\n// core\nvar config = require('../config')\nvar logger = require('../logger')\n\n// ot\nvar ot = require('../ot')\n\n// permission types\nvar permissionTypes = ['freely', 'editable', 'limited', 'locked', 'protected', 'private']\n\nmodule.exports = function (sequelize, DataTypes) {\n  var Note = sequelize.define('Note', {\n    id: {\n      type: DataTypes.UUID,\n      primaryKey: true,\n      defaultValue: Sequelize.UUIDV4\n    },\n    shortid: {\n      type: DataTypes.STRING,\n      unique: true,\n      allowNull: false,\n      defaultValue: shortId.generate\n    },\n    alias: {\n      type: DataTypes.STRING,\n      unique: true\n    },\n    permission: {\n      type: DataTypes.ENUM,\n      values: permissionTypes\n    },\n    viewcount: {\n      type: DataTypes.INTEGER,\n      allowNull: false,\n      defaultValue: 0\n    },\n    title: {\n      type: DataTypes.TEXT,\n      get: function () {\n        return sequelize.processData(this.getDataValue('title'), '')\n      },\n      set: function (value) {\n        this.setDataValue('title', sequelize.stripNullByte(value))\n      }\n    },\n    content: {\n      type: DataTypes.TEXT('long'),\n      get: function () {\n        return sequelize.processData(this.getDataValue('content'), '')\n      },\n      set: function (value) {\n        this.setDataValue('content', sequelize.stripNullByte(value))\n      }\n    },\n    authorship: {\n      type: DataTypes.TEXT('long'),\n      get: function () {\n        return sequelize.processData(this.getDataValue('authorship'), [], JSON.parse)\n      },\n      set: function (value) {\n        this.setDataValue('authorship', JSON.stringify(value))\n      }\n    },\n    lastchangeAt: {\n      type: DataTypes.DATE\n    },\n    savedAt: {\n      type: DataTypes.DATE\n    }\n  }, {\n    paranoid: false,\n    hooks: {\n      beforeCreate: function (note, options) {\n        return new Promise(function (resolve, reject) {\n          // if no content specified then use default note\n          if (!note.content) {\n            let filePath = config.defaultNotePath\n\n            if (note.alias) {\n              const notePathInDocPath = path.join(config.docsPath, path.basename(note.alias) + '.md')\n              if (Note.checkFileExist(notePathInDocPath)) {\n                filePath = notePathInDocPath\n              }\n            }\n\n            if (Note.checkFileExist(filePath)) {\n              const noteInFS = readFileSystemNote(filePath)\n              note.title = noteInFS.title\n              note.content = noteInFS.content\n              if (filePath !== config.defaultNotePath) {\n                note.createdAt = noteInFS.lastchangeAt\n                note.lastchangeAt = noteInFS.lastchangeAt\n              }\n            }\n          }\n          // if no permission specified and have owner then give default permission in config, else default permission is freely\n          if (!note.permission) {\n            if (note.ownerId) {\n              note.permission = config.defaultPermission\n            } else {\n              note.permission = 'freely'\n            }\n          }\n          return resolve(note)\n        })\n      },\n      afterCreate: function (note, options, callback) {\n        return new Promise(function (resolve, reject) {\n          sequelize.models.Revision.saveNoteRevision(note, function (err, revision) {\n            if (err) {\n              return reject(err)\n            }\n            return resolve(note)\n          })\n        })\n      }\n    }\n  })\n\n  Note.associate = function (models) {\n    Note.belongsTo(models.User, {\n      foreignKey: 'ownerId',\n      as: 'owner',\n      constraints: false,\n      onDelete: 'CASCADE',\n      hooks: true\n    })\n    Note.belongsTo(models.User, {\n      foreignKey: 'lastchangeuserId',\n      as: 'lastchangeuser',\n      constraints: false\n    })\n    Note.hasMany(models.Revision, {\n      foreignKey: 'noteId',\n      constraints: false\n    })\n    Note.hasMany(models.Author, {\n      foreignKey: 'noteId',\n      as: 'authors',\n      constraints: false\n    })\n  }\n  Note.checkFileExist = function (filePath) {\n    try {\n      return fs.statSync(filePath).isFile()\n    } catch (err) {\n      return false\n    }\n  }\n  Note.encodeNoteId = function (id) {\n    // remove dashes in UUID and encode in url-safe base64\n    const str = id.replace(/-/g, '')\n    const hexStr = Buffer.from(str, 'hex')\n    return base64url.encode(hexStr)\n  }\n  Note.decodeNoteId = function (encodedId) {\n    // decode from url-safe base64\n    const id = base64url.toBuffer(encodedId).toString('hex')\n    // add dashes between the UUID string parts\n    const idParts = []\n    idParts.push(id.substr(0, 8))\n    idParts.push(id.substr(8, 4))\n    idParts.push(id.substr(12, 4))\n    idParts.push(id.substr(16, 4))\n    idParts.push(id.substr(20, 12))\n    return idParts.join('-')\n  }\n  Note.checkNoteIdValid = function (id) {\n    var uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n    var result = id.match(uuidRegex)\n    if (result && result.length === 1) { return true } else { return false }\n  }\n  Note.parseNoteIdAsync = function (noteId) {\n    return new Promise((resolve, reject) => {\n      Note.parseNoteId(noteId, (err, id) => {\n        if (err) {\n          return reject(err)\n        }\n        resolve(id)\n      })\n    })\n  }\n\n  async function syncNote (noteInFS, note) {\n    const contentLength = noteInFS.content.length\n\n    let note2 = await note.update({\n      title: noteInFS.title,\n      content: noteInFS.content,\n      lastchangeAt: noteInFS.lastchangeAt\n    })\n    const revision = await sequelize.models.Revision.saveNoteRevisionAsync(note2)\n    // update authorship on after making revision of docs\n    const patch = dmp.patch_fromText(revision.patch)\n    const operations = Note.transformPatchToOperations(patch, contentLength)\n    let authorship = note2.authorship\n    for (let i = 0; i < operations.length; i++) {\n      authorship = Note.updateAuthorshipByOperation(operations[i], null, authorship)\n    }\n    note2 = await note.update({\n      authorship: authorship\n    })\n    return note2.id\n  }\n\n  Note.parseNoteId = function (noteId, callback) {\n    async.series({\n      parseNoteIdByAlias: function (_callback) {\n        // try to parse note id by alias (e.g. doc)\n        Note.findOne({\n          where: {\n            alias: noteId\n          }\n        }).then(async function (note) {\n          const filePath = path.join(config.docsPath, path.basename(noteId) + '.md')\n          if (Note.checkFileExist(filePath)) {\n            try {\n              if (note) {\n                // if doc in filesystem have newer modified time than last change time\n                // then will update the doc in db\n                const noteInFS = readFileSystemNote(filePath)\n                if (shouldSyncNote(note, noteInFS)) {\n                  const noteId = await syncNote(noteInFS, note)\n                  return callback(null, noteId)\n                }\n              } else {\n                // create new note with alias, and will sync md file in beforeCreateHook\n                const note = await Note.create({\n                  alias: noteId,\n                  owner: null,\n                  permission: 'locked'\n                })\n                return callback(null, note.id)\n              }\n            } catch (err) {\n              return _callback(err, null)\n            }\n          }\n          if (!note) {\n            return _callback(null, null)\n          }\n          return callback(null, note.id)\n        }).catch(function (err) {\n          return _callback(err, null)\n        })\n      },\n      // parse note id by LZString is deprecated, here for compability\n      parseNoteIdByLZString: function (_callback) {\n        // Calculate minimal string length for an UUID that is encoded\n        // base64 encoded and optimize comparsion by using -1\n        // this should make a lot of LZ-String parsing errors obsolete\n        // as we can assume that a nodeId that is 48 chars or longer is a\n        // noteID.\n        const base64UuidLength = ((4 * 36) / 3) - 1\n        if (!(noteId.length > base64UuidLength)) {\n          return _callback(null, null)\n        }\n        // try to parse note id by LZString Base64\n        try {\n          var id = LZString.decompressFromBase64(noteId)\n          if (id && Note.checkNoteIdValid(id)) { return callback(null, id) } else { return _callback(null, null) }\n        } catch (err) {\n          if (err.message === 'Cannot read property \\'charAt\\' of undefined') {\n            logger.warning('Looks like we can not decode \"' + noteId + '\" with LZString. Can be ignored.')\n          } else {\n            logger.error(err)\n          }\n          return _callback(null, null)\n        }\n      },\n      parseNoteIdByBase64Url: function (_callback) {\n        // try to parse note id by base64url\n        try {\n          var id = Note.decodeNoteId(noteId)\n          if (id && Note.checkNoteIdValid(id)) { return callback(null, id) } else { return _callback(null, null) }\n        } catch (err) {\n          logger.error(err)\n          return _callback(null, null)\n        }\n      },\n      parseNoteIdByShortId: function (_callback) {\n        // try to parse note id by shortId\n        try {\n          if (shortId.isValid(noteId)) {\n            Note.findOne({\n              where: {\n                shortid: noteId\n              }\n            }).then(function (note) {\n              if (!note) return _callback(null, null)\n              return callback(null, note.id)\n            }).catch(function (err) {\n              return _callback(err, null)\n            })\n          } else {\n            return _callback(null, null)\n          }\n        } catch (err) {\n          return _callback(err, null)\n        }\n      }\n    }, function (err, result) {\n      if (err) {\n        logger.error(err)\n        return callback(err, null)\n      }\n      return callback(null, null)\n    })\n  }\n  Note.parseNoteInfo = function (body) {\n    var parsed = Note.extractMeta(body)\n    var $ = cheerio.load(md.render(parsed.markdown))\n    return {\n      title: Note.extractNoteTitle(parsed.meta, $),\n      tags: Note.extractNoteTags(parsed.meta, $)\n    }\n  }\n  Note.parseNoteTitle = function (body) {\n    var parsed = Note.extractMeta(body)\n    var $ = cheerio.load(md.render(parsed.markdown))\n    return Note.extractNoteTitle(parsed.meta, $)\n  }\n  Note.extractNoteTitle = function (meta, $) {\n    var title = ''\n    if (meta.title && (typeof meta.title === 'string' || typeof meta.title === 'number')) {\n      title = meta.title\n    } else {\n      var h1s = $('h1')\n      if (h1s.length > 0 && h1s.first().text().split('\\n').length === 1) { title = stripTags(h1s.first().text()) }\n    }\n    if (!title) title = 'Untitled'\n    return title\n  }\n  Note.generateDescription = function (markdown) {\n    return markdown.substr(0, 100).replace(/(?:\\r\\n|\\r|\\n)/g, ' ')\n  }\n  Note.decodeTitle = function (title) {\n    return title || 'Untitled'\n  }\n  Note.generateWebTitle = function (title) {\n    title = !title || title === 'Untitled' ? 'CodiMD - Collaborative markdown notes' : title + ' - CodiMD'\n    return title\n  }\n  Note.extractNoteTags = function (meta, $) {\n    var tags = []\n    var rawtags = []\n    var metaTags\n    if (meta.tags && (typeof meta.tags === 'string' || typeof meta.tags === 'number')) {\n      metaTags = ('' + meta.tags).split(',')\n    } else if (meta.tags && (Array.isArray(meta.tags))) {\n      metaTags = meta.tags\n    }\n    if (metaTags) {\n      for (let i = 0; i < metaTags.length; i++) {\n        var text = metaTags[i].trim()\n        if (text) rawtags.push(text)\n      }\n    } else {\n      var h6s = $('h6')\n      h6s.each(function (key, value) {\n        if (/^tags/gmi.test($(value).text())) {\n          var codes = $(value).find('code')\n          for (let i = 0; i < codes.length; i++) {\n            var text = stripTags($(codes[i]).text().trim())\n            if (text) rawtags.push(text)\n          }\n        }\n      })\n    }\n    for (let i = 0; i < rawtags.length; i++) {\n      var found = false\n      for (let j = 0; j < tags.length; j++) {\n        if (tags[j] === rawtags[i]) {\n          found = true\n          break\n        }\n      }\n      if (!found) { tags.push(rawtags[i]) }\n    }\n    return tags\n  }\n  Note.extractMeta = function (content) {\n    var obj = null\n    try {\n      obj = metaMarked(content)\n      if (!obj.markdown) obj.markdown = ''\n      if (!obj.meta) obj.meta = {}\n    } catch (err) {\n      obj = {\n        markdown: content,\n        meta: {}\n      }\n    }\n    return obj\n  }\n  Note.parseMeta = function (meta) {\n    var _meta = {}\n    if (meta) {\n      if (meta.title && (typeof meta.title === 'string' || typeof meta.title === 'number')) { _meta.title = meta.title }\n      if (meta.description && (typeof meta.description === 'string' || typeof meta.description === 'number')) { _meta.description = meta.description }\n      if (meta.robots && (typeof meta.robots === 'string' || typeof meta.robots === 'number')) { _meta.robots = meta.robots }\n      if (meta.GA && (typeof meta.GA === 'string' || typeof meta.GA === 'number')) { _meta.GA = meta.GA }\n      if (meta.disqus && (typeof meta.disqus === 'string' || typeof meta.disqus === 'number')) { _meta.disqus = meta.disqus }\n      if (meta.slideOptions && (typeof meta.slideOptions === 'object')) { _meta.slideOptions = meta.slideOptions }\n    }\n    return _meta\n  }\n  Note.updateAuthorshipByOperation = function (operation, userId, authorships) {\n    var index = 0\n    var timestamp = Date.now()\n    for (let i = 0; i < operation.length; i++) {\n      var op = operation[i]\n      if (ot.TextOperation.isRetain(op)) {\n        index += op\n      } else if (ot.TextOperation.isInsert(op)) {\n        const opStart = index\n        const opEnd = index + op.length\n        let inserted = false\n        // authorship format: [userId, startPos, endPos, createdAt, updatedAt]\n        if (authorships.length <= 0) authorships.push([userId, opStart, opEnd, timestamp, timestamp])\n        else {\n          for (let j = 0; j < authorships.length; j++) {\n            const authorship = authorships[j]\n            if (!inserted) {\n              const nextAuthorship = authorships[j + 1] || -1\n              if ((nextAuthorship !== -1 && nextAuthorship[1] >= opEnd) || j >= authorships.length - 1) {\n                if (authorship[1] < opStart && authorship[2] > opStart) {\n                  // divide\n                  const postLength = authorship[2] - opStart\n                  authorship[2] = opStart\n                  authorship[4] = timestamp\n                  authorships.splice(j + 1, 0, [userId, opStart, opEnd, timestamp, timestamp])\n                  authorships.splice(j + 2, 0, [authorship[0], opEnd, opEnd + postLength, authorship[3], timestamp])\n                  j += 2\n                  inserted = true\n                } else if (authorship[1] >= opStart) {\n                  authorships.splice(j, 0, [userId, opStart, opEnd, timestamp, timestamp])\n                  j += 1\n                  inserted = true\n                } else if (authorship[2] <= opStart) {\n                  authorships.splice(j + 1, 0, [userId, opStart, opEnd, timestamp, timestamp])\n                  j += 1\n                  inserted = true\n                }\n              }\n            }\n            if (authorship[1] >= opStart) {\n              authorship[1] += op.length\n              authorship[2] += op.length\n            }\n          }\n        }\n        index += op.length\n      } else if (ot.TextOperation.isDelete(op)) {\n        const opStart = index\n        const opEnd = index - op\n        if (operation.length === 1) {\n          authorships = []\n        } else if (authorships.length > 0) {\n          for (let j = 0; j < authorships.length; j++) {\n            const authorship = authorships[j]\n            if (authorship[1] >= opStart && authorship[1] <= opEnd && authorship[2] >= opStart && authorship[2] <= opEnd) {\n              authorships.splice(j, 1)\n              j -= 1\n            } else if (authorship[1] < opStart && authorship[1] < opEnd && authorship[2] > opStart && authorship[2] > opEnd) {\n              authorship[2] += op\n              authorship[4] = timestamp\n            } else if (authorship[2] >= opStart && authorship[2] <= opEnd) {\n              authorship[2] = opStart\n              authorship[4] = timestamp\n            } else if (authorship[1] >= opStart && authorship[1] <= opEnd) {\n              authorship[1] = opEnd\n              authorship[4] = timestamp\n            }\n            if (authorship[1] >= opEnd) {\n              authorship[1] += op\n              authorship[2] += op\n            }\n          }\n        }\n        index += op\n      }\n    }\n    // merge\n    for (let j = 0; j < authorships.length; j++) {\n      const authorship = authorships[j]\n      for (let k = j + 1; k < authorships.length; k++) {\n        const nextAuthorship = authorships[k]\n        if (nextAuthorship && authorship[0] === nextAuthorship[0] && authorship[2] === nextAuthorship[1]) {\n          const minTimestamp = Math.min(authorship[3], nextAuthorship[3])\n          const maxTimestamp = Math.max(authorship[3], nextAuthorship[3])\n          authorships.splice(j, 1, [authorship[0], authorship[1], nextAuthorship[2], minTimestamp, maxTimestamp])\n          authorships.splice(k, 1)\n          j -= 1\n          break\n        }\n      }\n    }\n    // clear\n    for (let j = 0; j < authorships.length; j++) {\n      const authorship = authorships[j]\n      if (!authorship[0]) {\n        authorships.splice(j, 1)\n        j -= 1\n      }\n    }\n    return authorships\n  }\n  Note.transformPatchToOperations = function (patch, contentLength) {\n    var operations = []\n    if (patch.length > 0) {\n      // calculate original content length\n      for (let j = patch.length - 1; j >= 0; j--) {\n        var p = patch[j]\n        for (let i = 0; i < p.diffs.length; i++) {\n          var diff = p.diffs[i]\n          switch (diff[0]) {\n            case 1: // insert\n              contentLength -= diff[1].length\n              break\n            case -1: // delete\n              contentLength += diff[1].length\n              break\n          }\n        }\n      }\n      // generate operations\n      var bias = 0\n      var lengthBias = 0\n      for (let j = 0; j < patch.length; j++) {\n        var operation = []\n        const p = patch[j]\n        var currIndex = p.start1\n        var currLength = contentLength - bias\n        for (let i = 0; i < p.diffs.length; i++) {\n          const diff = p.diffs[i]\n          switch (diff[0]) {\n            case 0: // retain\n              if (i === 0) {\n                // first\n                operation.push(currIndex + diff[1].length)\n              } else if (i !== p.diffs.length - 1) {\n                // mid\n                operation.push(diff[1].length)\n              } else {\n                // last\n                operation.push(currLength + lengthBias - currIndex)\n              }\n              currIndex += diff[1].length\n              break\n            case 1: // insert\n              operation.push(diff[1])\n              lengthBias += diff[1].length\n              currIndex += diff[1].length\n              break\n            case -1: // delete\n              operation.push(-diff[1].length)\n              bias += diff[1].length\n              currIndex += diff[1].length\n              break\n          }\n        }\n        operations.push(operation)\n      }\n    }\n    return operations\n  }\n\n  function readFileSystemNote (filePath) {\n    const fsModifiedTime = moment(fs.statSync(filePath).mtime)\n    const content = fs.readFileSync(filePath, 'utf8')\n\n    return {\n      lastchangeAt: fsModifiedTime,\n      title: Note.parseNoteTitle(content),\n      content: content\n    }\n  }\n\n  function shouldSyncNote (note, noteInFS) {\n    const dbModifiedTime = moment(note.lastchangeAt || note.createdAt)\n    return noteInFS.lastchangeAt.isAfter(dbModifiedTime) && note.content !== noteInFS.content\n  }\n\n  return Note\n}\n"
  },
  {
    "path": "lib/models/revision.js",
    "content": "'use strict'\n// external modules\nvar Sequelize = require('sequelize')\nvar async = require('async')\nvar moment = require('moment')\nvar childProcess = require('child_process')\nvar shortId = require('shortid')\nvar path = require('path')\nvar util = require('util')\n\nvar Op = Sequelize.Op\n\n// core\nvar config = require('../config')\nvar logger = require('../logger')\n\nvar dmpWorker = createDmpWorker()\nvar dmpCallbackCache = {}\n\nfunction createDmpWorker () {\n  var worker = childProcess.fork(path.resolve(__dirname, '../workers/dmpWorker.js'), {\n    stdio: 'ignore'\n  })\n  if (config.debug) logger.info('dmp worker process started')\n  worker.on('message', function (data) {\n    if (!data || !data.msg || !data.cacheKey) {\n      return logger.error('dmp worker error: not enough data on message')\n    }\n    var cacheKey = data.cacheKey\n    switch (data.msg) {\n      case 'error':\n        dmpCallbackCache[cacheKey](data.error, null)\n        break\n      case 'check':\n        dmpCallbackCache[cacheKey](null, data.result)\n        break\n    }\n    delete dmpCallbackCache[cacheKey]\n  })\n  worker.on('close', function (code) {\n    dmpWorker = null\n    if (config.debug) logger.info('dmp worker process exited with code ' + code)\n  })\n  return worker\n}\n\nfunction sendDmpWorker (data, callback) {\n  if (!dmpWorker) dmpWorker = createDmpWorker()\n  var cacheKey = Date.now() + '_' + shortId.generate()\n  dmpCallbackCache[cacheKey] = callback\n  data = Object.assign(data, {\n    cacheKey: cacheKey\n  })\n  dmpWorker.send(data)\n}\n\nmodule.exports = function (sequelize, DataTypes) {\n  var Revision = sequelize.define('Revision', {\n    id: {\n      type: DataTypes.UUID,\n      primaryKey: true,\n      defaultValue: Sequelize.UUIDV4\n    },\n    patch: {\n      type: DataTypes.TEXT('long'),\n      get: function () {\n        return sequelize.processData(this.getDataValue('patch'), '')\n      },\n      set: function (value) {\n        this.setDataValue('patch', sequelize.stripNullByte(value))\n      }\n    },\n    lastContent: {\n      type: DataTypes.TEXT('long'),\n      get: function () {\n        return sequelize.processData(this.getDataValue('lastContent'), '')\n      },\n      set: function (value) {\n        this.setDataValue('lastContent', sequelize.stripNullByte(value))\n      }\n    },\n    content: {\n      type: DataTypes.TEXT('long'),\n      get: function () {\n        return sequelize.processData(this.getDataValue('content'), '')\n      },\n      set: function (value) {\n        this.setDataValue('content', sequelize.stripNullByte(value))\n      }\n    },\n    length: {\n      type: DataTypes.INTEGER\n    },\n    authorship: {\n      type: DataTypes.TEXT('long'),\n      get: function () {\n        return sequelize.processData(this.getDataValue('authorship'), [], JSON.parse)\n      },\n      set: function (value) {\n        this.setDataValue('authorship', value ? JSON.stringify(value) : value)\n      }\n    }\n  })\n\n  Revision.associate = function (models) {\n    Revision.belongsTo(models.Note, {\n      foreignKey: 'noteId',\n      as: 'note',\n      constraints: false,\n      onDelete: 'CASCADE',\n      hooks: true\n    })\n  }\n  Revision.getNoteRevisions = function (note, callback) {\n    Revision.findAll({\n      where: {\n        noteId: note.id\n      },\n      order: [['createdAt', 'DESC']]\n    }).then(function (revisions) {\n      var data = []\n      for (var i = 0, l = revisions.length; i < l; i++) {\n        var revision = revisions[i]\n        data.push({\n          time: moment(revision.createdAt).valueOf(),\n          length: revision.length\n        })\n      }\n      callback(null, data)\n    }).catch(function (err) {\n      callback(err, null)\n    })\n  }\n  Revision.getPatchedNoteRevisionByTime = function (note, time, callback) {\n    // find all revisions to prepare for all possible calculation\n    Revision.findAll({\n      where: {\n        noteId: note.id\n      },\n      order: [['createdAt', 'DESC']]\n    }).then(function (revisions) {\n      if (revisions.length <= 0) return callback(null, null)\n      // measure target revision position\n      Revision.count({\n        where: {\n          noteId: note.id,\n          createdAt: {\n            [Op.gte]: time\n          }\n        },\n        order: [['createdAt', 'DESC']]\n      }).then(function (count) {\n        if (count <= 0) return callback(null, null)\n        sendDmpWorker({\n          msg: 'get revision',\n          revisions: revisions,\n          count: count\n        }, callback)\n      }).catch(function (err) {\n        return callback(err, null)\n      })\n    }).catch(function (err) {\n      return callback(err, null)\n    })\n  }\n  Revision.checkAllNotesRevision = function (callback) {\n    Revision.saveAllNotesRevision(function (err, notes) {\n      if (err) return callback(err, null)\n      if (!notes || notes.length <= 0) {\n        return callback(null, notes)\n      } else {\n        Revision.checkAllNotesRevision(callback)\n      }\n    })\n  }\n  Revision.saveAllNotesRevision = function (callback) {\n    sequelize.models.Note.findAll({\n      // query all notes that need to save for revision\n      where: {\n        [Op.and]: [\n          {\n            lastchangeAt: {\n              [Op.or]: {\n                [Op.eq]: null,\n                [Op.and]: {\n                  [Op.ne]: null,\n                  [Op.gt]: sequelize.col('createdAt')\n                }\n              }\n            }\n          },\n          {\n            savedAt: {\n              [Op.or]: {\n                [Op.eq]: null,\n                [Op.lt]: sequelize.col('lastchangeAt')\n              }\n            }\n          }\n        ]\n      }\n    }).then(function (notes) {\n      if (notes.length <= 0) return callback(null, notes)\n      var savedNotes = []\n      async.each(notes, function (note, _callback) {\n        // revision saving policy: note not been modified for 5 mins or not save for 10 mins\n        if (note.lastchangeAt && note.savedAt) {\n          var lastchangeAt = moment(note.lastchangeAt)\n          var savedAt = moment(note.savedAt)\n          if (moment().isAfter(lastchangeAt.add(5, 'minutes'))) {\n            savedNotes.push(note)\n            Revision.saveNoteRevision(note, _callback)\n          } else if (lastchangeAt.isAfter(savedAt.add(10, 'minutes'))) {\n            savedNotes.push(note)\n            Revision.saveNoteRevision(note, _callback)\n          } else {\n            return _callback(null, null)\n          }\n        } else {\n          savedNotes.push(note)\n          Revision.saveNoteRevision(note, _callback)\n        }\n      }, function (err) {\n        if (err) {\n          return callback(err, null)\n        }\n        // return null when no notes need saving at this moment but have delayed tasks to be done\n        var result = ((savedNotes.length === 0) && (notes.length > savedNotes.length)) ? null : savedNotes\n        return callback(null, result)\n      })\n    }).catch(function (err) {\n      return callback(err, null)\n    })\n  }\n  Revision.saveNoteRevision = function (note, callback) {\n    Revision.findAll({\n      where: {\n        noteId: note.id\n      },\n      order: [['createdAt', 'DESC']]\n    }).then(function (revisions) {\n      if (revisions.length <= 0) {\n        // if no revision available\n        Revision.create({\n          noteId: note.id,\n          lastContent: note.content ? note.content : '',\n          length: note.content ? note.content.length : 0,\n          authorship: note.authorship\n        }).then(function (revision) {\n          Revision.finishSaveNoteRevision(note, revision, callback)\n        }).catch(function (err) {\n          return callback(err, null)\n        })\n      } else {\n        var latestRevision = revisions[0]\n        var lastContent = latestRevision.content || latestRevision.lastContent\n        var content = note.content\n        sendDmpWorker({\n          msg: 'create patch',\n          lastDoc: lastContent,\n          currDoc: content\n        }, function (err, patch) {\n          if (err) logger.error('save note revision error', err)\n          if (!patch) {\n            // if patch is empty (means no difference) then just update the latest revision updated time\n            latestRevision.changed('updatedAt', true)\n            latestRevision.update({\n              updatedAt: Date.now()\n            }).then(function (revision) {\n              Revision.finishSaveNoteRevision(note, revision, callback)\n            }).catch(function (err) {\n              return callback(err, null)\n            })\n          } else {\n            Revision.create({\n              noteId: note.id,\n              patch: patch,\n              content: note.content,\n              length: note.content.length,\n              authorship: note.authorship\n            }).then(function (revision) {\n              // clear last revision content to reduce db size\n              latestRevision.update({\n                content: null\n              }).then(function () {\n                Revision.finishSaveNoteRevision(note, revision, callback)\n              }).catch(function (err) {\n                return callback(err, null)\n              })\n            }).catch(function (err) {\n              return callback(err, null)\n            })\n          }\n        })\n      }\n    }).catch(function (err) {\n      return callback(err, null)\n    })\n  }\n  Revision.saveNoteRevisionAsync = util.promisify(Revision.saveNoteRevision)\n  Revision.finishSaveNoteRevision = function (note, revision, callback) {\n    note.update({\n      savedAt: revision.updatedAt\n    }).then(function () {\n      return callback(null, revision)\n    }).catch(function (err) {\n      return callback(err, null)\n    })\n  }\n\n  return Revision\n}\n"
  },
  {
    "path": "lib/models/user.js",
    "content": "'use strict'\n// external modules\nvar Sequelize = require('sequelize')\nvar Scrypt = require('scrypt-kdf')\n\n// core\nvar logger = require('../logger')\nvar { generateAvatarURL } = require('../letter-avatars')\n\nmodule.exports = function (sequelize, DataTypes) {\n  var User = sequelize.define('User', {\n    id: {\n      type: DataTypes.UUID,\n      primaryKey: true,\n      defaultValue: Sequelize.UUIDV4\n    },\n    profileid: {\n      type: DataTypes.STRING,\n      unique: true\n    },\n    profile: {\n      type: DataTypes.TEXT\n    },\n    history: {\n      type: DataTypes.TEXT\n    },\n    accessToken: {\n      type: DataTypes.TEXT\n    },\n    refreshToken: {\n      type: DataTypes.TEXT\n    },\n    deleteToken: {\n      type: DataTypes.UUID,\n      defaultValue: Sequelize.UUIDV4\n    },\n    email: {\n      type: Sequelize.TEXT,\n      validate: {\n        isEmail: true\n      }\n    },\n    password: {\n      type: Sequelize.TEXT\n    }\n  })\n\n  User.hashPassword = async function (plain) {\n    return (await Scrypt.kdf(plain, await Scrypt.pickParams(0.1))).toString('hex')\n  }\n\n  User.prototype.verifyPassword = async function (attempt) {\n    if (await Scrypt.verify(Buffer.from(this.password, 'hex'), attempt)) {\n      return this\n    }\n\n    return false\n  }\n\n  User.addHook('beforeCreate', async function (user) {\n    // only do hash when password is presented\n    if (user.password) {\n      user.password = await User.hashPassword(user.password)\n    }\n  })\n  User.addHook('beforeUpdate', async function (user) {\n    if (user.changed('password')) {\n      user.password = await User.hashPassword(user.password)\n    }\n  })\n\n  User.associate = function (models) {\n    User.hasMany(models.Note, {\n      foreignKey: 'ownerId',\n      constraints: false\n    })\n    User.hasMany(models.Note, {\n      foreignKey: 'lastchangeuserId',\n      constraints: false\n    })\n  }\n  User.getProfile = function (user) {\n    if (!user) {\n      return null\n    }\n    return user.profile ? User.parseProfile(user.profile) : (user.email ? User.parseProfileByEmail(user.email) : null)\n  }\n  User.parseProfile = function (profile) {\n    try {\n      profile = JSON.parse(profile)\n    } catch (err) {\n      logger.error(err)\n      profile = null\n    }\n    if (profile) {\n      profile = {\n        name: profile.displayName || profile.username,\n        photo: User.parsePhotoByProfile(profile),\n        biggerphoto: User.parsePhotoByProfile(profile, true)\n      }\n    }\n    return profile\n  }\n  User.parsePhotoByProfile = function (profile, bigger) {\n    var photo = null\n    switch (profile.provider) {\n      case 'facebook':\n        photo = 'https://graph.facebook.com/' + profile.id + '/picture'\n        if (bigger) photo += '?width=400'\n        else photo += '?width=96'\n        break\n      case 'twitter':\n        photo = 'https://twitter.com/' + profile.username + '/profile_image'\n        if (bigger) photo += '?size=original'\n        else photo += '?size=bigger'\n        break\n      case 'github':\n        const photoURL = new URL(profile.photos && profile.photos[0]\n          ? profile.photos[0].value\n          : `https://avatars.githubusercontent.com/u/${profile.id}`)\n        photoURL.searchParams.set('s', bigger ? 400 : 96)\n        photo = photoURL.toString()\n        break\n      case 'gitlab':\n        photo = profile.avatarUrl\n        if (photo) {\n          if (bigger) photo = photo.replace(/(\\?s=)\\d*$/i, '$1400')\n          else photo = photo.replace(/(\\?s=)\\d*$/i, '$196')\n        } else {\n          photo = generateAvatarURL(profile.username)\n        }\n        break\n      case 'mattermost':\n        photo = profile.avatarUrl\n        if (photo) {\n          if (bigger) photo = photo.replace(/(\\?s=)\\d*$/i, '$1400')\n          else photo = photo.replace(/(\\?s=)\\d*$/i, '$196')\n        } else {\n          photo = generateAvatarURL(profile.username)\n        }\n        break\n      case 'dropbox':\n        photo = generateAvatarURL('', profile.emails[0].value, bigger)\n        break\n      case 'google':\n        photo = profile.photos[0].value\n        if (bigger) photo = photo.replace(/(\\?sz=)\\d*$/i, '$1400')\n        else photo = photo.replace(/(\\?sz=)\\d*$/i, '$196')\n        break\n      case 'ldap':\n        photo = generateAvatarURL(profile.username, profile.emails[0], bigger)\n        break\n      case 'saml':\n        photo = generateAvatarURL(profile.username, profile.emails[0], bigger)\n        break\n      case 'oauth2':\n        photo = profile.photo\n        if (!photo) photo = generateAvatarURL(profile.username, profile.email, bigger)\n        break\n    }\n    return photo\n  }\n  User.parseProfileByEmail = function (email) {\n    return {\n      name: email.substring(0, email.lastIndexOf('@')),\n      photo: generateAvatarURL('', email, false),\n      biggerphoto: generateAvatarURL('', email, true)\n    }\n  }\n\n  return User\n}\n"
  },
  {
    "path": "lib/note/index.js",
    "content": "'use strict'\n\nconst config = require('../config')\nconst logger = require('../logger')\nconst { Note, User, Revision } = require('../models')\n\nconst { newCheckViewPermission, errorForbidden, responseCodiMD, errorNotFound, errorInternalError } = require('../response')\nconst { updateHistory, historyDelete } = require('../history')\nconst { actionPublish, actionSlide, actionInfo, actionDownload, actionPDF, actionGist, actionRevision, actionPandoc } = require('./noteActions')\nconst realtime = require('../realtime/realtime')\n\nasync function getNoteById (noteId, { includeUser } = { includeUser: false }) {\n  const id = await Note.parseNoteIdAsync(noteId)\n\n  const includes = []\n\n  if (includeUser) {\n    includes.push({\n      model: User,\n      as: 'owner'\n    }, {\n      model: User,\n      as: 'lastchangeuser'\n    })\n  }\n\n  const note = await Note.findOne({\n    where: {\n      id: id\n    },\n    include: includes\n  })\n  return note\n}\n\nasync function createNote (userId, noteAlias) {\n  if (!config.allowAnonymous && !userId) {\n    throw new Error('can not create note')\n  }\n\n  const note = await Note.create({\n    ownerId: userId,\n    alias: noteAlias\n  })\n\n  if (userId) {\n    updateHistory(userId, note)\n  }\n\n  return note\n}\n\n// controller\nasync function showNote (req, res) {\n  const noteId = req.params.noteId\n  const userId = req.user ? req.user.id : null\n\n  let note = await getNoteById(noteId)\n\n  if (!note) {\n    // if allow free url enable, auto create note\n    if (!config.allowFreeURL || config.forbiddenNoteIDs.includes(noteId)) {\n      return errorNotFound(req, res)\n    } else if (!config.allowAnonymous && !userId) {\n      return errorForbidden(req, res)\n    }\n    note = await createNote(userId, noteId)\n  }\n\n  if (!newCheckViewPermission(note, req.isAuthenticated(), userId)) {\n    return errorForbidden(req, res)\n  }\n\n  // force to use note id\n  const id = Note.encodeNoteId(note.id)\n  if ((note.alias && noteId !== note.alias) || (!note.alias && noteId !== id)) {\n    return res.redirect(config.serverURL + '/' + (note.alias || id))\n  }\n  return responseCodiMD(res, note)\n}\n\nfunction canViewNote (note, isLogin, userId) {\n  if (note.permission === 'private') {\n    return note.ownerId === userId\n  }\n  if (note.permission === 'limited' || note.permission === 'protected') {\n    return isLogin\n  }\n  return true\n}\n\nasync function showPublishNote (req, res) {\n  const shortid = req.params.shortid\n\n  const note = await getNoteById(shortid, {\n    includeUser: true\n  })\n\n  if (!note) {\n    return errorNotFound(req, res)\n  }\n\n  if (!canViewNote(note, req.isAuthenticated(), req.user ? req.user.id : null)) {\n    return errorForbidden(req, res)\n  }\n\n  if ((note.alias && shortid !== note.alias) || (!note.alias && shortid !== note.shortid)) {\n    return res.redirect(config.serverURL + '/s/' + (note.alias || note.shortid))\n  }\n\n  await note.increment('viewcount')\n\n  const body = note.content\n  const extracted = Note.extractMeta(body)\n  const markdown = extracted.markdown\n  const meta = Note.parseMeta(extracted.meta)\n  const createTime = note.createdAt\n  const updateTime = note.lastchangeAt\n  const title = Note.generateWebTitle(meta.title || Note.decodeTitle(note.title))\n\n  const data = {\n    title: title,\n    description: meta.description || (markdown ? Note.generateDescription(markdown) : null),\n    image: meta.image,\n    viewcount: note.viewcount,\n    createtime: createTime,\n    updatetime: updateTime,\n    body: body,\n    owner: note.owner ? note.owner.id : null,\n    ownerprofile: note.owner ? User.getProfile(note.owner) : null,\n    lastchangeuser: note.lastchangeuser ? note.lastchangeuser.id : null,\n    lastchangeuserprofile: note.lastchangeuser ? User.getProfile(note.lastchangeuser) : null,\n    robots: meta.robots || false, // default allow robots\n    GA: meta.GA,\n    disqus: meta.disqus,\n    cspNonce: res.locals.nonce\n  }\n\n  res.set({\n    'Cache-Control': 'private' // only cache by client\n  })\n\n  res.render('pretty.ejs', data)\n}\n\nasync function noteActions (req, res) {\n  const noteId = req.params.noteId\n\n  const note = await getNoteById(noteId)\n\n  if (!note) {\n    return errorNotFound(req, res)\n  }\n\n  if (!canViewNote(note, req.isAuthenticated(), req.user ? req.user.id : null)) {\n    return errorForbidden(req, res)\n  }\n\n  const action = req.params.action\n  switch (action) {\n    case 'publish':\n    case 'pretty': // pretty deprecated\n      return actionPublish(req, res, note)\n    case 'slide':\n      return actionSlide(req, res, note)\n    case 'download':\n      actionDownload(req, res, note)\n      break\n    case 'info':\n      actionInfo(req, res, note)\n      break\n    case 'pdf':\n      if (config.allowPDFExport) {\n        actionPDF(req, res, note)\n      } else {\n        logger.error('PDF export failed: Disabled by config. Set \"allowPDFExport: true\" to enable. Check the documentation for details')\n        errorForbidden(req, res)\n      }\n      break\n    case 'gist':\n      actionGist(req, res, note)\n      break\n    case 'revision':\n      actionRevision(req, res, note)\n      break\n    case 'pandoc':\n      actionPandoc(req, res, note)\n      break\n    default:\n      return res.redirect(config.serverURL + '/' + noteId)\n  }\n}\n\nasync function getMyNoteList (userId, callback) {\n  const myNotes = await Note.findAll({\n    where: {\n      ownerId: userId\n    }\n  })\n  if (!myNotes) {\n    return callback(null, null)\n  }\n  try {\n    const myNoteList = myNotes.map(note => ({\n      id: Note.encodeNoteId(note.id),\n      text: note.title,\n      tags: Note.parseNoteInfo(note.content).tags,\n      createdAt: note.createdAt,\n      lastchangeAt: note.lastchangeAt,\n      shortId: note.shortid\n    }))\n    if (config.debug) {\n      logger.info('Parse myNoteList success: ' + userId)\n    }\n    return callback(null, myNoteList)\n  } catch (err) {\n    logger.error('Parse myNoteList failed')\n    return callback(err, null)\n  }\n}\n\nfunction listMyNotes (req, res) {\n  if (req.isAuthenticated()) {\n    getMyNoteList(req.user.id, (err, myNoteList) => {\n      if (err) return errorInternalError(req, res)\n      if (!myNoteList) return errorNotFound(req, res)\n      res.send({\n        myNotes: myNoteList\n      })\n    })\n  } else {\n    return errorForbidden(req, res)\n  }\n}\n\nconst deleteNote = async (req, res) => {\n  if (req.isAuthenticated()) {\n    const noteId = await Note.parseNoteIdAsync(req.params.noteId)\n    try {\n      const destroyed = await Note.destroy({\n        where: {\n          id: noteId,\n          ownerId: req.user.id\n        }\n      })\n      if (!destroyed) {\n        logger.error('Delete note failed: Make sure the noteId and ownerId are correct.')\n        return errorNotFound(req, res)\n      }\n\n      historyDelete(req, res)\n\n      if (realtime.isNoteExistsInPool(noteId)) {\n        const note = realtime.getNoteFromNotePool(noteId)\n        realtime.disconnectSocketOnNote(note)\n      }\n\n      res.send({\n        status: 'ok'\n      })\n    } catch (err) {\n      logger.error('Delete note failed: Internal Error.')\n      return errorInternalError(req, res)\n    }\n  } else {\n    return errorForbidden(req, res)\n  }\n}\n\nconst updateNote = async (req, res) => {\n  if (req.isAuthenticated() || config.allowAnonymousEdits) {\n    const noteId = await Note.parseNoteIdAsync(req.params.noteId)\n    try {\n      const note = await Note.findOne({\n        where: {\n          id: noteId\n        }\n      })\n      if (!note) {\n        logger.error('Update note failed: Can\\'t find the note.')\n        return errorNotFound(req, res)\n      }\n\n      if (realtime.isNoteExistsInPool(noteId)) {\n        logger.error('Update note failed: There are online users opening this note.')\n        return res.status('403').json({ status: 'error', message: 'Update API can only be used when no users is online' })\n      }\n\n      const now = Date.now()\n      const content = req.body.content\n      const updated = await note.update({\n        title: Note.parseNoteTitle(content),\n        content: content,\n        lastchangeAt: now,\n        authorship: [\n          [\n            req.isAuthenticated() ? req.user.id : null,\n            0,\n            content.length,\n            now,\n            now\n          ]\n        ]\n      })\n\n      if (!updated) {\n        logger.error('Update note failed: Write note content error.')\n        return errorInternalError(req, res)\n      }\n\n      if (req.isAuthenticated()) {\n        updateHistory(req.user.id, Note.encodeNoteId(noteId), content)\n      }\n\n      Revision.saveNoteRevision(note, (err, revision) => {\n        if (err) {\n          logger.error(err)\n          return errorInternalError(req, res)\n        }\n        if (!revision) return errorNotFound(req, res)\n        res.send({\n          status: 'ok'\n        })\n      })\n    } catch (err) {\n      logger.error(err.stack)\n      logger.error('Update note failed: Internal Error.')\n      return errorInternalError(req, res)\n    }\n  } else {\n    return errorForbidden(req, res)\n  }\n}\n\nexports.showNote = showNote\nexports.showPublishNote = showPublishNote\nexports.noteActions = noteActions\nexports.listMyNotes = listMyNotes\nexports.deleteNote = deleteNote\nexports.updateNote = updateNote\n"
  },
  {
    "path": "lib/note/noteActions.js",
    "content": "'use strict'\n\nconst fs = require('fs')\nconst path = require('path')\nconst markdownpdf = require('markdown-pdf')\nconst shortId = require('shortid')\nconst querystring = require('querystring')\nconst moment = require('moment')\nconst { Pandoc } = require('@hackmd/pandoc.js')\n\nconst config = require('../config')\nconst logger = require('../logger')\nconst { Note, Revision } = require('../models')\nconst { errorInternalError, errorNotFound } = require('../response')\n\nfunction actionPublish (req, res, note) {\n  res.redirect(config.serverURL + '/s/' + (note.alias || note.shortid))\n}\n\nfunction actionSlide (req, res, note) {\n  res.redirect(config.serverURL + '/p/' + (note.alias || note.shortid))\n}\n\nfunction actionDownload (req, res, note) {\n  const body = note.content\n  const title = Note.decodeTitle(note.title)\n  const filename = encodeURIComponent(title)\n  res.set({\n    'Access-Control-Allow-Origin': '*', // allow CORS as API\n    'Access-Control-Allow-Headers': 'Range',\n    'Access-Control-Expose-Headers': 'Cache-Control, Content-Encoding, Content-Range',\n    'Content-Type': 'text/markdown; charset=UTF-8',\n    'Cache-Control': 'private',\n    'Content-disposition': 'attachment; filename=' + filename + '.md',\n    'X-Robots-Tag': 'noindex, nofollow' // prevent crawling\n  })\n  res.send(body)\n}\n\nfunction actionInfo (req, res, note) {\n  const body = note.content\n  const extracted = Note.extractMeta(body)\n  const markdown = extracted.markdown\n  const meta = Note.parseMeta(extracted.meta)\n  const createtime = note.createdAt\n  const updatetime = note.lastchangeAt\n  const title = Note.decodeTitle(note.title)\n\n  const data = {\n    title: meta.title || title,\n    description: meta.description || (markdown ? Note.generateDescription(markdown) : null),\n    viewcount: note.viewcount,\n    createtime: createtime,\n    updatetime: updatetime\n  }\n\n  res.set({\n    'Access-Control-Allow-Origin': '*', // allow CORS as API\n    'Access-Control-Allow-Headers': 'Range',\n    'Access-Control-Expose-Headers': 'Cache-Control, Content-Encoding, Content-Range',\n    'Cache-Control': 'private', // only cache by client\n    'X-Robots-Tag': 'noindex, nofollow' // prevent crawling\n  })\n  res.send(data)\n}\n\nfunction actionPDF (req, res, note) {\n  const url = config.serverURL || 'http://' + req.get('host')\n  const body = note.content\n  const extracted = Note.extractMeta(body)\n  let content = extracted.markdown\n  const title = Note.decodeTitle(note.title)\n\n  const highlightCssPath = path.join(config.appRootPath, '/node_modules/highlight.js/styles/github-gist.css')\n\n  if (!fs.existsSync(config.tmpPath)) {\n    fs.mkdirSync(config.tmpPath)\n  }\n  const pdfPath = config.tmpPath + '/' + Date.now() + '.pdf'\n  content = content.replace(/\\]\\(\\//g, '](' + url + '/')\n  const markdownpdfOptions = {\n    highlightCssPath: highlightCssPath\n  }\n  markdownpdf(markdownpdfOptions).from.string(content).to(pdfPath, function () {\n    if (!fs.existsSync(pdfPath)) {\n      logger.error('PDF seems to not be generated as expected. File doesn\\'t exist: ' + pdfPath)\n      return errorInternalError(req, res)\n    }\n    const stream = fs.createReadStream(pdfPath)\n    let filename = title\n    // Be careful of special characters\n    filename = encodeURIComponent(filename)\n    // Ideally this should strip them\n    res.setHeader('Content-disposition', 'attachment; filename=\"' + filename + '.pdf\"')\n    res.setHeader('Cache-Control', 'private')\n    res.setHeader('Content-Type', 'application/pdf; charset=UTF-8')\n    res.setHeader('X-Robots-Tag', 'noindex, nofollow') // prevent crawling\n    stream.on('end', () => {\n      stream.close()\n      fs.unlinkSync(pdfPath)\n    })\n    stream.pipe(res)\n  })\n}\n\nconst outputFormats = {\n  asciidoc: 'text/plain',\n  context: 'application/x-latex',\n  epub: 'application/epub+zip',\n  epub3: 'application/epub+zip',\n  latex: 'application/x-latex',\n  odt: 'application/vnd.oasis.opendocument.text',\n  pdf: 'application/pdf',\n  rst: 'text/plain',\n  rtf: 'application/rtf',\n  textile: 'text/plain',\n  docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'\n}\n\nasync function actionPandoc (req, res, note) {\n  var url = config.serverURL || 'http://' + req.get('host')\n  var body = note.content\n  var extracted = Note.extractMeta(body)\n  var content = extracted.markdown\n  var title = Note.decodeTitle(note.title)\n\n  if (!fs.existsSync(config.tmpPath)) {\n    fs.mkdirSync(config.tmpPath)\n  }\n  const pandoc = new Pandoc()\n\n  var path = config.tmpPath + '/' + Date.now()\n  content = content.replace(/\\]\\(\\//g, '](' + url + '/')\n\n  const { exportType } = req.query\n  if (typeof exportType !== 'string') {\n    return res.sendStatus(400)\n  }\n\n  const contentType = outputFormats[exportType]\n  if (!contentType) {\n    return res.sendStatus(400)\n  }\n\n  try {\n    // TODO: timeout rejection\n    await pandoc.convertToFile(content, 'markdown', exportType, path, [\n      '--metadata', `title=${title}`, '--sandbox'\n    ])\n\n    var stream = fs.createReadStream(path)\n    var filename = title\n    // Be careful of special characters\n    filename = encodeURIComponent(filename)\n    // Ideally this should strip them\n    res.setHeader('Content-disposition', `attachment; filename=\"${filename}.${exportType}\"`)\n    res.setHeader('Cache-Control', 'private')\n    res.setHeader('Content-Type', `${contentType}; charset=UTF-8`)\n    res.setHeader('X-Robots-Tag', 'noindex, nofollow') // prevent crawling\n    stream.pipe(res)\n  } catch (err) {\n    // TODO: handle error\n    res.json({\n      message: err.message\n    })\n  }\n}\n\nfunction actionGist (req, res, note) {\n  const data = {\n    client_id: config.github.clientID,\n    redirect_uri: config.serverURL + '/auth/github/callback/' + Note.encodeNoteId(note.id) + '/gist',\n    scope: 'gist',\n    state: shortId.generate()\n  }\n  const query = querystring.stringify(data)\n  res.redirect('https://github.com/login/oauth/authorize?' + query)\n}\n\nfunction actionRevision (req, res, note) {\n  const actionId = req.params.actionId\n  if (actionId) {\n    const time = moment(parseInt(actionId))\n    if (!time.isValid()) {\n      return errorNotFound(req, res)\n    }\n    Revision.getPatchedNoteRevisionByTime(note, time, function (err, content) {\n      if (err) {\n        logger.error(err)\n        return errorInternalError(req, res)\n      }\n      if (!content) {\n        return errorNotFound(req, res)\n      }\n      res.set({\n        'Access-Control-Allow-Origin': '*', // allow CORS as API\n        'Access-Control-Allow-Headers': 'Range',\n        'Access-Control-Expose-Headers': 'Cache-Control, Content-Encoding, Content-Range',\n        'Cache-Control': 'private', // only cache by client\n        'X-Robots-Tag': 'noindex, nofollow' // prevent crawling\n      })\n      res.send(content)\n    })\n  } else {\n    Revision.getNoteRevisions(note, function (err, data) {\n      if (err) {\n        logger.error(err)\n        return errorInternalError(req, res)\n      }\n      const result = {\n        revision: data\n      }\n      res.set({\n        'Access-Control-Allow-Origin': '*', // allow CORS as API\n        'Access-Control-Allow-Headers': 'Range',\n        'Access-Control-Expose-Headers': 'Cache-Control, Content-Encoding, Content-Range',\n        'Cache-Control': 'private', // only cache by client\n        'X-Robots-Tag': 'noindex, nofollow' // prevent crawling\n      })\n      res.send(result)\n    })\n  }\n}\n\nexports.actionPublish = actionPublish\nexports.actionSlide = actionSlide\nexports.actionDownload = actionDownload\nexports.actionInfo = actionInfo\nexports.actionPDF = actionPDF\nexports.actionGist = actionGist\nexports.actionPandoc = actionPandoc\nexports.actionRevision = actionRevision\n"
  },
  {
    "path": "lib/ot/client.js",
    "content": "// translation of https://github.com/djspiewak/cccp/blob/master/agent/src/main/scala/com/codecommit/cccp/agent/state.scala\n\nif (typeof ot === 'undefined') {\n  var ot = {};\n}\n\not.Client = (function (global) {\n  'use strict';\n\n  // Client constructor\n  function Client (revision) {\n    this.revision = revision; // the next expected revision number\n    this.setState(synchronized_); // start state\n  }\n\n  Client.prototype.setState = function (state) {\n    this.state = state;\n  };\n\n  // Call this method when the user changes the document.\n  Client.prototype.applyClient = function (operation) {\n    this.setState(this.state.applyClient(this, operation));\n  };\n\n  // Call this method with a new operation from the server\n  Client.prototype.applyServer = function (revision, operation) {\n    this.setState(this.state.applyServer(this, revision, operation));\n  };\n\n  Client.prototype.applyOperations = function (head, operations) {\n    this.setState(this.state.applyOperations(this, head, operations));\n  };\n\n  Client.prototype.serverAck = function (revision) {\n    this.setState(this.state.serverAck(this, revision));\n  };\n\n  Client.prototype.serverReconnect = function () {\n    if (typeof this.state.resend === 'function') { this.state.resend(this); }\n  };\n\n  // Transforms a selection from the latest known server state to the current\n  // client state. For example, if we get from the server the information that\n  // another user's cursor is at position 3, but the server hasn't yet received\n  // our newest operation, an insertion of 5 characters at the beginning of the\n  // document, the correct position of the other user's cursor in our current\n  // document is 8.\n  Client.prototype.transformSelection = function (selection) {\n    return this.state.transformSelection(selection);\n  };\n\n  // Override this method.\n  Client.prototype.sendOperation = function (revision, operation) {\n    throw new Error(\"sendOperation must be defined in child class\");\n  };\n\n  // Override this method.\n  Client.prototype.applyOperation = function (operation) {\n    throw new Error(\"applyOperation must be defined in child class\");\n  };\n\n\n  // In the 'Synchronized' state, there is no pending operation that the client\n  // has sent to the server.\n  function Synchronized () {}\n  Client.Synchronized = Synchronized;\n\n  Synchronized.prototype.applyClient = function (client, operation) {\n    // When the user makes an edit, send the operation to the server and\n    // switch to the 'AwaitingConfirm' state\n    client.sendOperation(client.revision, operation);\n    return new AwaitingConfirm(operation);\n  };\n\n  Synchronized.prototype.applyServer = function (client, revision, operation) {\n    if (revision - client.revision > 1) {\n      throw new Error(\"Invalid revision.\");\n    }\n    client.revision = revision;\n    // When we receive a new operation from the server, the operation can be\n    // simply applied to the current document\n    client.applyOperation(operation);\n    return this;\n  };\n\n  Synchronized.prototype.serverAck = function (client, revision) {\n    throw new Error(\"There is no pending operation.\");\n  };\n\n  // Nothing to do because the latest server state and client state are the same.\n  Synchronized.prototype.transformSelection = function (x) { return x; };\n\n  // Singleton\n  var synchronized_ = new Synchronized();\n\n\n  // In the 'AwaitingConfirm' state, there's one operation the client has sent\n  // to the server and is still waiting for an acknowledgement.\n  function AwaitingConfirm (outstanding) {\n    // Save the pending operation\n    this.outstanding = outstanding;\n  }\n  Client.AwaitingConfirm = AwaitingConfirm;\n\n  AwaitingConfirm.prototype.applyClient = function (client, operation) {\n    // When the user makes an edit, don't send the operation immediately,\n    // instead switch to 'AwaitingWithBuffer' state\n    return new AwaitingWithBuffer(this.outstanding, operation);\n  };\n\n  AwaitingConfirm.prototype.applyServer = function (client, revision, operation) {\n    if (revision - client.revision > 1) {\n      throw new Error(\"Invalid revision.\");\n    }\n    client.revision = revision;\n    // This is another client's operation. Visualization:\n    //\n    //                   /\\\n    // this.outstanding /  \\ operation\n    //                 /    \\\n    //                 \\    /\n    //  pair[1]         \\  / pair[0] (new outstanding)\n    //  (can be applied  \\/\n    //  to the client's\n    //  current document)\n    var pair = operation.constructor.transform(this.outstanding, operation);\n    client.applyOperation(pair[1]);\n    return new AwaitingConfirm(pair[0]);\n  };\n\n  AwaitingConfirm.prototype.serverAck = function (client, revision) {\n    if (revision - client.revision > 1) {\n      return new Stale(this.outstanding, client, revision).getOperations();\n    }\n    client.revision = revision;\n    // The client's operation has been acknowledged\n    // => switch to synchronized state\n    return synchronized_;\n  };\n\n  AwaitingConfirm.prototype.transformSelection = function (selection) {\n    return selection.transform(this.outstanding);\n  };\n\n  AwaitingConfirm.prototype.resend = function (client) {\n    // The confirm didn't come because the client was disconnected.\n    // Now that it has reconnected, we resend the outstanding operation.\n    client.sendOperation(client.revision, this.outstanding);\n  };\n\n\n  // In the 'AwaitingWithBuffer' state, the client is waiting for an operation\n  // to be acknowledged by the server while buffering the edits the user makes\n  function AwaitingWithBuffer (outstanding, buffer) {\n    // Save the pending operation and the user's edits since then\n    this.outstanding = outstanding;\n    this.buffer = buffer;\n  }\n  Client.AwaitingWithBuffer = AwaitingWithBuffer;\n\n  AwaitingWithBuffer.prototype.applyClient = function (client, operation) {\n    // Compose the user's changes onto the buffer\n    var newBuffer = this.buffer.compose(operation);\n    return new AwaitingWithBuffer(this.outstanding, newBuffer);\n  };\n\n  AwaitingWithBuffer.prototype.applyServer = function (client, revision, operation) {\n    if (revision - client.revision > 1) {\n      throw new Error(\"Invalid revision.\");\n    }\n    client.revision = revision;\n    // Operation comes from another client\n    //\n    //                       /\\\n    //     this.outstanding /  \\ operation\n    //                     /    \\\n    //                    /\\    /\n    //       this.buffer /  \\* / pair1[0] (new outstanding)\n    //                  /    \\/\n    //                  \\    /\n    //          pair2[1] \\  / pair2[0] (new buffer)\n    // the transformed    \\/\n    // operation -- can\n    // be applied to the\n    // client's current\n    // document\n    //\n    // * pair1[1]\n    var transform = operation.constructor.transform;\n    var pair1 = transform(this.outstanding, operation);\n    var pair2 = transform(this.buffer, pair1[1]);\n    client.applyOperation(pair2[1]);\n    return new AwaitingWithBuffer(pair1[0], pair2[0]);\n  };\n\n  AwaitingWithBuffer.prototype.serverAck = function (client, revision) {\n    if (revision - client.revision > 1) {\n      return new StaleWithBuffer(this.outstanding, this.buffer, client, revision).getOperations();\n    }\n    client.revision = revision;\n    // The pending operation has been acknowledged\n    // => send buffer\n    client.sendOperation(client.revision, this.buffer);\n    return new AwaitingConfirm(this.buffer);\n  };\n\n  AwaitingWithBuffer.prototype.transformSelection = function (selection) {\n    return selection.transform(this.outstanding).transform(this.buffer);\n  };\n\n  AwaitingWithBuffer.prototype.resend = function (client) {\n    // The confirm didn't come because the client was disconnected.\n    // Now that it has reconnected, we resend the outstanding operation.\n    client.sendOperation(client.revision, this.outstanding);\n  };\n\n\n  function Stale(acknowlaged, client, revision) {\n    this.acknowlaged = acknowlaged;\n    this.client = client;\n    this.revision = revision;\n  }\n  Client.Stale = Stale;\n\n  Stale.prototype.applyClient = function (client, operation) {\n    return new StaleWithBuffer(this.acknowlaged, operation, client, this.revision);\n  };\n\n  Stale.prototype.applyServer = function (client, revision, operation) {\n    throw new Error(\"Ignored server-side change.\");\n  };\n\n  Stale.prototype.applyOperations = function (client, head, operations) {\n    var transform = this.acknowlaged.constructor.transform;\n    for (var i = 0; i < operations.length; i++) {\n      var op = ot.TextOperation.fromJSON(operations[i]);\n      var pair = transform(this.acknowlaged, op);\n      client.applyOperation(pair[1]);\n      this.acknowlaged = pair[0];\n    }\n    client.revision = this.revision;\n    return synchronized_;\n  };\n\n  Stale.prototype.serverAck = function (client, revision) {\n    throw new Error(\"There is no pending operation.\");\n  };\n\n  Stale.prototype.transformSelection = function (selection) {\n    return selection;\n  };\n\n  Stale.prototype.getOperations = function () {\n    this.client.getOperations(this.client.revision, this.revision - 1); // acknowlaged is the one at revision\n    return this;\n  };\n\n\n  function StaleWithBuffer(acknowlaged, buffer, client, revision) {\n    this.acknowlaged = acknowlaged;\n    this.buffer = buffer;\n    this.client = client;\n    this.revision = revision;\n  }\n  Client.StaleWithBuffer = StaleWithBuffer;\n\n  StaleWithBuffer.prototype.applyClient = function (client, operation) {\n    var buffer = this.buffer.compose(operation);\n    return new StaleWithBuffer(this.acknowlaged, buffer, client, this.revision);\n  };\n\n  StaleWithBuffer.prototype.applyServer = function (client, revision, operation) {\n    throw new Error(\"Ignored server-side change.\");\n  };\n\n  StaleWithBuffer.prototype.applyOperations = function (client, head, operations) {\n    var transform = this.acknowlaged.constructor.transform;\n    for (var i = 0; i < operations.length; i++) {\n      var op = ot.TextOperation.fromJSON(operations[i]);\n      var pair1 = transform(this.acknowlaged, op);\n      var pair2 = transform(this.buffer, pair1[1]);\n      client.applyOperation(pair2[1]);\n      this.acknowlaged = pair1[0];\n      this.buffer = pair2[0];\n    }\n    client.revision = this.revision;\n    client.sendOperation(client.revision, this.buffer);\n    return new AwaitingConfirm(this.buffer);\n  };\n\n  StaleWithBuffer.prototype.serverAck = function (client, revision) {\n    throw new Error(\"There is no pending operation.\");\n  };\n\n  StaleWithBuffer.prototype.transformSelection = function (selection) {\n    return selection;\n  };\n\n  StaleWithBuffer.prototype.getOperations = function () {\n    this.client.getOperations(this.client.revision, this.revision - 1); // acknowlaged is the one at revision\n    return this;\n  };\n\n\n  return Client;\n\n}(this));\n\nif (typeof module === 'object') {\n  module.exports = ot.Client;\n}\n\n"
  },
  {
    "path": "lib/ot/editor-socketio-server.js",
    "content": "'use strict';\n\nvar EventEmitter = require('events').EventEmitter;\nvar TextOperation = require('./text-operation');\nvar WrappedOperation = require('./wrapped-operation');\nvar Server = require('./server');\nvar Selection = require('./selection');\nvar util = require('util');\n\nvar logger = require('../logger');\n\nfunction EditorSocketIOServer(document, operations, docId, mayWrite, operationCallback) {\n    EventEmitter.call(this);\n    Server.call(this, document, operations);\n    this.users = {};\n    this.docId = docId;\n    this.mayWrite = mayWrite || function (_, cb) {\n        cb(true);\n    };\n    this.operationCallback = operationCallback;\n}\n\nutil.inherits(EditorSocketIOServer, Server);\nextend(EditorSocketIOServer.prototype, EventEmitter.prototype);\n\nfunction extend(target, source) {\n    for (var key in source) {\n        if (source.hasOwnProperty(key)) {\n            target[key] = source[key];\n        }\n    }\n}\n\nEditorSocketIOServer.prototype.addClient = function (socket) {\n    var self = this;\n    socket.join(this.docId);\n    var docOut = {\n        str: this.document,\n        revision: this.operations.length,\n        clients: this.users\n    };\n    socket.emit('doc', docOut);\n    socket.on('operation', function (revision, operation, selection) {\n        socket.origin = 'operation';\n        self.mayWrite(socket, function (mayWrite) {\n            if (!mayWrite) {\n                logger.info(\"User doesn't have the right to edit.\");\n                return;\n            }\n            try {\n                self.onOperation(socket, revision, operation, selection);\n                if (typeof self.operationCallback === 'function')\n                    self.operationCallback(socket, operation);\n            } catch (err) {\n                setTimeout(function() {\n                    var docOut = {\n                        str: self.document,\n                        revision: self.operations.length,\n                        clients: self.users,\n                        force: true\n                    };\n                    socket.emit('doc', docOut);\n                }, 100);\n            }\n        });\n    });\n    socket.on('get_operations', function (base, head) {\n        self.onGetOperations(socket, base, head);\n    });\n    socket.on('selection', function (obj) {\n        socket.origin = 'selection';\n        self.mayWrite(socket, function (mayWrite) {\n            if (!mayWrite) {\n                logger.info(\"User doesn't have the right to edit.\");\n                return;\n            }\n            self.updateSelection(socket, obj && Selection.fromJSON(obj));\n        });\n    });\n    socket.on('disconnect', function () {\n        logger.debug(\"Disconnect\");\n        socket.leave(self.docId);\n        self.onDisconnect(socket);\n        /*\n        if (socket.manager && socket.manager.sockets.clients(self.docId).length === 0) {\n          self.emit('empty-room');\n        }\n        */\n    });\n};\n\nEditorSocketIOServer.prototype.onOperation = function (socket, revision, operation, selection) {\n    var wrapped;\n    try {\n        wrapped = new WrappedOperation(\n            TextOperation.fromJSON(operation),\n            selection && Selection.fromJSON(selection)\n        );\n    } catch (exc) {\n        logger.error(\"Invalid operation received: \");\n        logger.error(exc);\n        throw new Error(exc);\n    }\n\n    try {\n        var clientId = socket.id;\n        var wrappedPrime = this.receiveOperation(revision, wrapped);\n        if(!wrappedPrime) return;\n        logger.debug(\"new operation: \" + JSON.stringify(wrapped));\n        this.getClient(clientId).selection = wrappedPrime.meta;\n        revision = this.operations.length;\n        socket.emit('ack', revision);\n        socket.broadcast.in(this.docId).emit(\n            'operation', clientId, revision,\n            wrappedPrime.wrapped.toJSON(), wrappedPrime.meta\n        );\n        //set document is dirty\n        this.isDirty = true;\n    } catch (exc) {\n        logger.error(exc);\n        throw new Error(exc);\n    }\n};\n\nEditorSocketIOServer.prototype.onGetOperations = function (socket, base, head) {\n    var operations = this.operations.slice(base, head).map(function (op) {\n        return op.wrapped.toJSON();\n    });\n    socket.emit('operations', head, operations);\n};\n\nEditorSocketIOServer.prototype.updateSelection = function (socket, selection) {\n    var clientId = socket.id;\n    if (selection) {\n        this.getClient(clientId).selection = selection;\n    } else {\n        delete this.getClient(clientId).selection;\n    }\n    socket.broadcast.to(this.docId).emit('selection', clientId, selection);\n};\n\nEditorSocketIOServer.prototype.setName = function (socket, name) {\n    var clientId = socket.id;\n    this.getClient(clientId).name = name;\n    socket.broadcast.to(this.docId).emit('set_name', clientId, name);\n};\n\nEditorSocketIOServer.prototype.setColor = function (socket, color) {\n    var clientId = socket.id;\n    this.getClient(clientId).color = color;\n    socket.broadcast.to(this.docId).emit('set_color', clientId, color);\n};\n\nEditorSocketIOServer.prototype.getClient = function (clientId) {\n    return this.users[clientId] || (this.users[clientId] = {});\n};\n\nEditorSocketIOServer.prototype.onDisconnect = function (socket) {\n    var clientId = socket.id;\n    delete this.users[clientId];\n    socket.broadcast.to(this.docId).emit('client_left', clientId);\n};\n\nmodule.exports = EditorSocketIOServer;\n"
  },
  {
    "path": "lib/ot/index.js",
    "content": "exports.version = '0.0.15';\n\nexports.TextOperation        = require('./text-operation');\nexports.SimpleTextOperation  = require('./simple-text-operation');\nexports.Client               = require('./client');\nexports.Server               = require('./server');\nexports.Selection            = require('./selection');\nexports.EditorSocketIOServer = require('./editor-socketio-server');\n"
  },
  {
    "path": "lib/ot/selection.js",
    "content": "if (typeof ot === 'undefined') {\n  // Export for browsers\n  var ot = {};\n}\n\not.Selection = (function (global) {\n  'use strict';\n\n  var TextOperation = global.ot ? global.ot.TextOperation : require('./text-operation');\n\n  // Range has `anchor` and `head` properties, which are zero-based indices into\n  // the document. The `anchor` is the side of the selection that stays fixed,\n  // `head` is the side of the selection where the cursor is. When both are\n  // equal, the range represents a cursor.\n  function Range (anchor, head) {\n    this.anchor = anchor;\n    this.head = head;\n  }\n\n  Range.fromJSON = function (obj) {\n    return new Range(obj.anchor, obj.head);\n  };\n\n  Range.prototype.equals = function (other) {\n    return this.anchor === other.anchor && this.head === other.head;\n  };\n\n  Range.prototype.isEmpty = function () {\n    return this.anchor === this.head;\n  };\n\n  Range.prototype.transform = function (other) {\n    function transformIndex (index) {\n      var newIndex = index;\n      var ops = other.ops;\n      for (var i = 0, l = other.ops.length; i < l; i++) {\n        if (TextOperation.isRetain(ops[i])) {\n          index -= ops[i];\n        } else if (TextOperation.isInsert(ops[i])) {\n          newIndex += ops[i].length;\n        } else {\n          newIndex -= Math.min(index, -ops[i]);\n          index += ops[i];\n        }\n        if (index < 0) { break; }\n      }\n      return newIndex;\n    }\n\n    var newAnchor = transformIndex(this.anchor);\n    if (this.anchor === this.head) {\n      return new Range(newAnchor, newAnchor);\n    }\n    return new Range(newAnchor, transformIndex(this.head));\n  };\n\n  // A selection is basically an array of ranges. Every range represents a real\n  // selection or a cursor in the document (when the start position equals the\n  // end position of the range). The array must not be empty.\n  function Selection (ranges) {\n    this.ranges = ranges || [];\n  }\n\n  Selection.Range = Range;\n\n  // Convenience method for creating selections only containing a single cursor\n  // and no real selection range.\n  Selection.createCursor = function (position) {\n    return new Selection([new Range(position, position)]);\n  };\n\n  Selection.fromJSON = function (obj) {\n    var objRanges = obj.ranges || obj;\n    for (var i = 0, ranges = []; i < objRanges.length; i++) {\n      ranges[i] = Range.fromJSON(objRanges[i]);\n    }\n    return new Selection(ranges);\n  };\n\n  Selection.prototype.equals = function (other) {\n    if (this.position !== other.position) { return false; }\n    if (this.ranges.length !== other.ranges.length) { return false; }\n    // FIXME: Sort ranges before comparing them?\n    for (var i = 0; i < this.ranges.length; i++) {\n      if (!this.ranges[i].equals(other.ranges[i])) { return false; }\n    }\n    return true;\n  };\n\n  Selection.prototype.somethingSelected = function () {\n    for (var i = 0; i < this.ranges.length; i++) {\n      if (!this.ranges[i].isEmpty()) { return true; }\n    }\n    return false;\n  };\n\n  // Return the more current selection information.\n  Selection.prototype.compose = function (other) {\n    return other;\n  };\n\n  // Update the selection with respect to an operation.\n  Selection.prototype.transform = function (other) {\n    for (var i = 0, newRanges = []; i < this.ranges.length; i++) {\n      newRanges[i] = this.ranges[i].transform(other);\n    }\n    return new Selection(newRanges);\n  };\n\n  return Selection;\n\n}(this));\n\n// Export for CommonJS\nif (typeof module === 'object') {\n  module.exports = ot.Selection;\n}\n"
  },
  {
    "path": "lib/ot/server.js",
    "content": "var config = require('../config');\n\nif (typeof ot === 'undefined') {\n  var ot = {};\n}\n\not.Server = (function (global) {\n  'use strict';\n\n  // Constructor. Takes the current document as a string and optionally the array\n  // of all operations.\n  function Server (document, operations) {\n    this.document = document;\n    this.operations = operations || [];\n  }\n\n  // Call this method whenever you receive an operation from a client.\n  Server.prototype.receiveOperation = function (revision, operation) {\n    if (revision < 0 || this.operations.length < revision) {\n      throw new Error(\"operation revision not in history\");\n    }\n    // Find all operations that the client didn't know of when it sent the\n    // operation ...\n    var concurrentOperations = this.operations.slice(revision);\n\n    // ... and transform the operation against all these operations ...\n    var transform = operation.constructor.transform;\n    for (var i = 0; i < concurrentOperations.length; i++) {\n      operation = transform(operation, concurrentOperations[i])[0];\n    }\n\n    // ... and apply that on the document.\n    var newDocument = operation.apply(this.document);\n    // ignore if exceed the max length of document\n    if(newDocument.length > config.documentMaxLength && newDocument.length > this.document.length)\n        return;\n    this.document = newDocument;\n    // Store operation in history.\n    this.operations.push(operation);\n\n    // It's the caller's responsibility to send the operation to all connected\n    // clients and an acknowledgement to the creator.\n    return operation;\n  };\n\n  return Server;\n\n}(this));\n\nif (typeof module === 'object') {\n  module.exports = ot.Server;\n}"
  },
  {
    "path": "lib/ot/simple-text-operation.js",
    "content": "if (typeof ot === 'undefined') {\n  // Export for browsers\n  var ot = {};\n}\n\not.SimpleTextOperation = (function (global) {\n\n  var TextOperation = global.ot ? global.ot.TextOperation : require('./text-operation');\n\n  function SimpleTextOperation () {}\n\n\n  // Insert the string `str` at the zero-based `position` in the document.\n  function Insert (str, position) {\n    if (!this || this.constructor !== SimpleTextOperation) {\n      // => function was called without 'new'\n      return new Insert(str, position);\n    }\n    this.str = str;\n    this.position = position;\n  }\n\n  Insert.prototype = new SimpleTextOperation();\n  SimpleTextOperation.Insert = Insert;\n\n  Insert.prototype.toString = function () {\n    return 'Insert(' + JSON.stringify(this.str) + ', ' + this.position + ')';\n  };\n\n  Insert.prototype.equals = function (other) {\n    return other instanceof Insert &&\n      this.str === other.str &&\n      this.position === other.position;\n  };\n\n  Insert.prototype.apply = function (doc) {\n    return doc.slice(0, this.position) + this.str + doc.slice(this.position);\n  };\n\n\n  // Delete `count` many characters at the zero-based `position` in the document.\n  function Delete (count, position) {\n    if (!this || this.constructor !== SimpleTextOperation) {\n      return new Delete(count, position);\n    }\n    this.count = count;\n    this.position = position;\n  }\n\n  Delete.prototype = new SimpleTextOperation();\n  SimpleTextOperation.Delete = Delete;\n\n  Delete.prototype.toString = function () {\n    return 'Delete(' + this.count + ', ' + this.position + ')';\n  };\n\n  Delete.prototype.equals = function (other) {\n    return other instanceof Delete &&\n      this.count === other.count &&\n      this.position === other.position;\n  };\n\n  Delete.prototype.apply = function (doc) {\n    return doc.slice(0, this.position) + doc.slice(this.position + this.count);\n  };\n\n\n  // An operation that does nothing. This is needed for the result of the\n  // transformation of two deletions of the same character.\n  function Noop () {\n    if (!this || this.constructor !== SimpleTextOperation) { return new Noop(); }\n  }\n\n  Noop.prototype = new SimpleTextOperation();\n  SimpleTextOperation.Noop = Noop;\n\n  Noop.prototype.toString = function () {\n    return 'Noop()';\n  };\n\n  Noop.prototype.equals = function (other) { return other instanceof Noop; };\n\n  Noop.prototype.apply = function (doc) { return doc; };\n\n  var noop = new Noop();\n\n\n  SimpleTextOperation.transform = function (a, b) {\n    if (a instanceof Noop || b instanceof Noop) { return [a, b]; }\n\n    if (a instanceof Insert && b instanceof Insert) {\n      if (a.position < b.position || (a.position === b.position && a.str < b.str)) {\n        return [a, new Insert(b.str, b.position + a.str.length)];\n      }\n      if (a.position > b.position || (a.position === b.position && a.str > b.str)) {\n        return [new Insert(a.str, a.position + b.str.length), b];\n      }\n      return [noop, noop];\n    }\n\n    if (a instanceof Insert && b instanceof Delete) {\n      if (a.position <= b.position) {\n        return [a, new Delete(b.count, b.position + a.str.length)];\n      }\n      if (a.position >= b.position + b.count) {\n        return [new Insert(a.str, a.position - b.count), b];\n      }\n      // Here, we have to delete the inserted string of operation a.\n      // That doesn't preserve the intention of operation a, but it's the only\n      // thing we can do to get a valid transform function.\n      return [noop, new Delete(b.count + a.str.length, b.position)];\n    }\n\n    if (a instanceof Delete && b instanceof Insert) {\n      if (a.position >= b.position) {\n        return [new Delete(a.count, a.position + b.str.length), b];\n      }\n      if (a.position + a.count <= b.position) {\n        return [a, new Insert(b.str, b.position - a.count)];\n      }\n      // Same problem as above. We have to delete the string that was inserted\n      // in operation b.\n      return [new Delete(a.count + b.str.length, a.position), noop];\n    }\n\n    if (a instanceof Delete && b instanceof Delete) {\n      if (a.position === b.position) {\n        if (a.count === b.count) {\n          return [noop, noop];\n        } else if (a.count < b.count) {\n          return [noop, new Delete(b.count - a.count, b.position)];\n        }\n        return [new Delete(a.count - b.count, a.position), noop];\n      }\n      if (a.position < b.position) {\n        if (a.position + a.count <= b.position) {\n          return [a, new Delete(b.count, b.position - a.count)];\n        }\n        if (a.position + a.count >= b.position + b.count) {\n          return [new Delete(a.count - b.count, a.position), noop];\n        }\n        return [\n          new Delete(b.position - a.position, a.position),\n          new Delete(b.position + b.count - (a.position + a.count), a.position)\n        ];\n      }\n      if (a.position > b.position) {\n        if (a.position >= b.position + b.count) {\n          return [new Delete(a.count, a.position - b.count), b];\n        }\n        if (a.position + a.count <= b.position + b.count) {\n          return [noop, new Delete(b.count - a.count, b.position)];\n        }\n        return [\n          new Delete(a.position + a.count - (b.position + b.count), b.position),\n          new Delete(a.position - b.position, b.position)\n        ];\n      }\n    }\n  };\n\n  // Convert a normal, composable `TextOperation` into an array of\n  // `SimpleTextOperation`s.\n  SimpleTextOperation.fromTextOperation = function (operation) {\n    var simpleOperations = [];\n    var index = 0;\n    for (var i = 0; i < operation.ops.length; i++) {\n      var op = operation.ops[i];\n      if (TextOperation.isRetain(op)) {\n        index += op;\n      } else if (TextOperation.isInsert(op)) {\n        simpleOperations.push(new Insert(op, index));\n        index += op.length;\n      } else {\n        simpleOperations.push(new Delete(Math.abs(op), index));\n      }\n    }\n    return simpleOperations;\n  };\n\n\n  return SimpleTextOperation;\n})(this);\n\n// Export for CommonJS\nif (typeof module === 'object') {\n  module.exports = ot.SimpleTextOperation;\n}"
  },
  {
    "path": "lib/ot/text-operation.js",
    "content": "if (typeof ot === 'undefined') {\n  // Export for browsers\n  var ot = {};\n}\n\not.TextOperation = (function () {\n  'use strict';\n\n  // Constructor for new operations.\n  function TextOperation () {\n    if (!this || this.constructor !== TextOperation) {\n      // => function was called without 'new'\n      return new TextOperation();\n    }\n\n    // When an operation is applied to an input string, you can think of this as\n    // if an imaginary cursor runs over the entire string and skips over some\n    // parts, deletes some parts and inserts characters at some positions. These\n    // actions (skip/delete/insert) are stored as an array in the \"ops\" property.\n    this.ops = [];\n    // An operation's baseLength is the length of every string the operation\n    // can be applied to.\n    this.baseLength = 0;\n    // The targetLength is the length of every string that results from applying\n    // the operation on a valid input string.\n    this.targetLength = 0;\n  }\n\n  TextOperation.prototype.equals = function (other) {\n    if (this.baseLength !== other.baseLength) { return false; }\n    if (this.targetLength !== other.targetLength) { return false; }\n    if (this.ops.length !== other.ops.length) { return false; }\n    for (var i = 0; i < this.ops.length; i++) {\n      if (this.ops[i] !== other.ops[i]) { return false; }\n    }\n    return true;\n  };\n\n  // Operation are essentially lists of ops. There are three types of ops:\n  //\n  // * Retain ops: Advance the cursor position by a given number of characters.\n  //   Represented by positive ints.\n  // * Insert ops: Insert a given string at the current cursor position.\n  //   Represented by strings.\n  // * Delete ops: Delete the next n characters. Represented by negative ints.\n\n  var isRetain = TextOperation.isRetain = function (op) {\n    return typeof op === 'number' && op > 0;\n  };\n\n  var isInsert = TextOperation.isInsert = function (op) {\n    return typeof op === 'string';\n  };\n\n  var isDelete = TextOperation.isDelete = function (op) {\n    return typeof op === 'number' && op < 0;\n  };\n\n\n  // After an operation is constructed, the user of the library can specify the\n  // actions of an operation (skip/insert/delete) with these three builder\n  // methods. They all return the operation for convenient chaining.\n\n  // Skip over a given number of characters.\n  TextOperation.prototype.retain = function (n) {\n    if (typeof n !== 'number') {\n      throw new Error(\"retain expects an integer\");\n    }\n    if (n === 0) { return this; }\n    this.baseLength += n;\n    this.targetLength += n;\n    if (isRetain(this.ops[this.ops.length-1])) {\n      // The last op is a retain op => we can merge them into one op.\n      this.ops[this.ops.length-1] += n;\n    } else {\n      // Create a new op.\n      this.ops.push(n);\n    }\n    return this;\n  };\n\n  // Insert a string at the current position.\n  TextOperation.prototype.insert = function (str) {\n    if (typeof str !== 'string') {\n      throw new Error(\"insert expects a string\");\n    }\n    if (str === '') { return this; }\n    this.targetLength += str.length;\n    var ops = this.ops;\n    if (isInsert(ops[ops.length-1])) {\n      // Merge insert op.\n      ops[ops.length-1] += str;\n    } else if (isDelete(ops[ops.length-1])) {\n      // It doesn't matter when an operation is applied whether the operation\n      // is delete(3), insert(\"something\") or insert(\"something\"), delete(3).\n      // Here we enforce that in this case, the insert op always comes first.\n      // This makes all operations that have the same effect when applied to\n      // a document of the right length equal in respect to the `equals` method.\n      if (isInsert(ops[ops.length-2])) {\n        ops[ops.length-2] += str;\n      } else {\n        ops[ops.length] = ops[ops.length-1];\n        ops[ops.length-2] = str;\n      }\n    } else {\n      ops.push(str);\n    }\n    return this;\n  };\n\n  // Delete a string at the current position.\n  TextOperation.prototype['delete'] = function (n) {\n    if (typeof n === 'string') { n = n.length; }\n    if (typeof n !== 'number') {\n      throw new Error(\"delete expects an integer or a string\");\n    }\n    if (n === 0) { return this; }\n    if (n > 0) { n = -n; }\n    this.baseLength -= n;\n    if (isDelete(this.ops[this.ops.length-1])) {\n      this.ops[this.ops.length-1] += n;\n    } else {\n      this.ops.push(n);\n    }\n    return this;\n  };\n\n  // Tests whether this operation has no effect.\n  TextOperation.prototype.isNoop = function () {\n    return this.ops.length === 0 || (this.ops.length === 1 && isRetain(this.ops[0]));\n  };\n\n  // Pretty printing.\n  TextOperation.prototype.toString = function () {\n    // map: build a new array by applying a function to every element in an old\n    // array.\n    var map = Array.prototype.map || function (fn) {\n      var arr = this;\n      var newArr = [];\n      for (var i = 0, l = arr.length; i < l; i++) {\n        newArr[i] = fn(arr[i]);\n      }\n      return newArr;\n    };\n    return map.call(this.ops, function (op) {\n      if (isRetain(op)) {\n        return \"retain \" + op;\n      } else if (isInsert(op)) {\n        return \"insert '\" + op + \"'\";\n      } else {\n        return \"delete \" + (-op);\n      }\n    }).join(', ');\n  };\n\n  // Converts operation into a JSON value.\n  TextOperation.prototype.toJSON = function () {\n    return this.ops;\n  };\n\n  // Converts a plain JS object into an operation and validates it.\n  TextOperation.fromJSON = function (ops) {\n    var o = new TextOperation();\n    for (var i = 0, l = ops.length; i < l; i++) {\n      var op = ops[i];\n      if (isRetain(op)) {\n        o.retain(op);\n      } else if (isInsert(op)) {\n        o.insert(op);\n      } else if (isDelete(op)) {\n        o['delete'](op);\n      } else {\n        throw new Error(\"unknown operation: \" + JSON.stringify(op));\n      }\n    }\n    return o;\n  };\n\n  // Apply an operation to a string, returning a new string. Throws an error if\n  // there's a mismatch between the input string and the operation.\n  TextOperation.prototype.apply = function (str) {\n    var operation = this;\n    if (str.length !== operation.baseLength) {\n      throw new Error(\"The operation's base length must be equal to the string's length.\");\n    }\n    var newStr = [], j = 0;\n    var strIndex = 0;\n    var ops = this.ops;\n    for (var i = 0, l = ops.length; i < l; i++) {\n      var op = ops[i];\n      if (isRetain(op)) {\n        if (strIndex + op > str.length) {\n          throw new Error(\"Operation can't retain more characters than are left in the string.\");\n        }\n        // Copy skipped part of the old string.\n        newStr[j++] = str.slice(strIndex, strIndex + op);\n        strIndex += op;\n      } else if (isInsert(op)) {\n        // Insert string.\n        newStr[j++] = op;\n      } else { // delete op\n        strIndex -= op;\n      }\n    }\n    if (strIndex !== str.length) {\n      throw new Error(\"The operation didn't operate on the whole string.\");\n    }\n    return newStr.join('');\n  };\n\n  // Computes the inverse of an operation. The inverse of an operation is the\n  // operation that reverts the effects of the operation, e.g. when you have an\n  // operation 'insert(\"hello \"); skip(6);' then the inverse is 'delete(\"hello \");\n  // skip(6);'. The inverse should be used for implementing undo.\n  TextOperation.prototype.invert = function (str) {\n    var strIndex = 0;\n    var inverse = new TextOperation();\n    var ops = this.ops;\n    for (var i = 0, l = ops.length; i < l; i++) {\n      var op = ops[i];\n      if (isRetain(op)) {\n        inverse.retain(op);\n        strIndex += op;\n      } else if (isInsert(op)) {\n        inverse['delete'](op.length);\n      } else { // delete op\n        inverse.insert(str.slice(strIndex, strIndex - op));\n        strIndex -= op;\n      }\n    }\n    return inverse;\n  };\n\n  // Compose merges two consecutive operations into one operation, that\n  // preserves the changes of both. Or, in other words, for each input string S\n  // and a pair of consecutive operations A and B,\n  // apply(apply(S, A), B) = apply(S, compose(A, B)) must hold.\n  TextOperation.prototype.compose = function (operation2) {\n    var operation1 = this;\n    if (operation1.targetLength !== operation2.baseLength) {\n      throw new Error(\"The base length of the second operation has to be the target length of the first operation\");\n    }\n\n    var operation = new TextOperation(); // the combined operation\n    var ops1 = operation1.ops, ops2 = operation2.ops; // for fast access\n    var i1 = 0, i2 = 0; // current index into ops1 respectively ops2\n    var op1 = ops1[i1++], op2 = ops2[i2++]; // current ops\n    while (true) {\n      // Dispatch on the type of op1 and op2\n      if (typeof op1 === 'undefined' && typeof op2 === 'undefined') {\n        // end condition: both ops1 and ops2 have been processed\n        break;\n      }\n\n      if (isDelete(op1)) {\n        operation['delete'](op1);\n        op1 = ops1[i1++];\n        continue;\n      }\n      if (isInsert(op2)) {\n        operation.insert(op2);\n        op2 = ops2[i2++];\n        continue;\n      }\n\n      if (typeof op1 === 'undefined') {\n        throw new Error(\"Cannot compose operations: first operation is too short.\");\n      }\n      if (typeof op2 === 'undefined') {\n        throw new Error(\"Cannot compose operations: first operation is too long.\");\n      }\n\n      if (isRetain(op1) && isRetain(op2)) {\n        if (op1 > op2) {\n          operation.retain(op2);\n          op1 = op1 - op2;\n          op2 = ops2[i2++];\n        } else if (op1 === op2) {\n          operation.retain(op1);\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          operation.retain(op1);\n          op2 = op2 - op1;\n          op1 = ops1[i1++];\n        }\n      } else if (isInsert(op1) && isDelete(op2)) {\n        if (op1.length > -op2) {\n          op1 = op1.slice(-op2);\n          op2 = ops2[i2++];\n        } else if (op1.length === -op2) {\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          op2 = op2 + op1.length;\n          op1 = ops1[i1++];\n        }\n      } else if (isInsert(op1) && isRetain(op2)) {\n        if (op1.length > op2) {\n          operation.insert(op1.slice(0, op2));\n          op1 = op1.slice(op2);\n          op2 = ops2[i2++];\n        } else if (op1.length === op2) {\n          operation.insert(op1);\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          operation.insert(op1);\n          op2 = op2 - op1.length;\n          op1 = ops1[i1++];\n        }\n      } else if (isRetain(op1) && isDelete(op2)) {\n        if (op1 > -op2) {\n          operation['delete'](op2);\n          op1 = op1 + op2;\n          op2 = ops2[i2++];\n        } else if (op1 === -op2) {\n          operation['delete'](op2);\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          operation['delete'](op1);\n          op2 = op2 + op1;\n          op1 = ops1[i1++];\n        }\n      } else {\n        throw new Error(\n          \"This shouldn't happen: op1: \" +\n          JSON.stringify(op1) + \", op2: \" +\n          JSON.stringify(op2)\n        );\n      }\n    }\n    return operation;\n  };\n\n  function getSimpleOp (operation, fn) {\n    var ops = operation.ops;\n    var isRetain = TextOperation.isRetain;\n    switch (ops.length) {\n    case 1:\n      return ops[0];\n    case 2:\n      return isRetain(ops[0]) ? ops[1] : (isRetain(ops[1]) ? ops[0] : null);\n    case 3:\n      if (isRetain(ops[0]) && isRetain(ops[2])) { return ops[1]; }\n    }\n    return null;\n  }\n\n  function getStartIndex (operation) {\n    if (isRetain(operation.ops[0])) { return operation.ops[0]; }\n    return 0;\n  }\n\n  // When you use ctrl-z to undo your latest changes, you expect the program not\n  // to undo every single keystroke but to undo your last sentence you wrote at\n  // a stretch or the deletion you did by holding the backspace key down. This\n  // This can be implemented by composing operations on the undo stack. This\n  // method can help decide whether two operations should be composed. It\n  // returns true if the operations are consecutive insert operations or both\n  // operations delete text at the same position. You may want to include other\n  // factors like the time since the last change in your decision.\n  TextOperation.prototype.shouldBeComposedWith = function (other) {\n    if (this.isNoop() || other.isNoop()) { return true; }\n\n    var startA = getStartIndex(this), startB = getStartIndex(other);\n    var simpleA = getSimpleOp(this), simpleB = getSimpleOp(other);\n    if (!simpleA || !simpleB) { return false; }\n\n    if (isInsert(simpleA) && isInsert(simpleB)) {\n      return startA + simpleA.length === startB;\n    }\n\n    if (isDelete(simpleA) && isDelete(simpleB)) {\n      // there are two possibilities to delete: with backspace and with the\n      // delete key.\n      return (startB - simpleB === startA) || startA === startB;\n    }\n\n    return false;\n  };\n\n  // Decides whether two operations should be composed with each other\n  // if they were inverted, that is\n  // `shouldBeComposedWith(a, b) = shouldBeComposedWithInverted(b^{-1}, a^{-1})`.\n  TextOperation.prototype.shouldBeComposedWithInverted = function (other) {\n    if (this.isNoop() || other.isNoop()) { return true; }\n\n    var startA = getStartIndex(this), startB = getStartIndex(other);\n    var simpleA = getSimpleOp(this), simpleB = getSimpleOp(other);\n    if (!simpleA || !simpleB) { return false; }\n\n    if (isInsert(simpleA) && isInsert(simpleB)) {\n      return startA + simpleA.length === startB || startA === startB;\n    }\n\n    if (isDelete(simpleA) && isDelete(simpleB)) {\n      return startB - simpleB === startA;\n    }\n\n    return false;\n  };\n\n  // Transform takes two operations A and B that happened concurrently and\n  // produces two operations A' and B' (in an array) such that\n  // `apply(apply(S, A), B') = apply(apply(S, B), A')`. This function is the\n  // heart of OT.\n  TextOperation.transform = function (operation1, operation2) {\n    if (operation1.baseLength !== operation2.baseLength) {\n      throw new Error(\"Both operations have to have the same base length\");\n    }\n\n    var operation1prime = new TextOperation();\n    var operation2prime = new TextOperation();\n    var ops1 = operation1.ops, ops2 = operation2.ops;\n    var i1 = 0, i2 = 0;\n    var op1 = ops1[i1++], op2 = ops2[i2++];\n    while (true) {\n      // At every iteration of the loop, the imaginary cursor that both\n      // operation1 and operation2 have that operates on the input string must\n      // have the same position in the input string.\n\n      if (typeof op1 === 'undefined' && typeof op2 === 'undefined') {\n        // end condition: both ops1 and ops2 have been processed\n        break;\n      }\n\n      // next two cases: one or both ops are insert ops\n      // => insert the string in the corresponding prime operation, skip it in\n      // the other one. If both op1 and op2 are insert ops, prefer op1.\n      if (isInsert(op1)) {\n        operation1prime.insert(op1);\n        operation2prime.retain(op1.length);\n        op1 = ops1[i1++];\n        continue;\n      }\n      if (isInsert(op2)) {\n        operation1prime.retain(op2.length);\n        operation2prime.insert(op2);\n        op2 = ops2[i2++];\n        continue;\n      }\n\n      if (typeof op1 === 'undefined') {\n        throw new Error(\"Cannot compose operations: first operation is too short.\");\n      }\n      if (typeof op2 === 'undefined') {\n        throw new Error(\"Cannot compose operations: first operation is too long.\");\n      }\n\n      var minl;\n      if (isRetain(op1) && isRetain(op2)) {\n        // Simple case: retain/retain\n        if (op1 > op2) {\n          minl = op2;\n          op1 = op1 - op2;\n          op2 = ops2[i2++];\n        } else if (op1 === op2) {\n          minl = op2;\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          minl = op1;\n          op2 = op2 - op1;\n          op1 = ops1[i1++];\n        }\n        operation1prime.retain(minl);\n        operation2prime.retain(minl);\n      } else if (isDelete(op1) && isDelete(op2)) {\n        // Both operations delete the same string at the same position. We don't\n        // need to produce any operations, we just skip over the delete ops and\n        // handle the case that one operation deletes more than the other.\n        if (-op1 > -op2) {\n          op1 = op1 - op2;\n          op2 = ops2[i2++];\n        } else if (op1 === op2) {\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          op2 = op2 - op1;\n          op1 = ops1[i1++];\n        }\n      // next two cases: delete/retain and retain/delete\n      } else if (isDelete(op1) && isRetain(op2)) {\n        if (-op1 > op2) {\n          minl = op2;\n          op1 = op1 + op2;\n          op2 = ops2[i2++];\n        } else if (-op1 === op2) {\n          minl = op2;\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          minl = -op1;\n          op2 = op2 + op1;\n          op1 = ops1[i1++];\n        }\n        operation1prime['delete'](minl);\n      } else if (isRetain(op1) && isDelete(op2)) {\n        if (op1 > -op2) {\n          minl = -op2;\n          op1 = op1 + op2;\n          op2 = ops2[i2++];\n        } else if (op1 === -op2) {\n          minl = op1;\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          minl = op1;\n          op2 = op2 + op1;\n          op1 = ops1[i1++];\n        }\n        operation2prime['delete'](minl);\n      } else {\n        throw new Error(\"The two operations aren't compatible\");\n      }\n    }\n\n    return [operation1prime, operation2prime];\n  };\n\n  return TextOperation;\n\n}());\n\n// Export for CommonJS\nif (typeof module === 'object') {\n  module.exports = ot.TextOperation;\n}"
  },
  {
    "path": "lib/ot/wrapped-operation.js",
    "content": "if (typeof ot === 'undefined') {\n  // Export for browsers\n  var ot = {};\n}\n\not.WrappedOperation = (function (global) {\n  'use strict';\n\n  // A WrappedOperation contains an operation and corresponing metadata.\n  function WrappedOperation (operation, meta) {\n    this.wrapped = operation;\n    this.meta    = meta;\n  }\n\n  WrappedOperation.prototype.apply = function () {\n    return this.wrapped.apply.apply(this.wrapped, arguments);\n  };\n\n  WrappedOperation.prototype.invert = function () {\n    var meta = this.meta;\n    return new WrappedOperation(\n      this.wrapped.invert.apply(this.wrapped, arguments),\n      meta && typeof meta === 'object' && typeof meta.invert === 'function' ?\n        meta.invert.apply(meta, arguments) : meta\n    );\n  };\n\n  // Copy all properties from source to target.\n  function copy (source, target) {\n    for (var key in source) {\n      if (source.hasOwnProperty(key)) {\n        target[key] = source[key];\n      }\n    }\n  }\n\n  function composeMeta (a, b) {\n    if (a && typeof a === 'object') {\n      if (typeof a.compose === 'function') { return a.compose(b); }\n      var meta = {};\n      copy(a, meta);\n      copy(b, meta);\n      return meta;\n    }\n    return b;\n  }\n\n  WrappedOperation.prototype.compose = function (other) {\n    return new WrappedOperation(\n      this.wrapped.compose(other.wrapped),\n      composeMeta(this.meta, other.meta)\n    );\n  };\n\n  function transformMeta (meta, operation) {\n    if (meta && typeof meta === 'object') {\n      if (typeof meta.transform === 'function') {\n        return meta.transform(operation);\n      }\n    }\n    return meta;\n  }\n\n  WrappedOperation.transform = function (a, b) {\n    var transform = a.wrapped.constructor.transform;\n    var pair = transform(a.wrapped, b.wrapped);\n    return [\n      new WrappedOperation(pair[0], transformMeta(a.meta, b.wrapped)),\n      new WrappedOperation(pair[1], transformMeta(b.meta, a.wrapped))\n    ];\n  };\n\n  return WrappedOperation;\n\n}(this));\n\n// Export for CommonJS\nif (typeof module === 'object') {\n  module.exports = ot.WrappedOperation;\n}"
  },
  {
    "path": "lib/realtime/processQueue.js",
    "content": "'use strict'\n\nconst EventEmitter = require('events').EventEmitter\n\n/**\n * Queuing Class for connection queuing\n */\n\nconst QueueEvent = {\n  Tick: 'Tick',\n  Push: 'Push',\n  Finish: 'Finish'\n}\n\nclass ProcessQueue extends EventEmitter {\n  constructor ({\n    maximumLength = 500,\n    triggerTimeInterval = 5000,\n    // execute on push\n    proactiveMode = true,\n    // execute next work on finish\n    continuousMode = true\n  }) {\n    super()\n    this.max = maximumLength\n    this.triggerTime = triggerTimeInterval\n    this.taskMap = new Map()\n    this.queue = []\n    this.lock = false\n\n    this.on(QueueEvent.Tick, this.onEventProcessFunc.bind(this))\n    if (proactiveMode) {\n      this.on(QueueEvent.Push, this.onEventProcessFunc.bind(this))\n    }\n    if (continuousMode) {\n      this.on(QueueEvent.Finish, this.onEventProcessFunc.bind(this))\n    }\n  }\n\n  onEventProcessFunc () {\n    if (this.lock) return\n    this.lock = true\n    setImmediate(() => {\n      this.process()\n    })\n  }\n\n  start () {\n    if (this.eventTrigger) return\n    this.eventTrigger = setInterval(() => {\n      this.emit(QueueEvent.Tick)\n    }, this.triggerTime)\n  }\n\n  stop () {\n    if (this.eventTrigger) {\n      clearInterval(this.eventTrigger)\n      this.eventTrigger = null\n    }\n  }\n\n  checkTaskIsInQueue (id) {\n    return this.taskMap.has(id)\n  }\n\n  /**\n   * pushWithKey a promisify-task to queue\n   * @param id {string}\n   * @param processingFunc {Function<Promise>}\n   * @returns {boolean} if success return true, otherwise false\n   */\n  push (id, processingFunc) {\n    if (this.queue.length >= this.max) return false\n    if (this.checkTaskIsInQueue(id)) return false\n    const task = {\n      id: id,\n      processingFunc: processingFunc\n    }\n    this.taskMap.set(id, true)\n    this.queue.push(task)\n    this.start()\n    this.emit(QueueEvent.Push)\n    return true\n  }\n\n  process () {\n    if (this.queue.length <= 0) {\n      this.stop()\n      this.lock = false\n      return\n    }\n\n    const task = this.queue.shift()\n    this.taskMap.delete(task.id)\n\n    const finishTask = () => {\n      this.lock = false\n      setImmediate(() => {\n        this.emit(QueueEvent.Finish)\n      })\n    }\n    task.processingFunc().then(finishTask).catch(finishTask)\n  }\n}\n\nexports.ProcessQueue = ProcessQueue\n"
  },
  {
    "path": "lib/realtime/realtime.js",
    "content": "'use strict'\n// realtime\n// external modules\nconst cookie = require('cookie')\nconst cookieParser = require('cookie-parser')\nconst url = require('url')\nconst randomcolor = require('randomcolor')\nconst Chance = require('chance')\nconst chance = new Chance()\nconst moment = require('moment')\n\nconst get = require('lodash/get')\n\n// core\nconst config = require('../config')\nconst logger = require('../logger')\nconst history = require('../history')\nconst models = require('../models')\n\n// ot\nconst ot = require('../ot')\n\nconst { ProcessQueue } = require('./processQueue')\nconst { RealtimeClientConnection } = require('./realtimeClientConnection')\nconst { UpdateDirtyNoteJob } = require('./realtimeUpdateDirtyNoteJob')\nconst { CleanDanglingUserJob } = require('./realtimeCleanDanglingUserJob')\nconst { SaveRevisionJob } = require('./realtimeSaveRevisionJob')\n\n// public\nconst realtime = {\n  io: null,\n  onAuthorizeSuccess: onAuthorizeSuccess,\n  onAuthorizeFail: onAuthorizeFail,\n  secure: secure,\n  connection: connection,\n  getStatus: getStatus,\n  isReady: isReady,\n  maintenance: true\n}\n\nconst connectProcessQueue = new ProcessQueue({})\nconst disconnectProcessQueue = new ProcessQueue({})\nconst updateDirtyNoteJob = new UpdateDirtyNoteJob(realtime)\nconst cleanDanglingUserJob = new CleanDanglingUserJob(realtime)\nconst saveRevisionJob = new SaveRevisionJob(realtime)\n\n// TODO: test it\nfunction onAuthorizeSuccess (data, accept) {\n  accept()\n}\n\n// TODO: test it\nfunction onAuthorizeFail (data, message, error, accept) {\n  accept() // accept whether authorize or not to allow anonymous usage\n}\n\n// TODO: test it\n// secure the origin by the cookie\nfunction secure (socket, next) {\n  try {\n    var handshakeData = socket.request\n    if (handshakeData.headers.cookie) {\n      handshakeData.cookie = cookie.parse(handshakeData.headers.cookie)\n      handshakeData.sessionID = cookieParser.signedCookie(handshakeData.cookie[config.sessionName], config.sessionSecret)\n      if (handshakeData.sessionID &&\n        handshakeData.cookie[config.sessionName] &&\n        handshakeData.cookie[config.sessionName] !== handshakeData.sessionID) {\n        if (config.debug) {\n          logger.info('AUTH success cookie: ' + handshakeData.sessionID)\n        }\n        return next()\n      } else {\n        next(new Error('AUTH failed: Cookie is invalid.'))\n      }\n    } else {\n      next(new Error('AUTH failed: No cookie transmitted.'))\n    }\n  } catch (ex) {\n    next(new Error('AUTH failed:' + JSON.stringify(ex)))\n  }\n}\n\n// TODO: only use in `updateDirtyNote`\n// TODO: test it\nfunction emitCheck (note) {\n  var out = {\n    title: note.title,\n    updatetime: note.updatetime,\n    lastchangeuser: note.lastchangeuser,\n    lastchangeuserprofile: note.lastchangeuserprofile,\n    authors: note.authors,\n    authorship: note.authorship\n  }\n  realtime.io.to(note.id).emit('check', out)\n}\n\n// actions\nvar users = {}\nvar notes = {}\n\nfunction getNotePool () {\n  return notes\n}\n\nfunction isNoteExistsInPool (noteId) {\n  return !!notes[noteId]\n}\n\nfunction addNote (note) {\n  if (exports.isNoteExistsInPool(note.id)) return false\n  notes[note.id] = note\n  return true\n}\n\nfunction getNotePoolSize () {\n  return Object.keys(notes).length\n}\n\nfunction deleteNoteFromPool (noteId) {\n  delete notes[noteId]\n}\n\nfunction deleteAllNoteFromPool () {\n  Object.keys(notes).forEach(noteId => {\n    delete notes[noteId]\n  })\n}\n\nfunction getNoteFromNotePool (noteId) {\n  return notes[noteId]\n}\n\nfunction getUserPool () {\n  return users\n}\n\nfunction getUserFromUserPool (userId) {\n  return users[userId]\n}\n\ndisconnectProcessQueue.start()\nupdateDirtyNoteJob.start()\ncleanDanglingUserJob.start()\nsaveRevisionJob.start()\n\nfunction disconnectSocketOnNote (note) {\n  note.socks.forEach((sock) => {\n    if (sock) {\n      sock.emit('delete')\n      setImmediate(() => {\n        sock.disconnect(true)\n      })\n    }\n  })\n}\n\nfunction updateNote (note, callback) {\n  _updateNoteAsync(note).then(_note => {\n    callback(null, _note)\n  }).catch((err) => {\n    logger.error(err)\n    return callback(err, null)\n  })\n}\n\nfunction findNoteByIdAsync (id) {\n  return models.Note.findOne({\n    where: {\n      id: id\n    }\n  })\n}\n\nfunction updateHistoryForEveryUserCollaborateNote (note) {\n  // update history to every user in this note\n  const tempUsers = Object.assign({}, note.tempUsers)\n  note.tempUsers = {}\n  // update history should async function, but in there return values is not matter\n  Object.keys(tempUsers).forEach(function (key) {\n    exports.updateHistory(key, note, tempUsers[key])\n  })\n}\n\nasync function getUserProfileByIdAsync (id) {\n  const user = await models.User.findOne({\n    where: {\n      id: id\n    }\n  })\n  if (!user) return null\n  return models.User.getProfile(user)\n}\n\nclass UserNotFoundException extends Error {\n  constructor () {\n    super('user not found')\n    this.name = this.constructor.name\n    Error.captureStackTrace(this, this.constructor)\n  }\n}\n\nasync function getLastChangeUserProfileAsync (currentLastChangeUserId, lastChangeUserIdInDatabase, lastChangeUserProfileInDatabase) {\n  if (!currentLastChangeUserId) return null\n  if (currentLastChangeUserId === lastChangeUserIdInDatabase) return lastChangeUserProfileInDatabase\n  const profile = await getUserProfileByIdAsync(currentLastChangeUserId)\n  if (!profile) {\n    throw new UserNotFoundException()\n  }\n  return profile\n}\n\nfunction buildNoteUpdateData (note) {\n  const body = note.server.document\n  const title = note.title = models.Note.parseNoteTitle(body)\n  return {\n    title: title,\n    content: body,\n    authorship: note.authorship,\n    lastchangeuserId: note.lastchangeuser,\n    lastchangeAt: Date.now()\n  }\n}\n\nasync function _updateNoteAsync (note) {\n  let noteModel = await findNoteByIdAsync(note.id)\n  if (!noteModel) return null\n\n  updateHistoryForEveryUserCollaborateNote(note)\n\n  try {\n    note.lastchangeuserprofile = await getLastChangeUserProfileAsync(\n      note.lastchangeuser,\n      noteModel.lastchangeuserId,\n      noteModel.lastchangeuserprofile\n    )\n  } catch (err) {\n    if (err instanceof UserNotFoundException) {\n      return null\n    }\n    throw err\n  }\n\n  if (!note || !note.server) return null\n  noteModel = await noteModel.update(buildNoteUpdateData(note))\n  saveRevisionJob.setSaverSleep(false)\n  return noteModel\n}\n\n// TODO: test it\nfunction getStatus () {\n  return models.Note.count()\n    .then(function (notecount) {\n      var distinctaddresses = []\n      var regaddresses = []\n      var distinctregaddresses = []\n      Object.keys(users).forEach(function (key) {\n        var user = users[key]\n        if (!user) return\n        let found = false\n        for (let i = 0; i < distinctaddresses.length; i++) {\n          if (user.address === distinctaddresses[i]) {\n            found = true\n            break\n          }\n        }\n        if (!found) {\n          distinctaddresses.push(user.address)\n        }\n        if (user.login) {\n          regaddresses.push(user.address)\n          let found = false\n          for (let i = 0; i < distinctregaddresses.length; i++) {\n            if (user.address === distinctregaddresses[i]) {\n              found = true\n              break\n            }\n          }\n          if (!found) {\n            distinctregaddresses.push(user.address)\n          }\n        }\n      })\n\n      return models.User.count()\n        .then(function (regcount) {\n          return {\n            onlineNotes: Object.keys(notes).length,\n            onlineUsers: Object.keys(users).length,\n            distinctOnlineUsers: distinctaddresses.length,\n            notesCount: notecount,\n            registeredUsers: regcount,\n            onlineRegisteredUsers: regaddresses.length,\n            distinctOnlineRegisteredUsers: distinctregaddresses.length,\n            isConnectionBusy: connectProcessQueue.lock,\n            connectionSocketQueueLength: connectProcessQueue.queue.length,\n            isDisconnectBusy: disconnectProcessQueue.lock,\n            disconnectSocketQueueLength: disconnectProcessQueue.queue.length\n          }\n        })\n        .catch(function (err) {\n          logger.error('count user failed: ' + err)\n          return Promise.reject(new Error('count user failed: ' + err))\n        })\n    }).catch(function (err) {\n      logger.error('count note failed: ' + err)\n      return Promise.reject(new Error('count note failed: ' + err))\n    })\n}\n\n// TODO: test it\nfunction isReady () {\n  return realtime.io &&\n    Object.keys(notes).length === 0 && Object.keys(users).length === 0 &&\n    connectProcessQueue.queue.length === 0 && !connectProcessQueue.lock &&\n    disconnectProcessQueue.queue.length === 0 && !disconnectProcessQueue.lock\n}\n\nfunction parseUrl (data) {\n  try {\n    if (url.URL) {\n      return new url.URL(data)\n    } else {\n      // fallback legacy api\n      // eslint-disable-next-line\n      return url.parse(data)\n    }\n  } catch (e) {\n  }\n  return null\n}\n\nfunction extractNoteIdFromSocket (socket) {\n  function extractNoteIdFromReferer (referer) {\n    if (referer) {\n      const hostUrl = parseUrl(referer)\n      if (!hostUrl) {\n        return false\n      }\n      if (config.urlPath) {\n        return hostUrl.pathname.slice(config.urlPath.length + 1, hostUrl.pathname.length).split('/')[1]\n      }\n      return hostUrl.pathname.split('/')[1]\n    }\n    return false\n  }\n\n  if (!socket || !socket.handshake) {\n    return false\n  }\n\n  if (get(socket, 'handshake.query.noteId')) {\n    return decodeURIComponent(socket.handshake.query.noteId)\n  }\n\n  const referer = get(socket, 'handshake.headers.referer')\n  if (referer) {\n    // this part is only for backward compatibility only; current code\n    // should be using noteId query parameter instead.\n    return extractNoteIdFromReferer(referer)\n  }\n\n  return false\n}\n\nasync function parseNoteIdFromSocketAsync (socket) {\n  const noteId = extractNoteIdFromSocket(socket)\n  if (!noteId) {\n    return null\n  }\n\n  return new Promise((resolve, reject) => {\n    models.Note.parseNoteId(noteId, function (err, id) {\n      if (err) {\n        reject(err)\n      }\n      if (!id) {\n        resolve(null)\n      }\n      resolve(id)\n    })\n  })\n}\n\n// TODO: test it\nfunction emitOnlineUsers (socket) {\n  var noteId = socket.noteId\n  if (!noteId || !notes[noteId]) return\n  var users = []\n  Object.keys(notes[noteId].users).forEach(function (key) {\n    var user = notes[noteId].users[key]\n    if (user) {\n      users.push(buildUserOutData(user))\n    }\n  })\n  var out = {\n    users: users\n  }\n  realtime.io.to(noteId).emit('online users', out)\n}\n\n// TODO: test it\nfunction emitUserStatus (socket) {\n  var noteId = socket.noteId\n  var user = users[socket.id]\n  if (!noteId || !notes[noteId] || !user) return\n  var out = buildUserOutData(user)\n  socket.broadcast.to(noteId).emit('user status', out)\n}\n\n// TODO: test it\nfunction emitRefresh (socket) {\n  var noteId = socket.noteId\n  if (!noteId || !notes[noteId]) return\n  var note = notes[noteId]\n  var out = {\n    title: note.title,\n    docmaxlength: config.documentMaxLength,\n    owner: note.owner,\n    ownerprofile: note.ownerprofile,\n    lastchangeuser: note.lastchangeuser,\n    lastchangeuserprofile: note.lastchangeuserprofile,\n    authors: note.authors,\n    authorship: note.authorship,\n    permission: note.permission,\n    createtime: note.createtime,\n    updatetime: note.updatetime\n  }\n  socket.emit('refresh', out)\n}\n\nfunction checkViewPermission (req, note) {\n  if (note.permission === 'private') {\n    if (req.user && req.user.logged_in && req.user.id === note.owner) {\n      return true\n    } else {\n      return false\n    }\n  } else if (note.permission === 'limited' || note.permission === 'protected') {\n    if (req.user && req.user.logged_in) {\n      return true\n    } else {\n      return false\n    }\n  } else {\n    return true\n  }\n}\n\n// TODO: test it\nasync function fetchFullNoteAsync (noteId) {\n  return models.Note.findOne({\n    where: {\n      id: noteId\n    },\n    include: [{\n      model: models.User,\n      as: 'owner'\n    }, {\n      model: models.User,\n      as: 'lastchangeuser'\n    }, {\n      model: models.Author,\n      as: 'authors',\n      include: [{\n        model: models.User,\n        as: 'user'\n      }]\n    }]\n  })\n}\n\nfunction buildAuthorProfilesFromNote (noteAuthors) {\n  const authors = {}\n  noteAuthors.forEach((author) => {\n    const profile = models.User.getProfile(author.user)\n    if (profile) {\n      authors[author.userId] = {\n        userid: author.userId,\n        color: author.color,\n        photo: profile.photo,\n        name: profile.name\n      }\n    }\n  })\n  return authors\n}\n\nfunction makeNewServerNote (note) {\n  const authors = buildAuthorProfilesFromNote(note.authors)\n\n  return {\n    id: note.id,\n    alias: note.alias,\n    title: note.title,\n    owner: note.ownerId,\n    ownerprofile: note.owner ? models.User.getProfile(note.owner) : null,\n    permission: note.permission,\n    lastchangeuser: note.lastchangeuserId,\n    lastchangeuserprofile: note.lastchangeuser ? models.User.getProfile(note.lastchangeuser) : null,\n    socks: [],\n    users: {},\n    tempUsers: {},\n    createtime: moment(note.createdAt).valueOf(),\n    updatetime: moment(note.lastchangeAt).valueOf(),\n    server: new ot.EditorSocketIOServer(note.content, [], note.id, ifMayEdit, operationCallback),\n    authors: authors,\n    authorship: note.authorship\n  }\n}\n\n// TODO: test it\nfunction failConnection (code, err, socket) {\n  logger.error(err)\n  // emit error info\n  socket.emit('info', {\n    code: code\n  })\n  return socket.disconnect(true)\n}\n\nfunction queueForDisconnect (socket) {\n  disconnectProcessQueue.push(socket.id, async function () {\n    if (users[socket.id]) {\n      delete users[socket.id]\n    }\n    const noteId = socket.noteId\n    const note = notes[noteId]\n    if (note) {\n      // delete user in users\n      if (note.users[socket.id]) {\n        delete note.users[socket.id]\n      }\n      // remove sockets in the note socks\n      let index\n      do {\n        index = note.socks.indexOf(socket)\n        if (index !== -1) {\n          note.socks.splice(index, 1)\n        }\n      } while (index !== -1)\n      // remove note in notes if no user inside\n      if (Object.keys(note.users).length === 0) {\n        if (note.server.isDirty) {\n          exports.updateNote(note, function (err, _note) {\n            if (err) return logger.error('disconnect note failed: ' + err)\n            // clear server before delete to avoid memory leaks\n            note.server.document = ''\n            note.server.operations = []\n            delete note.server\n            delete notes[noteId]\n          })\n        } else {\n          delete note.server\n          delete notes[noteId]\n        }\n      }\n    }\n    exports.emitOnlineUsers(socket)\n  })\n}\n\nfunction buildUserOutData (user) {\n  var out = {\n    id: user.id,\n    login: user.login,\n    userid: user.userid,\n    photo: user.photo,\n    color: user.color,\n    cursor: user.cursor,\n    name: user.name,\n    idle: user.idle,\n    type: user.type\n  }\n  return out\n}\n\n// TODO: test it\nfunction updateUserData (socket, user) {\n  // retrieve user data from passport\n  if (socket.request.user && socket.request.user.logged_in) {\n    var profile = models.User.getProfile(socket.request.user)\n    user.photo = profile.photo\n    user.name = profile.name\n    user.userid = socket.request.user.id\n    user.login = true\n  } else {\n    user.userid = null\n    user.name = 'Guest ' + chance.animal()\n    user.login = false\n  }\n}\n\nfunction canEditNote (notePermission, noteOwnerId, currentUserId) {\n  switch (notePermission) {\n    case 'freely':\n      return true\n    case 'editable':\n    case 'limited':\n      // only login user can change\n      return !!currentUserId\n    case 'locked':\n    case 'private':\n    case 'protected':\n      // only owner can change\n      return noteOwnerId === currentUserId\n  }\n}\n\nfunction ifMayEdit (socket, callback) {\n  const note = getNoteFromNotePool(socket.noteId)\n  if (!note) return\n  const mayEdit = canEditNote(note.permission, note.owner, socket.request.user.id)\n  // if user may edit and this is a text operation\n  if (socket.origin === 'operation' && mayEdit) {\n    // save for the last change user id\n    if (socket.request.user && socket.request.user.logged_in) {\n      note.lastchangeuser = socket.request.user.id\n    } else {\n      note.lastchangeuser = null\n    }\n  }\n  return callback(mayEdit)\n}\n\n// TODO: test it\nfunction operationCallback (socket, operation) {\n  var noteId = socket.noteId\n  if (!noteId || !notes[noteId]) return\n  var note = notes[noteId]\n  var userId = null\n  // save authors\n  if (socket.request.user && socket.request.user.logged_in) {\n    var user = users[socket.id]\n    if (!user) return\n    userId = socket.request.user.id\n    if (!note.authors[userId]) {\n      models.Author.findOrCreate({\n        where: {\n          noteId: noteId,\n          userId: userId\n        },\n        defaults: {\n          noteId: noteId,\n          userId: userId,\n          color: user.color\n        }\n      }).spread(function (author, created) {\n        if (author) {\n          note.authors[author.userId] = {\n            userid: author.userId,\n            color: author.color,\n            photo: user.photo,\n            name: user.name\n          }\n        }\n      }).catch(function (err) {\n        return logger.error('operation callback failed: ' + err)\n      })\n    }\n    note.tempUsers[userId] = Date.now()\n  }\n  // save authorship - use timer here because it's an O(n) complexity algorithm\n  setImmediate(function () {\n    note.authorship = models.Note.updateAuthorshipByOperation(operation, userId, note.authorship)\n  })\n}\n\n// TODO: test it\nfunction updateHistory (userId, note, time) {\n  var noteId = note.alias ? note.alias : models.Note.encodeNoteId(note.id)\n  if (note.server) history.updateHistory(userId, noteId, note.server.document, time)\n}\n\nfunction getUniqueColorPerNote (noteId, maxAttempt = 10) {\n  // random color\n  let color = randomcolor()\n  if (!notes[noteId]) return color\n\n  const maxrandomcount = maxAttempt\n  let randomAttemp = 0\n  let found = false\n  do {\n    Object.keys(notes[noteId].users).forEach(userId => {\n      if (notes[noteId].users[userId].color === color) {\n        found = true\n      }\n    })\n    if (found) {\n      color = randomcolor()\n      randomAttemp++\n    }\n  } while (found && randomAttemp < maxrandomcount)\n  return color\n}\n\nfunction queueForConnect (socket) {\n  connectProcessQueue.push(socket.id, async function () {\n    try {\n      const noteId = await exports.parseNoteIdFromSocketAsync(socket)\n      if (!noteId) {\n        return exports.failConnection(404, 'note id not found', socket)\n      }\n      // store noteId in this socket session\n      socket.noteId = noteId\n      // initialize user data\n      // random color\n      var color = getUniqueColorPerNote(noteId)\n      // create user data\n      users[socket.id] = {\n        id: socket.id,\n        address: socket.handshake.headers['x-forwarded-for'] || socket.handshake.address,\n        'user-agent': socket.handshake.headers['user-agent'],\n        color: color,\n        cursor: null,\n        login: false,\n        userid: null,\n        name: null,\n        idle: false,\n        type: null\n      }\n      exports.updateUserData(socket, users[socket.id])\n      try {\n        if (!isNoteExistsInPool(noteId)) {\n          const note = await fetchFullNoteAsync(noteId)\n          if (!note) {\n            logger.error('note not found')\n            // emit error info\n            socket.emit('info', {\n              code: 404\n            })\n            return socket.disconnect(true)\n          }\n          getNotePool()[noteId] = makeNewServerNote(note)\n        }\n        // if no valid info provided will drop the client\n        if (!socket || !notes[noteId] || !users[socket.id]) {\n          if (notes[noteId]) delete notes[noteId]\n          if (users[socket.id]) delete users[socket.id]\n          return\n        }\n        // check view permission\n        if (!exports.checkViewPermission(socket.request, notes[noteId])) {\n          if (notes[noteId]) delete notes[noteId]\n          if (users[socket.id]) delete users[socket.id]\n          logger.error('connection forbidden')\n          // emit error info\n          socket.emit('info', {\n            code: 403\n          })\n          return socket.disconnect(true)\n        }\n        const note = notes[noteId]\n        const user = users[socket.id]\n        // update user color to author color\n        if (note.authors[user.userid]) {\n          user.color = users[socket.id].color = note.authors[user.userid].color\n        }\n        note.users[socket.id] = user\n        note.socks.push(socket)\n        note.server.addClient(socket)\n        note.server.setName(socket, user.name)\n        note.server.setColor(socket, user.color)\n\n        // update user note history\n        exports.updateHistory(user.userid, note)\n\n        exports.emitOnlineUsers(socket)\n        exports.emitRefresh(socket)\n\n        const socketClient = new RealtimeClientConnection(socket)\n        socketClient.registerEventHandler()\n\n        if (config.debug) {\n          const noteId = socket.noteId\n          logger.info('SERVER connected a client to [' + noteId + ']:')\n          logger.info(JSON.stringify(user))\n          getStatus().then(function (data) {\n            logger.info(JSON.stringify(data))\n          })\n        }\n      } catch (err) {\n        logger.error(err)\n        // emit error info\n        socket.emit('info', {\n          code: 500\n        })\n        return socket.disconnect(true)\n      }\n    } catch (err) {\n      return exports.failConnection(500, err, socket)\n    }\n  })\n}\n\nfunction connection (socket) {\n  if (realtime.maintenance) return\n  queueForConnect(socket)\n}\n\n// TODO: test it\nfunction terminate () {\n  disconnectProcessQueue.stop()\n  connectProcessQueue.stop()\n  updateDirtyNoteJob.stop()\n}\n\nexports = module.exports = realtime\nexports.extractNoteIdFromSocket = extractNoteIdFromSocket\nexports.updateNote = updateNote\nexports.failConnection = failConnection\nexports.updateUserData = updateUserData\nexports.emitRefresh = emitRefresh\nexports.emitUserStatus = emitUserStatus\nexports.emitOnlineUsers = emitOnlineUsers\nexports.checkViewPermission = checkViewPermission\nexports.getUserFromUserPool = getUserFromUserPool\nexports.buildUserOutData = buildUserOutData\nexports.emitCheck = emitCheck\nexports.disconnectSocketOnNote = disconnectSocketOnNote\nexports.queueForDisconnect = queueForDisconnect\nexports.terminate = terminate\nexports.updateHistory = updateHistory\nexports.ifMayEdit = ifMayEdit\nexports.parseNoteIdFromSocketAsync = parseNoteIdFromSocketAsync\nexports.disconnectProcessQueue = disconnectProcessQueue\nexports.users = users\nexports.getUserPool = getUserPool\n\nexports.notes = notes\nexports.getNotePool = getNotePool\nexports.getNotePoolSize = getNotePoolSize\nexports.isNoteExistsInPool = isNoteExistsInPool\nexports.addNote = addNote\nexports.getNoteFromNotePool = getNoteFromNotePool\nexports.deleteNoteFromPool = deleteNoteFromPool\nexports.deleteAllNoteFromPool = deleteAllNoteFromPool\n\nexports.saveRevisionJob = saveRevisionJob\n"
  },
  {
    "path": "lib/realtime/realtimeCleanDanglingUserJob.js",
    "content": "'use strict'\n\nconst async = require('async')\nconst config = require('../config')\nconst logger = require('../logger')\n\n/**\n * clean when user not in any rooms or user not in connected list\n */\nclass CleanDanglingUserJob {\n  constructor (realtime) {\n    this.realtime = realtime\n  }\n\n  start () {\n    if (this.timer) return\n    this.timer = setInterval(this.cleanDanglingUser.bind(this), 60000)\n  }\n\n  stop () {\n    if (!this.timer) return\n    clearInterval(this.timer)\n    this.timer = undefined\n  }\n\n  cleanDanglingUser () {\n    const users = this.realtime.getUserPool()\n    async.each(Object.keys(users), (key, callback) => {\n      const socket = this.realtime.io.sockets.connected[key]\n      if ((!socket && users[key]) ||\n        (socket && (!socket.rooms || socket.rooms.length <= 0))) {\n        if (config.debug) {\n          logger.info('cleaner found redundant user: ' + key)\n        }\n        if (!socket) {\n          return callback(null, null)\n        }\n        if (!this.realtime.disconnectProcessQueue.checkTaskIsInQueue(socket.id)) {\n          this.realtime.queueForDisconnect(socket)\n        }\n      }\n      return callback(null, null)\n    }, function (err) {\n      if (err) return logger.error('cleaner error', err)\n    })\n  }\n}\n\nexports.CleanDanglingUserJob = CleanDanglingUserJob\n"
  },
  {
    "path": "lib/realtime/realtimeClientConnection.js",
    "content": "'use strict'\n\nconst get = require('lodash/get')\n\nconst config = require('../config')\nconst models = require('../models')\nconst logger = require('../logger')\n\nclass RealtimeClientConnection {\n  constructor (socket) {\n    this.socket = socket\n    this.realtime = require('./realtime')\n  }\n\n  registerEventHandler () {\n    // received client refresh request\n    this.socket.on('refresh', this.refreshEventHandler.bind(this))\n    // received user status\n    this.socket.on('user status', this.userStatusEventHandler.bind(this))\n    // when a new client disconnect\n    this.socket.on('disconnect', this.disconnectEventHandler.bind(this))\n    // received cursor focus\n    this.socket.on('cursor focus', this.cursorFocusEventHandler.bind(this))\n    // received cursor activity\n    this.socket.on('cursor activity', this.cursorActivityEventHandler.bind(this))\n    // received cursor blur\n    this.socket.on('cursor blur', this.cursorBlurEventHandler.bind(this))\n    // check version\n    this.socket.on('version', this.checkVersionEventHandler.bind(this))\n    // received sync of online users request\n    this.socket.on('online users', this.onlineUsersEventHandler.bind(this))\n    // reveiced when user logout or changed\n    this.socket.on('user changed', this.userChangedEventHandler.bind(this))\n    // delete a note\n    this.socket.on('delete', this.deleteNoteEventHandler.bind(this))\n    // received note permission change request\n    this.socket.on('permission', this.permissionChangeEventHandler.bind(this))\n  }\n\n  isUserLoggedIn () {\n    return this.socket.request.user && this.socket.request.user.logged_in\n  }\n\n  isNoteAndUserExists () {\n    const note = this.realtime.getNoteFromNotePool(this.socket.noteId)\n    const user = this.realtime.getUserFromUserPool(this.socket.id)\n    return note && user\n  }\n\n  isNoteOwner () {\n    const note = this.getCurrentNote()\n    return get(note, 'owner') === this.getCurrentLoggedInUserId()\n  }\n\n  isAnonymousEnable () {\n    // TODO: move this method to config module\n    return config.allowAnonymous || config.allowAnonymousEdits\n  }\n\n  getAvailablePermissions () {\n    // TODO: move this method to config module\n    const availablePermission = Object.assign({}, config.permission)\n    if (!config.allowAnonymous && !config.allowAnonymousViews) {\n      delete availablePermission.freely\n      delete availablePermission.editable\n      delete availablePermission.locked\n    } else if (!config.allowAnonymous && !config.allowAnonymousEdits) {\n      delete availablePermission.freely\n    }\n    return availablePermission\n  }\n\n  getCurrentUser () {\n    if (!this.socket.id) return\n    return this.realtime.getUserFromUserPool(this.socket.id)\n  }\n\n  getCurrentLoggedInUserId () {\n    return get(this.socket, 'request.user.id')\n  }\n\n  getCurrentNote () {\n    if (!this.socket.noteId) return\n    return this.realtime.getNoteFromNotePool(this.socket.noteId)\n  }\n\n  getNoteChannel () {\n    return this.socket.broadcast.to(this.socket.noteId)\n  }\n\n  async destroyNote (id) {\n    return models.Note.destroy({\n      where: { id: id }\n    })\n  }\n\n  async changeNotePermission (newPermission) {\n    const [changedRows] = await models.Note.update({\n      permission: newPermission\n    }, {\n      where: {\n        id: this.getCurrentNote().id\n      }\n    })\n    if (changedRows !== 1) {\n      throw new Error(`updated permission failed, cannot set permission ${newPermission} to note ${this.getCurrentNote().id}`)\n    }\n  }\n\n  notifyPermissionChanged () {\n    this.realtime.io.to(this.getCurrentNote().id).emit('permission', {\n      permission: this.getCurrentNote().permission\n    })\n    this.getCurrentNote().socks.forEach((sock) => {\n      if (sock) {\n        if (!this.realtime.checkViewPermission(sock.request, this.getCurrentNote())) {\n          sock.emit('info', {\n            code: 403\n          })\n          setTimeout(function () {\n            sock.disconnect(true)\n          }, 0)\n        }\n      }\n    })\n  }\n\n  refreshEventHandler () {\n    this.realtime.emitRefresh(this.socket)\n  }\n\n  checkVersionEventHandler () {\n    this.socket.emit('version', {\n      version: config.fullversion,\n      minimumCompatibleVersion: config.minimumCompatibleVersion\n    })\n  }\n\n  userStatusEventHandler (data) {\n    if (!this.isNoteAndUserExists()) return\n    const user = this.getCurrentUser()\n    if (config.debug) {\n      logger.info('SERVER received [' + this.socket.noteId + '] user status from [' + this.socket.id + ']: ' + JSON.stringify(data))\n    }\n    if (data) {\n      user.idle = data.idle\n      user.type = data.type\n    }\n    this.realtime.emitUserStatus(this.socket)\n  }\n\n  userChangedEventHandler () {\n    logger.info('user changed')\n\n    const note = this.getCurrentNote()\n    if (!note) return\n    const user = note.users[this.socket.id]\n    if (!user) return\n\n    this.realtime.updateUserData(this.socket, user)\n    this.realtime.emitOnlineUsers(this.socket)\n  }\n\n  onlineUsersEventHandler () {\n    if (!this.isNoteAndUserExists()) return\n\n    const currentNote = this.getCurrentNote()\n\n    const currentNoteOnlineUserList = Object.keys(currentNote.users)\n      .map(key => this.realtime.buildUserOutData(currentNote.users[key]))\n\n    this.socket.emit('online users', {\n      users: currentNoteOnlineUserList\n    })\n  }\n\n  cursorFocusEventHandler (data) {\n    if (!this.isNoteAndUserExists()) return\n    const user = this.getCurrentUser()\n    user.cursor = data\n    const out = this.realtime.buildUserOutData(user)\n    this.getNoteChannel().emit('cursor focus', out)\n  }\n\n  cursorActivityEventHandler (data) {\n    if (!this.isNoteAndUserExists()) return\n    const user = this.getCurrentUser()\n    user.cursor = data\n    const out = this.realtime.buildUserOutData(user)\n    this.getNoteChannel().emit('cursor activity', out)\n  }\n\n  cursorBlurEventHandler () {\n    if (!this.isNoteAndUserExists()) return\n    const user = this.getCurrentUser()\n    user.cursor = null\n    this.getNoteChannel().emit('cursor blur', {\n      id: this.socket.id\n    })\n  }\n\n  deleteNoteEventHandler () {\n    // need login to do more actions\n    if (this.isUserLoggedIn() && this.isNoteAndUserExists()) {\n      const note = this.getCurrentNote()\n      // Only owner can delete note\n      if (note.owner && note.owner === this.getCurrentLoggedInUserId()) {\n        this.destroyNote(note.id)\n          .then((successRows) => {\n            if (!successRows) return\n            this.realtime.disconnectSocketOnNote(note)\n          })\n          .catch(function (err) {\n            return logger.error('delete note failed: ' + err)\n          })\n      }\n    }\n  }\n\n  permissionChangeEventHandler (permission) {\n    if (!this.isUserLoggedIn()) return\n    if (!this.isNoteAndUserExists()) return\n\n    const note = this.getCurrentNote()\n    // Only owner can change permission\n    if (!this.isNoteOwner()) return\n    if (!(permission in this.getAvailablePermissions())) return\n\n    this.changeNotePermission(permission)\n      .then(() => {\n        note.permission = permission\n        this.notifyPermissionChanged()\n      })\n      .catch(err => logger.error('update note permission failed: ' + err))\n  }\n\n  disconnectEventHandler () {\n    if (this.realtime.disconnectProcessQueue.checkTaskIsInQueue(this.socket.id)) {\n      return\n    }\n    this.realtime.queueForDisconnect(this.socket)\n  }\n}\n\nexports.RealtimeClientConnection = RealtimeClientConnection\n"
  },
  {
    "path": "lib/realtime/realtimeSaveRevisionJob.js",
    "content": "'use strict'\n\nconst models = require('../models')\nconst logger = require('../logger')\n\n/**\n * clean when user not in any rooms or user not in connected list\n */\nclass SaveRevisionJob {\n  constructor (realtime) {\n    this.realtime = realtime\n    this.saverSleep = false\n  }\n\n  start () {\n    if (this.timer) return\n    this.timer = setInterval(this.saveRevision.bind(this), 5 * 60 * 1000)\n  }\n\n  stop () {\n    if (!this.timer) return\n    clearInterval(this.timer)\n    this.timer = undefined\n  }\n\n  saveRevision () {\n    if (this.getSaverSleep()) return\n    models.Revision.saveAllNotesRevision((err, notes) => {\n      if (err) return logger.error('revision saver failed: ' + err)\n      if (notes && notes.length <= 0) {\n        this.setSaverSleep(true)\n      }\n    })\n  }\n\n  getSaverSleep () {\n    return this.saverSleep\n  }\n\n  setSaverSleep (val) {\n    this.saverSleep = val\n  }\n}\n\nexports.SaveRevisionJob = SaveRevisionJob\n"
  },
  {
    "path": "lib/realtime/realtimeUpdateDirtyNoteJob.js",
    "content": "'use strict'\n\nconst config = require('../config')\nconst logger = require('../logger')\nconst moment = require('moment')\n\nclass UpdateDirtyNoteJob {\n  constructor (realtime) {\n    this.realtime = realtime\n  }\n\n  start () {\n    if (this.timer) return\n    this.timer = setInterval(this.updateDirtyNotes.bind(this), 1000)\n  }\n\n  stop () {\n    if (!this.timer) return\n    clearInterval(this.timer)\n    this.timer = undefined\n  }\n\n  updateDirtyNotes () {\n    const notes = this.realtime.getNotePool()\n    Object.keys(notes).forEach((key) => {\n      const note = notes[key]\n      this.updateDirtyNote(note)\n        .catch((err) => {\n          logger.error('updateDirtyNote: updater error', err)\n        })\n    })\n  }\n\n  async updateDirtyNote (note) {\n    const notes = this.realtime.getNotePool()\n    if (!note.server.isDirty) return\n\n    if (config.debug) logger.info('updateDirtyNote: updater found dirty note: ' + note.id)\n    note.server.isDirty = false\n\n    try {\n      const _note = await this.updateNoteAsync(note)\n      // handle when note already been clean up\n      if (!notes[note.id] || !notes[note.id].server) return\n\n      if (!_note) {\n        this.realtime.io.to(note.id).emit('info', {\n          code: 404\n        })\n        logger.error('updateDirtyNote: note not found: ', note.id)\n        this.realtime.disconnectSocketOnNote(note)\n      }\n\n      note.updatetime = moment(_note.lastchangeAt).valueOf()\n      this.realtime.emitCheck(note)\n    } catch (err) {\n      logger.error('updateDirtyNote: note not found: ', note.id)\n      this.realtime.io.to(note.id).emit('info', {\n        code: 404\n      })\n      this.realtime.disconnectSocketOnNote(note)\n      throw err\n    }\n  }\n\n  updateNoteAsync (note) {\n    return new Promise((resolve, reject) => {\n      this.realtime.updateNote(note, (err, _note) => {\n        if (err) {\n          return reject(err)\n        }\n        return resolve(_note)\n      })\n    })\n  }\n}\n\nexports.UpdateDirtyNoteJob = UpdateDirtyNoteJob\n"
  },
  {
    "path": "lib/response.js",
    "content": "'use strict'\n// response\n// external modules\nconst request = require('request')\n\n// core\nconst config = require('./config')\nconst logger = require('./logger')\nconst models = require('./models')\nconst utils = require('./utils')\nconst history = require('./history')\n\n// public\nexports.responseError = responseError\nexports.errorForbidden = errorForbidden\nexports.errorNotFound = errorNotFound\nexports.errorBadRequest = errorBadRequest\nexports.errorTooLong = errorTooLong\nexports.errorInternalError = errorInternalError\nexports.errorServiceUnavailable = errorServiceUnavailable\nexports.newNote = newNote\nexports.showPublishSlide = showPublishSlide\nexports.publishNoteActions = publishNoteActions\nexports.publishSlideActions = publishSlideActions\nexports.githubActions = githubActions\nexports.gitlabActions = gitlabActions\nexports.checkViewPermission = checkViewPermission\nexports.newCheckViewPermission = newCheckViewPermission\nexports.responseCodiMD = responseCodiMD\n\nfunction errorForbidden (req, res) {\n  if (req.user) {\n    responseError(res, '403', 'Forbidden', 'oh no.')\n  } else {\n    var nextURL = new URL('', config.serverURL)\n    nextURL.search = new URLSearchParams({ next: req.originalUrl })\n    req.flash('error', 'You are not allowed to access this page. Maybe try logging in?')\n    res.redirect(nextURL.toString())\n  }\n}\n\nfunction errorNotFound (req, res) {\n  responseError(res, '404', 'Not Found', 'oops.')\n}\n\nfunction errorBadRequest (req, res) {\n  responseError(res, '400', 'Bad Request', 'something not right.')\n}\n\nfunction errorTooLong (req, res) {\n  responseError(res, '413', 'Payload Too Large', 'Shorten your note!')\n}\n\nfunction errorInternalError (req, res) {\n  responseError(res, '500', 'Internal Error', 'wtf.')\n}\n\nfunction errorServiceUnavailable (req, res) {\n  res.status(503).send('I\\'m busy right now, try again later.')\n}\n\nfunction responseError (res, code, detail, msg) {\n  res.status(code).render('error.ejs', {\n    title: code + ' ' + detail + ' ' + msg,\n    code: code,\n    detail: detail,\n    msg: msg\n  })\n}\n\nfunction responseCodiMD (res, note) {\n  var body = note.content\n  var extracted = models.Note.extractMeta(body)\n  var meta = models.Note.parseMeta(extracted.meta)\n  var title = models.Note.decodeTitle(note.title)\n  title = models.Note.generateWebTitle(meta.title || title)\n  res.set({\n    'Cache-Control': 'private', // only cache by client\n    'X-Robots-Tag': 'noindex, nofollow' // prevent crawling\n  })\n  res.render('codimd.ejs', {\n    title: title\n  })\n}\n\nfunction updateHistory (userId, note, document, time) {\n  var noteId = note.alias ? note.alias : models.Note.encodeNoteId(note.id)\n  history.updateHistory(userId, noteId, document, time)\n  logger.info('history updated')\n}\n\nfunction newNote (req, res, next) {\n  var owner = null\n  var body = ''\n  if (req.body && req.body.length > config.documentMaxLength) {\n    return errorTooLong(req, res)\n  } else if (req.body) {\n    body = req.body\n  }\n  body = body.replace(/[\\r]/g, '')\n  if (req.isAuthenticated()) {\n    owner = req.user.id\n  } else if (!config.allowAnonymous) {\n    return errorForbidden(req, res)\n  }\n  models.Note.create({\n    ownerId: owner,\n    alias: req.alias ? req.alias : null,\n    content: body\n  }).then(function (note) {\n    if (req.isAuthenticated()) {\n      updateHistory(owner, note, body)\n    }\n\n    return res.redirect(config.serverURL + '/' + models.Note.encodeNoteId(note.id))\n  }).catch(function (err) {\n    logger.error(err)\n    return errorInternalError(req, res)\n  })\n}\n\nfunction newCheckViewPermission (note, isLogin, userId) {\n  if (note.permission === 'private') {\n    return note.ownerId === userId\n  }\n  if (note.permission === 'limited' || note.permission === 'protected') {\n    return isLogin\n  }\n  return true\n}\n\nfunction checkViewPermission (req, note) {\n  if (note.permission === 'private') {\n    if (!req.isAuthenticated() || note.ownerId !== req.user.id) { return false } else { return true }\n  } else if (note.permission === 'limited' || note.permission === 'protected') {\n    if (!req.isAuthenticated()) { return false } else { return true }\n  } else {\n    return true\n  }\n}\n\nfunction findNote (req, res, callback, include) {\n  var noteId = req.params.noteId\n  var id = req.params.noteId || req.params.shortid\n  models.Note.parseNoteId(id, function (err, _id) {\n    if (err) {\n      logger.error(err)\n      return errorInternalError(req, res)\n    }\n    models.Note.findOne({\n      where: {\n        id: _id\n      },\n      include: include || null\n    }).then(function (note) {\n      if (!note) {\n        if (config.allowFreeURL && noteId && !config.forbiddenNoteIDs.includes(noteId)) {\n          req.alias = noteId\n          return newNote(req, res)\n        } else {\n          return errorNotFound(req, res)\n        }\n      }\n      if (!checkViewPermission(req, note)) {\n        return errorForbidden(req, res)\n      } else {\n        return callback(note)\n      }\n    }).catch(function (err) {\n      logger.error(err)\n      return errorInternalError(req, res)\n    })\n  })\n}\n\nfunction actionDownload (req, res, note) {\n  var body = note.content\n  var title = models.Note.decodeTitle(note.title)\n  var filename = title\n  filename = encodeURIComponent(filename)\n  res.set({\n    'Access-Control-Allow-Origin': '*', // allow CORS as API\n    'Access-Control-Allow-Headers': 'Range',\n    'Access-Control-Expose-Headers': 'Cache-Control, Content-Encoding, Content-Range',\n    'Content-Type': 'text/markdown; charset=UTF-8',\n    'Cache-Control': 'private',\n    'Content-disposition': 'attachment; filename=' + filename + '.md',\n    'X-Robots-Tag': 'noindex, nofollow' // prevent crawling\n  })\n  res.send(body)\n}\n\nfunction publishNoteActions (req, res, next) {\n  findNote(req, res, function (note) {\n    var action = req.params.action\n    switch (action) {\n      case 'download':\n        actionDownload(req, res, note)\n        break\n      case 'edit':\n        res.redirect(config.serverURL + '/' + (note.alias ? note.alias : models.Note.encodeNoteId(note.id)))\n        break\n      default:\n        res.redirect(config.serverURL + '/s/' + note.shortid)\n        break\n    }\n  })\n}\n\nfunction publishSlideActions (req, res, next) {\n  findNote(req, res, function (note) {\n    var action = req.params.action\n    switch (action) {\n      case 'edit':\n        res.redirect(config.serverURL + '/' + (note.alias ? note.alias : models.Note.encodeNoteId(note.id)))\n        break\n      default:\n        res.redirect(config.serverURL + '/p/' + note.shortid)\n        break\n    }\n  })\n}\n\nfunction githubActions (req, res, next) {\n  var noteId = req.params.noteId\n  findNote(req, res, function (note) {\n    var action = req.params.action\n    switch (action) {\n      case 'gist':\n        githubActionGist(req, res, note)\n        break\n      default:\n        res.redirect(config.serverURL + '/' + noteId)\n        break\n    }\n  })\n}\n\nfunction githubActionGist (req, res, note) {\n  var code = req.query.code\n  var state = req.query.state\n  if (!code || !state) {\n    return errorForbidden(req, res)\n  } else {\n    var data = {\n      client_id: config.github.clientID,\n      client_secret: config.github.clientSecret,\n      code: code,\n      state: state\n    }\n    var authUrl = 'https://github.com/login/oauth/access_token'\n    request({\n      url: authUrl,\n      method: 'POST',\n      json: data\n    }, function (error, httpResponse, body) {\n      if (!error && httpResponse.statusCode === 200) {\n        var accessToken = body.access_token\n        if (accessToken) {\n          var content = note.content\n          var title = models.Note.decodeTitle(note.title)\n          var filename = title.replace('/', ' ') + '.md'\n          var gist = {\n            files: {}\n          }\n          gist.files[filename] = {\n            content: content\n          }\n          var gistUrl = 'https://api.github.com/gists'\n          request({\n            url: gistUrl,\n            headers: {\n              'User-Agent': 'CodiMD',\n              Authorization: 'token ' + accessToken\n            },\n            method: 'POST',\n            json: gist\n          }, function (error, httpResponse, body) {\n            if (!error && httpResponse.statusCode === 201) {\n              res.setHeader('referer', '')\n              res.redirect(body.html_url)\n            } else {\n              return errorForbidden(req, res)\n            }\n          })\n        } else {\n          return errorForbidden(req, res)\n        }\n      } else {\n        return errorForbidden(req, res)\n      }\n    })\n  }\n}\n\nfunction gitlabActions (req, res, next) {\n  var noteId = req.params.noteId\n  findNote(req, res, function (note) {\n    var action = req.params.action\n    switch (action) {\n      case 'projects':\n        gitlabActionProjects(req, res, note)\n        break\n      default:\n        res.redirect(config.serverURL + '/' + noteId)\n        break\n    }\n  })\n}\n\nfunction gitlabActionProjects (req, res, note) {\n  if (req.isAuthenticated()) {\n    models.User.findOne({\n      where: {\n        id: req.user.id\n      }\n    }).then(function (user) {\n      if (!user) { return errorNotFound(req, res) }\n      var ret = { baseURL: config.gitlab.baseURL, version: config.gitlab.version }\n      ret.accesstoken = user.accessToken\n      ret.profileid = user.profileid\n      request(\n        config.gitlab.baseURL + '/api/' + config.gitlab.version + '/projects?membership=yes&per_page=100&access_token=' + user.accessToken,\n        function (error, httpResponse, body) {\n          if (!error && httpResponse.statusCode === 200) {\n            ret.projects = JSON.parse(body)\n            return res.send(ret)\n          } else {\n            return res.send(ret)\n          }\n        }\n      )\n    }).catch(function (err) {\n      logger.error('gitlab action projects failed: ' + err)\n      return errorInternalError(req, res)\n    })\n  } else {\n    return errorForbidden(req, res)\n  }\n}\n\nfunction showPublishSlide (req, res, next) {\n  var include = [{\n    model: models.User,\n    as: 'owner'\n  }, {\n    model: models.User,\n    as: 'lastchangeuser'\n  }]\n  findNote(req, res, function (note) {\n    // force to use short id\n    var shortid = req.params.shortid\n    if ((note.alias && shortid !== note.alias) || (!note.alias && shortid !== note.shortid)) { return res.redirect(config.serverURL + '/p/' + (note.alias || note.shortid)) }\n    note.increment('viewcount').then(function (note) {\n      if (!note) {\n        return errorNotFound(req, res)\n      }\n      var body = note.content\n      var extracted = models.Note.extractMeta(body)\n      var markdown = extracted.markdown\n      var meta = models.Note.parseMeta(extracted.meta)\n      var createtime = note.createdAt\n      var updatetime = note.lastchangeAt\n      var title = models.Note.decodeTitle(note.title)\n      title = models.Note.generateWebTitle(meta.title || title)\n      var data = {\n        title: title,\n        description: meta.description || (markdown ? models.Note.generateDescription(markdown) : null),\n        viewcount: note.viewcount,\n        createtime: createtime,\n        updatetime: updatetime,\n        body: markdown,\n        theme: meta.slideOptions && utils.isRevealTheme(meta.slideOptions.theme),\n        meta: JSON.stringify(extracted.meta),\n        owner: note.owner ? note.owner.id : null,\n        ownerprofile: note.owner ? models.User.getProfile(note.owner) : null,\n        lastchangeuser: note.lastchangeuser ? note.lastchangeuser.id : null,\n        lastchangeuserprofile: note.lastchangeuser ? models.User.getProfile(note.lastchangeuser) : null,\n        robots: meta.robots || false, // default allow robots\n        GA: meta.GA,\n        disqus: meta.disqus,\n        cspNonce: res.locals.nonce\n      }\n      res.set({\n        'Cache-Control': 'private' // only cache by client\n      })\n      res.render('slide.ejs', data)\n    }).catch(function (err) {\n      logger.error(err)\n      return errorInternalError(req, res)\n    })\n  }, include)\n}\n"
  },
  {
    "path": "lib/routes.js",
    "content": "'use strict'\n\nconst { Router } = require('express')\n\nconst { wrap, urlencodedParser, markdownParser } = require('./utils')\n\n// load controller\nconst indexController = require('./homepage')\nconst errorPageController = require('./errorPage')\nconst statusController = require('./status')\nconst historyController = require('./history')\nconst userController = require('./user')\nconst noteController = require('./note')\nconst response = require('./response')\nconst bodyParser = require('body-parser')\nconst appRouter = Router()\n\n// register route\n\nconst csurf = require('csurf')\nconst csurfMiddleware = csurf({ cookie: true })\n\n// get index\nappRouter.get('/', csurfMiddleware, wrap(indexController.showIndex))\n\n// ----- error page -----\n// get 403 forbidden\nappRouter.get('/403', errorPageController.errorForbidden)\n// get 404 not found\nappRouter.get('/404', errorPageController.errorNotFound)\n// get 500 internal error\nappRouter.get('/500', errorPageController.errorInternalError)\n\nappRouter.get('/config', statusController.getConfig)\n\n// register auth module\nappRouter.use(require('./auth'))\n\n// get history\nappRouter.get('/history', historyController.historyGet)\n// post history\nappRouter.post('/history', urlencodedParser, historyController.historyPost)\n// post history by note id\nappRouter.post('/history/:noteId', urlencodedParser, historyController.historyPost)\n// delete history\nappRouter.delete('/history', historyController.historyDelete)\n// delete history by note id\nappRouter.delete('/history/:noteId', historyController.historyDelete)\n\n// user\n// get me info\nappRouter.get('/me', wrap(userController.getMe))\n\n// delete the currently authenticated user\nappRouter.get('/me/delete/:token?', wrap(userController.deleteUser))\n\n// export the data of the authenticated user\nappRouter.post('/me/export', urlencodedParser, csurfMiddleware, userController.exportMyData)\n\nappRouter.get('/user/:username/avatar.svg', userController.getMyAvatar)\n\n// register image upload module\nappRouter.use(require('./imageRouter'))\n\n// get new note\nappRouter.get('/new', response.newNote)\n// post new note with content\nappRouter.post('/new', markdownParser, response.newNote)\n// get publish note\nappRouter.get('/s/:shortid', noteController.showPublishNote)\n// publish note actions\nappRouter.get('/s/:shortid/:action', response.publishNoteActions)\n// get publish slide\nappRouter.get('/p/:shortid', response.showPublishSlide)\n// publish slide actions\nappRouter.get('/p/:shortid/:action', response.publishSlideActions)\n// gey my note list\nappRouter.get('/api/notes/myNotes', noteController.listMyNotes)\n// delete note by id\nappRouter.delete('/api/notes/:noteId', noteController.deleteNote)\n// update note content by id\nappRouter.put('/api/notes/:noteId', bodyParser.json(), noteController.updateNote)\n// get note by id\nappRouter.get('/:noteId', wrap(noteController.showNote))\n// note actions\nappRouter.get('/:noteId/:action', noteController.noteActions)\n// note actions with action id\nappRouter.get('/:noteId/:action/:actionId', noteController.noteActions)\n\nexports.router = appRouter\n"
  },
  {
    "path": "lib/status/index.js",
    "content": "'use strict'\n\nconst realtime = require('../realtime/realtime')\nconst config = require('../config')\n\nexports.getStatus = async (req, res) => {\n  res.set({\n    'Cache-Control': 'private', // only cache by client\n    'X-Robots-Tag': 'noindex, nofollow', // prevent crawling\n    'Content-Type': 'application/json'\n  })\n\n  try {\n    const data = await realtime.getStatus()\n    res.send(data)\n  } catch (e) {\n    console.error(e)\n    res.status(500).send(e.toString())\n  }\n}\n\nexports.getMetrics = async (req, res) => {\n  const data = await realtime.getStatus()\n\n  res.set({\n    'Cache-Control': 'private', // only cache by client\n    'X-Robots-Tag': 'noindex, nofollow', // prevent crawling\n    'Content-Type': 'text/plain; charset=utf-8'\n  })\n  res.render('../js/lib/common/metrics.ejs', data)\n}\n\nexports.getConfig = (req, res) => {\n  const data = {\n    domain: config.domain,\n    urlpath: config.urlPath,\n    debug: config.debug,\n    version: config.fullversion,\n    plantumlServer: config.plantuml.server,\n    DROPBOX_APP_KEY: config.dropbox.appKey,\n    allowedUploadMimeTypes: config.allowedUploadMimeTypes,\n    defaultUseHardbreak: config.defaultUseHardbreak,\n    linkifyHeaderStyle: config.linkifyHeaderStyle,\n    useCDN: config.useCDN,\n    defaultTocDepth: config.defaultTocDepth\n  }\n  res.set({\n    'Cache-Control': 'private', // only cache by client\n    'X-Robots-Tag': 'noindex, nofollow', // prevent crawling\n    'Content-Type': 'application/javascript'\n  })\n  res.render('../js/lib/common/constant.ejs', data)\n}\n"
  },
  {
    "path": "lib/user/index.js",
    "content": "'use strict'\n\nconst archiver = require('archiver')\nconst async = require('async')\n\nconst response = require('../response')\nconst config = require('../config')\nconst models = require('../models')\nconst logger = require('../logger')\nconst { generateAvatar } = require('../letter-avatars')\n\nexports.getMe = async (req, res) => {\n  if (!req.isAuthenticated()) {\n    return res.status(401).send({\n      status: 'forbidden'\n    })\n  }\n\n  const user = await models.User.findOne({\n    where: {\n      id: req.user.id\n    }\n  })\n\n  if (!user) {\n    return response.errorNotFound(req, res)\n  }\n  const profile = models.User.getProfile(user)\n\n  res.send({\n    status: 'ok',\n    id: req.user.id,\n    name: profile.name,\n    photo: profile.photo\n  })\n}\n\nexports.deleteUser = async (req, res) => {\n  if (!req.isAuthenticated()) {\n    return response.errorForbidden(req, res)\n  }\n\n  const user = await models.User.findOne({\n    where: {\n      id: req.user.id\n    }\n  })\n\n  if (!user) {\n    return response.errorNotFound(req, res)\n  }\n\n  if (user.deleteToken !== req.params.token) {\n    return response.errorForbidden(req, res)\n  }\n\n  await user.destroy()\n  return res.redirect(config.serverURL + '/')\n}\n\nexports.exportMyData = (req, res) => {\n  if (!req.isAuthenticated()) {\n    return response.errorForbidden(req, res)\n  }\n\n  const archive = archiver('zip', {\n    zlib: { level: 3 } // Sets the compression level.\n  })\n\n  res.setHeader('Content-Type', 'application/zip')\n  res.attachment('archive.zip')\n  archive.pipe(res)\n  archive.on('error', function (err) {\n    logger.error('export user data failed: ' + err)\n    return response.errorInternalError(req, res)\n  })\n\n  models.User.findOne({\n    where: {\n      id: req.user.id\n    }\n  }).then(function (user) {\n    models.Note.findAll({\n      where: {\n        ownerId: user.id\n      }\n    }).then(function (notes) {\n      const filenames = {}\n      async.each(notes, function (note, callback) {\n        const basename = note.title.replace(/\\//g, '-') // Prevent subdirectories\n        let filename\n        let suffix = 0\n        do {\n          if (suffix === 0) {\n            filename = basename + '.md'\n          } else {\n            filename = basename + '-' + suffix + '.md'\n          }\n          suffix++\n        } while (filenames[filename])\n        filenames[filename] = true\n\n        logger.debug('Write: ' + filename)\n        archive.append(note.content, { name: filename, date: note.lastchangeAt })\n        callback(null, null)\n      }, function (err) {\n        if (err) {\n          return response.errorInternalError(req, res)\n        }\n\n        archive.finalize()\n      })\n    })\n  }).catch(function (err) {\n    logger.error('export user data failed: ' + err)\n    return response.errorInternalError(req, res)\n  })\n}\n\nexports.getMyAvatar = (req, res) => {\n  res.setHeader('Content-Type', 'image/svg+xml')\n  res.setHeader('Cache-Control', 'public, max-age=86400')\n  res.send(generateAvatar(req.params.username))\n}\n"
  },
  {
    "path": "lib/utils.js",
    "content": "'use strict'\nconst fs = require('fs')\nconst path = require('path')\nconst bodyParser = require('body-parser')\nconst mime = require('mime-types')\n\nexports.isSQLite = function isSQLite (sequelize) {\n  return sequelize.options.dialect === 'sqlite'\n}\n\nexports.getImageMimeType = function getImageMimeType (imagePath) {\n  return mime.lookup(path.extname(imagePath))\n}\n\nexports.isRevealTheme = function isRevealTheme (theme) {\n  if (fs.existsSync(path.join(__dirname, '..', 'public', 'build', 'reveal.js', 'css', 'theme', theme + '.css'))) {\n    return theme\n  }\n  return undefined\n}\n\nexports.wrap = innerHandler => (req, res, next) => innerHandler(req, res).catch(err => next(err))\n\n// create application/x-www-form-urlencoded parser\nexports.urlencodedParser = bodyParser.urlencoded({\n  extended: false,\n  limit: 1024 * 1024 * 10 // 10 mb\n})\n\n// create text/markdown parser\nexports.markdownParser = bodyParser.text({\n  inflate: true,\n  type: ['text/plain', 'text/markdown'],\n  limit: 1024 * 1024 * 10 // 10 mb\n})\n"
  },
  {
    "path": "lib/web/middleware/checkVersion.js",
    "content": "'use strict'\n\nconst { promisify } = require('util')\n\nconst request = require('request')\n\nconst logger = require('../../logger')\nconst config = require('../../config')\n\nlet lastCheckAt\n\nconst VERSION_CHECK_ENDPOINT = 'https://evangelion.codimd.dev/'\nconst CHECK_TIMEOUT = 1000 * 60 * 60 * 24 // 1 day\n\nconst rp = promisify(request)\n\nexports.checkVersion = checkVersion\n/**\n * @param {Express.Application|Express.Request} ctx\n */\nasync function checkVersion (ctx) {\n  if (lastCheckAt && (lastCheckAt + CHECK_TIMEOUT > Date.now())) {\n    return\n  }\n\n  // update lastCheckAt whether the check would fail or not\n  lastCheckAt = Date.now()\n\n  try {\n    const { statusCode, body: data } = await rp({\n      url: `${VERSION_CHECK_ENDPOINT}?v=${config.version}`,\n      method: 'GET',\n      json: true,\n      timeout: 3000\n    })\n\n    if (statusCode !== 200 || data.status === 'error') {\n      logger.warn('Version check failed.')\n      return\n    }\n\n    const locals = ctx.locals ? ctx.locals : ctx.app.locals\n\n    locals.versionInfo.latest = data.latest\n    locals.versionInfo.versionItem = data.latest ? null : data.versionItem\n\n    if (!data.latest) {\n      const { version, link } = data.versionItem\n\n      logger.info(`Your CodiMD version is out of date! The latest version is ${version}. Please see what's new on ${link}.`)\n    }\n  } catch (err) {\n    // ignore and skip version check\n    logger.warn('Version check failed.')\n    logger.warn(err)\n  }\n}\n\nexports.versionCheckMiddleware = function (req, res, next) {\n  checkVersion(req)\n    .then(() => {\n      next()\n    })\n    .catch((err) => {\n      logger.error(err)\n      next()\n    })\n}\n"
  },
  {
    "path": "lib/workers/dmpWorker.js",
    "content": "'use strict'\n// external modules\nvar DiffMatchPatch = require('@hackmd/diff-match-patch')\nvar dmp = new DiffMatchPatch()\n\n// core\nvar config = require('../config')\nvar logger = require('../logger')\n\nprocess.on('message', function (data) {\n  if (!data || !data.msg || !data.cacheKey) {\n    return logger.error('dmp worker error: not enough data')\n  }\n  switch (data.msg) {\n    case 'create patch':\n      if (!Object.hasOwnProperty.call(data, 'lastDoc') || !Object.hasOwnProperty.call(data, 'currDoc')) {\n        return logger.error('dmp worker error: not enough data on create patch')\n      }\n      try {\n        var patch = createPatch(data.lastDoc, data.currDoc)\n        process.send({\n          msg: 'check',\n          result: patch,\n          cacheKey: data.cacheKey\n        })\n      } catch (err) {\n        logger.error('dmp worker error', err)\n        process.send({\n          msg: 'error',\n          error: err,\n          cacheKey: data.cacheKey\n        })\n      }\n      break\n    case 'get revision':\n      if (!Object.hasOwnProperty.call(data, 'revisions') || !Object.hasOwnProperty.call(data, 'count')) {\n        return logger.error('dmp worker error: not enough data on get revision')\n      }\n      try {\n        var result = getRevision(data.revisions, data.count)\n        process.send({\n          msg: 'check',\n          result: result,\n          cacheKey: data.cacheKey\n        })\n      } catch (err) {\n        logger.error('dmp worker error', err)\n        process.send({\n          msg: 'error',\n          error: err,\n          cacheKey: data.cacheKey\n        })\n      }\n      break\n  }\n})\n\nfunction createPatch (lastDoc, currDoc) {\n  var msStart = (new Date()).getTime()\n  var diff = dmp.diff_main(lastDoc, currDoc)\n  var patch = dmp.patch_make(lastDoc, diff)\n  patch = dmp.patch_toText(patch)\n  var msEnd = (new Date()).getTime()\n  if (config.debug) {\n    logger.info(patch)\n    logger.info((msEnd - msStart) + 'ms')\n  }\n  return patch\n}\n\nfunction getRevision (revisions, count) {\n  var msStart = (new Date()).getTime()\n  var startContent = null\n  var lastPatch = []\n  var applyPatches = []\n  var authorship = []\n  if (count <= Math.round(revisions.length / 2)) {\n    // start from top to target\n    for (let i = 0; i < count; i++) {\n      const revision = revisions[i]\n      if (i === 0) {\n        startContent = revision.content || revision.lastContent\n      }\n      if (i !== count - 1) {\n        const patch = dmp.patch_fromText(revision.patch)\n        applyPatches = applyPatches.concat(patch)\n      }\n      lastPatch = revision.patch\n      authorship = revision.authorship\n    }\n    // swap DIFF_INSERT and DIFF_DELETE to achieve unpatching\n    for (let i = 0, l = applyPatches.length; i < l; i++) {\n      for (let j = 0, m = applyPatches[i].diffs.length; j < m; j++) {\n        var diff = applyPatches[i].diffs[j]\n        if (diff[0] === DiffMatchPatch.DIFF_INSERT) { diff[0] = DiffMatchPatch.DIFF_DELETE } else if (diff[0] === DiffMatchPatch.DIFF_DELETE) { diff[0] = DiffMatchPatch.DIFF_INSERT }\n      }\n    }\n  } else {\n    // start from bottom to target\n    var l = revisions.length - 1\n    for (var i = l; i >= count - 1; i--) {\n      const revision = revisions[i]\n      if (i === l) {\n        startContent = revision.lastContent\n        authorship = revision.authorship\n      }\n      if (revision.patch) {\n        const patch = dmp.patch_fromText(revision.patch)\n        applyPatches = applyPatches.concat(patch)\n      }\n      lastPatch = revision.patch\n      authorship = revision.authorship\n    }\n  }\n  try {\n    var finalContent = dmp.patch_apply(applyPatches, startContent)[0]\n  } catch (err) {\n    throw new Error(err)\n  }\n  var data = {\n    content: finalContent,\n    patch: dmp.patch_fromText(lastPatch),\n    authorship: authorship\n  }\n  var msEnd = (new Date()).getTime()\n  if (config.debug) {\n    logger.info((msEnd - msStart) + 'ms')\n  }\n  return data\n}\n\n// log uncaught exception\nprocess.on('uncaughtException', function (err) {\n  logger.error('An uncaught exception has occured.')\n  logger.error(err)\n  logger.error('Process will exit now.')\n  process.exit(1)\n})\n"
  },
  {
    "path": "locales/ca.json",
    "content": "{\n\t\"Collaborative markdown notes\": \"Notes col·laboratives a Markdown\",\n\t\"Realtime collaborative markdown notes on all platforms.\": \"Notes col·laboratives a Markdown per a totes les plataformes.\",\n\t\"Best way to write and share your knowledge in markdown.\": \"La millor forma d'escriure i compartir el teu coneixement a Markdown.\",\n\t\"Intro\": \"Introducció\",\n\t\"History\": \"Història\",\n\t\"New guest note\": \"Nova nota com a convidat\",\n\t\"Collaborate with URL\": \"Col·laborar a través de URL\",\n\t\"Support charts and MathJax\": \"Soport per a gràfics i MathJax\",\n\t\"Support slide mode\": \"Soport per a diapositives\",\n\t\"Sign In\": \"Entrar\",\n\t\"Below is the history from browser\": \"A continuació es mostra l'historial del navegador\",\n\t\"Welcome!\": \"Benvingut!\",\n\t\"New note\": \"Nova nota\",\n\t\"or\": \"o\",\n\t\"Sign Out\": \"Sortir\",\n\t\"Explore all features\": \"Explorar totes les funcions\",\n\t\"Select tags...\": \"Seleccionar etiquetes...\",\n\t\"Search keyword...\": \"Buscar paraules clau...\",\n\t\"Sort by title\": \"Ordenar per títol\",\n\t\"Title\": \"Títol\",\n\t\"Sort by time\": \"Ordenar per hora\",\n\t\"Time\": \"Tiempo\",\n\t\"Export history\": \"Exportar historial\",\n\t\"Import history\": \"Importar historial\",\n\t\"Clear history\": \"Borrar historial\",\n\t\"Refresh history\": \"Actualitzar historial\",\n\t\"No history\": \"Cap historial\",\n\t\"Import from browser\": \"Importar del navegador\",\n\t\"Releases\": \"Versions\",\n\t\"Are you sure?\": \"Estas segur?\",\n\t\"Cancel\": \"Cancel·lar\",\n\t\"Yes, do it!\": \"Si, fes-ho!\",\n\t\"Choose method\": \"Triar mètode\",\n\t\"Sign in via %s\": \"Entrar a través de %s\",\n\t\"New\": \"Nou\",\n\t\"Publish\": \"Publicar\",\n\t\"Extra\": \"Extra\",\n\t\"Revision\": \"Revisió\",\n\t\"Slide Mode\": \"Mode presentació\",\n\t\"Export\": \"Exportar\",\n\t\"Import\": \"Importar\",\n\t\"Clipboard\": \"Portapapers\",\n\t\"Download\": \"Descarregar\",\n\t\"Raw HTML\": \"HTML pur\",\n\t\"Edit\": \"Editar\",\n\t\"View\": \"Veure\",\n\t\"Both\": \"Ambdós\",\n\t\"Help\": \"Ajuda\",\n\t\"Upload Image\": \"Pujar imatge\",\n\t\"Menu\": \"Menú\",\n\t\"This page need refresh\": \"Aquesta pàgina necessita ser refrescada\",\n\t\"You have an incompatible client version.\": \"Tens una versió del client incompatible.\",\n\t\"Refresh to update.\": \"Refrescar per actualitzar\",\n\t\"New version available!\": \"Nova versió disponible!\",\n\t\"See releases notes here\": \"Veure les notes de publicació aquí\",\n\t\"Refresh to enjoy new features.\": \"Actualitzar per fer servir les noves funcions.\",\n\t\"Your user state has changed.\": \"L'estat del teu usuari ha canviat.\",\n\t\"Refresh to load new user state.\": \"Refrescar per actualitzar l'estat del teu usuari.\",\n\t\"Refresh\": \"Refrescar\",\n\t\"Contacts\": \"Contactes\",\n\t\"Report an issue\": \"Reportar un problema\",\n\t\"Send us email\": \"Enviar-nos un email\",\n\t\"Documents\": \"Documents\",\n\t\"Features\": \"Funcions\",\n\t\"YAML Metadata\": \"Metadades de YAML\",\n\t\"Slide Example\": \"Exemple de diapositiva\",\n\t\"Cheatsheet\": \"Ajudamemories\",\n\t\"Example\": \"Exemple\",\n\t\"Syntax\": \"Sintaxis\",\n\t\"Header\": \"Capçelera\",\n\t\"Unordered List\": \"Llista desordenada\",\n\t\"Ordered List\": \"Llista ordenada\",\n\t\"Todo List\": \"Llista de tasques\",\n\t\"Blockquote\": \"Bloc de cita\",\n\t\"Bold font\": \"Font negreta\",\n\t\"Italics font\": \"Font itàlica\",\n\t\"Strikethrough\": \"Ratllat\",\n\t\"Inserted text\": \"Text subrallat\",\n\t\"Marked text\": \"Text marcat\",\n\t\"Link\": \"Enllaç\",\n\t\"Image\": \"Imatge\",\n\t\"Code\": \"Codi\",\n\t\"Externals\": \"Externs\",\n\t\"This is a alert area.\": \"Això és una àrea d'alerta.\",\n\t\"Revert\": \"Revertir\",\n\t\"Import from clipboard\": \"Importar del portapapers\",\n\t\"Paste your markdown or webpage here...\": \"Enganxa la teva markdown o pàgina web aquí...\",\n\t\"Clear\": \"Netejar\",\n\t\"This note is locked\": \"Aquesta nota està bloquejada\",\n\t\"Sorry, only owner can edit this note.\": \"Perdona, només l'amo pot editar aquesta nota.\",\n\t\"OK\": \"OK\",\n\t\"Reach the limit\": \"Ha arribat al límit\",\n\t\"Sorry, you've reached the max length this note can be.\": \"Perdona, ha arribat a la longitut màxima que pot tenir aquesta nota.\",\n\t\"Please reduce the content or divide it to more notes, thank you!\": \"Siusplau, redueix el contingut o divideix-la en més notes, gràcies!\",\n\t\"Import from Gist\": \"Importar d'un Gist\",\n\t\"Paste your gist url here...\": \"Enganxa l'URL del teu Gist aquí...\",\n\t\"Import from Snippet\": \"Importar d'Snippet\",\n\t\"Select From Available Projects\": \"Triar d'un projecte disponsible\",\n\t\"Select From Available Snippets\": \"Triar d'un Snippet disponible\",\n\t\"OR\": \"O\",\n\t\"Export to Snippet\": \"Exportar a Snippet\",\n\t\"Select Visibility Level\": \"Triar el nivell de visibilitat\"\n}\n"
  },
  {
    "path": "locales/da.json",
    "content": "{\n\t\"Collaborative markdown notes\": \"Kollaborative markdown-noter\",\n\t\"Realtime collaborative markdown notes on all platforms.\": \"Kollaborative markdown-noter i realtid på alle platforme.\",\n\t\"Best way to write and share your knowledge in markdown.\": \"Bedste måde at skrive og dele din viden i markdown.\",\n\t\"Intro\": \"Intro\",\n\t\"History\": \"Historik\",\n\t\"New guest note\": \"Ny gæstenote\",\n\t\"Collaborate with URL\": \"Samarbejd via URL\",\n\t\"Support charts and MathJax\": \"Mulighed for diagrammer og MathJax\",\n\t\"Support slide mode\": \"Mulighed for præsentationer\",\n\t\"Sign In\": \"Log Ind\",\n\t\"Below is the history from browser\": \"Forneden findes historikken fra browseren\",\n\t\"Welcome!\": \"Velkommen!\",\n\t\"New note\": \"Ny note\",\n\t\"or\": \"eller\",\n\t\"Sign Out\": \" Log Ud\",\n\t\"Explore all features\": \"Udforsk alle features\",\n\t\"Select tags...\": \"Vælg tags...\",\n\t\"Search keyword...\": \"Søg nøgleord...\",\n\t\"Sort by title\": \"Sortér titler\",\n\t\"Title\": \"Titel\",\n\t\"Sort by time\": \"Sortér kronologisk\",\n\t\"Time\": \"Tid\",\n\t\"Export history\": \"Eksportér historik\",\n\t\"Import history\": \"Importér historik\",\n\t\"Clear history\": \"Ryd hsitorik\",\n\t\"Refresh history\": \"Genindlæs historik\",\n\t\"No history\": \"Ingen historik\",\n\t\"Import from browser\": \"Importér fra browser\",\n\t\"Releases\": \"Releases\",\n\t\"Are you sure?\": \"Er du sikker?\",\n\t\"Cancel\": \"Afbryd\",\n\t\"Yes, do it!\": \"Ja, gør det!\",\n\t\"Choose method\": \"Vælg metode\",\n\t\"Sign in via %s\": \"Log ind med %s\",\n\t\"New\": \"Ny\",\n\t\"Publish\": \"Publicér\",\n\t\"Extra\": \"Ekstra\",\n\t\"Revision\": \"Revision\",\n\t\"Slide Mode\": \"Præsentationstilstand\",\n\t\"Export\": \"Eksportér\",\n\t\"Import\": \"Importér\",\n\t\"Clipboard\": \"Udklipsholder\",\n\t\"Download\": \"Download\",\n\t\"Raw HTML\": \"Rå HTML\",\n\t\"Edit\": \"Redigér\",\n\t\"View\": \"Vis\",\n\t\"Both\": \"Begge\",\n\t\"Help\": \"Hjælp\",\n\t\"Upload Image\": \"Upload billede\",\n\t\"Menu\": \"Menu\",\n\t\"This page need refresh\": \"Denne side skal genindlæses\",\n\t\"You have an incompatible client version.\": \"Din klientversion er inkompatibel.\",\n\t\"Refresh to update.\": \"Genindlæs for at opdatere.\",\n\t\"New version available!\": \"Ny version tilgængelig!\",\n\t\"See releases notes here\": \"Se release notes her\",\n\t\"Refresh to enjoy new features.\": \"Genindlæs for at anvende ny funktionalitet.\",\n\t\"Your user state has changed.\": \"Din brugerstatus er ændret.\",\n\t\"Refresh to load new user state.\": \"Genindlæs for at anvende ny brugerstatus.\",\n\t\"Refresh\": \"Genindlæs\",\n\t\"Contacts\": \"Kontakter\",\n\t\"Report an issue\": \"Rapportér en fejl\",\n\t\"Send us email\": \"Send os en email\",\n\t\"Documents\": \"Dokumenter\",\n\t\"Features\": \"Funktionalitet\",\n\t\"YAML Metadata\": \"YAML Metadata\",\n\t\"Slide Example\": \"Præsentationseksempel\",\n\t\"Cheatsheet\": \"Snydeark\",\n\t\"Example\": \"Eksempel\",\n\t\"Syntax\": \"Syntaks\",\n\t\"Header\": \"Overskrift\",\n\t\"Unordered List\": \"Uordnet Liste\",\n\t\"Ordered List\": \"Ordnet Liste\",\n\t\"Todo List\": \"Tjekliste\",\n\t\"Blockquote\": \"Blokcitat\",\n\t\"Bold font\": \"Fed skrift\",\n\t\"Italics font\": \"Kursiv skrift\",\n\t\"Strikethrough\": \"Gennemstregning\",\n\t\"Inserted text\": \"Indsat tekst\",\n\t\"Marked text\": \"Markeret tekst\",\n\t\"Link\": \"Link\",\n\t\"Image\": \"Billede\",\n\t\"Code\": \"Kode\",\n\t\"Externals\": \"Eksterne\",\n\t\"This is a alert area.\": \"Dette er et alarmområde.\",\n\t\"Revert\": \"Fortryd ændringer\",\n\t\"Import from clipboard\": \"Importér fra udklipsholder\",\n\t\"Paste your markdown or webpage here...\": \"Indsæt din markdown eller hjemmeside her...\",\n\t\"Clear\": \"Ryd\",\n\t\"This note is locked\": \"Denne note er låst\",\n\t\"Sorry, only owner can edit this note.\": \"Beklager, men kun ejeren kan redigere denne note.\",\n\t\"OK\": \"Okay\",\n\t\"Reach the limit\": \"Nå grænsen\",\n\t\"Sorry, you've reached the max length this note can be.\": \"Beklager, du har nået grænsen for den maksimale længde denne note må være.\",\n\t\"Please reduce the content or divide it to more notes, thank you!\": \"Vær venlig at begrænse indholdets mængde eller opdel det i flere noter, tak!\",\n\t\"Import from Gist\": \"Importér fra Gist\",\n\t\"Paste your gist url here...\": \"Indsæt din gist-url her...\",\n\t\"Import from Snippet\": \"Importér fra Snippet\",\n\t\"Select From Available Projects\": \"Vælg fra tilgængelige projekter\",\n\t\"Select From Available Snippets\": \"Vælg fra tilgængelige Snippets\",\n\t\"OR\": \"ELLER\",\n\t\"Export to Snippet\": \"Eksportér til Snippet\",\n\t\"Select Visibility Level\": \"Vælg synlighedsniveau\"\n}\n"
  },
  {
    "path": "locales/de.json",
    "content": "{\n    \"Collaborative markdown notes\": \"Gemeinsame Markdown Notizen\",\n    \"Realtime collaborative markdown notes on all platforms.\": \"Gemeinsame Notizen in Echtzeit auf allen Plattformen.\",\n    \"Best way to write and share your knowledge in markdown.\": \"Der beste Weg, sein Wissen in Markdown zu schreiben und zu teilen.\",\n    \"Intro\": \"Intro\",\n    \"History\": \"Verlauf\",\n    \"New guest note\": \"Neue Gastnotiz\",\n    \"Collaborate with URL\": \"Zusammenarbeiten über URL\",\n    \"Support charts and MathJax\": \"Unterstützt charts und Mathjax\",\n    \"Support slide mode\": \"Unterstützt Präsentationsmodus\",\n    \"Sign In\": \"Anmelden\",\n    \"Below is the history from browser\": \"Im Folgenden finden Sie den Browserverlauf\",\n    \"Welcome!\": \"Willkommen!\",\n    \"New note\": \"Neue Notiz\",\n    \"or\": \"oder\",\n    \"Sign Out\": \"Ausloggen\",\n    \"Explore all features\": \"Entdecke alle Funktionen\",\n    \"Select tags...\": \"Stichwort auswählen ...\",\n    \"Search keyword...\": \"Suche nach Stichwort ...\",\n    \"Sort by title\": \"Nach Titel sortieren\",\n    \"Title\": \"Titel\",\n    \"Sort by time\": \"Nach Zeit sortieren\",\n    \"Time\": \"Zeit\",\n    \"Export history\": \"Verlauf exportieren\",\n    \"Import history\": \"Verlauf importieren\",\n    \"Clear history\": \"Verlauf löschen\",\n    \"Refresh history\": \"Verlauf aktualisieren\",\n    \"No history\": \"Kein Verlauf\",\n    \"Import from browser\": \"Vom Browser importieren\",\n    \"Releases\": \"Versionen\",\n    \"Are you sure?\": \"Sind sie sicher?\",\n    \"Do you really want to delete this note?\": \"Möchten Sie diese Notiz wirklich löschen?\",\n    \"All users will lose their connection.\": \"Alle Benutzer werden ihre Verbindung verlieren.\",\n    \"Cancel\": \"Abbrechen\",\n    \"Yes, do it!\": \"Ja, mach es!\",\n    \"Choose method\": \"Methode wählen\",\n    \"Sign in via %s\": \"Einloggen über %s\",\n    \"New\": \"Neu\",\n    \"Publish\": \"Veröffentlichen\",\n    \"Extra\": \"Extra\",\n    \"Revision\": \"Version\",\n    \"Slide Mode\": \"Präsentationsmodus\",\n    \"Export\": \"Exportieren\",\n    \"Import\": \"Importieren\",\n    \"Clipboard\": \"Zwischenablage\",\n    \"Download\": \"Download\",\n    \"Raw HTML\": \"Reines HTML\",\n    \"Edit\": \"Bearbeiten\",\n    \"View\": \"Anzeigen\",\n    \"Both\": \"Beides\",\n    \"Help\": \"Hilfe\",\n    \"Upload Image\": \"Foto hochladen\",\n    \"Menu\": \"Menü\",\n    \"This page need refresh\": \"Bitte laden Sie die Seite neu\",\n    \"You have an incompatible client version.\": \"Ihre Client Version ist nicht kompatibel\",\n    \"Refresh to update.\": \"Neu laden zum Updaten.\",\n    \"New version available!\": \"Neue Version verfügbar!\",\n    \"See releases notes here\": \"Versionshinweise hier ansehen\",\n    \"Refresh to enjoy new features.\": \"Neu laden für neue Funktionen.\",\n    \"Your user state has changed.\": \"Ihr Nutzerstatus hat sich geändert.\",\n    \"Refresh to load new user state.\": \"Neu laden für neuen Nutzerstatus.\",\n    \"Refresh\": \"Neu laden\",\n    \"Contacts\": \"Kontakte\",\n    \"Report an issue\": \"Fehlerbericht senden\",\n    \"Meet us on %s\": \"Triff uns auf %s\",\n    \"Send us email\": \"Sende uns eine Email\",\n    \"Documents\": \"Dokumente\",\n    \"Features\": \"Funktionen\",\n    \"YAML Metadata\": \"YAML Metadaten\",\n    \"Slide Example\": \"Beispiel Präsentation\",\n    \"Cheatsheet\": \"Cheatsheet\",\n    \"Example\": \"Beispiel\",\n    \"Syntax\": \"Syntax\",\n    \"Header\": \"Überschrift\",\n    \"Unordered List\": \"Ungeordnete Liste\",\n    \"Ordered List\": \"Geordnete Liste\",\n    \"Todo List\": \"To-Do Liste\",\n    \"Blockquote\": \"Zitat\",\n    \"Bold font\": \"Fett\",\n    \"Italics font\": \"Kursiv\",\n    \"Strikethrough\": \"Durchgestrichen\",\n    \"Inserted text\": \"Unterstrichen\",\n    \"Marked text\": \"Markiert\",\n    \"Link\": \"Link\",\n    \"Image\": \"Foto\",\n    \"Code\": \"Code\",\n    \"Externals\": \"Extern\",\n    \"This is a alert area.\": \"Dies ist ein Hinweisfeld.\",\n    \"Revert\": \"Zurücksetzen\",\n    \"Import from clipboard\": \"Importieren aus der Zwischenablage\",\n    \"Paste your markdown or webpage here...\": \"Markdown oder Website hier einfügen...\",\n    \"Clear\": \"Zurücksetzen\",\n    \"This note is locked\": \"Diese Notiz ist gesperrt\",\n    \"Sorry, only owner can edit this note.\": \"Entschuldigung, nur der Besitzer darf die Notiz bearbeiten.\",\n    \"OK\": \"Ok\",\n    \"Reach the limit\": \"Limit erreicht\",\n    \"Sorry, you've reached the max length this note can be.\": \"Entschuldigung, die maximale Länge der Notiz ist erreicht.\",\n    \"Please reduce the content or divide it to more notes, thank you!\": \"Bitte reduzieren Sie den Inhalt oder nutzen Sie mehrere Notizen, danke.\",\n    \"Import from Gist\": \"Aus Gist importieren\",\n    \"Paste your gist url here...\": \"gist URL hier einfügen ...\",\n    \"Import from Snippet\": \"Aus Snippet importieren\",\n    \"Select From Available Projects\": \"Aus verfügbaren Projekten wählen\",\n    \"Select From Available Snippets\": \"Aus verfügbaren Snippets wählen\",\n    \"OR\": \"Oder\",\n    \"Export to Snippet\": \"Zu Snippet exportieren\",\n    \"Select Visibility Level\": \"Sichtbarkeit bestimmen\",\n    \"Night Theme\": \"Nachtmodus\",\n    \"Follow us on %s and %s.\": \"Folge uns auf %s und %s.\",\n    \"Privacy\": \"Privatsphäre\",\n    \"Terms of Use\": \"Nutzungsbedingungen\",\n    \"Do you really want to delete your user account?\": \"Möchten Sie wirklich Ihren Nutzeraccount löschen?\",\n    \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"Hiermit löschen Sie Ihren Account, alle Ihre Notizen und alle Verweise auf Ihren Account aus anderen Notizen.\",\n    \"Delete user\": \"Benutzer löschen\",\n    \"Export user data\": \"Exportiere Nutzerdaten\",\n    \"Help us translating on %s\": \"Hilf uns zu übersetzen auf %s\",\n    \"Source Code\": \"Quelltext\"\n}\n"
  },
  {
    "path": "locales/el.json",
    "content": "{\n\t\"Collaborative markdown notes\": \"Συνεργατικές σημειώσεις markdown\",\n\t\"Realtime collaborative markdown notes on all platforms.\": \"Συνεργατική σημειώσεις markdown σε όλες τις πλατφόρμες σε πραγματικό χρόνο.\",\n\t\"Best way to write and share your knowledge in markdown.\": \"Ο καλύτερος τρόπος να γράψεις και να μοιραστείς την γνώση σου σε markdown.\",\n\t\"Intro\": \"Εισαγωγή\",\n\t\"History\": \"Ιστορία\",\n\t\"New guest note\": \"Νέα σημείωση επισκέπτη\",\n\t\"Collaborate with URL\": \"Συνεργαστείτε με URL\",\n\t\"Support charts and MathJax\": \"Υποστηρίζει διαγράμματα και MathJax\",\n\t\"Support slide mode\": \"Υποστηρίζει λειτουργία συρσίματος\",\n\t\"Sign In\": \"Eίσοδος\",\n\t\"Below is the history from browser\": \"Παρακάτω είναι η ιστορία του περιηγητή\",\n\t\"Welcome!\": \"Καλωσήρθατε!\",\n\t\"New note\": \"Νέα σημείωση\",\n\t\"or\": \"ή\",\n\t\"Sign Out\": \"Αποσύνδεση\",\n\t\"Explore all features\": \"Ανακαλύψτε όλες τις λειτουργίες\",\n\t\"Select tags...\": \"Επιλέξτε ετικέτα...\",\n\t\"Search keyword...\": \"Αναζήτηση λέξης-κλειδί...\",\n\t\"Sort by title\": \"Ταξινόμηση κατά τίτλο\",\n\t\"Title\": \"Τίτλος\",\n\t\"Sort by time\": \"Ταξινόμηση κατά ώρα\",\n\t\"Time\": \"Ώρα\",\n\t\"Export history\": \"Εξαγωγή ιστορίας\",\n\t\"Import history\": \"Εισαγωγή ιστορίας\",\n\t\"Clear history\": \"Καθαρισμός Ιστορίας\",\n\t\"Refresh history\": \"Ανανέωση ιστορίας\",\n\t\"No history\": \"Δεν υπάρχει ιστορία\",\n\t\"Import from browser\": \"Εισαγωγή απο τον περιηγητή\",\n\t\"Releases\": \"Κυκλοφορίες\",\n\t\"Are you sure?\": \"Είστε σίγουρος?\",\n\t\"Cancel\": \"Ακύρωση\",\n\t\"Yes, do it!\": \"Ναι, κάντο!\",\n\t\"Choose method\": \"Επιλογή μεθόδου\",\n\t\"Sign in via %s\": \"Σύνδεση μέσω %s\",\n\t\"New\": \"Νέο\",\n\t\"Publish\": \"Δημοσίευση\",\n\t\"Extra\": \"Επιπλέον\",\n\t\"Revision\": \"Αναθεώρηση\",\n\t\"Slide Mode\": \"Λειτουργία με σύρσιμο\",\n\t\"Export\": \"Εξαγωγή\",\n\t\"Import\": \"Εισαγωγή\",\n\t\"Clipboard\": \"Πρόχειρο\",\n\t\"Download\": \"Κατέβασμα\",\n\t\"Raw HTML\": \"Aκατέργαστο HTML\",\n\t\"Edit\": \"Επεξεργασία\",\n\t\"View\": \"Δες\",\n\t\"Both\": \"Και τα δύο\",\n\t\"Help\": \"Βοήθεια\",\n\t\"Upload Image\": \"Ανέβασμα φωτογραφίας\",\n\t\"Menu\": \"Μενού\",\n\t\"This page need refresh\": \"Η σελίδα χρειάζεται ανανέωση\",\n\t\"You have an incompatible client version.\": \"Έχετε μια μη συμβατή έκδοση.\",\n\t\"Refresh to update.\": \"Ανανεώστε για ενημέρωση\",\n\t\"New version available!\": \"Νέα διαθέσιμη έκδοση \",\n\t\"See releases notes here\": \"Δείτε τις κυκλοφορίες της σημείωσης εδώ\",\n\t\"Refresh to enjoy new features.\": \"Ανανεώστε για να δείτε τις κανούργιες λειτουργίες\",\n\t\"Your user state has changed.\": \"Η κατάσταση χρήστη έχει αλλάξει.\",\n\t\"Refresh to load new user state.\": \"Ανανεώστε για να φορτώσετε την νέα κατάσταση χρήστη.\",\n\t\"Refresh\": \"Ανανέωση\",\n\t\"Contacts\": \"Επαφές\",\n\t\"Report an issue\": \"Αναφέρετε ένα θέμα\",\n\t\"Send us email\": \"Στείλτε μας email\",\n\t\"Documents\": \"Έγγραφα\",\n\t\"Features\": \"Λειτουργία\",\n\t\"YAML Metadata\": \"YAML μεταδεδομένα\",\n\t\"Slide Example\": \"Σύρετε για παράδειγμα\",\n\t\"Cheatsheet\": \"Σκονάκι\",\n\t\"Example\": \"Παράδειγμα\",\n\t\"Syntax\": \"Σύνταξη\",\n\t\"Header\": \"Επικεφαλίδα\",\n\t\"Unordered List\": \"Μη αριθμημένη λίστα\",\n\t\"Ordered List\": \"Αριθμημένη λίστα\",\n\t\"Todo List\": \"Todo List\",\n\t\"Blockquote\": \"Παράγραφος\",\n\t\"Bold font\": \"Εντονη γραμματοσειρά\",\n\t\"Italics font\": \"Πλάγια γραμματοσειρά\",\n\t\"Strikethrough\": \"Διαγραμένη γραμματοσειρά\",\n\t\"Inserted text\": \"Εισαγμένο κείμενο\",\n\t\"Marked text\": \"Επιλεγμένο κείμενο\",\n\t\"Link\": \"Σύνδεσμος\",\n\t\"Image\": \"Εικόνα\",\n\t\"Code\": \"Κώδικας\",\n\t\"Externals\": \"Εξωτερικά\",\n\t\"This is a alert area.\": \"Αυτή είναι μια περιοχή ειδοποίησης\",\n\t\"Revert\": \"Επαναστροφή\",\n\t\"Import from clipboard\": \"Εισαγωγή από πρόχειρο\",\n\t\"Paste your markdown or webpage here...\": \"Επικολλήστε markdown ή την ιστοσελίδα σας εδώ...\",\n\t\"Clear\": \"Καθαρισμός\",\n\t\"This note is locked\": \"Η σημείωση είναι κλειδωμένη\",\n\t\"Sorry, only owner can edit this note.\": \"Συγνώμη, μόνο ο ιδιοκτήτης μπορεί να επεξεργαστεί αυτη την σημείωση.\",\n\t\"OK\": \"Εντάξει\",\n\t\"Reach the limit\": \"Φτάσατε το όριο\",\n\t\"Sorry, you've reached the max length this note can be.\": \"Συγνώμη, φτάσατε το μέγιστο μέγεθος αυτής της σημείωσης.\",\n\t\"Please reduce the content or divide it to more notes, thank you!\": \"Παρακαλώ μειώστε το περιεχόμενο η διαιρέστε το σε περισσότερες σημειώσεις, ευχαριστώ!\",\n\t\"Import from Gist\": \"Εισαγωγή από Gist\",\n\t\"Paste your gist url here...\": \"Κάντε επικκόληση του gist url εδώ...\",\n\t\"Import from Snippet\": \"Εισαγωγή από Snippet\",\n\t\"Select From Available Projects\": \"Eπιλογή από διαθέσιμα Projects\",\n\t\"Select From Available Snippets\": \"Eπιλογή από διαθέσιμα Snippets\",\n\t\"OR\": \"Ή\",\n\t\"Export to Snippet\": \"Eξαγωγή σε Snippet\",\n\t\"Select Visibility Level\": \"Επιλέξτε επίπεδο ορατότητας\"\n}\n"
  },
  {
    "path": "locales/en.json",
    "content": "{\n\t\"Collaborative markdown notes\": \"Collaborative markdown notes\",\n\t\"Realtime collaborative markdown notes on all platforms.\": \"Collaborate on markdown notes on all platforms in realtime.\",\n\t\"Best way to write and share your knowledge in markdown.\": \"The best platform to write and share markdown.\",\n\t\"Intro\": \"Intro\",\n\t\"History\": \"History\",\n\t\"New guest note\": \"New guest note\",\n\t\"Collaborate with URL\": \"Real time collaboration\",\n\t\"Support charts and MathJax\": \"Works with charts and MathJax\",\n\t\"Support slide mode\": \"Supports slide mode\",\n\t\"Sign In\": \"Sign In\",\n\t\"Below is the history from browser\": \"Below is history from this browser\",\n\t\"Welcome!\": \"Welcome!\",\n\t\"New note\": \"New note\",\n\t\"or\": \"or\",\n\t\"Sign Out\": \"Sign Out\",\n\t\"Explore all features\": \"Explore all features\",\n\t\"Select tags...\": \"Select tags…\",\n\t\"Search keyword...\": \"Search keyword…\",\n\t\"Sort by title\": \"Sort by title\",\n\t\"Title\": \"Title\",\n\t\"Sort by time\": \"Sort by time\",\n\t\"Time\": \"Time\",\n\t\"Export history\": \"Export history\",\n\t\"Import history\": \"Import history\",\n\t\"Clear history\": \"Clear history\",\n\t\"Refresh history\": \"Refresh history\",\n\t\"No history\": \"No history\",\n\t\"Import from browser\": \"Import from browser\",\n\t\"Releases\": \"Releases\",\n\t\"Are you sure?\": \"Are you sure?\",\n\t\"Do you really want to delete this note?\": \"Do you really want to delete this note?\",\n\t\"All users will lose their connection.\": \"All users will lose their connection.\",\n\t\"Cancel\": \"Cancel\",\n\t\"Yes, do it!\": \"Yes, do it!\",\n\t\"Choose method\": \"Choose method\",\n\t\"Sign in via %s\": \"Sign in via %s\",\n\t\"New\": \"New\",\n\t\"Publish\": \"Publish\",\n\t\"Extra\": \"Extra\",\n\t\"Revision\": \"Revision\",\n\t\"Slide Mode\": \"Slide Mode\",\n\t\"Export\": \"Export\",\n\t\"Import\": \"Import\",\n\t\"Clipboard\": \"Clipboard\",\n\t\"Download\": \"Download\",\n\t\"Raw HTML\": \"Raw HTML\",\n\t\"Edit\": \"Edit\",\n\t\"View\": \"View\",\n\t\"Both\": \"Both\",\n\t\"Help\": \"Help\",\n\t\"Upload Image\": \"Upload Image\",\n\t\"Menu\": \"Menu\",\n\t\"This page need refresh\": \"This page needs to be refreshed\",\n\t\"You have an incompatible client version.\": \"Your client's version is incompatible.\",\n\t\"Refresh to update.\": \"Refresh to update.\",\n\t\"New version available!\": \"New version available!\",\n\t\"See releases notes here\": \"See releases notes here\",\n\t\"Refresh to enjoy new features.\": \"Refresh to enjoy new features.\",\n\t\"Your user state has changed.\": \"Your user state has changed.\",\n\t\"Refresh to load new user state.\": \"Refresh to load new user state.\",\n\t\"Refresh\": \"Refresh\",\n\t\"Contacts\": \"Contacts\",\n\t\"Report an issue\": \"Report an issue\",\n\t\"Meet us on %s\": \"Meet us on %s\",\n\t\"Send us email\": \"Send us email\",\n\t\"Documents\": \"Documents\",\n\t\"Features\": \"Features\",\n\t\"YAML Metadata\": \"YAML Metadata\",\n\t\"Slide Example\": \"Slide Example\",\n\t\"Cheatsheet\": \"Cheatsheet\",\n\t\"Example\": \"Example\",\n\t\"Syntax\": \"Syntax\",\n\t\"Header\": \"Header\",\n\t\"Unordered List\": \"Unordered List\",\n\t\"Ordered List\": \"Ordered List\",\n\t\"Todo List\": \"Checklist\",\n\t\"Blockquote\": \"Blockquote\",\n\t\"Bold font\": \"Bold\",\n\t\"Italics font\": \"Italicize\",\n\t\"Strikethrough\": \"Strikethrough\",\n\t\"Inserted text\": \"Underlined text\",\n\t\"Marked text\": \"Highlighted text\",\n\t\"Link\": \"Link\",\n\t\"Image\": \"Image\",\n\t\"Code\": \"Code\",\n\t\"Externals\": \"Externals\",\n\t\"This is a alert area.\": \"This is an alert area.\",\n\t\"Revert\": \"Revert\",\n\t\"Import from clipboard\": \"Import from clipboard\",\n\t\"Paste your markdown or webpage here...\": \"Paste your markdown or webpage here…\",\n\t\"Clear\": \"Clear\",\n\t\"This note is locked\": \"This note is locked\",\n\t\"Sorry, only owner can edit this note.\": \"Sorry, only the owner can edit this note.\",\n\t\"OK\": \"OK\",\n\t\"Reach the limit\": \"Reach the limit\",\n\t\"Sorry, you've reached the max length this note can be.\": \"Sorry, you've reached the maximum length this note can be.\",\n\t\"Please reduce the content or divide it to more notes, thank you!\": \"Please shorten the note.\",\n\t\"Import from Gist\": \"Import from Gist\",\n\t\"Paste your gist url here...\": \"Paste your gist url here…\",\n\t\"Import from Snippet\": \"Import from Snippet\",\n\t\"Select From Available Projects\": \"Select From Available Projects\",\n\t\"Select From Available Snippets\": \"Select From Available Snippets\",\n\t\"OR\": \"OR\",\n\t\"Export to Snippet\": \"Export to Snippet\",\n\t\"Select Visibility Level\": \"Select Visibility Level\",\n\t\"Night Theme\": \"Night Theme\",\n\t\"Follow us on %s and %s.\": \"Follow us on %s, and %s.\",\n\t\"Privacy\": \"Privacy\",\n\t\"Terms of Use\": \"Terms of Use\",\n\t\"Do you really want to delete your user account?\": \"Do you really want to delete your user account?\",\n\t\"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\",\n\t\"Delete user\": \"Delete user\",\n\t\"Export user data\": \"Export user data\",\n\t\"Help us translating on %s\": \"Help us translating on %s\",\n\t\"Source Code\": \"Source Code\",\n\t\"Powered by %s\": \"Powered by %s\",\n\t\"Register\": \"Register\",\n\t\"Export with pandoc\": \"Export with pandoc\",\n\t\"Select output format\": \"Select output format\"\n}"
  },
  {
    "path": "locales/eo.json",
    "content": "{\n\t\"Collaborative markdown notes\": \"Kunlaborataj marksubenaj notoj\",\n\t\"Realtime collaborative markdown notes on all platforms.\": \"Tujkunlaborataj marksubenaj notoj ĉe ĉiuj sistemoj.\",\n\t\"Best way to write and share your knowledge in markdown.\": \"La plej bona maniero skribi kaj havigi vian scion marksubene.\",\n\t\"Intro\": \"Enkonduko\",\n\t\"History\": \"Historio\",\n\t\"New guest note\": \"Novan gastan noton\",\n\t\"Collaborate with URL\": \"Kunlaboru per URL\",\n\t\"Support charts and MathJax\": \"Ebleco por skemoj kaj MathJax\",\n\t\"Support slide mode\": \"Ebleco por bildvica modo\",\n\t\"Sign In\": \"Ensalutu\",\n\t\"Below is the history from browser\": \"Malsupre estas la historio de la retumilo\",\n\t\"Welcome!\": \"Bonvenon!\",\n\t\"New note\": \"Novan Noton\",\n\t\"or\": \"aŭ\",\n\t\"Sign Out\": \"Elsalutu\",\n\t\"Explore all features\": \"Esploru ĉiujn eblecojn\",\n\t\"Select tags...\": \"Elektu etikedojn..\",\n\t\"Search keyword...\": \"Serĉu ĉefvorton...\",\n\t\"Sort by title\": \"Ordigu laŭ titolo\",\n\t\"Title\": \"Titolo\",\n\t\"Sort by time\": \"Ordigu laŭ tempo\",\n\t\"Time\": \"Tempo\",\n\t\"Export history\": \"Elportu historion\",\n\t\"Import history\": \"Alportu historion\",\n\t\"Clear history\": \"Malplenigu historion\",\n\t\"Refresh history\": \"Refreŝigu historion\",\n\t\"No history\": \"Neniu historio\",\n\t\"Import from browser\": \"Alportu de retumilo\",\n\t\"Releases\": \"Eldonoj\",\n\t\"Are you sure?\": \"Ĉu vi certas?\",\n\t\"Cancel\": \"Nuligu\",\n\t\"Yes, do it!\": \"Jes, faru ĝin!\",\n\t\"Choose method\": \"Elektu metodon\",\n\t\"Sign in via %s\": \"Ensalutu per %s\",\n\t\"New\": \"Nova\",\n\t\"Publish\": \"Dissendu\",\n\t\"Extra\": \"Plia\",\n\t\"Revision\": \"Versio\",\n\t\"Slide Mode\": \"Bildvica modo\",\n\t\"Export\": \"Elportu\",\n\t\"Import\": \"Alportu\",\n\t\"Clipboard\": \"Poŝo\",\n\t\"Download\": \"Elŝuti\",\n\t\"Raw HTML\": \"Kruda HTML\",\n\t\"Edit\": \"Redaktu\",\n\t\"View\": \"Vidu\",\n\t\"Both\": \"Ambaŭ\",\n\t\"Help\": \"Helpo\",\n\t\"Upload Image\": \"Alŝutu bildon\",\n\t\"Menu\": \"Menuo\",\n\t\"This page need refresh\": \"Ĉi tiu paĝo bezonas refreŝiĝi\",\n\t\"You have an incompatible client version.\": \"Vi havas malkongruan klientversion.\",\n\t\"Refresh to update.\": \"Refreŝigu por ĝisdatigi\",\n\t\"New version available!\": \"Nova versio disponeblas!\",\n\t\"See releases notes here\": \"Vidu elsendajn notojn ĉi tie\",\n\t\"Refresh to enjoy new features.\": \"Refreŝigu por ĝui novajn eblecojn.\",\n\t\"Your user state has changed.\": \"Via uzantstato ŝanĝiĝis.\",\n\t\"Refresh to load new user state.\": \"Refreŝigu por ŝargi novan uzantstaton.\",\n\t\"Refresh\": \"Refreŝigu\",\n\t\"Contacts\": \"Kontaktuloj\",\n\t\"Report an issue\": \"Raportu problemon\",\n\t\"Send us email\": \"Sendu al ni retpoŝton\",\n\t\"Documents\": \"Dosieroj\",\n\t\"Features\": \"Eblecoj\",\n\t\"YAML Metadata\": \"YAML metadateno\",\n\t\"Slide Example\": \"Bildvica ekzemplo\",\n\t\"Cheatsheet\": \"Gvidfolio\",\n\t\"Example\": \"Ekzemplo\",\n\t\"Syntax\": \"Sintakso\",\n\t\"Header\": \"Paĝokapo\",\n\t\"Unordered List\": \"Neordita Listo\",\n\t\"Ordered List\": \"Ordita Listo\",\n\t\"Todo List\": \"Farenda Listo\",\n\t\"Blockquote\": \"Deŝovita cito\",\n\t\"Bold font\": \"Dika tiparo\",\n\t\"Italics font\": \"Kursiva tiparo\",\n\t\"Strikethrough\": \"Trastrekita\",\n\t\"Inserted text\": \"Enmetita teksto\",\n\t\"Marked text\": \"Markita teksto\",\n\t\"Link\": \"Ligilo\",\n\t\"Image\": \"Bildo\",\n\t\"Code\": \"Kodo\",\n\t\"Externals\": \"Eksteraĵoj\",\n\t\"This is a alert area.\": \"Ĉi tiu estas avertzono.\",\n\t\"Revert\": \"Malfaru ŝanĝojn\",\n\t\"Import from clipboard\": \"Alportu de la poŝo\",\n\t\"Paste your markdown or webpage here...\": \"Algluu vian marksubenon aŭ retpaĝaron ĉi tie...\",\n\t\"Clear\": \"Malplenigu\",\n\t\"This note is locked\": \"Ĉi tiu noto estas ŝlosita\",\n\t\"Sorry, only owner can edit this note.\": \"Bedaŭrinde, nur la proprulo povas redakti ĉi tiun noton.\",\n\t\"OK\": \"Bone\",\n\t\"Reach the limit\": \"Atingi la limigon\",\n\t\"Sorry, you've reached the max length this note can be.\": \"Pardonon, ĉi tiu noto jam atingis maksimuman longecon.\",\n\t\"Please reduce the content or divide it to more notes, thank you!\": \"Bonvolu malpligrandigi la enhavaĵon, aŭ dividi ĝin en pliajn notojn!\",\n\t\"Import from Gist\": \"Alportu el Gist\",\n\t\"Paste your gist url here...\": \"Algluu vian gist-an URL-n ĉi tie...\",\n\t\"Import from Snippet\": \"Alportu el tekstero\",\n\t\"Select From Available Projects\": \"Elektu el disponeblaj projektoj\",\n\t\"Select From Available Snippets\": \"Elektu el disponeblaj teksteroj\",\n\t\"OR\": \"AŬ\",\n\t\"Export to Snippet\": \"Elportu al Snippet\",\n\t\"Select Visibility Level\": \"Elektu videblecan nivelon\"\n}\n"
  },
  {
    "path": "locales/es.json",
    "content": "{\n\t\"Collaborative markdown notes\": \"Notas colaborativas en Markdown\",\n\t\"Realtime collaborative markdown notes on all platforms.\": \"Notas colaborativas en Markdown para todas las plataformas.\",\n\t\"Best way to write and share your knowledge in markdown.\": \"La mejor forma de escribir y compartir tu conocimiento en Markdown.\",\n\t\"Intro\": \"Introducción\",\n\t\"History\": \"Historia\",\n\t\"New guest note\": \"Nueva nota como invitado\",\n\t\"Collaborate with URL\": \"Colaborar via URL\",\n\t\"Support charts and MathJax\": \"Soporte para gráficos y MathJax\",\n\t\"Support slide mode\": \"Soporte para diapositivas\",\n\t\"Sign In\": \"Ingresar\",\n\t\"Below is the history from browser\": \"A continuación se muestra el historial del navegador\",\n\t\"Welcome!\": \"¡Bienvenido!\",\n\t\"New note\": \"Nueva nota\",\n\t\"or\": \"o\",\n\t\"Sign Out\": \"Salir\",\n\t\"Explore all features\": \"Explorar todas las funciones\",\n\t\"Select tags...\": \"Seleccionar etiquetas...\",\n\t\"Search keyword...\": \"Buscar palabras clave...\",\n\t\"Sort by title\": \"Ordenar por título\",\n\t\"Title\": \"Título\",\n\t\"Sort by time\": \"Ordenar por fecha\",\n\t\"Time\": \"Tiempo\",\n\t\"Export history\": \"Exportar historial\",\n\t\"Import history\": \"Importar historial\",\n\t\"Clear history\": \"Borrar historial\",\n\t\"Refresh history\": \"Actualizar historial\",\n\t\"No history\": \"Ningún historial\",\n\t\"Import from browser\": \"Importar del navegador\",\n\t\"Releases\": \"Versiones\",\n\t\"Are you sure?\": \"¿Estás seguro?\",\n\t\"Cancel\": \"Cancelar\",\n\t\"Yes, do it!\": \"Si, ¡hazlo!\",\n\t\"Choose method\": \"Elegir método\",\n\t\"Sign in via %s\": \"Ingresar via %s\",\n\t\"New\": \"Nuevo\",\n\t\"Publish\": \"Publicar\",\n\t\"Extra\": \"Extra\",\n\t\"Revision\": \"Revision\",\n\t\"Slide Mode\": \"Modo presentación\",\n\t\"Export\": \"Exportar\",\n\t\"Import\": \"Importar\",\n\t\"Clipboard\": \"Portapapeles\",\n\t\"Download\": \"Descargar\",\n\t\"Raw HTML\": \"HTML puro\",\n\t\"Edit\": \"Editar\",\n\t\"View\": \"Ver\",\n\t\"Both\": \"Ambos\",\n\t\"Help\": \"Ayuda\",\n\t\"Upload Image\": \"Subir imagen\",\n\t\"Menu\": \"Menú\",\n\t\"This page need refresh\": \"Esta página necesita ser cargada de nuevo\",\n\t\"You have an incompatible client version.\": \"Tienes una version del cliente incompatible.\",\n\t\"Refresh to update.\": \"Cargar de nuevo para actualizar.\",\n\t\"New version available!\": \"¡Nueva versión disponible!\",\n\t\"See releases notes here\": \"Ver aquí las notas de publicación\",\n\t\"Refresh to enjoy new features.\": \"Actualizar para usar las nuevas funciones.\",\n\t\"Your user state has changed.\": \"El estado de tu usuario ha cambiado.\",\n\t\"Refresh to load new user state.\": \"Recargar para actualizar el estado de tu usuario.\",\n\t\"Refresh\": \"Recargar\",\n\t\"Contacts\": \"Contactos\",\n\t\"Report an issue\": \"Reportar un problema\",\n\t\"Send us email\": \"Enviarnos un email\",\n\t\"Documents\": \"Documentos\",\n\t\"Features\": \"Funciones\",\n\t\"YAML Metadata\": \"Metadatos en YAML\",\n\t\"Slide Example\": \"Ejemplo de diapositiva\",\n\t\"Cheatsheet\": \"Ayudamemorias\",\n\t\"Example\": \"Ejemplo\",\n\t\"Syntax\": \"Sintaxis\",\n\t\"Header\": \"Cabecera\",\n\t\"Unordered List\": \"Lista desordenada\",\n\t\"Ordered List\": \"Lista ordenada\",\n\t\"Todo List\": \"Lista de tareas\",\n\t\"Blockquote\": \"Bloque de cita\",\n\t\"Bold font\": \"Fuente negrita\",\n\t\"Italics font\": \"Fuente itálica\",\n\t\"Strikethrough\": \"Tachado\",\n\t\"Inserted text\": \"Texto subrayado\",\n\t\"Marked text\": \"Texto marcado\",\n\t\"Link\": \"Enlace\",\n\t\"Image\": \"Imagen\",\n\t\"Code\": \"Código\",\n\t\"Externals\": \"Externos\",\n\t\"This is a alert area.\": \"Esto es un área de alerta.\",\n\t\"Revert\": \"Revertir\",\n\t\"Import from clipboard\": \"Importar del portapapeles\",\n\t\"Paste your markdown or webpage here...\": \"Pega tu markdown o página web aquí...\",\n\t\"Clear\": \"Limpiar\",\n\t\"This note is locked\": \"Esta nota está bloqueada\",\n\t\"Sorry, only owner can edit this note.\": \"Disculpa, solo el dueño puede editar esta nota.\",\n\t\"OK\": \"OK\",\n\t\"Reach the limit\": \"Haz alcanzado el límite\",\n\t\"Sorry, you've reached the max length this note can be.\": \"Disculpa, haz alcanzado la longitud máxima que puede tener esta nota.\",\n\t\"Please reduce the content or divide it to more notes, thank you!\": \"Por favor, reduce el contenido o dividela en mas notas, ¡gracias!\",\n\t\"Import from Gist\": \"Importar de un Gist\",\n\t\"Paste your gist url here...\": \"Pega el URL de tu Gist aquí...\",\n\t\"Import from Snippet\": \"Importar de Snippet\",\n\t\"Select From Available Projects\": \"Elegir de un proyecto disponible\",\n\t\"Select From Available Snippets\": \"Elegir de un Snippet disponible\",\n\t\"OR\": \"O\",\n\t\"Export to Snippet\": \"Exportar a Snippet\",\n\t\"Select Visibility Level\": \"Elegir el nivel de visibilidad\"\n}\n"
  },
  {
    "path": "locales/fr.json",
    "content": "{\n    \"Collaborative markdown notes\": \"Notes collaboratives en markdown\",\n    \"Realtime collaborative markdown notes on all platforms.\": \"Notes en markdown collaboratives en temps réel sur toutes les plateformes.\",\n    \"Best way to write and share your knowledge in markdown.\": \"Le meilleur moyen d'écrire et partager votre savoir en markdown.\",\n    \"Intro\": \"Intro\",\n    \"History\": \"Historique\",\n    \"New guest note\": \"Nouvelle note invité\",\n    \"Collaborate with URL\": \"Collaborez avec l'URL\",\n    \"Support charts and MathJax\": \"Supporte les graphiques et MathJax\",\n    \"Support slide mode\": \"Supporte le mode présentation\",\n    \"Sign In\": \"Se connecter\",\n    \"Below is the history from browser\": \"Ci-dessous, l'historique du navigateur\",\n    \"Welcome!\": \"Bienvenue !\",\n    \"New note\": \"Nouvelle note\",\n    \"or\": \"ou\",\n    \"Sign Out\": \"Se déconnecter\",\n    \"Explore all features\": \"Explorer toutes les fonctionnalités\",\n    \"Select tags...\": \"Sélectionner les tags...\",\n    \"Search keyword...\": \"Chercher un mot-clef...\",\n    \"Sort by title\": \"Trier par titre\",\n    \"Title\": \"Titre\",\n    \"Sort by time\": \"Trier par date\",\n    \"Time\": \"Date\",\n    \"Export history\": \"Exporter l'historique\",\n    \"Import history\": \"Importer l'historique\",\n    \"Clear history\": \"Supprimer l'historique\",\n    \"Refresh history\": \"Actualiser l'historique\",\n    \"No history\": \"Pas d'historique\",\n    \"Import from browser\": \"Importer depuis le navigateur\",\n    \"Releases\": \"Versions\",\n    \"Are you sure?\": \"Êtes-vous sûr ?\",\n    \"Do you really want to delete this note?\": \"Voulez-vous vraiment supprimer cette note ?\",\n    \"All users will lose their connection.\": \"Tous les utilisateurs perdront leur connexion.\",\n    \"Cancel\": \"Annuler\",\n    \"Yes, do it!\": \"Oui, je suis sûr !\",\n    \"Choose method\": \"Choisir la méthode\",\n    \"Sign in via %s\": \"Se connecter depuis %s\",\n    \"New\": \"Nouvelle\",\n    \"Publish\": \"Publier\",\n    \"Extra\": \"Extra\",\n    \"Revision\": \"Historique\",\n    \"Slide Mode\": \"Mode présentation\",\n    \"Export\": \"Exporter\",\n    \"Import\": \"Importer\",\n    \"Clipboard\": \"Presse-papier\",\n    \"Download\": \"Télécharger\",\n    \"Raw HTML\": \"HTML brut\",\n    \"Edit\": \"Éditer\",\n    \"View\": \"Voir\",\n    \"Both\": \"Les deux\",\n    \"Help\": \"Aide\",\n    \"Upload Image\": \"Uploader une image\",\n    \"Menu\": \"Menu\",\n    \"This page need refresh\": \"Cette page doit être rechargée\",\n    \"You have an incompatible client version.\": \"Vous avez une version client incompatible.\",\n    \"Refresh to update.\": \"Recharger pour mettre à jour.\",\n    \"New version available!\": \"Nouvelle version disponible !\",\n    \"See releases notes here\": \"Voir les commentaires de version ici\",\n    \"Refresh to enjoy new features.\": \"Recharger pour bénéficier des nouvelles fonctionnalités.\",\n    \"Your user state has changed.\": \"Votre statut utilisateur a changé.\",\n    \"Refresh to load new user state.\": \"Recharger pour avoir le nouveau statut utilisateur.\",\n    \"Refresh\": \"Recharger\",\n    \"Contacts\": \"Contacts\",\n    \"Report an issue\": \"Signaler un problème\",\n    \"Meet us on %s\": \"Rencontrez-nous sur %s\",\n    \"Send us email\": \"Envoyez-nous un mail\",\n    \"Documents\": \"Documents\",\n    \"Features\": \"Fonctionnalités\",\n    \"YAML Metadata\": \"Métadonnées YAML\",\n    \"Slide Example\": \"Exemple de présentation\",\n    \"Cheatsheet\": \"Pense-bête\",\n    \"Example\": \"Exemple\",\n    \"Syntax\": \"Syntaxe\",\n    \"Header\": \"En-tête\",\n    \"Unordered List\": \"Liste à puce\",\n    \"Ordered List\": \"Liste numérotée\",\n    \"Todo List\": \"Liste de tâches\",\n    \"Blockquote\": \"Citation\",\n    \"Bold font\": \"Gras\",\n    \"Italics font\": \"Italique\",\n    \"Strikethrough\": \"Barré\",\n    \"Inserted text\": \"Souligné\",\n    \"Marked text\": \"Surligné\",\n    \"Link\": \"Lien\",\n    \"Image\": \"Image\",\n    \"Code\": \"Code\",\n    \"Externals\": \"Contenus externes\",\n    \"This is a alert area.\": \"Ceci est un texte d'alerte.\",\n    \"Revert\": \"Revenir en arrière\",\n    \"Import from clipboard\": \"Importer depuis le presse-papier\",\n    \"Paste your markdown or webpage here...\": \"Collez votre markdown ou votre page web ici...\",\n    \"Clear\": \"Vider\",\n    \"This note is locked\": \"Cette note est verrouillée\",\n    \"Sorry, only owner can edit this note.\": \"Désolé, seul le propriétaire peut éditer cette note.\",\n    \"OK\": \"OK\",\n    \"Reach the limit\": \"Atteindre la limite\",\n    \"Sorry, you've reached the max length this note can be.\": \"Désolé, vous avez atteint la longueur maximale que cette note peut avoir.\",\n    \"Please reduce the content or divide it to more notes, thank you!\": \"Merci de réduire le contenu ou de le diviser en plusieurs notes !\",\n    \"Import from Gist\": \"Importer depuis Gist\",\n    \"Paste your gist url here...\": \"Coller l'URL de votre Gist ici...\",\n    \"Import from Snippet\": \"Importer depuis Snippet\",\n    \"Select From Available Projects\": \"Sélectionner depuis les projets disponibles\",\n    \"Select From Available Snippets\": \"Sélectionner depuis les Snippets disponibles\",\n    \"OR\": \"OU\",\n    \"Export to Snippet\": \"Exporter vers Snippet\",\n    \"Select Visibility Level\": \"Sélectionner le niveau de visibilité\",\n    \"Night Theme\": \"Thème Nuit\",\n    \"Follow us on %s and %s.\": \"Suivez-nous sur %s, et %s.\",\n    \"Privacy\": \"Confidentialité\",\n    \"Terms of Use\": \"Conditions d'utilisation\",\n    \"Do you really want to delete your user account?\": \"Voulez-vous vraiment supprimer votre compte utilisateur ?\",\n    \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"Cela supprimera votre compte, toutes les notes dont vous êtes propriétaire et supprimera toute référence à votre compte dans les autres notes.\",\n    \"Delete user\": \"Supprimer l'utilisateur\",\n    \"Export user data\": \"Exporter les données utilisateur\",\n    \"Help us translating on %s\": \"Aidez nous à traduire sur %s\",\n    \"Source Code\": \"Code source\",\n    \"Register\": \"S'enregistrer\",\n    \"Powered by %s\": \"Propulsé par %s\"\n}\n"
  },
  {
    "path": "locales/hi.json",
    "content": "{\n\t\"Collaborative markdown notes\": \"सहयोगात्मक मार्कडॉऊन नोट्स\",\n\t\"Realtime collaborative markdown notes on all platforms.\": \"सभी प्लेटफार्मों पर वास्तविक समय सहयोगी मार्कडॉऊन के नोट्स\",\n\t\"Best way to write and share your knowledge in markdown.\": \"मार्कडॉऊन में लिखने के लिए और अपना ज्ञान शेयर करने का सबसे अच्छा तरीका\",\n\t\"Intro\": \"परिचय\",\n\t\"History\": \"इतिहास\",\n\t\"New guest note\": \"नया अतिथि नोट\",\n\t\"Collaborate with URL\": \"यूआरएल के साथ सहयोग करें\",\n\t\"Support charts and MathJax\": \"चार्ट और MathJax का समर्थन\",\n\t\"Support slide mode\": \"स्लाइड मोड का समर्थन\",\n\t\"Sign In\": \"साइन इन करें\",\n\t\"Below is the history from browser\": \"नीचे ब्राउज़र से इतिहास है\",\n\t\"Welcome!\": \"स्वागत हे!\",\n\t\"New note\": \"नया नोट\",\n\t\"or\": \"या\",\n\t\"Sign Out\": \"साइन आउट\",\n\t\"Explore all features\": \"सभी सुविधाओं का अन्वेषण करें\",\n\t\"Select tags...\": \"टैग का चयन करें ...\",\n\t\"Search keyword...\": \"मुख्य शब्द ढूंडो...\",\n\t\"Sort by title\": \"शीर्षक द्वारा क्रमबद्ध करें\",\n\t\"Title\": \"शीर्षक\",\n\t\"Sort by time\": \"समय के अनुसार क्रमबद्ध करें\",\n\t\"Time\": \"समय\",\n\t\"Export history\": \"इतिहास को निर्यात करें\",\n\t\"Import history\": \"इतिहास को आयात करें\",\n\t\"Clear history\": \"इतिहास मिटा दें\",\n\t\"Refresh history\": \"इतिहास ताज़ा करे\",\n\t\"No history\": \"इतिहास न रखें\",\n\t\"Import from browser\": \"ब्राउज़र से आयात\",\n\t\"Releases\": \"विज्ञप्ति\",\n\t\"Are you sure?\": \"क्या आपको यकीन है?\",\n\t\"Cancel\": \"रद्द करे\",\n\t\"Yes, do it!\": \"हाँ करो इसे!\",\n\t\"Choose method\": \"विधि चुनें\",\n\t\"Sign in via %s\": \"%s के माध्यम से साइन इन करें\",\n\t\"New\": \"नया\",\n\t\"Publish\": \"प्रकाशित करें\",\n\t\"Extra\": \"अतिरिक्त\",\n\t\"Revision\": \"संशोधन\",\n\t\"Slide Mode\": \"स्लाइड मोड\",\n\t\"Export\": \"निर्यात\",\n\t\"Import\": \"आयात\",\n\t\"Clipboard\": \"क्लिपबोर्ड\",\n\t\"Download\": \"डाउनलोड\",\n\t\"Raw HTML\": \"सिर्फ एच टी एम एल\",\n\t\"Edit\": \"संपादित करें\",\n\t\"View\": \"देखें\",\n\t\"Both\": \"दोनों\",\n\t\"Help\": \"मदद\",\n\t\"Upload Image\": \"तस्वीर डालिये\",\n\t\"Menu\": \"मेन्यू\",\n\t\"This page need refresh\": \"इस पेज को ताजा करने की जरूरत है\",\n\t\"You have an incompatible client version.\": \"आप एक असंगत ग्राहक संस्करण है।\",\n\t\"Refresh to update.\": \"अद्यतन करने के लिए ताज़ा करें।\",\n\t\"New version available!\": \"नया संस्करण उपलब्ध है!\",\n\t\"See releases notes here\": \"यहाँ रिलीज़ नोट देखें \",\n\t\"Refresh to enjoy new features.\": \"नई सुविधाओं का आनंद करने के लिए ताज़ा करें।\",\n\t\"Your user state has changed.\": \"आपका उपयोगकर्ता राज्य बदल गया है।\",\n\t\"Refresh to load new user state.\": \"नई उपयोगकर्ता राज्य लोड करने के लिए ताज़ा करें।\",\n\t\"Refresh\": \"ताज़ा करे\",\n\t\"Contacts\": \"संपर्क\",\n\t\"Report an issue\": \"मामले की रिपोर्ट करें\",\n\t\"Send us email\": \"हमें ईमेल भेजें\",\n\t\"Documents\": \"दस्तावेज़\",\n\t\"Features\": \"विशेषताएं\",\n\t\"YAML Metadata\": \"YAML मेटाडाटा\",\n\t\"Slide Example\": \"स्लाइड उदाहरण\",\n\t\"Cheatsheet\": \"प्रवंचक पत्रक\",\n\t\"Example\": \"उदाहरण\",\n\t\"Syntax\": \"वाक्य - विन्यास\",\n\t\"Header\": \"हैडर\",\n\t\"Unordered List\": \"अव्यवस्थित सूची\",\n\t\"Ordered List\": \"आदेश सूची\",\n\t\"Todo List\": \"करने के लिए सूची\",\n\t\"Blockquote\": \"ब्लॉककोट\",\n\t\"Bold font\": \"बोल्ड फ़ॉन्ट\",\n\t\"Italics font\": \"इटालिक फ़ॉन्ट\",\n\t\"Strikethrough\": \"स्ट्राइकथ्रू\",\n\t\"Inserted text\": \"डाला गया टेक्स्ट\",\n\t\"Marked text\": \"निशान किया हुआ टेक्स्ट\",\n\t\"Link\": \"लिंक\",\n\t\"Image\": \"तस्वीर\",\n\t\"Code\": \"कोड\",\n\t\"Externals\": \"बाहरी\",\n\t\"This is a alert area.\": \"यह एक चेतावनी क्षेत्र है।\",\n\t\"Revert\": \"वापस करें\",\n\t\"Import from clipboard\": \"क्लिपबोर्ड से आयात\",\n\t\"Paste your markdown or webpage here...\": \"यहाँ अपने मार्कडॉऊन या वेब पेज पेस्ट करें ...\",\n\t\"Clear\": \"साफ़ करें\",\n\t\"This note is locked\": \"इस नोट को बंद कर दिया है\",\n\t\"Sorry, only owner can edit this note.\": \"क्षमा करें, केवल मालिक इस नोट को संपादित कर सकते हैं।\",\n\t\"OK\": \"ठीक\",\n\t\"Reach the limit\": \"सीमा तक पहुँचना\",\n\t\"Sorry, you've reached the max length this note can be.\": \"क्षमा करें, आप इस नोट की अधिकतम लंबाई तक पहुँच गए हैं।\",\n\t\"Please reduce the content or divide it to more notes, thank you!\": \"सामग्री को कम करें या इसे और अधिक नोटों में विभाजित करें, धन्यवाद!\",\n\t\"Import from Gist\": \"Gist से आयात करें\",\n\t\"Paste your gist url here...\": \"यहाँ अपना gist यूआरएल पेस्ट करें ...\",\n\t\"Import from Snippet\": \"स्निपेट से आयात करें\",\n\t\"Select From Available Projects\": \"उपलब्ध परियोजनाओं से चयन करें\",\n\t\"Select From Available Snippets\": \"उपलब्ध स्निपेट से चयन करें\",\n\t\"OR\": \"या\",\n\t\"Export to Snippet\": \"स्निपेट में निर्यात\",\n\t\"Select Visibility Level\": \"दृश्यता के स्तर का चयन\"\n}\n"
  },
  {
    "path": "locales/hr.json",
    "content": "{\r\n\t\"Collaborative markdown notes\": \"Kolaborativne markdown bilješke\",\r\n\t\"Realtime collaborative markdown notes on all platforms.\": \"Kolaborativne markdown bilješke na svim platformama u realnom vremenu.\",\r\n\t\"Best way to write and share your knowledge in markdown.\": \"Najbolji način za pisanje i dijeljenje svog znanja u markdown-u.\",\r\n\t\"Intro\": \"Uvod\",\r\n\t\"History\": \"Povijest\",\r\n\t\"New guest note\": \"Nova bilješka gosta\",\r\n\t\"Collaborate with URL\": \"Kolaboracija sa URL-om\",\r\n\t\"Support charts and MathJax\": \"Support charts and MathJax\",\r\n\t\"Support slide mode\": \"Način podrške slajda\",\r\n\t\"Sign In\": \"Prijavu se\",\r\n\t\"Below is the history from browser\": \"Ispod je povijest preglednika\",\r\n\t\"Welcome!\": \"Dobrodošli!\",\r\n\t\"New note\": \"Nova bilješka\",\r\n\t\"or\": \"ili\",\r\n\t\"Sign Out\": \"Odjavi se\",\r\n\t\"Explore all features\": \"Istraži sve značajke\",\r\n\t\"Select tags...\": \"Odaberi oznake...\",\r\n\t\"Search keyword...\": \"Pretraži ključnu riječ...\",\r\n\t\"Sort by title\": \"Sortiraj po naslovu\",\r\n\t\"Title\": \"Naslov\",\r\n\t\"Sort by time\": \"Sortiraj po vremenu\",\r\n\t\"Time\": \"Vrijeme\",\r\n\t\"Export history\": \"Izvezi povijest\",\r\n\t\"Import history\": \"Uvezi povijest\",\r\n\t\"Clear history\": \"Očisti povijest\",\r\n\t\"Refresh history\": \"Osvježi povijest\",\r\n\t\"No history\": \"Nema povijesti\",\r\n\t\"Import from browser\": \"Uvezi iz preglednika\",\r\n\t\"Releases\": \"Izdanja\",\r\n\t\"Are you sure?\": \"Jeste li sigurni?\",\r\n\t\"Cancel\": \"Odustani\",\r\n\t\"Yes, do it!\": \"Da, učini to!\",\r\n\t\"Choose method\": \"Izaberi metodu\",\r\n\t\"Sign in via %s\": \"Prijavi se pomoću %s\",\r\n\t\"New\": \"Novo\",\r\n\t\"Publish\": \"Objavi\",\r\n\t\"Extra\": \"Dodatno\",\r\n\t\"Revision\": \"Revizija\",\r\n\t\"Slide Mode\": \"Način slajda\",\r\n\t\"Export\": \"Izvoz\",\r\n\t\"Import\": \"Uvoz\",\r\n\t\"Clipboard\": \"Međuspremnik\",\r\n\t\"Download\": \"Preuzimanje\",\r\n\t\"Raw HTML\": \"Raw HTML\",\r\n\t\"Edit\": \"Uredi\",\r\n\t\"View\": \"Pregledaj\",\r\n\t\"Both\": \"Oboje\",\r\n\t\"Help\": \"Pomoć\",\r\n\t\"Upload Image\": \"Prenesi sliku\",\r\n\t\"Menu\": \"Meni\",\r\n\t\"This page need refresh\": \"Ovu stranicu je potrebno osvježiti\",\r\n\t\"You have an incompatible client version.\": \"Imate nekompatibilnu verziju klijenta.\",\r\n\t\"Refresh to update.\": \"Osvježite za ažuriranje.\",\r\n\t\"New version available!\": \"Nova verzija dostupna!\",\r\n\t\"See releases notes here\": \"Pogledajte bilješke izdanja ovdje\",\r\n\t\"Refresh to enjoy new features.\": \"Osvježi za nove značajke.\",\r\n\t\"Your user state has changed.\": \"Stanje Vašeg korisnika se promijenilo.\",\r\n\t\"Refresh to load new user state.\": \"Osvježi za učitavanje novog stanja korisnika.\",\r\n\t\"Refresh\": \"Osvježi\",\r\n\t\"Contacts\": \"Kontakti\",\r\n\t\"Report an issue\": \"Prijavi problem\",\r\n\t\"Send us email\": \"Pošalji nam email\",\r\n\t\"Documents\": \"Dokumenti\",\r\n\t\"Features\": \"Značajke\",\r\n\t\"YAML Metadata\": \"YAML Metadata\",\r\n\t\"Slide Example\": \"Primjer slajda\",\r\n\t\"Cheatsheet\": \"Cheatsheet\",\r\n\t\"Example\": \"Primjer\",\r\n\t\"Syntax\": \"Sintaksa\",\r\n\t\"Header\": \"Zaglavlje\",\r\n\t\"Unordered List\": \"Neuređeni popis\",\r\n\t\"Ordered List\": \"Uređeni popis\",\r\n\t\"Todo List\": \"Popis obaveza\",\r\n\t\"Blockquote\": \"Blockquote\",\r\n\t\"Bold font\": \"Bold font\",\r\n\t\"Italics font\": \"Kurzivan font\",\r\n\t\"Strikethrough\": \"Precrtano\",\r\n\t\"Inserted text\": \"Umetnuti tekst\",\r\n\t\"Marked text\": \"Označeni tekst\",\r\n\t\"Link\": \"Link\",\r\n\t\"Image\": \"Slika\",\r\n\t\"Code\": \"Kod\",\r\n\t\"Externals\": \"Vanjski izgled\",\r\n\t\"This is a alert area.\": \"Ovo je područje upozorenja.\",\r\n\t\"Revert\": \"Vrati\",\r\n\t\"Import from clipboard\": \"Uvezi iz međuspremnika\",\r\n\t\"Paste your markdown or webpage here...\": \"Zalijepi svoj markdown ili web stranicu ovdje...\",\r\n\t\"Clear\": \"Očisti\",\r\n\t\"This note is locked\": \"Ova bilješka je zaključana\",\r\n\t\"Sorry, only owner can edit this note.\": \"Žao nam je, samo vlasnik ove bilješke ju može uređivati.\",\r\n\t\"OK\": \"OK\",\r\n\t\"Reach the limit\": \"Dosegni granicu\",\r\n\t\"Sorry, you've reached the max length this note can be.\": \"Žao nam je, dosegli ste maksimalnu moguću duljinu ove bilješke.\",\r\n\t\"Please reduce the content or divide it to more notes, thank you!\": \"Molimo Vas smanjite sardžaj ili ga podijelite na više bilješki, hvala!\",\r\n\t\"Import from Gist\": \"Uvezi iz Gist-a\",\r\n\t\"Paste your gist url here...\": \"Zalijepi svoj gist url ovdje...\",\r\n\t\"Import from Snippet\": \"Uvezi iz isječka\",\r\n\t\"Select From Available Projects\": \"Odaberi iz raspoloživih projekta\",\r\n\t\"Select From Available Snippets\": \"Odaberi iz raspoloživih isječaka\",\r\n\t\"OR\": \"ILI\",\r\n\t\"Export to Snippet\": \"Izvoz u isječak\",\r\n\t\"Select Visibility Level\": \"Odaberi razinu vidljivosti\"\r\n}"
  },
  {
    "path": "locales/id.json",
    "content": "{\n    \"Collaborative markdown notes\": \"Catatan markdown kolaboratif\",\n    \"Realtime collaborative markdown notes on all platforms.\": \"Berkolaborasi di catatan markdown di semua platform secara realtime\",\n    \"Best way to write and share your knowledge in markdown.\": \"Platform terbaik untuk menulis dan membagikan markdown\",\n    \"Intro\": \"Perkenalan\",\n    \"History\": \"Riwayat\",\n    \"New guest note\": \"Catatan baru (sebagai tamu)\",\n    \"Collaborate with URL\": \"Kolaborasi real-time\",\n    \"Support charts and MathJax\": \"Mendukung charts dan MathJax\",\n    \"Support slide mode\": \"Mendukung mode slide\",\n    \"Sign In\": \"Masuk\",\n    \"Below is the history from browser\": \"Dibawah ini adalah riwayat dari peramban ini\",\n    \"Welcome!\": \"Selamat Datang\",\n    \"New note\": \"Catatan Baru\",\n    \"or\": \"atau\",\n    \"Sign Out\": \"Keluar\",\n    \"Explore all features\": \"Jelajahi semua fitur\",\n    \"Select tags...\": \"Pilih tanda...\",\n    \"Search keyword...\": \"Cari berdasarkan kata kunci...\",\n    \"Sort by title\": \"Urutkan berdasarkan judul\",\n    \"Title\": \"Judul\",\n    \"Sort by time\": \"Urutkan berdasarkan waktu\",\n    \"Time\": \"Waktu\",\n    \"Export history\": \"Ekspor Riwayat\",\n    \"Import history\": \"Impor Riwayat\",\n    \"Clear history\": \"Bersihkan Riwayat\",\n    \"Refresh history\": \"Muat-ulang Riwayat\",\n    \"No history\": \"Tidak ada riwayat\",\n    \"Import from browser\": \"Impor dari browser\",\n    \"Releases\": \"Penerbitan\",\n    \"Are you sure?\": \"Apakah anda yakin?\",\n    \"Do you really want to delete this note?\": \"Apakah anda yakin ingin menghapus catatan ini?\",\n    \"All users will lose their connection.\": \"Semua pengguna akan kehilangan koneksi nya\",\n    \"Cancel\": \"Batal\",\n    \"Yes, do it!\": \"Ya, lakukan!\",\n    \"Choose method\": \"Pilih cara\",\n    \"Sign in via %s\": \"Masuk menggunakan %s\",\n    \"New\": \"Baru\",\n    \"Publish\": \"Terbitkan\",\n    \"Extra\": \"Tambahan\",\n    \"Revision\": \"Revisi\",\n    \"Slide Mode\": \"Mode Slide\",\n    \"Export\": \"Ekspor\",\n    \"Import\": \"Impor\",\n    \"Clipboard\": \"Papan Klip\",\n    \"Download\": \"Unduh\",\n    \"Raw HTML\": \"File HTML\",\n    \"Edit\": \"Ubah\",\n    \"View\": \"Lihat\",\n    \"Both\": \"Keduanya\",\n    \"Help\": \"Bantuan\",\n    \"Upload Image\": \"Unggah Gambar\",\n    \"Menu\": \"Menu\",\n    \"This page need refresh\": \"Halaman ini perlu dimuat ulang\",\n    \"You have an incompatible client version.\": \"Versi pramban anda tidak kompatibel\",\n    \"Refresh to update.\": \"Muat ulang untuk memperbarui\",\n    \"New version available!\": \"Versi baru tersedia!\",\n    \"See releases notes here\": \"Lihat catatan penerbitan\",\n    \"Refresh to enjoy new features.\": \"Muat ulang untuk menikmati fitur baru.\",\n    \"Your user state has changed.\": \"Data pengguna anda telah berubah.\",\n    \"Refresh to load new user state.\": \"Muat ulang untuk memuat data baru pengguna.\",\n    \"Refresh\": \"Muat ulang\",\n    \"Contacts\": \"Kontak\",\n    \"Report an issue\": \"Laporkan kesalahan\",\n    \"Meet us on %s\": \"Temui kami di %s\",\n    \"Send us email\": \"Kirim kami email\",\n    \"Documents\": \"Dokumen\",\n    \"Features\": \"Fitur\",\n    \"YAML Metadata\": \"Metadata YML\",\n    \"Slide Example\": \"Contoh Slide\",\n    \"Cheatsheet\": \"Cheatsheet\",\n    \"Example\": \"Contoh\",\n    \"Syntax\": \"Sintaks\",\n    \"Header\": \"Header\",\n    \"Unordered List\": \"Daftar tak ber-urutan\",\n    \"Ordered List\": \"Daftar ber-urutan\",\n    \"Todo List\": \"Centang\",\n    \"Blockquote\": \"Blok kutipan\",\n    \"Bold font\": \"Tebal\",\n    \"Italics font\": \"Miring\",\n    \"Strikethrough\": \"Garis\",\n    \"Inserted text\": \"Teks ber-garis bawah\",\n    \"Marked text\": \"Teks yang disorot\",\n    \"Link\": \"Link\",\n    \"Image\": \"Gambar\",\n    \"Code\": \"Kode\",\n    \"Externals\": \"Eksternal\",\n    \"This is a alert area.\": \"Ini adalah area alert.\",\n    \"Revert\": \"Kembalikan\",\n    \"Import from clipboard\": \"Impor dari papan klip\",\n    \"Paste your markdown or webpage here...\": \"Tempel markdown atau halaman web disini\",\n    \"Clear\": \"Bersihkan\",\n    \"This note is locked\": \"Catatan ini terkunci\",\n    \"Sorry, only owner can edit this note.\": \"Maaf, hanya pemilik yang bisa mengubah catatan ini\",\n    \"OK\": \"OK\",\n    \"Reach the limit\": \"Memenuhi batas\",\n    \"Sorry, you've reached the max length this note can be.\": \"Maaf, anda telah memenuhi batas maksimum jumlah catatan ini\",\n    \"Please reduce the content or divide it to more notes, thank you!\": \"Tolong persingkat catatan nya.\",\n    \"Import from Gist\": \"Impor dari Gist\",\n    \"Paste your gist url here...\": \"Templekan URL gist anda disini...\",\n    \"Import from Snippet\": \"Impor dari Snippet\",\n    \"Select From Available Projects\": \"Pilih dari Project yang tersedia\",\n    \"Select From Available Snippets\": \"Pilih dari Snippet yang tersedia\",\n    \"OR\": \"Atau\",\n    \"Export to Snippet\": \"Ekspor ke Snippet\",\n    \"Select Visibility Level\": \"Pilih tingkat penglihatan\",\n    \"Night Theme\": \"Mode Malam\",\n    \"Follow us on %s and %s.\": \"Ikuti kami di %s, dan %s.\",\n    \"Privacy\": \"Privasi\",\n    \"Terms of Use\": \"Aturan Penggunaan\",\n    \"Do you really want to delete your user account?\": \"Apakah anda yakin ingin menghapus akun anda?\",\n    \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"Ini akan menghapus akun anda, semua catatan yang dimiliki oleh anda akan dihapus dan menghapus semua referensi ke akun anda dari catatan lain.\",\n    \"Delete user\": \"Hapus pengguna\",\n    \"Export user data\": \"Ekspor data pengguna\",\n    \"Help us translating on %s\": \"Bantu kami menerjemahkan di %s\",\n    \"Source Code\": \"Sumber Kode\",\n    \"Register\": \"Daftar\",\n    \"Powered by %s\": \"Ditenagai oleh %s\"\n}"
  },
  {
    "path": "locales/it.json",
    "content": "{\n    \"Collaborative markdown notes\": \"Note collaborative in markdown\",\n    \"Realtime collaborative markdown notes on all platforms.\": \"Note markdown collaborative in tempo reale per tutte le piattaforme.\",\n    \"Best way to write and share your knowledge in markdown.\": \"Miglior modo per scrivere e condividere le tue conoscenze in markdown.\",\n    \"Intro\": \"Intro\",\n    \"History\": \"Cronologia\",\n    \"New guest note\": \"Nuova nota ospite\",\n    \"Collaborate with URL\": \"Collabora tramite URL\",\n    \"Support charts and MathJax\": \"Supporta grafici e MathJax\",\n    \"Support slide mode\": \"Supporta modalità slide\",\n    \"Sign In\": \"Registrati\",\n    \"Below is the history from browser\": \"Qui sotto c'è la cronologia del browser\",\n    \"Welcome!\": \"Benvenuto!\",\n    \"New note\": \"Nuova nota\",\n    \"or\": \"o\",\n    \"Sign Out\": \"Disconettiti\",\n    \"Explore all features\": \"Esplora tutte le funzioni\",\n    \"Select tags...\": \"Seleziona tag...\",\n    \"Search keyword...\": \"Cerca...\",\n    \"Sort by title\": \"Ordina per titolo\",\n    \"Title\": \"Titolo\",\n    \"Sort by time\": \"Ordina per data\",\n    \"Time\": \"Data\",\n    \"Export history\": \"Esporta cronologia\",\n    \"Import history\": \"Importa cronologia\",\n    \"Clear history\": \"Cancella cronologia\",\n    \"Refresh history\": \"Aggiorna cronologia\",\n    \"No history\": \"Nessuna cronologia\",\n    \"Import from browser\": \"Importa da browser\",\n    \"Releases\": \"Versioni\",\n    \"Are you sure?\": \"Sei sicuro?\",\n    \"Do you really want to delete this note?\": \"Vuoi veramente eliminare questa nota?\",\n    \"All users will lose their connection.\": \"Tutti gli utenti perderanno la loro connessione.\",\n    \"Cancel\": \"Annulla\",\n    \"Yes, do it!\": \"SI, fallo!\",\n    \"Choose method\": \"Scegli metodo\",\n    \"Sign in via %s\": \"Registrati con %s\",\n    \"New\": \"Nuovo\",\n    \"Publish\": \"Pubblica\",\n    \"Extra\": \"Extra\",\n    \"Revision\": \"Revisione\",\n    \"Slide Mode\": \"Modalità slide\",\n    \"Export\": \"Esporta\",\n    \"Import\": \"Importa\",\n    \"Clipboard\": \"Appunti\",\n    \"Download\": \"Scarica\",\n    \"Raw HTML\": \"Raw HTML\",\n    \"Edit\": \"Modifica\",\n    \"View\": \"Visualizza\",\n    \"Both\": \"Entrambi\",\n    \"Help\": \"Aiuto\",\n    \"Upload Image\": \"Carica Immagine\",\n    \"Menu\": \"Menu\",\n    \"This page need refresh\": \"Questa pagina deve essere aggiornata\",\n    \"You have an incompatible client version.\": \"La versione del tuo client è incompatibile.\",\n    \"Refresh to update.\": \"Ricarica per aggiornare.\",\n    \"New version available!\": \"Nuova versione disponibile!\",\n    \"See releases notes here\": \"Vedi note di rilascio qui\",\n    \"Refresh to enjoy new features.\": \"Ricarica per godere delle nuove funzioni.\",\n    \"Your user state has changed.\": \"Il tuo stato utente è cambiato.\",\n    \"Refresh to load new user state.\": \"Aggiorna per caricare il nuovo stato utente.\",\n    \"Refresh\": \"Ricarica\",\n    \"Contacts\": \"Contatti\",\n    \"Report an issue\": \"Segnala un problema\",\n    \"Meet us on %s\": \"Vieni a trovarci su %s\",\n    \"Send us email\": \"Inviaci una email\",\n    \"Documents\": \"Documenti\",\n    \"Features\": \"Caratteristiche\",\n    \"YAML Metadata\": \"YAML Metadata\",\n    \"Slide Example\": \"Esempio Slide\",\n    \"Cheatsheet\": \"Cheatsheet\",\n    \"Example\": \"Esempio\",\n    \"Syntax\": \"Sintassi\",\n    \"Header\": \"Intestazione\",\n    \"Unordered List\": \"Lista non ordinata\",\n    \"Ordered List\": \"Lista ordinata\",\n    \"Todo List\": \"Elenco\",\n    \"Blockquote\": \"Citazione\",\n    \"Bold font\": \"Grassetto\",\n    \"Italics font\": \"Corsivo\",\n    \"Strikethrough\": \"Barrato\",\n    \"Inserted text\": \"Sottolineato\",\n    \"Marked text\": \"Evidenziato\",\n    \"Link\": \"Link\",\n    \"Image\": \"Immagine\",\n    \"Code\": \"Codice\",\n    \"Externals\": \"Esterni\",\n    \"This is a alert area.\": \"Questa è un area di avviso.\",\n    \"Revert\": \"Annulla\",\n    \"Import from clipboard\": \"Importa dagli appunti\",\n    \"Paste your markdown or webpage here...\": \"Incollare il markdown o una pagina web qui...\",\n    \"Clear\": \"Pulisci\",\n    \"This note is locked\": \"Questa nota è bloccata\",\n    \"Sorry, only owner can edit this note.\": \"Siamo spiacenti, solo il proprietario può modificare questa nota.\",\n    \"OK\": \"OK\",\n    \"Reach the limit\": \"Limite raggiunto\",\n    \"Sorry, you've reached the max length this note can be.\": \"Siamo spiacenti, hai raggiunto la lunghezza massima per questa nota.\",\n    \"Please reduce the content or divide it to more notes, thank you!\": \"Si prega di ridurre il contenuto o dividerlo in più note, grazie!\",\n    \"Import from Gist\": \"Importa da Gist\",\n    \"Paste your gist url here...\": \"Incolla il tuo link gist qui...\",\n    \"Import from Snippet\": \"Importa da Snippet\",\n    \"Select From Available Projects\": \"Seleziona da progetti disponibili\",\n    \"Select From Available Snippets\": \"Seleziona da snippets disponibili\",\n    \"OR\": \"O\",\n    \"Export to Snippet\": \"Esporta Snippet\",\n    \"Select Visibility Level\": \"Seleziona livello visibilità\",\n    \"Night Theme\": \"Tema Scuro\",\n    \"Follow us on %s and %s.\": \"Seguici su %s, e %s.\",\n    \"Privacy\": \"Privacy\",\n    \"Terms of Use\": \"Termini di Utilizzo\",\n    \"Do you really want to delete your user account?\": \"Vuoi veramente cancellare il tuo account utente?\",\n    \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"Questo cancellerà il tuo account, tutte le note di cui sei proprietario e rimuoverà i riferimenti al tuo account dalle altre note.\",\n    \"Delete user\": \"Elimina utente\",\n    \"Export user data\": \"Esporta dati utente\",\n    \"Help us translating on %s\": \"Aiutaci nella traduzione su %s\",\n    \"Source Code\": \"Codice Sorgente\",\n    \"Register\": \"Registrati\",\n    \"Powered by %s\": \"Alimentato da %s\"\n}"
  },
  {
    "path": "locales/ja.json",
    "content": "{\n    \"Collaborative markdown notes\": \"共同編集できるMarkdownノート\",\n    \"Realtime collaborative markdown notes on all platforms.\": \"マルチプラットフォーム、リアルタイムで共同編集できるMarkdownノート\",\n    \"Best way to write and share your knowledge in markdown.\": \"Markdownでナレッジを蓄積・共有できるベストツール\",\n    \"Intro\": \"サービスの紹介\",\n    \"History\": \"履歴\",\n    \"New guest note\": \"新規ゲストノート\",\n    \"Collaborate with URL\": \"URLで共同編集\",\n    \"Support charts and MathJax\": \"グラフとMathJaxのサポート\",\n    \"Support slide mode\": \"スライドモードのサポート\",\n    \"Sign In\": \"サインイン\",\n    \"Below is the history from browser\": \"ブラウザからの履歴\",\n    \"Welcome!\": \"ようこそ！\",\n    \"New note\": \"新規ノート\",\n    \"or\": \"または\",\n    \"Sign Out\": \"サインアウト\",\n    \"Explore all features\": \"すべての機能をチェック\",\n    \"Select tags...\": \"タグで検索\",\n    \"Search keyword...\": \"キーワードで検索\",\n    \"Sort by title\": \"タイトル順でソート\",\n    \"Title\": \"タイトル\",\n    \"Sort by time\": \"日時順でソート\",\n    \"Time\": \"日時\",\n    \"Export history\": \"履歴をエクスポート\",\n    \"Import history\": \"履歴をインポート\",\n    \"Clear history\": \"履歴をクリア\",\n    \"Refresh history\": \"履歴を更新\",\n    \"No history\": \"履歴はありません\",\n    \"Import from browser\": \"ブラウザからインポート\",\n    \"Releases\": \"リリース\",\n    \"Are you sure?\": \"本当にいいですか？\",\n    \"Do you really want to delete this note?\": \"本当にこのノートを削除しますか？\",\n    \"All users will lose their connection.\": \"すべてのユーザーの接続が切断されます。\",\n    \"Cancel\": \"キャンセル\",\n    \"Yes, do it!\": \"はい\",\n    \"Choose method\": \"選択してください\",\n    \"Sign in via %s\": \"%sでサインイン\",\n    \"New\": \"新規作成\",\n    \"Publish\": \"公開する\",\n    \"Extra\": \"その他\",\n    \"Revision\": \"編集履歴\",\n    \"Slide Mode\": \"スライドモード\",\n    \"Export\": \"エクスポート\",\n    \"Import\": \"インポート\",\n    \"Clipboard\": \"クリップボード\",\n    \"Download\": \"ダウンロード\",\n    \"Raw HTML\": \"HTMLパーツ\",\n    \"Edit\": \"編集モード\",\n    \"View\": \"表示モード\",\n    \"Both\": \"分割モード\",\n    \"Help\": \"ヘルプ\",\n    \"Upload Image\": \"画像をアップロード\",\n    \"Menu\": \"メニュー\",\n    \"This page need refresh\": \"ページをリロードしてください\",\n    \"You have an incompatible client version.\": \"クライアントのバージョンが一致しません\",\n    \"Refresh to update.\": \"リロードして更新を反映させてください\",\n    \"New version available!\": \"新しいバージョンが利用できます！\",\n    \"See releases notes here\": \"リリースノートをご覧ください\",\n    \"Refresh to enjoy new features.\": \"リロードして新しい機能を試してみましょう\",\n    \"Your user state has changed.\": \"ユーザー情報が変更されました\",\n    \"Refresh to load new user state.\": \"リロードすると最新のユーザー情報が反映されます\",\n    \"Refresh\": \"リロード\",\n    \"Contacts\": \"コンタクト\",\n    \"Report an issue\": \"問題を報告する\",\n    \"Meet us on %s\": \"%sでチャットする\",\n    \"Send us email\": \"メールを送る\",\n    \"Documents\": \"ドキュメント\",\n    \"Features\": \"機能\",\n    \"YAML Metadata\": \"YAMLメタデータ\",\n    \"Slide Example\": \"スライドサンプル\",\n    \"Cheatsheet\": \"チートシート\",\n    \"Example\": \"例\",\n    \"Syntax\": \"構文\",\n    \"Header\": \"見出し\",\n    \"Unordered List\": \"番号なしリスト\",\n    \"Ordered List\": \"番号付きリスト\",\n    \"Todo List\": \"TODOリスト\",\n    \"Blockquote\": \"引用文\",\n    \"Bold font\": \"太字\",\n    \"Italics font\": \"斜体\",\n    \"Strikethrough\": \"打ち消し線\",\n    \"Inserted text\": \"挿入文\",\n    \"Marked text\": \"マーカー\",\n    \"Link\": \"リンク\",\n    \"Image\": \"画像\",\n    \"Code\": \"コード\",\n    \"Externals\": \"モジュール\",\n    \"This is a alert area.\": \"これはアラートエリアです\",\n    \"Revert\": \"戻す\",\n    \"Import from clipboard\": \"クリップボードからインポート\",\n    \"Paste your markdown or webpage here...\": \"Markdownまたはウェブページを貼り付けてください\",\n    \"Clear\": \"クリア\",\n    \"This note is locked\": \"このノートはロックされています\",\n    \"Sorry, only owner can edit this note.\": \"このノートはオーナーのみが編集できます\",\n    \"OK\": \"OK\",\n    \"Reach the limit\": \"上限に達しました\",\n    \"Sorry, you've reached the max length this note can be.\": \"ノートの文字数が上限に達しました。\",\n    \"Please reduce the content or divide it to more notes, thank you!\": \"内容を減らすか、別のノートに分けてください\",\n    \"Import from Gist\": \"gistからインポート\",\n    \"Paste your gist url here...\": \"gistのURLを貼り付けてください\",\n    \"Import from Snippet\": \"スニペットからインポート\",\n    \"Select From Available Projects\": \"プロジェクトを一覧から選択してください\",\n    \"Select From Available Snippets\": \"スニペットを一覧から選択してください\",\n    \"OR\": \"または\",\n    \"Export to Snippet\": \"スニペットにエクスポート\",\n    \"Select Visibility Level\": \"公開範囲を選んでください\",\n    \"Night Theme\": \"ナイトテーマ\",\n    \"Follow us on %s and %s.\": \"%s と %s でフォローしてください。\",\n    \"Privacy\": \"プライバシー\",\n    \"Terms of Use\": \"利用条件\",\n    \"Do you really want to delete your user account?\": \"本当にアカウントを削除しますか？\",\n    \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"この操作はあなたのアカウントとあなたの所有するすべてのノートを削除し、さらに他の人のノートからあなたのアカウントへの参照を除去します。\",\n    \"Delete user\": \"ユーザーの削除\",\n    \"Export user data\": \"ユーザーデータをエクスポート\",\n    \"Help us translating on %s\": \"%s の翻訳にご協力ください\",\n    \"Source Code\": \"ソースコード\",\n    \"Register\": \"登録\",\n    \"Powered by %s\": \"Powered by %s\"\n}\n"
  },
  {
    "path": "locales/ko.json",
    "content": "{\n    \"Collaborative markdown notes\": \"협동 마크다운 노트\",\n    \"Realtime collaborative markdown notes on all platforms.\": \"실시간으로 모든 플랫폼에서 마크다운 노트를 함께 작성해보세요.\",\n    \"Best way to write and share your knowledge in markdown.\": \"마크다운을 쓰고 공유하는 최고의 플랫폼입니다.\",\n    \"Intro\": \"소개\",\n    \"History\": \"기록\",\n    \"New guest note\": \"새 손님 노트\",\n    \"Collaborate with URL\": \"URL을 통한 실시간 협업\",\n    \"Support charts and MathJax\": \"차트와 MathJax 지원\",\n    \"Support slide mode\": \"슬라이드 모드 지원\",\n    \"Sign In\": \"로그인\",\n    \"Below is the history from browser\": \"아래는 이 브라우저에서 찾은 기록입니다.\",\n    \"Welcome!\": \"환영합니다!\",\n    \"New note\": \"새 노트\",\n    \"or\": \"또는\",\n    \"Sign Out\": \"로그아웃\",\n    \"Explore all features\": \"모든 기능 둘러보기\",\n    \"Select tags...\": \"태그 선택하기\",\n    \"Search keyword...\": \"키워드 검색하기\",\n    \"Sort by title\": \"제목 기준 정렬\",\n    \"Title\": \"제목\",\n    \"Sort by time\": \"시간 기준 정렬\",\n    \"Time\": \"시간\",\n    \"Export history\": \"기록 내보내기\",\n    \"Import history\": \"기록 불러오기\",\n    \"Clear history\": \"기록 초기화\",\n    \"Refresh history\": \"기록 새로고침\",\n    \"No history\": \"기록 없음\",\n    \"Import from browser\": \"브라우저에서 불러오기\",\n    \"Releases\": \"릴리즈\",\n    \"Are you sure?\": \"확실합니까?\",\n    \"Do you really want to delete this note?\": \"정말로 이 노트를 삭제하시겠습니까?\",\n    \"All users will lose their connection.\": \"모든 사용자의 연결이 끊어집니다.\",\n    \"Cancel\": \"취소\",\n    \"Yes, do it!\": \"네\",\n    \"Choose method\": \"방법 선택\",\n    \"Sign in via %s\": \"%s으로 로그인\",\n    \"New\": \"새\",\n    \"Publish\": \"공개하기\",\n    \"Extra\": \"추가\",\n    \"Revision\": \"기록\",\n    \"Slide Mode\": \"슬라이드 모드\",\n    \"Export\": \"내보내기\",\n    \"Import\": \"들여오기\",\n    \"Clipboard\": \"클립보드\",\n    \"Download\": \"다운로드\",\n    \"Raw HTML\": \"순수 HTML\",\n    \"Edit\": \"수정\",\n    \"View\": \"보기\",\n    \"Both\": \"한번에\",\n    \"Help\": \"도움말\",\n    \"Upload Image\": \"이미지 업로드\",\n    \"Menu\": \"메뉴\",\n    \"This page need refresh\": \"새로고침이 필요합니다\",\n    \"You have an incompatible client version.\": \"호환되지 않는 클라이언트입니다.\",\n    \"Refresh to update.\": \"새로고침하기\",\n    \"New version available!\": \"새로운 버전이 있습니다!\",\n    \"See releases notes here\": \"릴리즈 노트를 읽어보세요\",\n    \"Refresh to enjoy new features.\": \"새로운 기능을 즐기려면 새로고침하십시오\",\n    \"Your user state has changed.\": \"유저 상태가 변경되었습니다.\",\n    \"Refresh to load new user state.\": \"새로고침하여 새로운 유저 상태를 적용합니다.\",\n    \"Refresh\": \"새로고침\",\n    \"Contacts\": \"연락처\",\n    \"Report an issue\": \"이슈 보고하기\",\n    \"Meet us on %s\": \"%s에서 만나보세요\",\n    \"Send us email\": \"이메일 보내기\",\n    \"Documents\": \"문서\",\n    \"Features\": \"기능\",\n    \"YAML Metadata\": \"YAML 속성\",\n    \"Slide Example\": \"슬라이드 예제\",\n    \"Cheatsheet\": \"치트시트\",\n    \"Example\": \"예시\",\n    \"Syntax\": \"문법\",\n    \"Header\": \"머리글\",\n    \"Unordered List\": \"순서 없는 목록\",\n    \"Ordered List\": \"순서 있는 목록\",\n    \"Todo List\": \"체크리스트\",\n    \"Blockquote\": \"인용문\",\n    \"Bold font\": \"굵게\",\n    \"Italics font\": \"기울임\",\n    \"Strikethrough\": \"취소선\",\n    \"Inserted text\": \"밑줄\",\n    \"Marked text\": \"강조\",\n    \"Link\": \"링크\",\n    \"Image\": \"이미지\",\n    \"Code\": \"코드\",\n    \"Externals\": \"외부 서비스 연동\",\n    \"This is a alert area.\": \"여기는 알림 공간입니다.\",\n    \"Revert\": \"되돌리기\",\n    \"Import from clipboard\": \"클립보드에서 불러오기\",\n    \"Paste your markdown or webpage here...\": \"마크다운이나 웹페이지 붙여넣기\",\n    \"Clear\": \"Clear\",\n    \"This note is locked\": \"이 노트는 잠겨있습니다.\",\n    \"Sorry, only owner can edit this note.\": \"죄송하지만 소유자만 이 노트를 수정할 수 있습니다.\",\n    \"OK\": \"확인\",\n    \"Reach the limit\": \"한계에 도달\",\n    \"Sorry, you've reached the max length this note can be.\": \"죄송합니다. 노트 최대 길이를 초과하였습니다.\",\n    \"Please reduce the content or divide it to more notes, thank you!\": \"노트 길이를 줄여주십시오.\",\n    \"Import from Gist\": \"Gist에서 불러오기\",\n    \"Paste your gist url here...\": \"Gist URL을 입력하세요\",\n    \"Import from Snippet\": \"Import from Snippet\",\n    \"Select From Available Projects\": \"가능한 프로젝트 중 선택\",\n    \"Select From Available Snippets\": \"Select From Available Snippets\",\n    \"OR\": \"또는\",\n    \"Export to Snippet\": \"Export to Snippet\",\n    \"Select Visibility Level\": \"Select Visibility Level\",\n    \"Night Theme\": \"다크 테마\",\n    \"Follow us on %s and %s.\": \"%s과 %s에서 저희를 팔로우해보세요\",\n    \"Privacy\": \"Privacy\",\n    \"Terms of Use\": \"Terms of Use\",\n    \"Do you really want to delete your user account?\": \"Do you really want to delete your user account?\",\n    \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\",\n    \"Delete user\": \"Delete user\",\n    \"Export user data\": \"Export user data\",\n    \"Help us translating on %s\": \"%s에서 번역으로 저희를 도와주세요\",\n    \"Source Code\": \"Source Code\"\n}"
  },
  {
    "path": "locales/nl.json",
    "content": "{\n    \"Collaborative markdown notes\": \"Samenwerkende markdown notities\",\n    \"Realtime collaborative markdown notes on all platforms.\": \"Realtime samenwerkende markdown notities.\",\n    \"Best way to write and share your knowledge in markdown.\": \"De beste manier je kennis te delen en schrijven in markdown.\",\n    \"Intro\": \"Introductie\",\n    \"History\": \"Geschiedenis\",\n    \"New guest note\": \"Nieuwe gastnotitie\",\n    \"Collaborate with URL\": \"Samenwerken met URL\",\n    \"Support charts and MathJax\": \"Ondersteunt grafieken en MathJax\",\n    \"Support slide mode\": \"Ondersteunt presentatiemodus\",\n    \"Sign In\": \"Inloggen\",\n    \"Below is the history from browser\": \"Hier onder staat de browser geschiedenis\",\n    \"Welcome!\": \"Welkom!\",\n    \"New note\": \"Nieuwe notitie\",\n    \"or\": \"of\",\n    \"Sign Out\": \"Uitloggen\",\n    \"Explore all features\": \"Ontdek alle features\",\n    \"Select tags...\": \"Selecteer tags...\",\n    \"Search keyword...\": \"Zoeken op keyword...\",\n    \"Sort by title\": \"Sorteren op titel\",\n    \"Title\": \"Titel\",\n    \"Sort by time\": \"Sorteren op tijd\",\n    \"Time\": \"Tijd\",\n    \"Export history\": \"Exporteer geschiedenis\",\n    \"Import history\": \"Importeer geschiedenis\",\n    \"Clear history\": \"Verwijder geschiedenis\",\n    \"Refresh history\": \"Ververs geschiedenis\",\n    \"No history\": \"Geen geschidenis gevonden\",\n    \"Import from browser\": \"Importeer van browser\",\n    \"Releases\": \"Releases\",\n    \"Are you sure?\": \"Weet je het zeker?\",\n    \"Do you really want to delete this note?\": \"Will je deze notitie echt verwijderen?\",\n    \"All users will lose their connection.\": \"Alle gebruikers zullen hun verbinding verliezen.\",\n    \"Cancel\": \"Stoppen\",\n    \"Yes, do it!\": \"Ja, doe het!\",\n    \"Choose method\": \"Kies methode\",\n    \"Sign in via %s\": \"Log in via %s\",\n    \"New\": \"Nieuw\",\n    \"Publish\": \"Publiceren\",\n    \"Extra\": \"Extra\",\n    \"Revision\": \"Versie\",\n    \"Slide Mode\": \"Presentatiemodus\",\n    \"Export\": \"Exporteren\",\n    \"Import\": \"Importeren\",\n    \"Clipboard\": \"Kladbord\",\n    \"Download\": \"Downloaden\",\n    \"Raw HTML\": \"Ruwe HTML\",\n    \"Edit\": \"Aanpassen\",\n    \"View\": \"Bekijken\",\n    \"Both\": \"Beide\",\n    \"Help\": \"Help\",\n    \"Upload Image\": \"Afbeelding uploaden\",\n    \"Menu\": \"Menu\",\n    \"This page need refresh\": \"Deze pagina moet vernieuwd worden\",\n    \"You have an incompatible client version.\": \"Je client is niet compatibel.\",\n    \"Refresh to update.\": \"Ververs om te updaten.\",\n    \"New version available!\": \"Nieuwe versie beschikbaar!\",\n    \"See releases notes here\": \"Bekijk de release notes hier\",\n    \"Refresh to enjoy new features.\": \"Ververs om de nieuwe features te zien.\",\n    \"Your user state has changed.\": \"Je gebruikers-status is veranderd.\",\n    \"Refresh to load new user state.\": \"Ververs om je nieuwe gebruikers-status te zien.\",\n    \"Refresh\": \"Ververs\",\n    \"Contacts\": \"Contacten\",\n    \"Report an issue\": \"Probleem rapporteren\",\n    \"Meet us on %s\": \"Ontmoet ons op %s\",\n    \"Send us email\": \"Stuur ons een mail\",\n    \"Documents\": \"Documenten\",\n    \"Features\": \"Features\",\n    \"YAML Metadata\": \"YAML Metadata\",\n    \"Slide Example\": \"Slide Voorbeeld\",\n    \"Cheatsheet\": \"Spiekbrief\",\n    \"Example\": \"Voorbeeld\",\n    \"Syntax\": \"Syntax\",\n    \"Header\": \"Koptekst\",\n    \"Unordered List\": \"Niet gesorteerde Lijst\",\n    \"Ordered List\": \"Gesorteerde List\",\n    \"Todo List\": \"Todo Lijst\",\n    \"Blockquote\": \"Citaat\",\n    \"Bold font\": \"Bold tekst\",\n    \"Italics font\": \"Italics tekst\",\n    \"Strikethrough\": \"Doorstreepte tekst\",\n    \"Inserted text\": \"Bijgevoegde tekst\",\n    \"Marked text\": \"Gemarkeerde tekst\",\n    \"Link\": \"Link\",\n    \"Image\": \"Afbeelding\",\n    \"Code\": \"Code\",\n    \"Externals\": \"Uiterlijkheden\",\n    \"This is a alert area.\": \"Dit is een waarschuwingsgebied.\",\n    \"Revert\": \"Terugzetten\",\n    \"Import from clipboard\": \"Importeren from kladbord\",\n    \"Paste your markdown or webpage here...\": \"Plak je markdown of webpagina hier...\",\n    \"Clear\": \"Legen\",\n    \"This note is locked\": \"Deze notitie zit op slot\",\n    \"Sorry, only owner can edit this note.\": \"Sorry, alleen de eigenaar kan deze notitie aanpassen.\",\n    \"OK\": \"OK\",\n    \"Reach the limit\": \"Limiet bereikt\",\n    \"Sorry, you've reached the max length this note can be.\": \"Sorry, je notitie heeft de maximale lengte bereikt.\",\n    \"Please reduce the content or divide it to more notes, thank you!\": \"Verwijder alsjeblieft wat tekst of verdeel het over meerdere notities!\",\n    \"Import from Gist\": \"Importeren vanaf een Gist\",\n    \"Paste your gist url here...\": \"Plak je Gist URL hier...\",\n    \"Import from Snippet\": \"Imporeren vanaf een Snippet\",\n    \"Select From Available Projects\": \"Selecteer van beschikbare projecten\",\n    \"Select From Available Snippets\": \"Selecteer van beschikbare Snippets\",\n    \"OR\": \"OF\",\n    \"Export to Snippet\": \"Exporteren naar Snippet\",\n    \"Select Visibility Level\": \"Selecteer zichtbaarheids niveau\",\n    \"Night Theme\": \"Nachtweergave\",\n    \"Follow us on %s and %s.\": \"Volg ons op %s en %s.\",\n    \"Privacy\": \"Privacy\",\n    \"Terms of Use\": \"Gebruikersvoorwaarden\",\n    \"Do you really want to delete your user account?\": \"Weet je zeker dat je je account wilt verwijderen?\",\n    \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"Dit zal je account verwijderen. Alle notities waar je eigenaar van bent worden verwijderd, samen met alle verwijzingen naar je account.\",\n    \"Delete user\": \"Gebruiker verwijderen\",\n    \"Export user data\": \"Gebruikersdata exporteren\",\n    \"Help us translating on %s\": \"Help ons vertalen op %s\",\n    \"Source Code\": \"Broncode\",\n    \"Register\": \"Registreren\",\n    \"Powered by %s\": \"Powered by %s\"\n}"
  },
  {
    "path": "locales/pl.json",
    "content": "{\n    \"Collaborative markdown notes\": \"Wspólne markdown notatki\",\n    \"Realtime collaborative markdown notes on all platforms.\": \"Rzeczywiste wspólne markdown notatki dla wszystkich platform\",\n    \"Best way to write and share your knowledge in markdown.\": \"Najlepszy sposób na pisanie i dzielenie się swoją wiedzą w markdown.\",\n    \"Intro\": \"Intro\",\n    \"History\": \"Historia\",\n    \"New guest note\": \"Nowa notatka gościa\",\n    \"Collaborate with URL\": \"Kolaboracja w czasie rzeczywistym\",\n    \"Support charts and MathJax\": \"Kompatybilne z wykresami oraz MathJax\",\n    \"Support slide mode\": \"Obsługuje tryb slajdów\",\n    \"Sign In\": \"Zaloguj się\",\n    \"Below is the history from browser\": \"Historia z przeglądarki poniżej\",\n    \"Welcome!\": \"Witam!\",\n    \"New note\": \"Nowa notatka\",\n    \"or\": \"lub\",\n    \"Sign Out\": \"Wyloguj się\",\n    \"Explore all features\": \"Przeglądaj wszystkie funkcje\",\n    \"Select tags...\": \"Wybierz tagi...\",\n    \"Search keyword...\": \"Znajdź kluczowe słowo...\",\n    \"Sort by title\": \"Sortuj według tytułu\",\n    \"Title\": \"Tytuł\",\n    \"Sort by time\": \"Sortuj według czasu\",\n    \"Time\": \"Czas\",\n    \"Export history\": \"Eksportuj historię\",\n    \"Import history\": \"Importuj historię\",\n    \"Clear history\": \"Wyczyść historię\",\n    \"Refresh history\": \"Odśwież historię\",\n    \"No history\": \"Brak historii\",\n    \"Import from browser\": \"Importuj z przeglądarki\",\n    \"Releases\": \"Wydania\",\n    \"Are you sure?\": \"Jesteś pewny?\",\n    \"Do you really want to delete this note?\": \"Do you really want to delete this note?\",\n    \"All users will lose their connection.\": \"All users will lose their connection.\",\n    \"Cancel\": \"Anuluj\",\n    \"Yes, do it!\": \"Tak, zrób to!\",\n    \"Choose method\": \"Wybierz metodę\",\n    \"Sign in via %s\": \"Zaloguj się poprzez %s\",\n    \"New\": \"Nowy\",\n    \"Publish\": \"Publikuj\",\n    \"Extra\": \"Ekstra\",\n    \"Revision\": \"Korekta\",\n    \"Slide Mode\": \"Tryb slajdów\",\n    \"Export\": \"Eksport\",\n    \"Import\": \"Import\",\n    \"Clipboard\": \"Schowek\",\n    \"Download\": \"Pobierz\",\n    \"Raw HTML\": \"Raw HTML\",\n    \"Edit\": \"Edytuj\",\n    \"View\": \"Pogląd\",\n    \"Both\": \"Both\",\n    \"Help\": \"Pomoc\",\n    \"Upload Image\": \"Prześlij zdjęcie\",\n    \"Menu\": \"Menu\",\n    \"This page need refresh\": \"Strona wymaga odświeżenia\",\n    \"You have an incompatible client version.\": \"Posiadasz niezgodną wersję kliencką.\",\n    \"Refresh to update.\": \"Odświerz aby zaktualizować.\",\n    \"New version available!\": \"Nowa wersja dostępna!\",\n    \"See releases notes here\": \"Zobacz informacje o wydaniach tutaj\",\n    \"Refresh to enjoy new features.\": \"Odśwież, aby korzystać z nowych funkcji.\",\n    \"Your user state has changed.\": \"Stan twojego użytkownika się zmienił.\",\n    \"Refresh to load new user state.\": \"Odśwież aby załadować nowy stan użytkownika.\",\n    \"Refresh\": \"Odśwież\",\n    \"Contacts\": \"Kontakty\",\n    \"Report an issue\": \"Zgłoś błąd\",\n    \"Meet us on %s\": \"Meet us on %s\",\n    \"Send us email\": \"Wyślij nam email\",\n    \"Documents\": \"Dokumenty\",\n    \"Features\": \"Funkcje\",\n    \"YAML Metadata\": \"YAML Meta dane\",\n    \"Slide Example\": \"Przykład slajdu\",\n    \"Cheatsheet\": \"Ściągawka\",\n    \"Example\": \"Przykład\",\n    \"Syntax\": \"Składnia\",\n    \"Header\": \"Nagłówek\",\n    \"Unordered List\": \"Nie posortowana lista\",\n    \"Ordered List\": \"Posortowana lista\",\n    \"Todo List\": \"Todo lista\",\n    \"Blockquote\": \"Cytat blokowy\",\n    \"Bold font\": \"Czcionka pogrubiona\",\n    \"Italics font\": \"Czcionka pochylona\",\n    \"Strikethrough\": \"Przekreślenie\",\n    \"Inserted text\": \"Wstawiony tekst\",\n    \"Marked text\": \"Zaznaczony tekst\",\n    \"Link\": \"Odnośnik\",\n    \"Image\": \"Zdjęcie\",\n    \"Code\": \"Kod\",\n    \"Externals\": \"Zewnętrzne\",\n    \"This is a alert area.\": \"This is a alert area.\",\n    \"Revert\": \"Cofnij\",\n    \"Import from clipboard\": \"Importuj ze schowka\",\n    \"Paste your markdown or webpage here...\": \"Wklej markdown lub stronę tutaj...\",\n    \"Clear\": \"Wyczyść\",\n    \"This note is locked\": \"Notatka jest zablokowana\",\n    \"Sorry, only owner can edit this note.\": \"Tylko właściciel może edytować tą notatkę.\",\n    \"OK\": \"OK\",\n    \"Reach the limit\": \"Osiągnięto limit\",\n    \"Sorry, you've reached the max length this note can be.\": \"Niestety, osiągnięto maksymalną długość notatki.\",\n    \"Please reduce the content or divide it to more notes, thank you!\": \"Proszę zmniejszyć zawartość notatki lub podzielić ją na kilka notatek, dziękuję!\",\n    \"Import from Gist\": \"Importuj z Gist\",\n    \"Paste your gist url here...\": \"Wklej gist url tutaj...\",\n    \"Import from Snippet\": \"Importuj z Snippet\",\n    \"Select From Available Projects\": \"Wybierz z dostępnych projektów\",\n    \"Select From Available Snippets\": \"Wybierz z dostępnych Snippets\",\n    \"OR\": \"LUB\",\n    \"Export to Snippet\": \"Eksportuj do Snippet\",\n    \"Select Visibility Level\": \"Wybierz poziom widoczności\",\n    \"Night Theme\": \"Night Theme\",\n    \"Follow us on %s and %s.\": \"Follow us on %s, and %s.\",\n    \"Privacy\": \"Privacy\",\n    \"Terms of Use\": \"Terms of Use\",\n    \"Do you really want to delete your user account?\": \"Do you really want to delete your user account?\",\n    \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\",\n    \"Delete user\": \"Delete user\",\n    \"Export user data\": \"Export user data\"\n}"
  },
  {
    "path": "locales/pt.json",
    "content": "{\n\t\"Collaborative markdown notes\": \"Notas em Markdown colaborativas\",\n\t\"Realtime collaborative markdown notes on all platforms.\": \"Notas colaborativas em Markdown para todas as plataformas.\",\n\t\"Best way to write and share your knowledge in markdown.\": \"A melhor forma de escrever e compartilhar seu conhecimento em Markdown.\",\n\t\"Intro\": \"Introdução\",\n\t\"History\": \"Histórico\",\n\t\"New guest note\": \"Nova nota como convidado\",\n\t\"Collaborate with URL\": \"Colaborar via URL\",\n\t\"Support charts and MathJax\": \"Suporte para gráficos e MathJax\",\n\t\"Support slide mode\": \"Suporte para modo apresentação\",\n\t\"Sign In\": \"Entrar\",\n\t\"Below is the history from browser\": \"A seguir está o histórico do navegador\",\n\t\"Welcome!\": \"Bem vindo!\",\n\t\"New note\": \"Nova nota\",\n\t\"or\": \"ou\",\n\t\"Sign Out\": \"Sair\",\n\t\"Explore all features\": \"Explore todas as funções\",\n\t\"Select tags...\": \"Selecionar etiquetas...\",\n\t\"Search keyword...\": \"Buscar palavra-chave...\",\n\t\"Sort by title\": \"Ordenar por título\",\n\t\"Title\": \"Título\",\n\t\"Sort by time\": \"Ordenar por hora\",\n\t\"Time\": \"Hora\",\n\t\"Export history\": \"Exportar histórico\",\n\t\"Import history\": \"Importar histórico\",\n\t\"Clear history\": \"Apagar histórico\",\n\t\"Refresh history\": \"Atualizar histórico\",\n\t\"No history\": \"Nenhum histórico\",\n\t\"Import from browser\": \"Importar do navegador\",\n\t\"Releases\": \"Lançamentos\",\n\t\"Are you sure?\": \"Tem certeza?\",\n\t\"Cancel\": \"Cancelar\",\n\t\"Yes, do it!\": \"Sim, faça!\",\n\t\"Choose method\": \"Escolher método\",\n\t\"Sign in via %s\": \"Entrar via %s\",\n\t\"New\": \"Novo\",\n\t\"Publish\": \"Publicar\",\n\t\"Extra\": \"Extra\",\n\t\"Revision\": \"Revisão\",\n\t\"Slide Mode\": \"Modo Apresentação\",\n\t\"Export\": \"Exportar\",\n\t\"Import\": \"Importar\",\n\t\"Clipboard\": \"Área de transferência\",\n\t\"Download\": \"Baixar\",\n\t\"Raw HTML\": \"HTML puro\",\n\t\"Edit\": \"Editar\",\n\t\"View\": \"Ver\",\n\t\"Both\": \"Ambos\",\n\t\"Help\": \"Ajuda\",\n\t\"Upload Image\": \"Carregar Imagem\",\n\t\"Menu\": \"Menu\",\n\t\"This page need refresh\": \"Esta página precisa ser recarregada\",\n\t\"You have an incompatible client version.\": \"Você tem uma versão incompatível do cliente.\",\n\t\"Refresh to update.\": \"Recarregar para atualizar.\",\n\t\"New version available!\": \"Nova versão disponível!\",\n\t\"See releases notes here\": \"Veja notas de lançamento aqui\",\n\t\"Refresh to enjoy new features.\": \"Atualize para usar as novas funções.\",\n\t\"Your user state has changed.\": \"O estado do seu usuário mudou.\",\n\t\"Refresh to load new user state.\": \"Atualize para carregar o novo estado do usuário.\",\n\t\"Refresh\": \"Recarregar\",\n\t\"Contacts\": \"Contatos\",\n\t\"Report an issue\": \"Relatar um problema\",\n\t\"Send us email\": \"Envie-nos um email\",\n\t\"Documents\": \"Documentos\",\n\t\"Features\": \"Funções\",\n\t\"YAML Metadata\": \"Metadados YAML\",\n\t\"Slide Example\": \"Exemplo de Apresentação\",\n\t\"Cheatsheet\": \"Dicas\",\n\t\"Example\": \"Exemplo\",\n\t\"Syntax\": \"Sintaxe\",\n\t\"Header\": \"Cabeçalho\",\n\t\"Unordered List\": \"Lista não ordenada\",\n\t\"Ordered List\": \"Lista ordenada\",\n\t\"Todo List\": \"Lista de tarefas\",\n\t\"Blockquote\": \"Citação\",\n\t\"Bold font\": \"Fonte negrito\",\n\t\"Italics font\": \"Fonte itálico\",\n\t\"Strikethrough\": \"Tachado\",\n\t\"Inserted text\": \"Texto inserido\",\n\t\"Marked text\": \"Texto marcado\",\n\t\"Link\": \"Ligação\",\n\t\"Image\": \"Imagem\",\n\t\"Code\": \"Código\",\n\t\"Externals\": \"Externos\",\n\t\"This is a alert area.\": \"Esta é uma área de alerta.\",\n\t\"Revert\": \"Reverter\",\n\t\"Import from clipboard\": \"Importar da área de transferência\",\n\t\"Paste your markdown or webpage here...\": \"Cole seu markdown ou página web aqui...\",\n\t\"Clear\": \"Limpar\",\n\t\"This note is locked\": \"Esta nota está bloqueada\",\n\t\"Sorry, only owner can edit this note.\": \"Desculpe, somente o dono pode editar esta nota.\",\n\t\"OK\": \"OK\",\n\t\"Reach the limit\": \"Alcançou o limite\",\n\t\"Sorry, you've reached the max length this note can be.\": \"Desculpe, você alcançou o tamanho máximo que esta nota pode ter.\",\n\t\"Please reduce the content or divide it to more notes, thank you!\": \"Por favor reduza o conteúdo ou divida em mais de uma nota, obrigado!\",\n\t\"Import from Gist\": \"Importar de um Gist\",\n\t\"Paste your gist url here...\": \"Cole a URL de seu Gist aqui...\",\n\t\"Import from Snippet\": \"Importar de Snippet\",\n\t\"Select From Available Projects\": \"Selecionar de Projetos Disponíveis\",\n\t\"Select From Available Snippets\": \"Selecionar de Snippets Disponíveis\",\n\t\"OR\": \"OU\",\n\t\"Export to Snippet\": \"Exportar para Snippet\",\n\t\"Select Visibility Level\": \"Selecionar Nível de Visibilidade\"\n}"
  },
  {
    "path": "locales/ru.json",
    "content": "{\n    \"Collaborative markdown notes\": \"Совместные markdown заметки\",\n    \"Realtime collaborative markdown notes on all platforms.\": \"Совместные markdown заметки в режиме реального времени на всех платформах.\",\n    \"Best way to write and share your knowledge in markdown.\": \"Лучший способ записывать свои знания и делиться ими в формате markdown.\",\n    \"Intro\": \"Введение\",\n    \"History\": \"История\",\n    \"New guest note\": \"Новая гостевая заметка\",\n    \"Collaborate with URL\": \"Сотрудничество по ссылке\",\n    \"Support charts and MathJax\": \"Поддержка графиков и MathJax\",\n    \"Support slide mode\": \"Поддержка режима слайдера\",\n    \"Sign In\": \"Войти\",\n    \"Below is the history from browser\": \"Ниже приводится история браузера\",\n    \"Welcome!\": \"Добро пожаловать!\",\n    \"New note\": \"Новая заметка\",\n    \"or\": \"или\",\n    \"Sign Out\": \"Выйти\",\n    \"Explore all features\": \"Изучите все возможности\",\n    \"Select tags...\": \"Выберите теги...\",\n    \"Search keyword...\": \"Поиск...\",\n    \"Sort by title\": \"Сортировка по заголовку\",\n    \"Title\": \"Заголовок\",\n    \"Sort by time\": \"Сортировка по времени\",\n    \"Time\": \"Время\",\n    \"Export history\": \"Экспорт истории\",\n    \"Import history\": \"Импорт истории\",\n    \"Clear history\": \"Очистить историю\",\n    \"Refresh history\": \"Обновить историю\",\n    \"No history\": \"Нет истории\",\n    \"Import from browser\": \"Импорт из браузера\",\n    \"Releases\": \"Релизы\",\n    \"Are you sure?\": \"Вы уверены?\",\n    \"Do you really want to delete this note?\": \"Вы точно хотите удалить эту заметку?\",\n    \"All users will lose their connection.\": \"Все пользователи потеряют соединение.\",\n    \"Cancel\": \"Отмена\",\n    \"Yes, do it!\": \"Да, сделать это!\",\n    \"Choose method\": \"Выберите метод\",\n    \"Sign in via %s\": \"Войти с помощью %s\",\n    \"New\": \"Новая\",\n    \"Publish\": \"Опубликовать\",\n    \"Extra\": \"Дополнительно\",\n    \"Revision\": \"Изменения\",\n    \"Slide Mode\": \"Режим слайдера\",\n    \"Export\": \"Экспорт\",\n    \"Import\": \"Импорт\",\n    \"Clipboard\": \"Буфер обмена\",\n    \"Download\": \"Скачать\",\n    \"Raw HTML\": \"Raw HTML\",\n    \"Edit\": \"Редактировать\",\n    \"View\": \"Посмотреть\",\n    \"Both\": \"И то и другое\",\n    \"Help\": \"Помощь\",\n    \"Upload Image\": \"Загрузить изображение\",\n    \"Menu\": \"Меню\",\n    \"This page need refresh\": \"Эту страницу необходимо обновить\",\n    \"You have an incompatible client version.\": \"Вы используете несовместимую версию клиента.\",\n    \"Refresh to update.\": \"Обновите страницу для обновления клиента.\",\n    \"New version available!\": \"Доступна новая версия!\",\n    \"See releases notes here\": \"Смотрите подробности обновлений здесь\",\n    \"Refresh to enjoy new features.\": \"Обновите, чтобы наслаждаться новыми возможностями.\",\n    \"Your user state has changed.\": \"Ваш аккаунт изменен.\",\n    \"Refresh to load new user state.\": \"Обновите, чтобы загрузить изменения аккаунта.\",\n    \"Refresh\": \"Обновить\",\n    \"Contacts\": \"Контакты\",\n    \"Report an issue\": \"Сообщить о проблеме\",\n    \"Meet us on %s\": \"Познакомьтесь с нами в %s\",\n    \"Send us email\": \"Отправить нам письмо\",\n    \"Documents\": \"Документы\",\n    \"Features\": \"Особенности\",\n    \"YAML Metadata\": \"Метаданные YAML\",\n    \"Slide Example\": \"Пример слайдера\",\n    \"Cheatsheet\": \"Шпаргалка\",\n    \"Example\": \"Пример\",\n    \"Syntax\": \"Синтаксис\",\n    \"Header\": \"Заголовок\",\n    \"Unordered List\": \"Маркированный список\",\n    \"Ordered List\": \"Нумерованный список\",\n    \"Todo List\": \"Список дел\",\n    \"Blockquote\": \"Цитата\",\n    \"Bold font\": \"Жирный шрифт\",\n    \"Italics font\": \"Курсив\",\n    \"Strikethrough\": \"Зачеркнутый\",\n    \"Inserted text\": \"Подчеркнутый текст\",\n    \"Marked text\": \"Выделенный текст\",\n    \"Link\": \"Ссылка\",\n    \"Image\": \"Изображение\",\n    \"Code\": \"Код\",\n    \"Externals\": \"Внешнее\",\n    \"This is a alert area.\": \"Это уведомление.\",\n    \"Revert\": \"Отменить\",\n    \"Import from clipboard\": \"Импорт из буфера обмена\",\n    \"Paste your markdown or webpage here...\": \"Вставьте ваш markdown код или веб-страницу здесь...\",\n    \"Clear\": \"Очистить\",\n    \"This note is locked\": \"Эта заметка заблокирована\",\n    \"Sorry, only owner can edit this note.\": \"К сожалению, только автор может редактировать эту заметку.\",\n    \"OK\": \"OK\",\n    \"Reach the limit\": \"Вы достигли лимита\",\n    \"Sorry, you've reached the max length this note can be.\": \"К сожалению, вы достигли максимальной длины заметки.\",\n    \"Please reduce the content or divide it to more notes, thank you!\": \"Пожалуйста, уменьшите размер содержимого или разделите его на несколько заметок, спасибо!\",\n    \"Import from Gist\": \"Импорт из Gist\",\n    \"Paste your gist url here...\": \"Вставьте ссылку на ваш gist здесь...\",\n    \"Import from Snippet\": \"Импорт фрагмента кода\",\n    \"Select From Available Projects\": \"Выберите из доступных проектов\",\n    \"Select From Available Snippets\": \"Выберите из доступных фрагментов кода\",\n    \"OR\": \"ИЛИ\",\n    \"Export to Snippet\": \"Экспорт фрагмента кода\",\n    \"Select Visibility Level\": \"Выберите уровень видимости\",\n    \"Night Theme\": \"Тёмная тема\",\n    \"Follow us on %s and %s.\": \"Подпишитесь на нас в %s и %s.\",\n    \"Privacy\": \"Безопасность\",\n    \"Terms of Use\": \"Условия использования\",\n    \"Do you really want to delete your user account?\": \"Вы точно хотите удалить свою учётную запись?\",\n    \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"Это действие удалит вашу учётную запись, все ваши заметки и удалит все ссылки на вашу учетную запись из других заметок.\",\n    \"Delete user\": \"Удалить пользователя\",\n    \"Export user data\": \"Экспортировать данные пользователя\",\n    \"Help us translating on %s\": \"Помогите нам перевести %s\",\n    \"Source Code\": \"Исходный код\"\n}"
  },
  {
    "path": "locales/sr.json",
    "content": "{\n    \"Collaborative markdown notes\": \"Дељене белешке у Markdown формату\",\n    \"Realtime collaborative markdown notes on all platforms.\": \"Заједнички рад на markdown тексту у реалном времену, на свим платформама\",\n    \"Best way to write and share your knowledge in markdown.\": \"Савршен начин за писање и дељење знања у markdown формату\",\n    \"Intro\": \"Увод\",\n    \"History\": \"Историја\",\n    \"New guest note\": \"Нова белешка госта\",\n    \"Collaborate with URL\": \"Сарадња уз помоћ URL-а\",\n    \"Support charts and MathJax\": \"Подршка за графиконе и MathJax\",\n    \"Support slide mode\": \"Подршка за слајдове и презентације\",\n    \"Sign In\": \"Пријави се\",\n    \"Below is the history from browser\": \"Ниже је историјат преузет из прегледача\",\n    \"Welcome!\": \"Добродошли!\",\n    \"New note\": \"Нова белешка\",\n    \"or\": \"или\",\n    \"Sign Out\": \"Одјави се\",\n    \"Explore all features\": \"Истражи све могућности\",\n    \"Select tags...\": \"Одабери тагове...\",\n    \"Search keyword...\": \"Претрага по кључној речи...\",\n    \"Sort by title\": \"Редослед по наслову\",\n    \"Title\": \"Наслов\",\n    \"Sort by time\": \"Редослед по времену\",\n    \"Time\": \"време\",\n    \"Export history\": \"Извези историјат\",\n    \"Import history\": \"Увези историјат\",\n    \"Clear history\": \"Очисти историју\",\n    \"Refresh history\": \"Освежи историју\",\n    \"No history\": \"Нема историје\",\n    \"Import from browser\": \"Увези из прегледача\",\n    \"Releases\": \"Издања\",\n    \"Are you sure?\": \"Јесте ли сигурни?\",\n    \"Do you really want to delete this note?\": \"Да ли заиста желите да обришете ову белешку?\",\n    \"All users will lose their connection.\": \"Сви корисници ће изгубити везу у реалном времену.\",\n    \"Cancel\": \"Одустани\",\n    \"Yes, do it!\": \"Да, уради!\",\n    \"Choose method\": \"Изаберите начин\",\n    \"Sign in via %s\": \"Пријавите се помоћу %s\",\n    \"New\": \"Ново\",\n    \"Publish\": \"Објави\",\n    \"Extra\": \"Додатно\",\n    \"Revision\": \"Ревизија\",\n    \"Slide Mode\": \"Презентациони мод\",\n    \"Export\": \"Извоз\",\n    \"Import\": \"Увоз\",\n    \"Clipboard\": \"Клипборд\",\n    \"Download\": \"Преузимање\",\n    \"Raw HTML\": \"Сирови HTML\",\n    \"Edit\": \"Измени\",\n    \"View\": \"Прегледај\",\n    \"Both\": \"Обоје\",\n    \"Help\": \"Помоћ\",\n    \"Upload Image\": \"Пошаљи слику\",\n    \"Menu\": \"Мени\",\n    \"This page need refresh\": \"Ову страну је неопходно освежити\",\n    \"You have an incompatible client version.\": \"Ова верзија клијента није компатибилна.\",\n    \"Refresh to update.\": \"Освежите за приказ измена.\",\n    \"New version available!\": \"Доступна је нова верзија!\",\n    \"See releases notes here\": \"Овде погледајте напомене о издањима\",\n    \"Refresh to enjoy new features.\": \"Освежите како бисте уживали у новим функцијама.\",\n    \"Your user state has changed.\": \"Ваше корисничко стање се променило.\",\n    \"Refresh to load new user state.\": \"Освежите за учитавање новог корисничког стања.\",\n    \"Refresh\": \"Освежи\",\n    \"Contacts\": \"Контакти\",\n    \"Report an issue\": \"Пријава проблема\",\n    \"Meet us on %s\": \"Пронађите нас на %s\",\n    \"Send us email\": \"Пошаљите нам имејл\",\n    \"Documents\": \"Документи\",\n    \"Features\": \"Могућности\",\n    \"YAML Metadata\": \"YAML Метаподаци\",\n    \"Slide Example\": \"Пример слајда\",\n    \"Cheatsheet\": \"Трикови и форе\",\n    \"Example\": \"Пример\",\n    \"Syntax\": \"Синтакса\",\n    \"Header\": \"Заглавље\",\n    \"Unordered List\": \"Неуређени списак\",\n    \"Ordered List\": \"Уређени списак\",\n    \"Todo List\": \"Списак обавеза\",\n    \"Blockquote\": \"Пасус са наводима\",\n    \"Bold font\": \"Масна слова\",\n    \"Italics font\": \"Закривљена слова\",\n    \"Strikethrough\": \"Прецртано\",\n    \"Inserted text\": \"Уметнут текст\",\n    \"Marked text\": \"Означени текст\",\n    \"Link\": \"Линк\",\n    \"Image\": \"Слика\",\n    \"Code\": \"Код\",\n    \"Externals\": \"Спољни\",\n    \"This is a alert area.\": \"Ово је пасус за упозорења.\",\n    \"Revert\": \"Врати\",\n    \"Import from clipboard\": \"Увези из клипборда\",\n    \"Paste your markdown or webpage here...\": \"Залепи свој markdown или веб страну овде...\",\n    \"Clear\": \"Очисти\",\n    \"This note is locked\": \"Ова белешка је закључана\",\n    \"Sorry, only owner can edit this note.\": \"Жао нам је, ову белешку може мењати само њен власник.\",\n    \"OK\": \"OK\",\n    \"Reach the limit\": \"Досегни лимит\",\n    \"Sorry, you've reached the max length this note can be.\": \"Нажалост, досегли сте максималну дужину ове белешке.\",\n    \"Please reduce the content or divide it to more notes, thank you!\": \"Молимо Вас да смањите количину текста или да га поделите на више белешки, хвала!\",\n    \"Import from Gist\": \"Увези из Github Gist-а\",\n    \"Paste your gist url here...\": \"Залепите Gist URL адресу овде...\",\n    \"Import from Snippet\": \"Увези из \\\"исечака\\\"\",\n    \"Select From Available Projects\": \"Изабери из доступних пројеката\",\n    \"Select From Available Snippets\": \"Изабери из доступних исечака\",\n    \"OR\": \"ИЛИ\",\n    \"Export to Snippet\": \"Извези у \\\"исечак\\\"\",\n    \"Select Visibility Level\": \"Изаберите ниво читкости\",\n    \"Night Theme\": \"Ноћна тема\",\n    \"Follow us on %s and %s.\": \"Пратите нас на %s и %s.\",\n    \"Privacy\": \"Приватност\",\n    \"Terms of Use\": \"Услови коришћења\",\n    \"Do you really want to delete your user account?\": \"Да ли заиста желите да трајно обришете свој налог?\",\n    \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"Ова операција ће избрисати ваш налог, све ваше белешке, а уклониће и све везе ка вашем налогу из других белешки.\",\n    \"Delete user\": \"Брисање корисника\",\n    \"Export user data\": \"Извоз свих корисничких података\",\n    \"Help us translating on %s\": \"Помозите нам да преведемо на %s\",\n    \"Source Code\": \"Изворни код\"\n}"
  },
  {
    "path": "locales/sv.json",
    "content": "{\n\t\"Collaborative markdown notes\": \"Kollaborativa markdownanteckningar\",\n\t\"Realtime collaborative markdown notes on all platforms.\": \"Kollaborativa markdownantackningar på alla plattformar.\",\n\t\"Best way to write and share your knowledge in markdown.\": \"Bästa sättet att skriva och dela din kunskap i markdown.\",\n\t\"Intro\": \"Intro\",\n\t\"History\": \"Historia\",\n\t\"New guest note\": \"Ny gästanteckning\",\n\t\"Collaborate with URL\": \"Samarbeta med URL\",\n\t\"Support charts and MathJax\": \"Stöd för diagram och MathJax\",\n\t\"Support slide mode\": \"Stöd för slide mode\",\n\t\"Sign In\": \"Logga in\",\n\t\"Below is the history from browser\": \"Nedanför finns historia från webbläsaren\",\n\t\"Welcome!\": \"Välkommen!\",\n\t\"New note\": \"Ny anteckning\",\n\t\"or\": \"eller\",\n\t\"Sign Out\": \"Logga ut\",\n\t\"Explore all features\": \"Upptäck alla funktioner\",\n\t\"Select tags...\": \"Välj taggar...\",\n\t\"Search keyword...\": \"Sök nyckelord...\",\n\t\"Sort by title\": \"Sortera titlar\",\n\t\"Title\": \"Titel\",\n\t\"Sort by time\": \"Sortera kronologiskt\",\n\t\"Time\": \"Tid\",\n\t\"Export history\": \"Exporthistorik\",\n\t\"Import history\": \"Importhistorik\",\n\t\"Clear history\": \"Rensa historik\",\n\t\"Refresh history\": \"Uppdatera historik\",\n\t\"No history\": \"Ingen historik\",\n\t\"Import from browser\": \"Importera från webbläsare\",\n\t\"Releases\": \"Lanseringar\",\n\t\"Are you sure?\": \"Är du säker?\",\n\t\"Cancel\": \"Avbryt\",\n\t\"Yes, do it!\": \"Ja, gör det!\",\n\t\"Choose method\": \"Välj metod\",\n\t\"Sign in via %s\": \"Logga in via %s\",\n\t\"New\": \"Ny\",\n\t\"Publish\": \"Publicera\",\n\t\"Extra\": \"Extra\",\n\t\"Revision\": \"Revision\",\n\t\"Slide Mode\": \"Slide Mode\",\n\t\"Export\": \"Exportera\",\n\t\"Import\": \"Importera\",\n\t\"Clipboard\": \"Urklipp\",\n\t\"Download\": \"Ladda ner\",\n\t\"Raw HTML\": \"Rå HTML\",\n\t\"Edit\": \"Redigera\",\n\t\"View\": \"Visa\",\n\t\"Both\": \"Båda\",\n\t\"Help\": \"Hjälp\",\n\t\"Upload Image\": \"Ladda upp bilder\",\n\t\"Menu\": \"Meny\",\n\t\"This page need refresh\": \"Den här sidan behöver laddas om\",\n\t\"You have an incompatible client version.\": \"Du har en inkompatibel klientversion.\",\n\t\"Refresh to update.\": \"Ladda om för att uppdatera.\",\n\t\"New version available!\": \"Ny version tillgänglig!\",\n\t\"See releases notes here\": \"Se releaseanteckningar här\",\n\t\"Refresh to enjoy new features.\": \"Ladda om för att använda de nya funktionerna.\",\n\t\"Your user state has changed.\": \"Din användarstatus har förändrats.\",\n\t\"Refresh to load new user state.\": \"Ladda om för att ladda ny användarstatus.\",\n\t\"Refresh\": \"Ladda om\",\n\t\"Contacts\": \"Kontakter\",\n\t\"Report an issue\": \"Rapportera ett fel\",\n\t\"Send us email\": \"Skicka e-post till oss\",\n\t\"Documents\": \"Dokument\",\n\t\"Features\": \"Funktioner\",\n\t\"YAML Metadata\": \"YAML Metadata\",\n\t\"Slide Example\": \"Slideexempel\",\n\t\"Cheatsheet\": \"Cheatsheet\",\n\t\"Example\": \"Exempel\",\n\t\"Syntax\": \"Syntax\",\n\t\"Header\": \"Huvud\",\n\t\"Unordered List\": \"Oordnad lists\",\n\t\"Ordered List\": \"Ordnad lista\",\n\t\"Todo List\": \"Todo-lista\",\n\t\"Blockquote\": \"Blockcitat\",\n\t\"Bold font\": \"Fet stil\",\n\t\"Italics font\": \"Kursiv stil\",\n\t\"Strikethrough\": \"Genomstrykning\",\n\t\"Inserted text\": \"Insatt text\",\n\t\"Marked text\": \"Markerad text\",\n\t\"Link\": \"Länk\",\n\t\"Image\": \"Bild\",\n\t\"Code\": \"Kod\",\n\t\"Externals\": \"Externa\",\n\t\"This is a alert area.\": \"Det här är ett varnande område.\",\n\t\"Revert\": \"Återgå\",\n\t\"Import from clipboard\": \"Importera från urklipp\",\n\t\"Paste your markdown or webpage here...\": \"Klipp in din markdown eller hemsida här...\",\n\t\"Clear\": \"Rensa\",\n\t\"This note is locked\": \"Anteckningen är låst\",\n\t\"Sorry, only owner can edit this note.\": \"Ursäkta, men endast ägaren kan redigera den här anteckningen.\",\n\t\"OK\": \"Okej\",\n\t\"Reach the limit\": \"Nå gränsen\",\n\t\"Sorry, you've reached the max length this note can be.\": \"Usräkta, men duhar nått maxlängden för vad en anteckning får vara.\",\n\t\"Please reduce the content or divide it to more notes, thank you!\": \"Var vänlig förkorta innehållet eller dela upp det i flera anteckningar, tack!\",\n\t\"Import from Gist\": \"Importera från Gist\",\n\t\"Paste your gist url here...\": \"Klipp in din gist-url här...\",\n\t\"Import from Snippet\": \"Importera från Snippet\",\n\t\"Select From Available Projects\": \"Välj från tillgängliga projekt\",\n\t\"Select From Available Snippets\": \"Välj från tillgängliga Snippets\",\n\t\"OR\": \"ELLER\",\n\t\"Export to Snippet\": \"Exportera till Snippet\",\n\t\"Select Visibility Level\": \"Välj synlighetsnivå\"\n}\n"
  },
  {
    "path": "locales/tr.json",
    "content": "{\n\t\"Collaborative markdown notes\": \"Ortak markdown notları\",\n\t\"Realtime collaborative markdown notes on all platforms.\": \"Tüm platformlarda gerçek zamanlı markdown notları\",\n\t\"Best way to write and share your knowledge in markdown.\": \"Markdownda bilginizi paylaşmanın en kolay yolu.\",\n\t\"Intro\": \"Giriş\",\n\t\"History\": \"Geçmiş\",\n\t\"New guest note\": \"Yeni kullanıcı notu\",\n\t\"Collaborate with URL\": \"URL ile katkıda bulun\",\n\t\"Support charts and MathJax\": \"Grafikler ve MathJax'ı destekle\",\n\t\"Support slide mode\": \"Sunum modunu destekle\",\n\t\"Sign In\": \"Kaydol\",\n\t\"Below is the history from browser\": \"Aşağıda tarayıcınızın geçmişi var\",\n\t\"Welcome!\": \"Hoşgeldiniz!\",\n\t\"New note\": \"Yeni not\",\n\t\"or\": \"veya\",\n\t\"Sign Out\": \"Çıkış Yap\",\n\t\"Explore all features\": \"Özellikleri keşfet\",\n\t\"Select tags...\": \"Etiketleri seçin...\",\n\t\"Search keyword...\": \"Anahtar kelimeleri arayın...\",\n\t\"Sort by title\": \"Başlığa göre sırala\",\n\t\"Title\": \"Başlık\",\n\t\"Sort by time\": \"Zamana göre sırala\",\n\t\"Time\": \"Zaman\",\n\t\"Export history\": \"Geçmişe dışa aktar\",\n\t\"Import history\": \"Geçmişi içe aktar\",\n\t\"Clear history\": \"Geçmişi temizle\",\n\t\"Refresh history\": \"Geçmişi yenile\",\n\t\"No history\": \"Geçmiş yok\",\n\t\"Import from browser\": \"Tarayıcıdan içe aktar\",\n\t\"Releases\": \"Sürümler\",\n\t\"Are you sure?\": \"Emin misiniz?\",\n\t\"Cancel\": \"İptal\",\n\t\"Yes, do it!\": \"Evet, devam et!\",\n\t\"Choose method\": \"Metot seçin\",\n\t\"Sign in via %s\": \"%s ile giriş yapın\",\n\t\"New\": \"Yeni\",\n\t\"Publish\": \"Yayınla\",\n\t\"Extra\": \"Ekstra\",\n\t\"Revision\": \"Sürüm\",\n\t\"Slide Mode\": \"Slayt Modu\",\n\t\"Export\": \"Dışa Aktar\",\n\t\"Import\": \"İçe Aktar\",\n\t\"Clipboard\": \"Pano\",\n\t\"Download\": \"İndir\",\n\t\"Raw HTML\": \"Kaynak HTML\",\n\t\"Edit\": \"Düzenle\",\n\t\"View\": \"İncele\",\n\t\"Both\": \"İkisi de\",\n\t\"Help\": \"Yardım\",\n\t\"Upload Image\": \"Resim Yükle\",\n\t\"Menu\": \"Menü\",\n\t\"This page need refresh\": \"Bu sayfayı yeniden yüklemek lazım\",\n\t\"You have an incompatible client version.\": \"Yerel uygulamanız uyumlu olmayan bir sürümde.\",\n\t\"Refresh to update.\": \"Güncellemek için yenileyin.\",\n\t\"New version available!\": \"Yeni versiyon kullanıma hazır!\",\n\t\"See releases notes here\": \"Değişikliklere burdan bakabilirsiniz\",\n\t\"Refresh to enjoy new features.\": \"Yeni özelliklere yenileyerek erişebilirsiniz.\",\n\t\"Your user state has changed.\": \"Kullanıcı durumunuz değişti.\",\n\t\"Refresh to load new user state.\": \"Yeni kullanıcı durumunuzu yüklemek için yenileyin.\",\n\t\"Refresh\": \"Yenile\",\n\t\"Contacts\": \"Kişiler\",\n\t\"Report an issue\": \"Hata bildir\",\n\t\"Send us email\": \"Bize email gönderin\",\n\t\"Documents\": \"Belgeler\",\n\t\"Features\": \"Özellikler\",\n\t\"YAML Metadata\": \"YAML Özbilgisi\",\n\t\"Slide Example\": \"Slayt Örneği\",\n\t\"Cheatsheet\": \"Cheatsheet\",\n\t\"Example\": \"Örnek\",\n\t\"Syntax\": \"Sentaks\",\n\t\"Header\": \"Başlık\",\n\t\"Unordered List\": \"Sırasız Liste\",\n\t\"Ordered List\": \"Sıralı Liste\",\n\t\"Todo List\": \"Yapılacaklar Listesi\",\n\t\"Blockquote\": \"Alıntı Bloğu\",\n\t\"Bold font\": \"Kalın yazı\",\n\t\"Italics font\": \"İtalik yazı\",\n\t\"Strikethrough\": \"Üstüçizili\",\n\t\"Inserted text\": \"Eklenmiş yazı\",\n\t\"Marked text\": \"Seçili yazı\",\n\t\"Link\": \"Link\",\n\t\"Image\": \"Resim\",\n\t\"Code\": \"Kod\",\n\t\"Externals\": \"Dış veriler\",\n\t\"This is a alert area.\": \"Burası bir uyarı bölgesi.\",\n\t\"Revert\": \"Geri al\",\n\t\"Import from clipboard\": \"Panodan içe aktar\",\n\t\"Paste your markdown or webpage here...\": \"Markdown veya web sayfanızı buraya yapıştırın...\",\n\t\"Clear\": \"Temizle\",\n\t\"This note is locked\": \"Burası kilitli\",\n\t\"Sorry, only owner can edit this note.\": \"Üzgünüm, bu not sadece sahibi tarafından düzenlenebilir.\",\n\t\"OK\": \"Tamam\",\n\t\"Reach the limit\": \"Limite eriş\",\n\t\"Sorry, you've reached the max length this note can be.\": \"Üzgünüm, bu not için maksimum harf sayısına ulaştınız\",\n\t\"Please reduce the content or divide it to more notes, thank you!\": \"Lütfen notu değiştirin veya birden fazla notlara bölün, teşekkürler!\",\n\t\"Import from Gist\": \"Gist'ten içe aktar\",\n\t\"Paste your gist url here...\": \"Gist URL'nizi buraya yapıştırın...\",\n\t\"Import from Snippet\": \"Snippet'ten içe aktar\",\n\t\"Select From Available Projects\": \"Uygun Projelerden Seçin\",\n\t\"Select From Available Snippets\": \"Uygun Snippet'lerden Seçin\",\n\t\"OR\": \"VEYA\",\n\t\"Export to Snippet\": \"Snippet olarak dışa aktarın\",\n\t\"Select Visibility Level\": \"Görünebilirlik seviyesini belirleyin\"\n}\n"
  },
  {
    "path": "locales/uk.json",
    "content": "{\n\t\"Collaborative markdown notes\": \"Спільні примітки щодо знижок\",\n\t\"Realtime collaborative markdown notes on all platforms.\": \"Спільні примітки щодо знижок в реальному часі на всіх платформах.\",\n\t\"Best way to write and share your knowledge in markdown.\": \"Кращий спосіб, щоб записувати і ділитись своїми знаннями щодо знижок в реальному часі.\",\n\t\"Intro\": \"Вступ\",\n\t\"History\": \"Історія\",\n\t\"New guest note\": \"Примітка нового гостя\",\n\t\"Collaborate with URL\": \"Спільна робота по URL\",\n\t\"Support charts and MathJax\": \"Підтримка графіків і MathJax\",\n\t\"Support slide mode\": \"Підтримка режиму слайдера\",\n\t\"Sign In\": \"Ввійти\",\n\t\"Below is the history from browser\": \"Нижче показана історія браузера\",\n\t\"Welcome!\": \"Ласкаво просимо!\",\n\t\"New note\": \"Нова примітка\",\n\t\"or\": \"або\",\n\t\"Sign Out\": \"Вийти\",\n\t\"Explore all features\": \"Дослідити всі можливості\",\n\t\"Select tags...\": \"Вибрати теги...\",\n\t\"Search keyword...\": \"Пошук...\",\n\t\"Sort by title\": \"Сортувати по заголовку\",\n\t\"Title\": \"Заголовок\",\n\t\"Sort by time\": \"Сортувати по часу\",\n\t\"Time\": \"Час\",\n\t\"Export history\": \"Еспортувати історію\",\n\t\"Import history\": \"Імпортувати історію\",\n\t\"Clear history\": \"Очистити історію\",\n\t\"Refresh history\": \"Оновити історію\",\n\t\"No history\": \"Історія відсутня\",\n\t\"Import from browser\": \"Імпортувати з браузера\",\n\t\"Releases\": \"Релізи\",\n\t\"Are you sure?\": \"Ви впевнені?\",\n\t\"Cancel\": \"Відмінити\",\n\t\"Yes, do it!\": \"Так, зробити це!\",\n\t\"Choose method\": \"Вибрати метод\",\n\t\"Sign in via %s\": \"Увійти за допомогою %s\",\n\t\"New\": \"Нова\",\n\t\"Publish\": \"Опублікувати\",\n\t\"Extra\": \"Дотатково\",\n\t\"Revision\": \"Ревізія\",\n\t\"Slide Mode\": \"Режим слайдера\",\n\t\"Export\": \"Експорт\",\n\t\"Import\": \"Імпорт\",\n\t\"Clipboard\": \"Буфер обміну\",\n\t\"Download\": \"Завантажити\",\n\t\"Raw HTML\": \"Raw HTML\",\n\t\"Edit\": \"Редагувати\",\n\t\"View\": \"Вигляд\",\n\t\"Both\": \"Обоє\",\n\t\"Help\": \"Допомога\",\n\t\"Upload Image\": \"Завантажити зображення\",\n\t\"Menu\": \"Меню\",\n\t\"This page need refresh\": \"Цю сторінку необхідно обновити\",\n\t\"You have an incompatible client version.\": \"Ви використовуєте несумісну версію клієнта.\",\n\t\"Refresh to update.\": \"Оновіть сторінку для оновлення.\",\n\t\"New version available!\": \"Нова версія доступна!\",\n\t\"See releases notes here\": \"Огляньте деталі оновлень тут\",\n\t\"Refresh to enjoy new features.\": \"Оновіть, щоб насолоджуватись новими можливостями.\",\n\t\"Your user state has changed.\": \"Ваш акаунт змінено.\",\n\t\"Refresh to load new user state.\": \"Оновіть, щоб завантажити зміни акаунта.\",\n\t\"Refresh\": \"Оновити\",\n\t\"Contacts\": \"Контакти\",\n\t\"Report an issue\": \"Повідомити про проблему\",\n\t\"Send us email\": \"Відправити нам лист\",\n\t\"Documents\": \"Документи\",\n\t\"Features\": \"Можливості\",\n\t\"YAML Metadata\": \"Метадані YAML\",\n\t\"Slide Example\": \"Приклад слайдера\",\n\t\"Cheatsheet\": \"Шпаргалка\",\n\t\"Example\": \"Приклад\",\n\t\"Syntax\": \"Синтаксис\",\n\t\"Header\": \"Заголовок\",\n\t\"Unordered List\": \"Маркований список\",\n\t\"Ordered List\": \"Нумерований список\",\n\t\"Todo List\": \"Список завдань\",\n\t\"Blockquote\": \"Цитата\",\n\t\"Bold font\": \"Жирний шрифт\",\n\t\"Italics font\": \"Курсив\",\n\t\"Strikethrough\": \"Перекреслений\",\n\t\"Inserted text\": \"Підкреслений текст\",\n\t\"Marked text\": \"Виділений текст\",\n\t\"Link\": \"Посилання\",\n\t\"Image\": \"Зображення\",\n\t\"Code\": \"Код\",\n\t\"Externals\": \"Зовнішнє\",\n\t\"This is a alert area.\": \"Це область повідомлення.\",\n\t\"Revert\": \"Відмінити\",\n\t\"Import from clipboard\": \"Імпорт з буферу обміну\",\n\t\"Paste your markdown or webpage here...\": \"Вставте ваш markdown або веб-сторінку тут...\",\n\t\"Clear\": \"Очистити\",\n\t\"This note is locked\": \"Ця замітка заблокована\",\n\t\"Sorry, only owner can edit this note.\": \"Вибачте, лише власник може редагувати цю замітку.\",\n\t\"OK\": \"OK\",\n\t\"Reach the limit\": \"Досягнено ліміту\",\n\t\"Sorry, you've reached the max length this note can be.\": \"Нажаль, ви досягли максимальної довжини замітки.\",\n\t\"Please reduce the content or divide it to more notes, thank you!\": \"Будь-ласка, зменшіть розмір вмісту або розділіть його на декілька заміток!\",\n\t\"Import from Gist\": \"Імпортувати з Gist\",\n\t\"Paste your gist url here...\": \"Вставте посилання на ваш gist тут...\",\n\t\"Import from Snippet\": \"Імпортувати фрагмент коду\",\n\t\"Select From Available Projects\": \"Виберіть з доступних проектів\",\n\t\"Select From Available Snippets\": \"Виберіть з доступних фрагментів коду\",\n\t\"OR\": \"АБО\",\n\t\"Export to Snippet\": \"Експорт фрагменту коду\",\n\t\"Select Visibility Level\": \"Вибрати рівень видимості\"\n}\n"
  },
  {
    "path": "locales/zh-CN.json",
    "content": "{\n    \"Collaborative markdown notes\": \"Markdown 协作笔记\",\n    \"Realtime collaborative markdown notes on all platforms.\": \"使用 Markdown 的跨平台即时协作笔记。\",\n    \"Best way to write and share your knowledge in markdown.\": \"写作与分享 Markdown 的最佳平台。\",\n    \"Intro\": \"简介\",\n    \"History\": \"历史\",\n    \"New guest note\": \"新建访客笔记\",\n    \"Collaborate with URL\": \"实时协作\",\n    \"Support charts and MathJax\": \"支持图表与 MathJax\",\n    \"Support slide mode\": \"支持幻灯模式\",\n    \"Sign In\": \"登录\",\n    \"Below is the history from browser\": \"以下为来自浏览器的历史\",\n    \"Welcome!\": \"欢迎！\",\n    \"New note\": \"新建笔记\",\n    \"or\": \"或\",\n    \"Sign Out\": \"登出\",\n    \"Explore all features\": \"探索所有功能\",\n    \"Select tags...\": \"选择标签...\",\n    \"Search keyword...\": \"搜索关键字...\",\n    \"Sort by title\": \"按标题排序\",\n    \"Title\": \"标题\",\n    \"Sort by time\": \"按时间排序\",\n    \"Time\": \"时间\",\n    \"Export history\": \"导出历史\",\n    \"Import history\": \"导入历史\",\n    \"Clear history\": \"清空历史\",\n    \"Refresh history\": \"刷新历史\",\n    \"No history\": \"无历史记录\",\n    \"Import from browser\": \"从浏览器导入\",\n    \"Releases\": \"版本\",\n    \"Are you sure?\": \"您确定吗？\",\n    \"Do you really want to delete this note?\": \"您确定要删除这篇笔记吗？\",\n    \"All users will lose their connection.\": \"所有用户将失去连接。\",\n    \"Cancel\": \"取消\",\n    \"Yes, do it!\": \"是的，就这样做！\",\n    \"Choose method\": \"选择方式\",\n    \"Sign in via %s\": \"通过 %s 登录\",\n    \"New\": \"新建\",\n    \"Publish\": \"发表\",\n    \"Extra\": \"附加功能\",\n    \"Revision\": \"修订版本\",\n    \"Slide Mode\": \"幻灯模式\",\n    \"Export\": \"导出\",\n    \"Import\": \"导入\",\n    \"Clipboard\": \"剪贴板\",\n    \"Download\": \"下载\",\n    \"Raw HTML\": \"原始 HTML\",\n    \"Edit\": \"编辑\",\n    \"View\": \"预览\",\n    \"Both\": \"双栏\",\n    \"Help\": \"帮助\",\n    \"Upload Image\": \"上传图片\",\n    \"Menu\": \"菜单\",\n    \"This page need refresh\": \"此页面需要刷新\",\n    \"You have an incompatible client version.\": \"您的客户端版本不兼容。\",\n    \"Refresh to update.\": \"刷新页面以更新。\",\n    \"New version available!\": \"新版本可用！\",\n    \"See releases notes here\": \"在此查看更新记录\",\n    \"Refresh to enjoy new features.\": \"刷新页面以体验新功能。\",\n    \"Your user state has changed.\": \"您的用户状态已变更。\",\n    \"Refresh to load new user state.\": \"刷新页面以加载新的用户状态。\",\n    \"Refresh\": \"刷新\",\n    \"Contacts\": \"联系我们\",\n    \"Report an issue\": \"报告问题\",\n    \"Meet us on %s\": \"在 %s 上联系我们\",\n    \"Send us email\": \"给我们发送电子邮件\",\n    \"Documents\": \"文档\",\n    \"Features\": \"功能\",\n    \"YAML Metadata\": \"YAML 元数据\",\n    \"Slide Example\": \"幻灯范例\",\n    \"Cheatsheet\": \"速查表\",\n    \"Example\": \"范例\",\n    \"Syntax\": \"语法\",\n    \"Header\": \"标题\",\n    \"Unordered List\": \"无序列表\",\n    \"Ordered List\": \"有序列表\",\n    \"Todo List\": \"清单\",\n    \"Blockquote\": \"引用\",\n    \"Bold font\": \"粗体\",\n    \"Italics font\": \"斜体\",\n    \"Strikethrough\": \"删除线\",\n    \"Inserted text\": \"下划线文字\",\n    \"Marked text\": \"高亮文字\",\n    \"Link\": \"链接\",\n    \"Image\": \"图片\",\n    \"Code\": \"代码\",\n    \"Externals\": \"外部扩展\",\n    \"This is a alert area.\": \"这是一个警告区块。\",\n    \"Revert\": \"还原\",\n    \"Import from clipboard\": \"从剪贴板导入\",\n    \"Paste your markdown or webpage here...\": \"在这里粘贴 Markdown 或网页内容...\",\n    \"Clear\": \"清除\",\n    \"This note is locked\": \"这篇笔记已被锁定\",\n    \"Sorry, only owner can edit this note.\": \"抱歉，只有所有者可以编辑这篇笔记。\",\n    \"OK\": \"好的\",\n    \"Reach the limit\": \"达到上限\",\n    \"Sorry, you've reached the max length this note can be.\": \"抱歉，您的这篇笔记已达到可用的最大长度。\",\n    \"Please reduce the content or divide it to more notes, thank you!\": \"请减少笔记的内容。\",\n    \"Import from Gist\": \"从 Gist 导入\",\n    \"Paste your gist url here...\": \"在这里粘贴 Gist 网址...\",\n    \"Import from Snippet\": \"从 Snippet 导入\",\n    \"Select From Available Projects\": \"从可用的项目中选择\",\n    \"Select From Available Snippets\": \"从可用的 Snippets 中选择\",\n    \"OR\": \"或\",\n    \"Export to Snippet\": \"导出到 Snippet\",\n    \"Select Visibility Level\": \"选择可见层级\",\n    \"Night Theme\": \"夜间主题\",\n    \"Follow us on %s and %s.\": \"在 %s 和 %s 上关注我们\",\n    \"Privacy\": \"隐私\",\n    \"Terms of Use\": \"使用条款\",\n    \"Do you really want to delete your user account?\": \"您确定要删除帐户吗？\",\n    \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"您的帐户、您所拥有的笔记、他人笔记中对您帐户的引用都将被删除。\",\n    \"Delete user\": \"删除帐户\",\n    \"Export user data\": \"导出用户数据\",\n    \"Help us translating on %s\": \"在 %s 上帮我们翻译\",\n    \"Source Code\": \"源代码\",\n    \"Powered by %s\": \"由 %s 驱动\",\n    \"Register\": \"注册\",\n    \"Export with pandoc\": \"使用 Pandoc 导出\",\n    \"Select output format\": \"选择输出格式\",\n    \"CONNECTED\": \"已连接\",\n    \"ONLINE\": \"在线\",\n    \"OFFLINE\": \"离线\",\n    \"Anyone can edit\": \"任何人都可以编辑\",\n    \"Freely\": \"自由地\",\n    \"Signed-in people can edit\": \"登录的人可以编辑\",\n    \"Editable\": \"可编辑\",\n    \"Signed-in people can edit (forbid guests)\": \"登录的人可以编辑（禁止访客）\",\n    \"Limited\": \"受限\",\n    \"Only owner can edit\": \"只有所有者可以编辑\",\n    \"Locked\": \"已锁定\",\n    \"Only owner can edit (forbid guests)\": \"只有所有者可以编辑（禁止访客）\",\n    \"Protected\": \"受保护\",\n    \"Only owner can view & edit\": \"只有所有者可以查看和编辑\",\n    \"Private\": \"私人\",\n    \"Delete this note\": \"删除这个笔记\",\n    \"owned this note\": \"拥有这个笔记\",\n    \"Expand all\": \"全部展开\",\n    \"Collapse all\": \"全部折叠\",\n    \"Back to top\": \"回到顶部\",\n    \"Go to bottom\": \"前往底部\"\n}\n"
  },
  {
    "path": "locales/zh-TW.json",
    "content": "{\n    \"Collaborative markdown notes\": \"Markdown 協作筆記\",\n    \"Realtime collaborative markdown notes on all platforms.\": \"使用 Markdown 的跨平台即時協作筆記\",\n    \"Best way to write and share your knowledge in markdown.\": \"使用 Markdown 寫作與分享知識的最佳方式\",\n    \"Intro\": \"簡介\",\n    \"History\": \"歷史記錄\",\n    \"New guest note\": \"建立訪客筆記\",\n    \"Collaborate with URL\": \"使用網址協作\",\n    \"Support charts and MathJax\": \"支援圖表與 MathJax\",\n    \"Support slide mode\": \"支援簡報模式\",\n    \"Sign In\": \"登入\",\n    \"Below is the history from browser\": \"以下是從瀏覽器取得的歷史記錄\",\n    \"Welcome!\": \"歡迎！\",\n    \"New note\": \"建立筆記\",\n    \"or\": \"或\",\n    \"Sign Out\": \"登出\",\n    \"Explore all features\": \"探索所有功能\",\n    \"Select tags...\": \"選擇標籤…\",\n    \"Search keyword...\": \"搜尋關鍵字…\",\n    \"Sort by title\": \"依標題排序\",\n    \"Title\": \"標題\",\n    \"Sort by time\": \"依時間排序\",\n    \"Time\": \"時間\",\n    \"Export history\": \"匯出記錄\",\n    \"Import history\": \"匯入記錄\",\n    \"Clear history\": \"清空記錄\",\n    \"Refresh history\": \"重新整理記錄\",\n    \"No history\": \"沒有記錄\",\n    \"Import from browser\": \"從瀏覽器匯入\",\n    \"Releases\": \"版本\",\n    \"Are you sure?\": \"您確定嗎？\",\n    \"Do you really want to delete this note?\": \"確定刪除這則筆記？\",\n    \"All users will lose their connection.\": \"所有使用者將會失去連線\",\n    \"Cancel\": \"取消\",\n    \"Yes, do it!\": \"沒錯，就這麼做！\",\n    \"Choose method\": \"選擇方式\",\n    \"Sign in via %s\": \"透過 %s 登入\",\n    \"New\": \"新增\",\n    \"Publish\": \"發佈\",\n    \"Extra\": \"增益\",\n    \"Revision\": \"修訂版本\",\n    \"Slide Mode\": \"簡報模式\",\n    \"Export\": \"匯出\",\n    \"Import\": \"匯入\",\n    \"Clipboard\": \"剪貼簿\",\n    \"Download\": \"下載\",\n    \"Raw HTML\": \"純 HTML\",\n    \"Edit\": \"編輯\",\n    \"View\": \"檢視\",\n    \"Both\": \"雙欄\",\n    \"Help\": \"協助\",\n    \"Upload Image\": \"上傳圖片\",\n    \"Menu\": \"選單\",\n    \"This page need refresh\": \"此頁面需要重新整理\",\n    \"You have an incompatible client version.\": \"您使用的是不相容的客戶端\",\n    \"Refresh to update.\": \"請重新整理來更新\",\n    \"New version available!\": \"新版本來了！\",\n    \"See releases notes here\": \"請由此查閱更新記錄\",\n    \"Refresh to enjoy new features.\": \"請重新整理來享受最新功能\",\n    \"Your user state has changed.\": \"您的使用者狀態已變更\",\n    \"Refresh to load new user state.\": \"請重新整理來載入新的使用者狀態\",\n    \"Refresh\": \"重新整理\",\n    \"Contacts\": \"聯絡方式\",\n    \"Report an issue\": \"回報問題\",\n    \"Meet us on %s\": \"透過 %s 聯絡我們\",\n    \"Send us email\": \"寄信給我們\",\n    \"Documents\": \"文件\",\n    \"Features\": \"功能簡介\",\n    \"YAML Metadata\": \"YAML 中繼資料\",\n    \"Slide Example\": \"簡報範例\",\n    \"Cheatsheet\": \"快速簡表\",\n    \"Example\": \"範例\",\n    \"Syntax\": \"語法\",\n    \"Header\": \"標題\",\n    \"Unordered List\": \"無序清單\",\n    \"Ordered List\": \"有序清單\",\n    \"Todo List\": \"待辦事項\",\n    \"Blockquote\": \"引用\",\n    \"Bold font\": \"粗體\",\n    \"Italics font\": \"斜體\",\n    \"Strikethrough\": \"刪除線\",\n    \"Inserted text\": \"插入文字\",\n    \"Marked text\": \"標記文字\",\n    \"Link\": \"連結\",\n    \"Image\": \"圖片\",\n    \"Code\": \"程式碼\",\n    \"Externals\": \"外部\",\n    \"This is a alert area.\": \"這是警告區塊\",\n    \"Revert\": \"還原\",\n    \"Import from clipboard\": \"從剪貼簿匯入\",\n    \"Paste your markdown or webpage here...\": \"在這裡貼上 Markdown 或是網頁內容…\",\n    \"Clear\": \"清除\",\n    \"This note is locked\": \"此份筆記已被鎖定\",\n    \"Sorry, only owner can edit this note.\": \"抱歉，只有擁有者可以編輯此筆記\",\n    \"OK\": \"好的\",\n    \"Reach the limit\": \"到達上限\",\n    \"Sorry, you've reached the max length this note can be.\": \"抱歉，您已使用到此份筆記可用的最大長度\",\n    \"Please reduce the content or divide it to more notes, thank you!\": \"請減少內容或是將內容切成更多筆記，謝謝！\",\n    \"Import from Gist\": \"從 Gist 匯入\",\n    \"Paste your gist url here...\": \"在此處貼上 gist 網址…\",\n    \"Import from Snippet\": \"從 Snippet 匯入\",\n    \"Select From Available Projects\": \"從可用專案選擇\",\n    \"Select From Available Snippets\": \"從可用的 Snippets 選擇\",\n    \"OR\": \"或是\",\n    \"Export to Snippet\": \"匯出至 Snippet\",\n    \"Select Visibility Level\": \"選擇可見層級\",\n    \"Night Theme\": \"夜間主題\",\n    \"Follow us on %s and %s.\": \"來 %s 或 %s 和我們互動吧！\",\n    \"Privacy\": \"隱私權政策\",\n    \"Terms of Use\": \"使用條款\",\n    \"Do you really want to delete your user account?\": \"你確定真的想要刪除帳戶？\",\n    \"This will delete your account, all notes that are owned by you and remove all references to your account from other notes.\": \"我們將會刪除你的帳戶、你所擁有的筆記、以及你在別人筆記裡的作者記錄。\",\n    \"Delete user\": \"刪除使用者\",\n    \"Export user data\": \"匯出使用者資料\",\n    \"Help us translating on %s\": \"來 %s 幫我們翻譯\",\n    \"Source Code\": \"原始碼\",\n    \"Powered by %s\": \"技術支援：%s\",\n    \"Register\": \"註冊\",\n    \"Export with pandoc\": \"使用 pandoc 匯出\",\n    \"Select output format\": \"選擇輸出格式\",\n    \"CONNECTED\": \"已連接\",\n    \"ONLINE\": \"線上\",\n    \"OFFLINE\": \"離線\",\n    \"Anyone can edit\": \"任何人皆可編輯\",\n    \"Freely\": \"自由地\",\n    \"Signed-in people can edit\": \"登入的人可以編輯\",\n    \"Editable\": \"可編輯\",\n    \"Signed-in people can edit (forbid guests)\": \"登入的人可以編輯（禁止訪客）\",\n    \"Limited\": \"受限\",\n    \"Only owner can edit\": \"僅擁有者可以編輯\",\n    \"Locked\": \"已鎖定\",\n    \"Only owner can edit (forbid guests)\": \"僅擁有者可以編輯（禁止訪客）\",\n    \"Protected\": \"受保護\",\n    \"Only owner can view & edit\": \"僅擁有者可以檢視與編輯\",\n    \"Private\": \"私人\",\n    \"Delete this note\": \"刪除這個筆記\",\n    \"owned this note\": \"擁有這個筆記\",\n    \"Expand all\": \"全部展開\",\n    \"Collapse all\": \"全部折疊\",\n    \"Back to top\": \"回到頂端\",\n    \"Go to bottom\": \"前往底端\"\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"codimd\",\n  \"version\": \"2.6.0\",\n  \"description\": \"Realtime collaborative markdown notes on all platforms.\",\n  \"keywords\": [\n    \"Collaborative\",\n    \"Markdown\",\n    \"Notes\"\n  ],\n  \"bugs\": \"https://github.com/hackmdio/codimd/issues\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/hackmdio/codimd.git\"\n  },\n  \"license\": \"AGPL-3.0\",\n  \"main\": \"app.js\",\n  \"scripts\": {\n    \"build\": \"cross-env NODE_ENV=production webpack --config webpack.prod.js --display errors-only -p\",\n    \"dev\": \"webpack --config webpack.dev.js --progress --colors --watch\",\n    \"doctoc\": \"doctoc --title='# Table of Contents' README.md\",\n    \"lint\": \"standard\",\n    \"jsonlint\": \"find . -type f -not -ipath \\\"./.devcontainer/*\\\" -not -ipath \\\"./node_modules/*\\\" -not -ipath \\\"./.vscode/*\\\" \\\\( -name \\\"*.json\\\" -o -name \\\"*.json.*\\\" \\\\) | xargs -n 1 -I{} -- bash -c 'echo {}; jq . {} > /dev/null;'\",\n    \"start\": \"sequelize db:migrate && node app.js\",\n    \"mocha\": \"mocha --require intelli-espower-loader --exit ./test --recursive\",\n    \"mocha:ci\": \"mocha --no-color -R dot --require intelli-espower-loader --exit ./test --recursive\",\n    \"coverage\": \"nyc mocha --require intelli-espower-loader --exit --recursive ./test\",\n    \"coverage:ci\": \"nyc mocha --no-color -R dot --require intelli-espower-loader --exit --recursive ./test\",\n    \"test\": \"npm run-script lint && npm run-script jsonlint && npm run-script coverage\",\n    \"test:ci\": \"npm run-script lint && npm run-script jsonlint && npm run-script coverage:ci\",\n    \"heroku-postbuild\": \"npm run build && ./bin/heroku\"\n  },\n  \"dependencies\": {\n    \"@aws-sdk/client-s3-node\": \"0.1.0-preview.2\",\n    \"@hackmd/diff-match-patch\": \"~1.1.3\",\n    \"@hackmd/imgur\": \"~0.5.0\",\n    \"@hackmd/lz-string\": \"~1.4.4\",\n    \"@hackmd/meta-marked\": \"~0.5.0\",\n    \"@hackmd/pandoc.js\": \"0.3.4\",\n    \"@mattermost/client\": \"^9.2.0\",\n    \"@passport-next/passport-openid\": \"~1.0.0\",\n    \"archiver\": \"^7.0.1\",\n    \"async\": \"^3.2.4\",\n    \"azure-storage\": \"~2.10.3\",\n    \"base64url\": \"~3.0.1\",\n    \"body-parser\": \"^1.20.2\",\n    \"chance\": \"~1.0.18\",\n    \"cheerio\": \"~0.22.0\",\n    \"connect-flash\": \"~0.1.1\",\n    \"connect-session-sequelize\": \"~6.0.0\",\n    \"cookie\": \"~0.4.0\",\n    \"cookie-parser\": \"~1.4.4\",\n    \"core-js\": \"^3.36.0\",\n    \"csurf\": \"~1.11.0\",\n    \"deep-freeze\": \"~0.0.1\",\n    \"ejs\": \"~2.6.2\",\n    \"express\": \"^4.18.2\",\n    \"express-session\": \"~1.16.2\",\n    \"formidable\": \"^2.1.1\",\n    \"helmet\": \"~3.20.0\",\n    \"https-proxy-agent\": \"^3.0.1\",\n    \"i18n\": \"^0.15.1\",\n    \"image-type\": \"^4.1.0\",\n    \"isomorphic-fetch\": \"~2.2.1\",\n    \"jsdom-nogyp\": \"~0.8.3\",\n    \"lodash\": \"^4.17.21\",\n    \"lutim\": \"~1.0.2\",\n    \"markdown-it\": \"~10.0.0\",\n    \"markdown-pdf\": \"~9.0.0\",\n    \"method-override\": \"~3.0.0\",\n    \"minimist\": \"^1.2.8\",\n    \"minio\": \"^7.1.1\",\n    \"moment\": \"^2.29.4\",\n    \"morgan\": \"~1.9.1\",\n    \"mysql\": \"^2.18.1\",\n    \"mysql2\": \"^2.0.1\",\n    \"passport\": \"^0.6.0\",\n    \"passport-bitbucket-oauth2\": \"~0.1.2\",\n    \"passport-dropbox-oauth2\": \"~1.1.0\",\n    \"passport-facebook\": \"~2.1.1\",\n    \"passport-github\": \"~1.1.0\",\n    \"passport-gitlab2\": \"~4.0.0\",\n    \"passport-google-oauth20\": \"~1.0.0\",\n    \"passport-ldapauth\": \"~2.1.3\",\n    \"passport-local\": \"~1.0.0\",\n    \"passport-oauth2\": \"^1.6.1\",\n    \"passport-saml\": \"~1.0.0\",\n    \"passport-twitter\": \"~1.0.4\",\n    \"passport.socketio\": \"~3.7.0\",\n    \"pg\": \"~8.8.0\",\n    \"pg-hstore\": \"~2.3.2\",\n    \"prom-client\": \"^11.0.0\",\n    \"prometheus-api-metrics\": \"^2.2.5\",\n    \"randomcolor\": \"~0.5.4\",\n    \"read-chunk\": \"^3.2.0\",\n    \"readline-sync\": \"~1.4.7\",\n    \"regenerator-runtime\": \"^0.14.0\",\n    \"request\": \"~2.88.0\",\n    \"scrypt-kdf\": \"^2.0.1\",\n    \"sequelize\": \"5.21.13\",\n    \"sequelize-cli\": \"~5.5.1\",\n    \"shortid\": \"~2.2.14\",\n    \"socket.io\": \"~2.2.0\",\n    \"toobusy-js\": \"~0.5.1\",\n    \"uuid\": \"~3.3.2\",\n    \"validator\": \"~11.1.0\",\n    \"winston\": \"^3.8.2\",\n    \"ws\": \"~7.1.1\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.24.0\",\n    \"@babel/plugin-transform-nullish-coalescing-operator\": \"^7.27.1\",\n    \"@babel/plugin-transform-optional-chaining\": \"^7.24.0\",\n    \"@babel/plugin-transform-runtime\": \"^7.24.0\",\n    \"@babel/preset-env\": \"^7.24.0\",\n    \"@babel/runtime\": \"^7.24.0\",\n    \"@babel/runtime-corejs3\": \"^7.28.2\",\n    \"@hackmd/codemirror\": \"^5.65.8\",\n    \"@hackmd/emojify.js\": \"^2.1.0\",\n    \"@hackmd/idle-js\": \"~1.0.1\",\n    \"@hackmd/js-sequence-diagrams\": \"~0.0.1-alpha.3\",\n    \"@susisu/mte-kernel\": \"^2.1.0\",\n    \"acorn\": \"~6.1.1\",\n    \"babel-loader\": \"^8.3.0\",\n    \"bootstrap\": \"~3.4.0\",\n    \"bootstrap-validator\": \"~0.11.8\",\n    \"copy-webpack-plugin\": \"~4.5.2\",\n    \"cross-env\": \"^7.0.3\",\n    \"css-loader\": \"~1.0.0\",\n    \"dictionary-de\": \"^2.0.3\",\n    \"dictionary-de-at\": \"^2.0.3\",\n    \"dictionary-de-ch\": \"^2.0.3\",\n    \"dictionary-en-gb\": \"^2.2.2\",\n    \"doctoc\": \"~1.4.0\",\n    \"ejs-loader\": \"^0.5.0\",\n    \"exports-loader\": \"~0.7.0\",\n    \"expose-loader\": \"~0.7.5\",\n    \"file-loader\": \"~2.0.0\",\n    \"file-saver\": \"~2.0.2\",\n    \"flowchart.js\": \"~1.15.0\",\n    \"fork-awesome\": \"~1.1.7\",\n    \"gist-embed\": \"~2.6.0\",\n    \"graceful-fs\": \"~4.2.1\",\n    \"handlebars\": \"^4.7.7\",\n    \"highlight.js\": \"~9.15.9\",\n    \"html-webpack-plugin\": \"~4.0.0-beta.2\",\n    \"imports-loader\": \"~0.8.0\",\n    \"intelli-espower-loader\": \"~1.0.1\",\n    \"ionicons\": \"~2.0.1\",\n    \"jquery\": \"^3.6.3\",\n    \"jquery-mousewheel\": \"~3.1.13\",\n    \"jquery-ui\": \"^1.13.2\",\n    \"js-cookie\": \"~2.2.0\",\n    \"js-yaml\": \"~3.13.1\",\n    \"jsonlint\": \"~1.6.2\",\n    \"keymaster\": \"~1.6.2\",\n    \"leaflet\": \"~1.6.0\",\n    \"less\": \"~3.9.0\",\n    \"less-loader\": \"~4.1.0\",\n    \"list.js\": \"~1.5.0\",\n    \"markdown-it-abbr\": \"~1.0.4\",\n    \"markdown-it-container\": \"~2.0.0\",\n    \"markdown-it-deflist\": \"~2.0.3\",\n    \"markdown-it-footnote\": \"~3.0.2\",\n    \"markdown-it-imsize\": \"~2.0.1\",\n    \"markdown-it-ins\": \"~2.0.0\",\n    \"markdown-it-mark\": \"~2.0.0\",\n    \"markdown-it-mathjax\": \"~2.0.0\",\n    \"markdown-it-regexp\": \"~0.4.0\",\n    \"markdown-it-ruby\": \"^0.1.1\",\n    \"markdown-it-sub\": \"~1.0.0\",\n    \"markdown-it-sup\": \"~1.0.0\",\n    \"markdownlint\": \"^0.27.0\",\n    \"markdownlint-rule-helpers\": \"^0.13.0\",\n    \"markmap-common\": \"0.18.9\",\n    \"markmap-lib\": \"0.18.12\",\n    \"markmap-view\": \"0.18.12\",\n    \"mathjax\": \"~2.7.5\",\n    \"mermaid\": \"~11.5.0\",\n    \"mini-css-extract-plugin\": \"~0.4.1\",\n    \"mocha\": \"~5.2.0\",\n    \"mock-require\": \"~3.0.3\",\n    \"nyc\": \"~14.0.0\",\n    \"optimize-css-assets-webpack-plugin\": \"~5.0.0\",\n    \"papaparse\": \"^5.2.0\",\n    \"pdfobject\": \"~2.2.4\",\n    \"plantuml-encoder\": \"^1.2.5\",\n    \"power-assert\": \"~1.6.1\",\n    \"prismjs\": \"^1.29.0\",\n    \"raphael\": \"~2.2.8\",\n    \"reveal.js\": \"~3.9.2\",\n    \"script-loader\": \"~0.7.2\",\n    \"select2\": \"~3.5.2-browserify\",\n    \"sinon\": \"~7.3.2\",\n    \"socket.io-client\": \"~2.2.0\",\n    \"spin.js\": \"~4.0.0\",\n    \"standard\": \"~13.1.0\",\n    \"store\": \"~2.0.12\",\n    \"string-loader\": \"~0.0.1\",\n    \"style-loader\": \"~0.23.1\",\n    \"tedious\": \"~6.2.0\",\n    \"turndown\": \"^7.1.1\",\n    \"typo-js\": \"^1.0.3\",\n    \"url-loader\": \"~1.0.1\",\n    \"vega\": \"^5.25.0\",\n    \"vega-embed\": \"~6.14.2\",\n    \"vega-lite\": \"~4.17.0\",\n    \"velocity-animate\": \"~1.5.2\",\n    \"visibilityjs\": \"~2.0.2\",\n    \"viz.js\": \"~2.1.2\",\n    \"webpack\": \"~4.39.0\",\n    \"webpack-cli\": \"~3.3.6\",\n    \"webpack-merge\": \"~4.2.1\",\n    \"webpack-parallel-uglify-plugin\": \"~1.1.0\",\n    \"wurl\": \"~2.5.3\",\n    \"xss\": \"~1.0.6\"\n  },\n  \"optionalDependencies\": {\n    \"bufferutil\": \"~4.0.0\",\n    \"utf-8-validate\": \"~5.0.1\"\n  },\n  \"engines\": {\n    \"node\": \">=14.0.0 <17.0.0\"\n  },\n  \"maintainers\": [\n    {\n      \"name\": \"Max Wu\",\n      \"email\": \"max@hackmd.io\"\n    },\n    {\n      \"name\": \"Yukai Huang\",\n      \"email\": \"yukai@hackmd.io\"\n    }\n  ],\n  \"standard\": {\n    \"ignore\": [\n      \"/public/build\",\n      \"/public/vendor\",\n      \"/lib/ot\",\n      \"webpack.*\"\n    ]\n  },\n  \"nyc\": {\n    \"all\": true,\n    \"include\": [\n      \"app.js\",\n      \"lib/**/*.js\"\n    ],\n    \"reporter\": \"lcov\"\n  }\n}\n"
  },
  {
    "path": "public/.eslintrc.js",
    "content": "// this config file is used in concert with the root .eslintrc.js in the root dir.\nmodule.exports = {\n  \"env\": {\n    \"browser\": true,\n    \"es6\": true\n  },\n  \"parserOptions\": {\n    \"ecmaVersion\": 2018,\n    \"sourceType\": \"module\"\n  },\n  \"globals\": {\n    \"$\": false,\n    \"CodeMirror\": false,\n    \"Cookies\": false,\n    \"moment\": false,\n    \"editor\": false,\n    \"ui\": false,\n    \"modeType\": false,\n    \"serverurl\": false,\n    \"key\": false,\n    \"gapi\": false,\n    \"Dropbox\": false,\n    \"FilePicker\": false,\n    \"ot\": false,\n    \"MediaUploader\": false,\n    \"hex2rgb\": false,\n    \"num_loaded\": false,\n    \"Visibility\": false,\n    \"inlineAttachment\": false\n  },\n  \"rules\": {\n    \"no-unused-vars\": \"warn\"\n  }\n};\n"
  },
  {
    "path": "public/css/bootstrap-social.css",
    "content": "/*\n * Social Buttons for Bootstrap\n *\n * Copyright 2013-2014 Panayiotis Lipiridis\n * Licensed under the MIT License\n *\n * https://github.com/lipis/bootstrap-social\n */\n\n.btn-social{position:relative;padding-left:44px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.btn-social>:first-child{position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)}\n.btn-social.btn-lg{padding-left:61px}.btn-social.btn-lg :first-child{line-height:45px;width:45px;font-size:1.8em}\n.btn-social.btn-sm{padding-left:38px}.btn-social.btn-sm :first-child{line-height:28px;width:28px;font-size:1.4em}\n.btn-social.btn-xs{padding-left:30px}.btn-social.btn-xs :first-child{line-height:20px;width:20px;font-size:1.2em}\n.btn-social-icon{position:relative;padding-left:44px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:34px;width:34px;padding:0}.btn-social-icon>:first-child{position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)}\n.btn-social-icon.btn-lg{padding-left:61px}.btn-social-icon.btn-lg :first-child{line-height:45px;width:45px;font-size:1.8em}\n.btn-social-icon.btn-sm{padding-left:38px}.btn-social-icon.btn-sm :first-child{line-height:28px;width:28px;font-size:1.4em}\n.btn-social-icon.btn-xs{padding-left:30px}.btn-social-icon.btn-xs :first-child{line-height:20px;width:20px;font-size:1.2em}\n.btn-social-icon :first-child{border:none;text-align:center;width:100% !important}\n.btn-social-icon.btn-lg{height:45px;width:45px;padding-left:0;padding-right:0}\n.btn-social-icon.btn-sm{height:30px;width:30px;padding-left:0;padding-right:0}\n.btn-social-icon.btn-xs{height:22px;width:22px;padding-left:0;padding-right:0}\n.btn-adn{color:#fff;background-color:#d87a68;border-color:rgba(0,0,0,0.2)}.btn-adn:hover,.btn-adn:focus,.btn-adn:active,.btn-adn.active,.open>.dropdown-toggle.btn-adn{color:#fff;background-color:#ce563f;border-color:rgba(0,0,0,0.2)}\n.btn-adn:active,.btn-adn.active,.open>.dropdown-toggle.btn-adn{background-image:none}\n.btn-adn.disabled,.btn-adn[disabled],fieldset[disabled] .btn-adn,.btn-adn.disabled:hover,.btn-adn[disabled]:hover,fieldset[disabled] .btn-adn:hover,.btn-adn.disabled:focus,.btn-adn[disabled]:focus,fieldset[disabled] .btn-adn:focus,.btn-adn.disabled:active,.btn-adn[disabled]:active,fieldset[disabled] .btn-adn:active,.btn-adn.disabled.active,.btn-adn[disabled].active,fieldset[disabled] .btn-adn.active{background-color:#d87a68;border-color:rgba(0,0,0,0.2)}\n.btn-adn .badge{color:#d87a68;background-color:#fff}\n.btn-bitbucket{color:#fff;background-color:#205081;border-color:rgba(0,0,0,0.2)}.btn-bitbucket:hover,.btn-bitbucket:focus,.btn-bitbucket:active,.btn-bitbucket.active,.open>.dropdown-toggle.btn-bitbucket{color:#fff;background-color:#163758;border-color:rgba(0,0,0,0.2)}\n.btn-bitbucket:active,.btn-bitbucket.active,.open>.dropdown-toggle.btn-bitbucket{background-image:none}\n.btn-bitbucket.disabled,.btn-bitbucket[disabled],fieldset[disabled] .btn-bitbucket,.btn-bitbucket.disabled:hover,.btn-bitbucket[disabled]:hover,fieldset[disabled] .btn-bitbucket:hover,.btn-bitbucket.disabled:focus,.btn-bitbucket[disabled]:focus,fieldset[disabled] .btn-bitbucket:focus,.btn-bitbucket.disabled:active,.btn-bitbucket[disabled]:active,fieldset[disabled] .btn-bitbucket:active,.btn-bitbucket.disabled.active,.btn-bitbucket[disabled].active,fieldset[disabled] .btn-bitbucket.active{background-color:#205081;border-color:rgba(0,0,0,0.2)}\n.btn-bitbucket .badge{color:#205081;background-color:#fff}\n.btn-dropbox{color:#fff;background-color:#1087dd;border-color:rgba(0,0,0,0.2)}.btn-dropbox:hover,.btn-dropbox:focus,.btn-dropbox:active,.btn-dropbox.active,.open>.dropdown-toggle.btn-dropbox{color:#fff;background-color:#0d6aad;border-color:rgba(0,0,0,0.2)}\n.btn-dropbox:active,.btn-dropbox.active,.open>.dropdown-toggle.btn-dropbox{background-image:none}\n.btn-dropbox.disabled,.btn-dropbox[disabled],fieldset[disabled] .btn-dropbox,.btn-dropbox.disabled:hover,.btn-dropbox[disabled]:hover,fieldset[disabled] .btn-dropbox:hover,.btn-dropbox.disabled:focus,.btn-dropbox[disabled]:focus,fieldset[disabled] .btn-dropbox:focus,.btn-dropbox.disabled:active,.btn-dropbox[disabled]:active,fieldset[disabled] .btn-dropbox:active,.btn-dropbox.disabled.active,.btn-dropbox[disabled].active,fieldset[disabled] .btn-dropbox.active{background-color:#1087dd;border-color:rgba(0,0,0,0.2)}\n.btn-dropbox .badge{color:#1087dd;background-color:#fff}\n.btn-facebook{color:#fff;background-color:#3b5998;border-color:rgba(0,0,0,0.2)}.btn-facebook:hover,.btn-facebook:focus,.btn-facebook:active,.btn-facebook.active,.open>.dropdown-toggle.btn-facebook{color:#fff;background-color:#2d4373;border-color:rgba(0,0,0,0.2)}\n.btn-facebook:active,.btn-facebook.active,.open>.dropdown-toggle.btn-facebook{background-image:none}\n.btn-facebook.disabled,.btn-facebook[disabled],fieldset[disabled] .btn-facebook,.btn-facebook.disabled:hover,.btn-facebook[disabled]:hover,fieldset[disabled] .btn-facebook:hover,.btn-facebook.disabled:focus,.btn-facebook[disabled]:focus,fieldset[disabled] .btn-facebook:focus,.btn-facebook.disabled:active,.btn-facebook[disabled]:active,fieldset[disabled] .btn-facebook:active,.btn-facebook.disabled.active,.btn-facebook[disabled].active,fieldset[disabled] .btn-facebook.active{background-color:#3b5998;border-color:rgba(0,0,0,0.2)}\n.btn-facebook .badge{color:#3b5998;background-color:#fff}\n.btn-flickr{color:#fff;background-color:#ff0084;border-color:rgba(0,0,0,0.2)}.btn-flickr:hover,.btn-flickr:focus,.btn-flickr:active,.btn-flickr.active,.open>.dropdown-toggle.btn-flickr{color:#fff;background-color:#cc006a;border-color:rgba(0,0,0,0.2)}\n.btn-flickr:active,.btn-flickr.active,.open>.dropdown-toggle.btn-flickr{background-image:none}\n.btn-flickr.disabled,.btn-flickr[disabled],fieldset[disabled] .btn-flickr,.btn-flickr.disabled:hover,.btn-flickr[disabled]:hover,fieldset[disabled] .btn-flickr:hover,.btn-flickr.disabled:focus,.btn-flickr[disabled]:focus,fieldset[disabled] .btn-flickr:focus,.btn-flickr.disabled:active,.btn-flickr[disabled]:active,fieldset[disabled] .btn-flickr:active,.btn-flickr.disabled.active,.btn-flickr[disabled].active,fieldset[disabled] .btn-flickr.active{background-color:#ff0084;border-color:rgba(0,0,0,0.2)}\n.btn-flickr .badge{color:#ff0084;background-color:#fff}\n.btn-foursquare{color:#fff;background-color:#f94877;border-color:rgba(0,0,0,0.2)}.btn-foursquare:hover,.btn-foursquare:focus,.btn-foursquare:active,.btn-foursquare.active,.open>.dropdown-toggle.btn-foursquare{color:#fff;background-color:#f71752;border-color:rgba(0,0,0,0.2)}\n.btn-foursquare:active,.btn-foursquare.active,.open>.dropdown-toggle.btn-foursquare{background-image:none}\n.btn-foursquare.disabled,.btn-foursquare[disabled],fieldset[disabled] .btn-foursquare,.btn-foursquare.disabled:hover,.btn-foursquare[disabled]:hover,fieldset[disabled] .btn-foursquare:hover,.btn-foursquare.disabled:focus,.btn-foursquare[disabled]:focus,fieldset[disabled] .btn-foursquare:focus,.btn-foursquare.disabled:active,.btn-foursquare[disabled]:active,fieldset[disabled] .btn-foursquare:active,.btn-foursquare.disabled.active,.btn-foursquare[disabled].active,fieldset[disabled] .btn-foursquare.active{background-color:#f94877;border-color:rgba(0,0,0,0.2)}\n.btn-foursquare .badge{color:#f94877;background-color:#fff}\n.btn-github{color:#fff;background-color:#444;border-color:rgba(0,0,0,0.2)}.btn-github:hover,.btn-github:focus,.btn-github:active,.btn-github.active,.open>.dropdown-toggle.btn-github{color:#fff;background-color:#2b2b2b;border-color:rgba(0,0,0,0.2)}\n.btn-github:active,.btn-github.active,.open>.dropdown-toggle.btn-github{background-image:none}\n.btn-github.disabled,.btn-github[disabled],fieldset[disabled] .btn-github,.btn-github.disabled:hover,.btn-github[disabled]:hover,fieldset[disabled] .btn-github:hover,.btn-github.disabled:focus,.btn-github[disabled]:focus,fieldset[disabled] .btn-github:focus,.btn-github.disabled:active,.btn-github[disabled]:active,fieldset[disabled] .btn-github:active,.btn-github.disabled.active,.btn-github[disabled].active,fieldset[disabled] .btn-github.active{background-color:#444;border-color:rgba(0,0,0,0.2)}\n.btn-github .badge{color:#444;background-color:#fff}\n.btn-google{color:#fff;background-color:#dd4b39;border-color:rgba(0,0,0,0.2)}.btn-google:hover,.btn-google:focus,.btn-google:active,.btn-google.active,.open>.dropdown-toggle.btn-google{color:#fff;background-color:#c23321;border-color:rgba(0,0,0,0.2)}\n.btn-google:active,.btn-google.active,.open>.dropdown-toggle.btn-google{background-image:none}\n.btn-google.disabled,.btn-google[disabled],fieldset[disabled] .btn-google,.btn-google.disabled:hover,.btn-google[disabled]:hover,fieldset[disabled] .btn-google:hover,.btn-google.disabled:focus,.btn-google[disabled]:focus,fieldset[disabled] .btn-google:focus,.btn-google.disabled:active,.btn-google[disabled]:active,fieldset[disabled] .btn-google:active,.btn-google.disabled.active,.btn-google[disabled].active,fieldset[disabled] .btn-google.active{background-color:#dd4b39;border-color:rgba(0,0,0,0.2)}\n.btn-google .badge{color:#dd4b39;background-color:#fff}\n.btn-instagram{color:#fff;background-color:#3f729b;border-color:rgba(0,0,0,0.2)}.btn-instagram:hover,.btn-instagram:focus,.btn-instagram:active,.btn-instagram.active,.open>.dropdown-toggle.btn-instagram{color:#fff;background-color:#305777;border-color:rgba(0,0,0,0.2)}\n.btn-instagram:active,.btn-instagram.active,.open>.dropdown-toggle.btn-instagram{background-image:none}\n.btn-instagram.disabled,.btn-instagram[disabled],fieldset[disabled] .btn-instagram,.btn-instagram.disabled:hover,.btn-instagram[disabled]:hover,fieldset[disabled] .btn-instagram:hover,.btn-instagram.disabled:focus,.btn-instagram[disabled]:focus,fieldset[disabled] .btn-instagram:focus,.btn-instagram.disabled:active,.btn-instagram[disabled]:active,fieldset[disabled] .btn-instagram:active,.btn-instagram.disabled.active,.btn-instagram[disabled].active,fieldset[disabled] .btn-instagram.active{background-color:#3f729b;border-color:rgba(0,0,0,0.2)}\n.btn-instagram .badge{color:#3f729b;background-color:#fff}\n.btn-linkedin{color:#fff;background-color:#007bb6;border-color:rgba(0,0,0,0.2)}.btn-linkedin:hover,.btn-linkedin:focus,.btn-linkedin:active,.btn-linkedin.active,.open>.dropdown-toggle.btn-linkedin{color:#fff;background-color:#005983;border-color:rgba(0,0,0,0.2)}\n.btn-linkedin:active,.btn-linkedin.active,.open>.dropdown-toggle.btn-linkedin{background-image:none}\n.btn-linkedin.disabled,.btn-linkedin[disabled],fieldset[disabled] .btn-linkedin,.btn-linkedin.disabled:hover,.btn-linkedin[disabled]:hover,fieldset[disabled] .btn-linkedin:hover,.btn-linkedin.disabled:focus,.btn-linkedin[disabled]:focus,fieldset[disabled] .btn-linkedin:focus,.btn-linkedin.disabled:active,.btn-linkedin[disabled]:active,fieldset[disabled] .btn-linkedin:active,.btn-linkedin.disabled.active,.btn-linkedin[disabled].active,fieldset[disabled] .btn-linkedin.active{background-color:#007bb6;border-color:rgba(0,0,0,0.2)}\n.btn-linkedin .badge{color:#007bb6;background-color:#fff}\n.btn-microsoft{color:#fff;background-color:#2672ec;border-color:rgba(0,0,0,0.2)}.btn-microsoft:hover,.btn-microsoft:focus,.btn-microsoft:active,.btn-microsoft.active,.open>.dropdown-toggle.btn-microsoft{color:#fff;background-color:#125acd;border-color:rgba(0,0,0,0.2)}\n.btn-microsoft:active,.btn-microsoft.active,.open>.dropdown-toggle.btn-microsoft{background-image:none}\n.btn-microsoft.disabled,.btn-microsoft[disabled],fieldset[disabled] .btn-microsoft,.btn-microsoft.disabled:hover,.btn-microsoft[disabled]:hover,fieldset[disabled] .btn-microsoft:hover,.btn-microsoft.disabled:focus,.btn-microsoft[disabled]:focus,fieldset[disabled] .btn-microsoft:focus,.btn-microsoft.disabled:active,.btn-microsoft[disabled]:active,fieldset[disabled] .btn-microsoft:active,.btn-microsoft.disabled.active,.btn-microsoft[disabled].active,fieldset[disabled] .btn-microsoft.active{background-color:#2672ec;border-color:rgba(0,0,0,0.2)}\n.btn-microsoft .badge{color:#2672ec;background-color:#fff}\n.btn-openid{color:#fff;background-color:#f7931e;border-color:rgba(0,0,0,0.2)}.btn-openid:hover,.btn-openid:focus,.btn-openid:active,.btn-openid.active,.open>.dropdown-toggle.btn-openid{color:#fff;background-color:#da7908;border-color:rgba(0,0,0,0.2)}\n.btn-openid:active,.btn-openid.active,.open>.dropdown-toggle.btn-openid{background-image:none}\n.btn-openid.disabled,.btn-openid[disabled],fieldset[disabled] .btn-openid,.btn-openid.disabled:hover,.btn-openid[disabled]:hover,fieldset[disabled] .btn-openid:hover,.btn-openid.disabled:focus,.btn-openid[disabled]:focus,fieldset[disabled] .btn-openid:focus,.btn-openid.disabled:active,.btn-openid[disabled]:active,fieldset[disabled] .btn-openid:active,.btn-openid.disabled.active,.btn-openid[disabled].active,fieldset[disabled] .btn-openid.active{background-color:#f7931e;border-color:rgba(0,0,0,0.2)}\n.btn-openid .badge{color:#f7931e;background-color:#fff}\n.btn-pinterest{color:#fff;background-color:#cb2027;border-color:rgba(0,0,0,0.2)}.btn-pinterest:hover,.btn-pinterest:focus,.btn-pinterest:active,.btn-pinterest.active,.open>.dropdown-toggle.btn-pinterest{color:#fff;background-color:#9f191f;border-color:rgba(0,0,0,0.2)}\n.btn-pinterest:active,.btn-pinterest.active,.open>.dropdown-toggle.btn-pinterest{background-image:none}\n.btn-pinterest.disabled,.btn-pinterest[disabled],fieldset[disabled] .btn-pinterest,.btn-pinterest.disabled:hover,.btn-pinterest[disabled]:hover,fieldset[disabled] .btn-pinterest:hover,.btn-pinterest.disabled:focus,.btn-pinterest[disabled]:focus,fieldset[disabled] .btn-pinterest:focus,.btn-pinterest.disabled:active,.btn-pinterest[disabled]:active,fieldset[disabled] .btn-pinterest:active,.btn-pinterest.disabled.active,.btn-pinterest[disabled].active,fieldset[disabled] .btn-pinterest.active{background-color:#cb2027;border-color:rgba(0,0,0,0.2)}\n.btn-pinterest .badge{color:#cb2027;background-color:#fff}\n.btn-reddit{color:#000;background-color:#eff7ff;border-color:rgba(0,0,0,0.2)}.btn-reddit:hover,.btn-reddit:focus,.btn-reddit:active,.btn-reddit.active,.open>.dropdown-toggle.btn-reddit{color:#000;background-color:#bcddff;border-color:rgba(0,0,0,0.2)}\n.btn-reddit:active,.btn-reddit.active,.open>.dropdown-toggle.btn-reddit{background-image:none}\n.btn-reddit.disabled,.btn-reddit[disabled],fieldset[disabled] .btn-reddit,.btn-reddit.disabled:hover,.btn-reddit[disabled]:hover,fieldset[disabled] .btn-reddit:hover,.btn-reddit.disabled:focus,.btn-reddit[disabled]:focus,fieldset[disabled] .btn-reddit:focus,.btn-reddit.disabled:active,.btn-reddit[disabled]:active,fieldset[disabled] .btn-reddit:active,.btn-reddit.disabled.active,.btn-reddit[disabled].active,fieldset[disabled] .btn-reddit.active{background-color:#eff7ff;border-color:rgba(0,0,0,0.2)}\n.btn-reddit .badge{color:#eff7ff;background-color:#000}\n.btn-soundcloud{color:#fff;background-color:#f50;border-color:rgba(0,0,0,0.2)}.btn-soundcloud:hover,.btn-soundcloud:focus,.btn-soundcloud:active,.btn-soundcloud.active,.open>.dropdown-toggle.btn-soundcloud{color:#fff;background-color:#c40;border-color:rgba(0,0,0,0.2)}\n.btn-soundcloud:active,.btn-soundcloud.active,.open>.dropdown-toggle.btn-soundcloud{background-image:none}\n.btn-soundcloud.disabled,.btn-soundcloud[disabled],fieldset[disabled] .btn-soundcloud,.btn-soundcloud.disabled:hover,.btn-soundcloud[disabled]:hover,fieldset[disabled] .btn-soundcloud:hover,.btn-soundcloud.disabled:focus,.btn-soundcloud[disabled]:focus,fieldset[disabled] .btn-soundcloud:focus,.btn-soundcloud.disabled:active,.btn-soundcloud[disabled]:active,fieldset[disabled] .btn-soundcloud:active,.btn-soundcloud.disabled.active,.btn-soundcloud[disabled].active,fieldset[disabled] .btn-soundcloud.active{background-color:#f50;border-color:rgba(0,0,0,0.2)}\n.btn-soundcloud .badge{color:#f50;background-color:#fff}\n.btn-tumblr{color:#fff;background-color:#2c4762;border-color:rgba(0,0,0,0.2)}.btn-tumblr:hover,.btn-tumblr:focus,.btn-tumblr:active,.btn-tumblr.active,.open>.dropdown-toggle.btn-tumblr{color:#fff;background-color:#1c2d3f;border-color:rgba(0,0,0,0.2)}\n.btn-tumblr:active,.btn-tumblr.active,.open>.dropdown-toggle.btn-tumblr{background-image:none}\n.btn-tumblr.disabled,.btn-tumblr[disabled],fieldset[disabled] .btn-tumblr,.btn-tumblr.disabled:hover,.btn-tumblr[disabled]:hover,fieldset[disabled] .btn-tumblr:hover,.btn-tumblr.disabled:focus,.btn-tumblr[disabled]:focus,fieldset[disabled] .btn-tumblr:focus,.btn-tumblr.disabled:active,.btn-tumblr[disabled]:active,fieldset[disabled] .btn-tumblr:active,.btn-tumblr.disabled.active,.btn-tumblr[disabled].active,fieldset[disabled] .btn-tumblr.active{background-color:#2c4762;border-color:rgba(0,0,0,0.2)}\n.btn-tumblr .badge{color:#2c4762;background-color:#fff}\n.btn-twitter{color:#fff;background-color:#55acee;border-color:rgba(0,0,0,0.2)}.btn-twitter:hover,.btn-twitter:focus,.btn-twitter:active,.btn-twitter.active,.open>.dropdown-toggle.btn-twitter{color:#fff;background-color:#2795e9;border-color:rgba(0,0,0,0.2)}\n.btn-twitter:active,.btn-twitter.active,.open>.dropdown-toggle.btn-twitter{background-image:none}\n.btn-twitter.disabled,.btn-twitter[disabled],fieldset[disabled] .btn-twitter,.btn-twitter.disabled:hover,.btn-twitter[disabled]:hover,fieldset[disabled] .btn-twitter:hover,.btn-twitter.disabled:focus,.btn-twitter[disabled]:focus,fieldset[disabled] .btn-twitter:focus,.btn-twitter.disabled:active,.btn-twitter[disabled]:active,fieldset[disabled] .btn-twitter:active,.btn-twitter.disabled.active,.btn-twitter[disabled].active,fieldset[disabled] .btn-twitter.active{background-color:#55acee;border-color:rgba(0,0,0,0.2)}\n.btn-twitter .badge{color:#55acee;background-color:#fff}\n.btn-vimeo{color:#fff;background-color:#1ab7ea;border-color:rgba(0,0,0,0.2)}.btn-vimeo:hover,.btn-vimeo:focus,.btn-vimeo:active,.btn-vimeo.active,.open>.dropdown-toggle.btn-vimeo{color:#fff;background-color:#1295bf;border-color:rgba(0,0,0,0.2)}\n.btn-vimeo:active,.btn-vimeo.active,.open>.dropdown-toggle.btn-vimeo{background-image:none}\n.btn-vimeo.disabled,.btn-vimeo[disabled],fieldset[disabled] .btn-vimeo,.btn-vimeo.disabled:hover,.btn-vimeo[disabled]:hover,fieldset[disabled] .btn-vimeo:hover,.btn-vimeo.disabled:focus,.btn-vimeo[disabled]:focus,fieldset[disabled] .btn-vimeo:focus,.btn-vimeo.disabled:active,.btn-vimeo[disabled]:active,fieldset[disabled] .btn-vimeo:active,.btn-vimeo.disabled.active,.btn-vimeo[disabled].active,fieldset[disabled] .btn-vimeo.active{background-color:#1ab7ea;border-color:rgba(0,0,0,0.2)}\n.btn-vimeo .badge{color:#1ab7ea;background-color:#fff}\n.btn-vk{color:#fff;background-color:#587ea3;border-color:rgba(0,0,0,0.2)}.btn-vk:hover,.btn-vk:focus,.btn-vk:active,.btn-vk.active,.open>.dropdown-toggle.btn-vk{color:#fff;background-color:#466482;border-color:rgba(0,0,0,0.2)}\n.btn-vk:active,.btn-vk.active,.open>.dropdown-toggle.btn-vk{background-image:none}\n.btn-vk.disabled,.btn-vk[disabled],fieldset[disabled] .btn-vk,.btn-vk.disabled:hover,.btn-vk[disabled]:hover,fieldset[disabled] .btn-vk:hover,.btn-vk.disabled:focus,.btn-vk[disabled]:focus,fieldset[disabled] .btn-vk:focus,.btn-vk.disabled:active,.btn-vk[disabled]:active,fieldset[disabled] .btn-vk:active,.btn-vk.disabled.active,.btn-vk[disabled].active,fieldset[disabled] .btn-vk.active{background-color:#587ea3;border-color:rgba(0,0,0,0.2)}\n.btn-vk .badge{color:#587ea3;background-color:#fff}\n.btn-yahoo{color:#fff;background-color:#720e9e;border-color:rgba(0,0,0,0.2)}.btn-yahoo:hover,.btn-yahoo:focus,.btn-yahoo:active,.btn-yahoo.active,.open>.dropdown-toggle.btn-yahoo{color:#fff;background-color:#500a6f;border-color:rgba(0,0,0,0.2)}\n.btn-yahoo:active,.btn-yahoo.active,.open>.dropdown-toggle.btn-yahoo{background-image:none}\n.btn-yahoo.disabled,.btn-yahoo[disabled],fieldset[disabled] .btn-yahoo,.btn-yahoo.disabled:hover,.btn-yahoo[disabled]:hover,fieldset[disabled] .btn-yahoo:hover,.btn-yahoo.disabled:focus,.btn-yahoo[disabled]:focus,fieldset[disabled] .btn-yahoo:focus,.btn-yahoo.disabled:active,.btn-yahoo[disabled]:active,fieldset[disabled] .btn-yahoo:active,.btn-yahoo.disabled.active,.btn-yahoo[disabled].active,fieldset[disabled] .btn-yahoo.active{background-color:#720e9e;border-color:rgba(0,0,0,0.2)}\n.btn-yahoo .badge{color:#720e9e;background-color:#fff}\n"
  },
  {
    "path": "public/css/center.css",
    "content": "html,\nbody,\n.container-fluid {\n    height: 98%;\n}\n.container-fluid {\n    display: table;\n    vertical-align: middle;\n}\n.vertical-center-row {\n    display: table-cell;\n    vertical-align: middle;\n}"
  },
  {
    "path": "public/css/codemirror-extend/ayu-dark.css",
    "content": "/* Based on https://github.com/dempfi/ayu */\n\n.cm-s-ayu-dark.CodeMirror { background: #0a0e14; color: #b3b1ad; }\n.cm-s-ayu-dark div.CodeMirror-selected { background: #273747; }\n.cm-s-ayu-dark .CodeMirror-line::selection, .cm-s-ayu-dark .CodeMirror-line > span::selection, .cm-s-ayu-dark .CodeMirror-line > span > span::selection { background: rgba(39, 55, 71, 99); }\n.cm-s-ayu-dark .CodeMirror-line::-moz-selection, .cm-s-ayu-dark .CodeMirror-line > span::-moz-selection, .cm-s-ayu-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(39, 55, 71, 99); }\n.cm-s-ayu-dark .CodeMirror-gutters { background: #0a0e14; border-right: 0px; }\n.cm-s-ayu-dark .CodeMirror-guttermarker { color: white; }\n.cm-s-ayu-dark .CodeMirror-guttermarker-subtle { color: #3d424d; }\n.cm-s-ayu-dark .CodeMirror-linenumber { color: #3d424d; }\n.cm-s-ayu-dark .CodeMirror-cursor { border-left: 1px solid #e6b450; }\n\n.cm-s-ayu-dark span.cm-comment { color: #626a73; }\n.cm-s-ayu-dark span.cm-atom { color: #ae81ff; }\n.cm-s-ayu-dark span.cm-number { color: #e6b450; }\n\n.cm-s-ayu-dark span.cm-comment.cm-attribute { color: #ffb454; }\n.cm-s-ayu-dark span.cm-comment.cm-def { color: rgba(57, 186, 230, 80); }\n.cm-s-ayu-dark span.cm-comment.cm-tag { color: #39bae6; }\n.cm-s-ayu-dark span.cm-comment.cm-type { color: #5998a6; }\n\n.cm-s-ayu-dark span.cm-property, .cm-s-ayu-dark span.cm-attribute { color: #ffb454; }\n.cm-s-ayu-dark span.cm-keyword { color: #ff8f40; }\n.cm-s-ayu-dark span.cm-builtin { color: #e6b450; }\n.cm-s-ayu-dark span.cm-string { color: #c2d94c; }\n\n.cm-s-ayu-dark span.cm-variable { color: #b3b1ad; }\n.cm-s-ayu-dark span.cm-variable-2 { color: #f07178; }\n.cm-s-ayu-dark span.cm-variable-3 { color: #39bae6; }\n.cm-s-ayu-dark span.cm-type { color: #ff8f40; }\n.cm-s-ayu-dark span.cm-def { color: #ffee99; }\n.cm-s-ayu-dark span.cm-bracket { color: #f8f8f2; }\n.cm-s-ayu-dark span.cm-tag { color: rgba(57, 186, 230, 80); }\n.cm-s-ayu-dark span.cm-header { color: #c2d94c; }\n.cm-s-ayu-dark span.cm-link { color: #39bae6; }\n.cm-s-ayu-dark span.cm-error { color: #ff3333; }\n\n.cm-s-ayu-dark .CodeMirror-activeline-background { background: #01060e; }\n.cm-s-ayu-dark .CodeMirror-matchingbracket {\n  text-decoration: underline;\n  color: white !important;\n}\n"
  },
  {
    "path": "public/css/codemirror-extend/ayu-mirage.css",
    "content": "/* Based on https://github.com/dempfi/ayu */\n\n.cm-s-ayu-mirage.CodeMirror { background: #1f2430; color: #cbccc6; }\n.cm-s-ayu-mirage div.CodeMirror-selected { background: #34455a; }\n.cm-s-ayu-mirage .CodeMirror-line::selection, .cm-s-ayu-mirage .CodeMirror-line > span::selection, .cm-s-ayu-mirage .CodeMirror-line > span > span::selection { background: #34455a; }\n.cm-s-ayu-mirage .CodeMirror-line::-moz-selection, .cm-s-ayu-mirage .CodeMirror-line > span::-moz-selection, .cm-s-ayu-mirage .CodeMirror-line > span > span::-moz-selection { background: rgba(25, 30, 42, 99); }\n.cm-s-ayu-mirage .CodeMirror-gutters { background: #1f2430; border-right: 0px; }\n.cm-s-ayu-mirage .CodeMirror-guttermarker { color: white; }\n.cm-s-ayu-mirage .CodeMirror-guttermarker-subtle { color:  rgba(112, 122, 140, 66); }\n.cm-s-ayu-mirage .CodeMirror-linenumber { color: rgba(61, 66, 77, 99); }\n.cm-s-ayu-mirage .CodeMirror-cursor { border-left: 1px solid #ffcc66; }\n\n.cm-s-ayu-mirage span.cm-comment { color: #5c6773; font-style:italic; }\n.cm-s-ayu-mirage span.cm-atom { color: #ae81ff; }\n.cm-s-ayu-mirage span.cm-number { color: #ffcc66; }\n\n.cm-s-ayu-mirage span.cm-comment.cm-attribute { color: #ffd580; }\n.cm-s-ayu-mirage span.cm-comment.cm-def { color: #d4bfff; }\n.cm-s-ayu-mirage span.cm-comment.cm-tag { color: #5ccfe6; }\n.cm-s-ayu-mirage span.cm-comment.cm-type { color: #5998a6; }\n\n.cm-s-ayu-mirage span.cm-property { color: #f29e74; }\n.cm-s-ayu-mirage span.cm-attribute { color: #ffd580; }\n.cm-s-ayu-mirage span.cm-keyword { color: #ffa759; }\n.cm-s-ayu-mirage span.cm-builtin { color: #ffcc66; }\n.cm-s-ayu-mirage span.cm-string { color: #bae67e; }\n\n.cm-s-ayu-mirage span.cm-variable { color: #cbccc6; }\n.cm-s-ayu-mirage span.cm-variable-2 { color: #f28779; }\n.cm-s-ayu-mirage span.cm-variable-3 { color: #5ccfe6; }\n.cm-s-ayu-mirage span.cm-type { color: #ffa759; }\n.cm-s-ayu-mirage span.cm-def { color: #ffd580; }\n.cm-s-ayu-mirage span.cm-bracket { color: rgba(92, 207, 230, 80); }\n.cm-s-ayu-mirage span.cm-tag { color: #5ccfe6; }\n.cm-s-ayu-mirage span.cm-header { color: #bae67e; }\n.cm-s-ayu-mirage span.cm-link { color: #5ccfe6; }\n.cm-s-ayu-mirage span.cm-error { color: #ff3333; }\n\n.cm-s-ayu-mirage .CodeMirror-activeline-background { background: #191e2a; }\n.cm-s-ayu-mirage .CodeMirror-matchingbracket {\n  text-decoration: underline;\n  color: white !important;\n}\n"
  },
  {
    "path": "public/css/codemirror-extend/one-dark.css",
    "content": ".cm-s-one-dark .CodeMirror-linenumber {\n  color: #676767;\n}\n\n.cm-s-one-dark.CodeMirror-focused\n  .CodeMirror-activeline\n  .CodeMirror-gutter-elt {\n  color: #b0b0b0;\n}\n\n.cm-s-one-dark .cm-comment {\n  color: #818895;\n}\n"
  },
  {
    "path": "public/css/codemirror-extend/tomorrow-night-bright.css",
    "content": "/*\n\n    Name:       Tomorrow Night - Bright\n    Author:     Chris Kempson\n\n    Port done by Gerard Braad <me@gbraad.nl>\n\n*/\n\n.cm-s-tomorrow-night-bright.CodeMirror { background: #000000; color: #eaeaea; }\n.cm-s-tomorrow-night-bright div.CodeMirror-selected { background: #424242; }\n.cm-s-tomorrow-night-bright .CodeMirror-gutters { background: #000000; border-right: 0px; }\n.cm-s-tomorrow-night-bright .CodeMirror-guttermarker { color: #e78c45; }\n.cm-s-tomorrow-night-bright .CodeMirror-guttermarker-subtle { color: #777; }\n.cm-s-tomorrow-night-bright .CodeMirror-linenumber { color: #424242; }\n.cm-s-tomorrow-night-bright .CodeMirror-cursor { border-left: 1px solid #6A6A6A; }\n\n.cm-s-tomorrow-night-bright span.cm-comment { color: #d27b53; }\n.cm-s-tomorrow-night-bright span.cm-atom { color: #a16a94; }\n.cm-s-tomorrow-night-bright span.cm-number { color: #a16a94; }\n\n.cm-s-tomorrow-night-bright span.cm-property, .cm-s-tomorrow-night-bright span.cm-attribute { color: #99cc99; }\n.cm-s-tomorrow-night-bright span.cm-keyword { color: #d54e53; }\n.cm-s-tomorrow-night-bright span.cm-string { color: #e7c547; }\n\n.cm-s-tomorrow-night-bright span.cm-variable { color: #b9ca4a; }\n.cm-s-tomorrow-night-bright span.cm-variable-2 { color: #7aa6da; }\n.cm-s-tomorrow-night-bright span.cm-def { color: #e78c45; }\n.cm-s-tomorrow-night-bright span.cm-bracket { color: #eaeaea; }\n.cm-s-tomorrow-night-bright span.cm-tag { color: #d54e53; }\n.cm-s-tomorrow-night-bright span.cm-link { color: #a16a94; }\n.cm-s-tomorrow-night-bright span.cm-error { background: #d54e53; color: #6A6A6A; }\n\n.cm-s-tomorrow-night-bright .CodeMirror-activeline-background { background: #2a2a2a; }\n.cm-s-tomorrow-night-bright .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }\n"
  },
  {
    "path": "public/css/codemirror-extend/tomorrow-night-eighties.css",
    "content": "/*\n\n    Name:       Tomorrow Night - Eighties\n    Author:     Chris Kempson\n\n    CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)\n    Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)\n\n*/\n\n.cm-s-tomorrow-night-eighties.CodeMirror { background: #000000; color: #CCCCCC; }\n.cm-s-tomorrow-night-eighties div.CodeMirror-selected { background: #2D2D2D; }\n.cm-s-tomorrow-night-eighties .CodeMirror-line::selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span::selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span > span::selection { background: rgba(45, 45, 45, 0.99); }\n.cm-s-tomorrow-night-eighties .CodeMirror-line::-moz-selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span::-moz-selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span > span::-moz-selection { background: rgba(45, 45, 45, 0.99); }\n.cm-s-tomorrow-night-eighties .CodeMirror-gutters { background: #000000; border-right: 0px; }\n.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker { color: #f2777a; }\n.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker-subtle { color: #777; }\n.cm-s-tomorrow-night-eighties .CodeMirror-linenumber { color: #515151; }\n.cm-s-tomorrow-night-eighties .CodeMirror-cursor { border-left: 1px solid #6A6A6A; }\n\n.cm-s-tomorrow-night-eighties span.cm-comment { color: #d27b53; }\n.cm-s-tomorrow-night-eighties span.cm-atom { color: #a16a94; }\n.cm-s-tomorrow-night-eighties span.cm-number { color: #a16a94; }\n\n.cm-s-tomorrow-night-eighties span.cm-property, .cm-s-tomorrow-night-eighties span.cm-attribute { color: #99cc99; }\n.cm-s-tomorrow-night-eighties span.cm-keyword { color: #f2777a; }\n.cm-s-tomorrow-night-eighties span.cm-string { color: #ffcc66; }\n\n.cm-s-tomorrow-night-eighties span.cm-variable { color: #99cc99; }\n.cm-s-tomorrow-night-eighties span.cm-variable-2 { color: #6699cc; }\n.cm-s-tomorrow-night-eighties span.cm-def { color: #f99157; }\n.cm-s-tomorrow-night-eighties span.cm-bracket { color: #CCCCCC; }\n.cm-s-tomorrow-night-eighties span.cm-tag { color: #f2777a; }\n.cm-s-tomorrow-night-eighties span.cm-link { color: #a16a94; }\n.cm-s-tomorrow-night-eighties span.cm-error { background: #f2777a; color: #6A6A6A; }\n\n.cm-s-tomorrow-night-eighties .CodeMirror-activeline-background { background: #343600; }\n.cm-s-tomorrow-night-eighties .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }\n"
  },
  {
    "path": "public/css/cover.css",
    "content": "/*\n * Globals\n */\n\n/* Links */\n\na,\na:focus,\na:hover {\n    color: #fff;\n}\n/* Custom default button */\n\n.btn-default,\n.btn-default:hover,\n.btn-default:focus {\n    color: #333;\n    text-shadow: none;\n    /* Prevent inheritence from `body` */\n    background-color: #fff;\n    border: 1px solid #fff;\n}\n/*\n * Base structure\n */\nhtml {\n    height: 100%;\n}\nhtml,\nbody {\n    background-color: #333;\n}\nbody {\n    min-height: 100%;\n    color: #fff;\n    text-align: center;\n    text-shadow: 0 1px 3px rgba(0, 0, 0, .5);\n}\n/* Extra markup and styles for table-esque vertical and horizontal centering */\n\n.site-wrapper {\n    padding: 10px;\n    display: table;\n    width: 100%;\n    height: 100vh;\n    /* For at least Firefox */\n    min-height: 100%;\n    -webkit-box-shadow: inset 0 0 100px rgba(0, 0, 0, .5);\n    box-shadow: inset 0 0 100px rgba(0, 0, 0, .5);\n}\n.site-wrapper-inner {\n    display: table-cell;\n    vertical-align: middle;\n}\n.cover-container {\n    width: 100%;\n    padding-top: 80px;\n    margin-right: auto;\n    margin-left: auto;\n}\n/* Padding for spacing */\n\n.inner {\n    padding: 10px;\n}\n/*\n * Header\n */\n\n.masthead {\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100%;\n}\n\n.masthead-brand {\n    margin-top: 10px;\n    margin-bottom: 10px;\n}\n.masthead-nav {\n    text-align: left;\n    max-width: 1000px;\n    margin: 0 auto;\n    padding-left: 10px;\n    padding-right: 10px;\n}\n.masthead-nav > li {\n    display: inline-block;\n}\n.masthead-nav > li + li {\n    margin-left: 20px;\n}\n.masthead-nav > li > a {\n    padding-right: 0;\n    padding-left: 0;\n    font-size: 16px;\n    font-weight: bold;\n    color: #fff;\n    /* IE8 proofing */\n    color: rgba(255, 255, 255, .75);\n    border-bottom: 2px solid transparent;\n}\n.masthead-nav > li > a:hover,\n.masthead-nav > li > a:focus {\n    background-color: transparent;\n    border-bottom-color: #a9a9a9;\n    border-bottom-color: rgba(255, 255, 255, .25);\n}\n.masthead-nav > .active > a,\n.masthead-nav > .active > a:hover,\n.masthead-nav > .active > a:focus {\n    color: #fff;\n    border-bottom-color: #fff;\n}\n@media (min-width: 768px) {\n    .masthead-brand {\n        float: left;\n    }\n    .masthead-nav {\n        float: none;\n    }\n    .inner {\n        padding: 30px 25px;\n    }\n}\n/*\n * Cover\n */\n\n.cover {\n    padding: 0 20px;\n}\n.cover .btn-lg {\n    padding: 10px 20px;\n    font-weight: bold;\n}\n/*\n * Footer\n */\n\n.mastfoot {\n    color: #999;\n    /* IE8 proofing */\n    color: rgba(255, 255, 255, .5);\n}\n/*\n * Affix and center\n */\n\n@media (min-width: 768px) {\n    /* Pull out the header and footer */\n    .masthead {\n        position: absolute;\n        top: 0;\n        left: 0;\n        width: 100% !important;\n    }\n    .mastfoot {\n        position: fixed;\n        bottom: 0;\n    }\n    /* Start the vertical centering */\n    .site-wrapper-inner {\n        vertical-align: middle;\n    }\n    /* Handle the widths */\n    .masthead,\n    .mastfoot,\n    .cover-container {\n        width: 100%;\n        /* Must be percentage or pixels for horizontal alignment */\n    }\n}\n@media (min-width: 992px) {\n    .masthead,\n    .mastfoot,\n    .cover-container {\n        width: 1000px;\n    }\n}\n.section ul {\n    list-style: none;\n}\n/* custom */\n\nhtml,\nbody {\n    overflow-x: hidden;\n}\ninput {\n    color: black;\n}\n.mastfoot {\n    position: relative;\n}\n.select2-container-multi .select2-choices .select2-search-field input {\n    font-family: inherit;\n    padding: 5px 12px;\n}\n.select2-container {\n    margin: 0 auto !important;\n}\n.list {\n    width: 100%;\n    padding-left: 0;\n    display: -webkit-inline-flex;\n    display: -moz-inline-flex;\n    display: -ms-inline-flex;\n    display: -o-inline-flex;\n    display: inline-flex;\n    -webkit-flex-direction: row;\n    -moz-flex-direction: row;\n    -ms-flex-direction: row;\n    flex-direction: row;\n    -webkit-flex-flow: row wrap;\n    -moz-flex-flow: row wrap;\n    -ms-flex-flow: row wrap;\n    flex-flow: row wrap;\n    -webkit-justify-content: flex-start;\n    -moz-justify-content: flex-start;\n    -ms-justify-content: flex-start;\n    justify-content: flex-start;\n}\n.list {\n    margin: 20px 0;\n}\n.list li {\n    padding: 0 10px;\n}\n.list li * {\n    word-break: break-word;\n    word-wrap: break-word;\n}\n.list li a {\n    text-decoration: none;\n}\n.list li p {\n    color: gray;\n}\n.list li .item {\n    padding: 5px 25px;\n    margin: 10px 0;\n    background: white;\n    border-radius: 5px;\n    color: black;\n    text-shadow: none;\n    min-height: 134px;\n    display: table;\n    min-width: 100%;\n}\n.list li .item .content {\n    display: table-cell;\n    vertical-align: middle;\n}\n.list li .item .content .tags {\n    line-height: 25px;\n}\n.list li .item .content .tags span {\n    display: inline-block;\n    line-height: 15px;\n}\n.form-inline {\n    padding: 0 10px;\n}\n.sort.asc {\n    text-decoration: overline;\n}\n.sort.desc {\n    text-decoration: underline;\n}\n.ui-avatar {\n    display: inline-block;\n    overflow: hidden;\n    line-height: 1;\n    vertical-align: middle;\n    border-radius: 3px;\n}\n.ui-avatar.circle {\n    border-radius: 50%;\n}\n.ui-history-close {\n    position: absolute;\n    right: 14px;\n    top: 15px;\n    font-size: 16px;\n    opacity: 0.5;\n}\n.ui-history-close:hover {\n    opacity: 1;\n}\n.ui-history-pin {\n    position: absolute;\n    left: 14px;\n    top: 15px;\n    font-size: 16px;\n    opacity: 0.2;\n\ttransition: opacity 0.2s ease-in-out;\n\t-webkit-transition: opacity 0.2s ease-in-out;\n}\n.item:hover .ui-history-pin:hover {\n    opacity: 1;\n}\n.item .ui-history-pin.active {\n\topacity: 1;\n    color: #d43f3a;\n}\n.ui-or {\n    margin: 5px;\n}\n.ui-use-tags {\n    min-width: 172px;\n    max-width: 344px;\n}\n\n.modal-title {\n    text-align: left;\n    color: black;\n}\n.modal-body {\n    color: black;\n}\n\n.btn-file {\n    position: relative;\n    overflow: hidden;\n}\n.btn-file input[type=file] {\n    position: absolute;\n    top: 0;\n    right: 0;\n    min-width: 100%;\n    min-height: 100%;\n    font-size: 100px;\n    text-align: right;\n    filter: alpha(opacity=0);\n    opacity: 0;\n    outline: none;\n    background: white;\n    cursor: inherit;\n    display: block;\n}\n\n.social-foot {\n    line-height: 30px;\n}\n.social-foot > * {\n    line-height: 20px;\n    vertical-align: middle !important;\n    display: inline-block !important;\n}\n\n.btn-link, .btn-link:hover, .btn-link:focus, .btn-link:active {\n    color: white;\n}\n\n.screenshot {\n    margin: 30px auto;\n    width: 100%;\n    border-radius: 3px;\n}\n\nselect {\n    color: black;\n}\n\n@media (max-width: 768px) {\n    span.ui-or {\n        display: block;\n    }\n    .ui-use-tags {\n        max-width: 100%;\n    }\n}\n\n.btn-mattermost {\n    background-color: #2179ec;\n    border-color: rgba(0,0,0,0.2);\n    color: #fff;\n}\n\n.btn-gitlab {\n    background-color: #e35431;\n    border-color: rgba(0,0,0,0.2);\n    color: #fff;\n}\n\n.btn-mattermost:hover, .btn-mattermost:active {\n    background-color: #105fc6;\n    border-color: rgba(0,0,0,0.2);\n    color: #fff;\n}\n\n.btn-gitlab:hover, .btn-gitlab:active {\n    background-color: #c23b1a;\n    border-color: rgba(0,0,0,0.2);\n    color: #fff;\n}\n\n/* add btn-login-method replaced of btn-social, to avoid ad block delete the login button */\n.btn-login-method {\n  padding-left: 61px;\n  position: relative;\n  text-align: left;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n}\n.btn-login-method.btn-lg :first-child {\n  line-height:45px;\n  width:45px;\n  font-size:1.8em;\n}\n.btn-login-method>:first-child {position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)}\n\na.btn.btn-login-method > i.oauth-icon {\n    display: inline-flex;\n    height: 45px;\n    width: 45px;\n    line-height: inherit;\n    padding: 6px;\n}\n\na.btn.btn-login-method > i.oauth-icon > img {\n    width: 100%;\n    height: 100%;\n    line-height: inherit;\n}\n"
  },
  {
    "path": "public/css/extra.css",
    "content": "/* for extra features should include this */\n\n.vimeo,\n.youtube {\n    position: relative;\n    cursor: pointer;\n    display: table;\n    width: 100%;\n    text-align: center;\n    background-position: center center;\n    background-repeat: no-repeat;\n    background-size: contain;\n    background-color: black;\n    overflow: hidden;\n}\n/* youtube always use 16:9 aspect ratio video */\n.youtube {\n    position: relative;\n    width: 100%;\n    padding-bottom: 56.25%;\n}\n.vimeo img {\n    width: 100%;\n    object-fit: contain;\n    z-index: 0;\n}\n.youtube img {\n    width: 100%;\n    height: 100%;\n    object-fit: cover;\n    position: absolute;\n    top: 0;\n    left: 0;\n    z-index: 0;\n}\n.vimeo iframe,\n.youtube iframe {\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    vertical-align: middle;\n    z-index: 1;\n}\n.vimeo .icon,\n.youtube .icon {\n    position: absolute;\n    height: auto;\n    width: auto;\n    top: 50%;\n    left: 50%;\n    transform: translate(-50%, -50%);\n    color: white;\n    opacity: 0.3;\n    -webkit-transition: opacity 0.2s; /* Safari */\n    transition: opacity 0.2s;\n    z-index: 0;\n}\n.vimeo:hover .icon,\n.youtube:hover .icon {\n    opacity: 0.6;\n    -webkit-transition: opacity 0.2s; /* Safari */\n    transition: opacity 0.2s;\n}\n\n.slideshare .inner,\n.speakerdeck .inner {\n    position: relative;\n    width: 100%;\n}\n.slideshare .inner iframe,\n.speakerdeck .inner iframe {\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    width: 100%;\n    height: 100%;\n}\n.geo-map {\n  width: 100%;\n  height: 250px;\n}\n\n/* markmap */\n.markmap-container {\n  height: 300px;\n}\n\n.markmap-container > svg {\n  width: 100%;\n  height: 100%;\n}\n\n.MJX_Assistive_MathML {\n    display: none;\n}\n\n.ui-infobar {\n    position: relative;\n    z-index: 2;\n    max-width: 758px;\n    margin-top: 25px;\n    margin-bottom: -25px;\n    color: #777;\n}\n.night .ui-infobar {\n  color: #ededed;\n}\n\n.toc .invisable-node {\n  list-style-type: none;\n}\n\n.ui-toc {\n    position: fixed;\n    bottom: 20px;\n    z-index: 10000;\n}\n\n.ui-toc-label {\n    opacity: 0.9;\n    background-color: #ccc;\n    border: none;\n    -webkit-transition: opacity 0.2s; /* Safari */\n    transition: opacity 0.2s;\n}\n\n.ui-toc .open .ui-toc-label {\n    opacity: 1;\n    color: #5f5f5f;\n    -webkit-transition: opacity 0.2s; /* Safari */\n    transition: opacity 0.2s;\n}\n\n.ui-toc-label:focus {\n    opacity: 1;\n    background-color: #ccc;\n    color: black;\n}\n\n.ui-toc-label:hover {\n    opacity: 1;\n    background-color: #ccc;\n    -webkit-transition: opacity 0.2s; /* Safari */\n    transition: opacity 0.2s;\n}\n\n.ui-toc-dropdown {\n    margin-top: 23px;\n    margin-bottom: 20px;\n    padding-left: 10px;\n    padding-right: 10px;\n    max-width: 45vw;\n    width: 25vw;\n    max-height: 70vh;\n    overflow: auto;\n    text-align: inherit;\n}\n\n.ui-toc-dropdown > .toc {\n    max-height: calc(70vh - 100px);\n    overflow: auto;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav {\n    padding-right: 0;\n    letter-spacing: 0.0029em;\n}\n\n.ui-toc-dropdown a {\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: pre;\n}\n\n.ui-toc-dropdown .nav>li>a {\n    display: block;\n    padding: 4px 20px;\n    font-size: 13px;\n    font-weight: 500;\n    color: #767676;\n}\n\n.ui-toc-dropdown .toc.expand ul {\n    display: block;\n}\n\n.ui-toc-dropdown .nav > li:first-child:nth-last-child(1) > ul {\n    display: block;\n}\n\n.ui-toc-dropdown .nav>li>a:focus,.ui-toc-dropdown .nav>li>a:hover {\n    padding-left: 19px;\n    color: black;\n    text-decoration: none;\n    background-color: transparent;\n    border-left: 1px solid black;\n}\n\n.night .ui-toc-dropdown .nav>li>a:focus, .night .ui-toc-dropdown .nav>li>a:hover{\n    color: white;\n    border-left-color: white;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav>li>a:focus,.ui-toc-dropdown[dir='rtl'] .nav>li>a:hover {\n    padding-right: 19px;\n    border-left: none;\n    border-right: 1px solid black;\n}\n\n.ui-toc-dropdown .nav>.active:focus>a,.ui-toc-dropdown .nav>.active:hover>a,.ui-toc-dropdown .nav>.active>a {\n    padding-left: 18px;\n    font-weight: 700;\n    color: black;\n    background-color: transparent;\n    border-left: 2px solid black;\n}\n.night .ui-toc-dropdown .nav>.active:focus>a,.night .ui-toc-dropdown .nav>.active:hover>a,.night .ui-toc-dropdown .nav>.active>a {\n    color: white;\n    border-left: 2px solid white;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav>.active:focus>a,.ui-toc-dropdown[dir='rtl'] .nav>.active:hover>a,.ui-toc-dropdown[dir='rtl'] .nav>.active>a {\n    padding-right: 18px;\n    border-left: none;\n    border-right: 2px solid black;\n}\n\n.ui-toc-dropdown .nav .nav {\n    display: none;\n    padding-bottom: 10px;\n}\n\n.ui-toc-dropdown .nav>.active>ul {\n    display: block;\n}\n\n.ui-toc-dropdown .nav .nav>li>a {\n    padding-top: 1px;\n    padding-bottom: 1px;\n    padding-left: 30px;\n    font-size: 12px;\n    font-weight: 400;\n}\n\n.night .ui-toc-dropdown .nav > li > a{\n    color: #aaa;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav .nav>li>a {\n    padding-right: 30px;\n}\n\n.ui-toc-dropdown .nav .nav>li>ul>li>a {\n    padding-top: 1px;\n    padding-bottom: 1px;\n    padding-left: 40px;\n    font-size: 12px;\n    font-weight: 400;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>a {\n    padding-right: 40px;\n}\n\n.ui-toc-dropdown .nav .nav>li>ul>li>ul>li>a {\n  padding-top: 1px;\n  padding-bottom: 1px;\n  padding-left: 50px;\n  font-size: 12px;\n  font-weight: 400;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>ul>li>a {\n  padding-right: 50px;\n}\n\n.ui-toc-dropdown .nav .nav>li>ul>li>ul>li>ul>li>a {\n  padding-top: 1px;\n  padding-bottom: 1px;\n  padding-left: 60px;\n  font-size: 12px;\n  font-weight: 400;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>ul>li>ul>li>a {\n  padding-right: 60px;\n}\n\n\n\n.ui-toc-dropdown .nav .nav>li>a:focus,.ui-toc-dropdown .nav .nav>li>a:hover {\n    padding-left: 29px;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav .nav>li>a:focus,.ui-toc-dropdown[dir='rtl'] .nav .nav>li>a:hover {\n    padding-right: 29px;\n}\n\n.ui-toc-dropdown .nav .nav>li>ul>li>a:focus,.ui-toc-dropdown .nav .nav>li>ul>li>a:hover {\n    padding-left: 39px;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>a:focus,.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>a:hover {\n    padding-right: 39px;\n}\n\n.ui-toc-dropdown .nav .nav>li>ul>li>ul>li>a:focus,.ui-toc-dropdown .nav .nav>li>ul>li>ul>li>a:hover {\n  padding-left: 49px;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>ul>li>a:focus,.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>ul>li>a:hover {\n  padding-right: 49px;\n}\n\n.ui-toc-dropdown .nav .nav>li>ul>li>ul>li>ul>li>a:focus,.ui-toc-dropdown .nav .nav>li>ul>li>ul>li>ul>li>a:hover {\n  padding-left: 59px;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>ul>li>ul>li>a:focus,.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>ul>li>ul>li>a:hover {\n  padding-right: 59px;\n}\n\n.ui-toc-dropdown .nav .nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>a {\n    padding-left: 28px;\n    font-weight: 500;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav .nav>.active:focus>a,.ui-toc-dropdown[dir='rtl'] .nav .nav>.active:hover>a,.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>a {\n    padding-right: 28px;\n}\n\n.ui-toc-dropdown .nav .nav>.active>.nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>a {\n    padding-left: 38px;\n    font-weight: 500;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.nav>.active:focus>a,.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.nav>.active:hover>a,.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.nav>.active>a {\n    padding-right: 38px;\n}\n\n.ui-toc-dropdown .nav .nav>.active>.nav>.active>.nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>.nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>.nav>.active>a {\n  padding-left: 48px;\n  font-weight: 500;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.nav>.active>.nav>.active:focus>a,.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.nav>.active>.nav>.active:hover>a,.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.active>.nav>.nav>.active>a {\n  padding-right: 48px;\n}\n\n.ui-toc-dropdown .nav .nav>.active>.nav>.active>.nav>.active>.nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>.nav>.active>.nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>.nav>.active>.nav>.active>a {\n  padding-left: 58px;\n  font-weight: 500;\n}\n\n.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.nav>.active>.nav>.active>.nav>.active:focus>a,.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.nav>.active>.nav>.active>.nav>.active:hover>a,.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.active>.nav>.nav>.active>.nav>.active>a {\n  padding-right: 58px;\n}\n\n/* support japanese font */\n.markdown-body[lang^=\"ja\"] {\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Helvetica, Arial, \"Hiragino Kaku Gothic Pro\", \"ヒラギノ角ゴ Pro W3\", Osaka, Meiryo, \"メイリオ\", \"MS Gothic\", \"ＭＳ ゴシック\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n}\n.ui-toc-dropdown[lang^=\"ja\"] {\n    font-family: \"Source Sans Pro\", Helvetica, Arial, \"Meiryo UI\", \"MS PGothic\", \"ＭＳ Ｐゴシック\", sans-serif;\n}\n\n/* support zh-tw font */\n.markdown-body[lang=\"zh-tw\"] {\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Helvetica, Arial, \"PingFang TC\", \"Microsoft JhengHei\", \"微軟正黑\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n}\n.ui-toc-dropdown[lang=\"zh-tw\"] {\n    font-family: \"Source Sans Pro\", Helvetica, Arial, \"Microsoft JhengHei UI\", \"微軟正黑UI\", sans-serif;\n}\n\n/* support zh-cn font */\n.markdown-body[lang=\"zh-cn\"] {\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Helvetica, Arial, \"PingFang SC\", \"Microsoft YaHei\", \"微软雅黑\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n}\n.ui-toc-dropdown[lang=\"zh-cn\"] {\n    font-family: \"Source Sans Pro\", Helvetica, Arial, \"Microsoft YaHei UI\", \"微软雅黑UI\", sans-serif;\n}\n\n.ui-affix-toc {\n    position: fixed;\n    top: 0;\n    max-width: 15vw;\n    max-height: 70vh;\n    overflow: auto;\n}\n\n.expand-toggle, .back-to-top, .go-to-bottom {\n    display: block;\n    padding: 4px 10px;\n    margin-top: 10px;\n    margin-left: 10px;\n    font-size: 12px;\n    font-weight: 500;\n    color: rgba(0, 0, 0, 0.85);\n}\n\n.expand-toggle:hover, .expand-toggle:focus, .back-to-top:hover, .back-to-top:focus, .go-to-bottom:hover, .go-to-bottom:focus {\n    color: #563d7c;\n    text-decoration: none;\n}\n\n.back-to-top, .go-to-bottom {\n    margin-top: 0;\n}\n\n.ui-user-icon {\n    width: 20px;\n    height: 20px;\n    display: block;\n    border-radius: 3px;\n    margin-top: 2px;\n    margin-bottom: 2px;\n    margin-right: 5px;\n    background-position: center center;\n    background-repeat: no-repeat;\n    background-size: contain;\n}\n.ui-user-icon.small {\n\twidth: 18px;\n\theight: 18px;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tmargin: 0 0 0.2em 0;\n}\n\nsmall span {\n    line-height: 22px;\n}\n\nsmall .dropdown {\n    display: inline-block;\n}\n\nsmall .dropdown a:focus, small .dropdown a:hover {\n    text-decoration: none;\n}\n\n.unselectable {\n    -moz-user-select: none;\n    -khtml-user-select: none;\n    -webkit-user-select: none;\n    -o-user-select: none;\n    user-select: none;\n}\n\n.night .navbar{\n    background: #333;\n    border-bottom-color: #333;\n    color: #eee;\n}\n\n.night .navbar-default .navbar-nav > li > a,\n.night .navbar a {\n    color: #eee;\n}\n\n@media print {\n    div, table, img, pre, blockquote {\n        page-break-inside: avoid !important;\n    }\n    a[href]:after {\n        font-size: 12px !important;\n    }\n}\n"
  },
  {
    "path": "public/css/font.css",
    "content": "/* latin-ext */\n@font-face {\n  font-family: 'Source Code Pro';\n  font-style: normal;\n  font-weight: 300;\n  src: local('Source Code Pro Light'), local('SourceCodePro-Light'), url('../fonts/SourceCodePro-Light.woff') format('woff');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Code Pro';\n  font-style: normal;\n  font-weight: 300;\n  src: local('Source Code Pro Light'), local('SourceCodePro-Light'), url('../fonts/SourceCodePro-Light.woff') format('woff');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Code Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Source Code Pro'), local('SourceCodePro-Regular'), url('../fonts/SourceCodePro-Regular.woff') format('woff');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Code Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Source Code Pro'), local('SourceCodePro-Regular'), url('../fonts/SourceCodePro-Regular.woff') format('woff');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Code Pro';\n  font-style: normal;\n  font-weight: 500;\n  src: local('Source Code Pro Medium'), local('SourceCodePro-Medium'), url('../fonts/SourceCodePro-Medium.woff') format('woff');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Code Pro';\n  font-style: normal;\n  font-weight: 500;\n  src: local('Source Code Pro Medium'), local('SourceCodePro-Medium'), url('../fonts/SourceCodePro-Medium.woff') format('woff');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 300;\n  src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('../fonts/SourceCodePro-Medium.woff') format('woff');\n  unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 300;\n  src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('../fonts/SourceSansPro-Light.woff') format('woff');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 300;\n  src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url('../fonts/SourceSansPro-Light.woff') format('woff');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url('../fonts/SourceSansPro-Regular.woff') format('woff');\n  unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url('../fonts/SourceSansPro-Regular.woff') format('woff');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url('../fonts/SourceSansPro-Regular.woff') format('woff');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), url('../fonts/SourceSansPro-Semibold.woff') format('woff');\n  unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), url('../fonts/SourceSansPro-Semibold.woff') format('woff');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), url('../fonts/SourceSansPro-Semibold.woff') format('woff');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 300;\n  src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'), url('../fonts/SourceSansPro-LightItalic.woff') format('woff');\n  unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 300;\n  src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'), url('../fonts/SourceSansPro-LightItalic.woff') format('woff');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 300;\n  src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'), url('../fonts/SourceSansPro-LightItalic.woff') format('woff');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 400;\n  src: local('Source Sans Pro Italic'), local('SourceSansPro-It'), url('../fonts/SourceSansPro-Italic.woff') format('woff');\n  unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 400;\n  src: local('Source Sans Pro Italic'), local('SourceSansPro-It'), url('../fonts/SourceSansPro-Italic.woff') format('woff');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 400;\n  src: local('Source Sans Pro Italic'), local('SourceSansPro-It'), url('../fonts/SourceSansPro-Italic.woff') format('woff');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* vietnamese */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'), url('../fonts/SourceSansPro-SemiboldItalic.woff') format('woff');\n  unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'), url('../fonts/SourceSansPro-SemiboldItalic.woff') format('woff');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'), url('../fonts/SourceSansPro-SemiboldItalic.woff') format('woff');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n/* latin-ext */\n@font-face {\n  font-family: 'Source Serif Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Source Serif Pro'), local('SourceSerifPro-Regular'), url('../fonts/SourceSerifPro-Regular.woff') format('woff');\n  unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: 'Source Serif Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Source Serif Pro'), local('SourceSerifPro-Regular'), url('../fonts/SourceSerifPro-Regular.woff') format('woff');\n  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;\n}\n"
  },
  {
    "path": "public/css/github-extract.css",
    "content": ".markdown-body {\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n    font-size: 16px;\n    line-height: 1.5;\n    word-wrap: break-word;\n}\n\n.markdown-body::before {\n    display: table;\n    content: \"\"\n}\n\n.markdown-body::after {\n    display: table;\n    clear: both;\n    content: \"\";\n}\n\n.markdown-body>*:first-child {\n    margin-top: 0 !important;\n}\n\n.markdown-body>*:last-child {\n    margin-bottom: 0 !important;\n}\n\n.markdown-body a:not([href]) {\n    color: inherit;\n    text-decoration: none;\n}\n\n.markdown-body .absent {\n    color: #c00;\n}\n\n.markdown-body .anchor {\n    float: left;\n    padding-right: 4px;\n    margin-left: -20px;\n    line-height: 1\n}\n\n.markdown-body .anchor:focus {\n    outline: none;\n}\n\n.markdown-body p,\n.markdown-body blockquote,\n.markdown-body ul,\n.markdown-body ol,\n.markdown-body dl,\n.markdown-body table,\n.markdown-body pre {\n    margin-top: 0;\n    margin-bottom: 16px;\n}\n\n.markdown-body hr {\n    height: 0.25em;\n    padding: 0;\n    margin: 24px 0;\n    background-color: #e7e7e7;\n    border: 0;\n}\n\n.markdown-body blockquote {\n    padding: 0 1em;\n    color: #777;\n    border-left: 0.25em solid #ddd;\n}\n.night .markdown-body blockquote{\n    color: #bcbcbc;\n}\n\n.markdown-body blockquote>:first-child {\n    margin-top: 0;\n}\n\n.markdown-body blockquote>:last-child {\n    margin-bottom: 0;\n}\n\n.markdown-body kbd {\n    display: inline-block;\n    padding: 3px 5px;\n    font-size: 11px;\n    line-height: 10px;\n    color: #555;\n    vertical-align: middle;\n    background-color: #fcfcfc;\n    border: solid 1px #ccc;\n    border-bottom-color: #bbb;\n    border-radius: 3px;\n    box-shadow: inset 0 -1px 0 #bbb;\n}\n\n.markdown-body .loweralpha {\n    list-style-type: lower-alpha;\n}\n\n.markdown-body h1,\n.markdown-body h2,\n.markdown-body h3,\n.markdown-body h4,\n.markdown-body h5,\n.markdown-body h6 {\n    margin-top: 24px;\n    margin-bottom: 16px;\n    font-weight: 600;\n    line-height: 1.25;\n}\n\n.night .markdown-body h1,\n.night .markdown-body h2,\n.night .markdown-body h3,\n.night .markdown-body h4,\n.night .markdown-body h5,\n.night .markdown-body h6 {\n    color: #ddd;\n}\n\n.markdown-body h1 .fa-link,\n.markdown-body h2 .fa-link,\n.markdown-body h3 .fa-link,\n.markdown-body h4 .fa-link,\n.markdown-body h5 .fa-link,\n.markdown-body h6 .fa-link {\n    color: #000;\n    vertical-align: middle;\n    visibility: hidden;\n    font-size: 16px;\n}\n\n.night .markdown-body h1 .fa-link,\n.night .markdown-body h2 .fa-link,\n.night .markdown-body h3 .fa-link,\n.night .markdown-body h4 .fa-link,\n.night .markdown-body h5 .fa-link,\n.night .markdown-body h6 .fa-link {\n    color: #fff;\n}\n\n.markdown-body h1:hover .anchor,\n.markdown-body h2:hover .anchor,\n.markdown-body h3:hover .anchor,\n.markdown-body h4:hover .anchor,\n.markdown-body h5:hover .anchor,\n.markdown-body h6:hover .anchor {\n    text-decoration: none;\n}\n\n.markdown-body h1:hover .anchor .fa-link,\n.markdown-body h2:hover .anchor .fa-link,\n.markdown-body h3:hover .anchor .fa-link,\n.markdown-body h4:hover .anchor .fa-link,\n.markdown-body h5:hover .anchor .fa-link,\n.markdown-body h6:hover .anchor .fa-link {\n    visibility: visible;\n}\n\n.markdown-body h1 tt,\n.markdown-body h1 code,\n.markdown-body h2 tt,\n.markdown-body h2 code,\n.markdown-body h3 tt,\n.markdown-body h3 code,\n.markdown-body h4 tt,\n.markdown-body h4 code,\n.markdown-body h5 tt,\n.markdown-body h5 code,\n.markdown-body h6 tt,\n.markdown-body h6 code {\n    font-size: inherit;\n}\n\n.markdown-body h1 {\n    padding-bottom: 0.3em;\n    font-size: 2em;\n    border-bottom: 1px solid #eee;\n}\n\n.markdown-body h2 {\n    padding-bottom: 0.3em;\n    font-size: 1.5em;\n    border-bottom: 1px solid #eee;\n}\n\n.markdown-body h3 {\n    font-size: 1.25em;\n}\n\n.markdown-body h4 {\n    font-size: 1em;\n}\n\n.markdown-body h5 {\n    font-size: 0.875em;\n}\n\n.markdown-body h6 {\n    font-size: 0.85em;\n    color: #777\n}\n\n\n\n.markdown-body ul,\n.markdown-body ol {\n    padding-left: 2em\n}\n\n.markdown-body ul.no-list,\n.markdown-body ol.no-list {\n    padding: 0;\n    list-style-type: none;\n}\n\n.markdown-body ul ul,\n.markdown-body ul ol,\n.markdown-body ol ol,\n.markdown-body ol ul {\n    margin-top: 0;\n    margin-bottom: 0\n}\n\n.markdown-body li>p {\n    margin-top: 16px\n}\n\n.markdown-body li+li {\n    margin-top: 0.25em;\n}\n\n.markdown-body dl {\n    padding: 0;\n}\n\n.markdown-body dl dt {\n    padding: 0;\n    margin-top: 16px;\n    font-size: 1em;\n    font-style: italic;\n    font-weight: bold;\n}\n\n.markdown-body dl dd {\n    padding: 0 16px;\n    margin-bottom: 16px;\n}\n\n.markdown-body table {\n    display: block;\n    width: 100%;\n    overflow: auto;\n    word-break: normal;\n    word-break: keep-all;\n}\n\n.markdown-body table th {\n    font-weight: bold\n}\n\n.markdown-body table th,\n.markdown-body table td {\n    padding: 6px 13px;\n    border: 1px solid #ddd;\n}\n\n.markdown-body table tr {\n    background-color: #fff;\n    border-top: 1px solid #ccc;\n}\n.night .markdown-body table tr {\n    background-color: #5f5f5f;\n}\n\n.markdown-body table tr:nth-child(2n) {\n    background-color: #f8f8f8;\n}\n\n.night .markdown-body table tr:nth-child(2n){\n\n    background-color: #4f4f4f;\n}\n\n.markdown-body img {\n    max-width: 100%;\n    box-sizing: content-box;\n    background-color: #fff;\n}\n\n.markdown-body img[align=right] {\n    padding-left: 20px;\n}\n\n.markdown-body img[align=left] {\n    padding-right: 20px;\n}\n\n.markdown-body .emoji {\n    max-width: none;\n    vertical-align: text-top;\n    background-color: transparent;\n}\n\n.markdown-body span.frame {\n    display: block;\n    overflow: hidden;\n}\n\n.markdown-body span.frame>span {\n    display: block;\n    float: left;\n    width: auto;\n    padding: 7px;\n    margin: 13px 0 0;\n    overflow: hidden;\n    border: 1px solid #ddd;\n}\n\n.markdown-body span.frame span img {\n    display: block;\n    float: left;\n}\n\n.markdown-body span.frame span span {\n    display: block;\n    padding: 5px 0 0;\n    clear: both;\n    color: #333;\n}\n\n.markdown-body span.align-center {\n    display: block;\n    overflow: hidden;\n    clear: both;\n}\n\n.markdown-body span.align-center>span {\n    display: block;\n    margin: 13px auto 0;\n    overflow: hidden;\n    text-align: center;\n}\n\n.markdown-body span.align-center span img {\n    margin: 0 auto;\n    text-align: center;\n}\n\n.markdown-body span.align-right {\n    display: block;\n    overflow: hidden;\n    clear: both;\n}\n\n.markdown-body span.align-right>span {\n    display: block;\n    margin: 13px 0 0;\n    overflow: hidden;\n    text-align: right;\n}\n\n.markdown-body span.align-right span img {\n    margin: 0;\n    text-align: right;\n}\n\n.markdown-body span.float-left {\n    display: block;\n    float: left;\n    margin-right: 13px;\n    overflow: hidden;\n}\n\n.markdown-body span.float-left span {\n    margin: 13px 0 0;\n}\n\n.markdown-body span.float-right {\n    display: block;\n    float: right;\n    margin-left: 13px;\n    overflow: hidden;\n}\n\n.markdown-body span.float-right>span {\n    display: block;\n    margin: 13px auto 0;\n    overflow: hidden;\n    text-align: right;\n}\n\n.markdown-body code,\n.markdown-body tt {\n    padding: 0;\n    padding-top: 0.2em;\n    padding-bottom: 0.2em;\n    margin: 0;\n    font-size: 85%;\n    background-color: rgba(0, 0, 0, 0.04);\n    border-radius: 3px;\n}\n\n.night .markdown-body code,\n.night .markdown-body tt {\n\n    color: #eee;\n    background-color: rgba(230, 230, 230, 0.36);\n\n}\n\n.markdown-body code::before,\n.markdown-body code::after,\n.markdown-body tt::before,\n.markdown-body tt::after {\n    letter-spacing: -0.2em;\n    content: \"\\00a0\";\n}\n\n.markdown-body code br,\n.markdown-body tt br {\n    display: none;\n}\n\n.markdown-body del code {\n    text-decoration: inherit;\n}\n\n.markdown-body pre {\n    word-wrap: normal;\n}\n\n.markdown-body pre>code {\n    padding: 0;\n    margin: 0;\n    font-size: 100%;\n    word-break: normal;\n    white-space: pre;\n    background: transparent;\n    border: 0;\n}\n\n.markdown-body .highlight {\n    margin-bottom: 16px;\n}\n\n.markdown-body .highlight pre {\n    margin-bottom: 0;\n    word-break: normal;\n}\n\n.markdown-body .highlight pre,\n.markdown-body pre {\n    padding: 16px;\n    overflow: auto;\n    font-size: 85%;\n    line-height: 1.45;\n    background-color: #f7f7f7;\n    border-radius: 3px;\n}\n\n.markdown-body pre code,\n.markdown-body pre tt {\n    display: inline;\n    max-width: auto;\n    padding: 0;\n    margin: 0;\n    overflow: visible;\n    line-height: inherit;\n    word-wrap: normal;\n    background-color: transparent;\n    border: 0;\n}\n\n.markdown-body pre code::before,\n.markdown-body pre code::after,\n.markdown-body pre tt::before,\n.markdown-body pre tt::after {\n    content: normal;\n}\n\n.markdown-body .csv-data td,\n.markdown-body .csv-data th {\n    padding: 5px;\n    overflow: hidden;\n    font-size: 12px;\n    line-height: 1;\n    text-align: left;\n    white-space: nowrap;\n}\n\n.markdown-body .csv-data .blob-line-num {\n    padding: 10px 8px 9px;\n    text-align: right;\n    background: #fff;\n    border: 0;\n}\n\n.markdown-body .csv-data tr {\n    border-top: 0;\n}\n\n.markdown-body .csv-data th {\n    font-weight: bold;\n    background: #f8f8f8;\n    border-top: 0;\n}\n\n.markdown-body kbd {\n    display: inline-block;\n    padding: 3px 5px;\n    font-size: 11px;\n    line-height: 10px;\n    color: #555;\n    vertical-align: middle;\n    background-color: #fcfcfc;\n    border: solid 1px #ccc;\n    border-bottom-color: #bbb;\n    border-radius: 3px;\n    box-shadow: inset 0 -1px 0 #bbb;\n}\n\n.news .alert .markdown-body blockquote {\n    padding: 0 0 0 40px;\n    border: 0 none;\n}\n\n.activity-tab .news .markdown-body blockquote,\n.activity-tab .news .alert .commits {\n    padding-left: 0;\n}\n\n.task-list-item {\n    list-style-type: none;\n}\n\n.task-list-item label {\n    font-weight: normal;\n}\n\n.task-list-item.enabled label {\n    cursor: pointer;\n}\n\n.task-list-item+.task-list-item {\n    margin-top: 3px;\n}\n\n.task-list-item-checkbox {\n    float: left;\n    margin: 0.31em 0 0.2em -1.3em !important;\n    vertical-align: middle;\n    cursor: default !important;\n}\n"
  },
  {
    "path": "public/css/google-font.css",
    "content": "@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600,600italic,300italic,300|Source+Serif+Pro|Source+Code+Pro:400,300,500&subset=latin,latin-ext);\n"
  },
  {
    "path": "public/css/index.css",
    "content": "html, body {\n    height: 100%;\n}\nbody {\n    margin: 0;\n    padding: 0;\n    max-width: inherit;\n    min-width: 200px;\n    /*margin-right: 15px;*/\n    padding-top: 51px;\n    /*overflow: hidden;*/\n}\n\n.night a,\n.night .open-files-container li.selected a {\n    color: #5EB7E0;\n}\n\nbody.night{\n    background: #333 !important;\n}\n\n.toolbar {\n  background-color: #1c1c1e;\n  border: 1px solid #343434;\n}\n\n.toolbar > .btn-toolbar {\n  white-space: nowrap;\n  overflow-y: auto;\n  scrollbar-width: none;\n}\n\n.toolbar > .btn-toolbar::-webkit-scrollbar {\n  display: none;\n}\n\n.toolbar > .btn-toolbar > .btn-group {\n  float: none;\n}\n\n.toolbar > .btn-toolbar > .btn-group > span {\n  display: inline-block;\n  float: left;\n  color: #fff;\n  padding: 5px;\n  line-height: 22px;\n}\n\n.toolbar > .btn-toolbar > .btn-group > span.separator {\n  color: #4d4d4d;\n}\n\n.toolbar > .btn-toolbar > .btn-group > .btn {\n  background-color: #1c1c1e;\n  padding: 5px;\n  font-size: 1em;\n}\n\n.toolbar > .btn-toolbar > .btn-group > .btn:hover {\n  background-color: #383a3e;\n\n  padding: 5px;\n}\n\n\n.CodeMirror {\n    font-family: \"Source Code Pro\", Consolas, monaco, monospace;\n    letter-spacing: 0.025em;\n    line-height: 1.25;\n    font-size: 18px;\n    height: auto !important;\n    overflow-y: hidden !important;\n    -webkit-overflow-scrolling: touch;\n}\n/* support japanese font */\n.CodeMirror[lang^=\"ja\"] {\n    font-family: \"Source Code Pro\", Consolas, monaco, Meiryo, \"ＭＳ ゴシック\", \"MS Gothic\", monospace;\n}\n/* support zh-tw font */\n.CodeMirror[lang=\"zh-tw\"] {\n    font-family: \"Source Code Pro\", Consolas, monaco, \"Microsoft JhengHei\", \"微軟正黑\", monospace;\n}\n/* support zh-cn font */\n.CodeMirror[lang=\"zh-cn\"] {\n    font-family: \"Source Code Pro\", Consolas, monaco, \"Microsoft YaHei\", \"微软雅黑\", monospace;\n}\n.CodeMirror-placeholder {\n    color: #777 !important;\n}\n.CodeMirror-scroll {\n    overflow-x: hidden !important;\n    overflow-y: auto !important;\n}\n.CodeMirror-code {\n    /*padding-bottom: 36px;*/\n}\n.CodeMirror-gutter-elt {\n    text-align: center;\n}\n.CodeMirror-linenumber {\n/*    opacity: 0.5;*/\n    min-width: 1.5em;\n    text-align: right;\n}\n.CodeMirror-gutter.authorship-gutters {\n    width: 8px;\n}\n.CodeMirror-matchingtag {\n    background: rgba(255, 255, 255, .1);\n    line-height: 1em;\n}\n.CodeMirror-foldmarker {\n    color: #d0d0d0;\n    text-shadow: none;\n    font-family: Arial;\n    font-size: 1em;\n    line-height: .3;\n    cursor: pointer;\n    margin: 2px;\n    padding-bottom: 2px;\n}\n.CodeMirror-foldgutter {\n    /*width: 1em;*/\n    cursor: default;\n    line-height: 100%;\n}\n.CodeMirror-foldgutter-open,\n.CodeMirror-foldgutter-folded {\n    line-height: 1em;\n    cursor: pointer;\n}\n.CodeMirror-foldgutter-open {\n    padding-top: 1px;\n}\n.CodeMirror-foldgutter-folded {\n    padding-top: 2px;\n}\n.CodeMirror-foldgutter-open:after {\n    content: \"⌵\";\n    font-size: 1em;\n/*    opacity: 0.5;*/\n}\n.CodeMirror-foldgutter-folded:after {\n    content: \"+\";\n    font-size: 1em;\n    font-weight: 700;\n}\n.CodeMirror-foldmarker, .CodeMirror-foldgutter-folded:after {\n    color: #78B2F2 !important;\n}\n.CodeMirror-sizer {\n    margin-bottom: 0px !important;\n}\n.CodeMirror-insert-match {\n  background: lawngreen;\n  border: 1px solid limegreen;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  opacity: .5;\n}\n.CodeMirror-delete-match {\n  background: indianred;\n  border: 1px solid darkred;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  opacity: .5;\n}\n.ui-content {\n    height: 100%;\n    margin-left: 0;\n    margin-right: 0;\n}\n\n.night .ui-content{\n    background-color: #333;\n}\n\n.ui-edit-area {\n    height: 100%;\n    /*padding-left: 15px;*/\n    padding-left: 0 !important;\n    padding-right: 0 !important;\n}\n.ui-edit-area .ui-resizable-handle.ui-resizable-e {\n    cursor: col-resize;\n    width: 8px;\n    right: -8px;\n    background-color: white;\n    box-shadow: 3px 0px 6px #e7e7e7;\n}\n.ui-edit-area .ui-sync-toggle {\n    width: 42px;\n    height: 42px;\n    padding: 2px 1px 0 0;\n    border-radius: 50%;\n    box-shadow: 2px 0px 2px #e7e7e7;\n    position: absolute;\n    top: 50%;\n    left: 50%;\n    transform: translate(-50%, -50%);\n}\n.night .ui-edit-area .ui-sync-toggle {\n    box-shadow: 2px 0px 2px #353535;\n}\n\n.ui-edit-area .ui-sync-toggle:active {\n    box-shadow: inset 0 3px 5px rgba(0,0,0,.125), 2px 0px 2px #e7e7e7;\n}\n\n.night .ui-edit-area .ui-resizable-handle.ui-resizable-e{\n   background: #3c3c3c;\n   box-shadow: 3px 0px 6px #353535;\n}\n\n.ui-view-area {\n    /*overflow-y: scroll;*/\n    -webkit-overflow-scrolling: touch;\n}\n@media (min-width: 768px) {\n    .ui-view-area {\n        padding-left: 15px;\n        padding-right: 15px;\n    }\n}\n\n.night .ui-view-area{\n    background: #333;\n    color: #ededed;\n}\n\n\n.ui-scrollable {\n    height: 100%;\n    overflow-x: hidden;\n    overflow-y: auto;\n}\n.ui-status * {\n    font-size: 16px !important;\n}\n.navbar-brand {\n    font-weight: bold;\n}\n.nav-status .ui-status * {\n    font-size: 14px;\n}\n.nav-mobile {\n    position: inherit;\n    margin-top: 8px;\n    margin-bottom: 8px;\n}\n.nav-mobile .dropdown-menu {\n    left: 40%;\n    right: 6px;\n    top: 42px;\n}\n.nav-status {\n    float: right !important;\n    padding: 7px 8px;\n}\n.ui-status {\n    cursor: auto !important;\n    min-width: 120px;\n    background-color: transparent !important;\n}\n.ui-status span {\n    cursor: pointer;\n}\n.ui-short-status {\n    cursor: pointer;\n    min-width: 40px;\n}\n.ui-short-status:hover {\n    text-decoration: none;\n}\n.ui-user-item {\n    /*na*/\n}\n.ui-user-name {\n    margin-top: 2px;\n}\n\n.ui-user-status {\n    margin-top: 5px;\n}\n.ui-user-status-online {\n    color: rgb(92,184,92);\n}\n.ui-user-status-idle {\n    color: rgb(240,173,78);\n}\n.ui-user-status-offline {\n    color: rgb(119,119,119);\n}\n.list > li > a {\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n#short-online-user-list .list .name {\n    max-width: 65%;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    float: left;\n}\n#online-user-list .list .name {\n    max-width: 110px;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    float: left;\n}\n.navbar-right {\n    margin-right: 0;\n}\n.navbar-nav > li > a {\n    cursor: pointer;\n}\n\n.night .navbar-default .navbar-nav > li > a:focus,\n.night .navbar-default .navbar-nav > li > a:hover,\n.night .navbar-default .navbar-brand:focus,\n.night .navbar-default .navbar-brand:hover{\n    color: #fff;\n}\n\n.night .navbar-default .navbar-nav > .open > a,\n.night .navbar-default .navbar-nav > .open > a:focus,\n.night .navbar-default .navbar-nav > .open > a:hover {\n    color: white;\n    background: #000;\n\n}\n\n.night .navbar-default .btn-link {\n  color: #bbb;\n}\n\n.dropdown-menu > li > a {\n    cursor: pointer;\n    text-overflow: ellipsis;\n    max-width: calc(100vw - 30px);\n    overflow: hidden;\n}\n\n.night .dropdown-menu > li > a {\n    color: #eee;\n}\n\n.night .dropdown-menu > li > a:focus,\n.night .dropdown-menu > li > a:hover {\n  color: #262626\n}\n\n.night .status-bar .dropdown-menu > li > a:focus, .status-bar .dropdown-menu > li > a:hover {\n    color: #ccc;\n}\n\n.night .dropdown-menu {\n    background: #222;\n}\n\n.night .modal-content,\n.night .panel,\n.night .panel-heading {\n  color: #eee;\n  background-color: #333;\n}\n\n.dropdown-menu.CodeMirror-other-cursor {\n    transition: none;\n}\n.cursortag {\n    cursor: pointer;\n    background: black;\n    position: absolute;\n    padding: 2px 7px 2px 8px;\n    font-size: 12px;\n    max-width: 150px;\n    text-overflow: ellipsis;\n    overflow: hidden;\n    font-family: inherit;\n    border-radius: .25em;\n    white-space: nowrap;\n    transition: left 0.1s ease-in-out, top 0.1s ease-in-out;\n}\n.fixfixed .navbar-fixed-top {\n    position: absolute !important;\n}\ndiv[contenteditable]:empty:not(:focus):before{\n    content:attr(data-ph);\n    color: gray;\n}\n.dropdown-menu.list {\n    max-height: 80vh;\n    overflow: auto;\n}\n.dropdown-menu.list.small {\n    max-height: 40vh;\n    overflow: auto;\n}\n.dropdown-menu.list::-webkit-scrollbar {\n    display: none;\n}\n.dropdown-menu .emoji {\n    margin-bottom: 0 !important;\n}\n.dropdown-menu.CodeMirror-other-cursor {\n    max-height: 50vh;\n    width: auto !important;\n    overflow: auto;\n    margin-bottom: 30px;\n}\n.CodeMirror-scrollbar-filler {\n    background: inherit;\n}\n\n.night .navbar .btn-default,\n.night .close {\n    background-color: #333;\n    border-color: #565656;\n    color: #eee;\n}\n\n.night .btn.btn-default.active{\n    background: #202020;\n}\n\n.btn-file {\n    position: relative;\n    overflow: hidden;\n}\n.btn-file input[type=file] {\n    position: absolute;\n    top: 0;\n    right: 0;\n    min-width: 100%;\n    min-height: 100%;\n    font-size: 100px;\n    text-align: right;\n    filter: alpha(opacity=0);\n    opacity: 0;\n    outline: none;\n    background: white;\n    cursor: inherit;\n    display: block;\n}\n\n.night .btn.focus,\n.night .btn:focus,\n.night .btn:hover,\n.night .close {\n    color: #fff;\n    background-color: #333;\n}\n\n.info-label {\n\twidth: 36%;\n\ttext-align: right;\n\tposition: relative;\n    display: inline-block;\n\tmargin-right: 6px;\n}\n.popover {\n\twidth: 100%;\n\tfont-family: inherit !important;\n\tline-height: 25px;\n}\n\n.text-ellipsis {\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n\twhite-space: nowrap;\n}\n\n.cm-trailing-space-a:before,\n.cm-trailing-space-b:before,\n.cm-trailing-space-new-line:before {\n  font-weight: bold;\n  color: hsl(30, 100%, 50%); /* a dark orange */\n  position: absolute;\n}\n\n.cm-trailing-space-a:before,\n.cm-trailing-space-b:before {\n  content: '·';\n}\n\n.cm-trailing-space-new-line:before {\n  content: '↵';\n}\n\n.cm-matchhighlight {\n/*    border-radius: 5px;*/\n/*    box-shadow: 0 1px 0 0 #ccc;*/\n    border-bottom: 1px solid #ccc;\n}\n\n.snippet-import-or {\n    text-align: center;\n    width: 100%;\n}\n\n.status-bar {\n    background: #1c1c1e;\n    border-top: 1px solid #343434;\n    color: #ccc;\n    position: relative;\n    display: block;\n    box-sizing: border-box;\n    font-size: 11px;\n    line-height: 25px;\n    height: 26px;\n}\n\n.status-bar .status-info {\n    color: #ccc;\n    left: 10px;\n    position: absolute;\n    white-space: nowrap;\n    max-width: 65%;\n    overflow: hidden;\n    text-overflow: ellipsis;\n}\n\n.status-bar .status-info div {\n    display: inline;\n}\n\n.status-bar .status-file {\n    color: #9a9a9a;\n}\n\n.status-bar .status-indicators {\n    background: #1c1c1e;\n    color: #ccc;\n    position: absolute;\n    right: 0;\n    text-align: right;\n    white-space: nowrap;\n    text-overflow: ellipsis;\n}\n\n.status-bar .status-indicators > div {\n    float: right;\n    padding: 0 10px;\n    border-left: 1px solid #343434;\n}\n\n.status-bar .status-indicators .status-keymap > a,\n.status-bar .status-indicators .status-theme > a,\n.status-bar .status-indicators .status-spellcheck > a,\n.status-bar .status-indicators .status-linter > a,\n.status-bar .status-indicators .status-preferences > a {\n    color: inherit;\n    text-decoration: none;\n}\n\n.status-bar .status-indicators .status-theme,\n.status-bar .status-indicators .status-spellcheck,\n.status-bar .status-indicators .status-linter,\n.status-bar .status-indicators .status-preferences {\n    padding: 0 4.3px;\n}\n\n.status-bar .status-indicators .status-preferences .dropdown-menu > li > a {\n    cursor: default;\n}\n\n.status-bar .status-indicators .status-preferences .dropdown-menu label {\n    font: inherit;\n    margin-bottom: 0;\n    cursor: pointer;\n}\n\n.status-bar .status-indicators .status-preferences .dropdown-menu label > input[type=\"checkbox\"] {\n    vertical-align: middle;\n    margin: -3px 0 0;\n}\n\n.ui-theme-toggle,\n.ui-linter-toggle,\n.ui-spellcheck-toggle {\n    opacity: 0.5;\n    cursor: pointer;\n}\n\n.ui-theme-toggle.active,\n.ui-linter-toggle.active,\n.ui-spellcheck-toggle.active {\n    opacity: 1;\n}\n\n.ui-theme-toggle:hover,\n.ui-linter-toggle:hover,\n.ui-spellcheck-toggle:hover {\n    opacity: 0.8;\n}\n\n.status-bar .indent-type, .status-bar .indent-width-label {\n    cursor: pointer;\n/*    margin-right: 3px;*/\n}\n\n.status-bar .indent-width-input {\n    font-size: 12px;\n    font-weight: 500;\n    height: 18px;\n    line-height: 1;\n    vertical-align: middle;\n    color: #ccc;\n    margin: 0;\n    padding: 0 0 2px;\n    position: relative;\n    left: 0;\n    top: -1px;\n    width: 18px;\n    transition: .1s linear all;\n    background-color: #555;\n    border: 1px solid #202020;\n    color: #fff;\n    box-shadow: inset 0 1px 0 rgba(0,0,0,0.06);\n    border-radius: 3px;\n    text-align: center;\n}\n\n.status-bar .indent-width-input:focus {\n    border: 1px solid #2893ef;\n}\n\n.status-bar .indent-width-input::-webkit-inner-spin-button,\n.status-bar .indent-width-input::-webkit-outer-spin-button {\n    -webkit-appearance: none;\n    margin: 0;\n}\n\n.status-bar .status-indent > * {\n    display: inline-block;\n}\n\n.status-bar .status-indent > *.hidden {\n    display: none;\n}\n\n.status-bar .status-overwrite:hover, .status-bar .indent-type:hover, .status-bar .indent-width-label:hover {\n    text-decoration: underline;\n}\n\n.status-bar .dropdown-menu {\n    background-color: #000;\n    color: #fff;\n    border: 1px solid rgba(255,255,255,0.09) !important;\n}\n\n.status-bar .dropdown-menu .divider {\n    background-color: #343434;\n}\n\n.status-bar .dropdown-menu > li > a {\n    color: #ccc;\n}\n\n.status-bar .dropdown-menu > li > a:focus, .status-bar .dropdown-menu > li > a:hover {\n    background-color: #212121;\n}\n\n@media print {\n    body {\n        padding-top: 0 !important;\n    }\n    .CodeMirror {\n        height: auto !important;\n    }\n}\n"
  },
  {
    "path": "public/css/markdown.css",
    "content": "/* for markdown-body */\n\n.markdown-body {\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n    padding-top: 40px;\n    padding-bottom: 40px;\n    max-width: 758px;\n\toverflow: visible !important;\n}\n/*fixed style for bootstrap comflict*/\n\n.markdown-body pre {\n    border: inherit !important;\n}\n\n.night .markdown-body pre {\n  filter: invert(100%);\n}\n\n.markdown-body code {\n    color: inherit !important;\n}\n\n.markdown-body pre code .wrapper {\n    display: -webkit-inline-flex;\n    display: -moz-inline-flex;\n    display: -ms-inline-flex;\n    display: -o-inline-flex;\n    display: inline-flex;\n}\n\n.markdown-body pre code .gutter {\n    float: left;\n    overflow: hidden;\n    -webkit-user-select: none;\n    user-select: none;\n}\n\n.markdown-body pre code .gutter.linenumber {\n    text-align: right;\n    position: relative;\n    display: inline-block;\n    cursor: default;\n    z-index: 4;\n    padding: 0 8px 0 0;\n    min-width: 20px;\n    box-sizing: content-box;\n    color: #afafaf !important;\n    border-right: 3px solid #6ce26c !important;\n}\n\n.markdown-body pre code .gutter.linenumber > span:before {\n    content: attr(data-linenumber);\n}\n\n.markdown-body pre code .code {\n    float: left;\n    margin: 0 0 0 16px;\n}\n\n.markdown-body .gist .line-numbers {\n    border-left: none;\n    border-top: none;\n    border-bottom: none;\n}\n\n.markdown-body .gist .line-data {\n    border: none;\n}\n\n.markdown-body .gist table {\n    border-spacing: 0;\n    border-collapse: inherit !important;\n}\n\n.night .markdown-body .gist table tr:nth-child(2n){\n\n    background-color: #ddd;\n\n}\n\n.markdown-body code[data-gist-id] {\n    background: none;\n    padding: 0;\n    filter: invert(100%);\n}\n\n.markdown-body code[data-gist-id]:before {\n    content: ''\n}\n\n.markdown-body code[data-gist-id]:after {\n    content: ''\n}\n\n.markdown-body code[data-gist-id] .blob-num {\n    border: unset;\n}\n\n.markdown-body code[data-gist-id] table {\n    overflow: unset;\n    margin-bottom: unset;\n}\n\n.markdown-body code[data-gist-id] table tr {\n    background: unset;\n\n}\n\n/*fixed style for rtl in pre and code*/\n\n.markdown-body[dir='rtl'] pre {\n    direction: ltr;\n}\n\n.markdown-body[dir='rtl'] code {\n    direction: ltr;\n    unicode-bidi: embed;\n}\n\n.markdown-body .alert > p {\n    margin-bottom: 0;\n}\n\n.markdown-body pre.flow-chart,\n.markdown-body pre.sequence-diagram,\n.markdown-body pre.graphviz,\n.markdown-body pre.mermaid,\n.markdown-body pre.abc,\n.markdown-body pre.geo,\n.markdown-body pre.vega {\n    text-align: center;\n    background-color: inherit;\n    border-radius: 0;\n    white-space: inherit;\n}\n\n.night .markdown-body pre.graphviz .graph > polygon{\n    fill: #333;\n}\n\n.night .markdown-body pre.mermaid .titleText,\n.night .markdown-body pre.mermaid text,\n.night .markdown-body pre.mermaid .sectionTitle{\n    fill: white;\n}\n\n.markdown-body pre.flow-chart > code,\n.markdown-body pre.sequence-diagram > code,\n.markdown-body pre.graphviz > code,\n.markdown-body pre.mermaid > code,\n.markdown-body pre.abc > code,\n.markdown-body pre.vega > code {\n    text-align: left;\n}\n\n.markdown-body pre.flow-chart > svg,\n.markdown-body pre.sequence-diagram > svg,\n.markdown-body pre.graphviz > svg,\n.markdown-body pre.mermaid > svg,\n.markdown-body pre.abc > svg,\n.markdown-body pre.vega > svg {\n    max-width: 100%;\n    height: 100%;\n}\n\n.night .markdown-body .abc path{\n    fill: #eee;\n}\n\n.night .markdown-body .abc path.note_selected{\n    fill: ##4DD0E1;\n}\n\n.night tspan{\n    fill: #fefefe;\n}\n\n.night pre rect{\n    fill: transparent;\n}\n\n.night pre.flow-chart rect,\n.night pre.flow-chart path{\n    stroke: white;\n}\n\n.markdown-body pre > code.wrap {\n    white-space: pre-wrap;       /* Since CSS 2.1 */\n    white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */\n    white-space: -pre-wrap;      /* Opera 4-6 */\n    white-space: -o-pre-wrap;    /* Opera 7 */\n    word-wrap: break-word;       /* Internet Explorer 5.5+ */\n}\n\n.markdown-body .alert > p,\n.markdown-body .alert > ul {\n    margin-bottom: 0;\n}\n\n/* Make details boxes look like on GitHub */\n.markdown-body summary {\n    display: list-item;\n}\n\n.markdown-body summary:focus {\n    outline: none;\n}\n\n.markdown-body details summary {\n    cursor: pointer;\n}\n\n.markdown-body details:not([open]) > *:not(summary) {\n    display: none;\n}\n\n.markdown-body figure {\n    margin: 1em 40px;\n}\n\n.markdown-body img {\n    background-color: transparent;\n}\n"
  },
  {
    "path": "public/css/mermaid.css",
    "content": "/* Flowchart variables */\n/* Sequence Diagram variables */\n/* Gantt chart variables */\n.mermaid .label {\n  color: #333;\n}\n/* workaround to solve conflict bootstrap styles */\n.mermaid .label {\n  display: unset;\n  padding: unset;\n  font-size: unset;\n  font-weight: unset;\n  line-height: unset;\n  text-align: unset;\n  white-space: unset;\n  vertical-align: unset;\n  border-radius: unset;\n}\n.mermaid .node rect,\n.mermaid .node circle,\n.mermaid .node ellipse,\n.mermaid .node polygon {\n  fill: #ECECFF;\n  stroke: #CCCCFF;\n  stroke-width: 1px;\n}\n.mermaid .edgePath .path {\n  stroke: #333333;\n}\n.mermaid .edgeLabel {\n  background-color: #e8e8e8;\n}\n.mermaid .cluster rect {\n  fill: #ffffde !important;\n  rx: 4 !important;\n  stroke: #aaaa33 !important;\n  stroke-width: 1px !important;\n}\n.mermaid .cluster text {\n  fill: #333;\n}\n.mermaid .actor {\n  stroke: #CCCCFF;\n  fill: #ECECFF;\n}\n.mermaid text.actor {\n  fill: black;\n  stroke: none;\n}\n.mermaid .actor-line {\n  stroke: grey;\n}\n.mermaid .messageLine0 {\n  stroke-width: 1.5;\n  stroke-dasharray: \"2 2\";\n  marker-end: \"url(#arrowhead)\";\n  stroke: #333;\n}\n.mermaid .messageLine1 {\n  stroke-width: 1.5;\n  stroke-dasharray: \"2 2\";\n  stroke: #333;\n}\n.mermaid #arrowhead {\n  fill: #333;\n}\n.mermaid #crosshead path {\n  fill: #333 !important;\n  stroke: #333 !important;\n}\n.mermaid .messageText {\n  fill: #333;\n  stroke: none;\n}\n.mermaid .labelBox {\n  stroke: #CCCCFF;\n  fill: #ECECFF;\n}\n.mermaid .labelText {\n  fill: black;\n  stroke: none;\n}\n.mermaid .loopText {\n  fill: black;\n  stroke: none;\n}\n.mermaid .loopLine {\n  stroke-width: 2;\n  stroke-dasharray: \"2 2\";\n  marker-end: \"url(#arrowhead)\";\n  stroke: #CCCCFF;\n}\n.mermaid .note {\n  stroke: #aaaa33;\n  fill: #fff5ad;\n}\n.mermaid .noteText {\n  fill: black;\n  stroke: none;\n  font-family: 'trebuchet ms', verdana, arial;\n  font-size: 14px;\n}\n/** Section styling */\n.mermaid .section {\n  stroke: none;\n  opacity: 0.2;\n}\n.mermaid .section0 {\n  fill: rgba(102, 102, 255, 0.49);\n}\n.mermaid .section2 {\n  fill: #fff400;\n}\n.mermaid .section1,\n.mermaid .section3 {\n  fill: white;\n  opacity: 0.2;\n}\n.mermaid .sectionTitle0 {\n  fill: #333;\n}\n.mermaid .sectionTitle1 {\n  fill: #333;\n}\n.mermaid .sectionTitle2 {\n  fill: #333;\n}\n.mermaid .sectionTitle3 {\n  fill: #333;\n}\n.mermaid .sectionTitle {\n  text-anchor: start;\n  font-size: 11px;\n  text-height: 14px;\n}\n/* Grid and axis */\n.mermaid .grid .tick {\n  stroke: lightgrey;\n  opacity: 0.3;\n  shape-rendering: crispEdges;\n}\n.mermaid .grid path {\n  stroke-width: 0;\n}\n/* Today line */\n.mermaid .today {\n  fill: none;\n  stroke: red;\n  stroke-width: 2px;\n}\n/* Task styling */\n/* Default task */\n.mermaid .task {\n  stroke-width: 2;\n}\n.mermaid .taskText {\n  text-anchor: middle;\n  font-size: 11px;\n}\n.mermaid .taskTextOutsideRight {\n  fill: black;\n  text-anchor: start;\n  font-size: 11px;\n}\n.mermaid .taskTextOutsideLeft {\n  fill: black;\n  text-anchor: end;\n  font-size: 11px;\n}\n/* Specific task settings for the sections*/\n.mermaid .taskText0,\n.mermaid .taskText1,\n.mermaid .taskText2,\n.mermaid .taskText3 {\n  fill: white;\n}\n.mermaid .task0,\n.mermaid .task1,\n.mermaid .task2,\n.mermaid .task3 {\n  fill: #8a90dd;\n  stroke: #534fbc;\n}\n.mermaid .taskTextOutside0,\n.mermaid .taskTextOutside2 {\n  fill: black;\n}\n.mermaid .taskTextOutside1,\n.mermaid .taskTextOutside3 {\n  fill: black;\n}\n/* Active task */\n.mermaid .active0,\n.mermaid .active1,\n.mermaid .active2,\n.mermaid .active3 {\n  fill: #bfc7ff;\n  stroke: #534fbc;\n}\n.mermaid .activeText0,\n.mermaid .activeText1,\n.mermaid .activeText2,\n.mermaid .activeText3 {\n  fill: black !important;\n}\n/* Completed task */\n.mermaid .done0,\n.mermaid .done1,\n.mermaid .done2,\n.mermaid .done3 {\n  stroke: grey;\n  fill: lightgrey;\n  stroke-width: 2;\n}\n.mermaid .doneText0,\n.mermaid .doneText1,\n.mermaid .doneText2,\n.mermaid .doneText3 {\n  fill: black !important;\n}\n/* Tasks on the critical line */\n.mermaid .crit0,\n.mermaid .crit1,\n.mermaid .crit2,\n.mermaid .crit3 {\n  stroke: #ff8888;\n  fill: red;\n  stroke-width: 2;\n}\n.mermaid .activeCrit0,\n.mermaid .activeCrit1,\n.mermaid .activeCrit2,\n.mermaid .activeCrit3 {\n  stroke: #ff8888;\n  fill: #bfc7ff;\n  stroke-width: 2;\n}\n.mermaid .doneCrit0,\n.mermaid .doneCrit1,\n.mermaid .doneCrit2,\n.mermaid .doneCrit3 {\n  stroke: #ff8888;\n  fill: lightgrey;\n  stroke-width: 2;\n  cursor: pointer;\n  shape-rendering: crispEdges;\n}\n.mermaid .doneCritText0,\n.mermaid .doneCritText1,\n.mermaid .doneCritText2,\n.mermaid .doneCritText3 {\n  fill: black !important;\n}\n.mermaid .activeCritText0,\n.mermaid .activeCritText1,\n.mermaid .activeCritText2,\n.mermaid .activeCritText3 {\n  fill: black !important;\n}\n.mermaid .titleText {\n  text-anchor: middle;\n  font-size: 18px;\n  fill: black;\n}\n/*\n\n\n*/\n.mermaid .node text {\n  font-family: 'trebuchet ms', verdana, arial;\n  font-size: 14px;\n}\n.mermaid div.mermaidTooltip {\n  position: absolute;\n  text-align: center;\n  max-width: 200px;\n  padding: 2px;\n  font-family: 'trebuchet ms', verdana, arial;\n  font-size: 12px;\n  background: #ffffde;\n  border: 1px solid #aaaa33;\n  border-radius: 2px;\n  pointer-events: none;\n  z-index: 100;\n}\n"
  },
  {
    "path": "public/css/site.css",
    "content": "/* for all pages should include this */\nbody {\n    font-smoothing: subpixel-antialiased !important;\n    -webkit-font-smoothing: subpixel-antialiased !important;\n    -moz-osx-font-smoothing: auto !important;\n    text-shadow: 0 0 1em transparent, 1px 1px 1.2px rgba(0, 0, 0, 0.004);\n    /*text-rendering: optimizeLegibility;*/\n    -webkit-overflow-scrolling: touch;\n    font-family: \"Source Sans Pro\", Helvetica, Arial, sans-serif;\n    letter-spacing: 0.025em;\n}\n:focus, .focus {\n    outline: none !important;\n}\n::-moz-focus-inner {\n    border: 0 !important;\n}\n\n/* manual fix for bootstrap issue 14040, there is an unnecessary padding-right on modal open */\nbody.modal-open {\n    overflow-y: auto;\n    padding-right: 0 !important;\n}\n"
  },
  {
    "path": "public/css/slide-preview.css",
    "content": ".markdown-body.slides {\n  position: relative;\n  z-index: 1;\n  color: #222;\n}\n\n.markdown-body.slides::before {\n  content: '';\n  display: block;\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  z-index: -1;\n  background-color: currentColor;\n  box-shadow: 0 0 0 50vw;\n}\n\n.markdown-body.slides section[data-markdown] {\n  position: relative;\n  margin-bottom: 1.5em;\n  background-color: #fff;\n  text-align: center;\n}\n\n.markdown-body.slides section[data-markdown] code {\n  text-align: left;\n}\n\n.markdown-body.slides section[data-markdown]::before {\n  content: '';\n  display: block;\n  padding-bottom: 56.23%;\n}\n\n.markdown-body.slides section[data-markdown] > div:first-child {\n  position: absolute;\n  top: 50%;\n  left: 1em;\n  right: 1em;\n  transform: translateY(-50%);\n  max-height: 100%;\n  overflow: hidden;\n}\n\n.markdown-body.slides section[data-markdown] > ul {\n  display: inline-block;\n}\n\n.markdown-body.slides > section > section + section::after {\n  content: '';\n  position: absolute;\n  top: -1.5em;\n  right: 1em;\n  height: 1.5em;\n  border: 3px solid #777;\n}\n"
  },
  {
    "path": "public/css/slide.css",
    "content": ".reveal {\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n}\n\n.reveal h1,\n.reveal h2,\n.reveal h3,\n.reveal h4,\n.reveal h5,\n.reveal h6 {\n    font-family: inherit;\n    text-transform: initial;\n}\n\n.reveal pre,\n.reveal code {\n    font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\n\n.reveal.fade {\n    opacity: unset;\n    -webkit-transition: unset;\n    transition: unset;\n}\n\n.vimeo,\n.youtube {\n    position: relative !important;\n    cursor: pointer;\n    display: table;\n    width: 100% !important;\n    text-align: center;\n    background-position: center center;\n    background-repeat: no-repeat;\n    background-size: contain;\n    background-color: black;\n    overflow: hidden;\n    font-size: 24px !important;\n}\n\n\n/* youtube always use 16:9 aspect ratio video */\n\n.vimeo,\n.youtube {\n    position: relative;\n    width: 100%;\n    padding-bottom: 56.25% !important;\n}\n\n.vimeo > img,\n.youtube > img {\n    max-width: 100%;\n    max-height: 100%;\n    margin: 0 !important;\n    border: 0 !important;\n    width: 100%;\n    height: 100%;\n    object-fit: cover;\n    position: absolute;\n    top: 0;\n    left: 0;\n    z-index: 0;\n}\n\n.vimeo > iframe,\n.youtube > iframe {\n    max-width: 100%;\n    max-height: 100%;\n}\n\n.slideshare .inner,\n.speakerdeck .inner {\n    padding-bottom: 62% !important;\n}\n\n.pdfobject {\n    height: 85vh !important;\n}\n\n.task-list-item-checkbox {\n    font-size: inherit;\n    height: 1em;\n    transform: scale(2);\n    margin: 0.15em 0 0.15em -0.84em !important;\n}\n\npre code .wrapper {\n    display: -webkit-inline-flex;\n    display: -moz-inline-flex;\n    display: -ms-inline-flex;\n    display: -o-inline-flex;\n    display: inline-flex;\n}\n\npre code .gutter {\n    float: left;\n    overflow: hidden;\n    -webkit-user-select: none;\n    user-select: none;\n}\n\npre code .gutter.linenumber {\n    text-align: right;\n    position: relative;\n    display: inline-block;\n    cursor: default;\n    z-index: 4;\n    padding: 0 8px 0 0;\n    min-width: 20px;\n    box-sizing: content-box;\n    color: #afafaf !important;\n    border-right: 3px solid #6ce26c !important;\n}\n\npre code .gutter.linenumber > span:before {\n    content: attr(data-linenumber);\n}\n\npre code .code {\n    float: left;\n    margin: 0 0 0 16px;\n}\n\n.gist .line-numbers {\n    border-left: none;\n    border-top: none;\n    border-bottom: none;\n}\n\n.gist .line-data {\n    border: none;\n}\n\n.gist table {\n    border-spacing: 0;\n    border-collapse: inherit !important;\n}\n\ncode[data-gist-id] {\n    background: none;\n    padding: 0;\n}\n\ncode[data-gist-id]:before {\n    content: ''\n}\n\ncode[data-gist-id]:after {\n    content: ''\n}\n\n.alert {\n    border-radius: 4px;\n}\n\n.alert h4 {\n    margin-top: 0;\n    color: inherit;\n}\n\n.alert > p {\n    padding: 5px !important;\n}\n\n.alert-success {\n    color: #3c763d;\n    background-color: #dff0d8;\n    border-color: #d6e9c6;\n}\n\n.alert-success hr {\n    border-top-color: #c9e2b3;\n}\n\n.alert-success .alert-link {\n    color: #2b542c;\n}\n\n.alert-info {\n    color: #31708f;\n    background-color: #d9edf7;\n    border-color: #bce8f1;\n}\n\n.alert-info hr {\n    border-top-color: #a6e1ec;\n}\n\n.alert-info .alert-link {\n    color: #245269;\n}\n\n.alert-warning {\n    color: #8a6d3b;\n    background-color: #fcf8e3;\n    border-color: #faebcc;\n}\n\n.alert-warning hr {\n    border-top-color: #f7e1b5;\n}\n\n.alert-warning .alert-link {\n    color: #66512c;\n}\n\n.alert-danger {\n    color: #a94442;\n    background-color: #f2dede;\n    border-color: #ebccd1;\n}\n\n.alert-danger hr {\n    border-top-color: #e4b9c0;\n}\n\n.alert-danger .alert-link {\n    color: #843534;\n}\n\npre.flow-chart,\npre.sequence-diagram,\npre.graphviz,\npre.mermaid,\npre.abc,\npre.geo,\npre.vega {\n    text-align: center;\n    background-color: white;\n    border-radius: 0;\n    white-space: inherit;\n}\n\npre.flow-chart > code,\npre.sequence-diagram > code,\npre.graphviz > code,\npre.mermaid > code,\npre.abc > code,\npre.vega > code {\n    text-align: left;\n}\n\npre.flow-chart > svg,\npre.sequence-diagram > svg,\npre.graphviz > svg,\npre.mermaid > svg,\npre.abc > svg,\npre.vega > svg {\n    max-width: 100%;\n    height: 100%;\n}\n\n.emoji {\n    margin: 0 !important;\n    background: transparent !important;\n    border: none !important;\n    box-shadow: none !important;\n    margin-bottom: -.25em !important;\n}\n\n.slides, #meta {\n    display: none;\n}\n\n.reveal.rtl .slides,\n.reveal.rtl .slides h1,\n.reveal.rtl .slides h2,\n.reveal.rtl .slides h3,\n.reveal.rtl .slides h4,\n.reveal.rtl .slides h5,\n.reveal.rtl .slides h6 {\n\tdirection: rtl;\n\tfont-family: inherit;\n}\n\n.text-uppercase {\n    text-transform: uppercase;\n}\n\n.footer {\n    background-color: white;\n    padding: 25px 15px;\n}\n\n.footer .gray-font {\n    color: #777;\n}\n\n.footer > * {\n    margin-left: auto;\n    margin-right: auto;\n    max-width: 758px;\n}\n\n.footer .ui-no-lastchangeuser {\n    width: 18px;\n}\n\n.footer .slides-disqus {\n    margin-top: 25px;\n    margin-bottom: 15px;\n}\n\nhtml, body {\n    height: 100%;\n    width: 100%;\n    overflow: hidden;\n}\n\n.container {\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    overflow-y: scroll;\n}\n\n.container.hidescrollbar {\n    right: -17px;\n}\n\n.reveal {\n    height: 100vh;\n}\n\n.reveal .progress,\n.reveal .slide-number,\n.reveal .playback,\n.reveal .controls {\n    position: absolute;\n}\n\n.print-pdf .container {\n    position: relative;\n    overflow-y: hidden;\n}\n\n.print-pdf .container.hidescrollbar {\n    right: 0;\n}\n\n.print-pdf .footer {\n    display: none;\n}\n\n.markmap-container {\n  background: #f7f7f7;\n}\n"
  },
  {
    "path": "public/default.md",
    "content": ""
  },
  {
    "path": "public/docs/features.md",
    "content": "Features\n===\n\nIntroduction\n===\n<i class=\"fa fa-file-text\"></i> **CodiMD** is a real-time, multi-platform collaborative markdown note editor.\nThis means that you can write notes with other people on your **desktop**, **tablet** or even on the **phone**.\nYou can sign-in via multiple auth providers like **Facebook**, **Twitter**, **GitHub** and many more on the [_homepage_](/).\n\nIf you experience any _issues_, feel free to report it on [**GitHub**](https://github.com/hackmdio/codimd/issues).\nOr meet us on [**Gitter**](https://gitter.im/hackmdio/hackmd) for dev-talk and interactive help.\n**Thank you very much!**\n\nWorkspace\n===\n## Modes\n**Desktop & Tablet**\n\n<i class=\"fa fa-edit fa-fw\"></i> Edit: See only the editor.\n<i class=\"fa fa-eye fa-fw\"></i> View: See only the result.\n<i class=\"fa fa-columns fa-fw\"></i> Both: See both in split view.\n\n**Mobile**\n\n<i class=\"fa fa-toggle-on fa-fw\"></i> View: See only the result.\n<i class=\"fa fa-toggle-off fa-fw\"></i> Edit: See only the editor.\n\n## Night Mode:\nWhen you are tired of a white screen and like a night mode, click on the little moon <i class=\"fa fa-moon-o\"></i> and turn on the night view of CodiMD.\n\nThe editor view, which is in night mode by default, can also be toggled between night and day view using the the little sun<i class=\"fa fa-sun-o fa-fw\"></i>.\n\n## Image Upload:\nYou can upload an image simply by clicking on the camera button <i class=\"fa fa-camera\"></i>.\nAlternatively, you can **drag-n-drop** an image into the editor. Even **pasting** images is possible!\nThis will automatically upload the image to **[imgur](http://imgur.com)**, **[Amazon S3](https://aws.amazon.com/s3/)**, **[Minio](https://minio.io)** or **local filesystem**, nothing to worry about. :tada:\n![imgur](https://i.imgur.com/9cgQVqD.png)\n\n## Share Notes:\nIf you want to share an **editable** note, just copy the URL.\nIf you want to share a **read-only** note, simply press publish button <i class=\"fa fa-share-square-o\"></i> and copy the URL.\n\n## Save a Note:\nCurrently, you can save to **Dropbox** <i class=\"fa fa-dropbox\"></i> or save an `.md` file <i class=\"fa fa-file-text\"></i> locally.\n\n## Import Notes:\nSimilarly to the _save_ feature, you can also import an `.md` file from **Dropbox** <i class=\"fa fa-dropbox\"></i>,\nor import content from your **clipboard** <i class=\"fa fa-clipboard\"></i>, and that can parse some **html** which might be useful :smiley:\n\n## Permissions:\nIt is possible to change the access permission to a note through the little button on the top right of the view.\nThere are four possible options:\n\n|                              |Owner read/write|Signed-in read|Signed-in write|Guest read|Guest write|\n|:-----------------------------|:--------------:|:------------:|:-------------:|:--------:|:---------:|\n|<span class=\"text-nowrap\"><i class=\"fa fa-leaf fa-fw\"></i> **Freely**</span>               |✔|✔|✔|✔|✔|\n|<span class=\"text-nowrap\"><i class=\"fa fa-pencil fa-fw\"></i> **Editable**</span>           |✔|✔|✔|✔|✖|\n|<span class=\"text-nowrap\"><i class=\"fa fa-id-card fa-fw\"></i> **Limited**</span>           |✔|✔|✔|✖|✖|\n|<span class=\"text-nowrap\"><i class=\"fa fa-lock fa-fw\"></i> **Locked**</span>               |✔|✔|✖|✔|✖|\n|<span class=\"text-nowrap\"><i class=\"fa fa-umbrella fa-fw\"></i> **Protected**</span>        |✔|✔|✖|✖|✖|\n|<span class=\"text-nowrap\"><i class=\"fa fa-hand-stop-o fa-fw\"></i> **Private**</span>       |✔|✖|✖|✖|✖|\n\n\n**Only the owner of the note can change the note's permissions.**\n\n## Embed a Note:\nNotes can be embedded as follows:\n\n```xml\n<iframe width=\"100%\" height=\"500\" src=\"https://hackmd.io/features\" frameborder=\"0\"></iframe>\n```\n\n## [Slide Mode](./slide-example):\nYou can use a special syntax to organize your note into slides.\nAfter that, you can use the **[Slide Mode](./slide-example)** <i class=\"fa fa-tv\"></i> to make a presentation.\nVisit the above link for details.\n\nTo switch the editor into slide mode, set the [document type](./yaml-metadata#type) to `slide`.\n\nView\n===\n## Table of Contents:\nYou can look at the bottom right section of the view area, there is a _ToC_ button <i class=\"fa fa-bars\"></i>.\nPressing that button will show you a current _Table of Contents_, and will highlight which section you're at.\nToCs support up to **five header levels**, the **default** is **set to three**. The maxLevel can be set for each note by using \n[YAML Metadata](./yaml-metadata)\n\n## Permalink\nEvery header will automatically add a permalink on the right side.\nYou can hover and click <i class=\"fa fa-chain\"></i> to anchor on it.\n\nEdit:\n===\n## Editor Modes:\nYou can look in the bottom right section of the editor area, there you'll find a button with `sublime` on it.\nWhen you click it, you can select 3 editor modes:\n\n- sublime (default)\n- emacs\n- vim\n\n## Shortcut Keys:\nThe shortcut keys depend on your selected editor mode. By default they are just like Sublime text, which is pretty quick and convenient.\n> For more information, see [here](https://codemirror.net/demo/sublime.html).\n\nFor emacs:\n> For more information, see [here](https://codemirror.net/demo/emacs.html).\n\nFor vim:\n> For more information, see [here](https://codemirror.net/demo/vim.html).\n\n## Auto-Complete:\nThis editor provides full auto-complete hints in markdown.\n- Emojis: type `:` to show hints.\n- Code blocks: type ` ``` ` and plus a character to show hint. <i hidden>```</i>\n- Headers: type `#` to show hint.\n- Referrals: type `[]` to show hint.\n- Externals: type `{}` to show hint.\n- Images: type `!` to show hint.\n\n## Title:\nThis will take the first **level 1 header** as the note title.\n\n## Tags:\nUsing tags as follows, the specified tags will show in your **history**.\n###### tags: `features` `cool` `updated`\n\n## [YAML Metadata](./yaml-metadata)\nYou can provide advanced note information to set the browser behavior (visit above link for details):\n- robots: set web robots meta\n- lang: set browser language\n- dir: set text direction\n- breaks: set to use line breaks\n- GA: set to use Google Analytics\n- disqus: set to use Disqus\n- slideOptions: setup slide mode options\n- toc: set options of the Table of Contents.\n\n## ToC:\nUse the syntax `[TOC]` to embed table of content into your note. By default, three header levels are displayed. This can also be specified by using [YAML Metadata](./yaml-metadata). \n\n[TOC]\n\nYou can also specify the number of header levels by specifying the `maxLevel` like this: `[TOC maxLevel=1]`\n\n[TOC maxLevel=1]\n\n\n\n## Emoji\nYou can type any emoji like this :smile: :smiley: :cry: :wink:\n> See full emoji list [here](http://www.emoji-cheat-sheet.com/).\n\n## ToDo List:\n- [ ] ToDos\n  - [x] Buy some salad\n  - [ ] Brush teeth\n  - [x] Drink some water\n\n## Code Block:\nWe support many programming languages, use the auto complete function to see the entire list.\n```javascript=\nvar s = \"JavaScript syntax highlighting\";\nalert(s);\nfunction $initHighlight(block, cls) {\n  try {\n    if (cls.search(/\\bno\\-highlight\\b/) != -1)\n      return process(block, true, 0x0F) +\n             ' class=\"\"';\n  } catch (e) {\n    /* handle exception */\n  }\n  for (var i = 0 / 2; i < classes.length; i++) {\n    if (checkCondition(classes[i]) === undefined)\n      return /\\d+[\\s/]/g;\n  }\n}\n```\n> If you want **line numbers**, type `=` after specifying the code block languagues.\n> Also, you can specify the start line number.\n> Like below, the line number starts from 101:\n```javascript=101\nvar s = \"JavaScript syntax highlighting\";\nalert(s);\nfunction $initHighlight(block, cls) {\n  try {\n    if (cls.search(/\\bno\\-highlight\\b/) != -1)\n      return process(block, true, 0x0F) +\n             ' class=\"\"';\n  } catch (e) {\n    /* handle exception */\n  }\n  for (var i = 0 / 2; i < classes.length; i++) {\n    if (checkCondition(classes[i]) === undefined)\n      return /\\d+[\\s/]/g;\n  }\n}\n```\n\n> Or you might want to continue the previous code block's line number, use `=+`\n\n```javascript=+\nvar s = \"JavaScript syntax highlighting\";\nalert(s);\n```\n\n> Somtimes you have a super long text without breaks. It's time to use `!` to wrap your code.\n\n```!\nWhen you’re a carpenter making a beautiful chest of drawers, you’re not going to use a piece of plywood on the back.\n```\n\n### Blockquote Tags:\n> Using the syntax below to specifiy your **name, time and color** to vary the blockquotes.\n> [name=ChengHan Wu] [time=Sun, Jun 28, 2015 9:59 PM] [color=#907bf7]\n> > Even support the nest blockquotes!\n> > [name=ChengHan Wu] [time=Sun, Jun 28, 2015 10:00 PM] [color=red]\n\n### Render CSV as table\n\nYou can use write csv in the codeblock:\n\n~~~md\n```csvpreview {header=\"true\"}\nfirstName,lastName,email,phoneNumber\nJohn,Doe,john@doe.com,0123456789\nJane,Doe,jane@doe.com,9876543210\nJames,Bond,james.bond@mi6.co.uk,0612345678\n```\n~~~\n\nwhich rendered to:\n\n```csvpreview {header=\"true\"}\nfirstName,lastName,email,phoneNumber\nJohn,Doe,john@doe.com,0123456789\nJane,Doe,jane@doe.com,9876543210\nJames,Bond,james.bond@mi6.co.uk,0612345678\n```\n\nWe use [Papa Parse](https://www.papaparse.com/) for parsing csv. The parsing option is given in braces: `{}`, and multiple options are seperated by a space. e.g. `{header=\"true\" delimiter=\".\"}`. Please read [their documentation](https://www.papaparse.com/docs#config) as reference.\n\n## Externals\n\n### YouTube\n{%youtube aqz-KE-bpKQ %}\n\n### Vimeo\n{%vimeo 124148255 %}\n\n### Gist\n{%gist schacon/4277%}\n\n### SlideShare\n{%slideshare briansolis/26-disruptive-technology-trends-2016-2018-56796196 %}\n\n### PDF\n**Caution: this might be blocked by your browser if not using an `https` URL.**\n{%pdf https://www.w3.org/TR/WAI-WEBCONTENT/wai-pageauth.pdf %}\n\n## MathJax\n\nYou can render *LaTeX* mathematical expressions using **MathJax**, as on [math.stackexchange.com](http://math.stackexchange.com/):\n\nThe *Gamma function* satisfying $\\Gamma(n) = (n-1)!\\quad\\forall n\\in\\mathbb N$ is via the Euler integral\n\n$$\nx = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.\n$$\n\n$$\n\\Gamma(z) = \\int_0^\\infty t^{z-1}e^{-t}dt\\,.\n$$\n\n> More information about **LaTeX** mathematical expressions [here](http://meta.math.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference).\n\n## UML Diagrams\n\n### Sequence Diagrams\n\nYou can render sequence diagrams like this:\n\n```sequence\nAlice->Bob: Hello Bob, how are you?\nNote right of Bob: Bob thinks\nBob-->Alice: I am good thanks!\nNote left of Alice: Alice responds\nAlice->Bob: Where have you been?\n```\n\n### Flow Charts\n\nFlow charts can be specified like this:\n```flow\nst=>start: Start\ne=>end: End\nop=>operation: My Operation\nop2=>operation: lalala\ncond=>condition: Yes or No?\n\nst->op->op2->cond\ncond(yes)->e\ncond(no)->op2\n```\n\n### Graphviz\n```graphviz\ndigraph hierarchy {\n\n                nodesep=1.0 // increases the separation between nodes\n\n                node [color=Red,fontname=Courier,shape=box] //All nodes will this shape and colour\n                edge [color=Blue, style=dashed] //All the lines look like this\n\n                Headteacher->{Deputy1 Deputy2 BusinessManager}\n                Deputy1->{Teacher1 Teacher2}\n                BusinessManager->ITManager\n                {rank=same;ITManager Teacher1 Teacher2}  // Put them on the same level\n}\n```\n\n### Mermaid\n```mermaid\ngantt\n    title A Gantt Diagram\n\n    section Section\n    A task           :a1, 2014-01-01, 30d\n    Another task     :after a1  , 20d\n    section Another\n    Task in sec      :2014-01-12  , 12d\n    anther task      : 24d\n```\n\n### PlantUML\n```plantuml\nstart\nif (condition A) then (yes)\n  :Text 1;\nelseif (condition B) then (yes)\n  :Text 2;\n  stop\nelseif (condition C) then (yes)\n  :Text 3;\nelseif (condition D) then (yes)\n  :Text 4;\nelse (nothing)\n  :Text else;\nendif\nstop\n```\n\n### Vega-Lite\n```vega\n{\n  \"$schema\": \"https://vega.github.io/schema/vega-lite/v4.json\",\n  \"data\": {\"url\": \"https://vega.github.io/editor/data/barley.json\"},\n  \"mark\": \"bar\",\n  \"encoding\": {\n    \"x\": {\"aggregate\": \"sum\", \"field\": \"yield\", \"type\": \"quantitative\"},\n    \"y\": {\"field\": \"variety\", \"type\": \"nominal\"},\n    \"color\": {\"field\": \"site\", \"type\": \"nominal\"}\n  }\n}\n```\n\n### Mindmap\n\n```markmap\n# markmap-lib\n\n## Links\n\n- <https://markmap.js.org/>\n- [GitHub](https://github.com/gera2ld/markmap-lib)\n\n## Related\n\n- [coc-markmap](https://github.com/gera2ld/coc-markmap)\n- [gatsby-remark-markmap](https://github.com/gera2ld/gatsby-remark-markmap)\n\n## Features\n\n- links\n- **inline** ~~text~~ *styles*\n- multiline\n  text\n```\n\n> More information about **sequence diagrams** syntax [here](http://bramp.github.io/js-sequence-diagrams/).\n> More information about **flow charts** syntax [here](http://adrai.github.io/flowchart.js/).\n> More information about **graphviz** syntax [here](http://www.tonyballantyne.com/graphs.html)\n> More information about **mermaid** syntax [here](http://mermaid-js.github.io/mermaid)\n> More information about **abc** syntax [here](http://abcnotation.com/learn)\n> More information about **plantuml** syntax [here](http://plantuml.com/index)\n> More information about **vega** syntax [here](https://vega.github.io/vega-lite/docs)\n> More information about **fretboard** syntax [here](https://hackmd.io/@docs/fretboard-syntax)\n\nAlert Area\n---\n:::success\nYes :tada:\n:::\n\n:::info\nThis is a message :mega:\n:::\n\n:::warning\nWatch out :zap:\n:::\n\n:::danger\nOh No! :fire:\n:::\n\n:::spoiler Click to show details\nYou found me :stuck_out_tongue_winking_eye:\n:::\n\n## Music\n\n### Abc\n```abc\nX:1\nT:Speed the Plough\nM:4/4\nC:Trad.\nK:G\n|:GABc dedB|dedB dedB|c2ec B2dB|c2A2 A2BA|\nGABc dedB|dedB dedB|c2ec B2dB|A2F2 G4:|\n|:g2gf gdBd|g2f2 e2d2|c2ec B2dB|c2A2 A2df|\ng2gf g2Bd|g2f2 e2d2|c2ec B2dB|A2F2 G4:|\n```\n\n### Fretboard\n\n```fretboard {title=\"horizontal, 6 frets, with nut\", type=\"h6\"}\n-oO-*-\n--o-o-\n-o-oo-\n-o-oO-\n-oo-o-\n-*O-o-\n  3\n```\n\n## Typography\n\n### Headers\n\n```\n# h1 Heading\n## h2 Heading\n### h3 Heading\n#### h4 Heading\n##### h5 Heading\n###### h6 Heading\n```\n\n### Horizontal Rules\n\n___\n\n---\n\n***\n\n\n### Typographic Replacements\n\nEnable typographer option to see result.\n\n(c) (C) (r) (R) (tm) (TM) (p) (P) +-\n\ntest.. test... test..... test?..... test!....\n\n!!!!!! ???? ,,\n\nRemarkable -- awesome\n\n\"Smartypants, double quotes\"\n\n'Smartypants, single quotes'\n\n### Emphasis\n\n**This is bold text**\n\n__This is bold text__\n\n*This is italic text*\n\n_This is italic text_\n\n~~Deleted text~~\n\nlu~lala~\n\nSuperscript: 19^th^\n\nSubscript: H~2~O\n\n++Inserted text++\n\n==Marked text==\n\n{ruby base|rubytext}\n\n### Blockquotes\n\n\n> Blockquotes can also be nested...\n>> ...by using additional greater-than signs right next to each other...\n> > > ...or with spaces between arrows.\n\n\n### Lists\n\n#### Unordered\n\n+ Create a list by starting a line with `+`, `-`, or `*`\n+ Sub-lists are made by indenting 2 spaces:\n  - Marker character change forces new list start:\n    * Ac tristique libero volutpat at\n    + Facilisis in pretium nisl aliquet\n    - Nulla volutpat aliquam velit\n+ Very easy!\n\n#### Ordered\n\n1. Lorem ipsum dolor sit amet\n2. Consectetur adipiscing elit\n3. Integer molestie lorem at massa\n\n\n1. You can use sequential numbers...\n1. ...or keep all the numbers as `1.`\n1. feafw\n2. 332\n3. 242\n4. 2552\n1. e2\n\nStart numbering with offset:\n\n57. foo\n1. bar\n\n### Code\n\nInline `code`\n\nIndented code\n\n    // Some comments\n    line 1 of code\n    line 2 of code\n    line 3 of code\n\n\nBlock code \"fences\"\n\n```\nSample text here...\n```\n\nSyntax highlighting\n\n``` js\nvar foo = function (bar) {\n  return bar++;\n};\n\nconsole.log(foo(5));\n```\n\n### Tables\n\n| Option | Description |\n| ------ | ----------- |\n| data   | path to data files to supply the data that will be passed into templates. |\n| engine | engine to be used for processing templates. Handlebars is the default. |\n| ext    | extension to be used for dest files. |\n\nRight aligned columns\n\n| Option | Description |\n| ------:| -----------:|\n| data   | path to data files to supply the data that will be passed into templates. |\n| engine | engine to be used for processing templates. Handlebars is the default. |\n| ext    | extension to be used for dest files. |\n\nLeft aligned columns\n\n| Option | Description |\n|:------ |:----------- |\n| data   | path to data files to supply the data that will be passed into templates. |\n| engine | engine to be used for processing templates. Handlebars is the default. |\n| ext    | extension to be used for dest files. |\n\nCenter aligned columns\n\n| Option | Description |\n|:------:|:-----------:|\n| data   | path to data files to supply the data that will be passed into templates. |\n| engine | engine to be used for processing templates. Handlebars is the default. |\n| ext    | extension to be used for dest files. |\n\n\n### Links\n[link text](http://dev.nodeca.com)\n[link with title](http://nodeca.github.io/pica/demo/ \"title text!\")\nAutoconverted link https://github.com/nodeca/pica\n\n\n### Images\n![Minion](https://octodex.github.com/images/minion.png)\n![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg \"The Stormtroopocat\")\nLike links, Images also have a footnote style syntax\n![Alt text][id]\nWith a reference later in the document defining the URL location:\n\n[id]: https://octodex.github.com/images/dojocat.jpg  \"The Dojocat\"\n\n![Minion](https://octodex.github.com/images/minion.png =200x200)\nShow the image with given size\n\n### Footnotes\n\nFootnote 1 link[^first].\nFootnote 2 link[^second].\nInline footnote^[Text of inline footnote] definition.\nDuplicated footnote reference[^second].\n\n[^first]: Footnote **can have markup**\n    and multiple paragraphs.\n[^second]: Footnote text.\n\n### Definition Lists\n\nTerm 1\n\n:   Definition 1\nwith lazy continuation.\n\nTerm 2 with *inline markup*\n\n:   Definition 2\n\n        { some code, part of Definition 2 }\n\n    Third paragraph of definition 2.\n\n_Compact style:_\n\nTerm 1\n  ~ Definition 1\n\nTerm 2\n  ~ Definition 2a\n  ~ Definition 2b\n\n### Abbreviations\n\nThis is an HTML abbreviation example.\nIt converts \"HTML\", but keeps intact partial entries like \"xxxHTMLyyy\" and so on.\n\n*[HTML]: Hyper Text Markup Language\n"
  },
  {
    "path": "public/docs/privacy.md.example",
    "content": "Privacy\n===\n\nWe process the following data, for the following purposes:\n\n|your data|our usage|\n|---------|---------|\n|IP-Address|Used to communicate with your browser and our servers. It's may exposed to third-parties which provide resources for this service. These services are, depending on your login method, the document you visit and the setup of this instance: Google, Disqus, MathJax, GitHub, SlideShare/LinkedIn, yahoo, Gravatar, Imgur, Amazon, and Cloudflare.|\n|Usernames and profiles|Your username as well as user profiles that are connected with it are transmitted and stored by us to provide a useful login integration with services like GitHub, Facebook, Twitter, GitLab, Dropbox, Google. Depending on the setup of this CodiMD instance there are maybe other third-parties involved using SAML, LDAP or the integration with a Mattermost instance.|\n|Profile pictures| Your profile picture is either loaded from the service you used to login, the CodiMD instance or Gravatar.|\n|Uploaded pictures| Pictures that are uploaded for documents are either uploaded to Amazon S3, Imgur, a minio instance or the local filesystem of the CodiMD server.|\n\nAll account data and notes are stored in a mysql/postgres/sqlite database. Besides the user accounts and the document themselves also relationships between the documents and the user accounts are stored. This includes ownership, authorship and revisions of all changes made during the creation of a note.\n\nTo delete your account and all your notes owned by your user account, you can find a button in the drop down menu on the front page.\n\nThe deletion of guest notes is not possible. These don't have any ownership and this means we can't connect these to you or anyone else. If you participated in a guest note or a note owned by someone else, your authorship for the revisions is removed from these notes as well. But the content you created will stay in place as the integrity of these notes has to stay untouched.\n"
  },
  {
    "path": "public/docs/release-notes.md",
    "content": "Release Notes\n===\n\n<i class=\"fa fa-tag\"></i> 2.6.0 <i class=\"fa fa-clock-o\"></i> 2025-06-10\n---\n\n[Check out the complete release note][v2_6_0].\n\n[v2_6_0]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_6_0\n\nThis minor release includes several enhancements and fixes to improve the overall functionality and performance of CodiMD.\n\n## Enhancements\n\n- Update GitHub Actions to use the latest versions [#1895](https://github.com/hackmdio/codimd/pull/1895)\n- Update ESLint configuration for ES6 support [#1900](https://github.com/hackmdio/codimd/pull/1900)\n- Add preference to disable table editor shortcuts and migrate preferences to localStorage [#1901](https://github.com/hackmdio/codimd/pull/1901)\n- Add PDF URL validation and content type check [#1896](https://github.com/hackmdio/codimd/pull/1896)\n- Upgrade mermaid to the latest version [#1894](https://github.com/hackmdio/codimd/pull/1894)\n- Add baseURL configuration option to S3 modules [#1876](https://github.com/hackmdio/codimd/pull/1876)\n- Improve contrast on certain elements [#1899](https://github.com/hackmdio/codimd/pull/1899)\n- Bump codemirror version to 5.65.8 [#1908](https://github.com/hackmdio/codimd/pull/1908)\n- Add state parameter to OAuth strategies for enhanced security [#1902](https://github.com/hackmdio/codimd/pull/1902)\n- Configure MiniCssExtractPlugin for production environment in webpack [#1897](https://github.com/hackmdio/codimd/pull/1897)\n- Refactor plugin paths and move custom reveal plugin [#1898](https://github.com/hackmdio/codimd/pull/1898)\n- Update dependencies for abcjs and mermaid.js [#1914](https://github.com/hackmdio/codimd/pull/1914)\n- VSCode: update image to allow development on MBP ARM chips [#1913](https://github.com/hackmdio/codimd/pull/1913)\n\n## Fixes\n\n- Fix: login email should be case insensitive [#1911](https://github.com/hackmdio/codimd/pull/1911)\n- Fix: Lost schema of S3 URL [#1893](https://github.com/hackmdio/codimd/pull/1893)\n- Chore: update docker-compose.yml with build instructions for codimd service [#1917](https://github.com/hackmdio/codimd/pull/1917)\n\n<i class=\"fa fa-tag\"></i> 2.5.4 <i class=\"fa fa-clock-o\"></i> 2024-06-06\n---\n\n[Check out the complete release note][v2_5_4]. Thank you CodiMD community and all our contributors. ❤️\n\n[v2_5_4]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_5_4\n\n## Enhancements\n\n- Add index at revision table for improving system performance [#1856](https://github.com/hackmdio/codimd/pull/1856)\n- Refactor to reuse random filename in filesystem image provider [#1867](https://github.com/hackmdio/codimd/pull/1867)\n\n## Fixes\n\n- Fix exclusion of name attribute from iframe filterXSS allowlist [#1865](https://github.com/hackmdio/codimd/pull/1865)\n- Fix typo: \"opened source\" -> \"open sourced\" [#1869](https://github.com/hackmdio/codimd/pull/1869)\n\n<i class=\"fa fa-tag\"></i> 2.5.3 <i class=\"fa fa-clock-o\"></i> 2024-01-08\n---\n\n[Check out the complete release note][v2_5_3]. Thank you CodiMD community and all our contributors. ❤️\n\n[v2_5_3]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_5_3\n\nIt's a minor fix release that bumps the version number in `package.json`\n\n## Enhancements\n\n- Add `codeium-chrome` extension support [#1851](https://github.com/hackmdio/codimd/pull/1851)\n- Add `check-release` GitHub action workflow that prevents us from forgetting to update the `package.json` during releases again [#1852](https://github.com/hackmdio/codimd/pull/1852)\n\n<i class=\"fa fa-tag\"></i> 2.5.2 <i class=\"fa fa-clock-o\"></i> 2024-01-05\n---\n\n[Check out the complete release note][v2_5_2]. Thank you CodiMD community and all our contributors. ❤️\n\n[v2_5_2]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_5_2\n\nThis is another recovery release that fixes the pandoc DoS issue.\n\n## Enhancements\n\n- Build docker image using github actions\n\n## Fixes\n\n- **\\[Security Issue]** address denial of service issue in actionPandoc\n\n\n<i class=\"fa fa-tag\"></i> 2.5.1 <i class=\"fa fa-clock-o\"></i> 2024-01-03\n---\n\n[Check out the complete release note][v2_5_1]. Thank you CodiMD community and all our contributors. ❤️\n\n[v2_5_1]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_5_1\n\n\n## Security Fixes\n\n- **\\[Security Issue]** Bump `@hackmd/pandoc.js` version to 0.2.0\n\n## Fixes\n\n- Replace mattermost-redux with mattermost/client\n- Fix dependency resolving with prom-client v12\n\n\n<i class=\"fa fa-tag\"></i> 2.5.0 The Formosan hare <i class=\"fa fa-clock-o\"></i> 2023-12-26\n---\n\n<div style=\"text-align: center; margin-bottom: 1em;\">\n  <img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Lepus_sinensis_formosus.jpg/640px-Lepus_sinensis_formosus.jpg\" width=\"600\">\n  <small style=\"display: block;\">The Formosan hare</small>\n</div>\n\n> The Formosan hare (scientific name: Lepus sinensis formosus), a species of the rabbit family, is a subspecies unique to Taiwan. It measures 30-40 centimeters in length, with a tail that's 5-6 centimeters long and ears that are 8-10 centimeters long. Smaller than the Chinese hare, it has brownish eyes.\n> [Wikipedia](https://zh.wikipedia.org/wiki/%E5%8F%B0%E7%81%A3%E9%87%8E%E5%85%94?oldformat=true)\n\n[Check out the complete release note][v2_5_0]. Thank you CodiMD community and all our contributors. ❤️\n\n[v2_5_0]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_5_0\n\n## Security Fixes\n* **\\[Security Issue]** Strip HTML tags for gist id to avoid stored XSS on showing error [Security Issue]\n* **\\[Security Issue]** Upgrade mermaid to version 8.10.2 to avoid prototype pollution\n* **\\[Security Issue]** potential XSS in vimeo embed\n* **\\[Security Issue]** FIX: pandoc security issue\n* **\\[Security Issue]** fix: sanitize pdf url to prevent XSS on inline PDFs\n\n## Fixes\n* Avoid append zero suffix on exporting user data\n* Handle when request url has no valid referer\n* Fix S3 client config passing for image upload\n* Set a proper \"lang\" attribute on <html>\n* Fix matchInContainer false positives\n* Convert \"include\" directives to functions\n* Move HTML-related code from JS to EJS to enable more i18n\n* fix: may referernce out of bound index in clearDuplicatedHistory\n* Feat/csrf export user data\n* sequelize.import deprecation\n* chore: remove unused uglifyjs-webpack-plugin dep\n* fix: should not clear guest history when guest pin note\n* Fix: s3 api supported multiple cloud providers. fixes: https://github.com/hackmdio/codimd/issues/1761\n* Fix: Code Fence parameter parsing\n* Update README.md to remove IE from supporting list\n* FIX: server crash when filename too long\n* fix: use encoded note id to update history\n* 🐛 [fix] modify replacement rule for disqus short-name\n* Fix history page nav\n* Fix the uploadimage form\n* Add the logout callback to prevent exception\n\n## Enhancements\n* Add TeX mhchem extensions for MathJax\n* Upgrade flowchart.js to version 1.15.0\n* Upgrade codemirror to 5.63.2\n* Update de.json in\n* Documentation - add Music section and move abc abd fretboard to this section\n* chore: bump meta-marked to 0.5.0\n* Typos + Better translation for \"Externals\"\n* feat: Migrate to gtag and support GA4\n* 【fix】reword japanese\n* upgrading pg to 8.8.0 to support new scram-sha-256 authentication\n* feat: add organizations whitelist to GitHub OAuth\n* Add oauth2 authorization\n* Update both Traditional and Simplified Chinese locales\n\n## DX\n* Run CI with GitHub Actions\n* Add dev container for GitHub Codespaces and VSCode remote container\n* Add arm64 docker image build.\n* fix(buildpacks): replace custom buildpack with APT buildpack\n* Update minimum required node.js version to v12 with npm package dependencies\n* Upgrade Node.js version\n* Update node.js version in .nvmrc\n* Update npm dependencies\n\n<i class=\"fa fa-tag\"></i> 2.4.2 <i class=\"fa fa-clock-o\"></i> 2022-08-06\n---\n\n## Security Fixes\n- **[Security Issue]** Upgrade flowchart.js to version 1.15.0\n- **[Security Issue]** Upgrade mermaid to 8.10.2\n- **[Security Issue]** Strip HTML tags for gist id to avoid stored XSS on showing error\n- **[Security Issue]** Add CSRF token in export API to prevent security issue\n- **[Security Issue]** Upgrade CodeMirror to 5.63.2\n\n## Fixes\n- Fix container syntax not parsed correctly\n- Handle request url has no valid referer case\n- Fix S3 client config passing for image upload\n- Fix array access index may out of bound\n- Remove unused uglifyjs webpack plugin dependency\n\n## Enhancements\n- Set lang attributes via user locale\n- Use include function instead of directives\n- Extract more keyword for i18n translate\n- Avoid append zero suffix on exporting user data\n- Add TeX mhchem extensions for MathJax\n- Support arm64 docker image\n- Refactor Sequelize model import mechanism due to sequelize.import is deprecated\n- Better german translation\n\n## DX\n- Support DevContainer for GitHub Codespaces and VSCode remote container\n- Run CI with GitHub Actions\n\n<i class=\"fa fa-tag\"></i> 2.4.0 Papilio maraho <i class=\"fa fa-clock-o\"></i> 2021-05-11\n---\n\n<div style=\"text-align: center; margin-bottom: 1em;\">\n  <img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Papilio_maraho_male_ventral_view_20160423.jpg/569px-Papilio_maraho_male_ventral_view_20160423.jpg\" width=\"600\">\n  <small style=\"display: block;\">Papilio maraho</small>\n</div>\n\n> Papilio maraho is a species of butterfly in the family Papilionidae. It is endemic to Taiwan.\n> \\- Wikipedia [Papilio maraho](https://en.wikipedia.org/wiki/Papilio_maraho)\n\n[Check out the complete release note][v2_4_0]. Thank you CodiMD community and all our contributors. ❤️\n\n[v2_4_0]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_4_0\n\n## Enhancements\n\n- Support autofix linter errors\n- Support anonymous updates via API\n- Support mediawiki export format in pandoc export\n- Add some help strings to Prometheus metrics\n- Allow more syntax highlight modes in editor\n- Support TOC level customization\n- Follow Google guidelines to use Google OAuth\n\n## Fixes\n\n- Vimeo won't show up due to the jsonp callback data unable be parsed with jQuery\n- Fix slide mode stored XSS\n- Enforce PG ssl require mode on heroku\n- Webpack exclude path should support windows path\n- Free url can read any md in file system\n- Use encoded noteId when calling updateHistory\n\n## Docs\n\n- Add matrix badge and links to README [#1629](https://github.com/hackmdio/codimd/pull/1629) [@a-andreyev](https://github.com/a-andreyev)\n\n<i class=\"fa fa-tag\"></i> 2.3.1 Isoetes taiwanensis <i class=\"fa fa-clock-o\"></i> 2021-01-04\n---\n\n### Fixes\n\n* Upgrade mermaid to 8.6.4 to make the previous fix works\n\n<i class=\"fa fa-tag\"></i> 2.3.0 Isoetes taiwanensis <i class=\"fa fa-clock-o\"></i> 2020-12-30\n---\n\n<div style=\"text-align: center; margin-bottom: 1em;\">\n  <img src=\"https://upload.wikimedia.org/wikipedia/commons/4/4a/%E5%8F%B0%E7%81%A3%E6%B0%B4%E9%9F%AD.JPG\" width=\"600\">\n  <small style=\"display: block;\">Isoetes taiwanensis</small>\n</div>\n\n> Isoetes taiwanensis is a species of plant in the family Isoetaceae. It is endemic to Taiwan, and the only species of quillwort there. As other quillworts, it is relatively small, with erect leaves 7–24 cm (2.8–9.4 in) long. It grows submersed in shallow ponds for most of the year. IUCN considers it critically endangered because of habitat loss.\n> \\- Wikipedia [Isoetes taiwanensis](https://en.wikipedia.org/wiki/Isoetes_taiwanensis)\n\nIn this release, we focus on polishing existing features, fixing bugs and patching security issues.\n\nWe continue to expand the APIs. CodiMD now supports [\"Update note's content\" and \"delete note\"](https://github.com/hackmdio/codimd/pull/1559) RESTful APIs. Thanks for the great works from [@JamesCamel](https://github.com/JamesCamel) :heart_eyes:\n\nWe also fix several XSS security issues, including [mermaid](https://github.com/hackmdio/codimd/pull/1633), [vega](https://github.com/hackmdio/codimd/pull/1637) and [image lightbox](https://github.com/hackmdio/codimd/pull/1632). We appreciate the security report from [@msrkp](https://github.com/@msrkp), [@Alemmi](https://github.com/Alemmi), and [@nename0\n](https://github.com/nename0).\n\nThis is the last release before the end of this year.\nMerry Christmas to everyone! Let's look forward and see you in the next year. :tada:\n\n[Check out the complete release note][v2_3_0]. Thank you CodiMD community and all our contributors. ❤️\n\n[v2_3_0]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_3_0\n\n### Enhancements\n\n- Fretboard improvements\n- Update and delete note api\n- Allow Sequelize CLI to use options set in config.json\n- Allow specifying option for graphviz\n- Spellcheck: add en_GB dictionary\n\n### Fixes\n\n- Fix ui-edit and ui-both buttons in night mode\n- Don't run jsonlint on .vscode jsonc files\n- Fix image lightbox xss issue\n- Fix mermaid xss issue\n- Check upload image mime type\n- Vega syntax XSS dependencies\n\n<i class=\"fa fa-tag\"></i> 2.2.0 Diploderma swinhonis <i class=\"fa fa-clock-o\"></i> 2020-07-20\n---\n\n<div style=\"text-align: center; margin-bottom: 1em;\">\n  <img src=\"https://i.imgur.com/P1HXrhw.jpg\" width=\"600\">\n  <small style=\"display: block;\">Diploderma swinhonis</small>\n</div>\n\n> Diploderma swinhonis, also known as the Taiwan japalure, Swinhoe's japalure, and Swinhoe's tree lizard, is a species of lizard in the family Agamidae. The species is endemic to Taiwan.\n> \\- Wikipedia [Diploderma swinhonis](https://en.wikipedia.org/wiki/Diploderma_swinhonis)\n\nIn this release, we've added some Markdown renderer plugins, including fretboard guitar, Mindmap, and CSV. We believe the simplicity and the extensibility of markdown can bring more possibilities to you and your workflow. So let's find out more about what we can do with markdown. :100: \n\nWe also fixed a long-lasting issue: CodiMD cannot be hosted under URL subpath perfectly. Check PR [#1551](https://github.com/hackmdio/codimd/pull/1551) for details.\n\nLast but not least, we start standarizing CodiMD API. We drafted [`List my notes`](https://github.com/hackmdio/codimd/pull/1548) API in this release. Stay tuned. :person_in_lotus_position: \n\nHere are some highlights from this release:\n\n- [Fretboard Guitar tab renderer](#Fretboard-Guitar-tab-renderer)\n- [Mindmap rendrer](#Mindmap)\n- [Image Lightbox](#Image-Lightbox-Support)\n- [CSV renderer](#Render-csv-codeblock-as-table)\n\n[Check out the complete release note][v2_2_0]. Thank you CodiMD community and all our contributors. ❤️\n\n[v2_2_0]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_2_0\n\n### Enhancements\n\n- Use array for tags when available\n- Replace btn-social with btn-login-method\n- Set html image meta tag with YAML metadata\n- List my note API\n\n### Fixes\n\n- Update Simplified Chinese translation and fix typography\n- Fix webpack urlpath font loading error\n\n\n\n<i class=\"fa fa-tag\"></i> 2.1.0 Zhangixalus prasinatus <i class=\"fa fa-clock-o\"></i> 2020-05-18\n---\n\n<div style=\"text-align: center; margin-bottom: 1em;\">\n  <img src=\"https://upload.wikimedia.org/wikipedia/commons/thumb/9/9e/Rhacophorus_prasinatus.jpg/640px-Rhacophorus_prasinatus.jpg\" width=\"450\">\n  <small style=\"display: block;\">Zhangixalus prasinatus</small>\n</div>\n\n> Zhangixalus prasinatus is a species of frog in the family Rhacophoridae endemic to northern Taiwan. It is the largest tree frog in Taiwan; females can reach 7 cm (2.8 in) in snout-vent length. It is known from Taipei, Yilan, and Taoyuan.\n> \\- Wikipedia [Zhangixalus prasinatus](https://en.wikipedia.org/wiki/Zhangixalus_prasinatus)\n\nDuring this hard time of COVID-19, it's a pleasure to help people collaborate better with CodiMD. We hope the world will recover from this situation soon. :sunrise: \n\nGood news, we have some goodies for CodiMD including:\n\n- [Support Prometheus metrics](https://hackmd.io/@codimd/v2_1_0#Support-Prometheus-metrics)\n- [Cut docker image size by 57%](https://hackmd.io/@codimd/v2_1_0#Cut-docker-image-size-by-57)\n- [Drop Node 8 Support](https://hackmd.io/@codimd/v2_1_0#Drop-Node-8-Support)\n\n[Check out the complete release note][v2_1_0]. Thank you CodiMD community and all our contributors. ❤️\n\n[v2_1_0]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_1_0\n\n### Enhancements\n\n- Optimize module size\n- Support brace wrapped param in fence lang\n- Upgrade Node.JS version to 10.20.1\n\n### Fixes\n\n- Fix getStatus caused \"TypeError: Converting circular structure to JSON\"\n\n\n<i class=\"fa fa-tag\"></i> 2.0.1 Urocissa caerulea <i class=\"fa fa-clock-o\"></i> 2020-04-09\n---\n\n[CodiMD 2.0.1](https://github.com/hackmdio/codimd/releases/tag/2.0.1) is a minor release fixing bugs introduced in 2.0.0 and earlier versions along with some enhancements. We encourage everyone to upgrade to 2.0.1 now. See how things are going on [GitHub](https://github.com/hackmdio/codimd/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc+milestone%3ANext). Stay tuned and healthy, and we hope you love it!\n\n\n### Enhancements\n\n- Allow inline markdown in spoiler summary syntax\n- Improve visibility of some UI elements\n- Support avatar for OAuth users\n\n### Fixes\n\n- Fix to add missing configs in docker secret\n- Fix not able to upload image using imgur\n- Fix to improve version checker behavior\n- Fix Wikipedia link in 2.0.0 release notes\n- Fix require path for minio\n- Fix check for creating free url notes\n\n[Check out the complete release note][v2_0_1]. Thank you CodiMD community and all our contributors. ❤️\n\n[v2_0_1]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_0_1\n\n<i class=\"fa fa-tag\"></i> 2.0.0 Urocissa caerulea <i class=\"fa fa-clock-o\"></i> 2020-03-02\n---\n\n<div style=\"text-align: center; margin-bottom: 1em;\">\n  <img src=\"https://i.imgur.com/oRbNzRm.jpg\" width=\"600\">\n  <small style=\"display: block;\">Urocissa caerulea</small>\n</div>\n\n> The Taiwan blue magpie (Urocissa caerulea), also called the Taiwan magpie, Formosan blue magpie , or the \"long-tailed mountain lady\", is a species of bird of the crow family. It is endemic to Taiwan.\n> \n> \\- Wikipedia [Taiwan blue magpie](https://en.wikipedia.org/wiki/Taiwan_blue_magpie)\n\nIn the past few months, we delivered not only a bunch of awesome features but also some critical bug fixes. Moreover, we refactored CodiMD's backend and started to write new tests.\n\nTo make it easier to maintain, we dropped legacy code, reorganize the repository, and add new documentation. For these reasons, we decided to make a huge leap toward version 2.0.0.\n\nHere are the highlights coming from version 2.0.0:\n\n- [Multilanguage spellchecker][multilanguage-spellchecker]\n- [Customize editor color schemes][customize-editor-color-schemes]\n- [Export note with Pandoc][support-pandoc-export]\n- [Embed Geolocation data][embedding-geolocation-data]\n- [Version checking][auto-version-check-for-site-admin]\n- [Meet the new CodiMD CLI][meet-the-new-codimd-cli]\n- [Refreshed Documentation structure and new Markdown guides](refreshed-documentation-structure-and-new-markdown-guides)\n\nIt's our pleasure to announce CodiMD `2.0.0`. Enjoy as always :heartpulse:.\n\n[Check out the complete release note][v2_0_0]. Thank you CodiMD community and all our contributors. ❤️\n\n[multilanguage-spellchecker]: https://hackmd.io/@codimd/v2_0_0#Multilanguage-spellchecker\n[customize-editor-color-schemes]: https://hackmd.io/@codimd/v2_0_0#Customize-editor-color-schemes\n[support-pandoc-export]: https://hackmd.io/@codimd/v2_0_0#Support-Pandoc-export\n[embedding-geolocation-data]: https://hackmd.io/@codimd/v2_0_0#Embedding-Geolocation-data\n[auto-version-check-for-site-admin]: https://hackmd.io/@codimd/v2_0_0#Auto-version-check-for-site-admin\n[meet-the-new-codimd-cli]: https://hackmd.io/@codimd/v2_0_0#Meet-the-new-CodiMD-CLI\n[refreshed-documentation-structure-and-new-markdown-guides]: https://hackmd.io/@codimd/v2_0_0#Refreshed-Documentation-structure-and-new-Markdown-guides\n\n[v2_0_0]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_0_0\n\n<i class=\"fa fa-tag\"></i> 1.4.1 <i class=\"fa fa-clock-o\"></i> 2019-12-13\n---\n\n[CodiMD 1.4.1](https://github.com/hackmdio/codimd/releases/tag/1.4.1) is a minor release including bug fixes introduced in 1.4.0 and earlier versions. We encourage everyone to upgrade to 1.4.1 now. Also, we're preparing for the next major release, and you can see how things are going on [GitHub](https://github.com/hackmdio/codimd/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc+milestone%3ANext). Stay tuned, and we hope you love it!\n\n### Fixes\n\n- Fix urlpath in webpack build\n- Fix mysql not bundled in package.json\n- Fix minio image uploading\n- Fix pcheck not parsed url correctly\n- Fix manage_users script\n\n### Enhancement\n\n- Added Scalingo compatible deployment\n\n[Check out the complete release note][v1_4_1]. Thank you CodiMD community and all our contributors. ❤️\n\n[v1_4_1]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv1_4_1\n\n<i class=\"fa fa-tag\"></i> 1.4.0 Syrmaticus mikado <i class=\"fa fa-clock-o\"></i> 2019-11-11\n---\n\n<div style=\"text-align: center; margin-bottom: 1em;\">\n  <img src=\"https://upload.wikimedia.org/wikipedia/commons/6/60/Mikado_Pheasant_398.jpg\" width=\"300\">\n  <small style=\"display: block;\">Mikado Pheasant, photo credits to <a href=\"https://zh.wikipedia.org/wiki/File:Mikado_Pheasant_398.jpg\">Snowyowls from wikipedia</a></small>\n</div>\n\nStarting from version 1.4.0, we'll pick one species from [_the endemic species of Taiwan_](https://en.wikipedia.org/wiki/List_of_endemic_species_of_Taiwan) as version name. Is there anyone still remember we've once used type of coffee as our version name? It's time to revive that good convention, but this time we don't need coffee to stay up all night. 💤\n\nIt has been over 200+ commits since our last release. These are the highlights from version 1.4.0:\n\n- [New table tools][table-tools] - Create table with auto-formatting and keyboard shortcut\n- [Markdownlint integration][markdownlint] - Lint you markdown document\n- [Support PlantUML, vega-lite renderer][more-renderers] - More renderers to come\n- [Support spoiler container, ruby markdown syntax][more-syntax]\n- [New Emoji sets][new-emoji]\n- [Slide mode plugins][slide-mode-plugins]: Elapsed time bar and Spotlight\n\n[Check out the complete release note][v1_4_0]. Thank you CodiMD community and all our contributors. ❤️\n\n[table-tools]: https://hackmd.io/@codimd/v1_4_0#New-Table-Tools\n[markdownlint]: https://hackmd.io/@codimd/v1_4_0#Markdownlint-integration\n[more-renderers]: https://hackmd.io/@codimd/v1_4_0#Support-2-new-render-engines-PlantUML-and-Vega-lite\n[more-syntax]: https://hackmd.io/@codimd/v1_4_0#Suppport-2-New-markdown-syntax-Spoiler-and-Ruby\n[new-emoji]: https://hackmd.io/@codimd/v1_4_0#New-emoji-sets\n[slide-mode-plugins]: https://hackmd.io/@codimd/v1_4_0#Slide-mode-enhancement\n\n[v1_4_0]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv1_4_0\n\n<i class=\"fa fa-tag\"></i> 1.3.1 <i class=\"fa fa-clock-o\"></i> 2019-03-23 00:00\n---\n\n### Enhancements\n* Add some missing translations\n* Add Serbian language\n\n### Fixes\n* Fix broken redirect for empty `serverURL`\n* Fix wrong variable type for HSTS maxAge\n* Fix GitLab snippets showing up without being configured\n* Fix Google's API after disabling Google+\n* Fix broken PDF export\n\n### Contributors\n* atachibana (translator)\n* [Aurélien JANVIER](https://github.com/ajanvier) (translator)\n* [Daan Sprenkels](https://github.com/dsprenkels) (translator)\n* Farizrizaldy (translator)\n* [Luclu7](https://github.com/Luclu7)\n* Sylke Vicious (translator)\n* [toshi0123](https://github.com/toshi0123) & okochi-toshiki\n* [Turakar](https://github.com/Turakar)\n* [Vladan](https://github.com/cvladan) (translator)\n\n<i class=\"fa fa-tag\"></i> 1.3.0 <i class=\"fa fa-clock-o\"></i> 2019-03-03 00:00\n---\n\n### Enhancements\n* Run db migrations on `npm start`\n* Add documentation about integration with AD LDAP\n* Add `rel=\"noopener\"` to all links\n* Add documentation about integration with Nextcloud for authentication\n* Update URL on frontpage to point to codimd.org\n* Replace Fontawesome with Forkawesome\n* Add OpenID support\n* Add print icon to slide view\n* Add auto-complete for language names that are highlighted in codeblocks\n* Improve translations for Chinese, Dutch, French, German, Italien, Korean, Polish, and Russian language\n* Add Download action to published document API\n* Add reset password feature to `manage_users` script\n* Move from own `./tmp` directory to system temp directory\n* Add Etherpad migration guide\n* Move XSS library to a more native position\n* Use full version string to determine changes from the backend\n* Update winston (logging library)\n* Use slide preview in slide example\n* Improve migration handling\n* Update reveal.js to version 3.7.0\n* Replace scrypt library with its successor\n* Replace `to-markdown` with `turndown` (successor library)\n* Update socket.io\n* Add warning on missing base URL\n* Update bootstrap to version 3.4.0\n* Update handlebar\n\n### Fixes\n* Fix paths in GitLab documentation\n* Fix missing `data:` URL in CSP\n* Fix oAuth2 name/label field\n* Fix GitLab API integration\n* Fix auto-completed but not rendered emojis\n* Fix menu organization depending on enabled services\n* Fix some logging in the OT module\n* Fix some unhandled internalOAuthError exception\n* Fix unwanted creation of robots.txt document in \"freeurl-mode\"\n* Fix some links on index page to lead to the right sections on feature page\n* Fix document breaking, empty headlines\n* Fix wrong multiplication for HSTS header seconds\n* Fix wrong subdirectories in exported user data\n* Fix CSP for speaker notes\n* Fix CSP for disqus\n* Fix URL API usage\n* Fix Gist embedding\n* Fix upload provider error message\n* Fix unescaped disqus user names\n* Fix SAML vulnerability\n* Fix link to SAML guide\n* Fix deep dependency problem with node 6.x\n* Fix broken PDF export by wrong unlink call\n* Fix possible XSS attack in MathJax\n\n### Refactors\n* Refactor to use `ws` instead of the the no longer supported `uws`\n* Refactor frontend build system to use webpack version 4\n* Refactor file path configuration (views, uploads, …)\n* Refactor `manage_users` script\n* Refactor handling of template variables\n* Refactor linting to use eslint\n\n### Removes\n* Remove no longer working Octicons\n* Remove links to our old Gitter channel\n* Remove unused library node-uuid\n* Remove unneeded blueimp-md5 dependency\n* Remove speakerdeck due to broken implementation\n\n### Contributors\n* Adam.emts (translator)\n* [Alex Garcia](https://github.com/asg017)\n* [Cédric Couralet (micedre)](https://github.com/micedre)\n* [Claudius Coenen](https://github.com/ccoenen)\n* [Daan Sprenkels](https://github.com/dsprenkels)\n* [David Mehren](https://github.com/davidmehren)\n* [Erona](https://github.com/Eronana)\n* [Felix Yan](https://github.com/felixonmars)\n* [Jonathan](https://github.com/phrix32)\n* Jong-kai Yang (translator)\n* [MartB](https://github.com/MartB)\n* [Max Wu (jackycute)](https://github.com/jackycute)\n* [mcnesium](https://github.com/mcnesium)\n* Nullnine (translator)\n* RanoIP (translator)\n* [SuNbiT](https://github.com/sunbit)\n* Sylke Vicious (translator)\n* Timothee (translator)\n* [WilliButz](https://github.com/WilliButz)\n* [Xaver Maierhofer](https://github.com/xf-)\n* [云屿](https://github.com/cloudyu)\n\n<i class=\"fa fa-tag\"></i> 1.2.1 <i class=\"fa fa-clock-o\"></i> 2018-09-26 00:00\n---\n\n### Enhancements\n* Update Italian translations\n* Update Japanese translations\n* Update markdown-pdf\n* Add support for unix sockets\n* Update \"follow us\" information to Community channel and translation\n* Add Cloudron installation method\n* Add guide for Mattermost authentication\n* Update various packages\n* Add Indonesian language as new translation\n\n### Fixes\n* Fix content types in status router\n* Fix some modal colors in night mode\n* Fix CSP to allow usage of speaker notes\n* Fix some wrong title attributes in the editor toolbar\n* Fix some confusion about the default location of images. It's always the local filesystem now\n* Fix object handling in avatar generation code\n* Finally fix error handling of LZ-String by using self-maintained version\n* Fix migration handling\n* Fix gitlab API version\n* Fix some server crashes caused by PDF creation\n* Fix document length limit on post to `/new`\n* Fix broken youtube embedding on `/features` page\n\n### Refactors\n* Refactor generation of table of contents\n* Refactor \"copyright\"-section to be a \"Powered by\"\n\n### Removes\n* Remove unneeded inline styling\n\n### Deprecations\n* NodeJS version 6\n* Mattermost login integration (is replaced by [generic oAuth2 module](https://github.com/hackmdio/codimd/blob/6ce7b20a7f92ccff2f7f870ff5d116d685310cfd/docs/guides/auth/mattermost-self-hosted.md))\n\n### Honorable mentions\n* [Alex Hesse (Pingu501)](https://github.com/Pingu501)\n* [Alexander Wellbrock (w4tsn)](https://github.com/w4tsn)\n* [Cédric Couralet (micedre)](https://github.com/micedre)\n* [Girish Ramakrishnan (gramakri)](https://github.com/gramakri)\n* [maahl](https://github.com/maahl)\n* [Max Wu (jackycute)](https://github.com/jackycute)\n* [Miranda (ahihi)](https://github.com/ahihi)\n* [Ondřej Slabý (maxer456)](https://github.com/maxer456)\n\n<i class=\"fa fa-tag\"></i> 1.2.0 <i class=\"fa fa-clock-o\"></i> 2018-06-28 00:00\n---\n\n### Announcement\n* HackMD CE is renamed to CodiMD to prevent confusion. [For details see here](https://github.com/hackmdio/codimd#hackmd-ce-became-codimd)\n\n### Enhancements\n* Show full title by hovering over to table of contents entries\n* Add generic OAUTH2 support for authentication\n* Redirect unauthenticated user to login page on \"forbidden\" pages\n* Add ability to add ToS and privacy documents without code changes\n* Add account deletion as part of user self-management\n* Add download of all own notes\n* Add privacy policy example (no legal advice)\n* Increase checkbox size on slides\n* Add support for Azure blob storage for image uploads\n* Add Korean translation\n* Add note about official K8s chart for deployment\n* Add toolbar for markdown shortcuts in editor\n* Add ability to disable Gravatar integration\n* Add print icon to slide menu which leads to the print view.\n* Add sequelize to setup instructions\n* Update various packages\n\n### Fixes\n* Fix local writes for non-existing translations in production\n* Fix wrong documentation about default image upload type\n* Fix possible error if CodiMD is started with wrong working directory\n* Fix issues caused by cached/cacheeable client config\n* Fix issues caused by notes created via curl/API with CRLF line endings\n* Fix broken images for downloaded PDFs while using `filesystem` as `imageUploadType`\n* Fix Unicode URLs when using `allowFreeURL=true`\n\n### Refactors\n* Split auth documentation into multiple documents\n\n### Removes\n* Remove polyfill for `useCDN=false` setups\n* Remove unused and no longer needed symlink from translations\n\n### Honorable mentions\n* [Adam Hoka (ahoka)](https://github.com/ahoka)\n* [Edgar Z. Alvarenga (aivuk)](https://github.com/aivuk)\n* [Jacob Burden (jekrb)](https://github.com/jekrb)\n* [Pedro Ferreira (pferreir)](https://github.com/pferreir)\n* [TC Liu (liuderchi)](https://github.com/liuderchi)\n\n\n<i class=\"fa fa-tag\"></i> 1.1.1-ce <i class=\"fa fa-clock-o\"></i> 2018-05-23 12:00\n---\n\n### Security\n* Fix Google Drive integration leaked `clientSecret` for Google integration\n* Update base64url package\n\n### Fixes\n* Fix typos in integrations\n* Fix high need of file descriptors during build\n* Fix heroku deployment by limiting node version to <10.x\n\n### Refactors\n* Refactor letterAvatars to be compliant with CSP\n\n### Removes\n* Google Drive integration\n\n### Honorable mentions\n* [Max Wu (jackycute)](https://github.com/jackycute)\n\n<i class=\"fa fa-tag\"></i> 1.1.0-ce <i class=\"fa fa-clock-o\"></i> 2018-04-06 12:00\n---\n\n### Security\n* Adding CSP headers\n* Prevent data-leak by wrong LDAP config\n* Generate dynamic `sessionSecret` if none is specified\n\n### Enhancements\n* Add Minio support\n* Allow posting content to new notes by API\n* Add anonymous edit function in restricted mode\n* Add support for more Mimetypes on S3, Minio and local filesystem uploads\n* Add basic CLI tooling for local user management\n* Add referrer policy\n* Add more usable HTML5 tags\n* Add `useridField` in LDAP config\n* Add option for ReportURI for CSP violations\n* Add persistance for night mode\n* Allow setting of `sessionSecret` by environment variable\n* Add night mode to features page\n* Add Riot / Matrix - Community link to help page\n\n### Fixes\n* Fix ToDo-toggle function\n* Fix LDAP provider name in front-end\n* Fix errors on authenticated sessions for deleted users\n* Fix typo in database migration\n* Fix possible data truncation of authorship\n* Minor fixes in README.md\n* Allow usage of ESC-key by codemirror\n* Fix array of emails in LDAP\n* Fix type errors by environment configs\n* Fix error message on some file API errors\n* Fix minor CSS issues in night mode\n\n### Refactors\n* Refactor contact\n* Refactor social media integration on main page\n* Refactor socket.io code to no longer use referrer\n* Refactor webpack config to need less dependencies in package.json\n* Refactor imageRouter for modularity\n* Refactor configs to be camel case\n\n### Removes\n* Remove unused `tokenSecret` from LDAP config\n\n### Deprecations\n* All non-camelcase config\n\n### Honorable mentions\n* [Dario Ernst (Nebukadneza)](https://github.com/Nebukadneza)\n* [David Mehren (davidmehren)](https://github.com/davidmehren)\n* [Dustin Frisch (fooker)](https://github.com/fooker)\n* [Felix Schäfer (thegcat)](https://github.com/thegcat)\n* [Literallie (xxyy)](https://github.com/xxyy)\n* [Marc Deop (marcdeop)](https://github.com/marcdeop)\n* [Max Wu (jackycute)](https://github.com/jackycute)\n* [Robin Naundorf (senk)](https://github.com/senk)\n* [Stefan Bühler (stbuehler)](https://github.com/stbuehler)\n* [Takeaki Matsumoto (takmatsu)](https://github.com/takmatsu)\n* [Tang TsungYi (vazontang)](https://github.com/vazontang)\n* [Zearin (Zearin)](https://github.com/Zearin)\n\n<i class=\"fa fa-tag\"></i> 1.0.1-ce <i class=\"fa fa-clock-o\"></i> 2018-01-19 15:00\n---\n\n### Security\n* Fix Dropbox client secret leak\n\n### Enhancements\n* Improve version handling\n* It's 2018!\n\n### Fixes\n* Fix image alt-tag rendering\n* Fix Dropbox appkey\n\n<i class=\"fa fa-tag\"></i> 1.0.0-ce <i class=\"fa fa-clock-o\"></i> 2018-01-18 12:00\n---\n### License\n* Switch from MIT to AGPL\n\n### Enhancements\n* Improve language support\n* Allow themes for reveal\n* Add dark theme for editor and view\n* Add danish translation\n* Add simplified chinese translation\n* Provide new permission table\n* Make HSTS configurable\n* Make PDF export configurable\n* Add Mattermost auth support\n* Add SAML support\n\n### Fixes\n* Fix regex for speaker notes\n* Fix S3 endpoint support\n* Fix German translation\n* Fix English translation\n* Fix broken profile images\n* Fix XSS attacks\n* Fix history order\n* Fix missing boolean settings\n* Fix LDAP auth\n* Fix too long notes droping content\n* Fix mermaid compatiblity with new version\n* Fix SSL CA path parsing\n\n### Refactors\n* Refactor main page\n* Refactor status pages\n* Refactor config handling\n* Refactor auth backend\n* Refactor code styling\n* Refactor middleware to modules\n\n<i class=\"fa fa-tag\"></i> 0.5.1 `Doppio` <i class=\"fa fa-clock-o\"></i> 2017-03-23 00:20\n---\n### Enhancements\n* Update to indicate version in status API header\n* Update to generate front-end constants on server startup\n* Update to add gitlab api scope option and auto adapt gitlab snippet feature on it\n* Update to add default permission config option\n* Update to add basics for secret management by Docker 1.13\n* Update webpack config to use parallel uglify plugin to speed up production build\n* Update realtime to use timer to avoid memory leaks on busy tick\n* Update to remove history cache to lower application coupling\n* Update to add screenshot on index page\n* Update index layout to add profile on navbar\n* Update to support allow email register option\n* Update to support disable anonymous view option\n* Update to add limited and protected permission\n* Update to allow displaying LDAP provider name on sign-in modal\n* Update to show yaml-metadata and diagram parsing error in the view\n\n### Fixes\n* Fix XSS vulnerability in link regex [Security Issue]\n* Fix todo list item class might add in wrong element\n* Fix pagination error in list.js over v1.5.0\n* Fix update doc from filesystem cause redundant authorship stringify\n* Fix export html to replace fallen cdn tortue.me to cdnjs\n* Fix rendering might result XSS attribute on self closing tag [Security Issue]\n* Fix out of sync when deleting on same cursor position on several clients\n* Fix not determine OT have pending operations properly\n* Fix to keep selections on save and restore info\n* Fix image path problem when using filesystem backend\n* Fix meta error not clear on before rendering\n* Fix duplicated headers anchor link not been updated properly\n* Fix checkLoginStateChanged might fall into infinite loop while calling loginStateChangeEvent\n* Fix to workaround text shadow for font antialias might cause cut off in Edge\n* Fix and refactor extracting content using metaMarked directly might lead in invalid object\n\n### Refactors\n* Refactor editor related code\n* Refactor code with JavaScript Standard Style\n* Refactor templates, partials and rearrange its path\n* Refactor front-end code with more modular concepts\n* Refactor front-end code using ES6 (also unify configs to `config.json`)\n\n### Removes\n- Removed UTF-8 BOM in download function\n\n<i class=\"fa fa-tag\"></i> 0.5.0 `Ristretto` <i class=\"fa fa-clock-o\"></i> 2017-01-02 02:35\n---\n### Enhancements\n* Update year to 2017 (Happy New Year!)\n* Update to improve editor performance by debounce checkEditorScrollbar event\n* Refactor data processing to model definition\n* Update to remove null byte on editor changes\n* Update to remove null byte before saving to DB\n* Update to support Esperanto locale\n* Little improvements (typos, uppercase + accents, better case) for French locale\n* Update features.md publish button name and icon\n\n### Fixes\n* Fix authorship might losing update event because of throttling\n* Fix migration script of revision lacks of definition of primary key\n* Fix to not use diff_cleanupSemantic\n* Fix URL concatenation when uploading images to local filesystem\n* Fix js-url not import correctly\n* Fixed typo: anonmyous\n* Fix codemirror spell checker not considering abbreviation which contain apostrophe in word\n* Fix possible user is undefined in realtime events\n* Fix wrong package name reference in webpack config for bootstrap-validator\n* Fix email option in config not parse correctly\n* Fix mathjax not able to render issue\n\n### Removes\n- Remove LZString compression for data storage\n- Remove LZString compression for some socket.io event data\n\n<i class=\"fa fa-tag\"></i> 0.4.6 `Melya` <i class=\"fa fa-clock-o\"></i> 2016-12-19 17:20\n---\n### Features\n+ Add support of allow free url config option\n+ Add support of allow anonymous config option\n+ Add preferences to editor status bar and add allow override browser keymap option\n+ Add support of s3 and local filesystem for image uploading\n+ Add of support optional email register and signin\n+ Use uWebSocket to improve websocket performance\n+ Use CDNJS by default with https and SRI support\n+ Use Webpack to bundle frontend code\n\n### Enhancements\n* Update to make TOC syntax be case-insensitive\n* Update to handle request with invalid uri\n* Update to auto generate meta description based on content in publish note and slide\n* Update to support haskell, go, typescript and jsx syntax highlighting in code block\n* Update to use workers to leverage intensive work loading\n* Update to support summary tag\n* Change use cdn config option default to be true\n* Update to retry when anytime the socket io disconnect\n* Change to raise socket io timeout, heartbeat interval and timeout to lower offline period\n* Update emoji parser using markdown-it-emoji instead of emojify\n* Optimize finishView selector performance by avoid universal selector\n* Config heroku deployment\n* Update to support Hindi, Swedish locale\n* Update to support wrap syntax for code block\n* Update to support pagination for history list\n\n### Fixes\n* Fix slide mode on print pdf not finish view rendering\n* Fix when server have heavy loading cache might not update to db properly\n* Fix redirection to url without trailing slashes not considering about config urlpath\n* Fix header id and text might affects by mathjax tags\n* Fix possible meta XSS in history list [Security Issue]\n* Fix possible XSS in yaml-metadata and turn using ejs escape syntax than external lib [Security Issue]\n* Fix to allow data attribute of section tag in slide\n* Fix slide might able to add unsafe attribute on section tag which cause XSS [Security Issue]\n* Fix slide might trigger script when processing markdown which cause XSS [Security Issue]\n* Fix published note won't scroll to hash on load\n* Fix mathjax with blockquote might have race condition\n* Fix server reconnect might not resend pending operations\n* Fix slide export pdf styles not applied issue\n* Fix possible unclose HTML and leaked html tags when fail to parse diagrams\n* Fix typos in the `slide-example.md`\n* Fix socket io doc event should setDoc when revision mismatch and no outstanding operation\n* Fix markdown styles conflicting bootstrap on p and ul under alert area\n* Fix finishView mermaid might select and replace whole markdown-body issue\n* Fix code block which in deeper level will not be parsed issue\n* Fix code block highlighting html not escaped when no languages specified\n* Fix client socket on delete event might not delete corresponding history record correctly\n* Fix to handle name or color is undefined error\n* Fix history item event not bind properly on pagination change\n* Fix history time should save in UNIX timestamp to avoid time offset issue\n\n### Removes\n- Drop bower the package manager\n- Remove auto linkify image\n\n<i class=\"fa fa-tag\"></i> 0.4.5 `latte` <i class=\"fa fa-clock-o\"></i> 2016-10-11 01:22\n---\n### Features\n+ Add more environment variables for server configuration\n+ Add setup script for getting started\n+ Add support of deleting note\n+ Add support of shortcut keys which can add and remove symbol surround text\n+ Add support of shortcut keys for changing mode\n+ Add support of i18n (English, Chinese, French, German, Japanese, Spanish, Portuguese, Greek, Italian, Turkish, Russian, Dutch, Croatian, Polish, Ukrainian)\n+ Add support of note info API\n+ Add support of disqus via yaml-metadata\n\n### Enhancements\n* Optimize png images by using zopflipng\n* Update CodeMirror to 5.19.0 and rename jade to pug\n* Update to add cache to history and improve its performance\n* Update default indent to use spaces instead of tabs\n* Improve syntax highlighting performance\n* Update to make client handle syncing error better, use delay to avoid wrong document revision\n* Update to allow CORS as API on revision actions\n* Update to support showing owner on the infobar\n* Update to prevent duplicate client push in queue to lower down server loading\n* Reduce update view debounce time to make preview refresh quicker\n* Update help modal cheatsheet font styles to make it more clear on spaces\n* Update to add revision saving policy\n* Update to support tiddlywiki and mediawiki syntax highlighting in editor\n* Update to support save mode to url and vise versa\n* Update edit and publish icon and change toggle icon for UX  \n* Improve authorship markers update performance\n* Update slide mode to show extra info and support url actions\n* Change the last change user saving strategy\n* Update to support data uri in src attribute of image tag\n* Improve index layout and UX with UI adjustments\n* Update XSS policy to allow iframe and link with custom protocol\n* Update markdown styles to follow github latest layout styles\n* Update slide mode, now respect all meta settings and update default styles\n* Update to make ToC menu always accessible without scrolling\n* Update to make doc only update while filesystem content not match db content\n\n### Fixes\n* Fix README and features document format and grammar issues\n* Fix some potential memory leaks bugs\n* Fix history storage might not fallback correctly\n* Fix to make mathjax expression display in editor correctly (not italic)\n* Fix note title might have unstriped html tags\n* Fix client reconnect should resend last operation\n* Fix a bug when setting both maxAge and expires may cause user can't signin\n* Fix text complete extra tags for blockquote and referrals\n* Fix bug that when window close will make ajax fail and cause cookies set to wrong state\n* Fix markdown render might fall into regex infinite loop\n* Fix syntax error caused by element contain special characters\n* Fix reference error caused by some scripts loading order\n* Fix ToC id naming to avoid possible overlap with user ToC\n* Fix header nav bar rwd detect element should use div tag or it might glitch the layout\n* Fix textcomplete of extra tags for blockquote not match space character in the between\n* Fix text-shadow for text antialiased might cause IE or Edge text cutoff\n\n### Removes\n- Cancel updating history on page unload\n\n<i class=\"fa fa-tag\"></i> 0.4.4 `mocha` <i class=\"fa fa-clock-o\"></i> 2016-08-02 17:10\n---\n### Features\n* Add support of showing authorship in editor\n* Add support of saving authorship\n* Add support of saving authors\n* Add support of slide preview in both mode\n* Add support of all extra syntax in slide mode\n\n### Enhancements\n* Update realtime check and refresh event, compress data to minimize network transfer delay\n* Update to keep showing second level TOC if there is only one first level TOC\n* Update to add expand and collapse toggle for TOC\n* Update to make help modal and text complete hint using consistent reminder text\n* Update to support slideOptions in the yaml metadata for customize slides\n* Update to support redirect back to previous url after signin\n* Update to avoid duplicated rendering slides and reduce DOM wrap\n* Update CodeMirror to version 5.17.1\n* Update to make random color more discrete\n* Update user icon styles to make avatar more obvious\n* Update Bootstrap to 3.3.7 and jQuery to 3.1.0 with related patches\n* Update spell checker to ignore non-english or numeric alphabets\n* Update to auto rolling session for auto extending cookies expiration\n* Update some menu items and UIs\n* Update to reduce realtime timeout and heartbeat interval to handle stale clients quicker\n* Update to force note, publish note, publish slide redirect to their expected url\n* Update to change server pre-rendering engine to markdown-it\n\n### Fixes\n* Workaround vim mode might overwrite copy keyMap on Windows\n* Fix TOC might not update after changeMode\n* Workaround slide mode gets glitch and blurry text on Firefox 47+\n* Fix idle.js not change isAway property on onAway and onAwayBack events\n* Fix http body request entity too large issue\n* Fix google-diff-match-patch encodeURI exception issue\n* Fix yaml metadata title should pass to generateWebTitle\n* Fix spellcheck settings from cookies might not a boolean in string type\n* Fix cookies might not in boolean type cause page refresh loop\n* Fix the signin and logout redirect url might be empty\n* Fix realtime might not clear or remove invalid sockets in queue\n* Fix slide not refresh layout on ajax item loaded\n* Fix retryOnDisconnect not clean up after reconnected\n* Fix some potential memory leaks\n\n<i class=\"fa fa-tag\"></i> 0.4.3 `espresso` <i class=\"fa fa-clock-o\"></i> 2016-06-28 02:04\n---\n### Features\n* Add support of spellcheck\n* Add support of light editor theme\n* Add support of embed pdf\n* Add support of exporting raw html\n* Add revision modal with UIs and support marking patch diff texts\n* Add support of saving note revision\n\n### Enhancements\n* Update to extend login info cookies to 365 days to reduce reductant page refresh\n* Update to support new metadata: title, description, tags and google-analytics\n* Prevent crawling editing note to enhance privacy\n* Update to remove all data lines attributes to gain better update performance\n* Update refresh modal to show more detail informations\n* Update to make cursor tag default as hover mode to prevent tag overlay other lines\n* Update highlight.js to version 9.4.0 and use bower dependency\n* Improve history performance\n\n### Fixes\n* Fix history filter tags and search keyword might not apply after refresh\n* Fix part class in list item might infect buildMap process\n* Fix pdf tmp path is missing a folder slash before timestamp\n* Fix realtime connection get stock when lots of client try to connect at same moment\n* Fix locked or private permission should block any operation if owner is null\n* Add back missing support of image size syntax in 0.4.2\n* Fix update permission might cause duplicate view rendering\n* Fix on paste long document to editor might cause scroll not syncing\n* Workaround CodeMirror won't draw selections outside of the viewport\n* Fix to make socket keep retry after disconnect on server maintenance\n\n### Removes\n- Remove metadata spellcheck support\n- Remove robot meta on note edit page and html template\n\n\n<i class=\"fa fa-tag\"></i> 0.4.2 `cappuccino` <i class=\"fa fa-clock-o\"></i> 2016-04-22 10:43\n---\n### Features\n+ Support sync scrolling to edit area\n+ Support import and export with GitLab snippet\n+ Support GitLab signin\n+ Add cheatsheet and help modal\n\n### Enhancements\n* Upgrade CodeMirror to version 5.15.3\n* Support maintenance mode and gracefully exit process on signal\n* Update to update doc in db when doc in filesystem have newer modified time\n* Update to replace animation acceleration library from gsap to velocity\n* Support image syntax with size\n* Update textcomplete rules to support more conditions\n* Update to use bigger user profile image\n* Support showing signin button only when needed\n\n### Fixes\n* Fix other clients' cursor might disappear or move out of bound\n* Fix to handle user profile image not exists\n* Fix potential toolbar layout glitch\n* Fix imgur uploads should always use https to avoid mix-content warning\n* Fix to change fullscreen key to avoid OS key conflicts\n* Fix and change ESC key in Vim mode\n\n<i class=\"fa fa-tag\"></i> 0.4.1 <i class=\"fa fa-clock-o\"></i> 2016-04-22 10:43\n---\n### Enhancements\n* Support when client domain not provided will use window.location variable\n* Support when domain not provided will use relative path\n* Support DOMAIN and URL_PATH environment variables\n\n\n<i class=\"fa fa-tag\"></i> 0.4.0 `first-year` <i class=\"fa fa-clock-o\"></i> 2016-04-20 14:30\n---\n### Features\n+ Support docs\n+ Support Ionicons and Octicons\n+ Support mermaid diagram\n+ Support import and export with Gist\n+ Support import and export with Google Drive\n+ Support more options in YAML metadata\n+ Support change keymap and indentation size/type\n\n### Enhancements\n* Change header anchor styles\n* Refactor server code and configs\n* Support experimental spell checking\n* Upgrade CodeMirror to 5.13.5\n* Update to emit info and disconnect clients if updater get errors\n* Support to indicate if the note status is created or updated\n* Support more DB types\n* Server now use ORM for DBs\n* Support static file cache\n* Support more ssl settings\n* Improve server stablilty\n* Improve server performance\n* Support Ionicons\n* Support container syntax and styles\n* Improve input performance\n* Change markdown engine from remarkable to markdown-it\n* Server now support set sub url path\n* Support textcomplete in multiple editing\n* Update to filter XSS on rendering\n* Update to make sync scroll lerp on last line\n* Update to make continue list in todo list default as unchecked\n* Support auto indent whole line in list or blockquote\n\n### Fixes\n* Fix status bar might be inserted before loaded\n* Fix mobile layout and focus issues\n* Fix editor layout and styles might not handle correctly\n* Fix all diagram rendering method and styles to avoid partial update gets wrong\n* Fix to ignore process image which already wrapped by link node\n* Fix when cut or patse scroll map might get wrong\n* Fix to handle more socket error and info status\n* Fix textcomplete not matching properly\n* Fix and refactor cursor tag and cursor menu\n* Fix Japanese, Chinese font styles\n* Fix minor bugs of UI and seletor syntaxes\n\n<i class=\"fa fa-tag\"></i> 0.3.4 `techstars` <i class=\"fa fa-clock-o\"></i> 2016-01-19 00:22\n---\n### Features\n+ Beta Support slide mode\n+ Beta Support export to PDF\n+ Support TOC syntax\n+ Support embed slideshare and speakerdeck\n+ Support Graphviz charts\n+ Support YAML metadata\n+ Support private permission\n\n### Enhancements\n* Support pin note in history\n* Support IE9 and above\n* Support specify and continue line number in code block\n* Changed all embed layout to 100% width\n* Added auto detect default mode\n* Support show last change note user\n* Upgrade CodeMirror to 5.10.1 with some manual patches\n* Improved server performance\n* Support autocomplete for code block languages of charts\n\n### Fixes\n* Fixed some server connection issues\n* Fixed several issues cause scrollMap incorrect\n* Fixed cursor animation should not apply on scroll\n* Fixed a possible bug in partial update\n* Fixed internal href should not link out\n* Fixed dropbox saver url not correct\n* Fixed mathjax might not parse properly\n* Fixed sequence diagram might render multiple times\n\n<i class=\"fa fa-tag\"></i> 0.3.3 `moon-festival` <i class=\"fa fa-clock-o\"></i> 2015-09-27 14:00\n---\n### Features\n+ Added status bar below editor\n+ Added resizable grid in both mode\n+ Added title reminder if have unread changes\n+ Support todo list change in the view mode\n+ Support export to HTML\n+ Changed to a new theme, One Dark(modified version)\n\n### Enhancements\n* Support extra tags in todo list\n* Changed overall font styles\n* Optimized build sync scroll map, gain lots better performance\n* Support and improved print styles\n* Support to use CDN\n* Image and link will href to new tab ors window\n* Support auto scroll to corresponding position when change mode from view to edit\n* Minor UI/UX tweaks\n\n### Fixes\n* Change DB schema to support long title\n* Change editable permission icon to avoid misunderstanding\n* Fixed some issues in OT and reconnection\n* Fixed cursor menu and cursor tag are not calculate doc height properly\n* Fixed scroll top might not animate\n* Fixed scroll top not save and restore properly\n* Fixed history might not delete or clear properly\n* Fixed server might not clean client properly\n\n<i class=\"fa fa-tag\"></i> 0.3.2 `typhoon` <i class=\"fa fa-clock-o\"></i> 2015-07-11 12:30\n---\n### Features\n+ Support operational transformation\n+ Support show other user selections\n+ Support show user profile image if available\n\n### Enhancements\n* Updated editor to 5.4.0\n* Change UI share to publish to avoid misleading\n* Added random color in blockquote tag\n* Optimized image renderer, avoid duplicated rendering\n* Optimized building syncscroll map, make it faster\n* Optimized SEO on publish and edit note\n\n<i class=\"fa fa-tag\"></i> 0.3.1 `clearsky` <i class=\"fa fa-clock-o\"></i> 2015-06-30 16:00\n---\n### Features\n+ Added auto table of content\n+ Added basic permission control\n+ Added view count in share note\n\n### Enhancements\n* Toolbar now will hide in single view\n* History time now will auto update\n* Smooth scroll on anchor changed\n* Updated video style\n\n### Fixes\n* Note might not clear when all users disconnect\n* Blockquote tag not parsed properly\n* History style not correct\n\n<i class=\"fa fa-tag\"></i> 0.3.0 `sunrise` <i class=\"fa fa-clock-o\"></i> 2015-06-15 24:00\n---\n### Enhancements\n* Used short url in share notes\n* Added upload image button on toolbar\n* Share notes are now SEO and mobile friendly\n* Updated code block style\n* Newline now will cause line breaks\n* Image now will link out\n* Used otk to avoid race condition\n* Used hash to avoid data inconsistency\n* Optimized server realtime script\n\n### Fixes\n* Composition input might lost or duplicated when other input involved\n* Note title might not save properly\n* Todo list not render properly\n\n<i class=\"fa fa-tag\"></i> 0.2.9 `wildfire` <i class=\"fa fa-clock-o\"></i> 2015-05-30 14:00\n---\n### Features\n+ Support text auto complete\n+ Support cursor tag and random last name\n+ Support online user list\n+ Support show user info in blockquote\n\n### Enhancements\n* Added more code highlighting support\n* Added more continue list support\n* Adjust menu and history filter UI for better UX\n* Adjust sync scoll animte to gain performance\n* Change compression method of dynamic data\n* Optimized render script\n\n### Fixes\n* Access history fallback might get wrong\n* Sync scroll not accurate\n* Sync scroll reach bottom range too much\n* Detect login state change not accurate\n* Detect editor focus not accurate\n* Server not handle some editor events\n\n<i class=\"fa fa-tag\"></i> 0.2.8 `flame` <i class=\"fa fa-clock-o\"></i> 2015-05-15 12:00\n---\n### Features\n+ Support drag-n-drop(exclude firefox) and paste image inline\n+ Support tags filter in history\n+ Support sublime-like shortcut keys\n\n### Enhancements\n* Adjust index description\n* Adjust toolbar ui and view font\n* Remove scroll sync delay and gain accuracy\n\n### Fixes\n* Partial update in the front and the end might not render properly\n* Server not handle some editor events\n\n<i class=\"fa fa-tag\"></i> 0.2.7 `fuel` <i class=\"fa fa-clock-o\"></i> 2015-05-03 12:00\n---\n### Features\n+ Support facebook, twitter, github, dropbox login\n+ Support own history\n\n### Enhancements\n* Adjust history ui\n* Upgrade realtime package\n* Upgrade editor package, now support composition input better\n\n### Fixes\n* Partial update might not render properly\n* Cursor focus might not at correct position\n\n<i class=\"fa fa-tag\"></i> 0.2.6 `zippo` <i class=\"fa fa-clock-o\"></i> 2015-04-24 16:00\n---\n### Features\n+ Support sync scroll\n+ Support partial update\n\n### Enhancements\n* Added feedback ui\n* Adjust animations and delays\n* Adjust editor viewportMargin for performance\n* Adjust emit refresh event occasion\n* Added editor fallback fonts\n* Index page auto focus at history if valid\n\n### Fixes\n* Server might not disconnect client properly\n* Resume connection might restore wrong info\n\n<i class=\"fa fa-tag\"></i> 0.2.5 `lightning` <i class=\"fa fa-clock-o\"></i> 2015-04-14 21:10\n---\n### Features\n+ Support import from dropbox and clipboard\n+ Support more code highlighting\n+ Support mathjax, sequence diagram and flow chart\n\n### Enhancements\n* Adjust toolbar and layout style\n* Adjust mobile layout style\n* Adjust history layout style\n* Server using heartbeat to gain accuracy of online users\n\n### Fixes\n* Virtual keyboard might broken the navbar\n* Adjust editor viewportMargin for preloading content\n\n<i class=\"fa fa-tag\"></i> 0.2.4 `flint` <i class=\"fa fa-clock-o\"></i> 2015-04-10 12:40\n---\n### Features\n+ Support save to dropbox\n+ Show other users' cursor with light color\n\n### Enhancements\n* Adjust toolbar layout style for future\n### Fixes\n* Title might not render properly\n* Code border style might not show properly\n* Server might not connect concurrent client properly\n\n<i class=\"fa fa-tag\"></i> 0.2.3 `light` <i class=\"fa fa-clock-o\"></i> 2015-04-06 20:30\n---\n### Features\n+ Support youtube, vimeo\n+ Support gist\n+ Added quick link in pretty\n+ Added font-smoothing style\n\n### Enhancements\n* Change the rendering engine to remarkable\n* Adjust view, todo list layout style for UX\n+ Added responsive layout check\n+ Auto reload if client version mismatch\n+ Keep history stack after reconnect if nothing changed\n+ Added features page\n\n### Fixes\n* Closetags auto input might not have proper origin\n* Autofocus on editor only if it's on desktop\n* Prevent using real script and iframe tags\n* Sorting in history by time not percise\n\n<i class=\"fa fa-tag\"></i> 0.2.2 `fire` <i class=\"fa fa-clock-o\"></i> 2015-03-27 21:10\n---\n### Features\n+ Support smartLists, smartypants\n+ Support line number on code block\n+ Support tags and search or sort history\n\n### Enhancements\n+ Added delay on socket change\n+ Updated markdown-body width to match github style\n+ Socket changes now won't add to editor's history\n+ Reduce redundant server events\n\n### Fixes\n* Toolbar links might get wrong\n* Wrong action redirections\n\n<i class=\"fa fa-tag\"></i> 0.2.1 `spark` <i class=\"fa fa-clock-o\"></i> 2015-03-17 13:40\n---\n\n### Features\n+ Support github-like todo-list\n+ Support emoji\n\n ### Enhancements\n+ Added more effects on transition\n+ Reduced rendering delay\n+ Auto close and match brackets\n+ Auto close and match tags\n+ Added code fold and fold gutters\n+ Added continue listing of markdown\n\n<i class=\"fa fa-tag\"></i> 0.2.0 `launch-day` <i class=\"fa fa-clock-o\"></i> 2015-03-14 20:20\n---\n### Features\n\n+ Markdown editor\n+ Preview html\n+ Realtime collaborate\n+ Cross-platformed\n+ Recently used history\n"
  },
  {
    "path": "public/docs/slide-example.md",
    "content": "---\ntype: slide\nslideOptions:\n  transition: slide\n---\n\n# Slide example\n\nThis feature still in beta, may have some issues.\n\nFor details please visit:\nhttps://github.com/hakimel/reveal.js/\n\nYou can use `URL query` or `slideOptions` of the YAML metadata to customize your slides.\n\n---\n\n## First slide\n\n`---`\n\nIs the divider of slides\n\n----\n\n### First branch of first the slide\n\n`----`\n\nIs the divider of branches\n\nUse the _Space_ key to navigate through all slides.\n\n----\n\n### Second branch of first the slide\n\nNested slides are useful for adding additional detail underneath a high-level horizontal slide.\n\n---\n\n## Point of View\n\nPress **ESC** to enter the slide overview.\n\n---\n\n## Touch Optimized\n\nPresentations look great on touch devices, like mobile phones and tablets. Simply swipe through your slides.\n\n---\n\n## Fragments\n\n`<!-- .element: class=\"fragment\" data-fragment-index=\"1\" -->`\n\nIs the fragment syntax\n\nHit the next arrow...\n\n... to step through ...\n\n<span>... a<!-- .element: class=\"fragment\" data-fragment-index=\"1\" --></span> <span>fragmented<!-- .element: class=\"fragment\" data-fragment-index=\"2\" --></span> <span>slide.<!-- .element: class=\"fragment\" data-fragment-index=\"3\" --></span>\n\nNote:\n  This slide has fragments which are also stepped through in the notes window.\n\n---\n\n## Fragment Styles\n\nThere are different types of fragments, like:\n\ngrow\n\nshrink\n\nfade-out\n\nfade-up (also down, left and right!)\n\ncurrent-visible\n\nHighlight <span><!-- .element: class=\"fragment highlight-red\" -->red</span> <span><!-- .element: class=\"fragment highlight-blue\" -->blue</span> <span><!-- .element: class=\"fragment highlight-green\"-->green</span>\n\n---\n\n<!-- .slide: data-transition=\"zoom\" -->\n\n## Transition Styles\nDifferent background transitions are available via the transition option. This one's called \"zoom\".\n\n`<!-- .slide: data-transition=\"zoom\" -->`\n\nIs the transition syntax\n\nYou can use:\n\nnone/fade/slide/convex/concave/zoom\n\n---\n\n<!-- .slide: data-transition=\"fade-in convex-out\" -->\n\n`<!-- .slide: data-transition=\"fade-in convex-out\" -->`\n\nAlso, you can set different in/out transition\n\nYou can use:\n\nnone/fade/slide/convex/concave/zoom\n\npostfix with `-in` or `-out`\n\n---\n\n<!-- .slide: data-transition-speed=\"fast\" -->\n\n`<!-- .slide: data-transition-speed=\"fast\" -->`\n\nCustom the transition speed!\n\nYou can use:\n\ndefault/fast/slow\n\n---\n\n## Themes\n\nreveal.js comes with a few themes built in:\n\nBlack (default) - White - League - Sky - Beige - Simple\n\nSerif - Blood - Night - Moon - Solarized\n\nIt can be set in YAML slideOptions\n\n---\n\n<!-- .slide: data-background=\"#1A237E\" -->\n\n`<!-- .slide: data-background=\"#1A237E\" -->`\n\nIs the background syntax\n\n---\n\n<!-- .slide: data-background=\"https://s3.amazonaws.com/hakim-static/reveal-js/image-placeholder.png\" data-background-color=\"#005\" -->\n\n<div style=\"color: #fff;\">\n\n## Image Backgrounds\n\n`<!-- .slide: data-background=\"image.png\"-->`\n\n</div>\n\n----\n\n<!-- .slide: data-background=\"https://s3.amazonaws.com/hakim-static/reveal-js/image-placeholder.png\" data-background-repeat=\"repeat\" data-background-size=\"100px\" data-background-color=\"#005\" -->\n\n<div style=\"color: #fff;\">\n\n## Tiled Backgrounds\n\n`<!-- .slide: data-background=\"image.png\" data-background-repeat=\"repeat\" data-background-size=\"100px\" -->`\n\n</div>\n\n----\n\n<!-- .slide: data-background-video=\"https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.mp4,https://s3.amazonaws.com/static.slid.es/site/homepage/v1/homepage-video-editor.webm\" data-background-color=\"#000000\" -->\n\n<div style=\"background-color: rgba(0, 0, 0, 0.9); color: #fff; padding: 20px;\">\n\n## Video Backgrounds\n\n`<!-- .slide: data-background-video=\"video.mp4,video.webm\" -->`\n\n</div>\n\n----\n\n<!-- .slide: data-background=\"http://i.giphy.com/90F8aUepslB84.gif\" -->\n\n## ... and GIFs!\n\n---\n\n## Pretty Code\n\n``` javascript\nfunction linkify( selector ) {\n  if( supports3DTransforms ) {\n\n    const nodes = document.querySelectorAll( selector );\n\n    for( const i = 0, len = nodes.length; i < len; i++ ) {\n      var node = nodes[i];\n\n      if( !node.className ) {\n        node.className += ' roll';\n      }\n    }\n  }\n}\n```\nCode syntax highlighting courtesy of [highlight.js](http://softwaremaniacs.org/soft/highlight/en/description/).\n\n---\n\n## Marvelous List\n\n- No order here\n- Or here\n- Or here\n- Or here\n\n---\n\n## Fantastic Ordered List\n\n1. One is smaller than...\n2. Two is smaller than...\n3. Three!\n\n---\n\n## Tabular Tables\n\n| Item     | Value | Quantity |\n| ----     | ----- | -------- |\n| Apples   | $1    | 7        |\n| Lemonade | $2    | 18       |\n| Bread    | $3    | 2        |\n\n---\n\n## Clever Quotes\n\n> “For years there has been a theory that millions of monkeys typing at random on millions of typewriters would reproduce the entire works of Shakespeare. The Internet has proven this theory to be untrue.”\n\n---\n\n## Intergalactic Interconnections\n\nYou can link between slides internally, [like this](#/1/3).\n\n---\n\n## Speaker\n\nThere's a [speaker view](https://github.com/hakimel/reveal.js#speaker-notes). It includes a timer, preview of the upcoming slide as well as your speaker notes.\n\nPress the _S_ key to try it out.\n\nNote:\n  Oh hey, these are some notes. They'll be hidden in your presentation, but you can see them if you open the speaker notes window (hit `s` on your keyboard).\n\n---\n\n## Take a Moment\n\nPress `B` or `.` on your keyboard to pause the presentation. This is helpful when you're on stage and want to take distracting slides off the screen.\n\n---\n\n## Print your Slides\n\nDown below you can find a print icon<i class=\"fa fa-fw fa-print\"></i>.\n\nAfter you click on it, use the print function of your browser (either CTRL+P or cmd+P) to print the slides as PDF. [See official reveal.js instructions for details](https://github.com/hakimel/reveal.js#instructions-1)\n\n---\n\n# The End\n"
  },
  {
    "path": "public/docs/yaml-metadata.md",
    "content": "---\nrobots: index, follow\nlang: en\ndir: ltr\nbreaks: true\n---\n\nSupported YAML metadata\n===\n\nFirst you need to insert syntax like this at the **start** of the note:\n```\n---\nYAML metas\n---\n```\n\nReplace the \"YAML metas\" in this section with any YAML options as below.\nYou can also refer to this note's source code.\n\ntitle\n---\nThis option will set the note title which prior than content title.\n\n> default: not set\n\n**Example**\n```yml\ntitle: meta title\n```\n\ndescription\n---\nThis option will set the note description.\n\n> default: not set\n\n**Example**\n```yml\ndescription: meta description\n```\n\nimage\n---\nThis option will set the html meta tag 'image'.\n\n> default: not set\n\n**Example**\n```yml\nimage: https://raw.githubusercontent.com/hackmdio/codimd/develop/public/screenshot.png\n```\n\ntags\n---\nThis option will set the tags which prior than content tags.\n\n> default: not set\n\n**Example**\n```yml\ntags: features, cool, updated\n```\n\nrobots\n---\nThis option will give below meta in the note head meta:\n```xml\n<meta name=\"robots\" content=\"your_meta\">\n```\nSo you can prevent any search engine index your note by set `noindex, nofollow`.\n\n> default: not set\n\n**Example**\n```yml\nrobots: noindex, nofollow\n```\n\nlang\n---\nThis option will set the language of the note, that might alter some typography of it.\nYou can find your the language code in ISO 639-1 standard:\nhttps://en.wikipedia.org/wiki/List_of_ISO_639-1_codes\n\n> default: not set (which will be en)\n\n**Example**\n```yml\nlangs: ja-jp\n```\n\ndir\n---\nThis option specifies the direction of the text in this note.\nYou can only use whether `rtl` or `ltr`.\nLook more at here:\nhttp://www.w3.org/International/questions/qa-html-dir\n\n> default: not set (which will be ltr)\n\n**Example**\n```yml\ndir: rtl\n```\n\nbreaks\n---\nThis option means the hardbreaks in the note will be parsed or be ignore.\nThe original markdown syntax breaks only if you put space twice, but CodiMD choose to breaks every time you enter a break.\nYou can only use whether `true` or `false`.\n\n> default: not set (which will be true)\n\n**Example**\n```yml\nbreaks: false\n```\n\nGA\n---\nThis option allows you to enable Google Analytics with your ID.\n\n> default: not set (which won't enable)\n\n**Example**\n```yml\nGA: UA-12345667-8\n```\n\ndisqus\n---\nThis option allows you to enable Disqus with your shortname.\n\n> default: not set (which won't enable)\n\n**Example**\n```yml\ndisqus: codimd\n```\n\ntoc\n---\n\nThis option allows you to set options regarding the table of contents (toc). Currently, its only option is to set the maxDepth.\n\n**Notice: always use two spaces as indention in YAML metadata!**\n\n\n> **maxDepth:**\n> default: not set (whioch will show everything until level 3 (h1 -- h3))\n> max: 5 (as defined by md-toc.js)\n\n\n**Example**\n\n\ntype\n---\nThis option allows you to switch the document view to the slide preview, to simplify live editing of presentations.\n\n> default: not set\n\n**Example:**\n```yml\ntype: slide\n```\n\nslideOptions\n---\nThis option allows you to provide custom options to slide mode.\nPlease below document for more details:\nhttps://github.com/hakimel/reveal.js/#configuration\n\nYou could also set slide theme which named in below css files:\nhttps://github.com/hakimel/reveal.js/tree/master/css/theme\n\n**Notice: always use two spaces as indention in YAML metadata!**\n\n> default: not set (which use default slide options)\n\n**Example**\n```yml\nslideOptions:\n  transition: fade\n  theme: white\n```\n"
  },
  {
    "path": "public/js/cover.js",
    "content": "/* eslint-env browser, jquery */\n/* global moment, serverurl */\n\nimport {\n  checkIfAuth,\n  clearLoginState,\n  getLoginState,\n  resetCheckAuth,\n  setloginStateChangeEvent\n} from './lib/common/login'\n\nimport {\n  clearDuplicatedHistory,\n  deleteServerHistory,\n  getHistory,\n  getStorageHistory,\n  parseHistory,\n  parseServerToHistory,\n  parseStorageToHistory,\n  postHistoryToServer,\n  removeHistory,\n  saveHistory,\n  saveStorageHistoryToServer\n} from './history'\n\nimport { saveAs } from 'file-saver'\nimport List from 'list.js'\nimport unescapeHTML from 'lodash/unescape'\n\nrequire('./locale')\n\nrequire('../css/cover.css')\nrequire('../css/site.css')\n\nconst options = {\n  valueNames: ['id', 'text', 'timestamp', 'fromNow', 'time', 'tags', 'pinned'],\n  item: `<li class=\"col-xs-12 col-sm-6 col-md-6 col-lg-4\">\n          <span class=\"id\" style=\"display:none;\"></span>\n          <a href=\"#\">\n            <div class=\"item\">\n              <div class=\"ui-history-pin fa fa-thumb-tack fa-fw\"></div>\n              <div class=\"ui-history-close fa fa-close fa-fw\" data-toggle=\"modal\" data-target=\".delete-history-modal\"></div>\n              <div class=\"content\">\n                <h4 class=\"text\"></h4>\n                <p>\n                  <i><i class=\"fa fa-clock-o\"></i> visited </i><i class=\"fromNow\"></i>\n                  <br>\n                  <i class=\"timestamp\" style=\"display:none;\"></i>\n                  <i class=\"time\"></i>\n                </p>\n                <p class=\"tags\"></p>\n              </div>\n            </div>\n          </a>\n        </li>`,\n  page: 18,\n  pagination: [{\n    outerWindow: 1\n  }]\n}\nconst historyList = new List('history', options)\n\nwindow.migrateHistoryFromTempCallback = pageInit\nsetloginStateChangeEvent(pageInit)\n\npageInit()\n\nfunction pageInit () {\n  checkIfAuth(\n    data => {\n      $('.ui-signin').hide()\n      $('.ui-or').hide()\n      $('.ui-welcome').show()\n      if (data.photo) $('.ui-avatar').prop('src', data.photo).show()\n      else $('.ui-avatar').prop('src', '').hide()\n      $('.ui-name').html(data.name)\n      $('.ui-signout').show()\n      $('.ui-history').click()\n      parseServerToHistory(historyList, parseHistoryCallback)\n    },\n    () => {\n      $('.ui-signin').show()\n      $('.ui-or').show()\n      $('.ui-welcome').hide()\n      $('.ui-avatar').prop('src', '').hide()\n      $('.ui-name').html('')\n      $('.ui-signout').hide()\n      parseStorageToHistory(historyList, parseHistoryCallback)\n    }\n  )\n}\n\n$('.masthead-nav > li').click(function () {\n  $(this).siblings().removeClass('active')\n  $(this).addClass('active')\n})\n\n// prevent empty link change hash\n$('a[href=\"#\"]').click(function (e) {\n  e.preventDefault()\n})\n\n$('.ui-home').click(function (e) {\n  if (!$('#home').is(':visible')) {\n    $('.section:visible').hide()\n    $('#home').fadeIn()\n  }\n})\n\n$('.ui-history').click(() => {\n  if (!$('#history').is(':visible')) {\n    $('.section:visible').hide()\n    $('#history').fadeIn()\n  }\n})\n\nfunction checkHistoryList () {\n  if ($('#history-list').children().length > 0) {\n    $('.pagination').show()\n    $('.ui-nohistory').hide()\n    $('.ui-import-from-browser').hide()\n  } else if ($('#history-list').children().length === 0) {\n    $('.pagination').hide()\n    $('.ui-nohistory').slideDown()\n    getStorageHistory(data => {\n      if (data && data.length > 0 && getLoginState() && historyList.items.length === 0) {\n        $('.ui-import-from-browser').slideDown()\n      }\n    })\n  }\n}\n\nfunction parseHistoryCallback (list, notehistory) {\n  checkHistoryList()\n  // sort by pinned then timestamp\n  list.sort('', {\n    sortFunction (a, b) {\n      const notea = a.values()\n      const noteb = b.values()\n      if (notea.pinned && !noteb.pinned) {\n        return -1\n      } else if (!notea.pinned && noteb.pinned) {\n        return 1\n      } else {\n        if (notea.timestamp > noteb.timestamp) {\n          return -1\n        } else if (notea.timestamp < noteb.timestamp) {\n          return 1\n        } else {\n          return 0\n        }\n      }\n    }\n  })\n  // parse filter tags\n  const filtertags = []\n  for (let i = 0, l = list.items.length; i < l; i++) {\n    const tags = list.items[i]._values.tags\n    if (tags && tags.length > 0) {\n      for (let j = 0; j < tags.length; j++) {\n        // push info filtertags if not found\n        let found = false\n        if (filtertags.includes(tags[j])) { found = true }\n        if (!found) { filtertags.push(tags[j]) }\n      }\n    }\n  }\n  buildTagsFilter(filtertags)\n}\n\n// update items whenever list updated\nhistoryList.on('updated', e => {\n  for (let i = 0, l = e.items.length; i < l; i++) {\n    const item = e.items[i]\n    if (item.visible()) {\n      const itemEl = $(item.elm)\n      const values = item._values\n      const a = itemEl.find('a')\n      const pin = itemEl.find('.ui-history-pin')\n      const tagsEl = itemEl.find('.tags')\n      // parse link to element a\n      a.attr('href', `${serverurl}/${values.id}`)\n      // parse pinned\n      if (values.pinned) {\n        pin.addClass('active')\n      } else {\n        pin.removeClass('active')\n      }\n      // parse tags\n      const tags = values.tags\n      if (tags && tags.length > 0 && tagsEl.children().length <= 0) {\n        const labels = []\n        for (let j = 0; j < tags.length; j++) {\n          // push into the item label\n          labels.push(`<span class='label label-default'>${tags[j]}</span>`)\n        }\n        tagsEl.html(labels.join(' '))\n      }\n    }\n  }\n  $('.ui-history-close').off('click')\n  $('.ui-history-close').on('click', historyCloseClick)\n  $('.ui-history-pin').off('click')\n  $('.ui-history-pin').on('click', historyPinClick)\n})\n\nfunction historyCloseClick (e) {\n  e.preventDefault()\n  const id = $(this).closest('a').siblings('span').html()\n  const value = historyList.get('id', id)[0]._values\n  $('.ui-delete-history-modal-msg').text('Do you really want to delete below history?')\n  $('.ui-delete-history-modal-item').html(`<i class=\"fa fa-file-text\"></i> ${value.text}<br><i class=\"fa fa-clock-o\"></i> ${value.time}`)\n  clearHistory = false\n  deleteId = id\n}\n\nfunction historyPinClick (e) {\n  e.preventDefault()\n  const $this = $(this)\n  const id = $this.closest('a').siblings('span').html()\n  const item = historyList.get('id', id)[0]\n  const values = item._values\n  let pinned = values.pinned\n  if (!values.pinned) {\n    pinned = true\n    item._values.pinned = true\n  } else {\n    pinned = false\n    item._values.pinned = false\n  }\n  checkIfAuth(() => {\n    postHistoryToServer(id, {\n      pinned\n    }, (err, result) => {\n      if (!err) {\n        if (pinned) { $this.addClass('active') } else { $this.removeClass('active') }\n      }\n    })\n  }, () => {\n    getHistory(notehistory => {\n      for (let i = 0; i < notehistory.length; i++) {\n        if (notehistory[i].id === id) {\n          notehistory[i].pinned = pinned\n          break\n        }\n      }\n      saveHistory(notehistory)\n      if (pinned) { $this.addClass('active') } else { $this.removeClass('active') }\n    })\n  })\n}\n\n// auto update item fromNow every minutes\nsetInterval(updateItemFromNow, 60000)\n\nfunction updateItemFromNow () {\n  const items = $('.item').toArray()\n  for (let i = 0; i < items.length; i++) {\n    const item = $(items[i])\n    const timestamp = parseInt(item.find('.timestamp').text())\n    item.find('.fromNow').text(moment(timestamp).fromNow())\n  }\n}\n\nvar clearHistory = false\nvar deleteId = null\n\nfunction deleteHistory () {\n  checkIfAuth(() => {\n    deleteServerHistory(deleteId, (err, result) => {\n      if (!err) {\n        if (clearHistory) {\n          historyList.clear()\n          checkHistoryList()\n        } else {\n          historyList.remove('id', deleteId)\n          checkHistoryList()\n        }\n      }\n      $('.delete-history-modal').modal('hide')\n      deleteId = null\n      clearHistory = false\n    })\n  }, () => {\n    if (clearHistory) {\n      saveHistory([])\n      historyList.clear()\n      checkHistoryList()\n      deleteId = null\n    } else {\n      if (!deleteId) return\n      getHistory(notehistory => {\n        const newnotehistory = removeHistory(deleteId, notehistory)\n        saveHistory(newnotehistory)\n        historyList.remove('id', deleteId)\n        checkHistoryList()\n        deleteId = null\n      })\n    }\n    $('.delete-history-modal').modal('hide')\n    clearHistory = false\n  })\n}\n\n$('.ui-delete-history-modal-confirm').click(() => {\n  deleteHistory()\n})\n\n$('.ui-import-from-browser').click(() => {\n  saveStorageHistoryToServer(() => {\n    parseStorageToHistory(historyList, parseHistoryCallback)\n  })\n})\n\n$('.ui-save-history').click(() => {\n  getHistory(data => {\n    const history = JSON.stringify(data)\n    const blob = new Blob([history], {\n      type: 'application/json;charset=utf-8'\n    })\n    saveAs(blob, `codimd_history_${moment().format('YYYYMMDDHHmmss')}`, true)\n  })\n})\n\n$('.ui-open-history').bind('change', e => {\n  const files = e.target.files || e.dataTransfer.files\n  const file = files[0]\n  const reader = new FileReader()\n  reader.onload = () => {\n    const notehistory = JSON.parse(reader.result)\n    // console.log(notehistory);\n    if (!reader.result) return\n    getHistory(data => {\n      let mergedata = data.concat(notehistory)\n      mergedata = clearDuplicatedHistory(mergedata)\n      saveHistory(mergedata)\n      parseHistory(historyList, parseHistoryCallback)\n    })\n    $('.ui-open-history').replaceWith($('.ui-open-history').val('').clone(true))\n  }\n  reader.readAsText(file)\n})\n\n$('.ui-clear-history').click(() => {\n  $('.ui-delete-history-modal-msg').text('Do you really want to clear all history?')\n  $('.ui-delete-history-modal-item').html('There is no turning back.')\n  clearHistory = true\n  deleteId = null\n})\n\n$('.ui-refresh-history').click(() => {\n  const lastTags = $('.ui-use-tags').select2('val')\n  $('.ui-use-tags').select2('val', '')\n  historyList.filter()\n  const lastKeyword = $('.search').val()\n  $('.search').val('')\n  historyList.search()\n  $('#history-list').slideUp('fast')\n  $('.pagination').hide()\n\n  resetCheckAuth()\n  historyList.clear()\n  parseHistory(historyList, (list, notehistory) => {\n    parseHistoryCallback(list, notehistory)\n    $('.ui-use-tags').select2('val', lastTags)\n    $('.ui-use-tags').trigger('change')\n    historyList.search(lastKeyword)\n    $('.search').val(lastKeyword)\n    checkHistoryList()\n    $('#history-list').slideDown('fast')\n  })\n})\n\n$('.ui-delete-user-modal-cancel').click(() => {\n  $('.ui-delete-user').parent().removeClass('active')\n})\n\n$('.ui-logout').click(() => {\n  clearLoginState()\n  location.href = `${serverurl}/logout`\n})\n\nlet filtertags = []\n$('.ui-use-tags').select2({\n  placeholder: $('.ui-use-tags').attr('placeholder'),\n  multiple: true,\n  data () {\n    return {\n      results: filtertags\n    }\n  }\n})\n$('.select2-input').css('width', 'inherit')\nbuildTagsFilter([])\n\nfunction buildTagsFilter (tags) {\n  for (let i = 0; i < tags.length; i++) {\n    tags[i] = {\n      id: i,\n      text: unescapeHTML(tags[i])\n    }\n  }\n  filtertags = tags\n}\n$('.ui-use-tags').on('change', function () {\n  const tags = []\n  const data = $(this).select2('data')\n  for (let i = 0; i < data.length; i++) { tags.push(data[i].text) }\n  if (tags.length > 0) {\n    historyList.filter(item => {\n      const values = item.values()\n      if (!values.tags) return false\n      let found = false\n      for (let i = 0; i < tags.length; i++) {\n        if (values.tags.includes(tags[i])) {\n          found = true\n          break\n        }\n      }\n      return found\n    })\n  } else {\n    historyList.filter()\n  }\n  checkHistoryList()\n})\n\n$('.search').keyup(() => {\n  checkHistoryList()\n})\n\n$('.ui-export-user-data').click(function (e) {\n  document.exportNoteData.submit()\n})\n"
  },
  {
    "path": "public/js/extra.js",
    "content": "/* eslint-env browser, jquery */\n/* global moment, serverurl, plantumlServer, L */\n\nimport Prism from 'prismjs'\nimport hljs from 'highlight.js'\nimport PDFObject from 'pdfobject'\nimport { saveAs } from 'file-saver'\n\nimport escapeHTML from 'lodash/escape'\nimport unescapeHTML from 'lodash/unescape'\n\nimport isURL from 'validator/lib/isURL'\n\nimport { Transformer } from 'markmap-lib'\nimport { Markmap, loadCSS, loadJS } from 'markmap-view'\n\nimport { stripTags } from '../../utils/string'\n\nimport getUIElements from './lib/editor/ui-elements'\nimport { emojifyImageDir } from './lib/editor/constants'\nimport {\n  parseFenceCodeParams,\n  serializeParamToAttribute,\n  deserializeParamAttributeFromElement\n} from './lib/markdown/utils'\nimport { renderFretBoard } from './lib/renderer/fretboard/fretboard'\nimport './lib/renderer/lightbox'\nimport { renderCSVPreview } from './lib/renderer/csvpreview'\n\nimport { escapeAttrValue } from './render'\nimport { sanitizeUrl, isPdfUrl } from './utils'\n\nimport markdownit from 'markdown-it'\nimport markdownitContainer from 'markdown-it-container'\n\n/* Defined regex markdown it plugins */\nimport Plugin from 'markdown-it-regexp'\n\nrequire('prismjs/themes/prism.css')\nrequire('prismjs/components/prism-wiki')\nrequire('prismjs/components/prism-haskell')\nrequire('prismjs/components/prism-go')\nrequire('prismjs/components/prism-typescript')\nrequire('prismjs/components/prism-jsx')\nrequire('prismjs/components/prism-makefile')\nrequire('prismjs/components/prism-gherkin')\n\nrequire('./lib/common/login')\nrequire('../vendor/md-toc')\nlet viz = new window.Viz()\nconst plantumlEncoder = require('plantuml-encoder')\n\nconst ui = getUIElements()\n\n// Initialize markmap transformer\nconst markmapTransformer = new Transformer()\n\n// auto update last change\nwindow.createtime = null\nwindow.lastchangetime = null\nwindow.lastchangeui = {\n  status: $('.ui-status-lastchange'),\n  time: $('.ui-lastchange'),\n  user: $('.ui-lastchangeuser'),\n  nouser: $('.ui-no-lastchangeuser')\n}\n\nconst ownerui = $('.ui-owner')\n\nexport function updateLastChange () {\n  if (!window.lastchangeui) return\n  if (window.createtime) {\n    if (window.createtime && !window.lastchangetime) {\n      window.lastchangeui.status.text('created')\n    } else {\n      window.lastchangeui.status.text('changed')\n    }\n    const time = window.lastchangetime || window.createtime\n    window.lastchangeui.time.html(moment(time).fromNow())\n    window.lastchangeui.time.attr('title', moment(time).format('llll'))\n  }\n}\nsetInterval(updateLastChange, 60000)\n\nwindow.lastchangeuser = null\nwindow.lastchangeuserprofile = null\n\nexport function updateLastChangeUser () {\n  if (window.lastchangeui) {\n    if (window.lastchangeuser && window.lastchangeuserprofile) {\n      const icon = window.lastchangeui.user.children('i')\n      icon.attr('title', window.lastchangeuserprofile.name).tooltip('fixTitle')\n      if (window.lastchangeuserprofile.photo) { icon.attr('style', `background-image:url(${window.lastchangeuserprofile.photo})`) }\n      window.lastchangeui.user.show()\n      window.lastchangeui.nouser.hide()\n    } else {\n      window.lastchangeui.user.hide()\n      window.lastchangeui.nouser.show()\n    }\n  }\n}\n\nwindow.owner = null\nwindow.ownerprofile = null\n\nexport function updateOwner () {\n  if (ownerui) {\n    if (window.owner && window.ownerprofile && window.owner !== window.lastchangeuser) {\n      const icon = ownerui.children('i')\n      icon.attr('title', window.ownerprofile.name).tooltip('fixTitle')\n      const styleString = `background-image:url(${window.ownerprofile.photo})`\n      if (window.ownerprofile.photo && icon.attr('style') !== styleString) { icon.attr('style', styleString) }\n      ownerui.show()\n    } else {\n      ownerui.hide()\n    }\n  }\n}\n\n// get title\nfunction getTitle (view) {\n  let title = ''\n  if (md && md.meta && md.meta.title && (typeof md.meta.title === 'string' || typeof md.meta.title === 'number')) {\n    title = md.meta.title\n  } else {\n    const h1s = view.find('h1')\n    if (h1s.length > 0) {\n      title = h1s.first().text()\n    } else {\n      title = null\n    }\n  }\n  return title\n}\n\n// render title\nexport function renderTitle (view) {\n  let title = getTitle(view)\n  if (title) {\n    title += ' - CodiMD'\n  } else {\n    title = 'CodiMD - Collaborative markdown notes'\n  }\n  return title\n}\n\n// render filename\nexport function renderFilename (view) {\n  let filename = getTitle(view)\n  if (!filename) {\n    filename = 'Untitled'\n  }\n  return filename\n}\n\n// render tags\nexport function renderTags (view) {\n  const tags = []\n  const rawtags = []\n  if (md && md.meta && md.meta.tags && (typeof md.meta.tags === 'string' || typeof md.meta.tags === 'number')) {\n    const metaTags = (`${md.meta.tags}`).split(',')\n    for (let i = 0; i < metaTags.length; i++) {\n      const text = metaTags[i].trim()\n      if (text) rawtags.push(text)\n    }\n  } else {\n    view.find('h6').each((key, value) => {\n      if (/^tags/gmi.test($(value).text())) {\n        const codes = $(value).find('code')\n        for (let i = 0; i < codes.length; i++) {\n          const text = codes[i].innerHTML.trim()\n          if (text) rawtags.push(text)\n        }\n      }\n    })\n  }\n  for (let i = 0; i < rawtags.length; i++) {\n    let found = false\n    for (let j = 0; j < tags.length; j++) {\n      if (tags[j] === rawtags[i]) {\n        found = true\n        break\n      }\n    }\n    if (!found) { tags.push(rawtags[i]) }\n  }\n  return tags\n}\n\nfunction slugifyWithUTF8 (text) {\n  // remove HTML tags and trim spaces\n  let newText = stripTags(text.toString().trim())\n  // replace space between words with dashes\n  newText = newText.replace(/\\s+/g, '-')\n  // slugify string to make it valid as an attribute\n  newText = newText.replace(/([!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~])/g, '')\n  return newText\n}\n\n// parse meta\nexport function parseMeta (md, edit, view, toc, tocAffix) {\n  let lang = null\n  let dir = null\n  let breaks = window.defaultUseHardbreak\n  if (md && md.meta) {\n    const meta = md.meta\n    lang = meta.lang\n    dir = meta.dir\n    breaks = meta.breaks\n  }\n  if (!lang || typeof lang !== 'string') {\n    lang = 'en'\n  }\n  // text language\n  view.attr('lang', lang)\n  toc.attr('lang', lang)\n  tocAffix.attr('lang', lang)\n  if (edit) { edit.attr('lang', lang) }\n\n  // text direction\n  if (dir && typeof dir === 'string') {\n    view.attr('dir', dir)\n    toc.attr('dir', dir)\n    tocAffix.attr('dir', dir)\n  } else {\n    view.removeAttr('dir')\n    toc.removeAttr('dir')\n    tocAffix.removeAttr('dir')\n  }\n  // breaks\n  if (typeof breaks === 'boolean') {\n    md.options.breaks = breaks\n  } else {\n    md.options.breaks = window.defaultUseHardbreak\n  }\n}\n\nwindow.viewAjaxCallback = null\n\n// regex for extra tags\nconst spaceregex = /\\s*/\nconst notinhtmltagregex = /(?![^<]*>|[^<>]*<\\/)/\nlet coloregex = /\\[color=([#|(|)|\\s|,|\\w]*?)\\]/\ncoloregex = new RegExp(coloregex.source + notinhtmltagregex.source, 'g')\nlet nameregex = /\\[name=(.*?)\\]/\nlet timeregex = /\\[time=([:|,|+|-|(|)|\\s|\\w]*?)\\]/\nconst nameandtimeregex = new RegExp(nameregex.source + spaceregex.source + timeregex.source + notinhtmltagregex.source, 'g')\nnameregex = new RegExp(nameregex.source + notinhtmltagregex.source, 'g')\ntimeregex = new RegExp(timeregex.source + notinhtmltagregex.source, 'g')\n\nfunction replaceExtraTags (html) {\n  html = html.replace(coloregex, '<span class=\"color\" data-color=\"$1\"></span>')\n  html = html.replace(nameandtimeregex, '<small><i class=\"fa fa-user\"></i> $1 <i class=\"fa fa-clock-o\"></i> $2</small>')\n  html = html.replace(nameregex, '<small><i class=\"fa fa-user\"></i> $1</small>')\n  html = html.replace(timeregex, '<small><i class=\"fa fa-clock-o\"></i> $1</small>')\n  return html\n}\n\nif (typeof window.mermaid !== 'undefined' && window.mermaid) {\n  window.mermaid.initialize({\n    startOnLoad: false\n  })\n\n  window.mermaid.parseError = function (err, hash) {\n    console.warn(err)\n  }\n}\n\nfunction jsonp (url, callback) {\n  const callbackName = 'jsonp_callback_' + Math.round(1000000000 * Math.random())\n  window[callbackName] = function (data) {\n    delete window[callbackName]\n    document.body.removeChild(script)\n    callback(data)\n  }\n\n  const script = document.createElement('script')\n  script.src = url + (url.indexOf('?') >= 0 ? '&' : '?') + 'callback=' + callbackName\n  document.body.appendChild(script)\n  script.onerror = function (e) {\n    console.error(e)\n    script.remove()\n  }\n}\n\n// dynamic event or object binding here\nexport function finishView (view) {\n  // todo list\n  const lis = view.find('li.raw').removeClass('raw').sortByDepth().toArray()\n\n  for (let li of lis) {\n    let html = $(li).clone()[0].innerHTML\n    const p = $(li).children('p')\n    if (p.length === 1) {\n      html = p.html()\n      li = p[0]\n    }\n    html = replaceExtraTags(html)\n    li.innerHTML = html\n    let disabled = 'disabled'\n    if (typeof editor !== 'undefined' && window.havePermission()) { disabled = '' }\n    if (/^\\s*\\[[x ]]\\s*/.test(html)) {\n      li.innerHTML = html.replace(/^\\s*\\[ ]\\s*/, `<input type=\"checkbox\" class=\"task-list-item-checkbox \"${disabled}><label></label>`)\n        .replace(/^\\s*\\[x]\\s*/, `<input type=\"checkbox\" class=\"task-list-item-checkbox\" checked ${disabled}><label></label>`)\n      if (li.tagName.toLowerCase() !== 'li') {\n        li.parentElement.setAttribute('class', 'task-list-item')\n      } else {\n        li.setAttribute('class', 'task-list-item')\n      }\n    }\n    if (typeof editor !== 'undefined' && window.havePermission()) { $(li).find('input').change(toggleTodoEvent) }\n    // color tag in list will convert it to tag icon with color\n    const tagColor = $(li).closest('ul').find('.color')\n    tagColor.each((key, value) => {\n      $(value).addClass('fa fa-tag').css('color', $(value).attr('data-color'))\n    })\n  }\n\n  // youtube\n  view.find('div.youtube.raw').removeClass('raw')\n    .click(function () {\n      imgPlayiframe(this, '//www.youtube.com/embed/')\n    })\n    // vimeo\n  view.find('div.vimeo.raw').removeClass('raw')\n    .click(function () {\n      imgPlayiframe(this, '//player.vimeo.com/video/')\n    })\n    .each((key, value) => {\n      const videoId = $(value).attr('data-videoid')\n      let urlForJsonp = ''\n      try {\n        const url = new URL(`https://vimeo.com/api/v2/video/${videoId}.json`)\n        if (!url.pathname.startsWith('/api/v2/video/')) {\n          throw new Error(`Invalid vimeo video id: ${videoId}`)\n        }\n        urlForJsonp = `//${url.origin}${url.pathname}`\n      } catch (err) {\n        console.error(err)\n        return\n      }\n      jsonp(urlForJsonp, function (data) {\n        const thumbnailSrc = data[0].thumbnail_large\n        const image = `<img src=\"${thumbnailSrc}\" />`\n        $(value).prepend(image)\n        if (window.viewAjaxCallback) window.viewAjaxCallback()\n      })\n    })\n    // gist\n  view.find('code[data-gist-id]').each((key, value) => {\n    if ($(value).children().length === 0) {\n      // strip HTML tags to avoid stored XSS\n      const gistid = value.getAttribute('data-gist-id')\n      value.setAttribute('data-gist-id', stripTags(gistid))\n      const gistfile = value.getAttribute('data-gist-file')\n      if (gistfile) value.setAttribute('data-gist-file', stripTags(gistfile))\n      const gistline = value.getAttribute('data-gist-line')\n      if (gistline) value.setAttribute('data-gist-line', stripTags(gistline))\n      const gisthighlightline = value.getAttribute('data-gist-highlight-line')\n      if (gisthighlightline) value.setAttribute('data-gist-highlight-line', stripTags(gisthighlightline))\n      const gistshowloading = value.getAttribute('data-gist-show-loading')\n      if (gistshowloading) value.setAttribute('data-gist-show-loading', stripTags(gistshowloading))\n      $(value).gist(window.viewAjaxCallback)\n    }\n  })\n  // sequence diagram\n  const sequences = view.find('div.sequence-diagram.raw').removeClass('raw')\n  sequences.each((key, value) => {\n    try {\n      var $value = $(value)\n      const $ele = $(value).parent().parent()\n\n      const sequence = $value\n      sequence.sequenceDiagram({\n        theme: 'simple'\n      })\n\n      $ele.addClass('sequence-diagram')\n      $value.children().unwrap().unwrap()\n      const svg = $ele.find('> svg')\n      svg[0].setAttribute('viewBox', `0 0 ${svg.attr('width')} ${svg.attr('height')}`)\n      svg[0].setAttribute('preserveAspectRatio', 'xMidYMid meet')\n    } catch (err) {\n      $value.unwrap()\n      $value.parent().append(`<div class=\"alert alert-warning\">${escapeHTML(err)}</div>`)\n      console.warn(err)\n    }\n  })\n  // flowchart\n  const flow = view.find('div.flow-chart.raw').removeClass('raw')\n  flow.each((key, value) => {\n    try {\n      var $value = $(value)\n      const $ele = $(value).parent().parent()\n\n      const chart = window.flowchart.parse($value.text())\n      $value.html('')\n      chart.drawSVG(value, {\n        'line-width': 2,\n        fill: 'none',\n        'font-size': '16px',\n        'font-family': \"'Andale Mono', monospace\"\n      })\n\n      $ele.addClass('flow-chart')\n      $value.children().unwrap().unwrap()\n    } catch (err) {\n      $value.unwrap()\n      $value.parent().append(`<div class=\"alert alert-warning\">${escapeHTML(err)}</div>`)\n      console.warn(err)\n    }\n  })\n  // graphviz\n  var graphvizs = view.find('div.graphviz.raw').removeClass('raw')\n  graphvizs.each(function (key, value) {\n    try {\n      var $value = $(value)\n      const options = deserializeParamAttributeFromElement(value)\n      var $ele = $(value).parent().parent()\n      $value.unwrap()\n      viz.renderString($value.text(), options)\n        .then(graphviz => {\n          if (!graphviz) throw Error('viz.js output empty graph')\n          $value.html(graphviz)\n\n          $ele.addClass('graphviz')\n          $value.children().unwrap()\n        })\n        .catch(err => {\n          viz = new window.Viz()\n          $value.parent().append(`<div class=\"alert alert-warning\">${escapeHTML(err)}</div>`)\n          console.warn(err)\n        })\n    } catch (err) {\n      viz = new window.Viz()\n      $value.parent().append(`<div class=\"alert alert-warning\">${escapeHTML(err)}</div>`)\n      console.warn(err)\n    }\n  })\n  // mermaid\n  const mermaids = view.find('div.mermaid.raw').removeClass('raw')\n  mermaids.each(async (key, value) => {\n    const $value = $(value)\n    const $ele = $value.closest('pre')\n    try {\n      const text = $value.text()\n      // validate the syntax first\n      if (window.mermaid.parse(text)) {\n        $ele.addClass('mermaid')\n        $ele.text(text)\n        // render the diagram\n        const id = `mermaid-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`\n        const { svg, bindFunctions } = await window.mermaid.render(id, text, $ele[0])\n        $ele.html(svg)\n        if (bindFunctions) {\n          bindFunctions($ele[0])\n        }\n      }\n    } catch (err) {\n      $value.unwrap()\n      $ele.append(`<div class=\"alert alert-warning\">${escapeHTML(err)}</div>`)\n      console.warn(err)\n    }\n  })\n  // abc.js\n  const abcs = view.find('div.abc.raw').removeClass('raw')\n  abcs.each((key, value) => {\n    try {\n      var $value = $(value)\n      var $ele = $(value).parent().parent()\n\n      window.ABCJS.renderAbc(value, $value.text())\n\n      $ele.addClass('abc')\n      $value.children().unwrap().unwrap()\n      const svg = $ele.find('> svg')\n      svg[0].setAttribute('viewBox', `0 0 ${svg.attr('width')} ${svg.attr('height')}`)\n      svg[0].setAttribute('preserveAspectRatio', 'xMidYMid meet')\n    } catch (err) {\n      $value.unwrap()\n      $value.parent().append(`<div class=\"alert alert-warning\">${escapeHTML(err)}</div>`)\n      console.warn(err)\n    }\n  })\n  // vega-lite\n  const vegas = view.find('div.vega.raw').removeClass('raw')\n  vegas.each((key, value) => {\n    try {\n      var $value = $(value)\n      var $ele = $(value).parent().parent()\n\n      const specText = $value.text()\n\n      $value.unwrap()\n      window.vegaEmbed($ele[0], JSON.parse(specText), { renderer: 'svg' })\n        .then(result => {\n          $ele.addClass('vega')\n        })\n        .catch(err => {\n          $ele.append(`<div class=\"alert alert-warning\">${escapeHTML(err)}</div>`)\n          console.warn(err)\n        })\n        .finally(() => {\n          if (window.viewAjaxCallback) window.viewAjaxCallback()\n        })\n    } catch (err) {\n      $ele.append(`<div class=\"alert alert-warning\">${escapeHTML(err)}</div>`)\n      console.warn(err)\n    }\n  })\n  // geo map\n  view.find('div.geo.raw').removeClass('raw').each(async function (key, value) {\n    const $elem = $(value).parent().parent()\n    const $value = $(value)\n    const content = $value.text()\n    $value.unwrap()\n\n    try {\n      let position, zoom\n      if (content.match(/^[-\\d.,\\s]+$/)) {\n        const [lng, lat, zoo] = content.split(',').map(parseFloat)\n        zoom = zoo\n        position = [lat, lng]\n      } else {\n        // parse value as address\n        const data = await fetch(`https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(content)}&format=json`).then(r => r.json())\n        if (!data || !data.length) {\n          throw new Error('Location not found')\n        }\n        const { lat, lon } = data[0]\n        position = [lat, lon]\n      }\n      $elem.html('<div class=\"geo-map\"></div>')\n      const map = L.map($elem.find('.geo-map')[0]).setView(position, zoom || 16)\n\n      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {\n        attribution: '<a href=\"https://www.openstreetmap.org/\">OSM</a>',\n        maxZoom: 18\n      }).addTo(map)\n      L.marker(position, {\n        icon: L.icon({\n          iconUrl: `${serverurl}/build/leaflet/images/marker-icon.png`,\n          shadowUrl: `${serverurl}/build/leaflet/images/marker-shadow.png`\n        })\n      }).addTo(map)\n      $elem.addClass('geo')\n    } catch (err) {\n      $elem.append(`<div class=\"alert alert-warning\">${escapeHTML(err)}</div>`)\n      console.warn(err)\n    }\n  })\n  // fretboard\n  const fretboard = view.find('div.fretboard_instance.raw').removeClass('raw')\n  fretboard.each((key, value) => {\n    const params = deserializeParamAttributeFromElement(value)\n    const $value = $(value)\n\n    try {\n      const $ele = $(value).parent().parent()\n      $ele.html(renderFretBoard($value.text(), params))\n      $ele.addClass('fretboard')\n    } catch (err) {\n      $value.unwrap()\n      $value.parent().append(`<div class=\"alert alert-warning\">${escapeHTML(err)}</div>`)\n      console.warn(err)\n    }\n  })\n  // markmap\n  view.find('div.markmap.raw').removeClass('raw').each(async (key, value) => {\n    const $elem = $(value).parent().parent()\n    const $value = $(value)\n    const content = $value.text()\n    $value.unwrap()\n    try {\n      const { root, features } = markmapTransformer.transform(content)\n      // Sanitize node contents to prevent XSS before rendering\n      sanitizeMarkmapNode(root)\n\n      // Load required assets\n      const { styles, scripts } = markmapTransformer.getUsedAssets(features)\n\n      if (styles) loadCSS(styles)\n      if (scripts) loadJS(scripts, { getMarkmap: () => ({ Markmap }) })\n\n      $elem.html('<div class=\"markmap-container\"><svg></svg></div>')\n      Markmap.create($elem.find('svg')[0], {\n        duration: 0,\n        maxWidth: 0\n      }, root)\n    } catch (err) {\n      $elem.html(`<div class=\"alert alert-warning\">${escapeHTML(err)}</div>`)\n      console.warn(err)\n    }\n  })\n\n  // image href new window(emoji not included)\n  const images = view.find('img.raw[src]').removeClass('raw')\n  images.each((key, value) => {\n    // if it's already wrapped by link, then ignore\n    const $value = $(value)\n    $value[0].onload = e => {\n      if (window.viewAjaxCallback) window.viewAjaxCallback()\n    }\n  })\n  // blockquote\n  const blockquote = view.find('blockquote.raw').removeClass('raw')\n  const blockquoteP = blockquote.find('p')\n  blockquoteP.each((key, value) => {\n    let html = $(value).html()\n    html = replaceExtraTags(html)\n    $(value).html(html)\n  })\n  // color tag in blockquote will change its left border color\n  const blockquoteColor = blockquote.find('.color')\n  blockquoteColor.each((key, value) => {\n    $(value).closest('blockquote').css('border-left-color', $(value).attr('data-color'))\n  })\n  // slideshare\n  view.find('div.slideshare.raw').removeClass('raw')\n    .each((key, value) => {\n      $.ajax({\n        type: 'GET',\n        url: `//www.slideshare.net/api/oembed/2?url=http://www.slideshare.net/${$(value).attr('data-slideshareid')}&format=json`,\n        jsonp: 'callback',\n        dataType: 'jsonp',\n        success (data) {\n          const $html = $(data.html)\n          const iframe = $html.closest('iframe')\n          const caption = $html.closest('div')\n          const inner = $('<div class=\"inner\"></div>').append(iframe)\n          const height = iframe.attr('height')\n          const width = iframe.attr('width')\n          const ratio = (height / width) * 100\n          inner.css('padding-bottom', `${ratio}%`)\n          $(value).html(inner).append(caption)\n          if (window.viewAjaxCallback) window.viewAjaxCallback()\n        }\n      })\n    })\n    // speakerdeck\n  view.find('div.speakerdeck.raw').removeClass('raw')\n    .each((key, value) => {\n      const url = `https://speakerdeck.com/${$(value).attr('data-speakerdeckid')}`\n      const inner = $('<a>Speakerdeck</a>')\n      inner.attr('href', url)\n      inner.attr('rel', 'noopener noreferrer')\n      inner.attr('target', '_blank')\n      $(value).append(inner)\n    })\n    // pdf\n  view.find('div.pdf.raw').removeClass('raw')\n    .each(function (key, value) {\n      const url = $(value).attr('data-pdfurl')\n      const cleanUrl = sanitizeUrl(url)\n      const inner = $('<div></div>')\n      $(this).append(inner)\n\n      // First check URL format\n      const isPDFByExtension = /\\.pdf(\\?.*)?$/i.test(cleanUrl) || cleanUrl.includes('pdf')\n\n      if (isPDFByExtension) {\n        // Show loading message while we check content type\n        const loadingMessage = $('<div class=\"alert alert-info\">Verifying PDF file...</div>')\n        inner.html(loadingMessage)\n\n        // Perform additional validation with HEAD request\n        isPdfUrl(cleanUrl).then(isPDFByContentType => {\n          if (isPDFByContentType) {\n            // Valid PDF by content type, embed it\n            PDFObject.embed(cleanUrl, inner, {\n              height: '400px'\n            })\n          } else {\n            // URL format looks like PDF but content type doesn't match\n            inner.html('<div class=\"alert alert-warning\">The URL looks like a PDF but the server didn\\'t confirm it has a PDF content type.</div>')\n            console.warn('URL has PDF extension but content type is not application/pdf:', cleanUrl)\n\n            // Try to embed anyway as a fallback\n            setTimeout(() => {\n              PDFObject.embed(cleanUrl, inner, {\n                height: '400px',\n                fallbackLink: 'This doesn\\'t appear to be a valid PDF. <a href=\"[url]\">Click here to try downloading it directly</a>.'\n              })\n            }, 1)\n          }\n        })\n      } else {\n        // Not a valid PDF URL by extension\n        inner.html('<div class=\"alert alert-danger\">Invalid PDF URL. The URL must point to a PDF file.</div>')\n        console.warn('Invalid PDF URL format:', cleanUrl)\n      }\n    })\n    // syntax highlighting\n  view.find('code.raw').removeClass('raw')\n    .each((key, value) => {\n      const langDiv = $(value)\n      if (langDiv.length > 0) {\n        const reallang = langDiv[0].className.replace(/hljs|wrap/g, '').trim()\n        const codeDiv = langDiv.find('.code')\n        let code = ''\n        if (codeDiv.length > 0) code = codeDiv.html()\n        else code = langDiv.html()\n        var result\n        if (!reallang) {\n          result = {\n            value: code\n          }\n        } else if (reallang === 'haskell' || reallang === 'go' || reallang === 'typescript' || reallang === 'jsx' || reallang === 'gherkin') {\n          code = unescapeHTML(code)\n          result = {\n            value: Prism.highlight(code, Prism.languages[reallang])\n          }\n        } else if (reallang === 'tiddlywiki' || reallang === 'mediawiki') {\n          code = unescapeHTML(code)\n          result = {\n            value: Prism.highlight(code, Prism.languages.wiki)\n          }\n        } else if (reallang === 'cmake') {\n          code = unescapeHTML(code)\n          result = {\n            value: Prism.highlight(code, Prism.languages.makefile)\n          }\n        } else {\n          code = unescapeHTML(code)\n          const languages = hljs.listLanguages()\n          if (!languages.includes(reallang)) {\n            result = hljs.highlightAuto(code)\n          } else {\n            result = hljs.highlight(reallang, code)\n          }\n        }\n        if (codeDiv.length > 0) codeDiv.html(result.value)\n        else langDiv.html(result.value)\n      }\n    })\n    // mathjax\n  const mathjaxdivs = view.find('span.mathjax.raw').removeClass('raw').toArray()\n  try {\n    if (mathjaxdivs.length > 1) {\n      window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, mathjaxdivs])\n      window.MathJax.Hub.Queue(window.viewAjaxCallback)\n    } else if (mathjaxdivs.length > 0) {\n      window.MathJax.Hub.Queue(['Typeset', window.MathJax.Hub, mathjaxdivs[0]])\n      window.MathJax.Hub.Queue(window.viewAjaxCallback)\n    }\n  } catch (err) {\n    console.warn(err)\n  }\n\n  // register details toggle for scrollmap recalulation\n  view.find('details.raw').removeClass('raw').each(function (key, val) {\n    $(val).on('toggle', window.viewAjaxCallback)\n  })\n\n  // render title\n  document.title = renderTitle(view)\n}\n\n// only static transform should be here\nexport function postProcess (code) {\n  const result = $(`<div>${code}</div>`)\n  // process style tags\n  result.find('style').each((key, value) => {\n    let html = $(value).html()\n    // unescape > symbel inside the style tags\n    html = html.replace(/&gt;/g, '>')\n    // remove css @import to prevent XSS\n    html = html.replace(/@import url\\(([^)]*)\\);?/gi, '')\n    $(value).html(html)\n  })\n  // link should open in new window or tab\n  // also add noopener to prevent clickjacking\n  // See details: https://mathiasbynens.github.io/rel-noopener/\n  result.find('a:not([href^=\"#\"]):not([target])').attr('target', '_blank').attr('rel', 'noopener')\n  // update continue line numbers\n  const linenumberdivs = result.find('.gutter.linenumber').toArray()\n  for (let i = 0; i < linenumberdivs.length; i++) {\n    if ($(linenumberdivs[i]).hasClass('continue')) {\n      const startnumber = linenumberdivs[i - 1] ? parseInt($(linenumberdivs[i - 1]).find('> span').last().attr('data-linenumber')) : 0\n      $(linenumberdivs[i]).find('> span').each((key, value) => {\n        $(value).attr('data-linenumber', startnumber + key + 1)\n      })\n    }\n  }\n  // show yaml meta paring error\n  if (md.metaError) {\n    var warning = result.find('div#meta-error')\n    if (warning && warning.length > 0) {\n      warning.text(md.metaError)\n    } else {\n      warning = $(`<div id=\"meta-error\" class=\"alert alert-warning\">${escapeHTML(md.metaError)}</div>`)\n      result.prepend(warning)\n    }\n  }\n  return result\n}\nwindow.postProcess = postProcess\n\nvar domevents = Object.getOwnPropertyNames(document).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(Object.getPrototypeOf(document)))).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(window))).filter(function (i) {\n  return !i.indexOf('on') && (document[i] === null || typeof document[i] === 'function')\n}).filter(function (elem, pos, self) {\n  return self.indexOf(elem) === pos\n})\n\nexport function removeDOMEvents (view) {\n  for (var i = 0, l = domevents.length; i < l; i++) {\n    view.find('[' + domevents[i] + ']').removeAttr(domevents[i])\n  }\n}\nwindow.removeDOMEvents = removeDOMEvents\n\nfunction generateCleanHTML (view) {\n  const src = view.clone()\n  const eles = src.find('*')\n  // remove syncscroll parts\n  eles.removeClass('part')\n  src.find('*[class=\"\"]').removeAttr('class')\n  eles.removeAttr('data-startline data-endline')\n  src.find(\"a[href^='#'][smoothhashscroll]\").removeAttr('smoothhashscroll')\n  // remove gist content\n  src.find('code[data-gist-id]').children().remove()\n  // disable todo list\n  src.find('input.task-list-item-checkbox').attr('disabled', '')\n  // replace emoji image path\n  src.find('img.emoji').each((key, value) => {\n    let name = $(value).attr('alt')\n    name = name.substr(1)\n    name = name.slice(0, name.length - 1)\n    $(value).attr('src', `https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/images/basic/${name}.png`)\n  })\n  // replace video to iframe\n  src.find('div[data-videoid]').each((key, value) => {\n    const id = $(value).attr('data-videoid')\n    const style = $(value).attr('style')\n    let url = null\n    if ($(value).hasClass('youtube')) {\n      url = 'https://www.youtube.com/embed/'\n    } else if ($(value).hasClass('vimeo')) {\n      url = 'https://player.vimeo.com/video/'\n    }\n    if (url) {\n      const iframe = $('<iframe frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>')\n      iframe.attr('src', url + id)\n      iframe.attr('style', style)\n      $(value).html(iframe)\n    }\n  })\n  return src\n}\n\nexport function exportToRawHTML (view) {\n  const filename = `${renderFilename(ui.area.markdown)}.html`\n  const src = generateCleanHTML(view)\n  $(src).find('a.anchor').remove()\n  const html = src[0].outerHTML\n  const blob = new Blob([html], {\n    type: 'text/html;charset=utf-8'\n  })\n  saveAs(blob, filename, true)\n}\n\n// extract markdown body to html and compile to template\nexport function exportToHTML (view) {\n  const title = renderTitle(ui.area.markdown)\n  const filename = `${renderFilename(ui.area.markdown)}.html`\n  const src = generateCleanHTML(view)\n  // generate toc\n  const toc = $('#ui-toc').clone()\n  toc.find('*').removeClass('active').find(\"a[href^='#'][smoothhashscroll]\").removeAttr('smoothhashscroll')\n  const tocAffix = $('#ui-toc-affix').clone()\n  tocAffix.find('*').removeClass('active').find(\"a[href^='#'][smoothhashscroll]\").removeAttr('smoothhashscroll')\n  // generate html via template\n  $.get(`${serverurl}/build/html.min.css`, css => {\n    $.get(`${serverurl}/views/html.hbs`, data => {\n      const template = window.Handlebars.compile(data)\n      const context = {\n        url: serverurl,\n        title,\n        css,\n        html: src[0].outerHTML,\n        'ui-toc': toc.html(),\n        'ui-toc-affix': tocAffix.html(),\n        lang: (md && md.meta && md.meta.lang) ? `lang=\"${escapeAttrValue(md.meta.lang)}\"` : null,\n        dir: (md && md.meta && md.meta.dir) ? `dir=\"${escapeAttrValue(md.meta.dir)}\"` : null\n      }\n      const html = template(context)\n      //        console.log(html);\n      const blob = new Blob([html], {\n        type: 'text/html;charset=utf-8'\n      })\n      saveAs(blob, filename, true)\n    })\n  })\n}\n\n// jQuery sortByDepth\n$.fn.sortByDepth = function () {\n  const ar = this.map(function () {\n    return {\n      length: $(this).parents().length,\n      elt: this\n    }\n  }).get()\n\n  const result = []\n  let i = ar.length\n  ar.sort((a, b) => a.length - b.length)\n  while (i--) {\n    result.push(ar[i].elt)\n  }\n  return $(result)\n}\n\nfunction toggleTodoEvent (e) {\n  const startline = $(this).closest('li').attr('data-startline') - 1\n  const line = window.editor.getLine(startline)\n  const matches = line.match(/^[>\\s-]*[-+*]\\s\\[([x ])\\]/)\n  if (matches && matches.length >= 2) {\n    let checked = null\n    if (matches[1] === 'x') { checked = true } else if (matches[1] === ' ') { checked = false }\n    const replacements = matches[0].match(/(^[>\\s-]*[-+*]\\s\\[)([x ])(\\])/)\n    window.editor.replaceRange(checked ? ' ' : 'x', {\n      line: startline,\n      ch: replacements[1].length\n    }, {\n      line: startline,\n      ch: replacements[1].length + 1\n    }, '+input')\n  }\n}\n\n// remove hash\nfunction removeHash () {\n  history.pushState('', document.title, window.location.pathname + window.location.search)\n}\n\nlet tocExpand = false\n\nfunction checkExpandToggle () {\n  const toc = $('.ui-toc-dropdown .toc')\n  const expand = $('.expand-toggle.expand-all')\n  const collapse = $('.expand-toggle.collapse-all')\n  if (!tocExpand) {\n    toc.removeClass('expand')\n    expand.show()\n    collapse.hide()\n  } else {\n    toc.addClass('expand')\n    expand.hide()\n    collapse.show()\n  }\n}\n\n// toc\nexport function generateToc (id) {\n  const target = $(`#${id}`)\n  target.html('')\n  /* eslint-disable no-unused-vars */\n\n  var tocOptions = md.meta.toc || {}\n  var maxLevel = (typeof tocOptions.maxLevel === 'number' && tocOptions.maxLevel > 0) ? tocOptions.maxLevel : window.defaultTocDepth\n\n  var toc = new window.Toc('doc', {\n    level: maxLevel,\n    top: -1,\n    class: 'toc',\n    ulClass: 'nav',\n    targetId: id,\n    process: getHeaderContent\n  })\n  /* eslint-enable no-unused-vars */\n  if (target.text() === 'undefined') { target.html('') }\n  checkExpandToggle()\n  const tocMenu = $('body').children('.toc-menu')\n  target.append(tocMenu.clone().show())\n  const toggle = $('.expand-toggle', target)\n  const backtotop = $('.back-to-top', target)\n  const gotobottom = $('.go-to-bottom', target)\n  toggle.click(e => {\n    e.preventDefault()\n    e.stopPropagation()\n    tocExpand = !tocExpand\n    checkExpandToggle()\n  })\n  backtotop.click(e => {\n    e.preventDefault()\n    e.stopPropagation()\n    if (window.scrollToTop) { window.scrollToTop() }\n    removeHash()\n  })\n  gotobottom.click(e => {\n    e.preventDefault()\n    e.stopPropagation()\n    if (window.scrollToBottom) { window.scrollToBottom() }\n    removeHash()\n  })\n}\n\n// smooth all hash trigger scrolling\nexport function smoothHashScroll () {\n  const hashElements = $(\"a[href^='#']:not([smoothhashscroll])\").toArray()\n\n  for (const element of hashElements) {\n    const $element = $(element)\n    const hash = element.hash\n    if (hash) {\n      $element.on('click', function (e) {\n        // store hash\n        const hash = decodeURIComponent(this.hash)\n        // escape special characters in jquery selector\n        const $hash = $(hash.replace(/(:|\\.|\\[|\\]|,)/g, '\\\\$1'))\n        // return if no element been selected\n        if ($hash.length <= 0) return\n        // prevent default anchor click behavior\n        e.preventDefault()\n        // animate\n        $('body, html').stop(true, true).animate({\n          scrollTop: $hash.offset().top\n        }, 100, 'linear', () => {\n          // when done, add hash to url\n          // (default click behaviour)\n          window.location.hash = hash\n        })\n      })\n      $element.attr('smoothhashscroll', '')\n    }\n  }\n}\n\nfunction imgPlayiframe (element, src) {\n  if (!$(element).attr('data-videoid')) return\n  const iframe = $(\"<iframe frameborder='0' webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>\")\n  $(iframe).attr('src', `${src + $(element).attr('data-videoid')}?autoplay=1`)\n  $(element).find('img').css('visibility', 'hidden')\n  $(element).append(iframe)\n}\n\nconst anchorForId = id => {\n  const anchor = document.createElement('a')\n  anchor.className = 'anchor hidden-xs'\n  anchor.href = `#${id}`\n  anchor.innerHTML = '<i class=\"fa fa-link\"></i>'\n  anchor.title = id\n  return anchor\n}\n\nconst createHeaderId = (headerContent, headerIds = null) => {\n  // to escape characters not allow in css and humanize\n  const slug = slugifyWithUTF8(headerContent)\n  let id\n  if (window.linkifyHeaderStyle === 'keep-case') {\n    id = slug\n  } else if (window.linkifyHeaderStyle === 'lower-case') {\n    // to make compatible with GitHub, GitLab, Pandoc and many more\n    id = slug.toLowerCase()\n  } else if (window.linkifyHeaderStyle === 'gfm') {\n    // see GitHub implementation reference:\n    // https://gist.github.com/asabaylus/3071099#gistcomment-1593627\n    // it works like 'lower-case', but ...\n    const idBase = slug.toLowerCase()\n    id = idBase\n    if (headerIds !== null) {\n      // ... making sure the id is unique\n      let i = 1\n      while (headerIds.has(id)) {\n        id = idBase + '-' + i\n        i++\n      }\n      headerIds.add(id)\n    }\n  } else {\n    throw new Error('Unknown linkifyHeaderStyle value \"' + window.linkifyHeaderStyle + '\"')\n  }\n  return id\n}\n\nconst linkifyAnchors = (level, containingElement) => {\n  const headers = containingElement.getElementsByTagName(`h${level}`)\n\n  for (let i = 0, l = headers.length; i < l; i++) {\n    const header = headers[i]\n    if (header.getElementsByClassName('anchor').length === 0) {\n      if (typeof header.id === 'undefined' || header.id === '') {\n        header.id = createHeaderId(getHeaderContent(header))\n      }\n      if (!(typeof header.id === 'undefined' || header.id === '')) {\n        header.insertBefore(anchorForId(header.id), header.firstChild)\n      }\n    }\n  }\n}\n\nexport function autoLinkify (view) {\n  const contentBlock = view[0]\n  if (!contentBlock) {\n    return\n  }\n  for (let level = 1; level <= 6; level++) {\n    linkifyAnchors(level, contentBlock)\n  }\n}\n\nfunction getHeaderContent (header) {\n  const headerHTML = $(header).clone()\n  headerHTML.find('.MathJax_Preview').remove()\n  headerHTML.find('.MathJax').remove()\n  return headerHTML[0].innerHTML\n}\n\nfunction changeHeaderId ($header, id, newId) {\n  $header.attr('id', newId)\n  const $headerLink = $header.find(`> a.anchor[href=\"#${id}\"]`)\n  $headerLink.attr('href', `#${newId}`)\n  $headerLink.attr('title', newId)\n}\n\nexport function deduplicatedHeaderId (view) {\n  // headers contained in the last change\n  const headers = view.find(':header.raw').removeClass('raw').toArray()\n  if (headers.length === 0) {\n    return\n  }\n  if (window.linkifyHeaderStyle === 'gfm') {\n    // consistent with GitHub, GitLab, Pandoc & co.\n    // all headers contained in the document, in order of appearance\n    const allHeaders = view.find(':header').toArray()\n    // list of finaly assigned header IDs\n    const headerIds = new Set()\n    for (let j = 0; j < allHeaders.length; j++) {\n      const $header = $(allHeaders[j])\n      const id = $header.attr('id')\n      const newId = createHeaderId(getHeaderContent($header), headerIds)\n      changeHeaderId($header, id, newId)\n    }\n  } else {\n    // the legacy way\n    for (let i = 0; i < headers.length; i++) {\n      const id = $(headers[i]).attr('id')\n      if (!id) continue\n      const duplicatedHeaders = view.find(`:header[id=\"${id}\"]`).toArray()\n      for (let j = 0; j < duplicatedHeaders.length; j++) {\n        if (duplicatedHeaders[j] !== headers[i]) {\n          const newId = id + j\n          const $header = $(duplicatedHeaders[j])\n          changeHeaderId($header, id, newId)\n        }\n      }\n    }\n  }\n}\n\nexport function renderTOC (view) {\n  const tocs = view.find('.toc').toArray()\n  for (let i = 0; i < tocs.length; i++) {\n    const toc = $(tocs[i])\n    const id = `toc${i}`\n    toc.attr('id', id)\n    const target = $(`#${id}`)\n    target.html('')\n    /* eslint-disable no-unused-vars */\n\n    const specificDepth = parseInt(toc.data('toc-depth'))\n\n    var tocOptions = md.meta.toc || {}\n    var yamlMaxDepth = (typeof tocOptions.maxLevel === 'number' && tocOptions.maxLevel > 0) ? tocOptions.maxLevel : window.defaultTocDepth\n\n    var maxLevel = specificDepth || yamlMaxDepth\n\n    const TOC = new window.Toc('doc', {\n      level: maxLevel,\n      top: -1,\n      class: 'toc',\n      targetId: id,\n      data: { tocDepth: specificDepth },\n      process: getHeaderContent\n    })\n    /* eslint-enable no-unused-vars */\n    if (target.text() === 'undefined') { target.html('') }\n    target.replaceWith(target.html())\n  }\n}\n\nexport function scrollToHash () {\n  const hash = location.hash\n  location.hash = ''\n  location.hash = hash\n}\n\nconst fenceCodeAlias = {\n  sequence: 'sequence-diagram',\n  flow: 'flow-chart',\n  graphviz: 'graphviz',\n  mermaid: 'mermaid',\n  abc: 'abc',\n  vega: 'vega',\n  geo: 'geo',\n  fretboard: 'fretboard_instance',\n  markmap: 'markmap'\n}\n\nfunction highlightRender (code, lang) {\n  if (!lang || /no(-?)highlight|plain|text/.test(lang)) { return }\n\n  const params = parseFenceCodeParams(lang)\n  const attr = serializeParamToAttribute(params)\n  lang = lang.split(/\\s+/g)[0]\n\n  code = escapeHTML(code)\n\n  const langAlias = fenceCodeAlias[lang]\n  if (langAlias) {\n    return `<div class=\"${langAlias} raw\"${attr}>${code}</div>`\n  }\n\n  const result = {\n    value: code\n  }\n  const showlinenumbers = /=$|=\\d+$|=\\+$/.test(lang)\n  if (showlinenumbers) {\n    let startnumber = 1\n    const matches = lang.match(/=(\\d+)$/)\n    if (matches) { startnumber = parseInt(matches[1]) }\n    const lines = result.value.split('\\n')\n    const linenumbers = []\n    for (let i = 0; i < lines.length - 1; i++) {\n      linenumbers[i] = `<span data-linenumber='${startnumber + i}'></span>`\n    }\n    const continuelinenumber = /=\\+$/.test(lang)\n    const linegutter = `<div class='gutter linenumber${continuelinenumber ? ' continue' : ''}'>${linenumbers.join('\\n')}</div>`\n    result.value = `<div class='wrapper'>${linegutter}<div class='code'>${result.value}</div></div>`\n  }\n  return result.value\n}\n\nexport const md = markdownit('default', {\n  html: true,\n  breaks: window.defaultUseHardbreak,\n  langPrefix: '',\n  linkify: true,\n  typographer: true,\n  highlight: highlightRender\n})\nwindow.md = md\n\nmd.use(require('markdown-it-abbr'))\nmd.use(require('markdown-it-footnote'))\nmd.use(require('markdown-it-deflist'))\nmd.use(require('markdown-it-mark'))\nmd.use(require('markdown-it-ins'))\nmd.use(require('markdown-it-sub'))\nmd.use(require('markdown-it-sup'))\nmd.use(require('markdown-it-mathjax')({\n  beforeMath: '<span class=\"mathjax raw\">',\n  afterMath: '</span>',\n  beforeInlineMath: '<span class=\"mathjax raw\">\\\\(',\n  afterInlineMath: '\\\\)</span>',\n  beforeDisplayMath: '<span class=\"mathjax raw\">\\\\[',\n  afterDisplayMath: '\\\\]</span>'\n}))\nmd.use(require('markdown-it-imsize'))\nmd.use(require('markdown-it-ruby'))\n\nwindow.emojify.setConfig({\n  blacklist: {\n    elements: ['script', 'textarea', 'a', 'pre', 'code', 'svg'],\n    classes: ['no-emojify']\n  },\n  img_dir: emojifyImageDir,\n  ignore_emoticons: true\n})\n\nfunction renderContainer (tokens, idx, options, env, self) {\n  tokens[idx].attrJoin('role', 'alert')\n  tokens[idx].attrJoin('class', 'alert')\n  tokens[idx].attrJoin('class', `alert-${tokens[idx].info.trim()}`)\n  return self.renderToken(...arguments)\n}\nmd.use(markdownitContainer, 'success', { render: renderContainer })\nmd.use(markdownitContainer, 'info', { render: renderContainer })\nmd.use(markdownitContainer, 'warning', { render: renderContainer })\nmd.use(markdownitContainer, 'danger', { render: renderContainer })\nmd.use(markdownitContainer, 'spoiler', {\n  validate: function (params) {\n    return params.trim().match(/^spoiler(\\s+.*)?$/)\n  },\n  render: function (tokens, idx) {\n    const m = tokens[idx].info.trim().match(/^spoiler(\\s+.*)?$/)\n\n    if (tokens[idx].nesting === 1) {\n      // opening tag\n      const summary = m[1] && m[1].trim()\n      if (summary) {\n        return `<details><summary>${md.renderInline(summary)}</summary>\\n`\n      } else {\n        return '<details>\\n'\n      }\n    } else {\n      // closing tag\n      return '</details>\\n'\n    }\n  }\n})\n\nconst defaultImageRender = md.renderer.rules.image\nmd.renderer.rules.image = function (tokens, idx, options, env, self) {\n  tokens[idx].attrJoin('class', 'raw')\n  tokens[idx].attrJoin('class', 'md-image')\n  return defaultImageRender(...arguments)\n}\nmd.renderer.rules.list_item_open = function (tokens, idx, options, env, self) {\n  tokens[idx].attrJoin('class', 'raw')\n  return self.renderToken(...arguments)\n}\nmd.renderer.rules.blockquote_open = function (tokens, idx, options, env, self) {\n  tokens[idx].attrJoin('class', 'raw')\n  return self.renderToken(...arguments)\n}\nmd.renderer.rules.heading_open = function (tokens, idx, options, env, self) {\n  tokens[idx].attrJoin('class', 'raw')\n  return self.renderToken(...arguments)\n}\nmd.renderer.rules.fence = (tokens, idx, options, env, self) => {\n  const token = tokens[idx]\n  const info = token.info ? md.utils.unescapeAll(token.info).trim() : ''\n  let langName = ''\n  let highlighted\n\n  if (info) {\n    langName = info.split(/\\s+/g)[0]\n\n    if (langName === 'csvpreview') {\n      const params = parseFenceCodeParams(info)\n      return renderCSVPreview(token.content, params)\n    }\n\n    if (/!$/.test(info)) token.attrJoin('class', 'wrap')\n    token.attrJoin('class', options.langPrefix + langName.replace(/=$|=\\d+$|=\\+$|!$|=!$/, ''))\n    token.attrJoin('class', 'hljs')\n    token.attrJoin('class', 'raw')\n  }\n\n  if (options.highlight) {\n    highlighted = options.highlight(token.content, info) || md.utils.escapeHtml(token.content)\n  } else {\n    highlighted = md.utils.escapeHtml(token.content)\n  }\n\n  if (highlighted.indexOf('<pre') === 0) {\n    return `${highlighted}\\n`\n  }\n\n  return `<pre><code${self.renderAttrs(token)}>${highlighted}</code></pre>\\n`\n}\n\nconst makePlantumlURL = (umlCode) => {\n  const format = 'svg'\n  const code = plantumlEncoder.encode(umlCode)\n  return `${plantumlServer}/${format}/${code}`\n}\n\n// https://github.com/qjebbs/vscode-plantuml/tree/master/src/markdown-it-plantuml\nmd.renderer.rules.plantuml = (tokens, idx) => {\n  const token = tokens[idx]\n  if (token.type !== 'plantuml') {\n    return tokens[idx].content\n  }\n\n  const url = makePlantumlURL(token.content)\n  return `<img src=\"${url}\" />`\n}\n\n// https://github.com/qjebbs/vscode-plantuml/tree/master/src/markdown-it-plantuml\nmd.core.ruler.push('plantuml', (state) => {\n  const blockTokens = state.tokens\n  for (const blockToken of blockTokens) {\n    if (blockToken.type === 'fence' && blockToken.info === 'plantuml') {\n      blockToken.type = 'plantuml'\n    }\n  }\n})\n\n// youtube\nconst youtubePlugin = new Plugin(\n  // regexp to match\n  /{%youtube\\s*([\\d\\D]*?)\\s*%}/,\n\n  (match, utils) => {\n    const videoid = match[1]\n    if (!videoid) return\n    const div = $('<div class=\"youtube raw\"></div>')\n    div.attr('data-videoid', videoid)\n    const thumbnailSrc = `//img.youtube.com/vi/${videoid}/hqdefault.jpg`\n    const image = `<img src=\"${thumbnailSrc}\" />`\n    div.append(image)\n    const icon = '<i class=\"icon fa fa-youtube-play fa-5x\"></i>'\n    div.append(icon)\n    return div[0].outerHTML\n  }\n)\n// vimeo\nconst vimeoPlugin = new Plugin(\n  // regexp to match\n  /{%vimeo\\s*([\\d\\D]*?)\\s*%}/,\n\n  (match, utils) => {\n    const videoid = match[1].split(/[?&=]+/)[0]\n    if (!videoid) return\n    const div = $('<div class=\"vimeo raw\"></div>')\n    div.attr('data-videoid', videoid)\n    const icon = '<i class=\"icon fa fa-vimeo-square fa-5x\"></i>'\n    div.append(icon)\n    return div[0].outerHTML\n  }\n)\n// gist\nconst gistPlugin = new Plugin(\n  // regexp to match\n  /{%gist\\s*([\\d\\D]*?)\\s*%}/,\n\n  (match, utils) => {\n    const gistid = match[1].split(/[?&=]+/)[0]\n    const code = `<code data-gist-id=\"${gistid}\"></code>`\n    return code\n  }\n)\n// TOC\nconst tocPlugin = new Plugin(\n  // regexp to match\n  /^\\[TOC(|\\s*maxLevel=\\d+?)\\]$/i,\n\n  (match, utils) => {\n    const tocDepth = match[1].split(/[?&=]+/)[1]\n    return `<div class=\"toc\" data-toc-depth=\"${tocDepth}\"></div>`\n  }\n)\n// slideshare\nconst slidesharePlugin = new Plugin(\n  // regexp to match\n  /{%slideshare\\s*([\\d\\D]*?)\\s*%}/,\n\n  (match, utils) => {\n    const slideshareid = match[1].split(/[?&=]+/)[0]\n    const div = $('<div class=\"slideshare raw\"></div>')\n    div.attr('data-slideshareid', slideshareid)\n    return div[0].outerHTML\n  }\n)\n// speakerdeck\nconst speakerdeckPlugin = new Plugin(\n  // regexp to match\n  /{%speakerdeck\\s*([\\d\\D]*?)\\s*%}/,\n\n  (match, utils) => {\n    const speakerdeckid = match[1]\n    const div = $('<div class=\"speakerdeck raw\"></div>')\n    div.attr('data-speakerdeckid', speakerdeckid)\n    return div[0].outerHTML\n  }\n)\n// pdf\nconst pdfPlugin = new Plugin(\n  // regexp to match\n  /{%pdf\\s*([\\d\\D]*?)\\s*%}/,\n\n  (match, utils) => {\n    const pdfurl = match[1]\n    if (!isURL(pdfurl)) return match[0]\n    const div = $('<div class=\"pdf raw\"></div>')\n    div.attr('data-pdfurl', pdfurl)\n    return div[0].outerHTML\n  }\n)\n\nconst emojijsPlugin = new Plugin(\n  // regexp to match emoji shortcodes :something:\n  // We generate an universal regex that guaranteed only contains the\n  // emojies we have available. This should prevent all false-positives\n  new RegExp(':(' + window.emojify.emojiNames.map((item) => { return RegExp.escape(item) }).join('|') + '):', 'i'),\n\n  (match, utils) => {\n    const emoji = match[1].toLowerCase()\n    const div = $(`<img class=\"emoji\" alt=\":${emoji}:\" src=\"${emojifyImageDir}/${emoji}.png\"></img>`)\n    return div[0].outerHTML\n  }\n)\n\n// yaml meta, from https://github.com/eugeneware/remarkable-meta\nfunction get (state, line) {\n  const pos = state.bMarks[line]\n  const max = state.eMarks[line]\n  return state.src.substr(pos, max - pos)\n}\n\nfunction meta (state, start, end, silent) {\n  if (start !== 0 || state.blkIndent !== 0) return false\n  if (state.tShift[start] < 0) return false\n  if (!get(state, start).match(/^---$/)) return false\n\n  const data = []\n  for (var line = start + 1; line < end; line++) {\n    const str = get(state, line)\n    if (str.match(/^(\\.{3}|-{3})$/)) break\n    if (state.tShift[line] < 0) break\n    data.push(str)\n  }\n\n  if (line >= end) return false\n\n  try {\n    md.meta = window.jsyaml.safeLoad(data.join('\\n')) || {}\n    delete md.metaError\n  } catch (err) {\n    md.metaError = err\n    console.warn(err)\n    return false\n  }\n\n  state.line = line + 1\n\n  return true\n}\n\nfunction metaPlugin (md) {\n  md.meta = md.meta || {}\n  md.block.ruler.before('code', 'meta', meta, {\n    alt: []\n  })\n}\n\nmd.use(metaPlugin)\nmd.use(emojijsPlugin)\nmd.use(youtubePlugin)\nmd.use(vimeoPlugin)\nmd.use(gistPlugin)\nmd.use(tocPlugin)\nmd.use(slidesharePlugin)\nmd.use(speakerdeckPlugin)\nmd.use(pdfPlugin)\n\nexport default {\n  md\n}\n\n// Add helper to sanitize markmap nodes against XSS using the global preventXSS\nfunction sanitizeMarkmapNode (node) {\n  if (!node || typeof node !== 'object') return\n  if (typeof node.content === 'string') {\n    try {\n      node.content = window.preventXSS(node.content)\n    } catch (e) {\n      // fallback: strip potentially dangerous characters\n      node.content = node.content.replace(/[<>]/g, '')\n    }\n  }\n  // remove dangerous href like javascript:\n  if (node.payload && typeof node.payload === 'object' && typeof node.payload.href === 'string') {\n    if (/^\\s*javascript:/i.test(node.payload.href)) {\n      delete node.payload.href\n    }\n  }\n  if (Array.isArray(node.children)) {\n    node.children.forEach(sanitizeMarkmapNode)\n  }\n}\n"
  },
  {
    "path": "public/js/history.js",
    "content": "/* eslint-env browser, jquery */\n/* global serverurl, moment */\n\nimport store from 'store'\nimport LZString from '@hackmd/lz-string'\n\nimport escapeHTML from 'lodash/escape'\n\nimport {\n  checkNoteIdValid,\n  encodeNoteId\n} from './utils'\n\nimport { checkIfAuth } from './lib/common/login'\n\nimport { urlpath } from './lib/config'\n\nwindow.migrateHistoryFromTempCallback = null\n\nexport function saveHistory (notehistory) {\n  checkIfAuth(\n    () => {\n      saveHistoryToServer(notehistory)\n    },\n    () => {\n      saveHistoryToStorage(notehistory)\n    }\n  )\n}\n\nfunction saveHistoryToStorage (notehistory) {\n  store.set('notehistory', JSON.stringify(notehistory))\n}\n\nfunction saveHistoryToServer (notehistory) {\n  $.post(`${serverurl}/history`, {\n    history: JSON.stringify(notehistory)\n  })\n}\n\nexport function saveStorageHistoryToServer (callback) {\n  const data = store.get('notehistory')\n  if (data) {\n    $.post(`${serverurl}/history`, {\n      history: data\n    })\n      .done(data => {\n        callback(data)\n      })\n  }\n}\n\nexport function clearDuplicatedHistory (notehistory) {\n  const newnotehistory = []\n  for (let i = 0; i < notehistory.length; i++) {\n    let found = false\n    for (let j = 0; j < newnotehistory.length; j++) {\n      const id = notehistory[i].id.replace(/=+$/, '')\n      const newId = newnotehistory[j].id.replace(/=+$/, '')\n      if (id === newId || notehistory[i].id === newnotehistory[j].id || !notehistory[i].id || !newnotehistory[j].id) {\n        const time = (typeof notehistory[i].time === 'number' ? moment(notehistory[i].time) : moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a'))\n        const newTime = (typeof newnotehistory[j].time === 'number' ? moment(newnotehistory[j].time) : moment(newnotehistory[j].time, 'MMMM Do YYYY, h:mm:ss a'))\n        if (time >= newTime) {\n          newnotehistory[j] = notehistory[i]\n        }\n        found = true\n        break\n      }\n    }\n    if (!found) { newnotehistory.push(notehistory[i]) }\n  }\n  return newnotehistory\n}\n\nfunction addHistory (id, text, time, tags, pinned, notehistory) {\n  // only add when note id exists\n  if (id) {\n    notehistory.push({\n      id,\n      text,\n      time,\n      tags,\n      pinned\n    })\n  }\n  return notehistory\n}\n\nexport function removeHistory (id, notehistory) {\n  for (let i = 0; i < notehistory.length; i++) {\n    if (notehistory[i].id === id) {\n      notehistory.splice(i, 1)\n      i -= 1\n    }\n  }\n  return notehistory\n}\n\n// used for inner\nexport function writeHistory (title, tags) {\n  checkIfAuth(\n    () => {\n      // no need to do this anymore, this will count from server-side\n      // writeHistoryToServer(title, tags);\n    },\n    () => {\n      writeHistoryToStorage(title, tags)\n    }\n  )\n}\n\nfunction writeHistoryToStorage (title, tags) {\n  const data = store.get('notehistory')\n  let notehistory\n  if (data && typeof data === 'string') {\n    notehistory = JSON.parse(data)\n  } else {\n    notehistory = []\n  }\n\n  const newnotehistory = generateHistory(title, tags, notehistory)\n  saveHistoryToStorage(newnotehistory)\n}\n\nif (!Array.isArray) {\n  Array.isArray = arg => Object.prototype.toString.call(arg) === '[object Array]'\n}\n\nfunction renderHistory (title, tags) {\n  // console.debug(tags);\n  const id = urlpath ? location.pathname.slice(urlpath.length + 1, location.pathname.length).split('/')[1] : location.pathname.split('/')[1]\n  return {\n    id,\n    text: title,\n    time: moment().valueOf(),\n    tags\n  }\n}\n\nfunction generateHistory (title, tags, notehistory) {\n  const info = renderHistory(title, tags)\n  // keep any pinned data\n  let pinned = false\n  for (let i = 0; i < notehistory.length; i++) {\n    if (notehistory[i].id === info.id && notehistory[i].pinned) {\n      pinned = true\n      break\n    }\n  }\n  notehistory = removeHistory(info.id, notehistory)\n  notehistory = addHistory(info.id, info.text, info.time, info.tags, pinned, notehistory)\n  notehistory = clearDuplicatedHistory(notehistory)\n  return notehistory\n}\n\n// used for outer\nexport function getHistory (callback) {\n  checkIfAuth(\n    () => {\n      getServerHistory(callback)\n    },\n    () => {\n      getStorageHistory(callback)\n    }\n  )\n}\n\nfunction getServerHistory (callback) {\n  $.get(`${serverurl}/history`)\n    .done(data => {\n      if (data.history) {\n        callback(data.history)\n      }\n    })\n    .fail((xhr, status, error) => {\n      console.error(xhr.responseText)\n    })\n}\n\nexport function getStorageHistory (callback) {\n  let data = store.get('notehistory')\n  if (data) {\n    if (typeof data === 'string') { data = JSON.parse(data) }\n    return callback(data)\n  }\n  // eslint-disable-next-line standard/no-callback-literal\n  callback([])\n}\n\nexport function parseHistory (list, callback) {\n  checkIfAuth(\n    () => {\n      parseServerToHistory(list, callback)\n    },\n    () => {\n      parseStorageToHistory(list, callback)\n    }\n  )\n}\n\nexport function parseServerToHistory (list, callback) {\n  $.get(`${serverurl}/history`)\n    .done(data => {\n      if (data.history) {\n        parseToHistory(list, data.history, callback)\n      }\n    })\n    .fail((xhr, status, error) => {\n      console.error(xhr.responseText)\n    })\n}\n\nexport function parseStorageToHistory (list, callback) {\n  let data = store.get('notehistory')\n  if (data) {\n    if (typeof data === 'string') { data = JSON.parse(data) }\n    parseToHistory(list, data, callback)\n  }\n  parseToHistory(list, [], callback)\n}\n\nfunction parseToHistory (list, notehistory, callback) {\n  if (!callback) return\n  else if (!list || !notehistory) callback(list, notehistory)\n  else if (notehistory && notehistory.length > 0) {\n    for (let i = 0; i < notehistory.length; i++) {\n      // migrate LZString encoded id to base64url encoded id\n      try {\n        const id = LZString.decompressFromBase64(notehistory[i].id)\n        if (id && checkNoteIdValid(id)) {\n          notehistory[i].id = encodeNoteId(id)\n        }\n      } catch (err) {\n        console.error(err)\n      }\n      // parse time to timestamp and fromNow\n      const timestamp = (typeof notehistory[i].time === 'number' ? moment(notehistory[i].time) : moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a'))\n      notehistory[i].timestamp = timestamp.valueOf()\n      notehistory[i].fromNow = timestamp.fromNow()\n      notehistory[i].time = timestamp.format('llll')\n      // prevent XSS\n      notehistory[i].text = escapeHTML(notehistory[i].text)\n      notehistory[i].tags = (notehistory[i].tags && notehistory[i].tags.length > 0) ? escapeHTML(notehistory[i].tags).split(',') : []\n      // add to list\n      if (notehistory[i].id && list.get('id', notehistory[i].id).length === 0) { list.add(notehistory[i]) }\n    }\n  }\n  callback(list, notehistory)\n}\n\nexport function postHistoryToServer (noteId, data, callback) {\n  $.post(`${serverurl}/history/${noteId}`, data)\n    .done(result => callback(null, result))\n    .fail((xhr, status, error) => {\n      console.error(xhr.responseText)\n      return callback(error, null)\n    })\n}\n\nexport function deleteServerHistory (noteId, callback) {\n  $.ajax({\n    url: `${serverurl}/history${noteId ? '/' + noteId : ''}`,\n    type: 'DELETE'\n  })\n    .done(result => callback(null, result))\n    .fail((xhr, status, error) => {\n      console.error(xhr.responseText)\n      return callback(error, null)\n    })\n}\n"
  },
  {
    "path": "public/js/htmlExport.js",
    "content": "require('../css/github-extract.css')\nrequire('../css/markdown.css')\nrequire('../css/extra.css')\nrequire('../css/slide-preview.css')\nrequire('../css/google-font.css')\nrequire('../css/site.css')\n"
  },
  {
    "path": "public/js/index.js",
    "content": "/* eslint-env browser, jquery */\n/* global CodeMirror, Cookies, moment, serverurl,\n   key, Dropbox, ot, hex2rgb, Visibility, inlineAttachment */\n\nimport TurndownService from 'turndown'\n\nimport { saveAs } from 'file-saver'\nimport randomColor from 'randomcolor'\nimport store from 'store'\nimport hljs from 'highlight.js'\n\nimport isURL from 'validator/lib/isURL'\n\nimport _ from 'lodash'\n\nimport wurl from 'wurl'\n\nimport List from 'list.js'\n\nimport Idle from '@hackmd/idle-js'\n\nimport { Spinner } from 'spin.js'\n\nimport {\n  checkLoginStateChanged,\n  setloginStateChangeEvent\n} from './lib/common/login'\n\nimport {\n  debug,\n  DROPBOX_APP_KEY,\n  noteid,\n  noteurl,\n  urlpath,\n  version\n} from './lib/config'\n\nimport {\n  autoLinkify,\n  deduplicatedHeaderId,\n  exportToHTML,\n  exportToRawHTML,\n  removeDOMEvents,\n  finishView,\n  generateToc,\n  md,\n  parseMeta,\n  postProcess,\n  renderFilename,\n  renderTOC,\n  renderTags,\n  renderTitle,\n  scrollToHash,\n  smoothHashScroll,\n  updateLastChange,\n  updateLastChangeUser,\n  updateOwner\n} from './extra'\n\nimport {\n  clearMap,\n  setupSyncAreas,\n  syncScrollToEdit,\n  syncScrollToView\n} from './lib/syncscroll'\n\nimport {\n  writeHistory,\n  deleteServerHistory,\n  getHistory,\n  saveHistory,\n  removeHistory\n} from './history'\n\nimport { preventXSS } from './render'\n\nimport Editor from './lib/editor'\n\nimport getUIElements from './lib/editor/ui-elements'\nimport { emojifyImageDir } from './lib/editor/constants'\nimport modeType from './lib/modeType'\nimport appState from './lib/appState'\n\nrequire('../vendor/showup/showup')\n\nrequire('../css/index.css')\nrequire('../css/extra.css')\nrequire('../css/slide-preview.css')\nrequire('../css/site.css')\nrequire('spin.js/spin.css')\n\nrequire('highlight.js/styles/github-gist.css')\n\nvar defaultTextHeight = 20\nvar viewportMargin = 20\nvar defaultEditorMode = 'gfm'\n\nvar idleTime = 300000 // 5 mins\nvar updateViewDebounce = 100\nvar cursorMenuThrottle = 50\nvar cursorActivityDebounce = 50\nvar cursorAnimatePeriod = 100\nvar supportContainers = ['success', 'info', 'warning', 'danger', 'spoiler']\nvar supportCodeModes = ['javascript', 'typescript', 'jsx', 'htmlmixed', 'htmlembedded', 'css', 'xml', 'clike', 'clojure', 'ruby', 'python', 'shell', 'php', 'sql', 'haskell', 'coffeescript', 'yaml', 'pug', 'lua', 'cmake', 'nginx', 'perl', 'sass', 'r', 'dockerfile', 'tiddlywiki', 'mediawiki', 'go', 'gherkin'].concat(hljs.listLanguages())\nvar supportCharts = ['sequence', 'flow', 'graphviz', 'mermaid', 'abc', 'plantuml', 'vega', 'geo', 'fretboard', 'markmap']\nvar supportHeaders = [\n  {\n    text: '# h1',\n    search: '#'\n  },\n  {\n    text: '## h2',\n    search: '##'\n  },\n  {\n    text: '### h3',\n    search: '###'\n  },\n  {\n    text: '#### h4',\n    search: '####'\n  },\n  {\n    text: '##### h5',\n    search: '#####'\n  },\n  {\n    text: '###### h6',\n    search: '######'\n  },\n  {\n    text: '###### tags: `example`',\n    search: '###### tags:'\n  }\n]\nconst supportReferrals = [\n  {\n    text: '[reference link]',\n    search: '[]'\n  },\n  {\n    text: '[reference]: https:// \"title\"',\n    search: '[]:'\n  },\n  {\n    text: '[^footnote link]',\n    search: '[^]'\n  },\n  {\n    text: '[^footnote reference]: https:// \"title\"',\n    search: '[^]:'\n  },\n  {\n    text: '^[inline footnote]',\n    search: '^[]'\n  },\n  {\n    text: '[link text][reference]',\n    search: '[][]'\n  },\n  {\n    text: '[link text](https:// \"title\")',\n    search: '[]()'\n  },\n  {\n    text: '![image alt][reference]',\n    search: '![][]'\n  },\n  {\n    text: '![image alt](https:// \"title\")',\n    search: '![]()'\n  },\n  {\n    text: '![image alt](https:// \"title\" =WidthxHeight)',\n    search: '![]()'\n  },\n  {\n    text: '[TOC]',\n    search: '[]'\n  }\n]\nconst supportExternals = [\n  {\n    text: '{%youtube youtubeid %}',\n    search: 'youtube'\n  },\n  {\n    text: '{%vimeo vimeoid %}',\n    search: 'vimeo'\n  },\n  {\n    text: '{%gist gistid %}',\n    search: 'gist'\n  },\n  {\n    text: '{%slideshare slideshareid %}',\n    search: 'slideshare'\n  },\n  {\n    text: '{%speakerdeck speakerdeckid %}',\n    search: 'speakerdeck'\n  },\n  {\n    text: '{%pdf pdfurl %}',\n    search: 'pdf'\n  }\n]\nconst supportExtraTags = [\n  {\n    text: '[name tag]',\n    search: '[]',\n    command: function () {\n      return '[name=' + personalInfo.name + ']'\n    }\n  },\n  {\n    text: '[time tag]',\n    search: '[]',\n    command: function () {\n      return '[time=' + moment().format('llll') + ']'\n    }\n  },\n  {\n    text: '[my color tag]',\n    search: '[]',\n    command: function () {\n      return '[color=' + personalInfo.color + ']'\n    }\n  },\n  {\n    text: '[random color tag]',\n    search: '[]',\n    command: function () {\n      var color = randomColor()\n      return '[color=' + color + ']'\n    }\n  }\n]\nconst statusType = {\n  connected: 1,\n  online: 2,\n  offline: 3\n}\n\n// global vars\nwindow.loaded = false\nlet needRefresh = false\nlet isDirty = false\nlet editShown = false\nlet visibleXS = false\nlet visibleSM = false\nlet visibleMD = false\nlet visibleLG = false\nconst isTouchDevice = 'ontouchstart' in document.documentElement\nlet currentStatus = statusType.offline\nconst lastInfo = {\n  needRestore: false,\n  cursor: null,\n  scroll: null,\n  edit: {\n    scroll: {\n      left: null,\n      top: null\n    },\n    cursor: {\n      line: null,\n      ch: null\n    },\n    selections: null\n  },\n  view: {\n    scroll: {\n      left: null,\n      top: null\n    }\n  },\n  history: null\n}\nlet personalInfo = {}\nlet onlineUsers = []\nconst fileTypes = {\n  pl: 'perl',\n  cgi: 'perl',\n  js: 'javascript',\n  php: 'php',\n  sh: 'bash',\n  rb: 'ruby',\n  html: 'html',\n  py: 'python'\n}\n\n// editor settings\nconst textit = document.getElementById('textit')\nif (!textit) {\n  throw new Error('There was no textit area!')\n}\n\nconst editorInstance = new Editor()\nvar editor = editorInstance.init(textit)\n\n// FIXME: global referncing in jquery-textcomplete patch\nwindow.editor = editor\n\nvar inlineAttach = inlineAttachment.editors.codemirror4.attach(editor)\ndefaultTextHeight = parseInt($('.CodeMirror').css('line-height'))\n\n//  initalize ui reference\nconst ui = getUIElements()\n\n// page actions\nvar opts = {\n  lines: 11, // The number of lines to draw\n  length: 20, // The length of each line\n  width: 2, // The line thickness\n  radius: 30, // The radius of the inner circle\n  corners: 0, // Corner roundness (0..1)\n  rotate: 0, // The rotation offset\n  direction: 1, // 1: clockwise, -1: counterclockwise\n  color: '#000', // #rgb or #rrggbb or array of colors\n  speed: 1.1, // Rounds per second\n  trail: 60, // Afterglow percentage\n  shadow: false, // Whether to render a shadow\n  hwaccel: true, // Whether to use hardware acceleration\n  className: 'spinner', // The CSS class to assign to the spinner\n  zIndex: 2e9, // The z-index (defaults to 2000000000)\n  top: '50%', // Top position relative to parent\n  left: '50%' // Left position relative to parent\n}\n\nnew Spinner(opts).spin(ui.spinner[0])\n\n// idle\nvar idle = new Idle({\n  onAway: function () {\n    idle.isAway = true\n    emitUserStatus()\n    updateOnlineStatus()\n  },\n  onAwayBack: function () {\n    idle.isAway = false\n    emitUserStatus()\n    updateOnlineStatus()\n    setHaveUnreadChanges(false)\n    updateTitleReminder()\n  },\n  awayTimeout: idleTime\n})\nui.area.codemirror.on('touchstart', function () {\n  idle.onActive()\n})\n\nvar haveUnreadChanges = false\n\nfunction setHaveUnreadChanges (bool) {\n  if (!window.loaded) return\n  if (bool && (idle.isAway || Visibility.hidden())) {\n    haveUnreadChanges = true\n  } else if (!bool && !idle.isAway && !Visibility.hidden()) {\n    haveUnreadChanges = false\n  }\n}\n\nfunction updateTitleReminder () {\n  if (!window.loaded) return\n  if (haveUnreadChanges) {\n    document.title = '• ' + renderTitle(ui.area.markdown)\n  } else {\n    document.title = renderTitle(ui.area.markdown)\n  }\n}\n\nfunction setRefreshModal (status) {\n  $('#refreshModal').modal('show')\n  $('#refreshModal').find('.modal-body > div').hide()\n  $('#refreshModal').find('.' + status).show()\n}\n\nfunction setNeedRefresh () {\n  needRefresh = true\n  editor.setOption('readOnly', true)\n  socket.disconnect()\n  showStatus(statusType.offline)\n}\n\nsetloginStateChangeEvent(function () {\n  setRefreshModal('user-state-changed')\n  setNeedRefresh()\n})\n\n// visibility\nvar wasFocus = false\nVisibility.change(function (e, state) {\n  var hidden = Visibility.hidden()\n  if (hidden) {\n    if (editorHasFocus()) {\n      wasFocus = true\n      editor.getInputField().blur()\n    }\n  } else {\n    if (wasFocus) {\n      if (!visibleXS) {\n        editor.focus()\n        editor.refresh()\n      }\n      wasFocus = false\n    }\n    setHaveUnreadChanges(false)\n  }\n  updateTitleReminder()\n})\n\n// when page ready\n$(document).ready(function () {\n  idle.checkAway()\n  checkResponsive()\n  // if in smaller screen, we don't need advanced scrollbar\n  var scrollbarStyle\n  if (visibleXS) {\n    scrollbarStyle = 'native'\n  } else {\n    scrollbarStyle = 'overlay'\n  }\n  if (scrollbarStyle !== editor.getOption('scrollbarStyle')) {\n    editor.setOption('scrollbarStyle', scrollbarStyle)\n    clearMap()\n  }\n  checkEditorStyle()\n\n  /* cache dom references */\n  var $body = $('body')\n\n  /* we need this only on touch devices */\n  if (isTouchDevice) {\n    /* bind events */\n    $(document)\n      .on('focus', 'textarea, input', function () {\n        $body.addClass('fixfixed')\n      })\n      .on('blur', 'textarea, input', function () {\n        $body.removeClass('fixfixed')\n      })\n  }\n\n  // Re-enable nightmode\n  if (store.get('nightMode') || Cookies.get('nightMode')) {\n    $body.addClass('night')\n    ui.toolbar.night.addClass('active')\n  }\n\n  // showup\n  $().showUp('.navbar', {\n    upClass: 'navbar-hide',\n    downClass: 'navbar-show'\n  })\n  // tooltip\n  $('[data-toggle=\"tooltip\"]').tooltip()\n  // shortcuts\n  // allow on all tags\n  key.filter = function (e) { return true }\n  key('ctrl+alt+e', function (e) {\n    changeMode(modeType.edit)\n  })\n  key('ctrl+alt+v', function (e) {\n    changeMode(modeType.view)\n  })\n  key('ctrl+alt+b', function (e) {\n    changeMode(modeType.both)\n  })\n  // toggle-dropdown\n  $(document).on('click', '.toggle-dropdown .dropdown-menu', function (e) {\n    e.stopPropagation()\n  })\n})\n// when page resize\n$(window).resize(function () {\n  checkLayout()\n  checkEditorStyle()\n  checkTocStyle()\n  checkCursorMenu()\n  windowResize()\n})\n// when page unload\n$(window).on('unload', function () {\n// updateHistoryInner();\n})\n$(window).on('error', function () {\n  // setNeedRefresh();\n})\n\nsetupSyncAreas(ui.area.codemirrorScroll, ui.area.view, ui.area.markdown, editor)\n\nfunction autoSyncscroll () {\n  if (editorHasFocus()) {\n    syncScrollToView()\n  } else {\n    syncScrollToEdit()\n  }\n}\n\nvar windowResizeDebounce = 200\nvar windowResize = _.debounce(windowResizeInner, windowResizeDebounce)\n\nfunction windowResizeInner (callback) {\n  checkLayout()\n  checkResponsive()\n  checkEditorStyle()\n  checkTocStyle()\n  checkCursorMenu()\n  // refresh editor\n  if (window.loaded) {\n    if (editor.getOption('scrollbarStyle') === 'native') {\n      setTimeout(function () {\n        clearMap()\n        autoSyncscroll()\n        updateScrollspy()\n        if (callback && typeof callback === 'function') { callback() }\n      }, 1)\n    } else {\n      // force it load all docs at once to prevent scroll knob blink\n      editor.setOption('viewportMargin', Infinity)\n      setTimeout(function () {\n        clearMap()\n        autoSyncscroll()\n        editor.setOption('viewportMargin', viewportMargin)\n        // add or update user cursors\n        for (var i = 0; i < onlineUsers.length; i++) {\n          if (onlineUsers[i].id !== personalInfo.id) { buildCursor(onlineUsers[i]) }\n        }\n        updateScrollspy()\n        if (callback && typeof callback === 'function') { callback() }\n      }, 1)\n    }\n  }\n}\n\nfunction checkLayout () {\n  var navbarHieght = $('.navbar').outerHeight()\n  $('body').css('padding-top', navbarHieght + 'px')\n}\n\nfunction editorHasFocus () {\n  return $(editor.getInputField()).is(':focus')\n}\n\n// 768-792px have a gap\nfunction checkResponsive () {\n  visibleXS = $('.visible-xs').is(':visible')\n  visibleSM = $('.visible-sm').is(':visible')\n  visibleMD = $('.visible-md').is(':visible')\n  visibleLG = $('.visible-lg').is(':visible')\n\n  if (visibleXS && appState.currentMode === modeType.both) {\n    if (editorHasFocus()) { changeMode(modeType.edit) } else { changeMode(modeType.view) }\n  }\n\n  emitUserStatus()\n}\n\nvar lastEditorWidth = 0\nvar previousFocusOnEditor = null\n\nfunction checkEditorStyle () {\n  var desireHeight = editorInstance.statusBar ? (ui.area.edit.height() - editorInstance.statusBar.outerHeight()) : ui.area.edit.height()\n  if (editorInstance.toolBar) {\n    desireHeight = desireHeight - editorInstance.toolBar.outerHeight()\n  }\n  // set editor height and min height based on scrollbar style and mode\n  var scrollbarStyle = editor.getOption('scrollbarStyle')\n  if (scrollbarStyle === 'overlay' || appState.currentMode === modeType.both) {\n    ui.area.codemirrorScroll.css('height', desireHeight + 'px')\n    ui.area.codemirrorScroll.css('min-height', '')\n    checkEditorScrollbar()\n  } else if (scrollbarStyle === 'native') {\n    ui.area.codemirrorScroll.css('height', '')\n    ui.area.codemirrorScroll.css('min-height', desireHeight + 'px')\n  }\n  // workaround editor will have wrong doc height when editor height changed\n  editor.setSize(null, ui.area.edit.height())\n  checkEditorScrollOverLines()\n  // make editor resizable\n  if (!ui.area.resize.handle.length) {\n    ui.area.edit.resizable({\n      handles: 'e',\n      maxWidth: $(window).width() * 0.7,\n      minWidth: $(window).width() * 0.2,\n      create: function (e, ui) {\n        $(this).parent().on('resize', function (e) {\n          e.stopPropagation()\n        })\n      },\n      start: function (e) {\n        editor.setOption('viewportMargin', Infinity)\n      },\n      resize: function (e) {\n        ui.area.resize.syncToggle.stop(true, true).show()\n        checkTocStyle()\n      },\n      stop: function (e) {\n        lastEditorWidth = ui.area.edit.width()\n        // workaround that scroll event bindings\n        window.preventSyncScrollToView = 2\n        window.preventSyncScrollToEdit = true\n        editor.setOption('viewportMargin', viewportMargin)\n        if (editorHasFocus()) {\n          windowResizeInner(function () {\n            ui.area.codemirrorScroll.scroll()\n          })\n        } else {\n          windowResizeInner(function () {\n            ui.area.view.scroll()\n          })\n        }\n        checkEditorScrollbar()\n      }\n    })\n    ui.area.resize.handle = $('.ui-resizable-handle')\n  }\n  if (!ui.area.resize.syncToggle.length) {\n    ui.area.resize.syncToggle = $('<button class=\"btn btn-lg btn-default ui-sync-toggle\" title=\"Toggle sync scrolling\"><i class=\"fa fa-link fa-fw\"></i></button>')\n    ui.area.resize.syncToggle.hover(function () {\n      previousFocusOnEditor = editorHasFocus()\n    }, function () {\n      previousFocusOnEditor = null\n    })\n    ui.area.resize.syncToggle.click(function () {\n      appState.syncscroll = !appState.syncscroll\n      checkSyncToggle()\n    })\n    ui.area.resize.handle.append(ui.area.resize.syncToggle)\n    ui.area.resize.syncToggle.hide()\n    ui.area.resize.handle.hover(function () {\n      ui.area.resize.syncToggle.stop(true, true).delay(200).fadeIn(100)\n    }, function () {\n      ui.area.resize.syncToggle.stop(true, true).delay(300).fadeOut(300)\n    })\n  }\n}\n\nfunction checkSyncToggle () {\n  if (appState.syncscroll) {\n    if (previousFocusOnEditor) {\n      window.preventSyncScrollToView = false\n      syncScrollToView()\n    } else {\n      window.preventSyncScrollToEdit = false\n      syncScrollToEdit()\n    }\n    ui.area.resize.syncToggle.find('i').removeClass('fa-unlink').addClass('fa-link')\n  } else {\n    ui.area.resize.syncToggle.find('i').removeClass('fa-link').addClass('fa-unlink')\n  }\n}\n\nvar checkEditorScrollbar = _.debounce(function () {\n  editor.operation(checkEditorScrollbarInner)\n}, 50)\n\nfunction checkEditorScrollbarInner () {\n  // workaround simple scroll bar knob\n  // will get wrong position when editor height changed\n  var scrollInfo = editor.getScrollInfo()\n  editor.scrollTo(null, scrollInfo.top - 1)\n  editor.scrollTo(null, scrollInfo.top)\n}\n\nfunction checkEditorScrollOverLines () {\n  const desireHeight = parseInt(ui.area.codemirrorScroll[0].style.height) || parseInt(ui.area.codemirrorScroll[0].style.minHeight)\n  // make editor have extra padding in the bottom (except small screen)\n  const paddingBottom = editor.doc && editor.doc.height > defaultTextHeight ? (desireHeight - defaultTextHeight) : 0\n  if (parseInt(ui.area.codemirrorLines.css('padding-bottom')) !== paddingBottom) {\n    ui.area.codemirrorLines.css('padding-bottom', paddingBottom + 'px')\n  }\n}\n\nfunction checkTocStyle () {\n  // toc right\n  var paddingRight = parseFloat(ui.area.markdown.css('padding-right'))\n  var right = ($(window).width() - (ui.area.markdown.offset().left + ui.area.markdown.outerWidth() - paddingRight))\n  ui.toc.toc.css('right', right + 'px')\n  // affix toc left\n  var newbool\n  var rightMargin = (ui.area.markdown.parent().outerWidth() - ui.area.markdown.outerWidth()) / 2\n  // for ipad or wider device\n  if (rightMargin >= 133) {\n    newbool = true\n    var affixLeftMargin = (ui.toc.affix.outerWidth() - ui.toc.affix.width()) / 2\n    var left = ui.area.markdown.offset().left + ui.area.markdown.outerWidth() - affixLeftMargin\n    ui.toc.affix.css('left', left + 'px')\n    ui.toc.affix.css('width', rightMargin + 'px')\n  } else {\n    newbool = false\n  }\n  // toc scrollspy\n  ui.toc.toc.removeClass('scrollspy-body, scrollspy-view')\n  ui.toc.affix.removeClass('scrollspy-body, scrollspy-view')\n  if (appState.currentMode === modeType.both) {\n    ui.toc.toc.addClass('scrollspy-view')\n    ui.toc.affix.addClass('scrollspy-view')\n  } else if (appState.currentMode !== modeType.both && !newbool) {\n    ui.toc.toc.addClass('scrollspy-body')\n    ui.toc.affix.addClass('scrollspy-body')\n  } else {\n    ui.toc.toc.addClass('scrollspy-view')\n    ui.toc.affix.addClass('scrollspy-body')\n  }\n  if (newbool !== enoughForAffixToc) {\n    enoughForAffixToc = newbool\n    generateScrollspy()\n  }\n}\n\nfunction showStatus (type, num) {\n  currentStatus = type\n\n  ui.toolbar.statusConnected.hide()\n  ui.toolbar.statusOnline.hide()\n  ui.toolbar.statusOffline.hide()\n\n  switch (currentStatus) {\n    case statusType.connected:\n      ui.toolbar.statusConnected.show()\n      break\n    case statusType.online:\n      ui.toolbar.statusShortMsg.text(num)\n      ui.toolbar.statusOnline.show()\n      break\n    case statusType.offline:\n      ui.toolbar.statusOffline.show()\n      break\n  }\n}\n\nfunction toggleMode () {\n  switch (appState.currentMode) {\n    case modeType.edit:\n      changeMode(modeType.view)\n      break\n    case modeType.view:\n      changeMode(modeType.edit)\n      break\n    case modeType.both:\n      changeMode(modeType.view)\n      break\n  }\n}\n\nvar lastMode = null\n\nfunction changeMode (type) {\n  // lock navbar to prevent it hide after changeMode\n  lockNavbar()\n  saveInfo()\n  if (type) {\n    lastMode = appState.currentMode\n    appState.currentMode = type\n  }\n  var responsiveClass = 'col-lg-6 col-md-6 col-sm-6'\n  var scrollClass = 'ui-scrollable'\n  ui.area.codemirror.removeClass(scrollClass)\n  ui.area.edit.removeClass(responsiveClass)\n  ui.area.view.removeClass(scrollClass)\n  ui.area.view.removeClass(responsiveClass)\n  switch (appState.currentMode) {\n    case modeType.edit:\n      ui.area.edit.show()\n      ui.area.view.hide()\n      if (!editShown) {\n        editor.refresh()\n        editShown = true\n      }\n      break\n    case modeType.view:\n      ui.area.edit.hide()\n      ui.area.view.show()\n      break\n    case modeType.both:\n      ui.area.codemirror.addClass(scrollClass)\n      ui.area.edit.addClass(responsiveClass).show()\n      ui.area.view.addClass(scrollClass)\n      ui.area.view.show()\n      break\n  }\n  // save mode to url\n  if (history.replaceState && window.loaded) history.replaceState(null, '', serverurl + '/' + noteid + '?' + appState.currentMode.name)\n  if (appState.currentMode === modeType.view) {\n    editor.getInputField().blur()\n  }\n  if (appState.currentMode === modeType.edit || appState.currentMode === modeType.both) {\n    ui.toolbar.uploadImage.fadeIn()\n    // add and update status bar\n    if (!editorInstance.statusBar) {\n      editorInstance.addStatusBar()\n      editorInstance.updateStatusBar()\n    }\n    // add and update tool bar\n    if (!editorInstance.toolBar) {\n      editorInstance.addToolBar()\n    }\n    // work around foldGutter might not init properly\n    editor.setOption('foldGutter', false)\n    editor.setOption('foldGutter', true)\n  } else {\n    ui.toolbar.uploadImage.fadeOut()\n  }\n  if (appState.currentMode !== modeType.edit) {\n    $(document.body).css('background-color', 'white')\n    updateView()\n  } else {\n    $(document.body).css('background-color', ui.area.codemirror.css('background-color'))\n  }\n  // check resizable editor style\n  if (appState.currentMode === modeType.both) {\n    if (lastEditorWidth > 0) {\n      ui.area.edit.css('width', lastEditorWidth + 'px')\n    } else {\n      ui.area.edit.css('width', '')\n    }\n    ui.area.resize.handle.show()\n  } else {\n    ui.area.edit.css('width', '')\n    ui.area.resize.handle.hide()\n  }\n\n  windowResizeInner()\n\n  restoreInfo()\n\n  if (lastMode === modeType.view && appState.currentMode === modeType.both) {\n    window.preventSyncScrollToView = 2\n    syncScrollToEdit(null, true)\n  }\n\n  if (lastMode === modeType.edit && appState.currentMode === modeType.both) {\n    window.preventSyncScrollToEdit = 2\n    syncScrollToView(null, true)\n  }\n\n  if (lastMode === modeType.both && appState.currentMode !== modeType.both) {\n    window.preventSyncScrollToView = false\n    window.preventSyncScrollToEdit = false\n  }\n\n  if (lastMode !== modeType.edit && appState.currentMode === modeType.edit) {\n    editor.refresh()\n  }\n\n  $(document.body).scrollspy('refresh')\n  ui.area.view.scrollspy('refresh')\n\n  ui.toolbar.both.removeClass('active')\n  ui.toolbar.edit.removeClass('active')\n  ui.toolbar.view.removeClass('active')\n  var modeIcon = ui.toolbar.mode.find('i')\n  modeIcon.removeClass('fa-pencil').removeClass('fa-eye')\n  if (ui.area.edit.is(':visible') && ui.area.view.is(':visible')) { // both\n    ui.toolbar.both.addClass('active')\n    modeIcon.addClass('fa-eye')\n  } else if (ui.area.edit.is(':visible')) { // edit\n    ui.toolbar.edit.addClass('active')\n    modeIcon.addClass('fa-eye')\n  } else if (ui.area.view.is(':visible')) { // view\n    ui.toolbar.view.addClass('active')\n    modeIcon.addClass('fa-pencil')\n  }\n  unlockNavbar()\n}\n\nfunction lockNavbar () {\n  $('.navbar').addClass('locked')\n}\n\nvar unlockNavbar = _.debounce(function () {\n  $('.navbar').removeClass('locked')\n}, 200)\n\nfunction showMessageModal (title, header, href, text, success) {\n  var modal = $('.message-modal')\n  modal.find('.modal-title').html(title)\n  modal.find('.modal-body h5').html(header)\n  if (href) { modal.find('.modal-body a').attr('href', href).text(text) } else { modal.find('.modal-body a').removeAttr('href').text(text) }\n  modal.find('.modal-footer button').removeClass('btn-default btn-success btn-danger')\n  if (success) { modal.find('.modal-footer button').addClass('btn-success') } else { modal.find('.modal-footer button').addClass('btn-danger') }\n  modal.modal('show')\n}\n\n// check if dropbox app key is set and load scripts\nif (DROPBOX_APP_KEY) {\n  $('<script>')\n    .attr('type', 'text/javascript')\n    .attr('src', 'https://www.dropbox.com/static/api/2/dropins.js')\n    .attr('id', 'dropboxjs')\n    .attr('data-app-key', DROPBOX_APP_KEY)\n    .prop('async', true)\n    .prop('defer', true)\n    .appendTo('body')\n} else {\n  ui.toolbar.import.dropbox.hide()\n  ui.toolbar.export.dropbox.hide()\n}\n\n// button actions\n// share\nui.toolbar.publish.attr('href', noteurl + '/publish')\n// extra\n// slide\nui.toolbar.extra.slide.attr('href', noteurl + '/slide')\n// download\n// markdown\nui.toolbar.download.markdown.click(function (e) {\n  e.preventDefault()\n  e.stopPropagation()\n  var filename = renderFilename(ui.area.markdown) + '.md'\n  var markdown = editor.getValue()\n  var blob = new Blob([markdown], {\n    type: 'text/markdown;charset=utf-8'\n  })\n  saveAs(blob, filename, true)\n})\n// html\nui.toolbar.download.html.click(function (e) {\n  e.preventDefault()\n  e.stopPropagation()\n  exportToHTML(ui.area.markdown)\n})\n// raw html\nui.toolbar.download.rawhtml.click(function (e) {\n  e.preventDefault()\n  e.stopPropagation()\n  exportToRawHTML(ui.area.markdown)\n})\n// pdf\nui.toolbar.download.pdf.attr('download', '').attr('href', noteurl + '/pdf')\n\nui.modal.pandocExport.find('#pandoc-export-download').click(function (e) {\n  e.preventDefault()\n\n  const exportType = ui.modal.pandocExport.find('select[name=\"output\"]').val()\n\n  window.open(`${noteurl}/pandoc?exportType=${exportType}`, '_blank')\n})\n\n// export to dropbox\nui.toolbar.export.dropbox.click(function () {\n  var filename = renderFilename(ui.area.markdown) + '.md'\n  var options = {\n    files: [\n      {\n        url: noteurl + '/download',\n        filename: filename\n      }\n    ],\n    error: function (errorMessage) {\n      console.error(errorMessage)\n    }\n  }\n  Dropbox.save(options)\n})\n// export to gist\nui.toolbar.export.gist.attr('href', noteurl + '/gist')\n// export to snippet\nui.toolbar.export.snippet.click(function () {\n  ui.spinner.show()\n  $.get(serverurl + '/auth/gitlab/callback/' + noteid + '/projects')\n    .done(function (data) {\n      $('#snippetExportModalAccessToken').val(data.accesstoken)\n      $('#snippetExportModalBaseURL').val(data.baseURL)\n      $('#snippetExportModalVersion').val(data.version)\n      $('#snippetExportModalLoading').hide()\n      $('#snippetExportModal').modal('toggle')\n      $('#snippetExportModalProjects').find('option').remove().end().append('<option value=\"init\" selected=\"selected\" disabled=\"disabled\">Select From Available Projects</option>')\n      if (data.projects) {\n        data.projects.sort(function (a, b) {\n          return (a.path_with_namespace < b.path_with_namespace) ? -1 : ((a.path_with_namespace > b.path_with_namespace) ? 1 : 0)\n        })\n        data.projects.forEach(function (project) {\n          if (!project.snippets_enabled ||\n                        (project.permissions.project_access === null && project.permissions.group_access === null) ||\n                        (project.permissions.project_access !== null && project.permissions.project_access.access_level < 20)) {\n            return\n          }\n          $('<option>').val(project.id).text(project.path_with_namespace).appendTo('#snippetExportModalProjects')\n        })\n        $('#snippetExportModalProjects').prop('disabled', false)\n      }\n      $('#snippetExportModalLoading').hide()\n    })\n    .fail(function (data) {\n      showMessageModal('<i class=\"fa fa-gitlab\"></i> Import from Snippet', 'Unable to fetch gitlab parameters :(', '', '', false)\n    })\n    .always(function () {\n      ui.spinner.hide()\n    })\n})\n// import from dropbox\nui.toolbar.import.dropbox.click(function () {\n  var options = {\n    success: function (files) {\n      ui.spinner.show()\n      var url = files[0].link\n      importFromUrl(url)\n    },\n    linkType: 'direct',\n    multiselect: false,\n    extensions: ['.md', '.html']\n  }\n  Dropbox.choose(options)\n})\n// import from gist\nui.toolbar.import.gist.click(function () {\n  // na\n})\n// import from snippet\nui.toolbar.import.snippet.click(function () {\n  ui.spinner.show()\n  $.get(serverurl + '/auth/gitlab/callback/' + noteid + '/projects')\n    .done(function (data) {\n      $('#snippetImportModalAccessToken').val(data.accesstoken)\n      $('#snippetImportModalBaseURL').val(data.baseURL)\n      $('#snippetImportModalVersion').val(data.version)\n      $('#snippetImportModalContent').prop('disabled', false)\n      $('#snippetImportModalConfirm').prop('disabled', false)\n      $('#snippetImportModalLoading').hide()\n      $('#snippetImportModal').modal('toggle')\n      $('#snippetImportModalProjects').find('option').remove().end().append('<option value=\"init\" selected=\"selected\" disabled=\"disabled\">Select From Available Projects</option>')\n      if (data.projects) {\n        data.projects.sort(function (a, b) {\n          return (a.path_with_namespace < b.path_with_namespace) ? -1 : ((a.path_with_namespace > b.path_with_namespace) ? 1 : 0)\n        })\n        data.projects.forEach(function (project) {\n          if (!project.snippets_enabled ||\n                        (project.permissions.project_access === null && project.permissions.group_access === null) ||\n                        (project.permissions.project_access !== null && project.permissions.project_access.access_level < 20)) {\n            return\n          }\n          $('<option>').val(project.id).text(project.path_with_namespace).appendTo('#snippetImportModalProjects')\n        })\n        $('#snippetImportModalProjects').prop('disabled', false)\n      }\n      $('#snippetImportModalLoading').hide()\n    })\n    .fail(function (data) {\n      showMessageModal('<i class=\"fa fa-gitlab\"></i> Import from Snippet', 'Unable to fetch gitlab parameters :(', '', '', false)\n    })\n    .always(function () {\n      ui.spinner.hide()\n    })\n})\n// import from clipboard\nui.toolbar.import.clipboard.click(function () {\n  // na\n})\n// upload image\nui.toolbar.uploadImage.bind('change', function (e) {\n  var files = e.target.files || e.dataTransfer.files\n  e.dataTransfer = {}\n  e.dataTransfer.files = files\n  inlineAttach.onDrop(e)\n})\n// toc\nui.toc.dropdown.click(function (e) {\n  e.stopPropagation()\n})\n// prevent empty link change hash\n$('a[href=\"#\"]').click(function (e) {\n  e.preventDefault()\n})\n\n// modal actions\nvar revisions = []\nvar revisionViewer = null\nvar revisionInsert = []\nvar revisionDelete = []\nvar revisionInsertAnnotation = null\nvar revisionDeleteAnnotation = null\nvar revisionList = ui.modal.revision.find('.ui-revision-list')\nvar revision = null\nvar revisionTime = null\nui.modal.revision.on('show.bs.modal', function (e) {\n  $.get(noteurl + '/revision')\n    .done(function (data) {\n      parseRevisions(data.revision)\n      initRevisionViewer()\n    })\n    .fail(function (err) {\n      if (debug) {\n        console.log(err)\n      }\n    })\n    .always(function () {\n      // na\n    })\n})\nfunction checkRevisionViewer () {\n  if (revisionViewer) {\n    var container = $(revisionViewer.display.wrapper).parent()\n    $(revisionViewer.display.scroller).css('height', container.height() + 'px')\n    revisionViewer.refresh()\n  }\n}\nui.modal.revision.on('shown.bs.modal', checkRevisionViewer)\n$(window).resize(checkRevisionViewer)\nfunction parseRevisions (_revisions) {\n  if (_revisions.length !== revisions) {\n    revisions = _revisions\n    var lastRevision = null\n    if (revisionList.children().length > 0) {\n      lastRevision = revisionList.find('.active').attr('data-revision-time')\n    }\n    revisionList.html('')\n    for (var i = 0; i < revisions.length; i++) {\n      var revision = revisions[i]\n      var item = $('<a href=\"#\" class=\"list-group-item\"></a>')\n      item.attr('data-revision-time', revision.time)\n      if (lastRevision === revision.time) item.addClass('active')\n      var itemHeading = $('<h5 class=\"list-group-item-heading\"></h5>')\n      itemHeading.html('<i class=\"fa fa-clock-o\"></i> ' + moment(revision.time).format('llll'))\n      var itemText = $('<p class=\"list-group-item-text\"></p>')\n      itemText.html('<i class=\"fa fa-file-text\"></i> Length: ' + revision.length)\n      item.append(itemHeading).append(itemText)\n      item.click(function (e) {\n        var time = $(this).attr('data-revision-time')\n        selectRevision(time)\n      })\n      revisionList.append(item)\n    }\n    if (!lastRevision) {\n      selectRevision(revisions[0].time)\n    }\n  }\n}\nfunction selectRevision (time) {\n  if (time === revisionTime) return\n  $.get(noteurl + '/revision/' + time)\n    .done(function (data) {\n      revision = data\n      revisionTime = time\n      var lastScrollInfo = revisionViewer.getScrollInfo()\n      revisionList.children().removeClass('active')\n      revisionList.find('[data-revision-time=\"' + time + '\"]').addClass('active')\n      var content = revision.content\n      revisionViewer.setValue(content)\n      revisionViewer.scrollTo(null, lastScrollInfo.top)\n      revisionInsert = []\n      revisionDelete = []\n      // mark the text which have been insert or delete\n      if (revision.patch.length > 0) {\n        var bias = 0\n        for (var j = 0; j < revision.patch.length; j++) {\n          var patch = revision.patch[j]\n          var currIndex = patch.start1 + bias\n          for (var i = 0; i < patch.diffs.length; i++) {\n            var diff = patch.diffs[i]\n            // ignore if diff only contains line breaks\n            if ((diff[1].match(/\\n/g) || []).length === diff[1].length) continue\n            var prePos\n            var postPos\n            switch (diff[0]) {\n              case 0: // retain\n                currIndex += diff[1].length\n                break\n              case 1: // insert\n                prePos = revisionViewer.posFromIndex(currIndex)\n                postPos = revisionViewer.posFromIndex(currIndex + diff[1].length)\n                revisionInsert.push({\n                  from: prePos,\n                  to: postPos\n                })\n                revisionViewer.markText(prePos, postPos, {\n                  css: 'background-color: rgba(230,255,230,0.7); text-decoration: underline;'\n                })\n                currIndex += diff[1].length\n                break\n              case -1: // delete\n                prePos = revisionViewer.posFromIndex(currIndex)\n                revisionViewer.replaceRange(diff[1], prePos)\n                postPos = revisionViewer.posFromIndex(currIndex + diff[1].length)\n                revisionDelete.push({\n                  from: prePos,\n                  to: postPos\n                })\n                revisionViewer.markText(prePos, postPos, {\n                  css: 'background-color: rgba(255,230,230,0.7); text-decoration: line-through;'\n                })\n                bias += diff[1].length\n                currIndex += diff[1].length\n                break\n            }\n          }\n        }\n      }\n      revisionInsertAnnotation.update(revisionInsert)\n      revisionDeleteAnnotation.update(revisionDelete)\n    })\n    .fail(function (err) {\n      if (debug) {\n        console.log(err)\n      }\n    })\n    .always(function () {\n      // na\n    })\n}\nfunction initRevisionViewer () {\n  if (revisionViewer) return\n  var revisionViewerTextArea = document.getElementById('revisionViewer')\n  revisionViewer = CodeMirror.fromTextArea(revisionViewerTextArea, {\n    mode: defaultEditorMode,\n    viewportMargin: viewportMargin,\n    lineNumbers: true,\n    lineWrapping: true,\n    showCursorWhenSelecting: true,\n    inputStyle: 'textarea',\n    gutters: ['CodeMirror-linenumbers'],\n    flattenSpans: true,\n    addModeClass: true,\n    readOnly: true,\n    autoRefresh: true,\n    scrollbarStyle: 'overlay'\n  })\n  revisionInsertAnnotation = revisionViewer.annotateScrollbar({ className: 'CodeMirror-insert-match' })\n  revisionDeleteAnnotation = revisionViewer.annotateScrollbar({ className: 'CodeMirror-delete-match' })\n  checkRevisionViewer()\n}\n$('#revisionModalDownload').click(function () {\n  if (!revision) return\n  var filename = renderFilename(ui.area.markdown) + '_' + revisionTime + '.md'\n  var blob = new Blob([revision.content], {\n    type: 'text/markdown;charset=utf-8'\n  })\n  saveAs(blob, filename, true)\n})\n$('#revisionModalRevert').click(function () {\n  if (!revision) return\n  editor.setValue(revision.content)\n  ui.modal.revision.modal('hide')\n})\n// snippet projects\nui.modal.snippetImportProjects.change(function () {\n  var accesstoken = $('#snippetImportModalAccessToken').val()\n  var baseURL = $('#snippetImportModalBaseURL').val()\n  var project = $('#snippetImportModalProjects').val()\n  var version = $('#snippetImportModalVersion').val()\n  $('#snippetImportModalLoading').show()\n  $('#snippetImportModalContent').val('/projects/' + project)\n  $.get(baseURL + '/api/' + version + '/projects/' + project + '/snippets?access_token=' + accesstoken)\n    .done(function (data) {\n      $('#snippetImportModalSnippets').find('option').remove().end().append('<option value=\"init\" selected=\"selected\" disabled=\"disabled\">Select From Available Snippets</option>')\n      data.forEach(function (snippet) {\n        $('<option>').val(snippet.id).text(snippet.title).appendTo($('#snippetImportModalSnippets'))\n      })\n      $('#snippetImportModalLoading').hide()\n      $('#snippetImportModalSnippets').prop('disabled', false)\n    })\n    .fail(function (err) {\n      if (debug) {\n        console.log(err)\n      }\n    })\n    .always(function () {\n      // na\n    })\n})\n// snippet snippets\nui.modal.snippetImportSnippets.change(function () {\n  var snippet = $('#snippetImportModalSnippets').val()\n  $('#snippetImportModalContent').val($('#snippetImportModalContent').val() + '/snippets/' + snippet)\n})\n\nfunction scrollToTop () {\n  if (appState.currentMode === modeType.both) {\n    if (editor.getScrollInfo().top !== 0) { editor.scrollTo(0, 0) } else {\n      ui.area.view.animate({\n        scrollTop: 0\n      }, 100, 'linear')\n    }\n  } else {\n    $('body, html').stop(true, true).animate({\n      scrollTop: 0\n    }, 100, 'linear')\n  }\n}\n\nfunction scrollToBottom () {\n  if (appState.currentMode === modeType.both) {\n    var scrollInfo = editor.getScrollInfo()\n    var scrollHeight = scrollInfo.height\n    if (scrollInfo.top !== scrollHeight) { editor.scrollTo(0, scrollHeight * 2) } else {\n      ui.area.view.animate({\n        scrollTop: ui.area.view[0].scrollHeight\n      }, 100, 'linear')\n    }\n  } else {\n    $('body, html').stop(true, true).animate({\n      scrollTop: $(document.body)[0].scrollHeight\n    }, 100, 'linear')\n  }\n}\n\nwindow.scrollToTop = scrollToTop\nwindow.scrollToBottom = scrollToBottom\n\nvar enoughForAffixToc = true\n\n// scrollspy\nfunction generateScrollspy () {\n  $(document.body).scrollspy({\n    target: '.scrollspy-body'\n  })\n  ui.area.view.scrollspy({\n    target: '.scrollspy-view'\n  })\n  $(document.body).scrollspy('refresh')\n  ui.area.view.scrollspy('refresh')\n  if (enoughForAffixToc) {\n    ui.toc.toc.hide()\n    ui.toc.affix.show()\n  } else {\n    ui.toc.affix.hide()\n    ui.toc.toc.show()\n  }\n  // $(document.body).scroll();\n  // ui.area.view.scroll();\n}\n\nfunction updateScrollspy () {\n  var headers = ui.area.markdown.find('h1, h2, h3').toArray()\n  var headerMap = []\n  for (var i = 0; i < headers.length; i++) {\n    headerMap.push($(headers[i]).offset().top - parseInt($(headers[i]).css('margin-top')))\n  }\n  applyScrollspyActive($(window).scrollTop(), headerMap, headers,\n    $('.scrollspy-body'), 0)\n  var offset = ui.area.view.scrollTop() - ui.area.view.offset().top\n  applyScrollspyActive(ui.area.view.scrollTop(), headerMap, headers,\n    $('.scrollspy-view'), offset - 10)\n}\n\nfunction applyScrollspyActive (top, headerMap, headers, target, offset) {\n  var index = 0\n  for (var i = headerMap.length - 1; i >= 0; i--) {\n    if (top >= (headerMap[i] + offset) && headerMap[i + 1] && top < (headerMap[i + 1] + offset)) {\n      index = i\n      break\n    }\n  }\n  var header = $(headers[index])\n  var active = target.find('a[href=\"#' + header.attr('id') + '\"]')\n  active.closest('li').addClass('active').parent().closest('li').addClass('active').parent().closest('li').addClass('active')\n}\n\n// clipboard modal\n// fix for wrong autofocus\n$('#clipboardModal').on('shown.bs.modal', function () {\n  $('#clipboardModal').blur()\n})\n$('#clipboardModalClear').click(function () {\n  $('#clipboardModalContent').html('')\n})\n$('#clipboardModalConfirm').click(function () {\n  var data = $('#clipboardModalContent').html()\n  if (data) {\n    parseToEditor(data)\n    $('#clipboardModal').modal('hide')\n    $('#clipboardModalContent').html('')\n  }\n})\n\n// refresh modal\n$('#refreshModalRefresh').click(function () {\n  location.reload(true)\n})\n\n// gist import modal\n$('#gistImportModalClear').click(function () {\n  $('#gistImportModalContent').val('')\n})\n$('#gistImportModalConfirm').click(function () {\n  var gisturl = $('#gistImportModalContent').val()\n  if (!gisturl) return\n  $('#gistImportModal').modal('hide')\n  $('#gistImportModalContent').val('')\n  if (!isURL(gisturl)) {\n    showMessageModal('<i class=\"fa fa-github\"></i> Import from Gist', 'Not a valid URL :(', '', '', false)\n  } else {\n    var hostname = wurl('hostname', gisturl)\n    if (hostname !== 'gist.github.com') {\n      showMessageModal('<i class=\"fa fa-github\"></i> Import from Gist', 'Not a valid Gist URL :(', '', '', false)\n    } else {\n      ui.spinner.show()\n      $.get('https://api.github.com/gists/' + wurl('-1', gisturl))\n        .done(function (data) {\n          if (data.files) {\n            var contents = ''\n            Object.keys(data.files).forEach(function (key) {\n              contents += key\n              contents += '\\n---\\n'\n              contents += data.files[key].content\n              contents += '\\n\\n'\n            })\n            replaceAll(contents)\n          } else {\n            showMessageModal('<i class=\"fa fa-github\"></i> Import from Gist', 'Unable to fetch gist files :(', '', '', false)\n          }\n        })\n        .fail(function (data) {\n          showMessageModal('<i class=\"fa fa-github\"></i> Import from Gist', 'Not a valid Gist URL :(', '', JSON.stringify(data), false)\n        })\n        .always(function () {\n          ui.spinner.hide()\n        })\n    }\n  }\n})\n\n// snippet import modal\n$('#snippetImportModalClear').click(function () {\n  $('#snippetImportModalContent').val('')\n  $('#snippetImportModalProjects').val('init')\n  $('#snippetImportModalSnippets').val('init')\n  $('#snippetImportModalSnippets').prop('disabled', true)\n})\n$('#snippetImportModalConfirm').click(function () {\n  var snippeturl = $('#snippetImportModalContent').val()\n  if (!snippeturl) return\n  $('#snippetImportModal').modal('hide')\n  $('#snippetImportModalContent').val('')\n  if (!/^.+\\/snippets\\/.+$/.test(snippeturl)) {\n    showMessageModal('<i class=\"fa fa-github\"></i> Import from Snippet', 'Not a valid Snippet URL :(', '', '', false)\n  } else {\n    ui.spinner.show()\n    var accessToken = '?access_token=' + $('#snippetImportModalAccessToken').val()\n    var fullURL = $('#snippetImportModalBaseURL').val() + '/api/' + $('#snippetImportModalVersion').val() + snippeturl\n    $.get(fullURL + accessToken)\n      .done(function (data) {\n        var content = '# ' + (data.title || 'Snippet Import')\n        var fileInfo = data.file_name.split('.')\n        fileInfo[1] = (fileInfo[1]) ? fileInfo[1] : 'md'\n        $.get(fullURL + '/raw' + accessToken)\n          .done(function (raw) {\n            if (raw) {\n              content += '\\n\\n'\n              if (fileInfo[1] !== 'md') {\n                content += '```' + fileTypes[fileInfo[1]] + '\\n'\n              }\n              content += raw\n              if (fileInfo[1] !== 'md') {\n                content += '\\n```'\n              }\n              replaceAll(content)\n            }\n          })\n          .fail(function (data) {\n            showMessageModal('<i class=\"fa fa-gitlab\"></i> Import from Snippet', 'Not a valid Snippet URL :(', '', JSON.stringify(data), false)\n          })\n          .always(function () {\n            ui.spinner.hide()\n          })\n      })\n      .fail(function (data) {\n        showMessageModal('<i class=\"fa fa-gitlab\"></i> Import from Snippet', 'Not a valid Snippet URL :(', '', JSON.stringify(data), false)\n      })\n  }\n})\n\n// snippet export modal\n$('#snippetExportModalConfirm').click(function () {\n  var accesstoken = $('#snippetExportModalAccessToken').val()\n  var baseURL = $('#snippetExportModalBaseURL').val()\n  var version = $('#snippetExportModalVersion').val()\n\n  var data = {\n    title: $('#snippetExportModalTitle').val(),\n    file_name: $('#snippetExportModalFileName').val(),\n    code: editor.getValue(),\n    visibility_level: $('#snippetExportModalVisibility').val(),\n    visibility: $('#snippetExportModalVisibility').val() === '0' ? 'private' : ($('#snippetExportModalVisibility').val() === '10' ? 'internal' : 'private')\n  }\n\n  if (!data.title || !data.file_name || !data.code || !data.visibility_level || !$('#snippetExportModalProjects').val()) return\n  $('#snippetExportModalLoading').show()\n  var fullURL = baseURL + '/api/' + version + '/projects/' + $('#snippetExportModalProjects').val() + '/snippets?access_token=' + accesstoken\n  $.post(fullURL\n    , data\n    , function (ret) {\n      $('#snippetExportModalLoading').hide()\n      $('#snippetExportModal').modal('hide')\n      var redirect = baseURL + '/' + $(\"#snippetExportModalProjects option[value='\" + $('#snippetExportModalProjects').val() + \"']\").text() + '/snippets/' + ret.id\n      showMessageModal('<i class=\"fa fa-gitlab\"></i> Export to Snippet', 'Export Successful!', redirect, 'View Snippet Here', true)\n    }\n  )\n})\n\nfunction parseToEditor (data) {\n  var turndownService = new TurndownService({\n    defaultReplacement: function (innerHTML, node) {\n      return node.isBlock ? '\\n\\n' + node.outerHTML + '\\n\\n' : node.outerHTML\n    }\n  })\n  var parsed = turndownService.turndown(data)\n  if (parsed) { replaceAll(parsed) }\n}\n\nfunction replaceAll (data) {\n  editor.replaceRange(data, {\n    line: 0,\n    ch: 0\n  }, {\n    line: editor.lastLine(),\n    ch: editor.lastLine().length\n  }, '+input')\n}\n\nfunction importFromUrl (url) {\n  // console.log(url);\n  if (!url) return\n  if (!isURL(url)) {\n    showMessageModal('<i class=\"fa fa-cloud-download\"></i> Import from URL', 'Not a valid URL :(', '', '', false)\n    return\n  }\n  $.ajax({\n    method: 'GET',\n    url: url,\n    success: function (data) {\n      var extension = url.split('.').pop()\n      if (extension === 'html') { parseToEditor(data) } else { replaceAll(data) }\n    },\n    error: function (data) {\n      showMessageModal('<i class=\"fa fa-cloud-download\"></i> Import from URL', 'Import failed :(', '', JSON.stringify(data), false)\n    },\n    complete: function () {\n      ui.spinner.hide()\n    }\n  })\n}\n\n// mode\nui.toolbar.mode.click(function () {\n  toggleMode()\n})\n// edit\nui.toolbar.edit.click(function () {\n  changeMode(modeType.edit)\n})\n// view\nui.toolbar.view.click(function () {\n  changeMode(modeType.view)\n})\n// both\nui.toolbar.both.click(function () {\n  changeMode(modeType.both)\n})\n\nui.toolbar.night.click(function () {\n  toggleNightMode()\n})\n// permission\n// freely\nui.infobar.permission.freely.click(function () {\n  emitPermission('freely')\n})\n// editable\nui.infobar.permission.editable.click(function () {\n  emitPermission('editable')\n})\n// locked\nui.infobar.permission.locked.click(function () {\n  emitPermission('locked')\n})\n// private\nui.infobar.permission.private.click(function () {\n  emitPermission('private')\n})\n// limited\nui.infobar.permission.limited.click(function () {\n  emitPermission('limited')\n})\n// protected\nui.infobar.permission.protected.click(function () {\n  emitPermission('protected')\n})\n// delete note\nui.infobar.delete.click(function () {\n  $('.delete-modal').modal('show')\n})\n$('.ui-delete-modal-confirm').click(function () {\n  socket.emit('delete')\n})\n\nfunction toggleNightMode () {\n  var $body = $('body')\n  var isActive = ui.toolbar.night.hasClass('active')\n  if (isActive) {\n    $body.removeClass('night')\n    appState.nightMode = false\n  } else {\n    $body.addClass('night')\n    appState.nightMode = true\n  }\n  if (store.enabled) {\n    store.set('nightMode', !isActive)\n  } else {\n    Cookies.set('nightMode', !isActive, {\n      expires: 365\n    })\n  }\n}\nfunction emitPermission (_permission) {\n  if (_permission !== permission) {\n    socket.emit('permission', _permission)\n  }\n}\n\nfunction updatePermission (newPermission) {\n  if (permission !== newPermission) {\n    permission = newPermission\n    if (window.loaded) refreshView()\n  }\n  ui.infobar.permission.label.hide()\n  switch (permission) {\n    case 'freely':\n      $('#permissionLabelFreely').show()\n      break\n    case 'editable':\n      $('#permissionLabelEditable').show()\n      break\n    case 'limited':\n      $('#permissionLabelLimited').show()\n      break\n    case 'locked':\n      $('#permissionLabelLocked').show()\n      break\n    case 'protected':\n      $('#permissionLabelProtected').show()\n      break\n    case 'private':\n      $('#permissionLabelPrivate').show()\n      break\n  }\n  if (personalInfo.userid && window.owner && personalInfo.userid === window.owner) {\n    ui.infobar.permission.labelCaretDown.show()\n    ui.infobar.permission.label.removeClass('disabled')\n  } else {\n    ui.infobar.permission.labelCaretDown.hide()\n    ui.infobar.permission.label.addClass('disabled')\n  }\n}\n\nfunction havePermission () {\n  var bool = false\n  switch (permission) {\n    case 'freely':\n      bool = true\n      break\n    case 'editable':\n    case 'limited':\n      if (!personalInfo.login) {\n        bool = false\n      } else {\n        bool = true\n      }\n      break\n    case 'locked':\n    case 'private':\n    case 'protected':\n      if (!window.owner || personalInfo.userid !== window.owner) {\n        bool = false\n      } else {\n        bool = true\n      }\n      break\n  }\n  return bool\n}\n// global module workaround\nwindow.havePermission = havePermission\n\n// socket.io actions\nvar io = require('socket.io-client')\nvar socket = io.connect({\n  path: urlpath ? '/' + urlpath + '/socket.io/' : '',\n  query: {\n    noteId: noteid\n  },\n  timeout: 5000, // 5 secs to timeout,\n  reconnectionAttempts: 20 // retry 20 times on connect failed\n})\n// overwrite original event for checking login state\nvar on = socket.on\nsocket.on = function () {\n  if (!checkLoginStateChanged() && !needRefresh) { return on.apply(socket, arguments) }\n}\nvar emit = socket.emit\nsocket.emit = function () {\n  if (!checkLoginStateChanged() && !needRefresh) { emit.apply(socket, arguments) }\n}\nsocket.on('info', function (data) {\n  console.error(data)\n  switch (data.code) {\n    case 403:\n      location.href = serverurl + '/403'\n      break\n    case 404:\n      location.href = serverurl + '/404'\n      break\n    case 500:\n      location.href = serverurl + '/500'\n      break\n  }\n})\nsocket.on('error', function (data) {\n  console.error(data)\n  if (data.message && data.message.indexOf('AUTH failed') === 0) { location.href = serverurl + '/403' }\n})\nsocket.on('delete', function () {\n  if (personalInfo.login) {\n    deleteServerHistory(noteid, function (err, data) {\n      if (!err) location.href = serverurl\n    })\n  } else {\n    getHistory(function (notehistory) {\n      var newnotehistory = removeHistory(noteid, notehistory)\n      saveHistory(newnotehistory)\n      location.href = serverurl\n    })\n  }\n})\nvar retryTimer = null\nsocket.on('maintenance', function () {\n  cmClient.revision = -1\n})\nsocket.on('disconnect', function (data) {\n  showStatus(statusType.offline)\n  if (window.loaded) {\n    saveInfo()\n    lastInfo.history = editor.getHistory()\n  }\n  if (!editor.getOption('readOnly')) { editor.setOption('readOnly', true) }\n  if (!retryTimer) {\n    retryTimer = setInterval(function () {\n      if (!needRefresh) socket.connect()\n    }, 1000)\n  }\n})\nsocket.on('reconnect', function (data) {\n  // sync back any change in offline\n  emitUserStatus(true)\n  cursorActivity(editor)\n  socket.emit('online users')\n})\nsocket.on('connect', function (data) {\n  clearInterval(retryTimer)\n  retryTimer = null\n  personalInfo.id = socket.id\n  showStatus(statusType.connected)\n  socket.emit('version')\n})\nsocket.on('version', function (data) {\n  if (version !== data.version) {\n    if (version < data.minimumCompatibleVersion) {\n      setRefreshModal('incompatible-version')\n      setNeedRefresh()\n    } else {\n      setRefreshModal('new-version')\n    }\n  }\n})\nvar authors = []\nvar authorship = []\nvar authorMarks = {} // temp variable\nvar addTextMarkers = [] // temp variable\nfunction updateInfo (data) {\n  // console.log(data);\n  if (Object.hasOwnProperty.call(data, 'createtime') && window.createtime !== data.createtime) {\n    window.createtime = data.createtime\n    updateLastChange()\n  }\n  if (Object.hasOwnProperty.call(data, 'updatetime') && window.lastchangetime !== data.updatetime) {\n    window.lastchangetime = data.updatetime\n    updateLastChange()\n  }\n  if (Object.hasOwnProperty.call(data, 'owner') && window.owner !== data.owner) {\n    window.owner = data.owner\n    window.ownerprofile = data.ownerprofile\n    updateOwner()\n  }\n  if (Object.hasOwnProperty.call(data, 'lastchangeuser') && window.lastchangeuser !== data.lastchangeuser) {\n    window.lastchangeuser = data.lastchangeuser\n    window.lastchangeuserprofile = data.lastchangeuserprofile\n    updateLastChangeUser()\n    updateOwner()\n  }\n  if (Object.hasOwnProperty.call(data, 'authors') && authors !== data.authors) {\n    authors = data.authors\n  }\n  if (Object.hasOwnProperty.call(data, 'authorship') && authorship !== data.authorship) {\n    authorship = data.authorship\n    updateAuthorship()\n  }\n}\nvar updateAuthorship = _.debounce(function () {\n  editor.operation(updateAuthorshipInner)\n}, 50)\nfunction initMark () {\n  return {\n    gutter: {\n      userid: null,\n      timestamp: null\n    },\n    textmarkers: []\n  }\n}\nfunction initMarkAndCheckGutter (mark, author, timestamp) {\n  if (!mark) mark = initMark()\n  if (!mark.gutter.userid || mark.gutter.timestamp > timestamp) {\n    mark.gutter.userid = author.userid\n    mark.gutter.timestamp = timestamp\n  }\n  return mark\n}\nvar addStyleRule = (function () {\n  var added = {}\n  var styleElement = document.createElement('style')\n  document.documentElement.getElementsByTagName('head')[0].appendChild(styleElement)\n  var styleSheet = styleElement.sheet\n\n  return function (css) {\n    if (added[css]) {\n      return\n    }\n    added[css] = true\n    styleSheet.insertRule(css, (styleSheet.cssRules || styleSheet.rules).length)\n  }\n}())\nfunction updateAuthorshipInner () {\n  // ignore when ot not synced yet\n  if (havePendingOperation()) return\n  authorMarks = {}\n  for (let i = 0; i < authorship.length; i++) {\n    var atom = authorship[i]\n    const author = authors[atom[0]]\n    if (author) {\n      var prePos = editor.posFromIndex(atom[1])\n      var preLine = editor.getLine(prePos.line)\n      var postPos = editor.posFromIndex(atom[2])\n      var postLine = editor.getLine(postPos.line)\n      if (prePos.ch === 0 && postPos.ch === postLine.length) {\n        for (let j = prePos.line; j <= postPos.line; j++) {\n          if (editor.getLine(j)) {\n            authorMarks[j] = initMarkAndCheckGutter(authorMarks[j], author, atom[3])\n          }\n        }\n      } else if (postPos.line - prePos.line >= 1) {\n        var startLine = prePos.line\n        var endLine = postPos.line\n        if (prePos.ch === preLine.length) {\n          startLine++\n        } else if (prePos.ch !== 0) {\n          const mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3])\n          var _postPos = {\n            line: prePos.line,\n            ch: preLine.length\n          }\n          if (JSON.stringify(prePos) !== JSON.stringify(_postPos)) {\n            mark.textmarkers.push({\n              userid: author.userid,\n              pos: [prePos, _postPos]\n            })\n            startLine++\n          }\n          authorMarks[prePos.line] = mark\n        }\n        if (postPos.ch === 0) {\n          endLine--\n        } else if (postPos.ch !== postLine.length) {\n          const mark = initMarkAndCheckGutter(authorMarks[postPos.line], author, atom[3])\n          var _prePos = {\n            line: postPos.line,\n            ch: 0\n          }\n          if (JSON.stringify(_prePos) !== JSON.stringify(postPos)) {\n            mark.textmarkers.push({\n              userid: author.userid,\n              pos: [_prePos, postPos]\n            })\n            endLine--\n          }\n          authorMarks[postPos.line] = mark\n        }\n        for (let j = startLine; j <= endLine; j++) {\n          if (editor.getLine(j)) {\n            authorMarks[j] = initMarkAndCheckGutter(authorMarks[j], author, atom[3])\n          }\n        }\n      } else {\n        const mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3])\n        if (JSON.stringify(prePos) !== JSON.stringify(postPos)) {\n          mark.textmarkers.push({\n            userid: author.userid,\n            pos: [prePos, postPos]\n          })\n        }\n        authorMarks[prePos.line] = mark\n      }\n    }\n  }\n  addTextMarkers = []\n  editor.eachLine(iterateLine)\n  const allTextMarks = editor.getAllMarks()\n  for (let i = 0; i < allTextMarks.length; i++) {\n    const _textMarker = allTextMarks[i]\n    const pos = _textMarker.find()\n    let found = false\n    for (let j = 0; j < addTextMarkers.length; j++) {\n      const textMarker = addTextMarkers[j]\n      const author = authors[textMarker.userid]\n      const className = 'authorship-inline-' + author.color.substr(1)\n      var obj = {\n        from: textMarker.pos[0],\n        to: textMarker.pos[1]\n      }\n      if (JSON.stringify(pos) === JSON.stringify(obj) && _textMarker.className &&\n                _textMarker.className.indexOf(className) > -1) {\n        addTextMarkers.splice(j, 1)\n        j--\n        found = true\n        break\n      }\n    }\n    if (!found && _textMarker.className && _textMarker.className.indexOf('authorship-inline') > -1) {\n      _textMarker.clear()\n    }\n  }\n  for (let i = 0; i < addTextMarkers.length; i++) {\n    const textMarker = addTextMarkers[i]\n    const author = authors[textMarker.userid]\n    const rgbcolor = hex2rgb(author.color)\n    const colorString = `rgba(${rgbcolor.red},${rgbcolor.green},${rgbcolor.blue},0.7)`\n    const styleString = `background-image: linear-gradient(to top, ${colorString} 1px, transparent 1px);`\n    const className = `authorship-inline-${author.color.substr(1)}`\n    const rule = `.${className} { ${styleString} }`\n    addStyleRule(rule)\n    editor.markText(textMarker.pos[0], textMarker.pos[1], {\n      className: 'authorship-inline ' + className,\n      title: author.name\n    })\n  }\n}\nfunction iterateLine (line) {\n  const lineNumber = line.lineNo()\n  const currMark = authorMarks[lineNumber]\n  const author = currMark ? authors[currMark.gutter.userid] : null\n  if (currMark && author) {\n    const className = 'authorship-gutter-' + author.color.substr(1)\n    const gutters = line.gutterMarkers\n    if (!gutters || !gutters['authorship-gutters'] ||\n        !gutters['authorship-gutters'].className ||\n        !gutters['authorship-gutters'].className.indexOf(className) < 0) {\n      const styleString = `border-left: 3px solid ${author.color}; height: ${defaultTextHeight}px; margin-left: 3px;`\n      const rule = `.${className} { ${styleString} }`\n      addStyleRule(rule)\n      const gutter = $('<div>', {\n        class: 'authorship-gutter ' + className,\n        title: author.name\n      })\n      editor.setGutterMarker(line, 'authorship-gutters', gutter[0])\n    }\n  } else {\n    editor.setGutterMarker(line, 'authorship-gutters', null)\n  }\n  if (currMark && currMark.textmarkers.length > 0) {\n    for (let i = 0; i < currMark.textmarkers.length; i++) {\n      const textMarker = currMark.textmarkers[i]\n      if (textMarker.userid !== currMark.gutter.userid) {\n        addTextMarkers.push(textMarker)\n      }\n    }\n  }\n}\neditorInstance.on('update', function () {\n  $('.authorship-gutter:not([data-original-title])').tooltip({\n    container: '.CodeMirror-lines',\n    placement: 'right',\n    delay: { show: 500, hide: 100 }\n  })\n  $('.authorship-inline:not([data-original-title])').tooltip({\n    container: '.CodeMirror-lines',\n    placement: 'bottom',\n    delay: { show: 500, hide: 100 }\n  })\n  // clear tooltip which described element has been removed\n  $('[id^=\"tooltip\"]').each(function (index, element) {\n    var $ele = $(element)\n    if ($('[aria-describedby=\"' + $ele.attr('id') + '\"]').length <= 0) $ele.remove()\n  })\n})\nsocket.on('check', function (data) {\n  // console.log(data);\n  updateInfo(data)\n})\nsocket.on('permission', function (data) {\n  updatePermission(data.permission)\n})\n\nvar permission = null\nsocket.on('refresh', function (data) {\n  // console.log(data);\n  editorInstance.config.docmaxlength = data.docmaxlength\n  editor.setOption('maxLength', editorInstance.config.docmaxlength)\n  updateInfo(data)\n  updatePermission(data.permission)\n  if (!window.loaded) {\n    // auto change mode if no content detected\n    var nocontent = editor.getValue().length <= 0\n    if (nocontent) {\n      if (visibleXS) { appState.currentMode = modeType.edit } else { appState.currentMode = modeType.both }\n    }\n    // parse mode from url\n    if (window.location.search.length > 0) {\n      var urlMode = modeType[window.location.search.substr(1)]\n      if (urlMode) appState.currentMode = urlMode\n    }\n    changeMode(appState.currentMode)\n    if (nocontent && !visibleXS) {\n      editor.focus()\n      editor.refresh()\n    }\n    updateViewInner() // bring up view rendering earlier\n    updateHistory() // update history whether have content or not\n    window.loaded = true\n    emitUserStatus() // send first user status\n    updateOnlineStatus() // update first online status\n    setTimeout(function () {\n      // work around editor not refresh or doc not fully loaded\n      windowResizeInner()\n      // work around might not scroll to hash\n      scrollToHash()\n    }, 1)\n  }\n  if (editor.getOption('readOnly')) { editor.setOption('readOnly', false) }\n})\n\nvar EditorClient = ot.EditorClient\nvar SocketIOAdapter = ot.SocketIOAdapter\nvar CodeMirrorAdapter = ot.CodeMirrorAdapter\nvar cmClient = null\nvar synchronized_ = null\n\nfunction havePendingOperation () {\n  return !!((cmClient && cmClient.state && Object.hasOwnProperty.call(cmClient.state, 'outstanding')))\n}\n\nsocket.on('doc', function (obj) {\n  var body = obj.str\n  var bodyMismatch = editor.getValue() !== body\n  var setDoc = !cmClient || (cmClient && (cmClient.revision === -1 || (cmClient.revision !== obj.revision && !havePendingOperation()))) || obj.force\n\n  saveInfo()\n  if (setDoc && bodyMismatch) {\n    if (cmClient) cmClient.editorAdapter.ignoreNextChange = true\n    if (body) editor.setValue(body)\n    else editor.setValue('')\n  }\n\n  if (!window.loaded) {\n    editor.clearHistory()\n    ui.spinner.hide()\n    ui.content.fadeIn()\n  } else {\n    // if current doc is equal to the doc before disconnect\n    if (setDoc && bodyMismatch) editor.clearHistory()\n    else if (lastInfo.history) editor.setHistory(lastInfo.history)\n    lastInfo.history = null\n  }\n\n  if (!cmClient) {\n    cmClient = window.cmClient = new EditorClient(\n      obj.revision, obj.clients,\n      new SocketIOAdapter(socket), new CodeMirrorAdapter(editor)\n    )\n    synchronized_ = cmClient.state\n  } else if (setDoc) {\n    if (bodyMismatch) {\n      cmClient.undoManager.undoStack.length = 0\n      cmClient.undoManager.redoStack.length = 0\n    }\n    cmClient.revision = obj.revision\n    cmClient.setState(synchronized_)\n    cmClient.initializeClientList()\n    cmClient.initializeClients(obj.clients)\n  } else if (havePendingOperation()) {\n    cmClient.serverReconnect()\n  }\n\n  if (setDoc && bodyMismatch) {\n    isDirty = true\n    updateView()\n  }\n\n  restoreInfo()\n})\n\nsocket.on('ack', function () {\n  isDirty = true\n  updateView()\n})\n\nsocket.on('operation', function () {\n  isDirty = true\n  updateView()\n})\n\nsocket.on('online users', function (data) {\n  if (debug) { console.debug(data) }\n  onlineUsers = data.users\n  updateOnlineStatus()\n  $('.CodeMirror-other-cursors').children().each(function (key, value) {\n    var found = false\n    for (var i = 0; i < data.users.length; i++) {\n      var user = data.users[i]\n      if ($(this).attr('id') === user.id) { found = true }\n    }\n    if (!found) {\n      $(this).stop(true).fadeOut('normal', function () {\n        $(this).remove()\n      })\n    }\n  })\n  for (var i = 0; i < data.users.length; i++) {\n    var user = data.users[i]\n    if (user.id !== socket.id) { buildCursor(user) } else { personalInfo = user }\n  }\n})\nsocket.on('user status', function (data) {\n  if (debug) { console.debug(data) }\n  for (var i = 0; i < onlineUsers.length; i++) {\n    if (onlineUsers[i].id === data.id) {\n      onlineUsers[i] = data\n    }\n  }\n  updateOnlineStatus()\n  if (data.id !== socket.id) { buildCursor(data) }\n})\nsocket.on('cursor focus', function (data) {\n  if (debug) { console.debug(data) }\n  for (var i = 0; i < onlineUsers.length; i++) {\n    if (onlineUsers[i].id === data.id) {\n      onlineUsers[i].cursor = data.cursor\n    }\n  }\n  if (data.id !== socket.id) { buildCursor(data) }\n  // force show\n  var cursor = $('div[data-clientid=\"' + data.id + '\"]')\n  if (cursor.length > 0) {\n    cursor.stop(true).fadeIn()\n  }\n})\nsocket.on('cursor activity', function (data) {\n  if (debug) { console.debug(data) }\n  for (var i = 0; i < onlineUsers.length; i++) {\n    if (onlineUsers[i].id === data.id) {\n      onlineUsers[i].cursor = data.cursor\n    }\n  }\n  if (data.id !== socket.id) { buildCursor(data) }\n})\nsocket.on('cursor blur', function (data) {\n  if (debug) { console.debug(data) }\n  for (var i = 0; i < onlineUsers.length; i++) {\n    if (onlineUsers[i].id === data.id) {\n      onlineUsers[i].cursor = null\n    }\n  }\n  if (data.id !== socket.id) { buildCursor(data) }\n  // force hide\n  var cursor = $('div[data-clientid=\"' + data.id + '\"]')\n  if (cursor.length > 0) {\n    cursor.stop(true).fadeOut()\n  }\n})\n\nvar options = {\n  valueNames: ['id', 'name'],\n  item: '<li class=\"ui-user-item\">' +\n        '<span class=\"id\" style=\"display:none;\"></span>' +\n        '<a href=\"#\">' +\n            '<span class=\"pull-left\"><i class=\"ui-user-icon\"></i></span><span class=\"ui-user-name name\"></span><span class=\"pull-right\"><i class=\"fa fa-circle ui-user-status\"></i></span>' +\n        '</a>' +\n        '</li>'\n}\nvar onlineUserList = new List('online-user-list', options)\nvar shortOnlineUserList = new List('short-online-user-list', options)\n\nfunction updateOnlineStatus () {\n  if (!window.loaded || !socket.connected) return\n  var _onlineUsers = deduplicateOnlineUsers(onlineUsers)\n  showStatus(statusType.online, _onlineUsers.length)\n  var items = onlineUserList.items\n  // update or remove current list items\n  for (let i = 0; i < items.length; i++) {\n    let found = false\n    let foundindex = null\n    for (let j = 0; j < _onlineUsers.length; j++) {\n      if (items[i].values().id === _onlineUsers[j].id) {\n        foundindex = j\n        found = true\n        break\n      }\n    }\n    const id = items[i].values().id\n    if (found) {\n      onlineUserList.get('id', id)[0].values(_onlineUsers[foundindex])\n      shortOnlineUserList.get('id', id)[0].values(_onlineUsers[foundindex])\n    } else {\n      onlineUserList.remove('id', id)\n      shortOnlineUserList.remove('id', id)\n    }\n  }\n  // add not in list items\n  for (let i = 0; i < _onlineUsers.length; i++) {\n    let found = false\n    for (let j = 0; j < items.length; j++) {\n      if (items[j].values().id === _onlineUsers[i].id) {\n        found = true\n        break\n      }\n    }\n    if (!found) {\n      onlineUserList.add(_onlineUsers[i])\n      shortOnlineUserList.add(_onlineUsers[i])\n    }\n  }\n  // sorting\n  sortOnlineUserList(onlineUserList)\n  sortOnlineUserList(shortOnlineUserList)\n  // render list items\n  renderUserStatusList(onlineUserList)\n  renderUserStatusList(shortOnlineUserList)\n}\n\nfunction sortOnlineUserList (list) {\n  // sort order by isSelf, login state, idle state, alphabet name, color brightness\n  list.sort('', {\n    sortFunction: function (a, b) {\n      var usera = a.values()\n      var userb = b.values()\n      var useraIsSelf = (usera.id === personalInfo.id || (usera.login && usera.userid === personalInfo.userid))\n      var userbIsSelf = (userb.id === personalInfo.id || (userb.login && userb.userid === personalInfo.userid))\n      if (useraIsSelf && !userbIsSelf) {\n        return -1\n      } else if (!useraIsSelf && userbIsSelf) {\n        return 1\n      } else {\n        if (usera.login && !userb.login) { return -1 } else if (!usera.login && userb.login) { return 1 } else {\n          if (!usera.idle && userb.idle) { return -1 } else if (usera.idle && !userb.idle) { return 1 } else {\n            if (usera.name && userb.name && usera.name.toLowerCase() < userb.name.toLowerCase()) {\n              return -1\n            } else if (usera.name && userb.name && usera.name.toLowerCase() > userb.name.toLowerCase()) {\n              return 1\n            } else {\n              if (usera.color && userb.color && usera.color.toLowerCase() < userb.color.toLowerCase()) { return -1 } else if (usera.color && userb.color && usera.color.toLowerCase() > userb.color.toLowerCase()) { return 1 } else { return 0 }\n            }\n          }\n        }\n      }\n    }\n  })\n}\n\nfunction renderUserStatusList (list) {\n  var items = list.items\n  for (var j = 0; j < items.length; j++) {\n    var item = items[j]\n    var userstatus = $(item.elm).find('.ui-user-status')\n    var usericon = $(item.elm).find('.ui-user-icon')\n    if (item.values().login && item.values().photo) {\n      usericon.css('background-image', 'url(' + item.values().photo + ')')\n      // add 1px more to right, make it feel aligned\n      usericon.css('margin-right', '6px')\n      $(item.elm).css('border-left', '4px solid ' + item.values().color)\n      usericon.css('margin-left', '-4px')\n    } else {\n      usericon.css('background-color', item.values().color)\n    }\n    userstatus.removeClass('ui-user-status-offline ui-user-status-online ui-user-status-idle')\n    if (item.values().idle) { userstatus.addClass('ui-user-status-idle') } else { userstatus.addClass('ui-user-status-online') }\n  }\n}\n\nfunction deduplicateOnlineUsers (list) {\n  var _onlineUsers = []\n  for (var i = 0; i < list.length; i++) {\n    var user = $.extend({}, list[i])\n    if (!user.userid) { _onlineUsers.push(user) } else {\n      var found = false\n      for (var j = 0; j < _onlineUsers.length; j++) {\n        if (_onlineUsers[j].userid === user.userid) {\n          // keep self color when login\n          if (user.id === personalInfo.id) {\n            _onlineUsers[j].color = user.color\n          }\n          // keep idle state if any of self client not idle\n          if (!user.idle) {\n            _onlineUsers[j].idle = user.idle\n            _onlineUsers[j].color = user.color\n          }\n          found = true\n          break\n        }\n      }\n      if (!found) { _onlineUsers.push(user) }\n    }\n  }\n  return _onlineUsers\n}\n\nvar userStatusCache = null\n\nfunction emitUserStatus (force) {\n  if (!window.loaded) return\n  var type = null\n  if (visibleXS) { type = 'xs' } else if (visibleSM) { type = 'sm' } else if (visibleMD) { type = 'md' } else if (visibleLG) { type = 'lg' }\n\n  personalInfo.idle = idle.isAway\n  personalInfo.type = type\n\n  for (var i = 0; i < onlineUsers.length; i++) {\n    if (onlineUsers[i].id === personalInfo.id) {\n      onlineUsers[i] = personalInfo\n    }\n  }\n\n  var userStatus = {\n    idle: idle.isAway,\n    type: type\n  }\n\n  if (force || JSON.stringify(userStatus) !== JSON.stringify(userStatusCache)) {\n    socket.emit('user status', userStatus)\n    userStatusCache = userStatus\n  }\n}\n\nfunction checkCursorTag (coord, ele) {\n  if (!ele) return // return if element not exists\n  // set margin\n  var tagRightMargin = 0\n  var tagBottomMargin = 2\n  // use sizer to get the real doc size (won't count status bar and gutters)\n  var docWidth = ui.area.codemirrorSizer.width()\n  // get editor size (status bar not count in)\n  var editorHeight = ui.area.codemirror.height()\n  // get element size\n  var width = ele.outerWidth()\n  var height = ele.outerHeight()\n  var padding = (ele.outerWidth() - ele.width()) / 2\n  // get coord position\n  var left = coord.left\n  var top = coord.top\n  // get doc top offset (to workaround with viewport)\n  var docTopOffset = ui.area.codemirrorSizerInner.position().top\n  // set offset\n  var offsetLeft = -3\n  var offsetTop = defaultTextHeight\n  // only do when have width and height\n  if (width > 0 && height > 0) {\n    // flip x when element right bound larger than doc width\n    if (left + width + offsetLeft + tagRightMargin > docWidth) {\n      offsetLeft = -(width + tagRightMargin) + padding + offsetLeft\n    }\n    // flip y when element bottom bound larger than doc height\n    // and element top position is larger than element height\n    if (top + docTopOffset + height + offsetTop + tagBottomMargin > Math.max(editor.doc.height, editorHeight) && top + docTopOffset > height + tagBottomMargin) {\n      offsetTop = -(height)\n    }\n  }\n  // set position\n  ele[0].style.left = offsetLeft + 'px'\n  ele[0].style.top = offsetTop + 'px'\n}\n\nfunction buildCursor (user) {\n  if (appState.currentMode === modeType.view) return\n  if (!user.cursor) return\n  var coord = editor.charCoords(user.cursor, 'windows')\n  coord.left = coord.left < 4 ? 4 : coord.left\n  coord.top = coord.top < 0 ? 0 : coord.top\n  var iconClass = 'fa-user'\n  switch (user.type) {\n    case 'xs':\n      iconClass = 'fa-mobile'\n      break\n    case 'sm':\n      iconClass = 'fa-tablet'\n      break\n    case 'md':\n      iconClass = 'fa-desktop'\n      break\n    case 'lg':\n      iconClass = 'fa-desktop'\n      break\n  }\n  if ($('div[data-clientid=\"' + user.id + '\"]').length <= 0) {\n    const cursor = $('<div data-clientid=\"' + user.id + '\" class=\"CodeMirror-other-cursor\" style=\"display:none;\"></div>')\n    cursor.attr('data-line', user.cursor.line)\n    cursor.attr('data-ch', user.cursor.ch)\n    cursor.attr('data-offset-left', 0)\n    cursor.attr('data-offset-top', 0)\n\n    const cursorbar = $('<div class=\"cursorbar\">&nbsp;</div>')\n    cursorbar[0].style.height = defaultTextHeight + 'px'\n    cursorbar[0].style.borderLeft = '2px solid ' + user.color\n\n    var icon = '<i class=\"fa ' + iconClass + '\"></i>'\n\n    const cursortag = $('<div class=\"cursortag\">' + icon + '&nbsp;<span class=\"name\">' + user.name + '</span></div>')\n    // cursortag[0].style.background = color;\n    cursortag[0].style.color = user.color\n\n    cursor.attr('data-mode', 'hover')\n    cursortag.delay(2000).fadeOut('fast')\n    cursor.hover(\n      function () {\n        if (cursor.attr('data-mode') === 'hover') { cursortag.stop(true).fadeIn('fast') }\n      },\n      function () {\n        if (cursor.attr('data-mode') === 'hover') { cursortag.stop(true).fadeOut('fast') }\n      })\n\n    var hideCursorTagDelay = 2000\n    var hideCursorTagTimer = null\n\n    var switchMode = function (ele) {\n      if (ele.attr('data-mode') === 'state') { ele.attr('data-mode', 'hover') } else if (ele.attr('data-mode') === 'hover') { ele.attr('data-mode', 'state') }\n    }\n\n    var switchTag = function (ele) {\n      if (ele.css('display') === 'none') { ele.stop(true).fadeIn('fast') } else { ele.stop(true).fadeOut('fast') }\n    }\n\n    var hideCursorTag = function () {\n      if (cursor.attr('data-mode') === 'hover') { cursortag.fadeOut('fast') }\n    }\n    cursor.on('touchstart', function (e) {\n      var display = cursortag.css('display')\n      cursortag.stop(true).fadeIn('fast')\n      clearTimeout(hideCursorTagTimer)\n      hideCursorTagTimer = setTimeout(hideCursorTag, hideCursorTagDelay)\n      if (display === 'none') {\n        e.preventDefault()\n        e.stopPropagation()\n      }\n    })\n    cursortag.on('mousedown touchstart', function (e) {\n      if (cursor.attr('data-mode') === 'state') { switchTag(cursortag) }\n      switchMode(cursor)\n      e.preventDefault()\n      e.stopPropagation()\n    })\n\n    cursor.append(cursorbar)\n    cursor.append(cursortag)\n\n    cursor[0].style.left = coord.left + 'px'\n    cursor[0].style.top = coord.top + 'px'\n    $('.CodeMirror-other-cursors').append(cursor)\n\n    if (!user.idle) { cursor.stop(true).fadeIn() }\n\n    checkCursorTag(coord, cursortag)\n  } else {\n    const cursor = $('div[data-clientid=\"' + user.id + '\"]')\n    cursor.attr('data-line', user.cursor.line)\n    cursor.attr('data-ch', user.cursor.ch)\n\n    const cursorbar = cursor.find('.cursorbar')\n    cursorbar[0].style.height = defaultTextHeight + 'px'\n    cursorbar[0].style.borderLeft = '2px solid ' + user.color\n\n    const cursortag = cursor.find('.cursortag')\n    cursortag.find('i').removeClass().addClass('fa').addClass(iconClass)\n    cursortag.find('.name').text(user.name)\n\n    if (cursor.css('display') === 'none') {\n      cursor[0].style.left = coord.left + 'px'\n      cursor[0].style.top = coord.top + 'px'\n    } else {\n      cursor.animate({\n        left: coord.left,\n        top: coord.top\n      }, {\n        duration: cursorAnimatePeriod,\n        queue: false\n      })\n    }\n\n    if (user.idle && cursor.css('display') !== 'none') { cursor.stop(true).fadeOut() } else if (!user.idle && cursor.css('display') === 'none') { cursor.stop(true).fadeIn() }\n\n    checkCursorTag(coord, cursortag)\n  }\n}\n\n// editor actions\nfunction removeNullByte (cm, change) {\n  var str = change.text.join('\\n')\n  // eslint-disable-next-line no-control-regex\n  if (/\\u0000/g.test(str) && change.update) {\n    // eslint-disable-next-line no-control-regex\n    change.update(change.from, change.to, str.replace(/\\u0000/g, '').split('\\n'))\n  }\n}\nfunction enforceMaxLength (cm, change) {\n  var maxLength = cm.getOption('maxLength')\n  if (maxLength && change.update) {\n    var str = change.text.join('\\n')\n    var delta = str.length - (cm.indexFromPos(change.to) - cm.indexFromPos(change.from))\n    if (delta <= 0) {\n      return false\n    }\n    delta = cm.getValue().length + delta - maxLength\n    if (delta > 0) {\n      str = str.substr(0, str.length - delta)\n      change.update(change.from, change.to, str.split('\\n'))\n      return true\n    }\n  }\n  return false\n}\nlet lastDocHeight\nvar ignoreEmitEvents = ['setValue', 'ignoreHistory']\neditorInstance.on('beforeChange', function (cm, change) {\n  if (debug) { console.debug(change) }\n  lastDocHeight = editor.doc.height\n  removeNullByte(cm, change)\n  if (enforceMaxLength(cm, change)) {\n    $('.limit-modal').modal('show')\n  }\n  var isIgnoreEmitEvent = (ignoreEmitEvents.indexOf(change.origin) !== -1)\n  if (!isIgnoreEmitEvent) {\n    if (!havePermission()) {\n      change.canceled = true\n      switch (permission) {\n        case 'editable':\n          $('.signin-modal').modal('show')\n          break\n        case 'locked':\n        case 'private':\n          $('.locked-modal').modal('show')\n          break\n      }\n    }\n  } else {\n    if (change.origin === 'ignoreHistory') {\n      setHaveUnreadChanges(true)\n      updateTitleReminder()\n    }\n  }\n  if (cmClient && !socket.connected) { cmClient.editorAdapter.ignoreNextChange = true }\n})\neditorInstance.on('cut', function () {\n  // na\n})\neditorInstance.on('paste', function () {\n  // na\n})\neditorInstance.on('changes', function (editor, changes) {\n  const docHeightChanged = editor.doc.height !== lastDocHeight\n  updateHistory()\n  var docLength = editor.getValue().length\n  // workaround for big documents\n  var newViewportMargin = 20\n  if (docLength > 20000) {\n    newViewportMargin = 1\n  } else if (docLength > 10000) {\n    newViewportMargin = 10\n  } else if (docLength > 5000) {\n    newViewportMargin = 15\n  }\n  if (newViewportMargin !== viewportMargin) {\n    viewportMargin = newViewportMargin\n    windowResize()\n  }\n  if (docHeightChanged) {\n    checkEditorScrollbar()\n    checkEditorScrollOverLines()\n    // always sync edit scrolling to view if user is editing\n    if (ui.area.codemirrorScroll[0].scrollHeight > ui.area.view[0].scrollHeight && editorHasFocus()) {\n      postUpdateEvent = function () {\n        syncScrollToView()\n        postUpdateEvent = null\n      }\n    }\n  }\n  lastDocHeight = editor.doc.height\n})\neditorInstance.on('focus', function (editor) {\n  for (var i = 0; i < onlineUsers.length; i++) {\n    if (onlineUsers[i].id === personalInfo.id) {\n      onlineUsers[i].cursor = editor.getCursor()\n    }\n  }\n  personalInfo.cursor = editor.getCursor()\n  socket.emit('cursor focus', editor.getCursor())\n})\n\nconst cursorActivity = _.debounce(cursorActivityInner, cursorActivityDebounce)\n\nfunction cursorActivityInner (editor) {\n  if (editorHasFocus() && !Visibility.hidden()) {\n    for (var i = 0; i < onlineUsers.length; i++) {\n      if (onlineUsers[i].id === personalInfo.id) {\n        onlineUsers[i].cursor = editor.getCursor()\n      }\n    }\n    personalInfo.cursor = editor.getCursor()\n    socket.emit('cursor activity', editor.getCursor())\n  }\n}\n\neditorInstance.on('cursorActivity', editorInstance.updateStatusBar)\neditorInstance.on('cursorActivity', cursorActivity)\n\neditorInstance.on('beforeSelectionChange', editorInstance.updateStatusBar)\neditorInstance.on('beforeSelectionChange', function (doc, selections) {\n  // check selection and whether the statusbar has added\n  if (selections && editorInstance.statusSelection) {\n    const selection = selections.ranges[0]\n\n    const anchor = selection.anchor\n    const head = selection.head\n    const start = head.line <= anchor.line ? head : anchor\n    const end = head.line >= anchor.line ? head : anchor\n    const selectionCharCount = Math.abs(head.ch - anchor.ch)\n\n    let selectionText = ' — Selected '\n\n    // borrow from brackets EditorStatusBar.js\n    if (start.line !== end.line) {\n      var lines = end.line - start.line + 1\n      if (end.ch === 0) {\n        lines--\n      }\n      selectionText += lines + ' lines'\n    } else if (selectionCharCount > 0) {\n      selectionText += selectionCharCount + ' columns'\n    }\n\n    if (start.line !== end.line || selectionCharCount > 0) {\n      editorInstance.statusSelection.text(selectionText)\n    } else {\n      editorInstance.statusSelection.text('')\n    }\n  }\n})\n\neditorInstance.on('blur', function (cm) {\n  for (var i = 0; i < onlineUsers.length; i++) {\n    if (onlineUsers[i].id === personalInfo.id) {\n      onlineUsers[i].cursor = null\n    }\n  }\n  personalInfo.cursor = null\n  socket.emit('cursor blur')\n})\n\nfunction saveInfo () {\n  var scrollbarStyle = editor.getOption('scrollbarStyle')\n  var left = $(window).scrollLeft()\n  var top = $(window).scrollTop()\n  switch (appState.currentMode) {\n    case modeType.edit:\n      if (scrollbarStyle === 'native') {\n        lastInfo.edit.scroll.left = left\n        lastInfo.edit.scroll.top = top\n      } else {\n        lastInfo.edit.scroll = editor.getScrollInfo()\n      }\n      break\n    case modeType.view:\n      lastInfo.view.scroll.left = left\n      lastInfo.view.scroll.top = top\n      break\n    case modeType.both:\n      lastInfo.edit.scroll = editor.getScrollInfo()\n      lastInfo.view.scroll.left = ui.area.view.scrollLeft()\n      lastInfo.view.scroll.top = ui.area.view.scrollTop()\n      break\n  }\n  lastInfo.edit.cursor = editor.getCursor()\n  lastInfo.edit.selections = editor.listSelections()\n  lastInfo.needRestore = true\n}\n\nfunction restoreInfo () {\n  var scrollbarStyle = editor.getOption('scrollbarStyle')\n  if (lastInfo.needRestore) {\n    var line = lastInfo.edit.cursor.line\n    var ch = lastInfo.edit.cursor.ch\n    editor.setCursor(line, ch)\n    editor.setSelections(lastInfo.edit.selections)\n    switch (appState.currentMode) {\n      case modeType.edit:\n        if (scrollbarStyle === 'native') {\n          $(window).scrollLeft(lastInfo.edit.scroll.left)\n          $(window).scrollTop(lastInfo.edit.scroll.top)\n        } else {\n          const left = lastInfo.edit.scroll.left\n          const top = lastInfo.edit.scroll.top\n          editor.scrollIntoView()\n          editor.scrollTo(left, top)\n        }\n        break\n      case modeType.view:\n        $(window).scrollLeft(lastInfo.view.scroll.left)\n        $(window).scrollTop(lastInfo.view.scroll.top)\n        break\n      case modeType.both:\n        const left = lastInfo.edit.scroll.left\n        const top = lastInfo.edit.scroll.top\n        editor.scrollIntoView()\n        editor.scrollTo(left, top)\n        ui.area.view.scrollLeft(lastInfo.view.scroll.left)\n        ui.area.view.scrollTop(lastInfo.view.scroll.top)\n        break\n    }\n\n    lastInfo.needRestore = false\n  }\n}\n\n// view actions\nfunction refreshView () {\n  ui.area.markdown.html('')\n  isDirty = true\n  updateViewInner()\n}\n\nvar updateView = _.debounce(function () {\n  editor.operation(updateViewInner)\n}, updateViewDebounce)\n\nvar lastResult = null\nvar postUpdateEvent = null\n\nfunction updateViewInner () {\n  if (appState.currentMode === modeType.edit || !isDirty) return\n  var value = editor.getValue()\n  var lastMeta = md.meta\n  md.meta = {}\n  delete md.metaError\n  var rendered = md.render(value)\n  if (md.meta.type && md.meta.type === 'slide') {\n    var RevealMarkdown = require('./reveal-markdown').default\n    var slideOptions = {\n      separator: '^(\\r\\n?|\\n)---(\\r\\n?|\\n)$',\n      verticalSeparator: '^(\\r\\n?|\\n)----(\\r\\n?|\\n)$'\n    }\n    var slides = RevealMarkdown.slidify(editor.getValue(), slideOptions)\n    ui.area.markdown.html(slides)\n    RevealMarkdown.initialize()\n    // prevent XSS\n    ui.area.markdown.html(preventXSS(ui.area.markdown.html()))\n    ui.area.markdown.addClass('slides')\n    appState.syncscroll = false\n    checkSyncToggle()\n  } else {\n    if (lastMeta.type && lastMeta.type === 'slide') {\n      refreshView()\n      ui.area.markdown.removeClass('slides')\n      appState.syncscroll = true\n      checkSyncToggle()\n    }\n    // only render again when meta changed\n    if (JSON.stringify(md.meta) !== JSON.stringify(lastMeta)) {\n      parseMeta(md, ui.area.codemirror, ui.area.markdown, $('#ui-toc'), $('#ui-toc-affix'))\n      rendered = md.render(value)\n    }\n    // prevent XSS\n    rendered = preventXSS(rendered)\n    var result = postProcess(rendered).children().toArray()\n    partialUpdate(result, lastResult, ui.area.markdown.children().toArray())\n    if (result && lastResult && result.length !== lastResult.length) { updateDataAttrs(result, ui.area.markdown.children().toArray()) }\n    lastResult = $(result).clone()\n  }\n  removeDOMEvents(ui.area.markdown)\n  finishView(ui.area.markdown)\n  autoLinkify(ui.area.markdown)\n  deduplicatedHeaderId(ui.area.markdown)\n  renderTOC(ui.area.markdown)\n  generateToc('ui-toc')\n  generateToc('ui-toc-affix')\n  autoLinkify(ui.area.markdown)\n  generateScrollspy()\n  updateScrollspy()\n  smoothHashScroll()\n  isDirty = false\n  clearMap()\n  // buildMap();\n  updateTitleReminder()\n  if (postUpdateEvent && typeof postUpdateEvent === 'function') { postUpdateEvent() }\n}\n\nvar updateHistoryDebounce = 600\n\nvar updateHistory = _.debounce(updateHistoryInner, updateHistoryDebounce)\n\nfunction updateHistoryInner () {\n  writeHistory(renderFilename(ui.area.markdown), renderTags(ui.area.markdown))\n}\n\nfunction updateDataAttrs (src, des) {\n  // sync data attr startline and endline\n  for (var i = 0; i < src.length; i++) {\n    copyAttribute(src[i], des[i], 'data-startline')\n    copyAttribute(src[i], des[i], 'data-endline')\n  }\n}\n\nfunction partialUpdate (src, tar, des) {\n  if (!src || src.length === 0 || !tar || tar.length === 0 || !des || des.length === 0) {\n    ui.area.markdown.html(src)\n    return\n  }\n  if (src.length === tar.length) { // same length\n    for (let i = 0; i < src.length; i++) {\n      copyAttribute(src[i], des[i], 'data-startline')\n      copyAttribute(src[i], des[i], 'data-endline')\n      var rawSrc = cloneAndRemoveDataAttr(src[i])\n      var rawTar = cloneAndRemoveDataAttr(tar[i])\n      if (rawSrc.outerHTML !== rawTar.outerHTML) {\n        // console.log(rawSrc);\n        // console.log(rawTar);\n        $(des[i]).replaceWith(src[i])\n      }\n    }\n  } else { // diff length\n    var start = 0\n    // find diff start position\n    for (let i = 0; i < tar.length; i++) {\n      // copyAttribute(src[i], des[i], 'data-startline');\n      // copyAttribute(src[i], des[i], 'data-endline');\n      const rawSrc = cloneAndRemoveDataAttr(src[i])\n      const rawTar = cloneAndRemoveDataAttr(tar[i])\n      if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {\n        start = i\n        break\n      }\n    }\n    // find diff end position\n    var srcEnd = 0\n    var tarEnd = 0\n    for (let i = 0; i < src.length; i++) {\n      // copyAttribute(src[i], des[i], 'data-startline');\n      // copyAttribute(src[i], des[i], 'data-endline');\n      const rawSrc = cloneAndRemoveDataAttr(src[i])\n      const rawTar = cloneAndRemoveDataAttr(tar[i])\n      if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {\n        start = i\n        break\n      }\n    }\n    // tar end\n    for (let i = 1; i <= tar.length + 1; i++) {\n      const srcLength = src.length\n      const tarLength = tar.length\n      // copyAttribute(src[srcLength - i], des[srcLength - i], 'data-startline');\n      // copyAttribute(src[srcLength - i], des[srcLength - i], 'data-endline');\n      const rawSrc = cloneAndRemoveDataAttr(src[srcLength - i])\n      const rawTar = cloneAndRemoveDataAttr(tar[tarLength - i])\n      if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {\n        tarEnd = tar.length - i\n        break\n      }\n    }\n    // src end\n    for (let i = 1; i <= src.length + 1; i++) {\n      const srcLength = src.length\n      const tarLength = tar.length\n      // copyAttribute(src[srcLength - i], des[srcLength - i], 'data-startline');\n      // copyAttribute(src[srcLength - i], des[srcLength - i], 'data-endline');\n      const rawSrc = cloneAndRemoveDataAttr(src[srcLength - i])\n      const rawTar = cloneAndRemoveDataAttr(tar[tarLength - i])\n      if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {\n        srcEnd = src.length - i\n        break\n      }\n    }\n    // check if tar end overlap tar start\n    var overlap = 0\n    for (var i = start; i >= 0; i--) {\n      var rawTarStart = cloneAndRemoveDataAttr(tar[i - 1])\n      var rawTarEnd = cloneAndRemoveDataAttr(tar[tarEnd + 1 + start - i])\n      if (rawTarStart && rawTarEnd && rawTarStart.outerHTML === rawTarEnd.outerHTML) { overlap++ } else { break }\n    }\n    if (debug) { console.log('overlap:' + overlap) }\n    // show diff content\n    if (debug) {\n      console.log('start:' + start)\n      console.log('tarEnd:' + tarEnd)\n      console.log('srcEnd:' + srcEnd)\n    }\n    tarEnd += overlap\n    srcEnd += overlap\n    var repeatAdd = (start - srcEnd) < (start - tarEnd)\n    var repeatDiff = Math.abs(srcEnd - tarEnd) - 1\n    // push new elements\n    var newElements = []\n    if (srcEnd >= start) {\n      for (let j = start; j <= srcEnd; j++) {\n        if (!src[j]) continue\n        newElements.push(src[j].outerHTML)\n      }\n    } else if (repeatAdd) {\n      for (let j = srcEnd - repeatDiff; j <= srcEnd; j++) {\n        if (!des[j]) continue\n        newElements.push(des[j].outerHTML)\n      }\n    }\n    // push remove elements\n    var removeElements = []\n    if (tarEnd >= start) {\n      for (let j = start; j <= tarEnd; j++) {\n        if (!des[j]) continue\n        removeElements.push(des[j])\n      }\n    } else if (!repeatAdd) {\n      for (let j = start; j <= start + repeatDiff; j++) {\n        if (!des[j]) continue\n        removeElements.push(des[j])\n      }\n    }\n    // add elements\n    if (debug) {\n      console.log('ADD ELEMENTS')\n      console.log(newElements.join('\\n'))\n    }\n    if (des[start]) { $(newElements.join('')).insertBefore(des[start]) } else { $(newElements.join('')).insertAfter(des[start - 1]) }\n    // remove elements\n    if (debug) { console.log('REMOVE ELEMENTS') }\n    for (let j = 0; j < removeElements.length; j++) {\n      if (debug) {\n        console.log(removeElements[j].outerHTML)\n      }\n      if (removeElements[j]) { $(removeElements[j]).remove() }\n    }\n  }\n}\n\nfunction cloneAndRemoveDataAttr (el) {\n  if (!el) return\n  var rawEl = $(el).clone()\n  rawEl.removeAttr('data-startline data-endline')\n  rawEl.find('[data-startline]').removeAttr('data-startline data-endline')\n  return rawEl[0]\n}\n\nfunction copyAttribute (src, des, attr) {\n  if (src && src.getAttribute(attr) && des) { des.setAttribute(attr, src.getAttribute(attr)) }\n}\n\nif ($('.cursor-menu').length <= 0) {\n  $(\"<div class='cursor-menu'>\").insertAfter('.CodeMirror-cursors')\n}\n\nfunction reverseSortCursorMenu (dropdown) {\n  var items = dropdown.find('.textcomplete-item')\n  items.sort(function (a, b) {\n    return $(b).attr('data-index') - $(a).attr('data-index')\n  })\n  return items\n}\n\nvar checkCursorMenu = _.throttle(checkCursorMenuInner, cursorMenuThrottle)\n\nfunction checkCursorMenuInner () {\n  // get element\n  var dropdown = $('.cursor-menu > .dropdown-menu')\n  // return if not exists\n  if (dropdown.length <= 0) return\n  // set margin\n  var menuRightMargin = 10\n  var menuBottomMargin = 4\n  // use sizer to get the real doc size (won't count status bar and gutters)\n  var docWidth = ui.area.codemirrorSizer.width()\n  // get editor size (status bar not count in)\n  var editorHeight = ui.area.codemirror.height()\n  // get element size\n  var width = dropdown.outerWidth()\n  var height = dropdown.outerHeight()\n  // get cursor\n  var cursor = editor.getCursor()\n  // set element cursor data\n  if (!dropdown.hasClass('CodeMirror-other-cursor')) { dropdown.addClass('CodeMirror-other-cursor') }\n  dropdown.attr('data-line', cursor.line)\n  dropdown.attr('data-ch', cursor.ch)\n  // get coord position\n  var coord = editor.charCoords({\n    line: cursor.line,\n    ch: cursor.ch\n  }, 'windows')\n  var left = coord.left\n  var top = coord.top\n  // get doc top offset (to workaround with viewport)\n  var docTopOffset = ui.area.codemirrorSizerInner.position().top\n  // set offset\n  var offsetLeft = 0\n  var offsetTop = defaultTextHeight\n  // set up side down\n  window.upSideDown = false\n  var lastUpSideDown = window.upSideDown = false\n  // only do when have width and height\n  if (width > 0 && height > 0) {\n    // make element right bound not larger than doc width\n    if (left + width + offsetLeft + menuRightMargin > docWidth) { offsetLeft = -(left + width - docWidth + menuRightMargin) }\n    // flip y when element bottom bound larger than doc height\n    // and element top position is larger than element height\n    if (top + docTopOffset + height + offsetTop + menuBottomMargin > Math.max(editor.doc.height, editorHeight) && top + docTopOffset > height + menuBottomMargin) {\n      offsetTop = -(height + menuBottomMargin)\n      // reverse sort menu because upSideDown\n      dropdown.html(reverseSortCursorMenu(dropdown))\n      window.upSideDown = true\n    }\n    var textCompleteDropdown = $(editor.getInputField()).data('textComplete').dropdown\n    lastUpSideDown = textCompleteDropdown.upSideDown\n    textCompleteDropdown.upSideDown = window.upSideDown\n  }\n  // make menu scroll top only if upSideDown changed\n  if (window.upSideDown !== lastUpSideDown) { dropdown.scrollTop(dropdown[0].scrollHeight) }\n  // set element offset data\n  dropdown.attr('data-offset-left', offsetLeft)\n  dropdown.attr('data-offset-top', offsetTop)\n  // set position\n  dropdown[0].style.left = left + offsetLeft + 'px'\n  dropdown[0].style.top = top + offsetTop + 'px'\n}\n\nfunction checkInIndentCode () {\n  // if line starts with tab or four spaces is a code block\n  var line = editor.getLine(editor.getCursor().line)\n  var isIndentCode = ((line.substr(0, 4) === '    ') || (line.substr(0, 1) === '\\t'))\n  return isIndentCode\n}\n\nvar isInCode = false\n\nfunction checkInCode () {\n  isInCode = checkAbove(matchInCode) || checkInIndentCode()\n}\n\nfunction checkAbove (method) {\n  var cursor = editor.getCursor()\n  var text = []\n  for (var i = 0; i < cursor.line; i++) { // contain current line\n    text.push(editor.getLine(i))\n  }\n  text = text.join('\\n') + '\\n' + editor.getLine(cursor.line).slice(0, cursor.ch)\n  // console.log(text);\n  return method(text)\n}\n\nfunction checkBelow (method) {\n  var cursor = editor.getCursor()\n  var count = editor.lineCount()\n  var text = []\n  for (var i = cursor.line + 1; i < count; i++) { // contain current line\n    text.push(editor.getLine(i))\n  }\n  text = editor.getLine(cursor.line).slice(cursor.ch) + '\\n' + text.join('\\n')\n  // console.log(text);\n  return method(text)\n}\n\nfunction matchInCode (text) {\n  var match\n  match = text.match(/`{3,}/g)\n  if (match && match.length % 2) {\n    return true\n  } else {\n    match = text.match(/`/g)\n    if (match && match.length % 2) {\n      return true\n    } else {\n      return false\n    }\n  }\n}\n\nvar isInContainer = false\nvar isInContainerSyntax = false\n\nfunction checkInContainer () {\n  isInContainer = checkAbove(matchInContainer) && !checkInIndentCode()\n}\n\nfunction checkInContainerSyntax () {\n  // if line starts with :::, it's in container syntax\n  var line = editor.getLine(editor.getCursor().line)\n  isInContainerSyntax = (line.substr(0, 3) === ':::')\n}\n\nfunction matchInContainer (text) {\n  var match\n  match = text.match(/^:::/gm)\n  if (match && match.length % 2) {\n    return true\n  } else {\n    return false\n  }\n}\n\nconst textCompleteKeyMap = {\n  Up: function () {\n    return false\n  },\n  Right: function () {\n    editor.doc.cm.execCommand('goCharRight')\n  },\n  Down: function () {\n    return false\n  },\n  Left: function () {\n    editor.doc.cm.execCommand('goCharLeft')\n  },\n  Enter: function () {\n    return false\n  },\n  Backspace: function () {\n    editor.doc.cm.execCommand('delCharBefore')\n  }\n}\n\n$(editor.getInputField())\n  .textcomplete([\n    { // emoji strategy\n      match: /(^|\\n|\\s)\\B:([-+\\w]*)$/,\n      search: function (term, callback) {\n        var line = editor.getLine(editor.getCursor().line)\n        term = line.match(this.match)[2]\n        var list = []\n        $.map(window.emojify.emojiNames, function (emoji) {\n          if (emoji.indexOf(term) === 0) { // match at first character\n            list.push(emoji)\n          }\n        })\n        $.map(window.emojify.emojiNames, function (emoji) {\n          if (emoji.indexOf(term) !== -1) { // match inside the word\n            list.push(emoji)\n          }\n        })\n        callback(list)\n      },\n      template: function (value) {\n        return `<img class=\"emoji\" src=\"${emojifyImageDir}/${value}.png\"></img> ${value}`\n      },\n      replace: function (value) {\n        return '$1:' + value + ': '\n      },\n      index: 1,\n      context: function (text) {\n        checkInCode()\n        checkInContainer()\n        checkInContainerSyntax()\n        return !isInCode && !isInContainerSyntax\n      }\n    },\n    { // Code block language strategy\n      langs: supportCodeModes,\n      charts: supportCharts,\n      match: /(^|\\n)```(\\w+)$/,\n      search: function (term, callback) {\n        var line = editor.getLine(editor.getCursor().line)\n        term = line.match(this.match)[2]\n        var list = []\n        $.map(this.langs, function (lang) {\n          if (lang.indexOf(term) === 0 && lang !== term) { list.push(lang) }\n        })\n        $.map(this.charts, function (chart) {\n          if (chart.indexOf(term) === 0 && chart !== term) { list.push(chart) }\n        })\n        callback(list)\n      },\n      replace: function (lang) {\n        var ending = ''\n        if (!checkBelow(matchInCode)) {\n          ending = '\\n\\n```'\n        }\n        if (this.langs.indexOf(lang) !== -1) { return '$1```' + lang + '=' + ending } else if (this.charts.indexOf(lang) !== -1) { return '$1```' + lang + ending }\n      },\n      done: function () {\n        var cursor = editor.getCursor()\n        var text = []\n        text.push(editor.getLine(cursor.line - 1))\n        text.push(editor.getLine(cursor.line))\n        text = text.join('\\n')\n        // console.log(text);\n        if (text === '\\n```') { editor.doc.cm.execCommand('goLineUp') }\n      },\n      context: function (text) {\n        return isInCode\n      }\n    },\n    { // Container strategy\n      containers: supportContainers,\n      match: /(^|\\n):::(\\s*)(\\w*)$/,\n      search: function (term, callback) {\n        var line = editor.getLine(editor.getCursor().line)\n        term = line.match(this.match)[3].trim()\n        var list = []\n        $.map(this.containers, function (container) {\n          if (container.indexOf(term) === 0 && container !== term) { list.push(container) }\n        })\n        callback(list)\n      },\n      replace: function (lang) {\n        var ending = ''\n        if (!checkBelow(matchInContainer)) {\n          ending = '\\n\\n:::'\n        }\n        if (this.containers.indexOf(lang) !== -1) { return '$1:::$2' + lang + ending }\n      },\n      done: function () {\n        var cursor = editor.getCursor()\n        var text = []\n        text.push(editor.getLine(cursor.line - 1))\n        text.push(editor.getLine(cursor.line))\n        text = text.join('\\n')\n        // console.log(text);\n        if (text === '\\n:::') { editor.doc.cm.execCommand('goLineUp') }\n      },\n      context: function (text) {\n        return !isInCode && isInContainer\n      }\n    },\n    { // header\n      match: /(?:^|\\n)(\\s{0,3})(#{1,6}\\w*)$/,\n      search: function (term, callback) {\n        callback($.map(supportHeaders, function (header) {\n          return header.search.indexOf(term) === 0 ? header.text : null\n        }))\n      },\n      replace: function (value) {\n        return '$1' + value\n      },\n      context: function (text) {\n        return !isInCode\n      }\n    },\n    { // extra tags for list\n      match: /(^[>\\s]*[-+*]\\s(?:\\[[x ]\\]|.*))(\\[\\])(\\w*)$/,\n      search: function (term, callback) {\n        var list = []\n        $.map(supportExtraTags, function (extratag) {\n          if (extratag.search.indexOf(term) === 0) { list.push(extratag.command()) }\n        })\n        $.map(supportReferrals, function (referral) {\n          if (referral.search.indexOf(term) === 0) { list.push(referral.text) }\n        })\n        callback(list)\n      },\n      replace: function (value) {\n        return '$1' + value\n      },\n      context: function (text) {\n        return !isInCode\n      }\n    },\n    { // extra tags for blockquote\n      match: /(?:^|\\n|\\s)(>.*|\\s|)((\\^|)\\[(\\^|)\\](\\[\\]|\\(\\)|:|)\\s*\\w*)$/,\n      search: function (term, callback) {\n        var line = editor.getLine(editor.getCursor().line)\n        var quote = line.match(this.match)[1].trim()\n        var list = []\n        if (quote.indexOf('>') === 0) {\n          $.map(supportExtraTags, function (extratag) {\n            if (extratag.search.indexOf(term) === 0) { list.push(extratag.command()) }\n          })\n        }\n        $.map(supportReferrals, function (referral) {\n          if (referral.search.indexOf(term) === 0) { list.push(referral.text) }\n        })\n        callback(list)\n      },\n      replace: function (value) {\n        return '$1' + value\n      },\n      context: function (text) {\n        return !isInCode\n      }\n    },\n    { // referral\n      match: /(^\\s*|\\n|\\s{2})((\\[\\]|\\[\\]\\[\\]|\\[\\]\\(\\)|!|!\\[\\]|!\\[\\]\\[\\]|!\\[\\]\\(\\))\\s*\\w*)$/,\n      search: function (term, callback) {\n        callback($.map(supportReferrals, function (referral) {\n          return referral.search.indexOf(term) === 0 ? referral.text : null\n        }))\n      },\n      replace: function (value) {\n        return '$1' + value\n      },\n      context: function (text) {\n        return !isInCode\n      }\n    },\n    { // externals\n      match: /(^|\\n|\\s)\\{\\}(\\w*)$/,\n      search: function (term, callback) {\n        callback($.map(supportExternals, function (external) {\n          return external.search.indexOf(term) === 0 ? external.text : null\n        }))\n      },\n      replace: function (value) {\n        return '$1' + value\n      },\n      context: function (text) {\n        return !isInCode\n      }\n    }\n  ], {\n    appendTo: $('.cursor-menu')\n  })\n  .on({\n    'textComplete:beforeSearch': function (e) {\n      // NA\n    },\n    'textComplete:afterSearch': function (e) {\n      checkCursorMenu()\n    },\n    'textComplete:select': function (e, value, strategy) {\n      // NA\n    },\n    'textComplete:show': function (e) {\n      $(this).data('autocompleting', true)\n      editor.addKeyMap(textCompleteKeyMap)\n    },\n    'textComplete:hide': function (e) {\n      $(this).data('autocompleting', false)\n      editor.removeKeyMap(textCompleteKeyMap)\n    }\n  })\n"
  },
  {
    "path": "public/js/lib/appState.js",
    "content": "import modeType from './modeType'\n\nconst state = {\n  syncscroll: true,\n  currentMode: modeType.view,\n  nightMode: false\n}\n\nexport default state\n"
  },
  {
    "path": "public/js/lib/common/constant.ejs",
    "content": "window.domain = '<%- domain %>'\nwindow.urlpath = '<%- urlpath %>'\nwindow.debug = <%- debug %>\nwindow.version = '<%- version %>'\nwindow.plantumlServer = '<%- plantumlServer %>'\n\nwindow.allowedUploadMimeTypes = <%- JSON.stringify(allowedUploadMimeTypes) %>\n\nwindow.defaultUseHardbreak = <%- defaultUseHardbreak %>\n\nwindow.linkifyHeaderStyle = '<%- linkifyHeaderStyle %>'\n\nwindow.DROPBOX_APP_KEY = '<%- DROPBOX_APP_KEY %>'\n\nwindow.USE_CDN = <%- useCDN %>\n\nwindow.defaultTocDepth = <%- defaultTocDepth %>\n"
  },
  {
    "path": "public/js/lib/common/login.js",
    "content": "/* eslint-env browser, jquery */\n/* global Cookies */\n\nimport { serverurl } from '../config'\n\nlet checkAuth = false\nlet profile = null\nlet lastLoginState = getLoginState()\nlet lastUserId = getUserId()\nvar loginStateChangeEvent = null\n\nexport function setloginStateChangeEvent (func) {\n  loginStateChangeEvent = func\n}\n\nexport function resetCheckAuth () {\n  checkAuth = false\n}\n\nexport function setLoginState (bool, id) {\n  Cookies.set('loginstate', bool, {\n    expires: 365\n  })\n  if (id) {\n    Cookies.set('userid', id, {\n      expires: 365\n    })\n  } else {\n    Cookies.remove('userid')\n  }\n  lastLoginState = bool\n  lastUserId = id\n  checkLoginStateChanged()\n}\n\nexport function checkLoginStateChanged () {\n  if (getLoginState() !== lastLoginState || getUserId() !== lastUserId) {\n    if (loginStateChangeEvent) setTimeout(loginStateChangeEvent, 100)\n    return true\n  } else {\n    return false\n  }\n}\n\nexport function getLoginState () {\n  const state = Cookies.get('loginstate')\n  return state === 'true' || state === true\n}\n\nexport function getUserId () {\n  return Cookies.get('userid')\n}\n\nexport function clearLoginState () {\n  Cookies.remove('loginstate')\n}\n\nexport function checkIfAuth (yesCallback, noCallback) {\n  const cookieLoginState = getLoginState()\n  if (checkLoginStateChanged()) checkAuth = false\n  if (!checkAuth || typeof cookieLoginState === 'undefined') {\n    $.get(`${serverurl}/me`)\n      .done(data => {\n        if (data && data.status === 'ok') {\n          profile = data\n          yesCallback(profile)\n          setLoginState(true, data.id)\n        } else {\n          noCallback()\n          setLoginState(false)\n        }\n      })\n      .fail(() => {\n        noCallback()\n      })\n      .always(() => {\n        checkAuth = true\n      })\n  } else if (cookieLoginState) {\n    yesCallback(profile)\n  } else {\n    noCallback()\n  }\n}\n\nexport default {\n  checkAuth,\n  profile,\n  lastLoginState,\n  lastUserId,\n  loginStateChangeEvent\n}\n"
  },
  {
    "path": "public/js/lib/common/metrics.ejs",
    "content": "# HELP online_notes Number of currently used notes\n# TYPE online_notes gauge\nonline_notes <%- onlineNotes %>\n# HELP online_users Number of online users\n# TYPE online_users gauge\nonline_users <%- onlineUsers %>\n# HELP distinct_online_users Number of distinct online users\n# TYPE distinct_online_users gauge\ndistinct_online_users <%- distinctOnlineUsers %>\n# HELP notes_count Total count of notes\n# TYPE notes_count gauge\nnotes_count <%- notesCount %>\n# HELP registered_users Number of registered users\n# TYPE registered_users gauge\nregistered_users <%- registeredUsers %>\n# HELP online_registered_users Number of online registered users\n# TYPE online_registered_users gauge\nonline_registered_users <%- onlineRegisteredUsers %>\n# HELP distinct_online_registered_users Number of distinct online registered users\n# TYPE distinct_online_registered_users gauge\ndistinct_online_registered_users <%- distinctOnlineRegisteredUsers %>\nis_connection_busy <%- isConnectionBusy ? 1 : 0 %>\nconnection_socket_queue_length <%- connectionSocketQueueLength %>\nis_disconnect_busy <%- isDisconnectBusy ? 1: 0 %>\ndisconnect_socket_queue_length <%- disconnectSocketQueueLength %>\n"
  },
  {
    "path": "public/js/lib/config/index.js",
    "content": "export const DROPBOX_APP_KEY = window.DROPBOX_APP_KEY || ''\n\nexport const domain = window.domain || '' // domain name\nexport const urlpath = window.urlpath || '' // sub url path, like: www.example.com/<urlpath>\nexport const debug = window.debug || false\n\nexport const port = window.location.port\nexport const serverurl = `${window.location.protocol}//${domain || window.location.hostname}${port ? ':' + port : ''}${urlpath ? '/' + urlpath : ''}`\nwindow.serverurl = serverurl\nexport const noteid = decodeURIComponent(urlpath ? window.location.pathname.slice(urlpath.length + 1, window.location.pathname.length).split('/')[1] : window.location.pathname.split('/')[1])\nexport const noteurl = `${serverurl}/${noteid}`\n\nexport const version = window.version\n"
  },
  {
    "path": "public/js/lib/editor/config.js",
    "content": "const config = {\n  docmaxlength: null\n}\n\nexport default config\n"
  },
  {
    "path": "public/js/lib/editor/constants.js",
    "content": "import { serverurl } from '../config'\n\nexport const availableThemes = [\n  { name: 'Light', value: 'default' },\n  { name: 'One Dark (Default)', value: 'one-dark' },\n  { name: 'Monokai', value: 'monokai' },\n  { name: 'Solarized Dark', value: 'solarized dark' },\n  { name: 'Solarized Light', value: 'solarized light' },\n  { name: 'Dracula', value: 'dracula' },\n  { name: 'Material', value: 'material' },\n  { name: 'Nord', value: 'nord' },\n  { name: 'Panda', value: 'panda-syntax' },\n  { name: 'Ayu Dark', value: 'ayu-dark' },\n  { name: 'Ayu Mirage', value: 'ayu-mirage' },\n  { name: 'Tomorror Night Bright', value: 'tomorrow-night-bright' },\n  { name: 'Tomorror Night Eighties', value: 'tomorrow-night-eighties' }\n]\n\nexport const emojifyImageDir = window.USE_CDN ? 'https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/images/basic' : `${serverurl}/build/emojify.js/dist/images/basic`\n"
  },
  {
    "path": "public/js/lib/editor/index.js",
    "content": "/* eslint-env browser */\n/* global CodeMirror, $, editor, Cookies */\nimport { options, Alignment, FormatType } from '@susisu/mte-kernel'\nimport debounce from 'lodash/debounce'\n\nimport * as utils from './utils'\nimport config from './config'\nimport statusBarTemplate from './statusbar.html'\nimport toolBarTemplate from './toolbar.html'\nimport { linterOptions } from './markdown-lint'\nimport CodeMirrorSpellChecker, { supportLanguages, supportLanguageCodes } from './spellcheck'\nimport { initTableEditor } from './table-editor'\nimport { availableThemes } from './constants'\n\n// Storage utility class for localStorage operations\nclass Storage {\n  static get (key, defaultValue = null) {\n    try {\n      const value = localStorage.getItem(key)\n      return value !== null ? value : defaultValue\n    } catch (e) {\n      console.error('Error getting from localStorage:', e)\n      return defaultValue\n    }\n  }\n\n  static set (key, value, options = {}) {\n    try {\n      localStorage.setItem(key, value)\n      return true\n    } catch (e) {\n      console.error('Error setting to localStorage:', e)\n      return false\n    }\n  }\n\n  static remove (key) {\n    try {\n      localStorage.removeItem(key)\n      return true\n    } catch (e) {\n      console.error('Error removing from localStorage:', e)\n      return false\n    }\n  }\n}\n\n/* config section */\nconst isMac = CodeMirror.keyMap.default === CodeMirror.keyMap.macDefault\nconst defaultEditorMode = 'gfm'\nconst viewportMargin = 20\n\nconst jumpToAddressBarKeymapName = isMac ? 'Cmd-L' : 'Ctrl-L'\n\nexport default class Editor {\n  constructor () {\n    this.editor = null\n    this.jumpToAddressBarKeymapValue = null\n    this.defaultExtraKeys = {\n      F10: function (cm) {\n        cm.setOption('fullScreen', !cm.getOption('fullScreen'))\n      },\n      Esc: function (cm) {\n        if (cm.getOption('fullScreen') && !(cm.getOption('keyMap').substr(0, 3) === 'vim')) {\n          cm.setOption('fullScreen', false)\n        } else {\n          return CodeMirror.Pass\n        }\n      },\n      'Cmd-S': function () {\n        return false\n      },\n      'Ctrl-S': function () {\n        return false\n      },\n      Enter: 'newlineAndIndentContinueMarkdownList',\n      Tab: function (cm) {\n        var tab = '\\t'\n\n        // contruct x length spaces\n        var spaces = Array(parseInt(cm.getOption('indentUnit')) + 1).join(' ')\n\n        // auto indent whole line when in list or blockquote\n        var cursor = cm.getCursor()\n        var line = cm.getLine(cursor.line)\n\n        // this regex match the following patterns\n        // 1. blockquote starts with \"> \" or \">>\"\n        // 2. unorder list starts with *+-\n        // 3. order list starts with \"1.\" or \"1)\"\n        var regex = /^(\\s*)(>[> ]*|[*+-]\\s|(\\d+)([.)]))/\n\n        var match\n        var multiple = cm.getSelection().split('\\n').length > 1 ||\n          cm.getSelections().length > 1\n\n        if (multiple) {\n          cm.execCommand('defaultTab')\n        } else if ((match = regex.exec(line)) !== null) {\n          var ch = match[1].length\n          var pos = {\n            line: cursor.line,\n            ch: ch\n          }\n          if (cm.getOption('indentWithTabs')) {\n            cm.replaceRange(tab, pos, pos, '+input')\n          } else {\n            cm.replaceRange(spaces, pos, pos, '+input')\n          }\n        } else {\n          if (cm.getOption('indentWithTabs')) {\n            cm.execCommand('defaultTab')\n          } else {\n            cm.replaceSelection(spaces)\n          }\n        }\n      },\n      'Cmd-Left': 'goLineLeftSmart',\n      'Cmd-Right': 'goLineRight',\n      Home: 'goLineLeftSmart',\n      End: 'goLineRight',\n      'Ctrl-C': function (cm) {\n        if (!isMac && cm.getOption('keyMap').substr(0, 3) === 'vim') {\n          document.execCommand('copy')\n        } else {\n          return CodeMirror.Pass\n        }\n      },\n      'Ctrl-*': cm => {\n        utils.wrapTextWith(this.editor, cm, '*')\n      },\n      'Shift-Ctrl-8': cm => {\n        utils.wrapTextWith(this.editor, cm, '*')\n      },\n      'Ctrl-_': cm => {\n        utils.wrapTextWith(this.editor, cm, '_')\n      },\n      'Shift-Ctrl--': cm => {\n        utils.wrapTextWith(this.editor, cm, '_')\n      },\n      'Ctrl-~': cm => {\n        utils.wrapTextWith(this.editor, cm, '~')\n      },\n      'Shift-Ctrl-`': cm => {\n        utils.wrapTextWith(this.editor, cm, '~')\n      },\n      'Ctrl-^': cm => {\n        utils.wrapTextWith(this.editor, cm, '^')\n      },\n      'Shift-Ctrl-6': cm => {\n        utils.wrapTextWith(this.editor, cm, '^')\n      },\n      'Ctrl-+': cm => {\n        utils.wrapTextWith(this.editor, cm, '+')\n      },\n      'Shift-Ctrl-=': cm => {\n        utils.wrapTextWith(this.editor, cm, '+')\n      },\n      'Ctrl-=': cm => {\n        utils.wrapTextWith(this.editor, cm, '=')\n      },\n      'Shift-Ctrl-Backspace': cm => {\n        utils.wrapTextWith(this.editor, cm, 'Backspace')\n      }\n    }\n    this.eventListeners = {}\n    this.config = config\n\n    // define modes from mode mime\n    const ignoreOverlay = {\n      token: function (stream, state) {\n        stream.next()\n        return null\n      }\n    }\n\n    CodeMirror.defineMode('c', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-csrc'), ignoreOverlay)\n    })\n    CodeMirror.defineMode('cpp', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-c++src'), ignoreOverlay)\n    })\n    CodeMirror.defineMode('java', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-java'), ignoreOverlay)\n    })\n    CodeMirror.defineMode('csharp', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-csharp'), ignoreOverlay)\n    })\n    CodeMirror.defineMode('objectivec', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-objectivec'), ignoreOverlay)\n    })\n    CodeMirror.defineMode('scala', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-scala'), ignoreOverlay)\n    })\n    CodeMirror.defineMode('kotlin', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-kotlin'), ignoreOverlay)\n    })\n    CodeMirror.defineMode('json', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'application/json'), ignoreOverlay)\n    })\n    CodeMirror.defineMode('jsonld', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'application/ld+json'), ignoreOverlay)\n    })\n    CodeMirror.defineMode('bash', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-sh'), ignoreOverlay)\n    })\n    CodeMirror.defineMode('ocaml', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-ocaml'), ignoreOverlay)\n    })\n    CodeMirror.defineMode('csvpreview', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'csv'), ignoreOverlay)\n    })\n    CodeMirror.defineMode('vega', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'application/ld+json'), ignoreOverlay)\n    })\n\n    CodeMirror.defineMode('markmap', function (config, modeConfig) {\n      return CodeMirror.overlayMode(CodeMirror.getMode(config, 'gfm'), ignoreOverlay)\n    })\n\n    // Migrate preferences from cookies to localStorage\n    this.migratePreferences()\n  }\n\n  // Migrate preferences from cookies to localStorage\n  migratePreferences () {\n    // Only run migration if window and localStorage are available\n    if (typeof window === 'undefined' || typeof localStorage === 'undefined' || typeof Cookies === 'undefined') {\n      return\n    }\n\n    const preferencesToMigrate = [\n      'indent_type',\n      'tab_size',\n      'space_units',\n      'keymap',\n      'theme',\n      'spellcheck',\n      'linter',\n      'preferences-override-browser-keymap',\n      'preferences-disable-table-shortcuts'\n    ]\n\n    preferencesToMigrate.forEach(key => {\n      // Check if preference exists in cookies but not in localStorage\n      const cookieValue = Cookies.get(key)\n      if (cookieValue !== undefined && Storage.get(key) === null) {\n        // Migrate the preference to localStorage\n        Storage.set(key, cookieValue)\n        console.log(`Migrated preference ${key} from cookies to localStorage`)\n      }\n    })\n  }\n\n  on (event, cb) {\n    if (!this.eventListeners[event]) {\n      this.eventListeners[event] = [cb]\n    } else {\n      this.eventListeners[event].push(cb)\n    }\n\n    this.editor.on(event, (...args) => {\n      this.eventListeners[event].forEach(cb => cb.bind(this)(...args))\n    })\n  }\n\n  addToolBar () {\n    this.toolBar = $(toolBarTemplate)\n    this.toolbarPanel = this.editor.addPanel(this.toolBar[0], {\n      position: 'top'\n    })\n\n    var makeBold = $('#makeBold')\n    var makeItalic = $('#makeItalic')\n    var makeStrike = $('#makeStrike')\n    var makeHeader = $('#makeHeader')\n    var makeCode = $('#makeCode')\n    var makeQuote = $('#makeQuote')\n    var makeGenericList = $('#makeGenericList')\n    var makeOrderedList = $('#makeOrderedList')\n    var makeCheckList = $('#makeCheckList')\n    var makeLink = $('#makeLink')\n    var makeImage = $('#makeImage')\n    var makeTable = $('#makeTable')\n    var makeLine = $('#makeLine')\n    var makeComment = $('#makeComment')\n\n    var insertRow = $('#insertRow')\n    var deleteRow = $('#deleteRow')\n    var moveRowUp = $('#moveRowUp')\n    var moveRowDown = $('#moveRowDown')\n    var insertColumn = $('#insertColumn')\n    var deleteColumn = $('#deleteColumn')\n    var moveColumnLeft = $('#moveColumnLeft')\n    var moveColumnRight = $('#moveColumnRight')\n    var alignLeft = $('#alignLeft')\n    var alignCenter = $('#alignCenter')\n    var alignRight = $('#alignRight')\n    var alignNone = $('#alignNone')\n\n    makeBold.click(() => {\n      utils.wrapTextWith(this.editor, this.editor, '**')\n      this.editor.focus()\n    })\n\n    makeItalic.click(() => {\n      utils.wrapTextWith(this.editor, this.editor, '*')\n      this.editor.focus()\n    })\n\n    makeStrike.click(() => {\n      utils.wrapTextWith(this.editor, this.editor, '~~')\n      this.editor.focus()\n    })\n\n    makeHeader.click(() => {\n      utils.insertHeader(this.editor)\n    })\n\n    makeCode.click(() => {\n      utils.wrapTextWith(this.editor, this.editor, '```')\n      this.editor.focus()\n    })\n\n    makeQuote.click(() => {\n      utils.insertOnStartOfLines(this.editor, '> ')\n    })\n\n    makeGenericList.click(() => {\n      utils.insertOnStartOfLines(this.editor, '* ')\n    })\n\n    makeOrderedList.click(() => {\n      utils.insertOnStartOfLines(this.editor, '1. ')\n    })\n\n    makeCheckList.click(() => {\n      utils.insertOnStartOfLines(this.editor, '- [ ] ')\n    })\n\n    makeLink.click(() => {\n      utils.insertLink(this.editor, false)\n    })\n\n    makeImage.click(() => {\n      utils.insertLink(this.editor, true)\n    })\n\n    makeTable.click(() => {\n      utils.insertText(this.editor, '\\n\\n| Column 1 | Column 2 | Column 3 |\\n| -------- | -------- | -------- |\\n| Text     | Text     | Text     |\\n')\n    })\n\n    makeLine.click(() => {\n      utils.insertText(this.editor, '\\n----\\n')\n    })\n\n    makeComment.click(() => {\n      utils.insertText(this.editor, '> []')\n    })\n\n    // table tools UI\n    const opts = options({\n      smartCursor: true,\n      formatType: FormatType.NORMAL\n    })\n\n    insertRow.click(() => {\n      this.tableEditor.insertRow(opts)\n      this.editor.focus()\n    })\n\n    deleteRow.click(() => {\n      this.tableEditor.deleteRow(opts)\n      this.editor.focus()\n    })\n\n    moveRowUp.click(() => {\n      this.tableEditor.moveRow(-1, opts)\n      this.editor.focus()\n    })\n\n    moveRowDown.click(() => {\n      this.tableEditor.moveRow(1, opts)\n      this.editor.focus()\n    })\n\n    insertColumn.click(() => {\n      this.tableEditor.insertColumn(opts)\n      this.editor.focus()\n    })\n\n    deleteColumn.click(() => {\n      this.tableEditor.deleteColumn(opts)\n      this.editor.focus()\n    })\n\n    moveColumnLeft.click(() => {\n      this.tableEditor.moveColumn(-1, opts)\n      this.editor.focus()\n    })\n\n    moveColumnRight.click(() => {\n      this.tableEditor.moveColumn(1, opts)\n      this.editor.focus()\n    })\n\n    alignLeft.click(() => {\n      this.tableEditor.alignColumn(Alignment.LEFT, opts)\n      this.editor.focus()\n    })\n\n    alignCenter.click(() => {\n      this.tableEditor.alignColumn(Alignment.CENTER, opts)\n      this.editor.focus()\n    })\n\n    alignRight.click(() => {\n      this.tableEditor.alignColumn(Alignment.RIGHT, opts)\n      this.editor.focus()\n    })\n\n    alignNone.click(() => {\n      this.tableEditor.alignColumn(Alignment.NONE, opts)\n      this.editor.focus()\n    })\n  }\n\n  addStatusBar () {\n    this.statusBar = $(statusBarTemplate)\n    this.statusCursor = this.statusBar.find('.status-cursor > .status-line-column')\n    this.statusSelection = this.statusBar.find('.status-cursor > .status-selection')\n    this.statusFile = this.statusBar.find('.status-file')\n    this.statusIndicators = this.statusBar.find('.status-indicators')\n    this.statusIndent = this.statusBar.find('.status-indent')\n    this.statusKeymap = this.statusBar.find('.status-keymap')\n    this.statusLength = this.statusBar.find('.status-length')\n    this.statusTheme = this.statusBar.find('.status-theme')\n    this.statusSpellcheck = this.statusBar.find('.status-spellcheck')\n    this.statusLinter = this.statusBar.find('.status-linter')\n    this.statusPreferences = this.statusBar.find('.status-preferences')\n    this.statusPanel = this.editor.addPanel(this.statusBar[0], {\n      position: 'bottom'\n    })\n\n    this.setIndent()\n    this.setKeymap()\n    this.setTheme()\n    this.setSpellcheck()\n    this.setLinter()\n    this.setPreferences()\n\n    this.handleStatusBarResize()\n  }\n\n  updateStatusBar () {\n    if (!this.statusBar) return\n\n    var cursor = this.editor.getCursor()\n    var cursorText = 'Line ' + (cursor.line + 1) + ', Column ' + (cursor.ch + 1)\n    this.statusCursor.text(cursorText)\n    var fileText = ' — ' + editor.lineCount() + ' Lines'\n    this.statusFile.text(fileText)\n    var docLength = editor.getValue().length\n    this.statusLength.text('Length ' + docLength)\n    if (docLength > (config.docmaxlength * 0.95)) {\n      this.statusLength.css('color', 'red')\n      this.statusLength.attr('title', 'You have almost reached the limit for this document.')\n    } else if (docLength > (config.docmaxlength * 0.8)) {\n      this.statusLength.css('color', 'orange')\n      this.statusLength.attr('title', 'This document is nearly full, consider splitting it or creating a new one.')\n    } else {\n      this.statusLength.css('color', 'white')\n      this.statusLength.attr('title', 'You can write up to ' + config.docmaxlength + ' characters in this document.')\n    }\n  }\n\n  handleStatusBarResize () {\n    const onResize = debounce(() => {\n      if (!this.statusBar) {\n        return\n      }\n\n      const maxHeight = window.innerHeight - this.statusBar.height() - 50 /* navbar height */ - 10 /* spacing */\n      this.statusBar.find('.status-theme ul.dropdown-menu').css('max-height', `${maxHeight}px`)\n    }, 300)\n\n    $(window).resize(onResize)\n\n    onResize()\n  }\n\n  setIndent () {\n    var storedIndentType = Storage.get('indent_type')\n    var storedTabSize = parseInt(Storage.get('tab_size'))\n    var storedSpaceUnits = parseInt(Storage.get('space_units'))\n    if (storedIndentType) {\n      if (storedIndentType === 'tab') {\n        this.editor.setOption('indentWithTabs', true)\n        if (storedTabSize) {\n          this.editor.setOption('indentUnit', storedTabSize)\n        }\n      } else if (storedIndentType === 'space') {\n        this.editor.setOption('indentWithTabs', false)\n        if (storedSpaceUnits) {\n          this.editor.setOption('indentUnit', storedSpaceUnits)\n        }\n      }\n    }\n    if (storedTabSize) {\n      this.editor.setOption('tabSize', storedTabSize)\n    }\n\n    var type = this.statusIndicators.find('.indent-type')\n    var widthLabel = this.statusIndicators.find('.indent-width-label')\n    var widthInput = this.statusIndicators.find('.indent-width-input')\n\n    const setType = () => {\n      if (this.editor.getOption('indentWithTabs')) {\n        Storage.set('indent_type', 'tab')\n        type.text('Tab Size:')\n      } else {\n        Storage.set('indent_type', 'space')\n        type.text('Spaces:')\n      }\n    }\n    setType()\n\n    const setUnit = () => {\n      var unit = this.editor.getOption('indentUnit')\n      if (this.editor.getOption('indentWithTabs')) {\n        Storage.set('tab_size', unit)\n      } else {\n        Storage.set('space_units', unit)\n      }\n      widthLabel.text(unit)\n    }\n    setUnit()\n\n    type.click(() => {\n      if (this.editor.getOption('indentWithTabs')) {\n        this.editor.setOption('indentWithTabs', false)\n        storedSpaceUnits = parseInt(Storage.get('space_units'))\n        if (storedSpaceUnits) {\n          this.editor.setOption('indentUnit', storedSpaceUnits)\n        }\n      } else {\n        this.editor.setOption('indentWithTabs', true)\n        storedTabSize = parseInt(Storage.get('tab_size'))\n        if (storedTabSize) {\n          this.editor.setOption('indentUnit', storedTabSize)\n          this.editor.setOption('tabSize', storedTabSize)\n        }\n      }\n      setType()\n      setUnit()\n    })\n    widthLabel.click(() => {\n      if (widthLabel.is(':visible')) {\n        widthLabel.addClass('hidden')\n        widthInput.removeClass('hidden')\n        widthInput.val(this.editor.getOption('indentUnit'))\n        widthInput.select()\n      } else {\n        widthLabel.removeClass('hidden')\n        widthInput.addClass('hidden')\n      }\n    })\n    widthInput.on('change', () => {\n      var val = parseInt(widthInput.val())\n      if (!val) val = this.editor.getOption('indentUnit')\n      if (val < 1) val = 1\n      else if (val > 10) val = 10\n\n      if (this.editor.getOption('indentWithTabs')) {\n        this.editor.setOption('tabSize', val)\n      }\n      this.editor.setOption('indentUnit', val)\n      setUnit()\n    })\n    widthInput.on('blur', function () {\n      widthLabel.removeClass('hidden')\n      widthInput.addClass('hidden')\n    })\n  }\n\n  setKeymap () {\n    var storedKeymap = Storage.get('keymap')\n    if (storedKeymap) {\n      this.editor.setOption('keyMap', storedKeymap)\n    }\n\n    var label = this.statusIndicators.find('.ui-keymap-label')\n    var sublime = this.statusIndicators.find('.ui-keymap-sublime')\n    var emacs = this.statusIndicators.find('.ui-keymap-emacs')\n    var vim = this.statusIndicators.find('.ui-keymap-vim')\n\n    const setKeymapLabel = () => {\n      var keymap = this.editor.getOption('keyMap')\n      Storage.set('keymap', keymap)\n      label.text(keymap)\n      this.restoreOverrideEditorKeymap()\n      this.setOverrideBrowserKeymap()\n    }\n    setKeymapLabel()\n\n    sublime.click(() => {\n      this.editor.setOption('keyMap', 'sublime')\n      setKeymapLabel()\n    })\n    emacs.click(() => {\n      this.editor.setOption('keyMap', 'emacs')\n      setKeymapLabel()\n    })\n    vim.click(() => {\n      this.editor.setOption('keyMap', 'vim')\n      setKeymapLabel()\n    })\n  }\n\n  setTheme () {\n    this.statusIndicators.find('.status-theme ul.dropdown-menu').append(availableThemes.map(theme => {\n      return $(`<li value=\"${theme.value}\"><a>${theme.name}</a></li>`)\n    }))\n\n    const activateThemeListItem = (theme) => {\n      this.statusIndicators.find('.status-theme li').removeClass('active')\n      this.statusIndicators.find(`.status-theme li[value=\"${theme}\"]`).addClass('active')\n    }\n\n    const setTheme = theme => {\n      this.editor.setOption('theme', theme)\n      Storage.set('theme', theme)\n      this.statusIndicators.find('.status-theme li').removeClass('active')\n      this.statusIndicators.find(`.status-theme li[value=\"${theme}\"]`).addClass('active')\n    }\n\n    const storedTheme = Storage.get('theme')\n    if (storedTheme && availableThemes.find(theme => storedTheme === theme.value)) {\n      setTheme(storedTheme)\n      activateThemeListItem(storedTheme)\n    } else {\n      activateThemeListItem(this.editor.getOption('theme'))\n    }\n\n    this.statusIndicators.find('.status-theme li').click(function () {\n      const theme = $(this).attr('value')\n      setTheme(theme)\n      activateThemeListItem(theme)\n    })\n  }\n\n  setSpellcheckLang (lang) {\n    if (lang === 'disabled') {\n      this.statusIndicators.find('.spellcheck-lang').text('')\n      this.activateSpellcheckListItem(false)\n      return\n    }\n\n    if (!supportLanguageCodes.includes(lang)) {\n      return\n    }\n\n    const langName = this.statusIndicators.find(`.status-spellcheck li[value=\"${lang}\"]`).text()\n    this.statusIndicators.find('.spellcheck-lang').text(langName)\n\n    this.spellchecker.setDictLang(lang)\n    this.activateSpellcheckListItem(lang)\n  }\n\n  getExistingSpellcheckLang () {\n    const storedSpellcheck = Storage.get('spellcheck')\n\n    if (storedSpellcheck) {\n      return storedSpellcheck === 'false' ? undefined : storedSpellcheck\n    } else {\n      return undefined\n    }\n  }\n\n  activateSpellcheckListItem (lang) {\n    this.statusIndicators.find('.status-spellcheck li').removeClass('active')\n\n    if (lang) {\n      this.statusIndicators.find(`.status-spellcheck li[value=\"${lang}\"]`).addClass('active')\n    } else {\n      this.statusIndicators.find('.status-spellcheck li[value=\"disabled\"]').addClass('active')\n    }\n  }\n\n  setSpellcheck () {\n    this.statusSpellcheck.find('ul.dropdown-menu').append(supportLanguages.map(lang => {\n      return $(`<li value=\"${lang.value}\"><a>${lang.name}</a></li>`)\n    }))\n\n    const storedSpellcheck = Storage.get('spellcheck')\n    if (storedSpellcheck) {\n      let mode = null\n      let lang = 'en_US'\n\n      if (storedSpellcheck === 'false' || !storedSpellcheck) {\n        mode = defaultEditorMode\n        this.activateSpellcheckListItem(false)\n      } else {\n        mode = 'spell-checker'\n        if (supportLanguageCodes.includes(storedSpellcheck)) {\n          lang = storedSpellcheck\n        }\n        this.setSpellcheckLang(lang)\n      }\n\n      this.editor.setOption('mode', mode)\n    }\n\n    const spellcheckToggle = this.statusSpellcheck.find('.ui-spellcheck-toggle')\n\n    const checkSpellcheck = () => {\n      var mode = this.editor.getOption('mode')\n      if (mode === defaultEditorMode) {\n        spellcheckToggle.removeClass('active')\n      } else {\n        spellcheckToggle.addClass('active')\n      }\n    }\n\n    const self = this\n    this.statusIndicators.find('.status-spellcheck li').click(function () {\n      const lang = $(this).attr('value')\n\n      if (lang === 'disabled') {\n        spellcheckToggle.removeClass('active')\n\n        Storage.set('spellcheck', 'false')\n\n        self.editor.setOption('mode', defaultEditorMode)\n      } else {\n        spellcheckToggle.addClass('active')\n\n        Storage.set('spellcheck', lang)\n\n        self.editor.setOption('mode', 'spell-checker')\n      }\n\n      self.setSpellcheckLang(lang)\n    })\n\n    checkSpellcheck()\n  }\n\n  toggleLinter (enable) {\n    const gutters = this.editor.getOption('gutters')\n    const lintGutter = 'CodeMirror-lint-markers'\n\n    if (enable) {\n      if (!gutters.includes(lintGutter)) {\n        this.editor.setOption('gutters', [lintGutter, ...gutters])\n      }\n      Storage.set('linter', 'true')\n    } else {\n      this.editor.setOption('gutters', gutters.filter(g => g !== lintGutter))\n      Storage.remove('linter')\n    }\n    this.editor.setOption('lint', enable ? linterOptions : false)\n  }\n\n  setLinter () {\n    const linterToggle = this.statusLinter.find('.ui-linter-toggle')\n\n    const updateLinterStatus = (enable) => {\n      linterToggle.toggleClass('active', enable)\n    }\n\n    linterToggle.click(() => {\n      const lintEnable = !!this.editor.getOption('lint')\n      this.toggleLinter.bind(this)(!lintEnable)\n      updateLinterStatus(!lintEnable)\n    })\n\n    const enable = Storage.get('linter') === 'true'\n    this.toggleLinter.bind(this)(enable)\n    updateLinterStatus(enable)\n  }\n\n  resetEditorKeymapToBrowserKeymap () {\n    var keymap = this.editor.getOption('keyMap')\n    if (!this.jumpToAddressBarKeymapValue) {\n      this.jumpToAddressBarKeymapValue = CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName]\n      delete CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName]\n    }\n  }\n\n  restoreOverrideEditorKeymap () {\n    var keymap = this.editor.getOption('keyMap')\n    if (this.jumpToAddressBarKeymapValue) {\n      CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName] = this.jumpToAddressBarKeymapValue\n      this.jumpToAddressBarKeymapValue = null\n    }\n  }\n\n  setOverrideBrowserKeymap () {\n    var overrideBrowserKeymap = $(\n      '.ui-preferences-override-browser-keymap label > input[type=\"checkbox\"]'\n    )\n    if (overrideBrowserKeymap.is(':checked')) {\n      Storage.set('preferences-override-browser-keymap', 'true')\n      this.restoreOverrideEditorKeymap()\n    } else {\n      Storage.remove('preferences-override-browser-keymap')\n      this.resetEditorKeymapToBrowserKeymap()\n    }\n  }\n\n  setPreferences () {\n    var overrideBrowserKeymap = $(\n      '.ui-preferences-override-browser-keymap label > input[type=\"checkbox\"]'\n    )\n    var storedOverrideBrowserKeymap = Storage.get(\n      'preferences-override-browser-keymap'\n    )\n    if (storedOverrideBrowserKeymap && storedOverrideBrowserKeymap === 'true') {\n      overrideBrowserKeymap.prop('checked', true)\n    } else {\n      overrideBrowserKeymap.prop('checked', false)\n    }\n    this.setOverrideBrowserKeymap()\n\n    overrideBrowserKeymap.change(() => {\n      this.setOverrideBrowserKeymap()\n    })\n\n    // Handle table editor shortcuts preference\n    var disableTableShortcuts = $(\n      '.ui-preferences-disable-table-shortcuts label > input[type=\"checkbox\"]'\n    )\n    var storedDisableTableShortcuts = Storage.get(\n      'preferences-disable-table-shortcuts'\n    )\n    if (storedDisableTableShortcuts && storedDisableTableShortcuts === 'true') {\n      disableTableShortcuts.prop('checked', true)\n    } else {\n      disableTableShortcuts.prop('checked', false)\n    }\n    this.setTableShortcutsPreference()\n\n    disableTableShortcuts.change(() => {\n      this.setTableShortcutsPreference()\n    })\n  }\n\n  setTableShortcutsPreference () {\n    var disableTableShortcuts = $(\n      '.ui-preferences-disable-table-shortcuts label > input[type=\"checkbox\"]'\n    )\n    if (disableTableShortcuts.is(':checked')) {\n      Storage.set('preferences-disable-table-shortcuts', 'true')\n    } else {\n      Storage.remove('preferences-disable-table-shortcuts')\n    }\n    // Notify table editor about the preference change\n    if (this.tableEditor) {\n      this.tableEditor.setShortcutsEnabled(!disableTableShortcuts.is(':checked'))\n    }\n  }\n\n  init (textit) {\n    this.editor = CodeMirror.fromTextArea(textit, {\n      mode: defaultEditorMode,\n      backdrop: defaultEditorMode,\n      keyMap: 'sublime',\n      viewportMargin: viewportMargin,\n      styleActiveLine: true,\n      lineNumbers: true,\n      lineWrapping: true,\n      showCursorWhenSelecting: true,\n      highlightSelectionMatches: true,\n      indentUnit: 4,\n      continueComments: 'Enter',\n      theme: 'one-dark',\n      inputStyle: 'textarea',\n      matchBrackets: true,\n      autoCloseBrackets: true,\n      matchTags: {\n        bothTags: true\n      },\n      autoCloseTags: true,\n      foldGutter: true,\n      gutters: [\n        'CodeMirror-linenumbers',\n        'authorship-gutters',\n        'CodeMirror-foldgutter'\n      ],\n      extraKeys: this.defaultExtraKeys,\n      flattenSpans: true,\n      addModeClass: true,\n      readOnly: true,\n      autoRefresh: true,\n      otherCursors: true,\n      placeholder: \"← Start by entering a title here\\n===\\nVisit /features if you don't know what to do.\\nHappy hacking :)\"\n    })\n\n    this.spellchecker = new CodeMirrorSpellChecker(CodeMirror, this.getExistingSpellcheckLang(), this.editor)\n    this.tableEditor = initTableEditor(this.editor)\n\n    return this.editor\n  }\n\n  getEditor () {\n    return this.editor\n  }\n}\n"
  },
  {
    "path": "public/js/lib/editor/markdown-lint/index.js",
    "content": "/* global CodeMirror */\n\n// load CM lint plugin explicitly\nimport '@hackmd/codemirror/addon/lint/lint'\n\nimport '@hackmd/codemirror/addon/hint/show-hint.css'\nimport helpers from 'markdownlint-rule-helpers'\n\nwindow.markdownit = require('markdown-it')\n// eslint-disable-next-line\nrequire('script-loader!markdownlint');\n\n(function (mod) {\n  mod(CodeMirror)\n})(function (CodeMirror) {\n  function validator (text) {\n    return lint(text).map(error => {\n      const {\n        ruleNames,\n        ruleDescription,\n        lineNumber: ln,\n        errorRange\n      } = error\n      const lineNumber = ln - 1\n\n      let start = 0; let end = -1\n      if (errorRange) {\n        [start, end] = errorRange.map(r => r - 1)\n      }\n\n      return {\n        messageHTML: `${ruleNames.join('/')}: ${ruleDescription} <small>markdownlint(${ruleNames[0]})</small>`,\n        severity: 'error',\n        from: CodeMirror.Pos(lineNumber, start),\n        to: CodeMirror.Pos(lineNumber, end),\n        __error: error\n      }\n    })\n  }\n\n  CodeMirror.registerHelper('lint', 'markdown', validator)\n})\n\nexport const linterOptions = {\n  fixedTooltip: true,\n  contextmenu: annotations => {\n    const singleFixMenus = annotations\n      .map(annotation => {\n        const error = annotation.__error\n        const ruleNameAlias = error.ruleNames.join('/')\n\n        if (annotation.__error.fixInfo) {\n          return {\n            content: `Click to fix this violoation of ${ruleNameAlias}`,\n            onClick () {\n              const doc = window.editor.doc\n              const fixInfo = normalizeFixInfo(error.fixInfo, error.lineNumber)\n              const line = fixInfo.lineNumber - 1\n              const lineContent = doc.getLine(line) || ''\n              const fixedText = helpers.applyFix(lineContent, fixInfo, '\\n')\n\n              let from = { line, ch: 0 }\n              let to = { line, ch: lineContent ? lineContent.length : 0 }\n\n              if (typeof fixedText === 'string') {\n                doc.replaceRange(fixedText, from, to)\n              } else {\n                if (fixInfo.lineNumber === 1) {\n                  if (doc.lineCount() > 1) {\n                    const nextLineStart = doc.indexFromPos({\n                      line: to.line + 1,\n                      ch: 0\n                    })\n                    to = doc.posFromIndex(nextLineStart)\n                  }\n                } else {\n                  const previousLineEnd = doc.indexFromPos(from) - 1\n                  from = doc.posFromIndex(previousLineEnd)\n                }\n\n                doc.replaceRange('', from, to)\n              }\n            }\n          }\n        } else {\n          return {\n            content: `Click for more information about ${ruleNameAlias}`,\n            onClick () {\n              window.open(error.ruleInformation, '_blank')\n            }\n          }\n        }\n      })\n\n    return singleFixMenus\n  }\n}\n\nfunction lint (content) {\n  const { content: errors } = window.markdownlint.sync({\n    strings: {\n      content\n    },\n    resultVersion: 3\n  })\n  return errors\n}\n\n// Taken from https://github.com/DavidAnson/markdownlint/blob/2a9274ece586514ba3e2819cec3eb74312dc1b84/helpers/helpers.js#L611\n/**\n * Normalizes the fields of a RuleOnErrorFixInfo instance.\n *\n * @param {Object} fixInfo RuleOnErrorFixInfo instance.\n * @param {number} [lineNumber] Line number.\n * @returns {Object} Normalized RuleOnErrorFixInfo instance.\n */\nfunction normalizeFixInfo (fixInfo, lineNumber) {\n  return {\n    lineNumber: fixInfo.lineNumber || lineNumber,\n    editColumn: fixInfo.editColumn || 1,\n    deleteCount: fixInfo.deleteCount || 0,\n    insertText: fixInfo.insertText || ''\n  }\n}\n"
  },
  {
    "path": "public/js/lib/editor/spellcheck.js",
    "content": "/* eslint-env browser */\n\n// Modified from https://github.com/sparksuite/codemirror-spell-checker\n\nimport Typo from 'typo-js'\nimport { serverurl } from '../config'\n\nexport const supportLanguages = [\n  {\n    name: 'English (United States)',\n    value: 'en_US',\n    aff: {\n      url: `${serverurl}/vendor/codemirror-spell-checker/en_US.aff`,\n      cdnUrl: `${serverurl}/vendor/codemirror-spell-checker/en_US.aff`\n    },\n    dic: {\n      url: `${serverurl}/vendor/codemirror-spell-checker/en_US.dic`,\n      cdnUrl: `${serverurl}/vendor/codemirror-spell-checker/en_US.dic`\n    }\n  },\n  {\n    name: 'English (United Kingdom)',\n    value: 'en_GB',\n    aff: {\n      url: `${serverurl}/build/dictionary-en-gb/index.aff`,\n      cdnUrl: 'https://cdn.jsdelivr.net/npm/dictionary-en-gb@2.2.2/index.aff'\n    },\n    dic: {\n      url: `${serverurl}/build/dictionary-en-gb/index.dic`,\n      cdnUrl: 'https://cdn.jsdelivr.net/npm/dictionary-en-gb@2.2.2/index.dic'\n    }\n  },\n  {\n    name: 'German',\n    value: 'de',\n    aff: {\n      url: `${serverurl}/build/dictionary-de/index.aff`,\n      cdnUrl: 'https://cdn.jsdelivr.net/npm/dictionary-de@2.0.3/index.aff'\n    },\n    dic: {\n      url: `${serverurl}/build/dictionary-de/index.dic`,\n      cdnUrl: 'https://cdn.jsdelivr.net/npm/dictionary-de@2.0.3/index.dic'\n    }\n  },\n  {\n    name: 'German (Austria)',\n    value: 'de_AT',\n    aff: {\n      url: `${serverurl}/build/dictionary-de-at/index.aff`,\n      cdnUrl: 'https://cdn.jsdelivr.net/npm/dictionary-de-at@2.0.3/index.aff'\n    },\n    dic: {\n      url: `${serverurl}/build/dictionary-de-at/index.dic`,\n      cdnUrl: 'https://cdn.jsdelivr.net/npm/dictionary-de-at@2.0.3/index.dic'\n    }\n  },\n  {\n    name: 'German (Switzerland)',\n    value: 'de_CH',\n    aff: {\n      url: `${serverurl}/build/dictionary-de-ch/index.aff`,\n      cdnUrl: 'https://cdn.jsdelivr.net/npm/dictionary-de-ch@2.0.3/index.aff'\n    },\n    dic: {\n      url: `${serverurl}/build/dictionary-de-ch/index.dic`,\n      cdnUrl: 'https://cdn.jsdelivr.net/npm/dictionary-de-ch@2.0.3/index.dic'\n    }\n  }\n]\n\nexport const supportLanguageCodes = supportLanguages.map(lang => lang.value)\n\nfunction request (url) {\n  return new Promise(resolve => {\n    const req = new XMLHttpRequest()\n    req.open('GET', url, true)\n    req.onload = () => {\n      if (req.readyState === 4 && req.status === 200) {\n        resolve(req.responseText)\n      }\n    }\n    req.send(null)\n  })\n}\n\nasync function runSeriesP (iterables, fn) {\n  const results = []\n  for (const iterable of iterables) {\n    results.push(await fn(iterable))\n  }\n  return results\n}\n\nfunction mapSeriesP (iterables, fn) {\n  return new Promise(resolve => {\n    resolve(runSeriesP(iterables, fn))\n  })\n}\n\nfunction createTypo (lang, affData, dicData) {\n  return new Typo(lang, affData, dicData, { platform: 'any' })\n}\n\nconst typoMap = new Map()\n\nlet fetching = false\nasync function findOrCreateTypoInstance (lang) {\n  if (!lang) {\n    return\n  }\n\n  // find existing typo instance\n  let typo = typoMap.get(lang)\n  if (typo) {\n    return typo\n  }\n\n  let dict = supportLanguages.find(l => l.value === lang)\n\n  if (!dict) {\n    console.error(`Dictionary not found for \"${lang}\"\\n Fallback to default English spellcheck`)\n    dict = supportLanguages[0]\n  }\n\n  let affUrl\n  let dicUrl\n  if (window.USE_CDN) {\n    affUrl = dict.aff.cdnUrl\n    dicUrl = dict.dic.cdnUrl\n  } else {\n    affUrl = dict.aff.url\n    dicUrl = dict.dic.url\n  }\n\n  if (fetching) {\n    return typo\n  }\n\n  try {\n    fetching = true\n\n    const [affData, dicData] = await mapSeriesP([affUrl, dicUrl], request)\n\n    typo = createTypo(lang, affData, dicData)\n    typoMap.set(lang, typo)\n  } catch (err) {\n    console.error(err)\n  } finally {\n    fetching = false\n  }\n\n  return typo\n}\n\nclass CodeMirrorSpellChecker {\n  /**\n   * @param {CodeMirror} cm\n   * @param {string} lang\n   */\n  constructor (cm, lang, editor) {\n    // Verify\n    if (typeof cm !== 'function' || typeof cm.defineMode !== 'function') {\n      console.log(\n        'CodeMirror Spell Checker: You must provide an instance of CodeMirror via the option `codeMirrorInstance`'\n      )\n      return\n    }\n\n    this.typo = undefined\n    this.defineSpellCheckerMode(cm, lang)\n    this.editor = editor\n  }\n\n  setDictLang (lang) {\n    findOrCreateTypoInstance(lang).then(typo => {\n      this.typo = typo\n\n      // re-enable overlay mode to refresh spellcheck\n      this.editor.setOption('mode', 'gfm')\n      this.editor.setOption('mode', 'spell-checker')\n    })\n  }\n\n  defineSpellCheckerMode (cm, lang) {\n    // Load AFF/DIC data async ASAP\n    this.setDictLang(lang)\n\n    cm.defineMode('spell-checker', config => {\n      // Define what separates a word\n      const regexWord = '!\"#$%&()*+,-./:;<=>?@[\\\\]^_`{|}~ '\n\n      // Create the overlay and such\n      const overlay = {\n        token: (stream) => {\n          let ch = stream.peek()\n          let word = ''\n\n          if (regexWord.includes(ch)) {\n            stream.next()\n            return null\n          }\n\n          while ((ch = stream.peek()) != null && !regexWord.includes(ch)) {\n            word += ch\n            stream.next()\n          }\n\n          if (this.typo && !this.typo.check(word)) {\n            return 'spell-error' // CSS class: cm-spell-error\n          }\n\n          return null\n        }\n      }\n\n      const mode = cm.getMode(config, config.backdrop || 'text/plain')\n\n      return cm.overlayMode(mode, overlay, true)\n    })\n  }\n}\n\nexport default CodeMirrorSpellChecker\n"
  },
  {
    "path": "public/js/lib/editor/statusbar.html",
    "content": "<div class=\"status-bar\">\n    <div class=\"status-info\">\n        <div class=\"status-cursor\">\n          <span class=\"status-line-column\"></span>\n          <span class=\"status-selection\"></span>\n        </div>\n        <div class=\"status-file\"></div>\n    </div>\n    <div class=\"status-indicators\">\n        <div class=\"status-length\"></div>\n        <div class=\"status-preferences dropup toggle-dropdown pull-right\">\n            <a id=\"preferencesLabel\" class=\"ui-preferences-label text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Click to change preferences\">\n                <i class=\"fa fa-wrench fa-fw\"></i>\n            </a>\n            <ul class=\"dropdown-menu\" aria-labelledby=\"preferencesLabel\">\n                <li class=\"ui-preferences-override-browser-keymap\"><a><label>Allow override browser keymap&nbsp;&nbsp;<input type=\"checkbox\"></label></a></li>\n                <li class=\"ui-preferences-disable-table-shortcuts\"><a><label>Disable table editor shortcuts&nbsp;&nbsp;<input type=\"checkbox\"></label></a></li>\n            </ul>\n        </div>\n        <div class=\"status-keymap dropup pull-right\">\n            <a id=\"keymapLabel\" class=\"ui-keymap-label text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Click to change keymap\">\n            Sublime\n            </a>\n            <ul class=\"dropdown-menu\" aria-labelledby=\"keymapLabel\">\n                <li class=\"ui-keymap-sublime\"><a>Sublime</a></li>\n                <li class=\"ui-keymap-emacs\"><a>Emacs</a></li>\n                <li class=\"ui-keymap-vim\"><a>Vim</a></li>\n            </ul>\n        </div>\n        <div class=\"status-indent\">\n            <div class=\"indent-type\" title=\"Click to switch indentation type\">Spaces:</div>\n            <div class=\"indent-width-label\" title=\"Click to change indentation size\">4</div>\n            <input class=\"indent-width-input hidden\" type=\"number\" min=\"1\" max=\"10\" maxlength=\"2\" size=\"2\">\n        </div>\n        <div class=\"status-theme dropup\">\n            <a id=\"themeLabel\" class=\"ui-theme-label text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Select theme\">\n                <i class=\"fa fa-paint-brush fa-fw\"></i>\n            </a>\n            <ul class=\"dropdown-menu\" aria-labelledby=\"themeLabel\" style=\"overflow: auto;\">\n            </ul>\n        </div>\n        <div class=\"status-spellcheck dropup pull-right\">\n            <a class=\"ui-spellcheck-toggle\" title=\"Toggle spellcheck\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\">\n                <i class=\"fa fa-check fa-fw\"></i>\n                <span class=\"spellcheck-lang\"></span>\n            </a>\n            <ul class=\"dropdown-menu\" aria-labelledby=\"themeLabel\">\n                <li value=\"disabled\"><a>Disabled</a></li>\n            </ul>\n        </div>\n        <div class=\"status-linter\">\n            <a class=\"ui-linter-toggle\" title=\"Toggle linter\"><i class=\"fa fa-lightbulb-o fa-fw\"></i></a>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "public/js/lib/editor/table-editor.js",
    "content": "/* global CodeMirror, $ */\nimport { TableEditor, Point, options, Alignment, FormatType } from '@susisu/mte-kernel'\n\n// port of the code from: https://github.com/susisu/mte-demo/blob/master/src/main.js\n\n// text editor interface\n// see https://doc.esdoc.org/github.com/susisu/mte-kernel/class/lib/text-editor.js~ITextEditor.html\nclass TextEditorInterface {\n  constructor (editor) {\n    this.editor = editor\n    this.doc = editor.getDoc()\n    this.transaction = false\n    this.onDidFinishTransaction = null\n  }\n\n  getCursorPosition () {\n    const { line, ch } = this.doc.getCursor()\n    return new Point(line, ch)\n  }\n\n  setCursorPosition (pos) {\n    this.doc.setCursor({ line: pos.row, ch: pos.column })\n  }\n\n  setSelectionRange (range) {\n    this.doc.setSelection(\n      { line: range.start.row, ch: range.start.column },\n      { line: range.end.row, ch: range.end.column }\n    )\n  }\n\n  getLastRow () {\n    return this.doc.lineCount() - 1\n  }\n\n  acceptsTableEdit () {\n    return true\n  }\n\n  getLine (row) {\n    return this.doc.getLine(row)\n  }\n\n  insertLine (row, line) {\n    const lastRow = this.getLastRow()\n    if (row > lastRow) {\n      const lastLine = this.getLine(lastRow)\n      this.doc.replaceRange(\n        '\\n' + line,\n        { line: lastRow, ch: lastLine.length },\n        { line: lastRow, ch: lastLine.length }\n      )\n    } else {\n      this.doc.replaceRange(\n        line + '\\n',\n        { line: row, ch: 0 },\n        { line: row, ch: 0 }\n      )\n    }\n  }\n\n  deleteLine (row) {\n    const lastRow = this.getLastRow()\n    if (row >= lastRow) {\n      if (lastRow > 0) {\n        const preLastLine = this.getLine(lastRow - 1)\n        const lastLine = this.getLine(lastRow)\n        this.doc.replaceRange(\n          '',\n          { line: lastRow - 1, ch: preLastLine.length },\n          { line: lastRow, ch: lastLine.length }\n        )\n      } else {\n        const lastLine = this.getLine(lastRow)\n        this.doc.replaceRange(\n          '',\n          { line: lastRow, ch: 0 },\n          { line: lastRow, ch: lastLine.length }\n        )\n      }\n    } else {\n      this.doc.replaceRange(\n        '',\n        { line: row, ch: 0 },\n        { line: row + 1, ch: 0 }\n      )\n    }\n  }\n\n  replaceLines (startRow, endRow, lines) {\n    const lastRow = this.getLastRow()\n    if (endRow > lastRow) {\n      const lastLine = this.getLine(lastRow)\n      this.doc.replaceRange(\n        lines.join('\\n'),\n        { line: startRow, ch: 0 },\n        { line: lastRow, ch: lastLine.length }\n      )\n    } else {\n      this.doc.replaceRange(\n        lines.join('\\n') + '\\n',\n        { line: startRow, ch: 0 },\n        { line: endRow, ch: 0 }\n      )\n    }\n  }\n\n  transact (func) {\n    this.transaction = true\n    func()\n    this.transaction = false\n    if (this.onDidFinishTransaction) {\n      this.onDidFinishTransaction.call(undefined)\n    }\n  }\n}\n\nexport function initTableEditor (editor) {\n  // create an interface to the text editor\n  const editorIntf = new TextEditorInterface(editor)\n  // create a table editor object\n  const tableEditor = new TableEditor(editorIntf)\n  // options for the table editor\n  const opts = options({\n    smartCursor: true,\n    formatType: FormatType.NORMAL\n  })\n\n  // Flag to track if shortcuts are enabled\n  let shortcutsEnabled = true\n\n  // Method to enable/disable shortcuts\n  tableEditor.setShortcutsEnabled = function (enabled) {\n    shortcutsEnabled = enabled\n    // If shortcuts are disabled and currently active, remove the keymap\n    if (!enabled && lastActive) {\n      editor.removeKeyMap(keyMap)\n    } else if (enabled && lastActive) {\n      // If shortcuts are enabled and cursor is in table, add the keymap back\n      editor.addKeyMap(keyMap)\n    }\n  }\n\n  // keymap of the commands\n  // from https://github.com/susisu/mte-demo/blob/master/src/main.js\n  const keyMap = CodeMirror.normalizeKeyMap({\n    Tab: () => { tableEditor.nextCell(opts) },\n    'Shift-Tab': () => { tableEditor.previousCell(opts) },\n    Enter: () => { tableEditor.nextRow(opts) },\n    'Ctrl-Enter': () => { tableEditor.escape(opts) },\n    'Cmd-Enter': () => { tableEditor.escape(opts) },\n    'Shift-Ctrl-Left': () => { tableEditor.alignColumn(Alignment.LEFT, opts) },\n    'Shift-Cmd-Left': () => { tableEditor.alignColumn(Alignment.LEFT, opts) },\n    'Shift-Ctrl-Right': () => { tableEditor.alignColumn(Alignment.RIGHT, opts) },\n    'Shift-Cmd-Right': () => { tableEditor.alignColumn(Alignment.RIGHT, opts) },\n    'Shift-Ctrl-Up': () => { tableEditor.alignColumn(Alignment.CENTER, opts) },\n    'Shift-Cmd-Up': () => { tableEditor.alignColumn(Alignment.CENTER, opts) },\n    'Shift-Ctrl-Down': () => { tableEditor.alignColumn(Alignment.NONE, opts) },\n    'Shift-Cmd-Down': () => { tableEditor.alignColumn(Alignment.NONE, opts) },\n    'Ctrl-Left': () => { tableEditor.moveFocus(0, -1, opts) },\n    'Cmd-Left': () => { tableEditor.moveFocus(0, -1, opts) },\n    'Ctrl-Right': () => { tableEditor.moveFocus(0, 1, opts) },\n    'Cmd-Right': () => { tableEditor.moveFocus(0, 1, opts) },\n    'Ctrl-Up': () => { tableEditor.moveFocus(-1, 0, opts) },\n    'Cmd-Up': () => { tableEditor.moveFocus(-1, 0, opts) },\n    'Ctrl-Down': () => { tableEditor.moveFocus(1, 0, opts) },\n    'Cmd-Down': () => { tableEditor.moveFocus(1, 0, opts) },\n    'Ctrl-K Ctrl-I': () => { tableEditor.insertRow(opts) },\n    'Cmd-K Cmd-I': () => { tableEditor.insertRow(opts) },\n    'Ctrl-L Ctrl-I': () => { tableEditor.deleteRow(opts) },\n    'Cmd-L Cmd-I': () => { tableEditor.deleteRow(opts) },\n    'Ctrl-K Ctrl-J': () => { tableEditor.insertColumn(opts) },\n    'Cmd-K Cmd-J': () => { tableEditor.insertColumn(opts) },\n    'Ctrl-L Ctrl-J': () => { tableEditor.deleteColumn(opts) },\n    'Cmd-L Cmd-J': () => { tableEditor.deleteColumn(opts) },\n    'Alt-Shift-Ctrl-Left': () => { tableEditor.moveColumn(-1, opts) },\n    'Alt-Shift-Cmd-Left': () => { tableEditor.moveColumn(-1, opts) },\n    'Alt-Shift-Ctrl-Right': () => { tableEditor.moveColumn(1, opts) },\n    'Alt-Shift-Cmd-Right': () => { tableEditor.moveColumn(1, opts) },\n    'Alt-Shift-Ctrl-Up': () => { tableEditor.moveRow(-1, opts) },\n    'Alt-Shift-Cmd-Up': () => { tableEditor.moveRow(-1, opts) },\n    'Alt-Shift-Ctrl-Down': () => { tableEditor.moveRow(1, opts) },\n    'Alt-Shift-Cmd-Down': () => { tableEditor.moveRow(1, opts) }\n  })\n  let lastActive\n  // enable keymap if the cursor is in a table\n  function updateActiveState () {\n    const tableTools = $('.toolbar .table-tools')\n    const active = tableEditor.cursorIsInTable(opts)\n    // avoid to update if state not changed\n    if (lastActive === active) {\n      return\n    }\n    if (active) {\n      tableTools.show()\n      tableTools.parent().scrollLeft(tableTools.parent()[0].scrollWidth)\n      // Only add keymap if shortcuts are enabled\n      if (shortcutsEnabled) {\n        editor.addKeyMap(keyMap)\n      }\n    } else {\n      tableTools.hide()\n      editor.removeKeyMap(keyMap)\n      tableEditor.resetSmartCursor()\n    }\n    lastActive = active\n  }\n  // event subscriptions\n  editor.on('cursorActivity', () => {\n    if (!editorIntf.transaction) {\n      updateActiveState()\n    }\n  })\n  editor.on('changes', () => {\n    if (!editorIntf.transaction) {\n      updateActiveState()\n    }\n  })\n  editorIntf.onDidFinishTransaction = () => {\n    updateActiveState()\n  }\n\n  return tableEditor\n}\n"
  },
  {
    "path": "public/js/lib/editor/toolbar.html",
    "content": "<div class=\"toolbar\">\n  <div class=\"btn-toolbar\" role=\"toolbar\" aria-label=\"Editor toolbar\">\n    <div class=\"btn-group\" role=\"group\">\n      <a id=\"makeBold\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Bold\">\n          <i class=\"fa fa-bold fa-fw\"></i>\n      </a>\n      <a id=\"makeItalic\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Italic\">\n          <i class=\"fa fa-italic fa-fw\"></i>\n      </a>\n      <a id=\"makeStrike\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Strikethrough\">\n          <i class=\"fa fa-strikethrough fa-fw\"></i>\n      </a>\n      <a id=\"makeHeader\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Heading\">\n          <i class=\"fa fa-h1 fa-fw\">H</i>\n      </a>\n      <a id=\"makeCode\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Code\">\n          <i class=\"fa fa-code fa-fw\"></i>\n      </a>\n      <a id=\"makeQuote\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Quote\">\n          <i class=\"fa fa-quote-right fa-fw\"></i>\n      </a>\n      <a id=\"makeGenericList\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"List\">\n          <i class=\"fa fa-list fa-fw\"></i>\n      </a>\n      <a id=\"makeOrderedList\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Numbered List\">\n          <i class=\"fa fa-list-ol fa-fw\"></i>\n      </a>\n      <a id=\"makeCheckList\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Check List\">\n          <i class=\"fa fa-check-square fa-fw\"></i>\n      </a>\n      <a id=\"makeLink\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Link\">\n          <i class=\"fa fa-link fa-fw\"></i>\n      </a>\n      <a id=\"makeImage\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Image\">\n          <i class=\"fa fa-image fa-fw\"></i>\n      </a>\n      <a id=\"makeTable\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Table\">\n          <i class=\"fa fa-table fa-fw\"></i>\n      </a>\n      <a id=\"makeLine\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Line\">\n          <i class=\"fa fa-minus fa-fw\"></i>\n      </a>\n      <a id=\"makeComment\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Comment\">\n          <i class=\"fa fa-comment fa-fw\"></i>\n      </a>\n    </div>\n    <span class=\"btn-group table-tools hidden-xs\" style=\"display: none;\">\n      <span class=\"separator\" style=\"margin-left: -10px;\">|</span>\n      <span>Row</span>\n      <a id=\"insertRow\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Insert Row\">\n          <i class=\"fa fa-plus-circle fa-fw\"></i>\n      </a>\n      <a id=\"deleteRow\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Delete Row\">\n          <i class=\"fa fa-minus-circle fa-fw\"></i>\n      </a>\n      <a id=\"moveRowUp\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Move Row Up\">\n          <i class=\"fa fa-long-arrow-up fa-fw\"></i>\n      </a>\n      <a id=\"moveRowDown\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Move Row Down\">\n          <i class=\"fa fa-long-arrow-down fa-fw\"></i>\n      </a>\n      <span>Column</span>\n      <a id=\"insertColumn\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Insert Column\">\n          <i class=\"fa fa-plus-circle fa-fw\"></i>\n      </a>\n      <a id=\"deleteColumn\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Delete Column\">\n          <i class=\"fa fa-minus-circle fa-fw\"></i>\n      </a>\n      <a id=\"moveColumnLeft\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Move Column Left\">\n          <i class=\"fa fa-long-arrow-left fa-fw\"></i>\n      </a>\n      <a id=\"moveColumnRight\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Move Column Right\">\n          <i class=\"fa fa-long-arrow-right fa-fw\"></i>\n      </a>\n      <span>Alignment</span>\n      <a id=\"alignLeft\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Align Left\">\n          <i class=\"fa fa-align-left fa-fw\"></i>\n      </a>\n      <a id=\"alignCenter\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Align Center\">\n          <i class=\"fa fa-align-center fa-fw\"></i>\n      </a>\n      <a id=\"alignRight\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Align Right\">\n          <i class=\"fa fa-align-right fa-fw\"></i>\n      </a>\n      <a id=\"alignNone\" class=\"btn btn-sm btn-dark text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Align None\">\n          <i class=\"fa fa-ban fa-fw\"></i>\n      </a>\n    </span>\n  </div>\n</div>\n"
  },
  {
    "path": "public/js/lib/editor/ui-elements.js",
    "content": "/*\n *  Global UI elements references\n */\n/* global $ */\n\nexport const getUIElements = () => ({\n  spinner: $('.ui-spinner'),\n  content: $('.ui-content'),\n  toolbar: {\n    shortStatus: $('.ui-short-status'),\n    status: $('.ui-status'),\n    statusShortMsg: $('.ui-status-short-msg'),\n    statusConnected: $('.ui-status-connected'),\n    statusOnline: $('.ui-status-online'),\n    statusOffline: $('.ui-status-offline'),\n    new: $('.ui-new'),\n    publish: $('.ui-publish'),\n    extra: {\n      revision: $('.ui-extra-revision'),\n      slide: $('.ui-extra-slide')\n    },\n    download: {\n      markdown: $('.ui-download-markdown'),\n      html: $('.ui-download-html'),\n      rawhtml: $('.ui-download-raw-html'),\n      pdf: $('.ui-download-pdf-beta')\n    },\n    export: {\n      dropbox: $('.ui-save-dropbox'),\n      gist: $('.ui-save-gist'),\n      snippet: $('.ui-save-snippet')\n    },\n    import: {\n      dropbox: $('.ui-import-dropbox'),\n      gist: $('.ui-import-gist'),\n      snippet: $('.ui-import-snippet'),\n      clipboard: $('.ui-import-clipboard')\n    },\n    mode: $('.ui-mode'),\n    edit: $('.ui-edit'),\n    view: $('.ui-view'),\n    both: $('.ui-both'),\n    night: $('.ui-night'),\n    uploadImage: $('.ui-upload-image')\n  },\n  infobar: {\n    lastchange: $('.ui-lastchange'),\n    lastchangeuser: $('.ui-lastchangeuser'),\n    nolastchangeuser: $('.ui-no-lastchangeuser'),\n    permission: {\n      permission: $('.ui-permission'),\n      label: $('.ui-permission-label'),\n      labelCaretDown: $('.ui-permission-caret-down'),\n      freely: $('.ui-permission-freely'),\n      editable: $('.ui-permission-editable'),\n      locked: $('.ui-permission-locked'),\n      private: $('.ui-permission-private'),\n      limited: $('.ui-permission-limited'),\n      protected: $('.ui-permission-protected')\n    },\n    delete: $('.ui-delete-note')\n  },\n  toc: {\n    toc: $('.ui-toc'),\n    affix: $('.ui-affix-toc'),\n    label: $('.ui-toc-label'),\n    dropdown: $('.ui-toc-dropdown')\n  },\n  area: {\n    edit: $('.ui-edit-area'),\n    view: $('.ui-view-area'),\n    codemirror: $('.ui-edit-area .CodeMirror'),\n    codemirrorScroll: $('.ui-edit-area .CodeMirror .CodeMirror-scroll'),\n    codemirrorSizer: $('.ui-edit-area .CodeMirror .CodeMirror-sizer'),\n    codemirrorSizerInner: $(\n      '.ui-edit-area .CodeMirror .CodeMirror-sizer > div'\n    ),\n    codemirrorLines: $(\n      '.ui-edit-area .CodeMirror .CodeMirror-lines'\n    ),\n    markdown: $('.ui-view-area .markdown-body'),\n    resize: {\n      handle: $('.ui-resizable-handle'),\n      syncToggle: $('.ui-sync-toggle')\n    }\n  },\n  modal: {\n    snippetImportProjects: $('#snippetImportModalProjects'),\n    snippetImportSnippets: $('#snippetImportModalSnippets'),\n    revision: $('#revisionModal'),\n    pandocExport: $('.pandoc-export-modal')\n  }\n})\n\nexport default getUIElements\n"
  },
  {
    "path": "public/js/lib/editor/utils.js",
    "content": "/* global CodeMirror, editor */\nconst wrapSymbols = ['*', '_', '~', '^', '+', '=']\nexport function wrapTextWith (editor, cm, symbol) {\n  if (!cm.getSelection()) {\n    return CodeMirror.Pass\n  } else {\n    const ranges = cm.listSelections()\n    for (let i = 0; i < ranges.length; i++) {\n      const range = ranges[i]\n      if (!range.empty()) {\n        const from = range.from()\n        const to = range.to()\n\n        if (symbol !== 'Backspace') {\n          const selection = cm.getRange(from, to)\n          const anchorIndex = editor.indexFromPos(ranges[i].anchor)\n          const headIndex = editor.indexFromPos(ranges[i].head)\n          cm.replaceRange(symbol + selection + symbol, from, to, '+input')\n          if (anchorIndex > headIndex) {\n            ranges[i].anchor.ch += symbol.length\n            ranges[i].head.ch += symbol.length\n          } else {\n            ranges[i].head.ch += symbol.length\n            ranges[i].anchor.ch += symbol.length\n          }\n          cm.setSelections(ranges)\n        } else {\n          const preEndPos = {\n            line: to.line,\n            ch: to.ch + symbol.length\n          }\n          const preText = cm.getRange(to, preEndPos)\n          const preIndex = wrapSymbols.indexOf(preText)\n          const postEndPos = {\n            line: from.line,\n            ch: from.ch - symbol.length\n          }\n          const postText = cm.getRange(postEndPos, from)\n          const postIndex = wrapSymbols.indexOf(postText)\n          // check if surround symbol are list in array and matched\n          if (preIndex > -1 && postIndex > -1 && preIndex === postIndex) {\n            cm.replaceRange('', to, preEndPos, '+delete')\n            cm.replaceRange('', postEndPos, from, '+delete')\n          }\n        }\n      }\n    }\n  }\n}\n\nexport function insertText (cm, text, cursorEnd = 0) {\n  const cursor = cm.getCursor()\n  cm.replaceSelection(text, cursor, cursor)\n  cm.focus()\n  cm.setCursor({ line: cursor.line, ch: cursor.ch + cursorEnd })\n}\n\nexport function insertLink (cm, isImage) {\n  const cursor = cm.getCursor()\n  const ranges = cm.listSelections()\n  const linkEnd = '](https://)'\n  const symbol = (isImage) ? '![' : '['\n\n  for (let i = 0; i < ranges.length; i++) {\n    const range = ranges[i]\n    if (!range.empty()) {\n      const from = range.from()\n      const to = range.to()\n      const anchorIndex = editor.indexFromPos(ranges[i].anchor)\n      const headIndex = editor.indexFromPos(ranges[i].head)\n      let selection = cm.getRange(from, to)\n      selection = symbol + selection + linkEnd\n      cm.replaceRange(selection, from, to)\n      if (anchorIndex > headIndex) {\n        ranges[i].anchor.ch += symbol.length\n        ranges[i].head.ch += symbol.length\n      } else {\n        ranges[i].head.ch += symbol.length\n        ranges[i].anchor.ch += symbol.length\n      }\n      cm.setSelections(ranges)\n    } else {\n      cm.replaceRange(symbol + linkEnd, cursor, cursor)\n      cm.setCursor({ line: cursor.line, ch: cursor.ch + symbol.length + linkEnd.length })\n    }\n  }\n  cm.focus()\n}\n\nexport function insertHeader (cm) {\n  const cursor = cm.getCursor()\n  const startOfLine = { line: cursor.line, ch: 0 }\n  const startOfLineText = cm.getRange(startOfLine, { line: cursor.line, ch: 1 })\n  // See if it is already a header\n  if (startOfLineText === '#') {\n    cm.replaceRange('#', startOfLine, startOfLine)\n  } else {\n    cm.replaceRange('# ', startOfLine, startOfLine)\n  }\n  cm.focus()\n}\n\nexport function insertOnStartOfLines (cm, symbol) {\n  const cursor = cm.getCursor()\n  const ranges = cm.listSelections()\n\n  for (let i = 0; i < ranges.length; i++) {\n    const range = ranges[i]\n    if (!range.empty()) {\n      const from = range.from()\n      const to = range.to()\n      let selection = cm.getRange({ line: from.line, ch: 0 }, to)\n      selection = selection.replace(/\\n/g, '\\n' + symbol)\n      selection = symbol + selection\n      cm.replaceRange(selection, from, to)\n    } else {\n      cm.replaceRange(symbol, { line: cursor.line, ch: 0 }, { line: cursor.line, ch: 0 })\n    }\n  }\n  cm.setCursor({ line: cursor.line, ch: cursor.ch + symbol.length })\n  cm.focus()\n}\n"
  },
  {
    "path": "public/js/lib/markdown/utils.js",
    "content": "export function parseFenceCodeParams (lang) {\n  const attrMatch = lang.match(/{(.*)}/)\n  const params = {}\n  if (attrMatch && attrMatch.length >= 2) {\n    const attrs = attrMatch[1]\n    const paraMatch = attrs.match(/([#.](\\S+?)\\s)|((\\S+?)\\s*=\\s*(\"(.+?)\"|'(.+?)'|\\[[^\\]]*\\]|\\{[}]*\\}|(\\S+)))/g)\n    paraMatch && paraMatch.forEach(param => {\n      param = param.trim()\n      if (param[0] === '#') {\n        params.id = param.slice(1)\n      } else if (param[0] === '.') {\n        if (!params.class) params.class = []\n        params.class = params.class.concat(param.slice(1))\n      } else {\n        const offset = param.indexOf('=')\n        const id = param.substring(0, offset).trim().toLowerCase()\n        let val = param.substring(offset + 1).trim()\n        const valStart = val[0]\n        const valEnd = val[val.length - 1]\n        if (['\"', \"'\"].indexOf(valStart) !== -1 && ['\"', \"'\"].indexOf(valEnd) !== -1 && valStart === valEnd) {\n          val = val.substring(1, val.length - 1)\n        }\n        if (id === 'class') {\n          if (params.class) params.class = []\n          params.class = params.class.concat(val)\n        } else {\n          params[id] = val\n        }\n      }\n    })\n  }\n  return params\n}\n\nexport function serializeParamToAttribute (params) {\n  if (Object.getOwnPropertyNames(params).length === 0) {\n    return ''\n  } else {\n    return ` data-params=\"${escape(JSON.stringify(params))}\"`\n  }\n}\n\n/**\n * @param {HTMLElement} elem\n */\nexport function deserializeParamAttributeFromElement (elem) {\n  const params = elem.getAttribute('data-params')\n  if (params) {\n    return JSON.parse(unescape(params))\n  } else {\n    return {}\n  }\n}\n"
  },
  {
    "path": "public/js/lib/modeType.js",
    "content": "export default {\n  edit: {\n    name: 'edit'\n  },\n  view: {\n    name: 'view'\n  },\n  both: {\n    name: 'both'\n  }\n}\n"
  },
  {
    "path": "public/js/lib/renderer/csvpreview.js",
    "content": "import Papa from 'papaparse'\nimport escapeHTML from 'lodash/escape'\n\nconst safeParse = d => {\n  try {\n    return JSON.parse(d)\n  } catch (err) {\n    return d\n  }\n}\n\nexport function renderCSVPreview (csv, options = {}, attr = '') {\n  const opt = Object.keys(options).reduce((acc, key) => {\n    return Object.assign(acc, {\n      [key]: safeParse(options[key])\n    })\n  }, {})\n\n  const results = Papa.parse(csv.trim(), opt)\n\n  if (opt.header) {\n    const fields = results.meta.fields\n    return `<table ${attr}>\n      <thead>\n        <tr>\n          ${fields.map(f => `<th>${escapeHTML(f)}</th>`).join('')}\n        </tr>\n      </thead>\n      <tbody>\n        ${results.data.map(d => `<tr>\n          ${fields.map(f => `<td>${escapeHTML(d[f])}</td>`).join('')}\n        </tr>`).join('')}\n      </tbody>\n    </table>`\n  } else {\n    return `<table ${attr}>\n      <tbody>\n        ${results.data.map(d => `<tr>\n          ${d.map(f => `<td>${escapeHTML(f)}</td>`).join('')}\n        </tr>`).join('')}\n      </tbody>\n    </table>`\n  }\n}\n"
  },
  {
    "path": "public/js/lib/renderer/fretboard/css/i.css",
    "content": "/* -- GENERAL TYPOGRAPHY -- */\n.fretTitle {\n  color: #555;\n  text-align: center;\n  font-family: \"Helvetica Neue\", sans-serif;\n  line-height: 1.4;\n  font-size: 1.6em;\n  margin: 10px 0 10px 0;\n  font-weight: 900;\n  padding: 5px;\n}\n\nsection {\n  padding: 20px;\n}\n\n.content {\n  max-width: 960px;\n  margin: auto;\n}\n\n/* Fretboard Container/Wrapper */\n\n.fretContainer, .fretContainer_h {\n  outline: solid 1px #eeee;\n  margin: 0 auto;\n  padding: 15px 0;\n}\n\n.fretContainer {\n  width: 320px;\n}\n\n.fretContainer_h {\n  max-width: 400px;\n}\n\n@media all and (max-width: 400px) {\n  .fretContainer_h {\n    max-width: 288px;\n  }\n}\n@media all and (max-width: 420px) {\n  .fretContainer {\n    max-width: 220px;\n  }\n}\n.svg_wrapper {\n  background-color: #fff;\n  position: relative;\n  height: 0;\n}\n\n.svg_wrapper svg.fretboard_bg {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 0;\n}\n\n.svg_wrapper .cells {\n  width: 100%;\n  height: 100%;\n  position: absolute;\n  top: 0;\n  left: 0;\n}\n\n.svg_wrapper.v4 {\n  padding-top: 91.6666666667%;\n}\n\n.svg_wrapper.v5 {\n  padding-top: 106.9444444444%;\n}\n\n.svg_wrapper.v7 {\n  padding-top: 137.5%;\n}\n\n.svg_wrapper.v9 {\n  padding-top: 168.0555555556%;\n}\n\n.svg_wrapper.v12 {\n  padding-top: 213.8888888889%;\n}\n\n.svg_wrapper.v15 {\n  padding-top: 259.7222222222%;\n}\n\n.svg_wrapper.v .cell svg {\n  width: 12.5%;\n  float: left;\n  display: block;\n}\n\n.svg_wrapper.v4 .cell svg {\n  height: 16.6666666667%;\n}\n\n.svg_wrapper.v5 .cell svg {\n  height: 14.2857142857%;\n}\n\n.svg_wrapper.v7 .cell svg {\n  height: 11.1111111111%;\n}\n\n.svg_wrapper.v9 .cell svg {\n  height: 9.0909090909%;\n}\n\n.svg_wrapper.v12 .cell svg {\n  height: 7.1428571429%;\n}\n\n.svg_wrapper.v15 .cell svg {\n  height: 5.8823529412%;\n}\n\n.svg_wrapper.h5 {\n  padding-top: 85.7142857143%;\n}\n\n.svg_wrapper.h6 {\n  padding-top: 75%;\n}\n\n.svg_wrapper.h7 {\n  padding-top: 72.7272727273%;\n}\n\n.svg_wrapper.h .cell svg {\n  height: 12.5%;\n  float: left;\n  display: block;\n  z-index: 2;\n}\n\n.svg_wrapper.h5 .cell svg {\n  width: 14.2857142857%;\n}\n\n.svg_wrapper.h6 .cell svg {\n  width: 12.5%;\n}\n\n.svg_wrapper.h7 .cell svg {\n  width: 12.1212121212%;\n}\n\n/* Fretboard Element Styles */\n.cell.dot .fretb_dot {\n  fill: #27a9e1;\n}\n\n.cell.dot.root .fretb_dot {\n  fill: #F05A28;\n}\n\n.cell.dot.faded .fretb_dot {\n  opacity: 0.25;\n}\n\n.fretboard_bg .fret_bg rect {\n  fill: #fff;\n}\n\n.fretboard_bg .frets rect {\n  fill: #ddd;\n}\n\n.fretboard_bg .nut rect {\n  fill: #6e6e6e;\n}\n\n.fretboard_bg .strings rect {\n  fill: #6e6e6e;\n}\n\n.svg_wrapper.noNut .fretboard_bg .nut rect {\n  fill: none;\n}\n\n/*# sourceMappingURL=i.css.map */\n\n.markdown-body pre.fretboard {\n  background-color: transparent;\n}\n"
  },
  {
    "path": "public/js/lib/renderer/fretboard/fretboard.js",
    "content": "/* global $ */\nimport escapeHTML from 'lodash/escape'\n\nimport './css/i.css'\nimport dotEmpty from './svg/dotEmpty.svg'\nimport dotEmptyH from './svg/dotEmpty_h.svg'\nimport dot from './svg/dot.svg'\nimport dotH from './svg/dot_h.svg'\nimport dotWideLeft from './svg/dotWideLeft.svg'\nimport dotWideRight from './svg/dotWideRight.svg'\nimport dotWideMiddle from './svg/dotWideMiddle.svg'\nimport stringO from './svg/string_o.svg'\nimport stringX from './svg/string_x.svg'\n\nconst switchListV = {\n  o: `<div class='cell dot'>${dot}</div>`,\n  '*': `<div class='cell dot faded'>${dot}</div>`,\n  '(': `<div class='cell'>${dotWideLeft}</div>`,\n  ')': `<div class='cell'>${dotWideRight}</div>`,\n  '=': `<div class='cell'>${dotWideMiddle}</div>`,\n  '^': `<div class='cell'>${stringO}</div>`,\n  x: `<div class='cell'>${stringX}</div>`,\n  '|': `<div class='cell empty'>${dotEmpty}</div>`,\n  ' ': `<div class='cell empty'>${dotEmpty}</div>`,\n  '\\n': `<div class='cell empty'>${dotEmpty}</div>`\n}\nconst switchListH = {\n  o: `<div class='cell dot'>${dotH}</div>`,\n  '*': `<div class='cell dot faded'>${dotH}</div>`,\n  O: `<div class='cell dot root'>${dotH}</div>`,\n  '-': `<div class='cell empty'>${dotEmptyH}</div>`,\n  ' ': `<div class='cell empty'>${dotEmptyH}</div>`,\n  '\\n': `<div class='cell empty'>${dotEmptyH}</div><div class='cell empty'>${dotEmptyH}</div>`\n}\n\nexport const renderFretBoard = (content, { title: fretTitle = '', type = '' }) => {\n  const isVertical = !(typeof type[0] === 'string' && type[0].startsWith('h'))\n\n  const containerClass = isVertical ? 'fretContainer' : 'fretContainer_h'\n\n  const [fretType, nutOption] = type.split(' ')\n  const fretboardHTML = $(`<div class=\"${containerClass}\"></div>`)\n\n  if (fretTitle) {\n    $(fretboardHTML).append(`<div class=\"fretTitle\">${escapeHTML(fretTitle)}</div>`)\n  }\n\n  // create fretboard background HTML\n  const fretbOrientation = isVertical ? 'vert' : 'horiz'\n  const fretbLen = fretType && fretType.substring(1)\n  const fretbClass = fretType && fretType[0] + ' ' + fretType\n  const nut = nutOption === 'noNut' ? 'noNut' : ''\n\n  const svgHTML = $(`<div class=\"svg_wrapper ${fretbClass} ${nut}\"></div>`)\n  const fretbBg = require(`./svg/fretb_${fretbOrientation}_${fretbLen}.svg`)\n\n  $(svgHTML).append($(fretbBg))\n\n  // create cells HTML\n  const cellsHTML = $('<div class=\"cells\"></div>')\n  let switchList = {}\n  if (isVertical) {\n    switchList = switchListV\n  } else {\n    // calculate position\n    const emptyFill = new Array(Number(fretbLen) + 3).fill(' ').join('')\n    content = `${emptyFill}${content}`\n\n    switchList = switchListH\n  }\n\n  const contentCell = content && content.split('')\n  // Go through each ASCII character...\n  const numArray = [...Array(10).keys()].slice(1)\n  contentCell && contentCell.forEach(char => {\n    if (numArray.toString().indexOf(char) !== -1) {\n      const numType = isVertical ? '' : '_h'\n      const numSvg = require(`./svg/number${char}${numType}.svg`)\n      cellsHTML.append(`<div class='cell empty'>${numSvg}</div>`)\n    } else if (typeof switchList[char] !== 'undefined') {\n      cellsHTML.append(switchList[char])\n    }\n  })\n\n  $(svgHTML).append(cellsHTML)\n  $(fretboardHTML).append(svgHTML)\n\n  return fretboardHTML[0].outerHTML\n}\n"
  },
  {
    "path": "public/js/lib/renderer/lightbox/index.js",
    "content": "import './lightbox.css'\nimport escape from 'lodash/escape'\n\nlet images = []\n/** @type {HTMLImageElement} */\nlet currentImage = null\nlet currentIndexIndex = 0\n\nlet hideContainer\n\nfunction findOrCreateLightboxContainer () {\n  const lightboxContainerSelector = '.lightbox-container'\n\n  let lightBoxContainer = document.querySelector(lightboxContainerSelector)\n  if (!lightBoxContainer) {\n    lightBoxContainer = document.createElement('div')\n    lightBoxContainer.className = 'lightbox-container'\n\n    lightBoxContainer.innerHTML = `\n      <i class=\"fa fa-chevron-left lightbox-control-previous\" aria-hidden=\"true\"></i>\n      <i class=\"fa fa-chevron-right lightbox-control-next\" aria-hidden=\"true\"></i>\n      <i class=\"fa fa-close lightbox-control-close\" aria-hidden=\"true\"></i>\n\n      <div class=\"lightbox-inner\">\n      </div>\n    `\n\n    addImageZoomListener(lightBoxContainer)\n\n    hideContainer = () => {\n      lightBoxContainer.classList.remove('show')\n      document.body.classList.remove('no-scroll')\n      currentImage = null\n    }\n\n    lightBoxContainer.querySelector('.lightbox-control-previous').addEventListener('click', (e) => {\n      e.stopPropagation()\n      switchImage(-1)\n    })\n    lightBoxContainer.querySelector('.lightbox-control-next').addEventListener('click', (e) => {\n      e.stopPropagation()\n      switchImage(1)\n    })\n    lightBoxContainer.querySelector('.lightbox-control-close').addEventListener('click', (e) => {\n      e.stopPropagation()\n      hideContainer()\n    })\n    lightBoxContainer.addEventListener('click', (e) => {\n      e.stopPropagation()\n      hideContainer()\n    })\n\n    document.body.appendChild(lightBoxContainer)\n  }\n\n  return lightBoxContainer\n}\n\nfunction switchImage (dir) {\n  const lightBoxContainer = findOrCreateLightboxContainer()\n\n  currentIndexIndex += dir\n  if (currentIndexIndex >= images.length) {\n    currentIndexIndex = 0\n  } else if (currentIndexIndex < 0) {\n    currentIndexIndex = images.length - 1\n  }\n\n  const img = images[currentIndexIndex]\n\n  setImageInner(img, lightBoxContainer)\n}\n\nfunction setImageInner (img, lightBoxContainer) {\n  const src = img.getAttribute('src')\n  const alt = img.getAttribute('alt')\n\n  lightBoxContainer.querySelector('.lightbox-inner').innerHTML = `<img src=\"${escape(src)}\" alt=\"${escape(alt)}\" draggable=\"false\">`\n  addImageDragListener(lightBoxContainer.querySelector('.lightbox-inner img'))\n}\n\nfunction onClickImage (img) {\n  const lightBoxContainer = findOrCreateLightboxContainer()\n\n  setImageInner(img, lightBoxContainer)\n\n  lightBoxContainer.classList.add('show')\n  document.body.classList.add('no-scroll')\n\n  currentImage = img\n  updateLightboxImages()\n}\n\nfunction updateLightboxImages () {\n  images = [...document.querySelectorAll('.markdown-body img.md-image')]\n\n  if (currentImage) {\n    currentIndexIndex = images.findIndex(image => image === currentImage)\n  }\n}\n\nfunction addImageZoomListener (container) {\n  container.addEventListener('wheel', function (e) {\n    // normalize scroll position as percentage\n    e.preventDefault()\n\n    /** @type {HTMLImageElement} */\n    const image = container.querySelector('img')\n\n    if (!image) {\n      return\n    }\n\n    let scale = image.getBoundingClientRect().width / image.offsetWidth\n    scale += e.deltaY * -0.01\n\n    // Restrict scale\n    scale = Math.min(Math.max(0.125, scale), 4)\n\n    var transformValue = `scale(${scale})`\n\n    image.style.WebkitTransform = transformValue\n    image.style.MozTransform = transformValue\n    image.style.OTransform = transformValue\n    image.style.transform = transformValue\n  })\n}\n\n/**\n * @param {HTMLImageElement} image\n */\nfunction addImageDragListener (image) {\n  let moved = false\n  let pos = []\n\n  const container = findOrCreateLightboxContainer()\n  const inner = container.querySelector('.lightbox-inner')\n\n  const onMouseDown = (evt) => {\n    moved = true\n\n    const { left, top } = image.getBoundingClientRect()\n\n    pos = [\n      evt.pageX - left,\n      evt.pageY - top\n    ]\n  }\n  image.addEventListener('mousedown', onMouseDown)\n  inner.addEventListener('mousedown', onMouseDown)\n\n  const onMouseMove = (evt) => {\n    if (!moved) {\n      return\n    }\n\n    image.style.left = `${evt.pageX - pos[0]}px`\n    image.style.top = `${evt.pageY - pos[1]}px`\n    image.style.position = 'absolute'\n  }\n  image.addEventListener('mousemove', onMouseMove)\n  inner.addEventListener('mousemove', onMouseMove)\n\n  const onMouseUp = () => {\n    moved = false\n    pos = []\n  }\n  image.addEventListener('mouseup', onMouseUp)\n  inner.addEventListener('mouseup', onMouseUp)\n\n  inner.addEventListener('click', (e) => {\n    e.stopPropagation()\n  })\n  image.addEventListener('click', (e) => {\n    e.stopPropagation()\n  })\n}\n\nconst init = () => {\n  const markdownBody = document.querySelector('.markdown-body')\n  if (!markdownBody) {\n    return\n  }\n\n  markdownBody.addEventListener('click', function (e) {\n    const img = e.target\n    if (img.nodeName === 'IMG' && img.classList.contains('md-image')) {\n      onClickImage(img)\n      e.stopPropagation()\n    }\n  })\n\n  window.addEventListener('keydown', function (e) {\n    if (!currentImage) {\n      return\n    }\n\n    if (e.key === 'ArrowRight') {\n      switchImage(1)\n      e.stopPropagation()\n    } else if (e.key === 'ArrowLeft') {\n      switchImage(-1)\n      e.stopPropagation()\n    } else if (e.key === 'Escape') {\n      if (hideContainer) {\n        hideContainer()\n        e.stopPropagation()\n      }\n    }\n  })\n}\n\ninit()\n"
  },
  {
    "path": "public/js/lib/renderer/lightbox/lightbox.css",
    "content": ".lightbox-container.show {\n  display: flex !important;\n}\n\n.lightbox-container {\n  display: none;\n\n  position: fixed;\n  z-index: 99999;\n  background-color: rgba(255, 255, 255, 0.8);\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n\n  justify-content: center;\n  align-items: center;\n  padding: 0px 40px;\n}\n\n.night .lightbox-container {\n  background-color: rgba(47, 47, 47, 0.8);;\n}\n\n.lightbox-container .lightbox-control-previous,\n.lightbox-container .lightbox-control-next,\n.lightbox-container .lightbox-control-close {\n  position: absolute;\n  width: 40px;\n  height: 40px;\n  color: rgba(65, 65, 65, 0.8);\n  text-align: center;\n  cursor: pointer;\n  user-select: none;\n  font-size: 25px;\n  z-index: 1;\n}\n\n.night .lightbox-container .lightbox-control-previous,\n.night .lightbox-container .lightbox-control-next,\n.night .lightbox-container .lightbox-control-close {\n  color: rgba(255, 255, 255, 0.5);\n}\n\n.lightbox-container .lightbox-control-previous:hover,\n.lightbox-container .lightbox-control-next:hover,\n.lightbox-container .lightbox-control-close:hover {\n  color: rgba(130, 130, 130, 0.78);\n}\n\n.night .lightbox-container .lightbox-control-previous:hover,\n.night .lightbox-container .lightbox-control-next:hover,\n.night .lightbox-container .lightbox-control-close:hover {\n  color: rgba(255, 255, 255, 0.8);\n}\n\n.lightbox-container .lightbox-control-next,\n.lightbox-container .lightbox-control-previous {\n  top: calc(50% - 10px);\n}\n\n.lightbox-container .lightbox-control-previous {\n  left: 0;\n}\n\n.lightbox-container .lightbox-control-next {\n  right: 0;\n}\n\n.lightbox-container .lightbox-control-close {\n  top: 10px;\n  right: 10px;\n}\n\n.lightbox-container .lightbox-inner {\n  width: 100%;\n  height: 100%;\n  cursor: move;\n\n  display: -webkit-box;\n  display: -webkit-flex;\n  display: -moz-box;\n  display: -ms-flexbox;\n\n  display: flex;\n  -webkit-box-align: center;\n  -webkit-align-items: center;\n     -moz-box-align: center;\n      -ms-flex-align: center;\n          align-items: center;\n  -webkit-box-pack: center;\n  -webkit-justify-content: center;\n     -moz-box-pack: center;\n      -ms-flex-pack: center;\n          justify-content: center;\n}\n\n.lightbox-container .lightbox-inner img {\n  max-width: 100%;\n  cursor: move;\n\n  transform-origin: 0 0;\n  -moz-transform-origin: 0 0;\n  -webkit-transform-origin: 0 0;\n  -ms-transform-origin: 0 0;\n  -o-transform-origin: 0 0;\n}\n\n.markdown-body img.md-image {\n  cursor: zoom-in;\n}\n\nbody.no-scroll {\n  overflow: hidden;\n}\n"
  },
  {
    "path": "public/js/lib/syncscroll.js",
    "content": "/* eslint-env browser, jquery */\n/* global _ */\n// Inject line numbers for sync scroll.\n\nimport markdownitContainer from 'markdown-it-container'\n\nimport { md } from '../extra'\nimport modeType from './modeType'\nimport appState from './appState'\nimport { renderCSVPreview } from './renderer/csvpreview'\nimport { parseFenceCodeParams } from './markdown/utils'\n\nfunction addPart (tokens, idx) {\n  if (tokens[idx].map && tokens[idx].level === 0) {\n    const startline = tokens[idx].map[0] + 1\n    const endline = tokens[idx].map[1]\n    tokens[idx].attrJoin('class', 'part')\n    tokens[idx].attrJoin('data-startline', startline)\n    tokens[idx].attrJoin('data-endline', endline)\n  }\n}\n\nmd.renderer.rules.blockquote_open = function (tokens, idx, options, env, self) {\n  tokens[idx].attrJoin('class', 'raw')\n  addPart(tokens, idx)\n  return self.renderToken(...arguments)\n}\nmd.renderer.rules.table_open = function (tokens, idx, options, env, self) {\n  addPart(tokens, idx)\n  return self.renderToken(...arguments)\n}\nconst defaultImageRender = md.renderer.rules.image\nmd.renderer.rules.image = function (tokens, idx, options, env, self) {\n  tokens[idx].attrJoin('class', 'md-image')\n  return defaultImageRender(...arguments)\n}\nmd.renderer.rules.bullet_list_open = function (tokens, idx, options, env, self) {\n  addPart(tokens, idx)\n  return self.renderToken(...arguments)\n}\nmd.renderer.rules.list_item_open = function (tokens, idx, options, env, self) {\n  tokens[idx].attrJoin('class', 'raw')\n  if (tokens[idx].map) {\n    const startline = tokens[idx].map[0] + 1\n    const endline = tokens[idx].map[1]\n    tokens[idx].attrJoin('data-startline', startline)\n    tokens[idx].attrJoin('data-endline', endline)\n  }\n  return self.renderToken(...arguments)\n}\nmd.renderer.rules.ordered_list_open = function (tokens, idx, options, env, self) {\n  addPart(tokens, idx)\n  return self.renderToken(...arguments)\n}\nmd.renderer.rules.link_open = function (tokens, idx, options, env, self) {\n  addPart(tokens, idx)\n  return self.renderToken(...arguments)\n}\nmd.renderer.rules.paragraph_open = function (tokens, idx, options, env, self) {\n  addPart(tokens, idx)\n  return self.renderToken(...arguments)\n}\nmd.renderer.rules.heading_open = function (tokens, idx, options, env, self) {\n  tokens[idx].attrJoin('class', 'raw')\n  addPart(tokens, idx)\n  return self.renderToken(...arguments)\n}\nmd.renderer.rules.fence = (tokens, idx, options, env, self) => {\n  const token = tokens[idx]\n  const info = token.info ? md.utils.unescapeAll(token.info).trim() : ''\n  let langName = ''\n  let highlighted\n\n  if (info) {\n    langName = info.split(/\\s+/g)[0]\n\n    if (langName === 'csvpreview') {\n      const params = parseFenceCodeParams(info)\n      let attr = ''\n      if (tokens[idx].map && tokens[idx].level === 0) {\n        const startline = tokens[idx].map[0] + 1\n        const endline = tokens[idx].map[1]\n        attr = `class=\"part\" data-startline=\"${startline}\" data-endline=\"${endline}\"`\n      }\n      return renderCSVPreview(token.content, params, attr)\n    }\n\n    if (/!$/.test(info)) token.attrJoin('class', 'wrap')\n    token.attrJoin('class', options.langPrefix + langName.replace(/=$|=\\d+$|=\\+$|!$|=!/, ''))\n    token.attrJoin('class', 'hljs')\n    token.attrJoin('class', 'raw')\n  }\n\n  if (options.highlight) {\n    highlighted = options.highlight(token.content, info) || md.utils.escapeHtml(token.content)\n  } else {\n    highlighted = md.utils.escapeHtml(token.content)\n  }\n\n  if (highlighted.indexOf('<pre') === 0) {\n    return `${highlighted}\\n`\n  }\n\n  if (tokens[idx].map && tokens[idx].level === 0) {\n    const startline = tokens[idx].map[0] + 1\n    const endline = tokens[idx].map[1]\n    return `<pre class=\"part\" data-startline=\"${startline}\" data-endline=\"${endline}\"><code${self.renderAttrs(token)}>${highlighted}</code></pre>\\n`\n  }\n\n  return `<pre><code${self.renderAttrs(token)}>${highlighted}</code></pre>\\n`\n}\nmd.renderer.rules.code_block = (tokens, idx, options, env, self) => {\n  if (tokens[idx].map && tokens[idx].level === 0) {\n    const startline = tokens[idx].map[0] + 1\n    const endline = tokens[idx].map[1]\n    return `<pre class=\"part\" data-startline=\"${startline}\" data-endline=\"${endline}\"><code>${md.utils.escapeHtml(tokens[idx].content)}</code></pre>\\n`\n  }\n  return `<pre><code>${md.utils.escapeHtml(tokens[idx].content)}</code></pre>\\n`\n}\nfunction renderContainer (tokens, idx, options, env, self) {\n  tokens[idx].attrJoin('role', 'alert')\n  tokens[idx].attrJoin('class', 'alert')\n  tokens[idx].attrJoin('class', `alert-${tokens[idx].info.trim()}`)\n  addPart(tokens, idx)\n  return self.renderToken(...arguments)\n}\n\nmd.use(markdownitContainer, 'success', { render: renderContainer })\nmd.use(markdownitContainer, 'info', { render: renderContainer })\nmd.use(markdownitContainer, 'warning', { render: renderContainer })\nmd.use(markdownitContainer, 'danger', { render: renderContainer })\nmd.use(markdownitContainer, 'spoiler', {\n  validate: function (params) {\n    return params.trim().match(/^spoiler(\\s+.*)?$/)\n  },\n  render: function (tokens, idx) {\n    const m = tokens[idx].info.trim().match(/^spoiler(\\s+.*)?$/)\n\n    if (tokens[idx].nesting === 1) {\n      // opening tag\n      const startline = tokens[idx].map[0] + 1\n      const endline = tokens[idx].map[1]\n\n      const partClass = `class=\"part raw\" data-startline=\"${startline}\" data-endline=\"${endline}\"`\n      const summary = m[1] && m[1].trim()\n      if (summary) {\n        return `<details ${partClass}><summary>${md.renderInline(summary)}</summary>\\n`\n      } else {\n        return `<details ${partClass}>\\n`\n      }\n    } else {\n      // closing tag\n      return '</details>\\n'\n    }\n  }\n})\n\nwindow.preventSyncScrollToEdit = false\nwindow.preventSyncScrollToView = false\n\nconst editScrollThrottle = 5\nconst viewScrollThrottle = 5\nconst buildMapThrottle = 100\n\nlet viewScrolling = false\nlet editScrolling = false\n\nlet editArea = null\nlet viewArea = null\nlet markdownArea = null\n\nlet editor\n\nexport function setupSyncAreas (edit, view, markdown, _editor) {\n  editArea = edit\n  viewArea = view\n  markdownArea = markdown\n\n  editor = _editor\n\n  editArea.on('scroll', _.throttle(syncScrollToView, editScrollThrottle))\n  viewArea.on('scroll', _.throttle(syncScrollToEdit, viewScrollThrottle))\n}\n\nlet scrollMap, lineHeightMap, viewTop, viewBottom\n\nexport function clearMap () {\n  scrollMap = null\n  lineHeightMap = null\n  viewTop = null\n  viewBottom = null\n}\nwindow.viewAjaxCallback = clearMap\n\nconst buildMap = _.throttle(buildMapInner, buildMapThrottle)\n\n// Build offsets for each line (lines can be wrapped)\n// That's a bit dirty to process each line everytime, but ok for demo.\n// Optimizations are required only for big texts.\nfunction buildMapInner (callback) {\n  if (!viewArea || !markdownArea) return\n  let i, pos, a, b, acc\n\n  const offset = viewArea.scrollTop() - viewArea.offset().top\n  const _scrollMap = []\n  const nonEmptyList = []\n  const _lineHeightMap = []\n  viewTop = 0\n  viewBottom = viewArea[0].scrollHeight - viewArea.height()\n\n  acc = 0\n  const lines = editor.getValue().split('\\n')\n  const lineHeight = editor.defaultTextHeight()\n  for (i = 0; i < lines.length; i++) {\n    const str = lines[i]\n\n    _lineHeightMap.push(acc)\n\n    if (str.length === 0) {\n      acc++\n      continue\n    }\n\n    const h = editor.heightAtLine(i + 1) - editor.heightAtLine(i)\n    acc += Math.round(h / lineHeight)\n  }\n  _lineHeightMap.push(acc)\n  const linesCount = acc\n\n  for (i = 0; i < linesCount; i++) {\n    _scrollMap.push(-1)\n  }\n\n  nonEmptyList.push(0)\n  // make the first line go top\n  _scrollMap[0] = viewTop\n\n  const parts = markdownArea.find('.part').toArray()\n  for (i = 0; i < parts.length; i++) {\n    const $el = $(parts[i])\n    let t = $el.attr('data-startline') - 1\n    if (t === '') {\n      return\n    }\n    t = _lineHeightMap[t]\n    if (t !== 0 && t !== nonEmptyList[nonEmptyList.length - 1]) {\n      nonEmptyList.push(t)\n    }\n    _scrollMap[t] = Math.round($el.offset().top + offset - 10)\n  }\n\n  nonEmptyList.push(linesCount)\n  _scrollMap[linesCount] = viewArea[0].scrollHeight\n\n  pos = 0\n  for (i = 1; i < linesCount; i++) {\n    if (_scrollMap[i] !== -1) {\n      pos++\n      continue\n    }\n\n    a = nonEmptyList[pos]\n    b = nonEmptyList[pos + 1]\n    _scrollMap[i] = Math.round((_scrollMap[b] * (i - a) + _scrollMap[a] * (b - i)) / (b - a))\n  }\n\n  _scrollMap[0] = 0\n\n  scrollMap = _scrollMap\n  lineHeightMap = _lineHeightMap\n\n  if (window.loaded && callback) callback()\n}\n\n// sync view scroll progress to edit\nlet viewScrollingTimer = null\n\nexport function syncScrollToEdit (event, preventAnimate) {\n  if (appState.currentMode !== modeType.both || !appState.syncscroll || !editArea) return\n  if (window.preventSyncScrollToEdit) {\n    if (typeof window.preventSyncScrollToEdit === 'number') {\n      window.preventSyncScrollToEdit--\n    } else {\n      window.preventSyncScrollToEdit = false\n    }\n    return\n  }\n  if (!scrollMap || !lineHeightMap) {\n    buildMap(() => {\n      syncScrollToEdit(event, preventAnimate)\n    })\n    return\n  }\n  if (editScrolling) return\n\n  const scrollTop = viewArea[0].scrollTop\n  let lineIndex = 0\n  for (let i = 0, l = scrollMap.length; i < l; i++) {\n    if (scrollMap[i] > scrollTop) {\n      break\n    } else {\n      lineIndex = i\n    }\n  }\n  let lineNo = 0\n  let lineDiff = 0\n  for (let i = 0, l = lineHeightMap.length; i < l; i++) {\n    if (lineHeightMap[i] > lineIndex) {\n      break\n    } else {\n      lineNo = lineHeightMap[i]\n      lineDiff = lineHeightMap[i + 1] - lineNo\n    }\n  }\n\n  let posTo = 0\n  let topDiffPercent = 0\n  let posToNextDiff = 0\n  const scrollInfo = editor.getScrollInfo()\n  const textHeight = editor.defaultTextHeight()\n  const preLastLineHeight = scrollInfo.height - scrollInfo.clientHeight - textHeight\n  const preLastLineNo = Math.round(preLastLineHeight / textHeight)\n  const preLastLinePos = scrollMap[preLastLineNo]\n\n  if (scrollInfo.height > scrollInfo.clientHeight && scrollTop >= preLastLinePos) {\n    posTo = preLastLineHeight\n    topDiffPercent = (scrollTop - preLastLinePos) / (viewBottom - preLastLinePos)\n    posToNextDiff = textHeight * topDiffPercent\n    posTo += Math.ceil(posToNextDiff)\n  } else {\n    posTo = lineNo * textHeight\n    topDiffPercent = (scrollTop - scrollMap[lineNo]) / (scrollMap[lineNo + lineDiff] - scrollMap[lineNo])\n    posToNextDiff = textHeight * lineDiff * topDiffPercent\n    posTo += Math.ceil(posToNextDiff)\n  }\n\n  if (preventAnimate) {\n    editArea.scrollTop(posTo)\n  } else {\n    const posDiff = Math.abs(scrollInfo.top - posTo)\n    var duration = posDiff / 50\n    duration = duration >= 100 ? duration : 100\n    editArea.stop(true, true).animate({\n      scrollTop: posTo\n    }, duration, 'linear')\n  }\n\n  viewScrolling = true\n  clearTimeout(viewScrollingTimer)\n  viewScrollingTimer = setTimeout(viewScrollingTimeoutInner, duration * 1.5)\n}\n\nfunction viewScrollingTimeoutInner () {\n  viewScrolling = false\n}\n\n// sync edit scroll progress to view\nlet editScrollingTimer = null\n\nexport function syncScrollToView (event, preventAnimate) {\n  if (appState.currentMode !== modeType.both || !appState.syncscroll || !viewArea) return\n  if (window.preventSyncScrollToView) {\n    if (typeof preventSyncScrollToView === 'number') {\n      window.preventSyncScrollToView--\n    } else {\n      window.preventSyncScrollToView = false\n    }\n    return\n  }\n  if (!scrollMap || !lineHeightMap) {\n    buildMap(() => {\n      syncScrollToView(event, preventAnimate)\n    })\n    return\n  }\n  if (viewScrolling) return\n\n  let posTo\n  let topDiffPercent, posToNextDiff\n  const scrollInfo = editor.getScrollInfo()\n  const textHeight = editor.defaultTextHeight()\n  const lineNo = Math.floor(scrollInfo.top / textHeight)\n  // if reach the last line, will start lerp to the bottom\n  const diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight)\n  if (scrollInfo.height > scrollInfo.clientHeight && diffToBottom > 0) {\n    topDiffPercent = diffToBottom / textHeight\n    posTo = scrollMap[lineNo + 1]\n    posToNextDiff = (viewBottom - posTo) * topDiffPercent\n    posTo += Math.floor(posToNextDiff)\n  } else {\n    topDiffPercent = (scrollInfo.top % textHeight) / textHeight\n    posTo = scrollMap[lineNo]\n    posToNextDiff = (scrollMap[lineNo + 1] - posTo) * topDiffPercent\n    posTo += Math.floor(posToNextDiff)\n  }\n\n  if (preventAnimate) {\n    viewArea.scrollTop(posTo)\n  } else {\n    const posDiff = Math.abs(viewArea.scrollTop() - posTo)\n    var duration = posDiff / 50\n    duration = duration >= 100 ? duration : 100\n    viewArea.stop(true, true).animate({\n      scrollTop: posTo\n    }, duration, 'linear')\n  }\n\n  editScrolling = true\n  clearTimeout(editScrollingTimer)\n  editScrollingTimer = setTimeout(editScrollingTimeoutInner, duration * 1.5)\n}\n\nfunction editScrollingTimeoutInner () {\n  editScrolling = false\n}\n"
  },
  {
    "path": "public/js/locale.js",
    "content": "/* eslint-env browser, jquery */\n/* global Cookies */\n\nvar lang = 'en'\nvar userLang = navigator.language || navigator.userLanguage\nvar userLangCode = userLang.split('-')[0]\nvar locale = $('.ui-locale')\nvar supportLangs = []\n$('.ui-locale option').each(function () {\n  supportLangs.push($(this).val())\n})\nif (Cookies.get('locale')) {\n  lang = Cookies.get('locale')\n  if (lang === 'zh') {\n    lang = 'zh-TW'\n  }\n} else if (supportLangs.indexOf(userLang) !== -1) {\n  lang = supportLangs[supportLangs.indexOf(userLang)]\n} else if (supportLangs.indexOf(userLangCode) !== -1) {\n  lang = supportLangs[supportLangs.indexOf(userLangCode)]\n}\n\nlocale.val(lang)\n$('select.ui-locale option[value=\"' + lang + '\"]').attr('selected', 'selected')\n\nlocale.change(function () {\n  Cookies.set('locale', $(this).val(), {\n    expires: 365\n  })\n  window.location.reload()\n})\n"
  },
  {
    "path": "public/js/mathjax-config-extra.js",
    "content": "window.MathJax = {\n  messageStyle: 'none',\n  skipStartupTypeset: true,\n  tex2jax: {\n    inlineMath: [['$', '$'], ['\\\\(', '\\\\)']],\n    processEscapes: true\n  },\n  TeX: {\n    extensions: ['mhchem.js']\n  }\n}\n"
  },
  {
    "path": "public/js/pretty.js",
    "content": "/* eslint-env browser, jquery */\n/* global refreshView */\nimport RevealMarkdown from './reveal-markdown'\n\nimport {\n  autoLinkify,\n  deduplicatedHeaderId,\n  removeDOMEvents,\n  finishView,\n  generateToc,\n  md,\n  parseMeta,\n  postProcess,\n  renderTOC,\n  scrollToHash,\n  smoothHashScroll,\n  updateLastChange\n} from './extra'\n\nimport { preventXSS } from './render'\n\nrequire('../css/extra.css')\nrequire('../css/slide-preview.css')\nrequire('../css/site.css')\n\nrequire('highlight.js/styles/github-gist.css')\n\nconst markdown = $('#doc.markdown-body')\nconst text = markdown.text()\nconst lastMeta = md.meta\nmd.meta = {}\ndelete md.metaError\nlet rendered = md.render(text)\nif (md.meta.type && md.meta.type === 'slide') {\n  const slideOptions = {\n    separator: '^(\\r\\n?|\\n)---(\\r\\n?|\\n)$',\n    verticalSeparator: '^(\\r\\n?|\\n)----(\\r\\n?|\\n)$'\n  }\n  const slides = RevealMarkdown.slidify(text, slideOptions)\n  markdown.html(slides)\n  RevealMarkdown.initialize()\n  // prevent XSS\n  markdown.html(preventXSS(markdown.html()))\n  markdown.addClass('slides')\n} else {\n  if (lastMeta.type && lastMeta.type === 'slide') {\n    refreshView()\n    markdown.removeClass('slides')\n  }\n  // only render again when meta changed\n  if (JSON.stringify(md.meta) !== JSON.stringify(lastMeta)) {\n    parseMeta(md, null, markdown, $('#ui-toc'), $('#ui-toc-affix'))\n    rendered = md.render(text)\n  }\n  // prevent XSS\n  rendered = preventXSS(rendered)\n  const result = postProcess(rendered)\n  markdown.html(result.html())\n}\n$(document.body).show()\n\nremoveDOMEvents(markdown)\nfinishView(markdown)\nautoLinkify(markdown)\ndeduplicatedHeaderId(markdown)\nrenderTOC(markdown)\ngenerateToc('ui-toc')\ngenerateToc('ui-toc-affix')\nsmoothHashScroll()\nwindow.createtime = window.lastchangeui.time.attr('data-createtime')\nwindow.lastchangetime = window.lastchangeui.time.attr('data-updatetime')\nupdateLastChange()\n\nconst url = window.location.pathname\n$('.ui-edit').attr('href', `${url}/edit`)\nconst toc = $('.ui-toc')\nconst tocAffix = $('.ui-affix-toc')\nconst tocDropdown = $('.ui-toc-dropdown')\n// toc\ntocDropdown.click(e => {\n  e.stopPropagation()\n})\n\nlet enoughForAffixToc = true\n\nfunction generateScrollspy () {\n  $(document.body).scrollspy({\n    target: ''\n  })\n  $(document.body).scrollspy('refresh')\n  if (enoughForAffixToc) {\n    toc.hide()\n    tocAffix.show()\n  } else {\n    tocAffix.hide()\n    toc.show()\n  }\n  $(document.body).scroll()\n}\n\nfunction windowResize () {\n  // toc right\n  const paddingRight = parseFloat(markdown.css('padding-right'))\n  const right = ($(window).width() - (markdown.offset().left + markdown.outerWidth() - paddingRight))\n  toc.css('right', `${right}px`)\n  // affix toc left\n  let newbool\n  const rightMargin = (markdown.parent().outerWidth() - markdown.outerWidth()) / 2\n  // for ipad or wider device\n  if (rightMargin >= 133) {\n    newbool = true\n    const affixLeftMargin = (tocAffix.outerWidth() - tocAffix.width()) / 2\n    const left = markdown.offset().left + markdown.outerWidth() - affixLeftMargin\n    tocAffix.css('left', `${left}px`)\n  } else {\n    newbool = false\n  }\n  if (newbool !== enoughForAffixToc) {\n    enoughForAffixToc = newbool\n    generateScrollspy()\n  }\n}\n$(window).resize(() => {\n  windowResize()\n})\n$(document).ready(() => {\n  windowResize()\n  generateScrollspy()\n  setTimeout(scrollToHash, 0)\n  // tooltip\n  $('[data-toggle=\"tooltip\"]').tooltip()\n})\n\nexport function scrollToTop () {\n  $('body, html').stop(true, true).animate({\n    scrollTop: 0\n  }, 100, 'linear')\n}\n\nexport function scrollToBottom () {\n  $('body, html').stop(true, true).animate({\n    scrollTop: $(document.body)[0].scrollHeight\n  }, 100, 'linear')\n}\n\nwindow.scrollToTop = scrollToTop\nwindow.scrollToBottom = scrollToBottom\n"
  },
  {
    "path": "public/js/render.js",
    "content": "/* eslint-env browser, jquery */\n// allow some attributes\n\nimport filterXSS from 'xss'\n\nvar whiteListAttr = ['id', 'class', 'style']\nwindow.whiteListAttr = whiteListAttr\n// allow link starts with '.', '/' and custom protocol with '://', exclude link starts with javascript://\nvar linkRegex = /^(?!javascript:\\/\\/)([\\w|-]+:\\/\\/)|^([.|/])+/i\n// allow data uri, from https://gist.github.com/bgrins/6194623\nvar dataUriRegex = /^\\s*data:([a-z]+\\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\\-._~:@/?%\\s]*)\\s*$/i\n// custom white list\nvar whiteList = filterXSS.whiteList\n// allow ol specify start number\nwhiteList.ol = ['start']\n// allow li specify value number\nwhiteList.li = ['value']\n// allow style tag\nwhiteList.style = []\n// allow kbd tag\nwhiteList.kbd = []\n// allow ifram tag with some safe attributes\nwhiteList.iframe = ['allowfullscreen', 'referrerpolicy', 'src', 'width', 'height']\n// allow summary tag\nwhiteList.summary = []\n// allow ruby tag\nwhiteList.ruby = []\n// allow rp tag for ruby\nwhiteList.rp = []\n// allow rt tag for ruby\nwhiteList.rt = []\n// allow figure tag\nwhiteList.figure = []\n// allow figcaption tag\nwhiteList.figcaption = []\n\nvar filterXSSOptions = {\n  allowCommentTag: true,\n  whiteList: whiteList,\n  escapeHtml: function (html) {\n    // allow html comment in multiple lines\n    return html.replace(/<(?!!--)/g, '&lt;').replace(/-->/g, '__HTML_COMMENT_END__').replace(/>/g, '&gt;').replace(/__HTML_COMMENT_END__/g, '-->')\n  },\n  onIgnoreTag: function (tag, html, options) {\n    // allow comment tag\n    if (tag === '!--') {\n      // do not filter its attributes\n      return html.replace(/<(?!!--)/g, '&lt;').replace(/-->/g, '__HTML_COMMENT_END__').replace(/>/g, '&gt;').replace(/__HTML_COMMENT_END__/g, '-->')\n    }\n  },\n  onTagAttr: function (tag, name, value, isWhiteAttr) {\n    // allow href and src that match linkRegex\n    if (isWhiteAttr && (name === 'href' || name === 'src') && linkRegex.test(value)) {\n      return name + '=\"' + filterXSS.escapeAttrValue(value) + '\"'\n    }\n    // allow data uri in img src\n    if (isWhiteAttr && (tag === 'img' && name === 'src') && dataUriRegex.test(value)) {\n      return name + '=\"' + filterXSS.escapeAttrValue(value) + '\"'\n    }\n  },\n  onIgnoreTagAttr: function (tag, name, value, isWhiteAttr) {\n    // allow attr start with 'data-' or in the whiteListAttr\n    if (name.substr(0, 5) === 'data-' || window.whiteListAttr.indexOf(name) !== -1) {\n      // escape its value using built-in escapeAttrValue function\n      return name + '=\"' + filterXSS.escapeAttrValue(value) + '\"'\n    }\n  }\n}\n\nfunction preventXSS (html) {\n  return filterXSS(html, filterXSSOptions)\n}\nwindow.preventXSS = preventXSS\n\nexport { preventXSS }\nexport const escapeAttrValue = filterXSS.escapeAttrValue\n"
  },
  {
    "path": "public/js/reveal-markdown.js",
    "content": "/* eslint-env browser, jquery */\n/* global globalThis */\n\nimport { preventXSS, escapeAttrValue } from './render'\nimport { md } from './extra'\n\n/**\n * The reveal.js markdown plugin. Handles parsing of\n * markdown inside of presentations as well as loading\n * of external markdown documents.\n */\n(function (root, factory) {\n  if (typeof exports === 'object') {\n    module.exports = factory()\n  } else {\n    // Browser globals (root is window)\n    root.RevealMarkdown = factory()\n    root.RevealMarkdown.initialize()\n  }\n}(typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : this, function () {\n  var DEFAULT_SLIDE_SEPARATOR = '^\\r?\\n---\\r?\\n$'\n  var DEFAULT_NOTES_SEPARATOR = '^note:'\n  var DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\\\.element\\\\s*?(.+?)$'\n  var DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\\\.slide:\\\\s*?(\\\\S.+?)$'\n\n  var SCRIPT_END_PLACEHOLDER = '__SCRIPT_END__'\n\n  /**\n   * Retrieves the markdown contents of a slide section\n   * element. Normalizes leading tabs/whitespace.\n   */\n  function getMarkdownFromSlide (section) {\n    var template = section.querySelector('script')\n\n    // strip leading whitespace so it isn't evaluated as code\n    var text = (template || section).textContent\n\n    // restore script end tags\n    text = text.replace(new RegExp(SCRIPT_END_PLACEHOLDER, 'g'), '</script>')\n\n    var leadingWs = text.match(/^\\n?(\\s*)/)[1].length\n    var leadingTabs = text.match(/^\\n?(\\t*)/)[1].length\n\n    if (leadingTabs > 0) {\n      text = text.replace(new RegExp('\\\\n?\\\\t{' + leadingTabs + '}', 'g'), '\\n')\n    } else if (leadingWs > 1) {\n      text = text.replace(new RegExp('\\\\n? {' + leadingWs + '}', 'g'), '\\n')\n    }\n\n    return text\n  }\n\n  /**\n   * Given a markdown slide section element, this will\n   * return all arguments that aren't related to markdown\n   * parsing. Used to forward any other user-defined arguments\n   * to the output markdown slide.\n   */\n  function getForwardedAttributes (section) {\n    var attributes = section.attributes\n    var result = []\n\n    for (var i = 0, len = attributes.length; i < len; i++) {\n      var name = attributes[i].name\n      var value = attributes[i].value\n\n      // disregard attributes that are used for markdown loading/parsing\n      if (/data-(markdown|separator|vertical|notes)/gi.test(name)) continue\n\n      if (value) {\n        result.push(name + '=\"' + value + '\"')\n      } else {\n        result.push(name)\n      }\n    }\n\n    return result.join(' ')\n  }\n\n  /**\n   * Inspects the given options and fills out default\n   * values for what's not defined.\n   */\n  function getSlidifyOptions (options) {\n    options = options || {}\n    options.separator = options.separator || DEFAULT_SLIDE_SEPARATOR\n    options.notesSeparator = options.notesSeparator || DEFAULT_NOTES_SEPARATOR\n    options.attributes = options.attributes || ''\n\n    return options\n  }\n\n  /**\n   * Helper function for constructing a markdown slide.\n   */\n  function createMarkdownSlide (content, options) {\n    options = getSlidifyOptions(options)\n\n    var notesMatch = content.split(new RegExp(options.notesSeparator, 'mgi'))\n\n    if (notesMatch.length === 2) {\n      content = notesMatch[0] + '<aside class=\"notes\" data-markdown>' + notesMatch[1].trim() + '</aside>'\n    }\n\n    // prevent script end tags in the content from interfering\n    // with parsing\n    content = content.replace(/<\\/script>/gi, SCRIPT_END_PLACEHOLDER)\n\n    return '<script type=\"text/template\">' + content + '</script>'\n  }\n\n  /**\n   * Parses a data string into multiple slides based\n   * on the passed in separator arguments.\n   */\n  function slidify (markdown, options) {\n    options = getSlidifyOptions(options)\n\n    var separatorRegex = new RegExp(options.separator + (options.verticalSeparator ? '|' + options.verticalSeparator : ''), 'mg')\n    var horizontalSeparatorRegex = new RegExp(options.separator)\n\n    var matches\n    var lastIndex = 0\n    var isHorizontal\n    var wasHorizontal = true\n    var content\n    var sectionStack = []\n\n    // iterate until all blocks between separators are stacked up\n    while ((matches = separatorRegex.exec(markdown)) !== null) {\n      // determine direction (horizontal by default)\n      isHorizontal = horizontalSeparatorRegex.test(matches[0])\n\n      if (!isHorizontal && wasHorizontal) {\n        // create vertical stack\n        sectionStack.push([])\n      }\n\n      // pluck slide content from markdown input\n      content = markdown.substring(lastIndex, matches.index)\n\n      if (isHorizontal && wasHorizontal) {\n        // add to horizontal stack\n        sectionStack.push(content)\n      } else {\n        // add to vertical stack\n        sectionStack[sectionStack.length - 1].push(content)\n      }\n\n      lastIndex = separatorRegex.lastIndex\n      wasHorizontal = isHorizontal\n    }\n\n    // add the remaining slide\n    (wasHorizontal ? sectionStack : sectionStack[sectionStack.length - 1]).push(markdown.substring(lastIndex))\n\n    var markdownSections = ''\n\n    // flatten the hierarchical stack, and insert <section data-markdown> tags\n    for (var i = 0, len = sectionStack.length; i < len; i++) {\n      // vertical\n      if (sectionStack[i] instanceof Array) {\n        markdownSections += '<section ' + options.attributes + '>'\n\n        sectionStack[i].forEach(function (child) {\n          markdownSections += '<section data-markdown>' + createMarkdownSlide(child, options) + '</section>'\n        })\n\n        markdownSections += '</section>'\n      } else {\n        markdownSections += '<section ' + options.attributes + ' data-markdown>' + createMarkdownSlide(sectionStack[i], options) + '</section>'\n      }\n    }\n\n    return markdownSections\n  }\n\n  /**\n   * Parses any current data-markdown slides, splits\n   * multi-slide markdown into separate sections and\n   * handles loading of external markdown.\n   */\n  function processSlides () {\n    var sections = document.querySelectorAll('[data-markdown]')\n    var section\n\n    for (var i = 0, len = sections.length; i < len; i++) {\n      section = sections[i]\n\n      if (section.getAttribute('data-markdown').length) {\n        var xhr = new XMLHttpRequest()\n        var url = section.getAttribute('data-markdown')\n\n        var datacharset = section.getAttribute('data-charset')\n\n        // see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes\n        if (datacharset !== null && datacharset !== '') {\n          xhr.overrideMimeType('text/html; charset=' + datacharset)\n        }\n\n        xhr.onreadystatechange = function () {\n          if (xhr.readyState === 4) {\n            // file protocol yields status code 0 (useful for local debug, mobile applications etc.)\n            if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 0) {\n              section.outerHTML = slidify(xhr.responseText, {\n                separator: section.getAttribute('data-separator'),\n                verticalSeparator: section.getAttribute('data-separator-vertical'),\n                notesSeparator: section.getAttribute('data-separator-notes'),\n                attributes: getForwardedAttributes(section)\n              })\n            } else {\n              section.outerHTML = '<section data-state=\"alert\">' +\n              'ERROR: The attempt to fetch ' + url + ' failed with HTTP status ' + xhr.status + '.' +\n              'Check your browser\\'s JavaScript console for more details.' +\n              '<p>Remember that you need to serve the presentation HTML from a HTTP server.</p>' +\n              '</section>'\n            }\n          }\n        }\n\n        xhr.open('GET', url, false)\n\n        try {\n          xhr.send()\n        } catch (e) {\n          alert('Failed to get the Markdown file ' + url + '. Make sure that the presentation and the file are served by a HTTP server and the file can be found there. ' + e)\n        }\n      } else if (section.getAttribute('data-separator') || section.getAttribute('data-separator-vertical') || section.getAttribute('data-separator-notes')) {\n        section.outerHTML = slidify(getMarkdownFromSlide(section), {\n          separator: section.getAttribute('data-separator'),\n          verticalSeparator: section.getAttribute('data-separator-vertical'),\n          notesSeparator: section.getAttribute('data-separator-notes'),\n          attributes: getForwardedAttributes(section)\n        })\n      } else {\n        section.innerHTML = createMarkdownSlide(getMarkdownFromSlide(section))\n      }\n    }\n  }\n\n  /**\n   * Check if a node value has the attributes pattern.\n   * If yes, extract it and add that value as one or several attributes\n   * the the terget element.\n   *\n   * You need Cache Killer on Chrome to see the effect on any FOM transformation\n   * directly on refresh (F5)\n   * http://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development/7000899#answer-11786277\n   */\n  function addAttributeInElement (node, elementTarget, separator) {\n    var mardownClassesInElementsRegex = new RegExp(separator, 'mg')\n    var mardownClassRegex = new RegExp('([^\"= ]+?)=\"([^\"=]+?)\"', 'mg')\n    var nodeValue = node.nodeValue\n    var matches\n    var matchesClass\n    if ((matches = mardownClassesInElementsRegex.exec(nodeValue))) {\n      var classes = matches[1]\n      nodeValue = nodeValue.substring(0, matches.index) + nodeValue.substring(mardownClassesInElementsRegex.lastIndex)\n      node.nodeValue = nodeValue\n      while ((matchesClass = mardownClassRegex.exec(classes))) {\n        var name = matchesClass[1]\n        var value = matchesClass[2]\n        if (name.substr(0, 5) === 'data-' || window.whiteListAttr.indexOf(name) !== -1) { elementTarget.setAttribute(name, escapeAttrValue(value)) }\n      }\n      return true\n    }\n    return false\n  }\n\n  /**\n   * Add attributes to the parent element of a text node,\n   * or the element of an attribute node.\n   */\n  function addAttributes (section, element, previousElement, separatorElementAttributes, separatorSectionAttributes) {\n    if (element != null && element.childNodes !== undefined && element.childNodes.length > 0) {\n      var previousParentElement = element\n      for (var i = 0; i < element.childNodes.length; i++) {\n        var childElement = element.childNodes[i]\n        if (i > 0) {\n          let j = i - 1\n          while (j >= 0) {\n            var aPreviousChildElement = element.childNodes[j]\n            if (typeof aPreviousChildElement.setAttribute === 'function' && aPreviousChildElement.tagName !== 'BR') {\n              previousParentElement = aPreviousChildElement\n              break\n            }\n            j = j - 1\n          }\n        }\n        var parentSection = section\n        if (childElement.nodeName === 'section') {\n          parentSection = childElement\n          previousParentElement = childElement\n        }\n        if (typeof childElement.setAttribute === 'function' || childElement.nodeType === Node.COMMENT_NODE) {\n          addAttributes(parentSection, childElement, previousParentElement, separatorElementAttributes, separatorSectionAttributes)\n        }\n      }\n    }\n\n    if (element.nodeType === Node.COMMENT_NODE) {\n      if (addAttributeInElement(element, previousElement, separatorElementAttributes) === false) {\n        addAttributeInElement(element, section, separatorSectionAttributes)\n      }\n    }\n  }\n\n  /**\n   * Converts any current data-markdown slides in the\n   * DOM to HTML.\n   */\n  function convertSlides () {\n    var sections = document.querySelectorAll('[data-markdown]')\n\n    for (var i = 0, len = sections.length; i < len; i++) {\n      var section = sections[i]\n\n      // Only parse the same slide once\n      if (!section.getAttribute('data-markdown-parsed')) {\n        section.setAttribute('data-markdown-parsed', true)\n\n        var notes = section.querySelector('aside.notes')\n        var markdown = getMarkdownFromSlide(section)\n        markdown = markdown.replace(/&lt;/g, '<').replace(/&gt;/g, '>')\n        var rendered = md.render(markdown)\n        rendered = preventXSS(rendered)\n        var result = window.postProcess(rendered)\n        section.innerHTML = result[0].outerHTML\n        addAttributes(section, section, null, section.getAttribute('data-element-attributes') ||\n        section.parentNode.getAttribute('data-element-attributes') ||\n        DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR,\n        section.getAttribute('data-attributes') ||\n        section.parentNode.getAttribute('data-attributes') ||\n        DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR)\n\n        // If there were notes, we need to re-add them after\n        // having overwritten the section's HTML\n        if (notes) {\n          section.appendChild(notes)\n        }\n      }\n    }\n  }\n\n  // API\n  return {\n    initialize: function () {\n      processSlides()\n      convertSlides()\n    },\n    // TODO: Do these belong in the API?\n    processSlides: processSlides,\n    convertSlides: convertSlides,\n    slidify: slidify\n  }\n}))\n\n// ES Module export for modern imports\nconst RevealMarkdownAPI = (function () {\n  if (typeof window !== 'undefined' && window.RevealMarkdown) {\n    return window.RevealMarkdown\n  }\n  // Fallback - shouldn't happen in normal usage\n  return {}\n})()\n\nexport default RevealMarkdownAPI\n"
  },
  {
    "path": "public/js/revealjs-plugins/elapsed-time-bar/elapsed-time-bar.js",
    "content": "/* eslint-disable */\nvar ElapsedTimeBar = {\n  // default value\n  barColor: 'rgb(200,0,0)',\n  pausedBarColor: 'rgba(200,0,0,.6)',\n\n  isPaused: false,\n  isFinished: false,\n\n  allottedTime: null,\n  timeProgressBar: null,\n  startTime: null,\n  pauseTime: null,\n  pauseTimeDuration: 0,\n\n  /**\n   * initialize elements\n   */\n  handleReady() {\n    var config = Reveal.getConfig();\n\n    // activate this plugin if config.allottedTime exists.\n    if (!config.allottedTime) {\n      console.warn('Failed to start ElapsedTimeBar plugin. \"allottedTime\" property is required.');\n      return;\n    }\n\n    // set configurations\n    this.barColor = config.barColor || this.barColor;\n    this.pausedBarColor = config.pausedBarColor || this.pausedBarColor;\n\n    // calc barHeight from config.barHeight or page-progress container\n    var barHeight;\n    var pageProgressContainer = document.querySelector('.progress');\n    if (config.progressBarHeight) {\n      barHeight = parseInt(config.progressBarHeight, 10) + 'px';\n\n      // override height of page-progress container\n      pageProgressContainer && (pageProgressContainer.style.height = barHeight);\n    } else if (config.progress && pageProgressContainer) {\n      // get height from page-progress container\n      barHeight = pageProgressContainer.getBoundingClientRect().height + 'px';\n    } else {\n      // default\n      barHeight = '3px';\n    }\n\n    // create container of time-progress\n    var timeProgressContainer = document.createElement('div');\n    timeProgressContainer.classList.add('progress');\n    Object.entries({\n      display: 'block',\n      position: 'fixed',\n      bottom: config.progress ? barHeight : 0,\n      width: '100%',\n      height: barHeight\n    }).forEach(([k, v]) => {\n      timeProgressContainer.style[k] = v;\n    });\n    document.querySelector('.reveal').appendChild(timeProgressContainer);\n\n    // create content of time-progress\n    this.timeProgressBar = document.createElement('div');\n    Object.entries({\n      height: '100%',\n      willChange: 'width'\n    }).forEach(([k, v]) => {\n      this.timeProgressBar.style[k] = v;\n    });\n    timeProgressContainer.appendChild(this.timeProgressBar);\n\n    // start timer\n    this.start(config.allottedTime);\n  },\n\n  /**\n   * update repeatedly using requestAnimationFrame.\n   */\n  loop() {\n    if (this.isPaused) return;\n    var now = +new Date();\n    var elapsedTime = now - this.startTime - this.pauseTimeDuration;\n    if (elapsedTime > this.allottedTime) {\n      this.timeProgressBar.style.width = '100%';\n      this.isFinished = true;\n    } else {\n      this.timeProgressBar.style.width = elapsedTime / this.allottedTime * 100 + '%';\n      requestAnimationFrame(this.loop.bind(this));\n    }\n  },\n\n  /**\n   * set color of progress bar\n   */\n  setBarColor() {\n    if (this.isPaused) {\n      this.timeProgressBar.style.backgroundColor = this.pausedBarColor;\n    } else {\n      this.timeProgressBar.style.backgroundColor = this.barColor;\n    }\n  },\n\n  /**\n   * start(reset) timer with new allotted time.\n   * @param {number} allottedTime\n   * @param {number} [elapsedTime=0]\n   */\n  start(allottedTime, elapsedTime = 0) {\n    this.isFinished = false;\n    this.isPaused = false;\n    this.allottedTime = allottedTime;\n    this.startTime = +new Date() - elapsedTime;\n    this.pauseTimeDuration = 0;\n    this.setBarColor();\n    this.loop();\n  },\n\n  reset() {\n    this.start(this.allottedTime);\n  },\n\n  pause() {\n    if (this.isPaused) return;\n    this.isPaused = true;\n    this.pauseTime = +new Date();\n    this.setBarColor();\n  },\n\n  resume() {\n    if (!this.isPaused) return;\n\n    // add paused time duration\n    this.isPaused = false;\n    this.pauseTimeDuration += new Date() - this.pauseTime;\n    this.pauseTime = null;\n    this.setBarColor();\n    this.loop();\n  }\n};\n\nif (Reveal.isReady()) {\n  ElapsedTimeBar.handleReady();\n} else {\n  Reveal.addEventListener('ready', () => ElapsedTimeBar.handleReady());\n}\n"
  },
  {
    "path": "public/js/revealjs-plugins/spotlight/spotlight.js",
    "content": "/* eslint-disable */\nvar RevealSpotlight = window.RevealSpotlight || (function () {\n\n  //configs\n  var spotlightSize;\n  var toggleOnMouseDown;\n  var spotlightOnKeyPressAndHold;\n  var presentingCursor;\n  var spotlightCursor;\n  var initialPresentationMode;\n  var disablingUserSelect;\n  var fadeInAndOut;\n  var style;\n  var lockPointerInsideCanvas;\n  var getMousePos;\n\n  var drawBoard;\n  var isSpotlightOn = true;\n  var isCursorOn = true;\n\n  var lastMouseMoveEvent;\n\n  function onRevealJsReady(event) {\n    configure();\n    drawBoard = setupCanvas();\n\n    addWindowResizeListener();\n\n    addMouseMoveListener();\n\n    if (toggleOnMouseDown) {\n      addMouseToggleSpotlightListener();\n    }\n\n    if (spotlightOnKeyPressAndHold) {\n      addKeyPressAndHoldSpotlightListener(spotlightOnKeyPressAndHold);\n    }\n\n    setCursor(!initialPresentationMode);\n    setSpotlight(false);\n  }\n\n  function configure() {\n    var config = Reveal.getConfig().spotlight || {};\n    spotlightSize = config.size || 60;\n    presentingCursor = config.presentingCursor || \"none\";\n    spotlightCursor = config.spotlightCursor || \"none\";\n    var useAsPointer = config.useAsPointer || false;\n    var pointerColor = config.pointerColor || 'red';\n    lockPointerInsideCanvas = config.lockPointerInsideCanvas || false;\n\n    if(lockPointerInsideCanvas){\n      getMousePos = getMousePosByMovement;\n    } else {\n      getMousePos = getMousePosByBoundingClientRect;\n    }\n\n    // If using as pointer draw a transparent background and\n    // the mouse pointer in the specified color or default\n    var pointerStyle = {\n      backgroundFillStyle : \"rgba(0, 0, 0, 0)\",\n      mouseFillStyle : pointerColor\n    };\n\n    var spotlightStyle = {\n      backgroundFillStyle : \"#000000A8\",\n      mouseFillStyle : \"#FFFFFFFF\"\n    };\n\n    style = useAsPointer ? pointerStyle : spotlightStyle;\n\n    if (config.hasOwnProperty(\"toggleSpotlightOnMouseDown\")) {\n      toggleOnMouseDown = config.toggleSpotlightOnMouseDown;\n    } else {\n      toggleOnMouseDown = true;\n    }\n\n    if (config.hasOwnProperty(\"initialPresentationMode\")) {\n      initialPresentationMode = config.initialPresentationMode;\n    } else {\n      initialPresentationMode = toggleOnMouseDown;\n    }\n\n    if (config.hasOwnProperty(\"spotlightOnKeyPressAndHold\")) {\n      spotlightOnKeyPressAndHold = config.spotlightOnKeyPressAndHold;\n    } else {\n      spotlightOnKeyPressAndHold = false;\n    }\n\n    if (config.hasOwnProperty(\"disablingUserSelect\")) {\n      disablingUserSelect = config.disablingUserSelect;\n    } else {\n      disablingUserSelect = true;\n    }\n\n    if (config.hasOwnProperty(\"fadeInAndOut\")) {\n      fadeInAndOut = config.fadeInAndOut;\n    } else {\n      fadeInAndOut = false;\n    }\n  }\n\n  function setupCanvas() {\n    var container = document.createElement('div');\n    container.id = \"spotlight\";\n    container.style.cssText = \"position:absolute;top:0;left:0;bottom:0;right:0;z-index:99;\";\n    if (fadeInAndOut) {\n      container.style.cssText += \"transition: \" + fadeInAndOut + \"ms opacity;\";\n    }\n\n    var canvas = document.createElement('canvas');\n    var context = canvas.getContext(\"2d\");\n\n    canvas.width = window.innerWidth;\n    canvas.height = window.innerHeight;\n\n    container.appendChild(canvas);\n    document.body.appendChild(container);\n    container.style.opacity = 0;\n    container.style['pointer-events'] = 'none';\n    return {\n      container,\n      canvas,\n      context\n    }\n  }\n\n  function addWindowResizeListener() {\n    window.addEventListener('resize', function (e) {\n      var canvas = drawBoard.canvas;\n      canvas.width = window.innerWidth;\n      canvas.height = window.innerHeight;\n    }, false);\n  }\n\n  function addMouseMoveListener() {\n    document.body.addEventListener('mousemove', function (e) {\n      if(isSpotlightOn) {\n        showSpotlight(e);\n      }\n      lastMouseMoveEvent = e;\n    }, false);\n  }\n\n  function addMouseToggleSpotlightListener() {\n\n    window.addEventListener(\"mousedown\", function (e) {\n      if (!isCursorOn) {\n        setSpotlight(true, e);\n      }\n    }, false);\n\n    window.addEventListener(\"mouseup\", function (e) {\n      if (!isCursorOn) {\n        setSpotlight(false, e);\n      }\n    }, false);\n  }\n\n  function addKeyPressAndHoldSpotlightListener(keyCode) {\n\n    window.addEventListener(\"keydown\", function (e) {\n      if (!isCursorOn && !isSpotlightOn && e.keyCode === keyCode) {\n        setSpotlight(true, lastMouseMoveEvent);\n      }\n    }, false);\n\n    window.addEventListener(\"keyup\", function (e) {\n      if (!isCursorOn && e.keyCode === keyCode) {\n        setSpotlight(false);\n      }\n    }, false);\n  }\n\n  function toggleSpotlight() {\n    setSpotlight(!isSpotlightOn, lastMouseMoveEvent);\n  }\n\n  function setSpotlight(isOn, mouseEvt) {\n    isSpotlightOn = isOn;\n    var container = drawBoard.container;\n    if (isOn) {\n      if (lockPointerInsideCanvas && document.pointerLockElement != drawBoard.canvas) {\n        drawBoard.canvas.requestPointerLock();\n      }\n      container.style.opacity = 1;\n      container.style['pointer-events'] = null;\n      document.body.style.cursor = spotlightCursor;\n      if (mouseEvt) {\n        showSpotlight(mouseEvt);\n      }\n    } else {\n      container.style.opacity = 0;\n      container.style['pointer-events'] = 'none';\n      document.body.style.cursor = presentingCursor;\n    }\n  }\n\n  function togglePresentationMode() {\n    setCursor(!isCursorOn);\n  }\n\n  function setCursor(isOn) {\n    isCursorOn = isOn;\n    if (isOn) {\n      if (disablingUserSelect) {\n        document.body.style.userSelect = null;\n      }\n      document.body.style.cursor = null;\n    } else {\n      if (disablingUserSelect) {\n        document.body.style.userSelect = \"none\";\n      }\n      document.body.style.cursor = presentingCursor;\n    }\n  }\n\n  function showSpotlight(mouseEvt) {\n    var canvas = drawBoard.canvas;\n    var context = drawBoard.context;\n    var mousePos = getMousePos(canvas, mouseEvt);\n\n    context.clearRect(0, 0, canvas.width, canvas.height);\n\n    // Create a canvas mask\n    var maskCanvas = document.createElement('canvas');\n    maskCanvas.width = canvas.width;\n    maskCanvas.height = canvas.height;\n\n    var maskCtx = maskCanvas.getContext('2d');\n\n    maskCtx.fillStyle = style.backgroundFillStyle;\n    maskCtx.fillRect(0, 0, maskCanvas.width, maskCanvas.height);\n    maskCtx.globalCompositeOperation = 'xor';\n\n    maskCtx.fillStyle = style.mouseFillStyle;\n    maskCtx.arc(mousePos.x, mousePos.y, spotlightSize, 0, 2 * Math.PI);\n    maskCtx.fill();\n\n    context.drawImage(maskCanvas, 0, 0);\n  }\n\n  var mX = 0;\n  var mY = 0;\n\n  function getMousePosByMovement(canvas, evt) {\n    var movementX = evt.movementX || 0;\n    var movementY = evt.movementY || 0;\n    mX += movementX;\n    mY += movementY;\n\n    if (mX > canvas.clientWidth) {\n      mX = canvas.clientWidth;\n    }\n    if (mY > canvas.clientHeight) {\n      mY = canvas.clientHeight;\n    }\n    if (mX < 0) {\n      mX = 0;\n    }\n    if (mY < 0) {\n      mY = 0;\n    }\n\n    return {\n      x: mX,\n      y: mY\n    };\n  }\n\n  function getMousePosByBoundingClientRect(canvas, evt) {\n    var rect = canvas.getBoundingClientRect();\n    return {\n      x: evt.clientX - rect.left,\n      y: evt.clientY - rect.top\n    };\n  }\n\n  Reveal.addEventListener('ready', onRevealJsReady);\n\n  this.toggleSpotlight = toggleSpotlight;\n  this.togglePresentationMode = togglePresentationMode;\n  return this;\n})();\n"
  },
  {
    "path": "public/js/slide.js",
    "content": "/* eslint-env browser, jquery */\n/* global serverurl, Reveal */\n\nimport RevealMarkdown from './reveal-markdown'\n\nimport { preventXSS } from './render'\nimport { md, updateLastChange, removeDOMEvents, finishView } from './extra'\n\nrequire('../css/extra.css')\nrequire('../css/site.css')\n\nconst body = preventXSS($('.slides').text())\n\nwindow.createtime = window.lastchangeui.time.attr('data-createtime')\nwindow.lastchangetime = window.lastchangeui.time.attr('data-updatetime')\nupdateLastChange()\nconst url = window.location.pathname\n$('.ui-edit').attr('href', `${url}/edit`)\n$('.ui-print').attr('href', `${url}?print-pdf`)\n\n$(document).ready(() => {\n  // tooltip\n  $('[data-toggle=\"tooltip\"]').tooltip()\n})\n\nfunction extend () {\n  const target = {}\n\n  for (const source of arguments) {\n    for (const key in source) {\n      if (Object.hasOwnProperty.call(source, key)) {\n        target[key] = source[key]\n      }\n    }\n  }\n\n  return target\n}\n\n// Optional libraries used to extend on reveal.js\nconst deps = [{\n  src: `${serverurl}/build/reveal.js/lib/js/classList.js`,\n  condition () {\n    return !document.body.classList\n  }\n}, {\n  src: `${serverurl}/build/reveal.js/plugin/notes/notes.js`,\n  async: true,\n  condition () {\n    return !!document.body.classList\n  }\n}]\n\n// options from yaml meta\nconst meta = JSON.parse($('#meta').text())\n// breaks\nif (typeof meta.breaks === 'boolean') {\n  md.options.breaks = meta.breaks\n} else {\n  md.options.breaks = window.defaultUseHardbreak\n}\n\nconst slideOptions = {\n  separator: '^(\\r\\n?|\\n)---(\\r\\n?|\\n)$',\n  verticalSeparator: '^(\\r\\n?|\\n)----(\\r\\n?|\\n)$'\n}\nconst slides = RevealMarkdown.slidify(body, slideOptions)\n$('.slides').html(slides)\nRevealMarkdown.initialize()\nremoveDOMEvents($('.slides'))\n$('.slides').show()\n\n// default options to init reveal.js\nconst defaultOptions = {\n  controls: true,\n  progress: true,\n  slideNumber: true,\n  history: true,\n  center: true,\n  transition: 'none',\n  dependencies: deps\n}\n\nvar options = meta.slideOptions || {}\n// delete dependencies to avoid import user defined external resources\ndelete options.dependencies\n\nif (Object.hasOwnProperty.call(options, 'spotlight')) {\n  defaultOptions.dependencies.push({\n    src: `${serverurl}/build/revealjs-plugins/spotlight/spotlight.js`\n  })\n}\n\nif (Object.hasOwnProperty.call(options, 'allottedTime') || Object.hasOwnProperty.call(options, 'allottedMinutes')) {\n  defaultOptions.dependencies.push({\n    src: `${serverurl}/build/revealjs-plugins/elapsed-time-bar/elapsed-time-bar.js`\n  })\n  if (Object.hasOwnProperty.call(options, 'allottedMinutes')) {\n    options.allottedTime = options.allottedMinutes * 60 * 1000\n  }\n}\n\nconst view = $('.reveal')\n\n// text language\nif (meta.lang && typeof meta.lang === 'string') {\n  view.attr('lang', meta.lang)\n} else {\n  view.removeAttr('lang')\n}\n// text direction\nif (meta.dir && typeof meta.dir === 'string' && meta.dir === 'rtl') {\n  options.rtl = true\n} else {\n  options.rtl = false\n}\n\n// options from URL query string\nconst queryOptions = Reveal.getQueryHash() || {}\n\noptions = extend(defaultOptions, options, queryOptions)\nReveal.initialize(options)\n\nwindow.viewAjaxCallback = () => {\n  Reveal.layout()\n}\n\nfunction renderSlide (event) {\n  if (window.location.search.match(/print-pdf/gi)) {\n    const slides = $('.slides')\n    const title = document.title\n    finishView(slides)\n    document.title = title\n    Reveal.layout()\n  } else {\n    const markdown = $(event.currentSlide)\n    if (!markdown.attr('data-rendered')) {\n      const title = document.title\n      finishView(markdown)\n      markdown.attr('data-rendered', 'true')\n      document.title = title\n      Reveal.layout()\n    }\n  }\n}\n\nReveal.addEventListener('ready', event => {\n  renderSlide(event)\n  const markdown = $(event.currentSlide)\n  // force browser redraw\n  setTimeout(() => {\n    markdown.hide().show(0)\n  }, 0)\n})\nReveal.addEventListener('slidechanged', renderSlide)\n\nconst isWinLike = navigator.platform.indexOf('Win') > -1\n\nif (isWinLike) $('.container').addClass('hidescrollbar')\n"
  },
  {
    "path": "public/js/utils.js",
    "content": "/* global fetch */\nimport base64url from 'base64url'\n\nconst uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\nexport function checkNoteIdValid (id) {\n  const result = id.match(uuidRegex)\n  return !!(result && result.length === 1)\n}\n\nexport function encodeNoteId (id) {\n  // remove dashes in UUID and encode in url-safe base64\n  const str = id.replace(/-/g, '')\n  const hexStr = Buffer.from(str, 'hex')\n  return base64url.encode(hexStr)\n}\n\nexport function decodeNoteId (encodedId) {\n  // decode from url-safe base64\n  const id = base64url.toBuffer(encodedId).toString('hex')\n  // add dashes between the UUID string parts\n  const idParts = []\n  idParts.push(id.substr(0, 8))\n  idParts.push(id.substr(8, 4))\n  idParts.push(id.substr(12, 4))\n  idParts.push(id.substr(16, 4))\n  idParts.push(id.substr(20, 12))\n  return idParts.join('-')\n}\n\n/**\n * sanitize url to prevent XSS\n * @see {@link https://github.com/braintree/sanitize-url/issues/52#issue-1593777166}\n *\n * @param {string} rawUrl\n * @returns {string} sanitized url\n */\nexport function sanitizeUrl (rawUrl) {\n  try {\n    const url = new URL(rawUrl)\n    if (url.protocol === 'http:' || url.protocol === 'https:') {\n      return url.toString()\n    }\n\n    throw new Error('Invalid protocol')\n  } catch (error) {\n    return 'about:blank'\n  }\n}\n\n// Check if URL is a PDF based on Content-Type header\nexport async function isPdfUrl (url) {\n  try {\n    const response = await fetch(url, { method: 'HEAD' })\n    const contentType = response.headers.get('Content-Type')\n    return contentType === 'application/pdf'\n  } catch (error) {\n    console.warn('Error checking PDF content type:', error)\n    return false\n  }\n}\n"
  },
  {
    "path": "public/markdown-lint/css/lint.css",
    "content": "/* The lint marker gutter */\n.CodeMirror-lint-markers {\n  width: 16px;\n}\n\n.CodeMirror-lint-tooltip {\n  background-color: #333333;\n  border: 1px solid #eeeeee;\n  border-radius: 4px;\n  color: white;\n  font-family: \"Source Code Pro\", Consolas, monaco, monospace;\n  font-size: 10pt;\n  overflow: hidden;\n  padding: 2px 5px;\n  position: fixed;\n  white-space: pre;\n  white-space: pre-wrap;\n  z-index: 100;\n  max-width: 600px;\n  opacity: 0;\n  transition: opacity .4s;\n  -moz-transition: opacity .4s;\n  -webkit-transition: opacity .4s;\n  -o-transition: opacity .4s;\n  -ms-transition: opacity .4s;\n}\n\n.CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning {\n  background-position: left bottom;\n  background-repeat: repeat-x;\n}\n\n.CodeMirror-lint-mark-error {\n  background-image: url(../images/mark-error.png);\n}\n\n.CodeMirror-lint-mark-warning {\n  background-image: url(../images/mark-warning.png);\n}\n\n.CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning {\n  background-position: center center;\n  background-repeat: no-repeat;\n  cursor: pointer;\n  display: inline-block;\n  height: 16px;\n  width: 16px;\n  vertical-align: middle;\n  position: relative;\n  margin-left: 5px;\n}\n\n.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning {\n  padding-left: 20px;\n  background-position: top left;\n  background-repeat: no-repeat;\n  background-position-y: 2px;\n}\n\n.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {\n  background-image: url(../images/message-error.png);\n}\n\n.CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning {\n  background-image: url(../images/message-warning.png);\n}\n\n.CodeMirror-lint-marker-multiple {\n  background-image: url(../images/mark-multiple.png);\n  background-repeat: no-repeat;\n  background-position: right bottom;\n  width: 100%; height: 100%;\n}\n\n.CodeMirror-hints {\n  background: #333;\n}\n\n.CodeMirror-hint {\n  color: white;\n}\n"
  },
  {
    "path": "public/uploads/.gitkeep",
    "content": ""
  },
  {
    "path": "public/vendor/abcjs_basic_3.1.1-min.js",
    "content": "/*! abcjs v3.1.1 Copyright © 2009-2016 Paul Rosen and Gregory Dyke (http://abcjs.net) */\nfunction calcHorizontalSpacing(isLastLine,stretchLast,targetWidth,lineWidth,spacing,spacingUnits,minSpace){if(isLastLine&&lineWidth/targetWidth<.66&&!stretchLast)return null;if(Math.abs(targetWidth-lineWidth)<2)return null;var relSpace=spacingUnits*spacing,constSpace=lineWidth-relSpace;return spacingUnits>0?(spacing=(targetWidth-constSpace)/spacingUnits,spacing*minSpace>50&&(spacing=50/minSpace),spacing):null}function centerWholeRests(voices){for(var i=0;i<voices.length;i++)for(var voice=voices[i],j=1;j<voice.children.length-1;j++){var absElem=voice.children[j];if(absElem.abcelem.rest&&\"whole\"===absElem.abcelem.rest.type){var before=voice.children[j-1],after=voice.children[j+1],midpoint=(after.x-before.x)/2+before.x;absElem.x=midpoint-absElem.w/2;for(var k=0;k<absElem.children.length;k++)absElem.children[k].x=absElem.x}}}function kernSymbols(lastSymbol,thisSymbol,lastSymbolWidth){var width=lastSymbolWidth;return\"f\"===lastSymbol&&\"f\"===thisSymbol&&(width=2*width/3),\"p\"===lastSymbol&&\"p\"===thisSymbol&&(width=5*width/6),\"f\"===lastSymbol&&\"z\"===thisSymbol&&(width=5*width/8),width}!function(glob){var current_event,stop,version=\"0.4.2\",has=\"hasOwnProperty\",separator=/[\\.\\/]/,wildcard=\"*\",fun=function(){},numsort=function(a,b){return a-b},events={n:{}},eve=function(name,scope){name=String(name);var l,oldstop=stop,args=Array.prototype.slice.call(arguments,2),listeners=eve.listeners(name),z=0,indexed=[],queue={},out=[],ce=current_event;current_event=name,stop=0;for(var i=0,ii=listeners.length;i<ii;i++)\"zIndex\"in listeners[i]&&(indexed.push(listeners[i].zIndex),listeners[i].zIndex<0&&(queue[listeners[i].zIndex]=listeners[i]));for(indexed.sort(numsort);indexed[z]<0;)if(l=queue[indexed[z++]],out.push(l.apply(scope,args)),stop)return stop=oldstop,out;for(i=0;i<ii;i++)if(l=listeners[i],\"zIndex\"in l)if(l.zIndex==indexed[z]){if(out.push(l.apply(scope,args)),stop)break;do if(z++,l=queue[indexed[z]],l&&out.push(l.apply(scope,args)),stop)break;while(l)}else queue[l.zIndex]=l;else if(out.push(l.apply(scope,args)),stop)break;return stop=oldstop,current_event=ce,out.length?out:null};eve._events=events,eve.listeners=function(name){var item,items,k,i,ii,j,jj,nes,names=name.split(separator),e=events,es=[e],out=[];for(i=0,ii=names.length;i<ii;i++){for(nes=[],j=0,jj=es.length;j<jj;j++)for(e=es[j].n,items=[e[names[i]],e[wildcard]],k=2;k--;)item=items[k],item&&(nes.push(item),out=out.concat(item.f||[]));es=nes}return out},eve.on=function(name,f){if(name=String(name),\"function\"!=typeof f)return function(){};for(var names=name.split(separator),e=events,i=0,ii=names.length;i<ii;i++)e=e.n,e=e.hasOwnProperty(names[i])&&e[names[i]]||(e[names[i]]={n:{}});for(e.f=e.f||[],i=0,ii=e.f.length;i<ii;i++)if(e.f[i]==f)return fun;return e.f.push(f),function(zIndex){+zIndex==+zIndex&&(f.zIndex=+zIndex)}},eve.f=function(event){var attrs=[].slice.call(arguments,1);return function(){eve.apply(null,[event,null].concat(attrs).concat([].slice.call(arguments,0)))}},eve.stop=function(){stop=1},eve.nt=function(subname){return subname?new RegExp(\"(?:\\\\.|\\\\/|^)\"+subname+\"(?:\\\\.|\\\\/|$)\").test(current_event):current_event},eve.nts=function(){return current_event.split(separator)},eve.off=eve.unbind=function(name,f){if(!name)return void(eve._events=events={n:{}});var e,key,splice,i,ii,j,jj,names=name.split(separator),cur=[events];for(i=0,ii=names.length;i<ii;i++)for(j=0;j<cur.length;j+=splice.length-2){if(splice=[j,1],e=cur[j].n,names[i]!=wildcard)e[names[i]]&&splice.push(e[names[i]]);else for(key in e)e[has](key)&&splice.push(e[key]);cur.splice.apply(cur,splice)}for(i=0,ii=cur.length;i<ii;i++)for(e=cur[i];e.n;){if(f){if(e.f){for(j=0,jj=e.f.length;j<jj;j++)if(e.f[j]==f){e.f.splice(j,1);break}!e.f.length&&delete e.f}for(key in e.n)if(e.n[has](key)&&e.n[key].f){var funcs=e.n[key].f;for(j=0,jj=funcs.length;j<jj;j++)if(funcs[j]==f){funcs.splice(j,1);break}!funcs.length&&delete e.n[key].f}}else{delete e.f;for(key in e.n)e.n[has](key)&&e.n[key].f&&delete e.n[key].f}e=e.n}},eve.once=function(name,f){var f2=function(){return eve.unbind(name,f2),f.apply(this,arguments)};return eve.on(name,f2)},eve.version=version,eve.toString=function(){return\"You are running Eve \"+version},\"undefined\"!=typeof module&&module.exports?module.exports=eve:\"undefined\"!=typeof define?define(\"eve\",[],function(){return eve}):glob.eve=eve}(this),function(glob,factory){\"function\"==typeof define&&define.amd?define([\"eve\"],function(eve){return factory(glob,eve)}):factory(glob,glob.eve)}(this,function(window,eve){function R(first){if(R.is(first,\"function\"))return loaded?first():eve.on(\"raphael.DOMload\",first);if(R.is(first,array))return R._engine.create[apply](R,first.splice(0,3+R.is(first[0],nu))).add(first);var args=Array.prototype.slice.call(arguments,0);if(R.is(args[args.length-1],\"function\")){var f=args.pop();return loaded?f.call(R._engine.create[apply](R,args)):eve.on(\"raphael.DOMload\",function(){f.call(R._engine.create[apply](R,args))})}return R._engine.create[apply](R,arguments)}function clone(obj){if(\"function\"==typeof obj||Object(obj)!==obj)return obj;var res=new obj.constructor;for(var key in obj)obj[has](key)&&(res[key]=clone(obj[key]));return res}function repush(array,item){for(var i=0,ii=array.length;i<ii;i++)if(array[i]===item)return array.push(array.splice(i,1)[0])}function cacher(f,scope,postprocessor){function newf(){var arg=Array.prototype.slice.call(arguments,0),args=arg.join(\"␀\"),cache=newf.cache=newf.cache||{},count=newf.count=newf.count||[];return cache[has](args)?(repush(count,args),postprocessor?postprocessor(cache[args]):cache[args]):(count.length>=1e3&&delete cache[count.shift()],count.push(args),cache[args]=f[apply](scope,arg),postprocessor?postprocessor(cache[args]):cache[args])}return newf}function clrToString(){return this.hex}function catmullRom2bezier(crp,z){for(var d=[],i=0,iLen=crp.length;iLen-2*!z>i;i+=2){var p=[{x:+crp[i-2],y:+crp[i-1]},{x:+crp[i],y:+crp[i+1]},{x:+crp[i+2],y:+crp[i+3]},{x:+crp[i+4],y:+crp[i+5]}];z?i?iLen-4==i?p[3]={x:+crp[0],y:+crp[1]}:iLen-2==i&&(p[2]={x:+crp[0],y:+crp[1]},p[3]={x:+crp[2],y:+crp[3]}):p[0]={x:+crp[iLen-2],y:+crp[iLen-1]}:iLen-4==i?p[3]=p[2]:i||(p[0]={x:+crp[i],y:+crp[i+1]}),d.push([\"C\",(-p[0].x+6*p[1].x+p[2].x)/6,(-p[0].y+6*p[1].y+p[2].y)/6,(p[1].x+6*p[2].x-p[3].x)/6,(p[1].y+6*p[2].y-p[3].y)/6,p[2].x,p[2].y])}return d}function base3(t,p1,p2,p3,p4){var t1=-3*p1+9*p2-9*p3+3*p4,t2=t*t1+6*p1-12*p2+6*p3;return t*t2-3*p1+3*p2}function bezlen(x1,y1,x2,y2,x3,y3,x4,y4,z){null==z&&(z=1),z=z>1?1:z<0?0:z;for(var z2=z/2,n=12,Tvalues=[-.1252,.1252,-.3678,.3678,-.5873,.5873,-.7699,.7699,-.9041,.9041,-.9816,.9816],Cvalues=[.2491,.2491,.2335,.2335,.2032,.2032,.1601,.1601,.1069,.1069,.0472,.0472],sum=0,i=0;i<n;i++){var ct=z2*Tvalues[i]+z2,xbase=base3(ct,x1,x2,x3,x4),ybase=base3(ct,y1,y2,y3,y4),comb=xbase*xbase+ybase*ybase;sum+=Cvalues[i]*math.sqrt(comb)}return z2*sum}function getTatLen(x1,y1,x2,y2,x3,y3,x4,y4,ll){if(!(ll<0||bezlen(x1,y1,x2,y2,x3,y3,x4,y4)<ll)){var l,t=1,step=t/2,t2=t-step,e=.01;for(l=bezlen(x1,y1,x2,y2,x3,y3,x4,y4,t2);abs(l-ll)>e;)step/=2,t2+=(l<ll?1:-1)*step,l=bezlen(x1,y1,x2,y2,x3,y3,x4,y4,t2);return t2}}function intersect(x1,y1,x2,y2,x3,y3,x4,y4){if(!(mmax(x1,x2)<mmin(x3,x4)||mmin(x1,x2)>mmax(x3,x4)||mmax(y1,y2)<mmin(y3,y4)||mmin(y1,y2)>mmax(y3,y4))){var nx=(x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4),ny=(x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4),denominator=(x1-x2)*(y3-y4)-(y1-y2)*(x3-x4);if(denominator){var px=nx/denominator,py=ny/denominator,px2=+px.toFixed(2),py2=+py.toFixed(2);if(!(px2<+mmin(x1,x2).toFixed(2)||px2>+mmax(x1,x2).toFixed(2)||px2<+mmin(x3,x4).toFixed(2)||px2>+mmax(x3,x4).toFixed(2)||py2<+mmin(y1,y2).toFixed(2)||py2>+mmax(y1,y2).toFixed(2)||py2<+mmin(y3,y4).toFixed(2)||py2>+mmax(y3,y4).toFixed(2)))return{x:px,y:py}}}}function interHelper(bez1,bez2,justCount){var bbox1=R.bezierBBox(bez1),bbox2=R.bezierBBox(bez2);if(!R.isBBoxIntersect(bbox1,bbox2))return justCount?0:[];for(var l1=bezlen.apply(0,bez1),l2=bezlen.apply(0,bez2),n1=mmax(~~(l1/5),1),n2=mmax(~~(l2/5),1),dots1=[],dots2=[],xy={},res=justCount?0:[],i=0;i<n1+1;i++){var p=R.findDotsAtSegment.apply(R,bez1.concat(i/n1));dots1.push({x:p.x,y:p.y,t:i/n1})}for(i=0;i<n2+1;i++)p=R.findDotsAtSegment.apply(R,bez2.concat(i/n2)),dots2.push({x:p.x,y:p.y,t:i/n2});for(i=0;i<n1;i++)for(var j=0;j<n2;j++){var di=dots1[i],di1=dots1[i+1],dj=dots2[j],dj1=dots2[j+1],ci=abs(di1.x-di.x)<.001?\"y\":\"x\",cj=abs(dj1.x-dj.x)<.001?\"y\":\"x\",is=intersect(di.x,di.y,di1.x,di1.y,dj.x,dj.y,dj1.x,dj1.y);if(is){if(xy[is.x.toFixed(4)]==is.y.toFixed(4))continue;xy[is.x.toFixed(4)]=is.y.toFixed(4);var t1=di.t+abs((is[ci]-di[ci])/(di1[ci]-di[ci]))*(di1.t-di.t),t2=dj.t+abs((is[cj]-dj[cj])/(dj1[cj]-dj[cj]))*(dj1.t-dj.t);t1>=0&&t1<=1.001&&t2>=0&&t2<=1.001&&(justCount?res++:res.push({x:is.x,y:is.y,t1:mmin(t1,1),t2:mmin(t2,1)}))}}return res}function interPathHelper(path1,path2,justCount){path1=R._path2curve(path1),path2=R._path2curve(path2);for(var x1,y1,x2,y2,x1m,y1m,x2m,y2m,bez1,bez2,res=justCount?0:[],i=0,ii=path1.length;i<ii;i++){var pi=path1[i];if(\"M\"==pi[0])x1=x1m=pi[1],y1=y1m=pi[2];else{\"C\"==pi[0]?(bez1=[x1,y1].concat(pi.slice(1)),x1=bez1[6],y1=bez1[7]):(bez1=[x1,y1,x1,y1,x1m,y1m,x1m,y1m],x1=x1m,y1=y1m);for(var j=0,jj=path2.length;j<jj;j++){var pj=path2[j];if(\"M\"==pj[0])x2=x2m=pj[1],y2=y2m=pj[2];else{\"C\"==pj[0]?(bez2=[x2,y2].concat(pj.slice(1)),x2=bez2[6],y2=bez2[7]):(bez2=[x2,y2,x2,y2,x2m,y2m,x2m,y2m],x2=x2m,y2=y2m);var intr=interHelper(bez1,bez2,justCount);if(justCount)res+=intr;else{for(var k=0,kk=intr.length;k<kk;k++)intr[k].segment1=i,intr[k].segment2=j,intr[k].bez1=bez1,intr[k].bez2=bez2;res=res.concat(intr)}}}}}return res}function Matrix(a,b,c,d,e,f){null!=a?(this.a=+a,this.b=+b,this.c=+c,this.d=+d,this.e=+e,this.f=+f):(this.a=1,this.b=0,this.c=0,this.d=1,this.e=0,this.f=0)}function x_y_w_h(){return this.x+S+this.y+S+this.width+\" × \"+this.height}function CubicBezierAtTime(t,p1x,p1y,p2x,p2y,duration){function sampleCurveX(t){return((ax*t+bx)*t+cx)*t}function solve(x,epsilon){var t=solveCurveX(x,epsilon);return((ay*t+by)*t+cy)*t}function solveCurveX(x,epsilon){var t0,t1,t2,x2,d2,i;for(t2=x,i=0;i<8;i++){if(x2=sampleCurveX(t2)-x,abs(x2)<epsilon)return t2;if(d2=(3*ax*t2+2*bx)*t2+cx,abs(d2)<1e-6)break;t2-=x2/d2}if(t0=0,t1=1,t2=x,t2<t0)return t0;if(t2>t1)return t1;for(;t0<t1;){if(x2=sampleCurveX(t2),abs(x2-x)<epsilon)return t2;x>x2?t0=t2:t1=t2,t2=(t1-t0)/2+t0}return t2}var cx=3*p1x,bx=3*(p2x-p1x)-cx,ax=1-cx-bx,cy=3*p1y,by=3*(p2y-p1y)-cy,ay=1-cy-by;return solve(t,1/(200*duration))}function Animation(anim,ms){var percents=[],newAnim={};if(this.ms=ms,this.times=1,anim){for(var attr in anim)anim[has](attr)&&(newAnim[toFloat(attr)]=anim[attr],percents.push(toFloat(attr)));percents.sort(sortByNumber)}this.anim=newAnim,this.top=percents[percents.length-1],this.percents=percents}function runAnimation(anim,element,percent,status,totalOrigin,times){percent=toFloat(percent);var params,isInAnim,isInAnimSet,next,prev,timestamp,ms=anim.ms,from={},to={},diff={};if(status)for(i=0,ii=animationElements.length;i<ii;i++){var e=animationElements[i];if(e.el.id==element.id&&e.anim==anim){e.percent!=percent?(animationElements.splice(i,1),isInAnimSet=1):isInAnim=e,element.attr(e.totalOrigin);break}}else status=+to;for(var i=0,ii=anim.percents.length;i<ii;i++){if(anim.percents[i]==percent||anim.percents[i]>status*anim.top){percent=anim.percents[i],prev=anim.percents[i-1]||0,ms=ms/anim.top*(percent-prev),next=anim.percents[i+1],params=anim.anim[percent];break}status&&element.attr(anim.anim[anim.percents[i]])}if(params){if(isInAnim)isInAnim.initstatus=status,isInAnim.start=new Date-isInAnim.ms*status;else{for(var attr in params)if(params[has](attr)&&(availableAnimAttrs[has](attr)||element.paper.customAttributes[has](attr)))switch(from[attr]=element.attr(attr),null==from[attr]&&(from[attr]=availableAttrs[attr]),to[attr]=params[attr],availableAnimAttrs[attr]){case nu:diff[attr]=(to[attr]-from[attr])/ms;break;case\"colour\":from[attr]=R.getRGB(from[attr]);var toColour=R.getRGB(to[attr]);diff[attr]={r:(toColour.r-from[attr].r)/ms,g:(toColour.g-from[attr].g)/ms,b:(toColour.b-from[attr].b)/ms};break;case\"path\":var pathes=path2curve(from[attr],to[attr]),toPath=pathes[1];for(from[attr]=pathes[0],diff[attr]=[],i=0,ii=from[attr].length;i<ii;i++){diff[attr][i]=[0];for(var j=1,jj=from[attr][i].length;j<jj;j++)diff[attr][i][j]=(toPath[i][j]-from[attr][i][j])/ms}break;case\"transform\":var _=element._,eq=equaliseTransform(_[attr],to[attr]);if(eq)for(from[attr]=eq.from,to[attr]=eq.to,diff[attr]=[],diff[attr].real=!0,i=0,ii=from[attr].length;i<ii;i++)for(diff[attr][i]=[from[attr][i][0]],j=1,jj=from[attr][i].length;j<jj;j++)diff[attr][i][j]=(to[attr][i][j]-from[attr][i][j])/ms;else{var m=element.matrix||new Matrix,to2={_:{transform:_.transform},getBBox:function(){return element.getBBox(1)}};from[attr]=[m.a,m.b,m.c,m.d,m.e,m.f],extractTransform(to2,to[attr]),to[attr]=to2._.transform,diff[attr]=[(to2.matrix.a-m.a)/ms,(to2.matrix.b-m.b)/ms,(to2.matrix.c-m.c)/ms,(to2.matrix.d-m.d)/ms,(to2.matrix.e-m.e)/ms,(to2.matrix.f-m.f)/ms]}break;case\"csv\":var values=Str(params[attr])[split](separator),from2=Str(from[attr])[split](separator);if(\"clip-rect\"==attr)for(from[attr]=from2,diff[attr]=[],i=from2.length;i--;)diff[attr][i]=(values[i]-from[attr][i])/ms;to[attr]=values;break;default:for(values=[][concat](params[attr]),from2=[][concat](from[attr]),diff[attr]=[],i=element.paper.customAttributes[attr].length;i--;)diff[attr][i]=((values[i]||0)-(from2[i]||0))/ms}var easing=params.easing,easyeasy=R.easing_formulas[easing];if(!easyeasy)if(easyeasy=Str(easing).match(bezierrg),easyeasy&&5==easyeasy.length){var curve=easyeasy;easyeasy=function(t){return CubicBezierAtTime(t,+curve[1],+curve[2],+curve[3],+curve[4],ms)}}else easyeasy=pipe;if(timestamp=params.start||anim.start||+new Date,e={anim:anim,percent:percent,timestamp:timestamp,start:timestamp+(anim.del||0),status:0,initstatus:status||0,stop:!1,ms:ms,easing:easyeasy,from:from,diff:diff,to:to,el:element,callback:params.callback,prev:prev,next:next,repeat:times||anim.times,origin:element.attr(),totalOrigin:totalOrigin},animationElements.push(e),status&&!isInAnim&&!isInAnimSet&&(e.stop=!0,e.start=new Date-ms*status,1==animationElements.length))return animation();isInAnimSet&&(e.start=new Date-e.ms*status),1==animationElements.length&&requestAnimFrame(animation)}eve(\"raphael.anim.start.\"+element.id,element,anim)}}function stopAnimation(paper){for(var i=0;i<animationElements.length;i++)animationElements[i].el.paper==paper&&animationElements.splice(i--,1)}R.version=\"2.1.2\",R.eve=eve;var loaded,paperproto,separator=/[, ]+/,elements={circle:1,rect:1,path:1,ellipse:1,text:1,image:1},formatrg=/\\{(\\d+)\\}/g,has=\"hasOwnProperty\",g={doc:document,win:window},oldRaphael={was:Object.prototype[has].call(g.win,\"Raphael\"),is:g.win.Raphael},Paper=function(){this.ca=this.customAttributes={}},apply=\"apply\",concat=\"concat\",supportsTouch=\"ontouchstart\"in g.win||g.win.DocumentTouch&&g.doc instanceof DocumentTouch,E=\"\",S=\" \",Str=String,split=\"split\",events=\"click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel\"[split](S),touchMap={mousedown:\"touchstart\",mousemove:\"touchmove\",mouseup:\"touchend\"},lowerCase=Str.prototype.toLowerCase,math=Math,mmax=math.max,mmin=math.min,abs=math.abs,pow=math.pow,PI=math.PI,nu=\"number\",string=\"string\",array=\"array\",objectToString=Object.prototype.toString,colourRegExp=(R._ISURL=/^url\\(['\"]?([^\\)]+?)['\"]?\\)$/i,/^\\s*((#[a-f\\d]{6})|(#[a-f\\d]{3})|rgba?\\(\\s*([\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+%?(?:\\s*,\\s*[\\d\\.]+%?)?)\\s*\\)|hsba?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\)|hsla?\\(\\s*([\\d\\.]+(?:deg|\\xb0|%)?\\s*,\\s*[\\d\\.]+%?\\s*,\\s*[\\d\\.]+(?:%?\\s*,\\s*[\\d\\.]+)?)%?\\s*\\))\\s*$/i),isnan={NaN:1,Infinity:1,\"-Infinity\":1},bezierrg=/^(?:cubic-)?bezier\\(([^,]+),([^,]+),([^,]+),([^\\)]+)\\)/,round=math.round,toFloat=parseFloat,toInt=parseInt,upperCase=Str.prototype.toUpperCase,availableAttrs=R._availableAttrs={\"arrow-end\":\"none\",\"arrow-start\":\"none\",blur:0,\"clip-rect\":\"0 0 1e9 1e9\",cursor:\"default\",cx:0,cy:0,fill:\"#fff\",\"fill-opacity\":1,font:'10px \"Arial\"',\"font-family\":'\"Arial\"',\"font-size\":\"10\",\"font-style\":\"normal\",\"font-weight\":400,gradient:0,height:0,href:\"http://raphaeljs.com/\",\"letter-spacing\":0,opacity:1,path:\"M0,0\",r:0,rx:0,ry:0,src:\"\",stroke:\"#000\",\"stroke-dasharray\":\"\",\"stroke-linecap\":\"butt\",\"stroke-linejoin\":\"butt\",\"stroke-miterlimit\":0,\"stroke-opacity\":1,\"stroke-width\":1,target:\"_blank\",\"text-anchor\":\"middle\",title:\"Raphael\",transform:\"\",width:0,x:0,y:0},availableAnimAttrs=R._availableAnimAttrs={blur:nu,\"clip-rect\":\"csv\",cx:nu,cy:nu,fill:\"colour\",\"fill-opacity\":nu,\"font-size\":nu,height:nu,opacity:nu,path:\"path\",r:nu,rx:nu,ry:nu,stroke:\"colour\",\"stroke-opacity\":nu,\"stroke-width\":nu,transform:\"transform\",width:nu,x:nu,y:nu},commaSpaces=/[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/,hsrg={hs:1,rg:1},p2s=/,?([achlmqrstvxz]),?/gi,pathCommand=/([achlmrqstvz])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/gi,tCommand=/([rstm])[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*)+)/gi,pathValues=/(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,?[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*/gi,eldata=(R._radial_gradient=/^r(?:\\(([^,]+?)[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*,[\\x09\\x0a\\x0b\\x0c\\x0d\\x20\\xa0\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\u2028\\u2029]*([^\\)]+?)\\))?/,{}),sortByNumber=function(a,b){return toFloat(a)-toFloat(b)},fun=function(){},pipe=function(x){return x},rectPath=R._rectPath=function(x,y,w,h,r){return r?[[\"M\",x+r,y],[\"l\",w-2*r,0],[\"a\",r,r,0,0,1,r,r],[\"l\",0,h-2*r],[\"a\",r,r,0,0,1,-r,r],[\"l\",2*r-w,0],[\"a\",r,r,0,0,1,-r,-r],[\"l\",0,2*r-h],[\"a\",r,r,0,0,1,r,-r],[\"z\"]]:[[\"M\",x,y],[\"l\",w,0],[\"l\",0,h],[\"l\",-w,0],[\"z\"]]},ellipsePath=function(x,y,rx,ry){return null==ry&&(ry=rx),[[\"M\",x,y],[\"m\",0,-ry],[\"a\",rx,ry,0,1,1,0,2*ry],[\"a\",rx,ry,0,1,1,0,-2*ry],[\"z\"]]},getPath=R._getPath={path:function(el){return el.attr(\"path\")},circle:function(el){var a=el.attrs;return ellipsePath(a.cx,a.cy,a.r)},ellipse:function(el){var a=el.attrs;return ellipsePath(a.cx,a.cy,a.rx,a.ry)},rect:function(el){var a=el.attrs;return rectPath(a.x,a.y,a.width,a.height,a.r)},image:function(el){var a=el.attrs;return rectPath(a.x,a.y,a.width,a.height)},text:function(el){var bbox=el._getBBox();return rectPath(bbox.x,bbox.y,bbox.width,bbox.height)},set:function(el){var bbox=el._getBBox();return rectPath(bbox.x,bbox.y,bbox.width,bbox.height)}},mapPath=R.mapPath=function(path,matrix){if(!matrix)return path;var x,y,i,j,ii,jj,pathi;for(path=path2curve(path),i=0,ii=path.length;i<ii;i++)for(pathi=path[i],j=1,jj=pathi.length;j<jj;j+=2)x=matrix.x(pathi[j],pathi[j+1]),y=matrix.y(pathi[j],pathi[j+1]),pathi[j]=x,pathi[j+1]=y;return path};if(R._g=g,R.type=g.win.SVGAngle||g.doc.implementation.hasFeature(\"http://www.w3.org/TR/SVG11/feature#BasicStructure\",\"1.1\")?\"SVG\":\"VML\",\"VML\"==R.type){var b,d=g.doc.createElement(\"div\");if(d.innerHTML='<v:shape adj=\"1\"/>',b=d.firstChild,b.style.behavior=\"url(#default#VML)\",!b||\"object\"!=typeof b.adj)return R.type=E;d=null}R.svg=!(R.vml=\"VML\"==R.type),R._Paper=Paper,R.fn=paperproto=Paper.prototype=R.prototype,R._id=0,R._oid=0,R.is=function(o,type){return type=lowerCase.call(type),\"finite\"==type?!isnan[has](+o):\"array\"==type?o instanceof Array:\"null\"==type&&null===o||type==typeof o&&null!==o||\"object\"==type&&o===Object(o)||\"array\"==type&&Array.isArray&&Array.isArray(o)||objectToString.call(o).slice(8,-1).toLowerCase()==type},R.angle=function(x1,y1,x2,y2,x3,y3){if(null==x3){var x=x1-x2,y=y1-y2;return x||y?(180+180*math.atan2(-y,-x)/PI+360)%360:0}return R.angle(x1,y1,x3,y3)-R.angle(x2,y2,x3,y3)},R.rad=function(deg){return deg%360*PI/180},R.deg=function(rad){return 180*rad/PI%360},R.snapTo=function(values,value,tolerance){if(tolerance=R.is(tolerance,\"finite\")?tolerance:10,R.is(values,array)){for(var i=values.length;i--;)if(abs(values[i]-value)<=tolerance)return values[i]}else{values=+values;var rem=value%values;if(rem<tolerance)return value-rem;if(rem>values-tolerance)return value-rem+values}return value};R.createUUID=function(uuidRegEx,uuidReplacer){return function(){return\"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(uuidRegEx,uuidReplacer).toUpperCase()}}(/[xy]/g,function(c){var r=16*math.random()|0,v=\"x\"==c?r:3&r|8;return v.toString(16)});R.setWindow=function(newwin){eve(\"raphael.setWindow\",R,g.win,newwin),g.win=newwin,g.doc=g.win.document,R._engine.initWin&&R._engine.initWin(g.win)};var toHex=function(color){if(R.vml){var bod,trim=/^\\s+|\\s+$/g;try{var docum=new ActiveXObject(\"htmlfile\");docum.write(\"<body>\"),docum.close(),bod=docum.body}catch(e){bod=createPopup().document.body}var range=bod.createTextRange();toHex=cacher(function(color){try{bod.style.color=Str(color).replace(trim,E);var value=range.queryCommandValue(\"ForeColor\");return value=(255&value)<<16|65280&value|(16711680&value)>>>16,\"#\"+(\"000000\"+value.toString(16)).slice(-6)}catch(e){return\"none\"}})}else{var i=g.doc.createElement(\"i\");i.title=\"Raphaël Colour Picker\",i.style.display=\"none\",g.doc.body.appendChild(i),toHex=cacher(function(color){return i.style.color=color,g.doc.defaultView.getComputedStyle(i,E).getPropertyValue(\"color\")})}return toHex(color)},hsbtoString=function(){return\"hsb(\"+[this.h,this.s,this.b]+\")\"},hsltoString=function(){return\"hsl(\"+[this.h,this.s,this.l]+\")\"},rgbtoString=function(){return this.hex},prepareRGB=function(r,g,b){if(null==g&&R.is(r,\"object\")&&\"r\"in r&&\"g\"in r&&\"b\"in r&&(b=r.b,g=r.g,r=r.r),null==g&&R.is(r,string)){var clr=R.getRGB(r);r=clr.r,g=clr.g,b=clr.b}return(r>1||g>1||b>1)&&(r/=255,g/=255,b/=255),[r,g,b]},packageRGB=function(r,g,b,o){r*=255,g*=255,b*=255;var rgb={r:r,g:g,b:b,hex:R.rgb(r,g,b),toString:rgbtoString};return R.is(o,\"finite\")&&(rgb.opacity=o),rgb};R.color=function(clr){var rgb;return R.is(clr,\"object\")&&\"h\"in clr&&\"s\"in clr&&\"b\"in clr?(rgb=R.hsb2rgb(clr),clr.r=rgb.r,clr.g=rgb.g,clr.b=rgb.b,clr.hex=rgb.hex):R.is(clr,\"object\")&&\"h\"in clr&&\"s\"in clr&&\"l\"in clr?(rgb=R.hsl2rgb(clr),clr.r=rgb.r,clr.g=rgb.g,clr.b=rgb.b,clr.hex=rgb.hex):(R.is(clr,\"string\")&&(clr=R.getRGB(clr)),R.is(clr,\"object\")&&\"r\"in clr&&\"g\"in clr&&\"b\"in clr?(rgb=R.rgb2hsl(clr),clr.h=rgb.h,clr.s=rgb.s,clr.l=rgb.l,rgb=R.rgb2hsb(clr),clr.v=rgb.b):(clr={hex:\"none\"},clr.r=clr.g=clr.b=clr.h=clr.s=clr.v=clr.l=-1)),clr.toString=rgbtoString,clr},R.hsb2rgb=function(h,s,v,o){this.is(h,\"object\")&&\"h\"in h&&\"s\"in h&&\"b\"in h&&(v=h.b,s=h.s,h=h.h,o=h.o),h*=360;var R,G,B,X,C;return h=h%360/60,C=v*s,X=C*(1-abs(h%2-1)),R=G=B=v-C,h=~~h,R+=[C,X,0,0,X,C][h],G+=[X,C,C,X,0,0][h],B+=[0,0,X,C,C,X][h],packageRGB(R,G,B,o)},R.hsl2rgb=function(h,s,l,o){this.is(h,\"object\")&&\"h\"in h&&\"s\"in h&&\"l\"in h&&(l=h.l,s=h.s,h=h.h),(h>1||s>1||l>1)&&(h/=360,s/=100,l/=100),h*=360;var R,G,B,X,C;return h=h%360/60,C=2*s*(l<.5?l:1-l),X=C*(1-abs(h%2-1)),R=G=B=l-C/2,h=~~h,R+=[C,X,0,0,X,C][h],G+=[X,C,C,X,0,0][h],B+=[0,0,X,C,C,X][h],packageRGB(R,G,B,o)},R.rgb2hsb=function(r,g,b){b=prepareRGB(r,g,b),r=b[0],g=b[1],b=b[2];var H,S,V,C;return V=mmax(r,g,b),C=V-mmin(r,g,b),H=0==C?null:V==r?(g-b)/C:V==g?(b-r)/C+2:(r-g)/C+4,H=(H+360)%6*60/360,S=0==C?0:C/V,{h:H,s:S,b:V,toString:hsbtoString}},R.rgb2hsl=function(r,g,b){b=prepareRGB(r,g,b),r=b[0],g=b[1],b=b[2];var H,S,L,M,m,C;return M=mmax(r,g,b),m=mmin(r,g,b),C=M-m,H=0==C?null:M==r?(g-b)/C:M==g?(b-r)/C+2:(r-g)/C+4,H=(H+360)%6*60/360,L=(M+m)/2,S=0==C?0:L<.5?C/(2*L):C/(2-2*L),{h:H,s:S,l:L,toString:hsltoString}},R._path2string=function(){return this.join(\",\").replace(p2s,\"$1\")};R._preload=function(src,f){var img=g.doc.createElement(\"img\");img.style.cssText=\"position:absolute;left:-9999em;top:-9999em\",img.onload=function(){f.call(this),this.onload=null,g.doc.body.removeChild(this)},img.onerror=function(){g.doc.body.removeChild(this)},g.doc.body.appendChild(img),img.src=src};R.getRGB=cacher(function(colour){if(!colour||(colour=Str(colour)).indexOf(\"-\")+1)return{r:-1,g:-1,b:-1,hex:\"none\",error:1,toString:clrToString};if(\"none\"==colour)return{r:-1,g:-1,b:-1,hex:\"none\",toString:clrToString};!(hsrg[has](colour.toLowerCase().substring(0,2))||\"#\"==colour.charAt())&&(colour=toHex(colour));var red,green,blue,opacity,t,values,rgb=colour.match(colourRegExp);return rgb?(rgb[2]&&(blue=toInt(rgb[2].substring(5),16),green=toInt(rgb[2].substring(3,5),16),red=toInt(rgb[2].substring(1,3),16)),rgb[3]&&(blue=toInt((t=rgb[3].charAt(3))+t,16),green=toInt((t=rgb[3].charAt(2))+t,16),red=toInt((t=rgb[3].charAt(1))+t,16)),rgb[4]&&(values=rgb[4][split](commaSpaces),red=toFloat(values[0]),\"%\"==values[0].slice(-1)&&(red*=2.55),green=toFloat(values[1]),\"%\"==values[1].slice(-1)&&(green*=2.55),blue=toFloat(values[2]),\"%\"==values[2].slice(-1)&&(blue*=2.55),\"rgba\"==rgb[1].toLowerCase().slice(0,4)&&(opacity=toFloat(values[3])),values[3]&&\"%\"==values[3].slice(-1)&&(opacity/=100)),rgb[5]?(values=rgb[5][split](commaSpaces),red=toFloat(values[0]),\"%\"==values[0].slice(-1)&&(red*=2.55),green=toFloat(values[1]),\"%\"==values[1].slice(-1)&&(green*=2.55),blue=toFloat(values[2]),\"%\"==values[2].slice(-1)&&(blue*=2.55),(\"deg\"==values[0].slice(-3)||\"°\"==values[0].slice(-1))&&(red/=360),\"hsba\"==rgb[1].toLowerCase().slice(0,4)&&(opacity=toFloat(values[3])),values[3]&&\"%\"==values[3].slice(-1)&&(opacity/=100),R.hsb2rgb(red,green,blue,opacity)):rgb[6]?(values=rgb[6][split](commaSpaces),red=toFloat(values[0]),\"%\"==values[0].slice(-1)&&(red*=2.55),green=toFloat(values[1]),\"%\"==values[1].slice(-1)&&(green*=2.55),blue=toFloat(values[2]),\"%\"==values[2].slice(-1)&&(blue*=2.55),(\"deg\"==values[0].slice(-3)||\"°\"==values[0].slice(-1))&&(red/=360),\"hsla\"==rgb[1].toLowerCase().slice(0,4)&&(opacity=toFloat(values[3])),values[3]&&\"%\"==values[3].slice(-1)&&(opacity/=100),R.hsl2rgb(red,green,blue,opacity)):(rgb={r:red,g:green,b:blue,toString:clrToString},rgb.hex=\"#\"+(16777216|blue|green<<8|red<<16).toString(16).slice(1),R.is(opacity,\"finite\")&&(rgb.opacity=opacity),rgb)):{r:-1,g:-1,b:-1,hex:\"none\",error:1,toString:clrToString}},R),R.hsb=cacher(function(h,s,b){return R.hsb2rgb(h,s,b).hex}),R.hsl=cacher(function(h,s,l){return R.hsl2rgb(h,s,l).hex}),R.rgb=cacher(function(r,g,b){return\"#\"+(16777216|b|g<<8|r<<16).toString(16).slice(1)}),R.getColor=function(value){var start=this.getColor.start=this.getColor.start||{h:0,s:1,b:value||.75},rgb=this.hsb2rgb(start.h,start.s,start.b);return start.h+=.075,start.h>1&&(start.h=0,start.s-=.2,start.s<=0&&(this.getColor.start={h:0,s:1,b:start.b})),rgb.hex},R.getColor.reset=function(){delete this.start},R.parsePathString=function(pathString){if(!pathString)return null;var pth=paths(pathString);if(pth.arr)return pathClone(pth.arr);var paramCounts={a:7,c:6,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,z:0},data=[];return R.is(pathString,array)&&R.is(pathString[0],array)&&(data=pathClone(pathString)),data.length||Str(pathString).replace(pathCommand,function(a,b,c){var params=[],name=b.toLowerCase();if(c.replace(pathValues,function(a,b){b&&params.push(+b)}),\"m\"==name&&params.length>2&&(data.push([b][concat](params.splice(0,2))),name=\"l\",b=\"m\"==b?\"l\":\"L\"),\"r\"==name)data.push([b][concat](params));else for(;params.length>=paramCounts[name]&&(data.push([b][concat](params.splice(0,paramCounts[name]))),paramCounts[name]););}),data.toString=R._path2string,pth.arr=pathClone(data),data},R.parseTransformString=cacher(function(TString){if(!TString)return null;var data=[];return R.is(TString,array)&&R.is(TString[0],array)&&(data=pathClone(TString)),data.length||Str(TString).replace(tCommand,function(a,b,c){var params=[];lowerCase.call(b);c.replace(pathValues,function(a,b){b&&params.push(+b)}),data.push([b][concat](params))}),data.toString=R._path2string,data});var paths=function(ps){var p=paths.ps=paths.ps||{};return p[ps]?p[ps].sleep=1:p[ps]={sleep:1},setTimeout(function(){for(var key in p)p[has](key)&&key!=ps&&(p[key].sleep--,!p[key].sleep&&delete p[key])}),p[ps]};R.findDotsAtSegment=function(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,t){var t1=1-t,t13=pow(t1,3),t12=pow(t1,2),t2=t*t,t3=t2*t,x=t13*p1x+3*t12*t*c1x+3*t1*t*t*c2x+t3*p2x,y=t13*p1y+3*t12*t*c1y+3*t1*t*t*c2y+t3*p2y,mx=p1x+2*t*(c1x-p1x)+t2*(c2x-2*c1x+p1x),my=p1y+2*t*(c1y-p1y)+t2*(c2y-2*c1y+p1y),nx=c1x+2*t*(c2x-c1x)+t2*(p2x-2*c2x+c1x),ny=c1y+2*t*(c2y-c1y)+t2*(p2y-2*c2y+c1y),ax=t1*p1x+t*c1x,ay=t1*p1y+t*c1y,cx=t1*c2x+t*p2x,cy=t1*c2y+t*p2y,alpha=90-180*math.atan2(mx-nx,my-ny)/PI;return(mx>nx||my<ny)&&(alpha+=180),{x:x,y:y,m:{x:mx,y:my},n:{x:nx,y:ny},start:{x:ax,y:ay},end:{x:cx,y:cy},alpha:alpha}},R.bezierBBox=function(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y){R.is(p1x,\"array\")||(p1x=[p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y]);var bbox=curveDim.apply(null,p1x);return{x:bbox.min.x,y:bbox.min.y,x2:bbox.max.x,y2:bbox.max.y,width:bbox.max.x-bbox.min.x,height:bbox.max.y-bbox.min.y}},R.isPointInsideBBox=function(bbox,x,y){return x>=bbox.x&&x<=bbox.x2&&y>=bbox.y&&y<=bbox.y2},R.isBBoxIntersect=function(bbox1,bbox2){var i=R.isPointInsideBBox;return i(bbox2,bbox1.x,bbox1.y)||i(bbox2,bbox1.x2,bbox1.y)||i(bbox2,bbox1.x,bbox1.y2)||i(bbox2,bbox1.x2,bbox1.y2)||i(bbox1,bbox2.x,bbox2.y)||i(bbox1,bbox2.x2,bbox2.y)||i(bbox1,bbox2.x,bbox2.y2)||i(bbox1,bbox2.x2,bbox2.y2)||(bbox1.x<bbox2.x2&&bbox1.x>bbox2.x||bbox2.x<bbox1.x2&&bbox2.x>bbox1.x)&&(bbox1.y<bbox2.y2&&bbox1.y>bbox2.y||bbox2.y<bbox1.y2&&bbox2.y>bbox1.y)},R.pathIntersection=function(path1,path2){return interPathHelper(path1,path2)},R.pathIntersectionNumber=function(path1,path2){return interPathHelper(path1,path2,1)},R.isPointInsidePath=function(path,x,y){var bbox=R.pathBBox(path);return R.isPointInsideBBox(bbox,x,y)&&interPathHelper(path,[[\"M\",x,y],[\"H\",bbox.x2+10]],1)%2==1},R._removedFactory=function(methodname){return function(){eve(\"raphael.log\",null,\"Raphaël: you are calling to method “\"+methodname+\"” of removed object\",methodname)}};var pathDimensions=R.pathBBox=function(path){var pth=paths(path);if(pth.bbox)return clone(pth.bbox);if(!path)return{x:0,y:0,width:0,height:0,x2:0,y2:0};path=path2curve(path);for(var p,x=0,y=0,X=[],Y=[],i=0,ii=path.length;i<ii;i++)if(p=path[i],\"M\"==p[0])x=p[1],y=p[2],X.push(x),Y.push(y);else{var dim=curveDim(x,y,p[1],p[2],p[3],p[4],p[5],p[6]);X=X[concat](dim.min.x,dim.max.x),Y=Y[concat](dim.min.y,dim.max.y),x=p[5],y=p[6]}var xmin=mmin[apply](0,X),ymin=mmin[apply](0,Y),xmax=mmax[apply](0,X),ymax=mmax[apply](0,Y),width=xmax-xmin,height=ymax-ymin,bb={x:xmin,y:ymin,x2:xmax,y2:ymax,width:width,height:height,cx:xmin+width/2,cy:ymin+height/2};return pth.bbox=clone(bb),bb},pathClone=function(pathArray){var res=clone(pathArray);return res.toString=R._path2string,res},pathToRelative=R._pathToRelative=function(pathArray){var pth=paths(pathArray);if(pth.rel)return pathClone(pth.rel);R.is(pathArray,array)&&R.is(pathArray&&pathArray[0],array)||(pathArray=R.parsePathString(pathArray));\nvar res=[],x=0,y=0,mx=0,my=0,start=0;\"M\"==pathArray[0][0]&&(x=pathArray[0][1],y=pathArray[0][2],mx=x,my=y,start++,res.push([\"M\",x,y]));for(var i=start,ii=pathArray.length;i<ii;i++){var r=res[i]=[],pa=pathArray[i];if(pa[0]!=lowerCase.call(pa[0]))switch(r[0]=lowerCase.call(pa[0]),r[0]){case\"a\":r[1]=pa[1],r[2]=pa[2],r[3]=pa[3],r[4]=pa[4],r[5]=pa[5],r[6]=+(pa[6]-x).toFixed(3),r[7]=+(pa[7]-y).toFixed(3);break;case\"v\":r[1]=+(pa[1]-y).toFixed(3);break;case\"m\":mx=pa[1],my=pa[2];default:for(var j=1,jj=pa.length;j<jj;j++)r[j]=+(pa[j]-(j%2?x:y)).toFixed(3)}else{r=res[i]=[],\"m\"==pa[0]&&(mx=pa[1]+x,my=pa[2]+y);for(var k=0,kk=pa.length;k<kk;k++)res[i][k]=pa[k]}var len=res[i].length;switch(res[i][0]){case\"z\":x=mx,y=my;break;case\"h\":x+=+res[i][len-1];break;case\"v\":y+=+res[i][len-1];break;default:x+=+res[i][len-2],y+=+res[i][len-1]}}return res.toString=R._path2string,pth.rel=pathClone(res),res},pathToAbsolute=R._pathToAbsolute=function(pathArray){var pth=paths(pathArray);if(pth.abs)return pathClone(pth.abs);if(R.is(pathArray,array)&&R.is(pathArray&&pathArray[0],array)||(pathArray=R.parsePathString(pathArray)),!pathArray||!pathArray.length)return[[\"M\",0,0]];var res=[],x=0,y=0,mx=0,my=0,start=0;\"M\"==pathArray[0][0]&&(x=+pathArray[0][1],y=+pathArray[0][2],mx=x,my=y,start++,res[0]=[\"M\",x,y]);for(var r,pa,crz=3==pathArray.length&&\"M\"==pathArray[0][0]&&\"R\"==pathArray[1][0].toUpperCase()&&\"Z\"==pathArray[2][0].toUpperCase(),i=start,ii=pathArray.length;i<ii;i++){if(res.push(r=[]),pa=pathArray[i],pa[0]!=upperCase.call(pa[0]))switch(r[0]=upperCase.call(pa[0]),r[0]){case\"A\":r[1]=pa[1],r[2]=pa[2],r[3]=pa[3],r[4]=pa[4],r[5]=pa[5],r[6]=+(pa[6]+x),r[7]=+(pa[7]+y);break;case\"V\":r[1]=+pa[1]+y;break;case\"H\":r[1]=+pa[1]+x;break;case\"R\":for(var dots=[x,y][concat](pa.slice(1)),j=2,jj=dots.length;j<jj;j++)dots[j]=+dots[j]+x,dots[++j]=+dots[j]+y;res.pop(),res=res[concat](catmullRom2bezier(dots,crz));break;case\"M\":mx=+pa[1]+x,my=+pa[2]+y;default:for(j=1,jj=pa.length;j<jj;j++)r[j]=+pa[j]+(j%2?x:y)}else if(\"R\"==pa[0])dots=[x,y][concat](pa.slice(1)),res.pop(),res=res[concat](catmullRom2bezier(dots,crz)),r=[\"R\"][concat](pa.slice(-2));else for(var k=0,kk=pa.length;k<kk;k++)r[k]=pa[k];switch(r[0]){case\"Z\":x=mx,y=my;break;case\"H\":x=r[1];break;case\"V\":y=r[1];break;case\"M\":mx=r[r.length-2],my=r[r.length-1];default:x=r[r.length-2],y=r[r.length-1]}}return res.toString=R._path2string,pth.abs=pathClone(res),res},l2c=function(x1,y1,x2,y2){return[x1,y1,x2,y2,x2,y2]},q2c=function(x1,y1,ax,ay,x2,y2){var _13=1/3,_23=2/3;return[_13*x1+_23*ax,_13*y1+_23*ay,_13*x2+_23*ax,_13*y2+_23*ay,x2,y2]},a2c=function(x1,y1,rx,ry,angle,large_arc_flag,sweep_flag,x2,y2,recursive){var xy,_120=120*PI/180,rad=PI/180*(+angle||0),res=[],rotate=cacher(function(x,y,rad){var X=x*math.cos(rad)-y*math.sin(rad),Y=x*math.sin(rad)+y*math.cos(rad);return{x:X,y:Y}});if(recursive)f1=recursive[0],f2=recursive[1],cx=recursive[2],cy=recursive[3];else{xy=rotate(x1,y1,-rad),x1=xy.x,y1=xy.y,xy=rotate(x2,y2,-rad),x2=xy.x,y2=xy.y;var x=(math.cos(PI/180*angle),math.sin(PI/180*angle),(x1-x2)/2),y=(y1-y2)/2,h=x*x/(rx*rx)+y*y/(ry*ry);h>1&&(h=math.sqrt(h),rx*=h,ry*=h);var rx2=rx*rx,ry2=ry*ry,k=(large_arc_flag==sweep_flag?-1:1)*math.sqrt(abs((rx2*ry2-rx2*y*y-ry2*x*x)/(rx2*y*y+ry2*x*x))),cx=k*rx*y/ry+(x1+x2)/2,cy=k*-ry*x/rx+(y1+y2)/2,f1=math.asin(((y1-cy)/ry).toFixed(9)),f2=math.asin(((y2-cy)/ry).toFixed(9));f1=x1<cx?PI-f1:f1,f2=x2<cx?PI-f2:f2,f1<0&&(f1=2*PI+f1),f2<0&&(f2=2*PI+f2),sweep_flag&&f1>f2&&(f1-=2*PI),!sweep_flag&&f2>f1&&(f2-=2*PI)}var df=f2-f1;if(abs(df)>_120){var f2old=f2,x2old=x2,y2old=y2;f2=f1+_120*(sweep_flag&&f2>f1?1:-1),x2=cx+rx*math.cos(f2),y2=cy+ry*math.sin(f2),res=a2c(x2,y2,rx,ry,angle,0,sweep_flag,x2old,y2old,[f2,f2old,cx,cy])}df=f2-f1;var c1=math.cos(f1),s1=math.sin(f1),c2=math.cos(f2),s2=math.sin(f2),t=math.tan(df/4),hx=4/3*rx*t,hy=4/3*ry*t,m1=[x1,y1],m2=[x1+hx*s1,y1-hy*c1],m3=[x2+hx*s2,y2-hy*c2],m4=[x2,y2];if(m2[0]=2*m1[0]-m2[0],m2[1]=2*m1[1]-m2[1],recursive)return[m2,m3,m4][concat](res);res=[m2,m3,m4][concat](res).join()[split](\",\");for(var newres=[],i=0,ii=res.length;i<ii;i++)newres[i]=i%2?rotate(res[i-1],res[i],rad).y:rotate(res[i],res[i+1],rad).x;return newres},findDotAtSegment=function(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,t){var t1=1-t;return{x:pow(t1,3)*p1x+3*pow(t1,2)*t*c1x+3*t1*t*t*c2x+pow(t,3)*p2x,y:pow(t1,3)*p1y+3*pow(t1,2)*t*c1y+3*t1*t*t*c2y+pow(t,3)*p2y}},curveDim=cacher(function(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y){var dot,a=c2x-2*c1x+p1x-(p2x-2*c2x+c1x),b=2*(c1x-p1x)-2*(c2x-c1x),c=p1x-c1x,t1=(-b+math.sqrt(b*b-4*a*c))/2/a,t2=(-b-math.sqrt(b*b-4*a*c))/2/a,y=[p1y,p2y],x=[p1x,p2x];return abs(t1)>\"1e12\"&&(t1=.5),abs(t2)>\"1e12\"&&(t2=.5),t1>0&&t1<1&&(dot=findDotAtSegment(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,t1),x.push(dot.x),y.push(dot.y)),t2>0&&t2<1&&(dot=findDotAtSegment(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,t2),x.push(dot.x),y.push(dot.y)),a=c2y-2*c1y+p1y-(p2y-2*c2y+c1y),b=2*(c1y-p1y)-2*(c2y-c1y),c=p1y-c1y,t1=(-b+math.sqrt(b*b-4*a*c))/2/a,t2=(-b-math.sqrt(b*b-4*a*c))/2/a,abs(t1)>\"1e12\"&&(t1=.5),abs(t2)>\"1e12\"&&(t2=.5),t1>0&&t1<1&&(dot=findDotAtSegment(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,t1),x.push(dot.x),y.push(dot.y)),t2>0&&t2<1&&(dot=findDotAtSegment(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,t2),x.push(dot.x),y.push(dot.y)),{min:{x:mmin[apply](0,x),y:mmin[apply](0,y)},max:{x:mmax[apply](0,x),y:mmax[apply](0,y)}}}),path2curve=R._path2curve=cacher(function(path,path2){var pth=!path2&&paths(path);if(!path2&&pth.curve)return pathClone(pth.curve);for(var p=pathToAbsolute(path),p2=path2&&pathToAbsolute(path2),attrs={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},attrs2={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},processPath=(function(path,d,pcom){var nx,ny;if(!path)return[\"C\",d.x,d.y,d.x,d.y,d.x,d.y];switch(!(path[0]in{T:1,Q:1})&&(d.qx=d.qy=null),path[0]){case\"M\":d.X=path[1],d.Y=path[2];break;case\"A\":path=[\"C\"][concat](a2c[apply](0,[d.x,d.y][concat](path.slice(1))));break;case\"S\":\"C\"==pcom||\"S\"==pcom?(nx=2*d.x-d.bx,ny=2*d.y-d.by):(nx=d.x,ny=d.y),path=[\"C\",nx,ny][concat](path.slice(1));break;case\"T\":\"Q\"==pcom||\"T\"==pcom?(d.qx=2*d.x-d.qx,d.qy=2*d.y-d.qy):(d.qx=d.x,d.qy=d.y),path=[\"C\"][concat](q2c(d.x,d.y,d.qx,d.qy,path[1],path[2]));break;case\"Q\":d.qx=path[1],d.qy=path[2],path=[\"C\"][concat](q2c(d.x,d.y,path[1],path[2],path[3],path[4]));break;case\"L\":path=[\"C\"][concat](l2c(d.x,d.y,path[1],path[2]));break;case\"H\":path=[\"C\"][concat](l2c(d.x,d.y,path[1],d.y));break;case\"V\":path=[\"C\"][concat](l2c(d.x,d.y,d.x,path[1]));break;case\"Z\":path=[\"C\"][concat](l2c(d.x,d.y,d.X,d.Y))}return path}),fixArc=function(pp,i){if(pp[i].length>7){pp[i].shift();for(var pi=pp[i];pi.length;)pp.splice(i++,0,[\"C\"][concat](pi.splice(0,6)));pp.splice(i,1),ii=mmax(p.length,p2&&p2.length||0)}},fixM=function(path1,path2,a1,a2,i){path1&&path2&&\"M\"==path1[i][0]&&\"M\"!=path2[i][0]&&(path2.splice(i,0,[\"M\",a2.x,a2.y]),a1.bx=0,a1.by=0,a1.x=path1[i][1],a1.y=path1[i][2],ii=mmax(p.length,p2&&p2.length||0))},i=0,ii=mmax(p.length,p2&&p2.length||0);i<ii;i++){p[i]=processPath(p[i],attrs),fixArc(p,i),p2&&(p2[i]=processPath(p2[i],attrs2)),p2&&fixArc(p2,i),fixM(p,p2,attrs,attrs2,i),fixM(p2,p,attrs2,attrs,i);var seg=p[i],seg2=p2&&p2[i],seglen=seg.length,seg2len=p2&&seg2.length;attrs.x=seg[seglen-2],attrs.y=seg[seglen-1],attrs.bx=toFloat(seg[seglen-4])||attrs.x,attrs.by=toFloat(seg[seglen-3])||attrs.y,attrs2.bx=p2&&(toFloat(seg2[seg2len-4])||attrs2.x),attrs2.by=p2&&(toFloat(seg2[seg2len-3])||attrs2.y),attrs2.x=p2&&seg2[seg2len-2],attrs2.y=p2&&seg2[seg2len-1]}return p2||(pth.curve=pathClone(p)),p2?[p,p2]:p},null,pathClone),tear=(R._parseDots=cacher(function(gradient){for(var dots=[],i=0,ii=gradient.length;i<ii;i++){var dot={},par=gradient[i].match(/^([^:]*):?([\\d\\.]*)/);if(dot.color=R.getRGB(par[1]),dot.color.error)return null;dot.color=dot.color.hex,par[2]&&(dot.offset=par[2]+\"%\"),dots.push(dot)}for(i=1,ii=dots.length-1;i<ii;i++)if(!dots[i].offset){for(var start=toFloat(dots[i-1].offset||0),end=0,j=i+1;j<ii;j++)if(dots[j].offset){end=dots[j].offset;break}end||(end=100,j=ii),end=toFloat(end);for(var d=(end-start)/(j-i+1);i<j;i++)start+=d,dots[i].offset=start+\"%\"}return dots}),R._tear=function(el,paper){el==paper.top&&(paper.top=el.prev),el==paper.bottom&&(paper.bottom=el.next),el.next&&(el.next.prev=el.prev),el.prev&&(el.prev.next=el.next)}),toMatrix=(R._tofront=function(el,paper){paper.top!==el&&(tear(el,paper),el.next=null,el.prev=paper.top,paper.top.next=el,paper.top=el)},R._toback=function(el,paper){paper.bottom!==el&&(tear(el,paper),el.next=paper.bottom,el.prev=null,paper.bottom.prev=el,paper.bottom=el)},R._insertafter=function(el,el2,paper){tear(el,paper),el2==paper.top&&(paper.top=el),el2.next&&(el2.next.prev=el),el.next=el2.next,el.prev=el2,el2.next=el},R._insertbefore=function(el,el2,paper){tear(el,paper),el2==paper.bottom&&(paper.bottom=el),el2.prev&&(el2.prev.next=el),el.prev=el2.prev,el2.prev=el,el.next=el2},R.toMatrix=function(path,transform){var bb=pathDimensions(path),el={_:{transform:E},getBBox:function(){return bb}};return extractTransform(el,transform),el.matrix}),extractTransform=(R.transformPath=function(path,transform){return mapPath(path,toMatrix(path,transform))},R._extractTransform=function(el,tstr){if(null==tstr)return el._.transform;tstr=Str(tstr).replace(/\\.{3}|\\u2026/g,el._.transform||E);var tdata=R.parseTransformString(tstr),deg=0,dx=0,dy=0,sx=1,sy=1,_=el._,m=new Matrix;if(_.transform=tdata||[],tdata)for(var i=0,ii=tdata.length;i<ii;i++){var x1,y1,x2,y2,bb,t=tdata[i],tlen=t.length,command=Str(t[0]).toLowerCase(),absolute=t[0]!=command,inver=absolute?m.invert():0;\"t\"==command&&3==tlen?absolute?(x1=inver.x(0,0),y1=inver.y(0,0),x2=inver.x(t[1],t[2]),y2=inver.y(t[1],t[2]),m.translate(x2-x1,y2-y1)):m.translate(t[1],t[2]):\"r\"==command?2==tlen?(bb=bb||el.getBBox(1),m.rotate(t[1],bb.x+bb.width/2,bb.y+bb.height/2),deg+=t[1]):4==tlen&&(absolute?(x2=inver.x(t[2],t[3]),y2=inver.y(t[2],t[3]),m.rotate(t[1],x2,y2)):m.rotate(t[1],t[2],t[3]),deg+=t[1]):\"s\"==command?2==tlen||3==tlen?(bb=bb||el.getBBox(1),m.scale(t[1],t[tlen-1],bb.x+bb.width/2,bb.y+bb.height/2),sx*=t[1],sy*=t[tlen-1]):5==tlen&&(absolute?(x2=inver.x(t[3],t[4]),y2=inver.y(t[3],t[4]),m.scale(t[1],t[2],x2,y2)):m.scale(t[1],t[2],t[3],t[4]),sx*=t[1],sy*=t[2]):\"m\"==command&&7==tlen&&m.add(t[1],t[2],t[3],t[4],t[5],t[6]),_.dirtyT=1,el.matrix=m}el.matrix=m,_.sx=sx,_.sy=sy,_.deg=deg,_.dx=dx=m.e,_.dy=dy=m.f,1==sx&&1==sy&&!deg&&_.bbox?(_.bbox.x+=+dx,_.bbox.y+=+dy):_.dirtyT=1}),getEmpty=function(item){var l=item[0];switch(l.toLowerCase()){case\"t\":return[l,0,0];case\"m\":return[l,1,0,0,1,0,0];case\"r\":return 4==item.length?[l,0,item[2],item[3]]:[l,0];case\"s\":return 5==item.length?[l,1,1,item[3],item[4]]:3==item.length?[l,1,1]:[l,1]}},equaliseTransform=R._equaliseTransform=function(t1,t2){t2=Str(t2).replace(/\\.{3}|\\u2026/g,t1),t1=R.parseTransformString(t1)||[],t2=R.parseTransformString(t2)||[];for(var j,jj,tt1,tt2,maxlength=mmax(t1.length,t2.length),from=[],to=[],i=0;i<maxlength;i++){if(tt1=t1[i]||getEmpty(t2[i]),tt2=t2[i]||getEmpty(tt1),tt1[0]!=tt2[0]||\"r\"==tt1[0].toLowerCase()&&(tt1[2]!=tt2[2]||tt1[3]!=tt2[3])||\"s\"==tt1[0].toLowerCase()&&(tt1[3]!=tt2[3]||tt1[4]!=tt2[4]))return;for(from[i]=[],to[i]=[],j=0,jj=mmax(tt1.length,tt2.length);j<jj;j++)j in tt1&&(from[i][j]=tt1[j]),j in tt2&&(to[i][j]=tt2[j])}return{from:from,to:to}};R._getContainer=function(x,y,w,h){var container;if(container=null!=h||R.is(x,\"object\")?x:g.doc.getElementById(x),null!=container)return container.tagName?null==y?{container:container,width:container.style.pixelWidth||container.offsetWidth,height:container.style.pixelHeight||container.offsetHeight}:{container:container,width:y,height:w}:{container:1,x:x,y:y,width:w,height:h}},R.pathToRelative=pathToRelative,R._engine={},R.path2curve=path2curve,R.matrix=function(a,b,c,d,e,f){return new Matrix(a,b,c,d,e,f)},function(matrixproto){function norm(a){return a[0]*a[0]+a[1]*a[1]}function normalize(a){var mag=math.sqrt(norm(a));a[0]&&(a[0]/=mag),a[1]&&(a[1]/=mag)}matrixproto.add=function(a,b,c,d,e,f){var x,y,z,res,out=[[],[],[]],m=[[this.a,this.c,this.e],[this.b,this.d,this.f],[0,0,1]],matrix=[[a,c,e],[b,d,f],[0,0,1]];for(a&&a instanceof Matrix&&(matrix=[[a.a,a.c,a.e],[a.b,a.d,a.f],[0,0,1]]),x=0;x<3;x++)for(y=0;y<3;y++){for(res=0,z=0;z<3;z++)res+=m[x][z]*matrix[z][y];out[x][y]=res}this.a=out[0][0],this.b=out[1][0],this.c=out[0][1],this.d=out[1][1],this.e=out[0][2],this.f=out[1][2]},matrixproto.invert=function(){var me=this,x=me.a*me.d-me.b*me.c;return new Matrix(me.d/x,-me.b/x,-me.c/x,me.a/x,(me.c*me.f-me.d*me.e)/x,(me.b*me.e-me.a*me.f)/x)},matrixproto.clone=function(){return new Matrix(this.a,this.b,this.c,this.d,this.e,this.f)},matrixproto.translate=function(x,y){this.add(1,0,0,1,x,y)},matrixproto.scale=function(x,y,cx,cy){null==y&&(y=x),(cx||cy)&&this.add(1,0,0,1,cx,cy),this.add(x,0,0,y,0,0),(cx||cy)&&this.add(1,0,0,1,-cx,-cy)},matrixproto.rotate=function(a,x,y){a=R.rad(a),x=x||0,y=y||0;var cos=+math.cos(a).toFixed(9),sin=+math.sin(a).toFixed(9);this.add(cos,sin,-sin,cos,x,y),this.add(1,0,0,1,-x,-y)},matrixproto.x=function(x,y){return x*this.a+y*this.c+this.e},matrixproto.y=function(x,y){return x*this.b+y*this.d+this.f},matrixproto.get=function(i){return+this[Str.fromCharCode(97+i)].toFixed(4)},matrixproto.toString=function(){return R.svg?\"matrix(\"+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)].join()+\")\":[this.get(0),this.get(2),this.get(1),this.get(3),0,0].join()},matrixproto.toFilter=function(){return\"progid:DXImageTransform.Microsoft.Matrix(M11=\"+this.get(0)+\", M12=\"+this.get(2)+\", M21=\"+this.get(1)+\", M22=\"+this.get(3)+\", Dx=\"+this.get(4)+\", Dy=\"+this.get(5)+\", sizingmethod='auto expand')\"},matrixproto.offset=function(){return[this.e.toFixed(4),this.f.toFixed(4)]},matrixproto.split=function(){var out={};out.dx=this.e,out.dy=this.f;var row=[[this.a,this.c],[this.b,this.d]];out.scalex=math.sqrt(norm(row[0])),normalize(row[0]),out.shear=row[0][0]*row[1][0]+row[0][1]*row[1][1],row[1]=[row[1][0]-row[0][0]*out.shear,row[1][1]-row[0][1]*out.shear],out.scaley=math.sqrt(norm(row[1])),normalize(row[1]),out.shear/=out.scaley;var sin=-row[0][1],cos=row[1][1];return cos<0?(out.rotate=R.deg(math.acos(cos)),sin<0&&(out.rotate=360-out.rotate)):out.rotate=R.deg(math.asin(sin)),out.isSimple=!(+out.shear.toFixed(9)||out.scalex.toFixed(9)!=out.scaley.toFixed(9)&&out.rotate),out.isSuperSimple=!+out.shear.toFixed(9)&&out.scalex.toFixed(9)==out.scaley.toFixed(9)&&!out.rotate,out.noRotation=!+out.shear.toFixed(9)&&!out.rotate,out},matrixproto.toTransformString=function(shorter){var s=shorter||this[split]();return s.isSimple?(s.scalex=+s.scalex.toFixed(4),s.scaley=+s.scaley.toFixed(4),s.rotate=+s.rotate.toFixed(4),(s.dx||s.dy?\"t\"+[s.dx,s.dy]:E)+(1!=s.scalex||1!=s.scaley?\"s\"+[s.scalex,s.scaley,0,0]:E)+(s.rotate?\"r\"+[s.rotate,0,0]:E)):\"m\"+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)]}}(Matrix.prototype);var version=navigator.userAgent.match(/Version\\/(.*?)\\s/)||navigator.userAgent.match(/Chrome\\/(\\d+)/);\"Apple Computer, Inc.\"==navigator.vendor&&(version&&version[1]<4||\"iP\"==navigator.platform.slice(0,2))||\"Google Inc.\"==navigator.vendor&&version&&version[1]<8?paperproto.safari=function(){var rect=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:\"none\"});setTimeout(function(){rect.remove()})}:paperproto.safari=fun;for(var preventDefault=function(){this.returnValue=!1},preventTouch=function(){return this.originalEvent.preventDefault()},stopPropagation=function(){this.cancelBubble=!0},stopTouch=function(){return this.originalEvent.stopPropagation()},getEventPosition=function(e){var scrollY=g.doc.documentElement.scrollTop||g.doc.body.scrollTop,scrollX=g.doc.documentElement.scrollLeft||g.doc.body.scrollLeft;return{x:e.clientX+scrollX,y:e.clientY+scrollY}},addEvent=function(){return g.doc.addEventListener?function(obj,type,fn,element){var f=function(e){var pos=getEventPosition(e);return fn.call(element,e,pos.x,pos.y)};if(obj.addEventListener(type,f,!1),supportsTouch&&touchMap[type]){var _f=function(e){for(var pos=getEventPosition(e),olde=e,i=0,ii=e.targetTouches&&e.targetTouches.length;i<ii;i++)if(e.targetTouches[i].target==obj){e=e.targetTouches[i],e.originalEvent=olde,e.preventDefault=preventTouch,e.stopPropagation=stopTouch;break}return fn.call(element,e,pos.x,pos.y)};obj.addEventListener(touchMap[type],_f,!1)}return function(){return obj.removeEventListener(type,f,!1),supportsTouch&&touchMap[type]&&obj.removeEventListener(touchMap[type],f,!1),!0}}:g.doc.attachEvent?function(obj,type,fn,element){var f=function(e){e=e||g.win.event;var scrollY=g.doc.documentElement.scrollTop||g.doc.body.scrollTop,scrollX=g.doc.documentElement.scrollLeft||g.doc.body.scrollLeft,x=e.clientX+scrollX,y=e.clientY+scrollY;return e.preventDefault=e.preventDefault||preventDefault,e.stopPropagation=e.stopPropagation||stopPropagation,fn.call(element,e,x,y)};obj.attachEvent(\"on\"+type,f);var detacher=function(){return obj.detachEvent(\"on\"+type,f),!0};return detacher}:void 0}(),drag=[],dragMove=function(e){for(var dragi,x=e.clientX,y=e.clientY,scrollY=g.doc.documentElement.scrollTop||g.doc.body.scrollTop,scrollX=g.doc.documentElement.scrollLeft||g.doc.body.scrollLeft,j=drag.length;j--;){if(dragi=drag[j],supportsTouch&&e.touches){for(var touch,i=e.touches.length;i--;)if(touch=e.touches[i],touch.identifier==dragi.el._drag.id){x=touch.clientX,y=touch.clientY,(e.originalEvent?e.originalEvent:e).preventDefault();break}}else e.preventDefault();var o,node=dragi.el.node,next=node.nextSibling,parent=node.parentNode,display=node.style.display;g.win.opera&&parent.removeChild(node),node.style.display=\"none\",o=dragi.el.paper.getElementByPoint(x,y),node.style.display=display,g.win.opera&&(next?parent.insertBefore(node,next):parent.appendChild(node)),o&&eve(\"raphael.drag.over.\"+dragi.el.id,dragi.el,o),x+=scrollX,y+=scrollY,eve(\"raphael.drag.move.\"+dragi.el.id,dragi.move_scope||dragi.el,x-dragi.el._drag.x,y-dragi.el._drag.y,x,y,e)}},dragUp=function(e){R.unmousemove(dragMove).unmouseup(dragUp);for(var dragi,i=drag.length;i--;)dragi=drag[i],dragi.el._drag={},eve(\"raphael.drag.end.\"+dragi.el.id,dragi.end_scope||dragi.start_scope||dragi.move_scope||dragi.el,e);drag=[]},elproto=R.el={},i=events.length;i--;)!function(eventName){R[eventName]=elproto[eventName]=function(fn,scope){return R.is(fn,\"function\")&&(this.events=this.events||[],this.events.push({name:eventName,f:fn,unbind:addEvent(this.shape||this.node||g.doc,eventName,fn,scope||this)})),this},R[\"un\"+eventName]=elproto[\"un\"+eventName]=function(fn){for(var events=this.events||[],l=events.length;l--;)events[l].name!=eventName||!R.is(fn,\"undefined\")&&events[l].f!=fn||(events[l].unbind(),events.splice(l,1),!events.length&&delete this.events);return this}}(events[i]);elproto.data=function(key,value){var data=eldata[this.id]=eldata[this.id]||{};if(0==arguments.length)return data;if(1==arguments.length){if(R.is(key,\"object\")){for(var i in key)key[has](i)&&this.data(i,key[i]);return this}return eve(\"raphael.data.get.\"+this.id,this,data[key],key),data[key]}return data[key]=value,eve(\"raphael.data.set.\"+this.id,this,value,key),this},elproto.removeData=function(key){return null==key?eldata[this.id]={}:eldata[this.id]&&delete eldata[this.id][key],this},elproto.getData=function(){return clone(eldata[this.id]||{})},elproto.hover=function(f_in,f_out,scope_in,scope_out){return this.mouseover(f_in,scope_in).mouseout(f_out,scope_out||scope_in)},elproto.unhover=function(f_in,f_out){return this.unmouseover(f_in).unmouseout(f_out)};var draggable=[];elproto.drag=function(onmove,onstart,onend,move_scope,start_scope,end_scope){function start(e){(e.originalEvent||e).preventDefault();var x=e.clientX,y=e.clientY,scrollY=g.doc.documentElement.scrollTop||g.doc.body.scrollTop,scrollX=g.doc.documentElement.scrollLeft||g.doc.body.scrollLeft;if(this._drag.id=e.identifier,supportsTouch&&e.touches)for(var touch,i=e.touches.length;i--;)if(touch=e.touches[i],this._drag.id=touch.identifier,touch.identifier==this._drag.id){x=touch.clientX,y=touch.clientY;break}this._drag.x=x+scrollX,this._drag.y=y+scrollY,!drag.length&&R.mousemove(dragMove).mouseup(dragUp),drag.push({el:this,move_scope:move_scope,start_scope:start_scope,end_scope:end_scope}),onstart&&eve.on(\"raphael.drag.start.\"+this.id,onstart),onmove&&eve.on(\"raphael.drag.move.\"+this.id,onmove),onend&&eve.on(\"raphael.drag.end.\"+this.id,onend),eve(\"raphael.drag.start.\"+this.id,start_scope||move_scope||this,e.clientX+scrollX,e.clientY+scrollY,e)}return this._drag={},draggable.push({el:this,start:start}),this.mousedown(start),this},elproto.onDragOver=function(f){f?eve.on(\"raphael.drag.over.\"+this.id,f):eve.unbind(\"raphael.drag.over.\"+this.id)},elproto.undrag=function(){for(var i=draggable.length;i--;)draggable[i].el==this&&(this.unmousedown(draggable[i].start),draggable.splice(i,1),eve.unbind(\"raphael.drag.*.\"+this.id));!draggable.length&&R.unmousemove(dragMove).unmouseup(dragUp),drag=[]},paperproto.circle=function(x,y,r){var out=R._engine.circle(this,x||0,y||0,r||0);return this.__set__&&this.__set__.push(out),out},paperproto.rect=function(x,y,w,h,r){var out=R._engine.rect(this,x||0,y||0,w||0,h||0,r||0);return this.__set__&&this.__set__.push(out),out},paperproto.ellipse=function(x,y,rx,ry){var out=R._engine.ellipse(this,x||0,y||0,rx||0,ry||0);return this.__set__&&this.__set__.push(out),out},paperproto.path=function(pathString){pathString&&!R.is(pathString,string)&&!R.is(pathString[0],array)&&(pathString+=E);var out=R._engine.path(R.format[apply](R,arguments),this);return this.__set__&&this.__set__.push(out),out},paperproto.image=function(src,x,y,w,h){var out=R._engine.image(this,src||\"about:blank\",x||0,y||0,w||0,h||0);return this.__set__&&this.__set__.push(out),out},paperproto.text=function(x,y,text){var out=R._engine.text(this,x||0,y||0,Str(text));return this.__set__&&this.__set__.push(out),out},paperproto.set=function(itemsArray){!R.is(itemsArray,\"array\")&&(itemsArray=Array.prototype.splice.call(arguments,0,arguments.length));var out=new Set(itemsArray);return this.__set__&&this.__set__.push(out),out.paper=this,out.type=\"set\",out},paperproto.setStart=function(set){this.__set__=set||this.set()},paperproto.setFinish=function(set){var out=this.__set__;return delete this.__set__,out},paperproto.setSize=function(width,height){return R._engine.setSize.call(this,width,height)},paperproto.setViewBox=function(x,y,w,h,fit){return R._engine.setViewBox.call(this,x,y,w,h,fit)},paperproto.top=paperproto.bottom=null,paperproto.raphael=R;var getOffset=function(elem){var box=elem.getBoundingClientRect(),doc=elem.ownerDocument,body=doc.body,docElem=doc.documentElement,clientTop=docElem.clientTop||body.clientTop||0,clientLeft=docElem.clientLeft||body.clientLeft||0,top=box.top+(g.win.pageYOffset||docElem.scrollTop||body.scrollTop)-clientTop,left=box.left+(g.win.pageXOffset||docElem.scrollLeft||body.scrollLeft)-clientLeft;return{y:top,x:left}};paperproto.getElementByPoint=function(x,y){var paper=this,svg=paper.canvas,target=g.doc.elementFromPoint(x,y);if(g.win.opera&&\"svg\"==target.tagName){var so=getOffset(svg),sr=svg.createSVGRect();sr.x=x-so.x,sr.y=y-so.y,sr.width=sr.height=1;var hits=svg.getIntersectionList(sr,null);hits.length&&(target=hits[hits.length-1])}if(!target)return null;for(;target.parentNode&&target!=svg.parentNode&&!target.raphael;)target=target.parentNode;return target==paper.canvas.parentNode&&(target=svg),target=target&&target.raphael?paper.getById(target.raphaelid):null},paperproto.getElementsByBBox=function(bbox){var set=this.set();return this.forEach(function(el){R.isBBoxIntersect(el.getBBox(),bbox)&&set.push(el)}),set},paperproto.getById=function(id){for(var bot=this.bottom;bot;){if(bot.id==id)return bot;bot=bot.next}return null},paperproto.forEach=function(callback,thisArg){for(var bot=this.bottom;bot;){if(callback.call(thisArg,bot)===!1)return this;bot=bot.next}return this},paperproto.getElementsByPoint=function(x,y){var set=this.set();return this.forEach(function(el){el.isPointInside(x,y)&&set.push(el)}),set},elproto.isPointInside=function(x,y){var rp=this.realPath=getPath[this.type](this);return this.attr(\"transform\")&&this.attr(\"transform\").length&&(rp=R.transformPath(rp,this.attr(\"transform\"))),R.isPointInsidePath(rp,x,y)},elproto.getBBox=function(isWithoutTransform){if(this.removed)return{};var _=this._;return isWithoutTransform?(!_.dirty&&_.bboxwt||(this.realPath=getPath[this.type](this),_.bboxwt=pathDimensions(this.realPath),_.bboxwt.toString=x_y_w_h,_.dirty=0),_.bboxwt):((_.dirty||_.dirtyT||!_.bbox)&&(!_.dirty&&this.realPath||(_.bboxwt=0,this.realPath=getPath[this.type](this)),_.bbox=pathDimensions(mapPath(this.realPath,this.matrix)),_.bbox.toString=x_y_w_h,_.dirty=_.dirtyT=0),_.bbox)},elproto.clone=function(){if(this.removed)return null;var out=this.paper[this.type]().attr(this.attr());return this.__set__&&this.__set__.push(out),out},elproto.glow=function(glow){if(\"text\"==this.type)return null;glow=glow||{};var s={width:(glow.width||10)+(+this.attr(\"stroke-width\")||1),fill:glow.fill||!1,opacity:glow.opacity||.5,offsetx:glow.offsetx||0,offsety:glow.offsety||0,color:glow.color||\"#000\"},c=s.width/2,r=this.paper,out=r.set(),path=this.realPath||getPath[this.type](this);path=this.matrix?mapPath(path,this.matrix):path;for(var i=1;i<c+1;i++)out.push(r.path(path).attr({stroke:s.color,fill:s.fill?s.color:\"none\",\"stroke-linejoin\":\"round\",\"stroke-linecap\":\"round\",\"stroke-width\":+(s.width/c*i).toFixed(3),opacity:+(s.opacity/c).toFixed(3)}));return out.insertBefore(this).translate(s.offsetx,s.offsety)};var getPointAtSegmentLength=function(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,length){return null==length?bezlen(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y):R.findDotsAtSegment(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,getTatLen(p1x,p1y,c1x,c1y,c2x,c2y,p2x,p2y,length))},getLengthFactory=function(istotal,subpath){return function(path,length,onlystart){path=path2curve(path);for(var x,y,p,l,point,sp=\"\",subpaths={},len=0,i=0,ii=path.length;i<ii;i++){if(p=path[i],\"M\"==p[0])x=+p[1],y=+p[2];else{if(l=getPointAtSegmentLength(x,y,p[1],p[2],p[3],p[4],p[5],p[6]),len+l>length){if(subpath&&!subpaths.start){if(point=getPointAtSegmentLength(x,y,p[1],p[2],p[3],p[4],p[5],p[6],length-len),sp+=[\"C\"+point.start.x,point.start.y,point.m.x,point.m.y,point.x,point.y],onlystart)return sp;subpaths.start=sp,sp=[\"M\"+point.x,point.y+\"C\"+point.n.x,point.n.y,point.end.x,point.end.y,p[5],p[6]].join(),len+=l,x=+p[5],y=+p[6];continue}if(!istotal&&!subpath)return point=getPointAtSegmentLength(x,y,p[1],p[2],p[3],p[4],p[5],p[6],length-len),{x:point.x,y:point.y,alpha:point.alpha}}len+=l,x=+p[5],y=+p[6]}sp+=p.shift()+p}return subpaths.end=sp,point=istotal?len:subpath?subpaths:R.findDotsAtSegment(x,y,p[0],p[1],p[2],p[3],p[4],p[5],1),point.alpha&&(point={x:point.x,y:point.y,alpha:point.alpha}),point}},getTotalLength=getLengthFactory(1),getPointAtLength=getLengthFactory(),getSubpathsAtLength=getLengthFactory(0,1);R.getTotalLength=getTotalLength,R.getPointAtLength=getPointAtLength,R.getSubpath=function(path,from,to){if(this.getTotalLength(path)-to<1e-6)return getSubpathsAtLength(path,from).end;var a=getSubpathsAtLength(path,to,1);return from?getSubpathsAtLength(a,from).end:a},elproto.getTotalLength=function(){var path=this.getPath();if(path)return this.node.getTotalLength?this.node.getTotalLength():getTotalLength(path)},elproto.getPointAtLength=function(length){var path=this.getPath();if(path)return getPointAtLength(path,length)},elproto.getPath=function(){var path,getPath=R._getPath[this.type];if(\"text\"!=this.type&&\"set\"!=this.type)return getPath&&(path=getPath(this)),path},elproto.getSubpath=function(from,to){var path=this.getPath();if(path)return R.getSubpath(path,from,to)};var ef=R.easing_formulas={linear:function(n){return n},\"<\":function(n){return pow(n,1.7)},\">\":function(n){return pow(n,.48)},\"<>\":function(n){var q=.48-n/1.04,Q=math.sqrt(.1734+q*q),x=Q-q,X=pow(abs(x),1/3)*(x<0?-1:1),y=-Q-q,Y=pow(abs(y),1/3)*(y<0?-1:1),t=X+Y+.5;return 3*(1-t)*t*t+t*t*t},backIn:function(n){var s=1.70158;return n*n*((s+1)*n-s)},backOut:function(n){n-=1;var s=1.70158;return n*n*((s+1)*n+s)+1},elastic:function(n){return n==!!n?n:pow(2,-10*n)*math.sin((n-.075)*(2*PI)/.3)+1},bounce:function(n){var l,s=7.5625,p=2.75;return n<1/p?l=s*n*n:n<2/p?(n-=1.5/p,l=s*n*n+.75):n<2.5/p?(n-=2.25/p,l=s*n*n+.9375):(n-=2.625/p,l=s*n*n+.984375),l}};ef.easeIn=ef[\"ease-in\"]=ef[\"<\"],ef.easeOut=ef[\"ease-out\"]=ef[\">\"],ef.easeInOut=ef[\"ease-in-out\"]=ef[\"<>\"],ef[\"back-in\"]=ef.backIn,ef[\"back-out\"]=ef.backOut;var animationElements=[],requestAnimFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(callback){setTimeout(callback,16)},animation=function(){for(var Now=+new Date,l=0;l<animationElements.length;l++){var e=animationElements[l];if(!e.el.removed&&!e.paused){var now,key,time=Now-e.start,ms=e.ms,easing=e.easing,from=e.from,diff=e.diff,to=e.to,that=(e.t,e.el),set={},init={};if(e.initstatus?(time=(e.initstatus*e.anim.top-e.prev)/(e.percent-e.prev)*ms,e.status=e.initstatus,delete e.initstatus,e.stop&&animationElements.splice(l--,1)):e.status=(e.prev+(e.percent-e.prev)*(time/ms))/e.anim.top,!(time<0))if(time<ms){var pos=easing(time/ms);for(var attr in from)if(from[has](attr)){switch(availableAnimAttrs[attr]){case nu:now=+from[attr]+pos*ms*diff[attr];break;case\"colour\":now=\"rgb(\"+[upto255(round(from[attr].r+pos*ms*diff[attr].r)),upto255(round(from[attr].g+pos*ms*diff[attr].g)),upto255(round(from[attr].b+pos*ms*diff[attr].b))].join(\",\")+\")\";break;case\"path\":now=[];for(var i=0,ii=from[attr].length;i<ii;i++){now[i]=[from[attr][i][0]];for(var j=1,jj=from[attr][i].length;j<jj;j++)now[i][j]=+from[attr][i][j]+pos*ms*diff[attr][i][j];now[i]=now[i].join(S)}now=now.join(S);break;case\"transform\":if(diff[attr].real)for(now=[],i=0,ii=from[attr].length;i<ii;i++)for(now[i]=[from[attr][i][0]],j=1,jj=from[attr][i].length;j<jj;j++)now[i][j]=from[attr][i][j]+pos*ms*diff[attr][i][j];else{var get=function(i){return+from[attr][i]+pos*ms*diff[attr][i]};now=[[\"m\",get(0),get(1),get(2),get(3),get(4),get(5)]]}break;case\"csv\":if(\"clip-rect\"==attr)for(now=[],i=4;i--;)now[i]=+from[attr][i]+pos*ms*diff[attr][i];break;default:var from2=[][concat](from[attr]);for(now=[],i=that.paper.customAttributes[attr].length;i--;)now[i]=+from2[i]+pos*ms*diff[attr][i]}set[attr]=now}that.attr(set),function(id,that,anim){setTimeout(function(){eve(\"raphael.anim.frame.\"+id,that,anim)})}(that.id,that,e.anim)}else{if(function(f,el,a){setTimeout(function(){eve(\"raphael.anim.frame.\"+el.id,el,a),eve(\"raphael.anim.finish.\"+el.id,el,a),R.is(f,\"function\")&&f.call(el)})}(e.callback,that,e.anim),that.attr(to),animationElements.splice(l--,1),e.repeat>1&&!e.next){for(key in to)to[has](key)&&(init[key]=e.totalOrigin[key]);e.el.attr(init),runAnimation(e.anim,e.el,e.anim.percents[0],null,e.totalOrigin,e.repeat-1)}e.next&&!e.stop&&runAnimation(e.anim,e.el,e.next,null,e.totalOrigin,e.repeat)}}}R.svg&&that&&that.paper&&that.paper.safari(),animationElements.length&&requestAnimFrame(animation)},upto255=function(color){return color>255?255:color<0?0:color};elproto.animateWith=function(el,anim,params,ms,easing,callback){var element=this;if(element.removed)return callback&&callback.call(element),element;var a=params instanceof Animation?params:R.animation(params,ms,easing,callback);runAnimation(a,element,a.percents[0],null,element.attr());for(var i=0,ii=animationElements.length;i<ii;i++)if(animationElements[i].anim==anim&&animationElements[i].el==el){animationElements[ii-1].start=animationElements[i].start;break}return element},elproto.onAnimation=function(f){return f?eve.on(\"raphael.anim.frame.\"+this.id,f):eve.unbind(\"raphael.anim.frame.\"+this.id),this},Animation.prototype.delay=function(delay){var a=new Animation(this.anim,this.ms);return a.times=this.times,a.del=+delay||0,a},Animation.prototype.repeat=function(times){var a=new Animation(this.anim,this.ms);return a.del=this.del,a.times=math.floor(mmax(times,0))||1,a},R.animation=function(params,ms,easing,callback){if(params instanceof Animation)return params;\n!R.is(easing,\"function\")&&easing||(callback=callback||easing||null,easing=null),params=Object(params),ms=+ms||0;var json,attr,p={};for(attr in params)params[has](attr)&&toFloat(attr)!=attr&&toFloat(attr)+\"%\"!=attr&&(json=!0,p[attr]=params[attr]);return json?(easing&&(p.easing=easing),callback&&(p.callback=callback),new Animation({100:p},ms)):new Animation(params,ms)},elproto.animate=function(params,ms,easing,callback){var element=this;if(element.removed)return callback&&callback.call(element),element;var anim=params instanceof Animation?params:R.animation(params,ms,easing,callback);return runAnimation(anim,element,anim.percents[0],null,element.attr()),element},elproto.setTime=function(anim,value){return anim&&null!=value&&this.status(anim,mmin(value,anim.ms)/anim.ms),this},elproto.status=function(anim,value){var len,e,out=[],i=0;if(null!=value)return runAnimation(anim,this,-1,mmin(value,1)),this;for(len=animationElements.length;i<len;i++)if(e=animationElements[i],e.el.id==this.id&&(!anim||e.anim==anim)){if(anim)return e.status;out.push({anim:e.anim,status:e.status})}return anim?0:out},elproto.pause=function(anim){for(var i=0;i<animationElements.length;i++)animationElements[i].el.id!=this.id||anim&&animationElements[i].anim!=anim||eve(\"raphael.anim.pause.\"+this.id,this,animationElements[i].anim)!==!1&&(animationElements[i].paused=!0);return this},elproto.resume=function(anim){for(var i=0;i<animationElements.length;i++)if(animationElements[i].el.id==this.id&&(!anim||animationElements[i].anim==anim)){var e=animationElements[i];eve(\"raphael.anim.resume.\"+this.id,this,e.anim)!==!1&&(delete e.paused,this.status(e.anim,e.status))}return this},elproto.stop=function(anim){for(var i=0;i<animationElements.length;i++)animationElements[i].el.id!=this.id||anim&&animationElements[i].anim!=anim||eve(\"raphael.anim.stop.\"+this.id,this,animationElements[i].anim)!==!1&&animationElements.splice(i--,1);return this},eve.on(\"raphael.remove\",stopAnimation),eve.on(\"raphael.clear\",stopAnimation),elproto.toString=function(){return\"Raphaël’s object\"};var Set=function(items){if(this.items=[],this.length=0,this.type=\"set\",items)for(var i=0,ii=items.length;i<ii;i++)!items[i]||items[i].constructor!=elproto.constructor&&items[i].constructor!=Set||(this[this.items.length]=this.items[this.items.length]=items[i],this.length++)},setproto=Set.prototype;setproto.push=function(){for(var item,len,i=0,ii=arguments.length;i<ii;i++)item=arguments[i],!item||item.constructor!=elproto.constructor&&item.constructor!=Set||(len=this.items.length,this[len]=this.items[len]=item,this.length++);return this},setproto.pop=function(){return this.length&&delete this[this.length--],this.items.pop()},setproto.forEach=function(callback,thisArg){for(var i=0,ii=this.items.length;i<ii;i++)if(callback.call(thisArg,this.items[i],i)===!1)return this;return this};for(var method in elproto)elproto[has](method)&&(setproto[method]=function(methodname){return function(){var arg=arguments;return this.forEach(function(el){el[methodname][apply](el,arg)})}}(method));return setproto.attr=function(name,value){if(name&&R.is(name,array)&&R.is(name[0],\"object\"))for(var j=0,jj=name.length;j<jj;j++)this.items[j].attr(name[j]);else for(var i=0,ii=this.items.length;i<ii;i++)this.items[i].attr(name,value);return this},setproto.clear=function(){for(;this.length;)this.pop()},setproto.splice=function(index,count,insertion){index=index<0?mmax(this.length+index,0):index,count=mmax(0,mmin(this.length-index,count));var i,tail=[],todel=[],args=[];for(i=2;i<arguments.length;i++)args.push(arguments[i]);for(i=0;i<count;i++)todel.push(this[index+i]);for(;i<this.length-index;i++)tail.push(this[index+i]);var arglen=args.length;for(i=0;i<arglen+tail.length;i++)this.items[index+i]=this[index+i]=i<arglen?args[i]:tail[i-arglen];for(i=this.items.length=this.length-=count-arglen;this[i];)delete this[i++];return new Set(todel)},setproto.exclude=function(el){for(var i=0,ii=this.length;i<ii;i++)if(this[i]==el)return this.splice(i,1),!0},setproto.animate=function(params,ms,easing,callback){(R.is(easing,\"function\")||!easing)&&(callback=easing||null);var item,collector,len=this.items.length,i=len,set=this;if(!len)return this;callback&&(collector=function(){!--len&&callback.call(set)}),easing=R.is(easing,string)?easing:collector;var anim=R.animation(params,ms,easing,collector);for(item=this.items[--i].animate(anim);i--;)this.items[i]&&!this.items[i].removed&&this.items[i].animateWith(item,anim,anim),this.items[i]&&!this.items[i].removed||len--;return this},setproto.insertAfter=function(el){for(var i=this.items.length;i--;)this.items[i].insertAfter(el);return this},setproto.getBBox=function(){for(var x=[],y=[],x2=[],y2=[],i=this.items.length;i--;)if(!this.items[i].removed){var box=this.items[i].getBBox();x.push(box.x),y.push(box.y),x2.push(box.x+box.width),y2.push(box.y+box.height)}return x=mmin[apply](0,x),y=mmin[apply](0,y),x2=mmax[apply](0,x2),y2=mmax[apply](0,y2),{x:x,y:y,x2:x2,y2:y2,width:x2-x,height:y2-y}},setproto.clone=function(s){s=this.paper.set();for(var i=0,ii=this.items.length;i<ii;i++)s.push(this.items[i].clone());return s},setproto.toString=function(){return\"Raphaël‘s set\"},setproto.glow=function(glowConfig){var ret=this.paper.set();return this.forEach(function(shape,index){var g=shape.glow(glowConfig);null!=g&&g.forEach(function(shape2,index2){ret.push(shape2)})}),ret},setproto.isPointInside=function(x,y){var isPointInside=!1;return this.forEach(function(el){if(el.isPointInside(x,y))return console.log(\"runned\"),isPointInside=!0,!1}),isPointInside},R.registerFont=function(font){if(!font.face)return font;this.fonts=this.fonts||{};var fontcopy={w:font.w,face:{},glyphs:{}},family=font.face[\"font-family\"];for(var prop in font.face)font.face[has](prop)&&(fontcopy.face[prop]=font.face[prop]);if(this.fonts[family]?this.fonts[family].push(fontcopy):this.fonts[family]=[fontcopy],!font.svg){fontcopy.face[\"units-per-em\"]=toInt(font.face[\"units-per-em\"],10);for(var glyph in font.glyphs)if(font.glyphs[has](glyph)){var path=font.glyphs[glyph];if(fontcopy.glyphs[glyph]={w:path.w,k:{},d:path.d&&\"M\"+path.d.replace(/[mlcxtrv]/g,function(command){return{l:\"L\",c:\"C\",x:\"z\",t:\"m\",r:\"l\",v:\"c\"}[command]||\"M\"})+\"z\"},path.k)for(var k in path.k)path[has](k)&&(fontcopy.glyphs[glyph].k[k]=path.k[k])}}return font},paperproto.getFont=function(family,weight,style,stretch){if(stretch=stretch||\"normal\",style=style||\"normal\",weight=+weight||{normal:400,bold:700,lighter:300,bolder:800}[weight]||400,R.fonts){var font=R.fonts[family];if(!font){var name=new RegExp(\"(^|\\\\s)\"+family.replace(/[^\\w\\d\\s+!~.:_-]/g,E)+\"(\\\\s|$)\",\"i\");for(var fontName in R.fonts)if(R.fonts[has](fontName)&&name.test(fontName)){font=R.fonts[fontName];break}}var thefont;if(font)for(var i=0,ii=font.length;i<ii&&(thefont=font[i],thefont.face[\"font-weight\"]!=weight||thefont.face[\"font-style\"]!=style&&thefont.face[\"font-style\"]||thefont.face[\"font-stretch\"]!=stretch);i++);return thefont}},paperproto.print=function(x,y,string,font,size,origin,letter_spacing,line_spacing){origin=origin||\"middle\",letter_spacing=mmax(mmin(letter_spacing||0,1),-1),line_spacing=mmax(mmin(line_spacing||1,3),1);var scale,letters=Str(string)[split](E),shift=0,notfirst=0,path=E;if(R.is(font,\"string\")&&(font=this.getFont(font)),font){scale=(size||16)/font.face[\"units-per-em\"];for(var bb=font.face.bbox[split](separator),top=+bb[0],lineHeight=bb[3]-bb[1],shifty=0,height=+bb[1]+(\"baseline\"==origin?lineHeight+ +font.face.descent:lineHeight/2),i=0,ii=letters.length;i<ii;i++){if(\"\\n\"==letters[i])shift=0,curr=0,notfirst=0,shifty+=lineHeight*line_spacing;else{var prev=notfirst&&font.glyphs[letters[i-1]]||{},curr=font.glyphs[letters[i]];shift+=notfirst?(prev.w||font.w)+(prev.k&&prev.k[letters[i]]||0)+font.w*letter_spacing:0,notfirst=1}curr&&curr.d&&(path+=R.transformPath(curr.d,[\"t\",shift*scale,shifty*scale,\"s\",scale,scale,top,height,\"t\",(x-top)/scale,(y-height)/scale]))}}return this.path(path).attr({fill:\"#000\",stroke:\"none\"})},paperproto.add=function(json){if(R.is(json,\"array\"))for(var j,res=this.set(),i=0,ii=json.length;i<ii;i++)j=json[i]||{},elements[has](j.type)&&res.push(this[j.type]().attr(j));return res},R.format=function(token,params){var args=R.is(params,array)?[0][concat](params):arguments;return token&&R.is(token,string)&&args.length-1&&(token=token.replace(formatrg,function(str,i){return null==args[++i]?E:args[i]})),token||E},R.fullfill=function(){var tokenRegex=/\\{([^\\}]+)\\}/g,objNotationRegex=/(?:(?:^|\\.)(.+?)(?=\\[|\\.|$|\\()|\\[('|\")(.+?)\\2\\])(\\(\\))?/g,replacer=function(all,key,obj){var res=obj;return key.replace(objNotationRegex,function(all,name,quote,quotedName,isFunc){name=name||quotedName,res&&(name in res&&(res=res[name]),\"function\"==typeof res&&isFunc&&(res=res()))}),res=(null==res||res==obj?all:res)+\"\"};return function(str,obj){return String(str).replace(tokenRegex,function(all,key){return replacer(all,key,obj)})}}(),R.st=setproto,function(doc,loaded,f){function isLoaded(){/in/.test(doc.readyState)?setTimeout(isLoaded,9):R.eve(\"raphael.DOMload\")}null==doc.readyState&&doc.addEventListener&&(doc.addEventListener(loaded,f=function(){doc.removeEventListener(loaded,f,!1),doc.readyState=\"complete\"},!1),doc.readyState=\"loading\"),isLoaded()}(document,\"DOMContentLoaded\"),eve.on(\"raphael.DOMload\",function(){loaded=!0}),function(){if(R.svg){var has=\"hasOwnProperty\",Str=String,toFloat=parseFloat,toInt=parseInt,math=Math,mmax=math.max,abs=math.abs,pow=math.pow,separator=/[, ]+/,eve=R.eve,E=\"\",S=\" \",xlink=\"http://www.w3.org/1999/xlink\",markers={block:\"M5,0 0,2.5 5,5z\",classic:\"M5,0 0,2.5 5,5 3.5,3 3.5,2z\",diamond:\"M2.5,0 5,2.5 2.5,5 0,2.5z\",open:\"M6,1 1,3.5 6,6\",oval:\"M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z\"},markerCounter={};R.toString=function(){return\"Your browser supports SVG.\\nYou are running Raphaël \"+this.version};var $=function(el,attr){if(attr){\"string\"==typeof el&&(el=$(el));for(var key in attr)attr[has](key)&&(\"xlink:\"==key.substring(0,6)?el.setAttributeNS(xlink,key.substring(6),Str(attr[key])):el.setAttribute(key,Str(attr[key])))}else el=R._g.doc.createElementNS(\"http://www.w3.org/2000/svg\",el),el.style&&(el.style.webkitTapHighlightColor=\"rgba(0,0,0,0)\");return el},addGradientFill=function(element,gradient){var type=\"linear\",id=element.id+gradient,fx=.5,fy=.5,o=element.node,SVG=element.paper,s=o.style,el=R._g.doc.getElementById(id);if(!el){if(gradient=Str(gradient).replace(R._radial_gradient,function(all,_fx,_fy){if(type=\"radial\",_fx&&_fy){fx=toFloat(_fx),fy=toFloat(_fy);var dir=2*(fy>.5)-1;pow(fx-.5,2)+pow(fy-.5,2)>.25&&(fy=math.sqrt(.25-pow(fx-.5,2))*dir+.5)&&.5!=fy&&(fy=fy.toFixed(5)-1e-5*dir)}return E}),gradient=gradient.split(/\\s*\\-\\s*/),\"linear\"==type){var angle=gradient.shift();if(angle=-toFloat(angle),isNaN(angle))return null;var vector=[0,0,math.cos(R.rad(angle)),math.sin(R.rad(angle))],max=1/(mmax(abs(vector[2]),abs(vector[3]))||1);vector[2]*=max,vector[3]*=max,vector[2]<0&&(vector[0]=-vector[2],vector[2]=0),vector[3]<0&&(vector[1]=-vector[3],vector[3]=0)}var dots=R._parseDots(gradient);if(!dots)return null;if(id=id.replace(/[\\(\\)\\s,\\xb0#]/g,\"_\"),element.gradient&&id!=element.gradient.id&&(SVG.defs.removeChild(element.gradient),delete element.gradient),!element.gradient){el=$(type+\"Gradient\",{id:id}),element.gradient=el,$(el,\"radial\"==type?{fx:fx,fy:fy}:{x1:vector[0],y1:vector[1],x2:vector[2],y2:vector[3],gradientTransform:element.matrix.invert()}),SVG.defs.appendChild(el);for(var i=0,ii=dots.length;i<ii;i++)el.appendChild($(\"stop\",{offset:dots[i].offset?dots[i].offset:i?\"100%\":\"0%\",\"stop-color\":dots[i].color||\"#fff\"}))}}return $(o,{fill:\"url(#\"+id+\")\",opacity:1,\"fill-opacity\":1}),s.fill=E,s.opacity=1,s.fillOpacity=1,1},updatePosition=function(o){var bbox=o.getBBox(1);$(o.pattern,{patternTransform:o.matrix.invert()+\" translate(\"+bbox.x+\",\"+bbox.y+\")\"})},addArrow=function(o,value,isEnd){if(\"path\"==o.type){for(var from,to,dx,refX,attr,values=Str(value).toLowerCase().split(\"-\"),p=o.paper,se=isEnd?\"end\":\"start\",node=o.node,attrs=o.attrs,stroke=attrs[\"stroke-width\"],i=values.length,type=\"classic\",w=3,h=3,t=5;i--;)switch(values[i]){case\"block\":case\"classic\":case\"oval\":case\"diamond\":case\"open\":case\"none\":type=values[i];break;case\"wide\":h=5;break;case\"narrow\":h=2;break;case\"long\":w=5;break;case\"short\":w=2}if(\"open\"==type?(w+=2,h+=2,t+=2,dx=1,refX=isEnd?4:1,attr={fill:\"none\",stroke:attrs.stroke}):(refX=dx=w/2,attr={fill:attrs.stroke,stroke:\"none\"}),o._.arrows?isEnd?(o._.arrows.endPath&&markerCounter[o._.arrows.endPath]--,o._.arrows.endMarker&&markerCounter[o._.arrows.endMarker]--):(o._.arrows.startPath&&markerCounter[o._.arrows.startPath]--,o._.arrows.startMarker&&markerCounter[o._.arrows.startMarker]--):o._.arrows={},\"none\"!=type){var pathId=\"raphael-marker-\"+type,markerId=\"raphael-marker-\"+se+type+w+h;R._g.doc.getElementById(pathId)?markerCounter[pathId]++:(p.defs.appendChild($($(\"path\"),{\"stroke-linecap\":\"round\",d:markers[type],id:pathId})),markerCounter[pathId]=1);var use,marker=R._g.doc.getElementById(markerId);marker?(markerCounter[markerId]++,use=marker.getElementsByTagName(\"use\")[0]):(marker=$($(\"marker\"),{id:markerId,markerHeight:h,markerWidth:w,orient:\"auto\",refX:refX,refY:h/2}),use=$($(\"use\"),{\"xlink:href\":\"#\"+pathId,transform:(isEnd?\"rotate(180 \"+w/2+\" \"+h/2+\") \":E)+\"scale(\"+w/t+\",\"+h/t+\")\",\"stroke-width\":(1/((w/t+h/t)/2)).toFixed(4)}),marker.appendChild(use),p.defs.appendChild(marker),markerCounter[markerId]=1),$(use,attr);var delta=dx*(\"diamond\"!=type&&\"oval\"!=type);isEnd?(from=o._.arrows.startdx*stroke||0,to=R.getTotalLength(attrs.path)-delta*stroke):(from=delta*stroke,to=R.getTotalLength(attrs.path)-(o._.arrows.enddx*stroke||0)),attr={},attr[\"marker-\"+se]=\"url(#\"+markerId+\")\",(to||from)&&(attr.d=R.getSubpath(attrs.path,from,to)),$(node,attr),o._.arrows[se+\"Path\"]=pathId,o._.arrows[se+\"Marker\"]=markerId,o._.arrows[se+\"dx\"]=delta,o._.arrows[se+\"Type\"]=type,o._.arrows[se+\"String\"]=value}else isEnd?(from=o._.arrows.startdx*stroke||0,to=R.getTotalLength(attrs.path)-from):(from=0,to=R.getTotalLength(attrs.path)-(o._.arrows.enddx*stroke||0)),o._.arrows[se+\"Path\"]&&$(node,{d:R.getSubpath(attrs.path,from,to)}),delete o._.arrows[se+\"Path\"],delete o._.arrows[se+\"Marker\"],delete o._.arrows[se+\"dx\"],delete o._.arrows[se+\"Type\"],delete o._.arrows[se+\"String\"];for(attr in markerCounter)if(markerCounter[has](attr)&&!markerCounter[attr]){var item=R._g.doc.getElementById(attr);item&&item.parentNode.removeChild(item)}}},dasharray={\"\":[0],none:[0],\"-\":[3,1],\".\":[1,1],\"-.\":[3,1,1,1],\"-..\":[3,1,1,1,1,1],\". \":[1,3],\"- \":[4,3],\"--\":[8,3],\"- .\":[4,3,1,3],\"--.\":[8,3,1,3],\"--..\":[8,3,1,3,1,3]},addDashes=function(o,value,params){if(value=dasharray[Str(value).toLowerCase()]){for(var width=o.attrs[\"stroke-width\"]||\"1\",butt={round:width,square:width,butt:0}[o.attrs[\"stroke-linecap\"]||params[\"stroke-linecap\"]]||0,dashes=[],i=value.length;i--;)dashes[i]=value[i]*width+(i%2?1:-1)*butt;$(o.node,{\"stroke-dasharray\":dashes.join(\",\")})}},setFillAndStroke=function(o,params){var node=o.node,attrs=o.attrs,vis=node.style.visibility;node.style.visibility=\"hidden\";for(var att in params)if(params[has](att)){if(!R._availableAttrs[has](att))continue;var value=params[att];switch(attrs[att]=value,att){case\"blur\":o.blur(value);break;case\"href\":case\"title\":var hl=$(\"title\"),val=R._g.doc.createTextNode(value);hl.appendChild(val),node.appendChild(hl);break;case\"target\":var pn=node.parentNode;if(\"a\"!=pn.tagName.toLowerCase()){var hl=$(\"a\");pn.insertBefore(hl,node),hl.appendChild(node),pn=hl}\"target\"==att?pn.setAttributeNS(xlink,\"show\",\"blank\"==value?\"new\":value):pn.setAttributeNS(xlink,att,value);break;case\"cursor\":node.style.cursor=value;break;case\"transform\":o.transform(value);break;case\"arrow-start\":addArrow(o,value);break;case\"arrow-end\":addArrow(o,value,1);break;case\"clip-rect\":var rect=Str(value).split(separator);if(4==rect.length){o.clip&&o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);var el=$(\"clipPath\"),rc=$(\"rect\");el.id=R.createUUID(),$(rc,{x:rect[0],y:rect[1],width:rect[2],height:rect[3]}),el.appendChild(rc),o.paper.defs.appendChild(el),$(node,{\"clip-path\":\"url(#\"+el.id+\")\"}),o.clip=rc}if(!value){var path=node.getAttribute(\"clip-path\");if(path){var clip=R._g.doc.getElementById(path.replace(/(^url\\(#|\\)$)/g,E));clip&&clip.parentNode.removeChild(clip),$(node,{\"clip-path\":E}),delete o.clip}}break;case\"path\":\"path\"==o.type&&($(node,{d:value?attrs.path=R._pathToAbsolute(value):\"M0,0\"}),o._.dirty=1,o._.arrows&&(\"startString\"in o._.arrows&&addArrow(o,o._.arrows.startString),\"endString\"in o._.arrows&&addArrow(o,o._.arrows.endString,1)));break;case\"width\":if(node.setAttribute(att,value),o._.dirty=1,!attrs.fx)break;att=\"x\",value=attrs.x;case\"x\":attrs.fx&&(value=-attrs.x-(attrs.width||0));case\"rx\":if(\"rx\"==att&&\"rect\"==o.type)break;case\"cx\":node.setAttribute(att,value),o.pattern&&updatePosition(o),o._.dirty=1;break;case\"height\":if(node.setAttribute(att,value),o._.dirty=1,!attrs.fy)break;att=\"y\",value=attrs.y;case\"y\":attrs.fy&&(value=-attrs.y-(attrs.height||0));case\"ry\":if(\"ry\"==att&&\"rect\"==o.type)break;case\"cy\":node.setAttribute(att,value),o.pattern&&updatePosition(o),o._.dirty=1;break;case\"r\":\"rect\"==o.type?$(node,{rx:value,ry:value}):node.setAttribute(att,value),o._.dirty=1;break;case\"src\":\"image\"==o.type&&node.setAttributeNS(xlink,\"href\",value);break;case\"stroke-width\":1==o._.sx&&1==o._.sy||(value/=mmax(abs(o._.sx),abs(o._.sy))||1),o.paper._vbSize&&(value*=o.paper._vbSize),node.setAttribute(att,value),attrs[\"stroke-dasharray\"]&&addDashes(o,attrs[\"stroke-dasharray\"],params),o._.arrows&&(\"startString\"in o._.arrows&&addArrow(o,o._.arrows.startString),\"endString\"in o._.arrows&&addArrow(o,o._.arrows.endString,1));break;case\"stroke-dasharray\":addDashes(o,value,params);break;case\"fill\":var isURL=Str(value).match(R._ISURL);if(isURL){el=$(\"pattern\");var ig=$(\"image\");el.id=R.createUUID(),$(el,{x:0,y:0,patternUnits:\"userSpaceOnUse\",height:1,width:1}),$(ig,{x:0,y:0,\"xlink:href\":isURL[1]}),el.appendChild(ig),function(el){R._preload(isURL[1],function(){var w=this.offsetWidth,h=this.offsetHeight;$(el,{width:w,height:h}),$(ig,{width:w,height:h}),o.paper.safari()})}(el),o.paper.defs.appendChild(el),$(node,{fill:\"url(#\"+el.id+\")\"}),o.pattern=el,o.pattern&&updatePosition(o);break}var clr=R.getRGB(value);if(clr.error){if((\"circle\"==o.type||\"ellipse\"==o.type||\"r\"!=Str(value).charAt())&&addGradientFill(o,value)){if(\"opacity\"in attrs||\"fill-opacity\"in attrs){var gradient=R._g.doc.getElementById(node.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g,E));if(gradient){var stops=gradient.getElementsByTagName(\"stop\");$(stops[stops.length-1],{\"stop-opacity\":(\"opacity\"in attrs?attrs.opacity:1)*(\"fill-opacity\"in attrs?attrs[\"fill-opacity\"]:1)})}}attrs.gradient=value,attrs.fill=\"none\";break}}else delete params.gradient,delete attrs.gradient,!R.is(attrs.opacity,\"undefined\")&&R.is(params.opacity,\"undefined\")&&$(node,{opacity:attrs.opacity}),!R.is(attrs[\"fill-opacity\"],\"undefined\")&&R.is(params[\"fill-opacity\"],\"undefined\")&&$(node,{\"fill-opacity\":attrs[\"fill-opacity\"]});clr[has](\"opacity\")&&$(node,{\"fill-opacity\":clr.opacity>1?clr.opacity/100:clr.opacity});case\"stroke\":clr=R.getRGB(value),node.setAttribute(att,clr.hex),\"stroke\"==att&&clr[has](\"opacity\")&&$(node,{\"stroke-opacity\":clr.opacity>1?clr.opacity/100:clr.opacity}),\"stroke\"==att&&o._.arrows&&(\"startString\"in o._.arrows&&addArrow(o,o._.arrows.startString),\"endString\"in o._.arrows&&addArrow(o,o._.arrows.endString,1));break;case\"gradient\":(\"circle\"==o.type||\"ellipse\"==o.type||\"r\"!=Str(value).charAt())&&addGradientFill(o,value);break;case\"opacity\":attrs.gradient&&!attrs[has](\"stroke-opacity\")&&$(node,{\"stroke-opacity\":value>1?value/100:value});case\"fill-opacity\":if(attrs.gradient){gradient=R._g.doc.getElementById(node.getAttribute(\"fill\").replace(/^url\\(#|\\)$/g,E)),gradient&&(stops=gradient.getElementsByTagName(\"stop\"),$(stops[stops.length-1],{\"stop-opacity\":value}));break}default:\"font-size\"==att&&(value=toInt(value,10)+\"px\");var cssrule=att.replace(/(\\-.)/g,function(w){return w.substring(1).toUpperCase()});node.style[cssrule]=value,o._.dirty=1,node.setAttribute(att,value)}}tuneText(o,params),node.style.visibility=vis},leading=1.2,tuneText=function(el,params){if(\"text\"==el.type&&(params[has](\"text\")||params[has](\"font\")||params[has](\"font-size\")||params[has](\"x\")||params[has](\"y\"))){var a=el.attrs,node=el.node,fontSize=node.firstChild?toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild,E).getPropertyValue(\"font-size\"),10):10;if(params[has](\"text\")){for(a.text=params.text;node.firstChild;)node.removeChild(node.firstChild);for(var tspan,texts=Str(params.text).split(\"\\n\"),tspans=[],i=0,ii=texts.length;i<ii;i++)tspan=$(\"tspan\"),i&&$(tspan,{dy:fontSize*leading,x:a.x}),tspan.appendChild(R._g.doc.createTextNode(texts[i])),node.appendChild(tspan),tspans[i]=tspan}else for(tspans=node.getElementsByTagName(\"tspan\"),i=0,ii=tspans.length;i<ii;i++)i?$(tspans[i],{dy:fontSize*leading,x:a.x}):$(tspans[0],{dy:0});$(node,{x:a.x,y:a.y}),el._.dirty=1;var bb=el._getBBox(),dif=a.y-(bb.y+bb.height/2);dif&&R.is(dif,\"finite\")&&$(tspans[0],{dy:dif})}},Element=function(node,svg){this[0]=this.node=node,node.raphael=!0,this.id=R._oid++,node.raphaelid=this.id,this.matrix=R.matrix(),this.realPath=null,this.paper=svg,this.attrs=this.attrs||{},this._={transform:[],sx:1,sy:1,deg:0,dx:0,dy:0,dirty:1},!svg.bottom&&(svg.bottom=this),this.prev=svg.top,svg.top&&(svg.top.next=this),svg.top=this,this.next=null},elproto=R.el;Element.prototype=elproto,elproto.constructor=Element,R._engine.path=function(pathString,SVG){var el=$(\"path\");SVG.canvas&&SVG.canvas.appendChild(el);var p=new Element(el,SVG);return p.type=\"path\",setFillAndStroke(p,{fill:\"none\",stroke:\"#000\",path:pathString}),p},elproto.rotate=function(deg,cx,cy){if(this.removed)return this;if(deg=Str(deg).split(separator),deg.length-1&&(cx=toFloat(deg[1]),cy=toFloat(deg[2])),deg=toFloat(deg[0]),null==cy&&(cx=cy),null==cx||null==cy){var bbox=this.getBBox(1);cx=bbox.x+bbox.width/2,cy=bbox.y+bbox.height/2}return this.transform(this._.transform.concat([[\"r\",deg,cx,cy]])),this},elproto.scale=function(sx,sy,cx,cy){if(this.removed)return this;if(sx=Str(sx).split(separator),sx.length-1&&(sy=toFloat(sx[1]),cx=toFloat(sx[2]),cy=toFloat(sx[3])),sx=toFloat(sx[0]),null==sy&&(sy=sx),null==cy&&(cx=cy),null==cx||null==cy)var bbox=this.getBBox(1);return cx=null==cx?bbox.x+bbox.width/2:cx,cy=null==cy?bbox.y+bbox.height/2:cy,this.transform(this._.transform.concat([[\"s\",sx,sy,cx,cy]])),this},elproto.translate=function(dx,dy){return this.removed?this:(dx=Str(dx).split(separator),dx.length-1&&(dy=toFloat(dx[1])),dx=toFloat(dx[0])||0,dy=+dy||0,this.transform(this._.transform.concat([[\"t\",dx,dy]])),this)},elproto.transform=function(tstr){var _=this._;if(null==tstr)return _.transform;if(R._extractTransform(this,tstr),this.clip&&$(this.clip,{transform:this.matrix.invert()}),this.pattern&&updatePosition(this),this.node&&$(this.node,{transform:this.matrix}),1!=_.sx||1!=_.sy){var sw=this.attrs[has](\"stroke-width\")?this.attrs[\"stroke-width\"]:1;this.attr({\"stroke-width\":sw})}return this},elproto.hide=function(){return!this.removed&&this.paper.safari(this.node.style.display=\"none\"),this},elproto.show=function(){return!this.removed&&this.paper.safari(this.node.style.display=\"\"),this},elproto.remove=function(){if(!this.removed&&this.node.parentNode){var paper=this.paper;paper.__set__&&paper.__set__.exclude(this),eve.unbind(\"raphael.*.*.\"+this.id),this.gradient&&paper.defs.removeChild(this.gradient),R._tear(this,paper),\"a\"==this.node.parentNode.tagName.toLowerCase()?this.node.parentNode.parentNode.removeChild(this.node.parentNode):this.node.parentNode.removeChild(this.node);for(var i in this)this[i]=\"function\"==typeof this[i]?R._removedFactory(i):null;this.removed=!0}},elproto._getBBox=function(){if(\"none\"==this.node.style.display){this.show();var hide=!0}var bbox={};try{bbox=this.node.getBBox()}catch(e){}finally{bbox=bbox||{}}return hide&&this.hide(),bbox},elproto.attr=function(name,value){if(this.removed)return this;if(null==name){var res={};for(var a in this.attrs)this.attrs[has](a)&&(res[a]=this.attrs[a]);return res.gradient&&\"none\"==res.fill&&(res.fill=res.gradient)&&delete res.gradient,res.transform=this._.transform,res}if(null==value&&R.is(name,\"string\")){if(\"fill\"==name&&\"none\"==this.attrs.fill&&this.attrs.gradient)return this.attrs.gradient;if(\"transform\"==name)return this._.transform;for(var names=name.split(separator),out={},i=0,ii=names.length;i<ii;i++)name=names[i],name in this.attrs?out[name]=this.attrs[name]:R.is(this.paper.customAttributes[name],\"function\")?out[name]=this.paper.customAttributes[name].def:out[name]=R._availableAttrs[name];return ii-1?out:out[names[0]]}if(null==value&&R.is(name,\"array\")){for(out={},i=0,ii=name.length;i<ii;i++)out[name[i]]=this.attr(name[i]);return out}if(null!=value){var params={};params[name]=value}else null!=name&&R.is(name,\"object\")&&(params=name);for(var key in params)eve(\"raphael.attr.\"+key+\".\"+this.id,this,params[key]);for(key in this.paper.customAttributes)if(this.paper.customAttributes[has](key)&&params[has](key)&&R.is(this.paper.customAttributes[key],\"function\")){var par=this.paper.customAttributes[key].apply(this,[].concat(params[key]));this.attrs[key]=params[key];for(var subkey in par)par[has](subkey)&&(params[subkey]=par[subkey])}return setFillAndStroke(this,params),this},elproto.toFront=function(){if(this.removed)return this;\"a\"==this.node.parentNode.tagName.toLowerCase()?this.node.parentNode.parentNode.appendChild(this.node.parentNode):this.node.parentNode.appendChild(this.node);var svg=this.paper;return svg.top!=this&&R._tofront(this,svg),this},elproto.toBack=function(){if(this.removed)return this;var parent=this.node.parentNode;\"a\"==parent.tagName.toLowerCase()?parent.parentNode.insertBefore(this.node.parentNode,this.node.parentNode.parentNode.firstChild):parent.firstChild!=this.node&&parent.insertBefore(this.node,this.node.parentNode.firstChild),R._toback(this,this.paper);this.paper;return this},elproto.insertAfter=function(element){if(this.removed)return this;var node=element.node||element[element.length-1].node;return node.nextSibling?node.parentNode.insertBefore(this.node,node.nextSibling):node.parentNode.appendChild(this.node),R._insertafter(this,element,this.paper),this},elproto.insertBefore=function(element){if(this.removed)return this;var node=element.node||element[0].node;return node.parentNode.insertBefore(this.node,node),R._insertbefore(this,element,this.paper),this},elproto.blur=function(size){var t=this;if(0!==+size){var fltr=$(\"filter\"),blur=$(\"feGaussianBlur\");t.attrs.blur=size,fltr.id=R.createUUID(),$(blur,{stdDeviation:+size||1.5}),fltr.appendChild(blur),t.paper.defs.appendChild(fltr),t._blur=fltr,$(t.node,{filter:\"url(#\"+fltr.id+\")\"})}else t._blur&&(t._blur.parentNode.removeChild(t._blur),delete t._blur,delete t.attrs.blur),t.node.removeAttribute(\"filter\");return t},R._engine.circle=function(svg,x,y,r){var el=$(\"circle\");svg.canvas&&svg.canvas.appendChild(el);var res=new Element(el,svg);return res.attrs={cx:x,cy:y,r:r,fill:\"none\",stroke:\"#000\"},res.type=\"circle\",$(el,res.attrs),res},R._engine.rect=function(svg,x,y,w,h,r){var el=$(\"rect\");svg.canvas&&svg.canvas.appendChild(el);var res=new Element(el,svg);return res.attrs={x:x,y:y,width:w,height:h,r:r||0,rx:r||0,ry:r||0,fill:\"none\",stroke:\"#000\"},res.type=\"rect\",$(el,res.attrs),res},R._engine.ellipse=function(svg,x,y,rx,ry){var el=$(\"ellipse\");svg.canvas&&svg.canvas.appendChild(el);var res=new Element(el,svg);return res.attrs={cx:x,cy:y,rx:rx,ry:ry,fill:\"none\",stroke:\"#000\"},res.type=\"ellipse\",$(el,res.attrs),res},R._engine.image=function(svg,src,x,y,w,h){var el=$(\"image\");$(el,{x:x,y:y,width:w,height:h,preserveAspectRatio:\"none\"}),el.setAttributeNS(xlink,\"href\",src),svg.canvas&&svg.canvas.appendChild(el);var res=new Element(el,svg);return res.attrs={x:x,y:y,width:w,height:h,src:src},res.type=\"image\",res},R._engine.text=function(svg,x,y,text){var el=$(\"text\");svg.canvas&&svg.canvas.appendChild(el);var res=new Element(el,svg);return res.attrs={x:x,y:y,\"text-anchor\":\"middle\",text:text,font:R._availableAttrs.font,stroke:\"none\",fill:\"#000\"},res.type=\"text\",setFillAndStroke(res,res.attrs),res},R._engine.setSize=function(width,height){return this.width=width||this.width,this.height=height||this.height,this.canvas.setAttribute(\"width\",this.width),this.canvas.setAttribute(\"height\",this.height),this._viewBox&&this.setViewBox.apply(this,this._viewBox),this},R._engine.create=function(){var con=R._getContainer.apply(0,arguments),container=con&&con.container,x=con.x,y=con.y,width=con.width,height=con.height;if(!container)throw new Error(\"SVG container not found.\");var isFloating,cnvs=$(\"svg\"),css=\"overflow:hidden;\";return x=x||0,y=y||0,width=width||512,height=height||342,$(cnvs,{height:height,version:1.1,width:width,xmlns:\"http://www.w3.org/2000/svg\"}),1==container?(cnvs.style.cssText=css+\"position:absolute;left:\"+x+\"px;top:\"+y+\"px\",R._g.doc.body.appendChild(cnvs),isFloating=1):(cnvs.style.cssText=css+\"position:relative\",container.firstChild?container.insertBefore(cnvs,container.firstChild):container.appendChild(cnvs)),container=new R._Paper,container.width=width,container.height=height,container.canvas=cnvs,container.clear(),container._left=container._top=0,isFloating&&(container.renderfix=function(){}),container.renderfix(),container},R._engine.setViewBox=function(x,y,w,h,fit){eve(\"raphael.setViewBox\",this,this._viewBox,[x,y,w,h,fit]);var vb,sw,size=mmax(w/this.width,h/this.height),top=this.top,aspectRatio=fit?\"meet\":\"xMinYMin\";for(null==x?(this._vbSize&&(size=1),delete this._vbSize,vb=\"0 0 \"+this.width+S+this.height):(this._vbSize=size,vb=x+S+y+S+w+S+h),$(this.canvas,{viewBox:vb,preserveAspectRatio:aspectRatio});size&&top;)sw=\"stroke-width\"in top.attrs?top.attrs[\"stroke-width\"]:1,top.attr({\"stroke-width\":sw}),top._.dirty=1,top._.dirtyT=1,top=top.prev;return this._viewBox=[x,y,w,h,!!fit],this},R.prototype.renderfix=function(){var pos,cnvs=this.canvas,s=cnvs.style;try{pos=cnvs.getScreenCTM()||cnvs.createSVGMatrix()}catch(e){pos=cnvs.createSVGMatrix()}var left=-pos.e%1,top=-pos.f%1;(left||top)&&(left&&(this._left=(this._left+left)%1,s.left=this._left+\"px\"),top&&(this._top=(this._top+top)%1,s.top=this._top+\"px\"))},R.prototype.clear=function(){R.eve(\"raphael.clear\",this);for(var c=this.canvas;c.firstChild;)c.removeChild(c.firstChild);this.bottom=this.top=null,(this.desc=$(\"desc\")).appendChild(R._g.doc.createTextNode(\"Created with Raphaël \"+R.version)),c.appendChild(this.desc),c.appendChild(this.defs=$(\"defs\"))},R.prototype.remove=function(){eve(\"raphael.remove\",this),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var i in this)this[i]=\"function\"==typeof this[i]?R._removedFactory(i):null};var setproto=R.st;for(var method in elproto)elproto[has](method)&&!setproto[has](method)&&(setproto[method]=function(methodname){return function(){var arg=arguments;return this.forEach(function(el){el[methodname].apply(el,arg)})}}(method))}}(),function(){if(R.vml){var has=\"hasOwnProperty\",Str=String,toFloat=parseFloat,math=Math,round=math.round,mmax=math.max,mmin=math.min,abs=math.abs,fillString=\"fill\",separator=/[, ]+/,eve=R.eve,ms=\" progid:DXImageTransform.Microsoft\",S=\" \",E=\"\",map={M:\"m\",L:\"l\",C:\"c\",Z:\"x\",m:\"t\",l:\"r\",c:\"v\",z:\"x\"},bites=/([clmz]),?([^clmz]*)/gi,blurregexp=/ progid:\\S+Blur\\([^\\)]+\\)/g,val=/-?[^,\\s-]+/g,cssDot=\"position:absolute;left:0;top:0;width:1px;height:1px\",zoom=21600,pathTypes={path:1,rect:1,image:1},ovalTypes={circle:1,ellipse:1},path2vml=function(path){var total=/[ahqstv]/gi,command=R._pathToAbsolute;if(Str(path).match(total)&&(command=R._path2curve),total=/[clmz]/g,command==R._pathToAbsolute&&!Str(path).match(total)){var res=Str(path).replace(bites,function(all,command,args){var vals=[],isMove=\"m\"==command.toLowerCase(),res=map[command];return args.replace(val,function(value){isMove&&2==vals.length&&(res+=vals+map[\"m\"==command?\"l\":\"L\"],vals=[]),vals.push(round(value*zoom))}),res+vals});return res}var p,r,pa=command(path);res=[];\nfor(var i=0,ii=pa.length;i<ii;i++){p=pa[i],r=pa[i][0].toLowerCase(),\"z\"==r&&(r=\"x\");for(var j=1,jj=p.length;j<jj;j++)r+=round(p[j]*zoom)+(j!=jj-1?\",\":E);res.push(r)}return res.join(S)},compensation=function(deg,dx,dy){var m=R.matrix();return m.rotate(-deg,.5,.5),{dx:m.x(dx,dy),dy:m.y(dx,dy)}},setCoords=function(p,sx,sy,dx,dy,deg){var _=p._,m=p.matrix,fillpos=_.fillpos,o=p.node,s=o.style,y=1,flip=\"\",kx=zoom/sx,ky=zoom/sy;if(s.visibility=\"hidden\",sx&&sy){if(o.coordsize=abs(kx)+S+abs(ky),s.rotation=deg*(sx*sy<0?-1:1),deg){var c=compensation(deg,dx,dy);dx=c.dx,dy=c.dy}if(sx<0&&(flip+=\"x\"),sy<0&&(flip+=\" y\")&&(y=-1),s.flip=flip,o.coordorigin=dx*-kx+S+dy*-ky,fillpos||_.fillsize){var fill=o.getElementsByTagName(fillString);fill=fill&&fill[0],o.removeChild(fill),fillpos&&(c=compensation(deg,m.x(fillpos[0],fillpos[1]),m.y(fillpos[0],fillpos[1])),fill.position=c.dx*y+S+c.dy*y),_.fillsize&&(fill.size=_.fillsize[0]*abs(sx)+S+_.fillsize[1]*abs(sy)),o.appendChild(fill)}s.visibility=\"visible\"}};R.toString=function(){return\"Your browser doesn’t support SVG. Falling down to VML.\\nYou are running Raphaël \"+this.version};var addArrow=function(o,value,isEnd){for(var values=Str(value).toLowerCase().split(\"-\"),se=isEnd?\"end\":\"start\",i=values.length,type=\"classic\",w=\"medium\",h=\"medium\";i--;)switch(values[i]){case\"block\":case\"classic\":case\"oval\":case\"diamond\":case\"open\":case\"none\":type=values[i];break;case\"wide\":case\"narrow\":h=values[i];break;case\"long\":case\"short\":w=values[i]}var stroke=o.node.getElementsByTagName(\"stroke\")[0];stroke[se+\"arrow\"]=type,stroke[se+\"arrowlength\"]=w,stroke[se+\"arrowwidth\"]=h},setFillAndStroke=function(o,params){o.attrs=o.attrs||{};var node=o.node,a=o.attrs,s=node.style,newpath=pathTypes[o.type]&&(params.x!=a.x||params.y!=a.y||params.width!=a.width||params.height!=a.height||params.cx!=a.cx||params.cy!=a.cy||params.rx!=a.rx||params.ry!=a.ry||params.r!=a.r),isOval=ovalTypes[o.type]&&(a.cx!=params.cx||a.cy!=params.cy||a.r!=params.r||a.rx!=params.rx||a.ry!=params.ry),res=o;for(var par in params)params[has](par)&&(a[par]=params[par]);if(newpath&&(a.path=R._getPath[o.type](o),o._.dirty=1),params.href&&(node.href=params.href),params.title&&(node.title=params.title),params.target&&(node.target=params.target),params.cursor&&(s.cursor=params.cursor),\"blur\"in params&&o.blur(params.blur),(params.path&&\"path\"==o.type||newpath)&&(node.path=path2vml(~Str(a.path).toLowerCase().indexOf(\"r\")?R._pathToAbsolute(a.path):a.path),\"image\"==o.type&&(o._.fillpos=[a.x,a.y],o._.fillsize=[a.width,a.height],setCoords(o,1,1,0,0,0))),\"transform\"in params&&o.transform(params.transform),isOval){var cx=+a.cx,cy=+a.cy,rx=+a.rx||+a.r||0,ry=+a.ry||+a.r||0;node.path=R.format(\"ar{0},{1},{2},{3},{4},{1},{4},{1}x\",round((cx-rx)*zoom),round((cy-ry)*zoom),round((cx+rx)*zoom),round((cy+ry)*zoom),round(cx*zoom)),o._.dirty=1}if(\"clip-rect\"in params){var rect=Str(params[\"clip-rect\"]).split(separator);if(4==rect.length){rect[2]=+rect[2]+ +rect[0],rect[3]=+rect[3]+ +rect[1];var div=node.clipRect||R._g.doc.createElement(\"div\"),dstyle=div.style;dstyle.clip=R.format(\"rect({1}px {2}px {3}px {0}px)\",rect),node.clipRect||(dstyle.position=\"absolute\",dstyle.top=0,dstyle.left=0,dstyle.width=o.paper.width+\"px\",dstyle.height=o.paper.height+\"px\",node.parentNode.insertBefore(div,node),div.appendChild(node),node.clipRect=div)}params[\"clip-rect\"]||node.clipRect&&(node.clipRect.style.clip=\"auto\")}if(o.textpath){var textpathStyle=o.textpath.style;params.font&&(textpathStyle.font=params.font),params[\"font-family\"]&&(textpathStyle.fontFamily='\"'+params[\"font-family\"].split(\",\")[0].replace(/^['\"]+|['\"]+$/g,E)+'\"'),params[\"font-size\"]&&(textpathStyle.fontSize=params[\"font-size\"]),params[\"font-weight\"]&&(textpathStyle.fontWeight=params[\"font-weight\"]),params[\"font-style\"]&&(textpathStyle.fontStyle=params[\"font-style\"])}if(\"arrow-start\"in params&&addArrow(res,params[\"arrow-start\"]),\"arrow-end\"in params&&addArrow(res,params[\"arrow-end\"],1),null!=params.opacity||null!=params[\"stroke-width\"]||null!=params.fill||null!=params.src||null!=params.stroke||null!=params[\"stroke-width\"]||null!=params[\"stroke-opacity\"]||null!=params[\"fill-opacity\"]||null!=params[\"stroke-dasharray\"]||null!=params[\"stroke-miterlimit\"]||null!=params[\"stroke-linejoin\"]||null!=params[\"stroke-linecap\"]){var fill=node.getElementsByTagName(fillString),newfill=!1;if(fill=fill&&fill[0],!fill&&(newfill=fill=createNode(fillString)),\"image\"==o.type&&params.src&&(fill.src=params.src),params.fill&&(fill.on=!0),null!=fill.on&&\"none\"!=params.fill&&null!==params.fill||(fill.on=!1),fill.on&&params.fill){var isURL=Str(params.fill).match(R._ISURL);if(isURL){fill.parentNode==node&&node.removeChild(fill),fill.rotate=!0,fill.src=isURL[1],fill.type=\"tile\";var bbox=o.getBBox(1);fill.position=bbox.x+S+bbox.y,o._.fillpos=[bbox.x,bbox.y],R._preload(isURL[1],function(){o._.fillsize=[this.offsetWidth,this.offsetHeight]})}else fill.color=R.getRGB(params.fill).hex,fill.src=E,fill.type=\"solid\",R.getRGB(params.fill).error&&(res.type in{circle:1,ellipse:1}||\"r\"!=Str(params.fill).charAt())&&addGradientFill(res,params.fill,fill)&&(a.fill=\"none\",a.gradient=params.fill,fill.rotate=!1)}if(\"fill-opacity\"in params||\"opacity\"in params){var opacity=((+a[\"fill-opacity\"]+1||2)-1)*((+a.opacity+1||2)-1)*((+R.getRGB(params.fill).o+1||2)-1);opacity=mmin(mmax(opacity,0),1),fill.opacity=opacity,fill.src&&(fill.color=\"none\")}node.appendChild(fill);var stroke=node.getElementsByTagName(\"stroke\")&&node.getElementsByTagName(\"stroke\")[0],newstroke=!1;!stroke&&(newstroke=stroke=createNode(\"stroke\")),(params.stroke&&\"none\"!=params.stroke||params[\"stroke-width\"]||null!=params[\"stroke-opacity\"]||params[\"stroke-dasharray\"]||params[\"stroke-miterlimit\"]||params[\"stroke-linejoin\"]||params[\"stroke-linecap\"])&&(stroke.on=!0),(\"none\"==params.stroke||null===params.stroke||null==stroke.on||0==params.stroke||0==params[\"stroke-width\"])&&(stroke.on=!1);var strokeColor=R.getRGB(params.stroke);stroke.on&&params.stroke&&(stroke.color=strokeColor.hex),opacity=((+a[\"stroke-opacity\"]+1||2)-1)*((+a.opacity+1||2)-1)*((+strokeColor.o+1||2)-1);var width=.75*(toFloat(params[\"stroke-width\"])||1);if(opacity=mmin(mmax(opacity,0),1),null==params[\"stroke-width\"]&&(width=a[\"stroke-width\"]),params[\"stroke-width\"]&&(stroke.weight=width),width&&width<1&&(opacity*=width)&&(stroke.weight=1),stroke.opacity=opacity,params[\"stroke-linejoin\"]&&(stroke.joinstyle=params[\"stroke-linejoin\"]||\"miter\"),stroke.miterlimit=params[\"stroke-miterlimit\"]||8,params[\"stroke-linecap\"]&&(stroke.endcap=\"butt\"==params[\"stroke-linecap\"]?\"flat\":\"square\"==params[\"stroke-linecap\"]?\"square\":\"round\"),params[\"stroke-dasharray\"]){var dasharray={\"-\":\"shortdash\",\".\":\"shortdot\",\"-.\":\"shortdashdot\",\"-..\":\"shortdashdotdot\",\". \":\"dot\",\"- \":\"dash\",\"--\":\"longdash\",\"- .\":\"dashdot\",\"--.\":\"longdashdot\",\"--..\":\"longdashdotdot\"};stroke.dashstyle=dasharray[has](params[\"stroke-dasharray\"])?dasharray[params[\"stroke-dasharray\"]]:E}newstroke&&node.appendChild(stroke)}if(\"text\"==res.type){res.paper.canvas.style.display=E;var span=res.paper.span,m=100,fontSize=a.font&&a.font.match(/\\d+(?:\\.\\d*)?(?=px)/);s=span.style,a.font&&(s.font=a.font),a[\"font-family\"]&&(s.fontFamily=a[\"font-family\"]),a[\"font-weight\"]&&(s.fontWeight=a[\"font-weight\"]),a[\"font-style\"]&&(s.fontStyle=a[\"font-style\"]),fontSize=toFloat(a[\"font-size\"]||fontSize&&fontSize[0])||10,s.fontSize=fontSize*m+\"px\",res.textpath.string&&(span.innerHTML=Str(res.textpath.string).replace(/</g,\"&#60;\").replace(/&/g,\"&#38;\").replace(/\\n/g,\"<br>\"));var brect=span.getBoundingClientRect();res.W=a.w=(brect.right-brect.left)/m,res.H=a.h=(brect.bottom-brect.top)/m,res.X=a.x,res.Y=a.y+res.H/2,(\"x\"in params||\"y\"in params)&&(res.path.v=R.format(\"m{0},{1}l{2},{1}\",round(a.x*zoom),round(a.y*zoom),round(a.x*zoom)+1));for(var dirtyattrs=[\"x\",\"y\",\"text\",\"font\",\"font-family\",\"font-weight\",\"font-style\",\"font-size\"],d=0,dd=dirtyattrs.length;d<dd;d++)if(dirtyattrs[d]in params){res._.dirty=1;break}switch(a[\"text-anchor\"]){case\"start\":res.textpath.style[\"v-text-align\"]=\"left\",res.bbx=res.W/2;break;case\"end\":res.textpath.style[\"v-text-align\"]=\"right\",res.bbx=-res.W/2;break;default:res.textpath.style[\"v-text-align\"]=\"center\",res.bbx=0}res.textpath.style[\"v-text-kern\"]=!0}},addGradientFill=function(o,gradient,fill){o.attrs=o.attrs||{};var pow=(o.attrs,Math.pow),type=\"linear\",fxfy=\".5 .5\";if(o.attrs.gradient=gradient,gradient=Str(gradient).replace(R._radial_gradient,function(all,fx,fy){return type=\"radial\",fx&&fy&&(fx=toFloat(fx),fy=toFloat(fy),pow(fx-.5,2)+pow(fy-.5,2)>.25&&(fy=math.sqrt(.25-pow(fx-.5,2))*(2*(fy>.5)-1)+.5),fxfy=fx+S+fy),E}),gradient=gradient.split(/\\s*\\-\\s*/),\"linear\"==type){var angle=gradient.shift();if(angle=-toFloat(angle),isNaN(angle))return null}var dots=R._parseDots(gradient);if(!dots)return null;if(o=o.shape||o.node,dots.length){o.removeChild(fill),fill.on=!0,fill.method=\"none\",fill.color=dots[0].color,fill.color2=dots[dots.length-1].color;for(var clrs=[],i=0,ii=dots.length;i<ii;i++)dots[i].offset&&clrs.push(dots[i].offset+S+dots[i].color);fill.colors=clrs.length?clrs.join():\"0% \"+fill.color,\"radial\"==type?(fill.type=\"gradientTitle\",fill.focus=\"100%\",fill.focussize=\"0 0\",fill.focusposition=fxfy,fill.angle=0):(fill.type=\"gradient\",fill.angle=(270-angle)%360),o.appendChild(fill)}return 1},Element=function(node,vml){this[0]=this.node=node,node.raphael=!0,this.id=R._oid++,node.raphaelid=this.id,this.X=0,this.Y=0,this.attrs={},this.paper=vml,this.matrix=R.matrix(),this._={transform:[],sx:1,sy:1,dx:0,dy:0,deg:0,dirty:1,dirtyT:1},!vml.bottom&&(vml.bottom=this),this.prev=vml.top,vml.top&&(vml.top.next=this),vml.top=this,this.next=null},elproto=R.el;Element.prototype=elproto,elproto.constructor=Element,elproto.transform=function(tstr){if(null==tstr)return this._.transform;var oldt,vbs=this.paper._viewBoxShift,vbt=vbs?\"s\"+[vbs.scale,vbs.scale]+\"-1-1t\"+[vbs.dx,vbs.dy]:E;vbs&&(oldt=tstr=Str(tstr).replace(/\\.{3}|\\u2026/g,this._.transform||E)),R._extractTransform(this,vbt+tstr);var split,matrix=this.matrix.clone(),skew=this.skew,o=this.node,isGrad=~Str(this.attrs.fill).indexOf(\"-\"),isPatt=!Str(this.attrs.fill).indexOf(\"url(\");if(matrix.translate(1,1),isPatt||isGrad||\"image\"==this.type)if(skew.matrix=\"1 0 0 1\",skew.offset=\"0 0\",split=matrix.split(),isGrad&&split.noRotation||!split.isSimple){o.style.filter=matrix.toFilter();var bb=this.getBBox(),bbt=this.getBBox(1),dx=bb.x-bbt.x,dy=bb.y-bbt.y;o.coordorigin=dx*-zoom+S+dy*-zoom,setCoords(this,1,1,dx,dy,0)}else o.style.filter=E,setCoords(this,split.scalex,split.scaley,split.dx,split.dy,split.rotate);else o.style.filter=E,skew.matrix=Str(matrix),skew.offset=matrix.offset();return oldt&&(this._.transform=oldt),this},elproto.rotate=function(deg,cx,cy){if(this.removed)return this;if(null!=deg){if(deg=Str(deg).split(separator),deg.length-1&&(cx=toFloat(deg[1]),cy=toFloat(deg[2])),deg=toFloat(deg[0]),null==cy&&(cx=cy),null==cx||null==cy){var bbox=this.getBBox(1);cx=bbox.x+bbox.width/2,cy=bbox.y+bbox.height/2}return this._.dirtyT=1,this.transform(this._.transform.concat([[\"r\",deg,cx,cy]])),this}},elproto.translate=function(dx,dy){return this.removed?this:(dx=Str(dx).split(separator),dx.length-1&&(dy=toFloat(dx[1])),dx=toFloat(dx[0])||0,dy=+dy||0,this._.bbox&&(this._.bbox.x+=dx,this._.bbox.y+=dy),this.transform(this._.transform.concat([[\"t\",dx,dy]])),this)},elproto.scale=function(sx,sy,cx,cy){if(this.removed)return this;if(sx=Str(sx).split(separator),sx.length-1&&(sy=toFloat(sx[1]),cx=toFloat(sx[2]),cy=toFloat(sx[3]),isNaN(cx)&&(cx=null),isNaN(cy)&&(cy=null)),sx=toFloat(sx[0]),null==sy&&(sy=sx),null==cy&&(cx=cy),null==cx||null==cy)var bbox=this.getBBox(1);return cx=null==cx?bbox.x+bbox.width/2:cx,cy=null==cy?bbox.y+bbox.height/2:cy,this.transform(this._.transform.concat([[\"s\",sx,sy,cx,cy]])),this._.dirtyT=1,this},elproto.hide=function(){return!this.removed&&(this.node.style.display=\"none\"),this},elproto.show=function(){return!this.removed&&(this.node.style.display=E),this},elproto._getBBox=function(){return this.removed?{}:{x:this.X+(this.bbx||0)-this.W/2,y:this.Y-this.H,width:this.W,height:this.H}},elproto.remove=function(){if(!this.removed&&this.node.parentNode){this.paper.__set__&&this.paper.__set__.exclude(this),R.eve.unbind(\"raphael.*.*.\"+this.id),R._tear(this,this.paper),this.node.parentNode.removeChild(this.node),this.shape&&this.shape.parentNode.removeChild(this.shape);for(var i in this)this[i]=\"function\"==typeof this[i]?R._removedFactory(i):null;this.removed=!0}},elproto.attr=function(name,value){if(this.removed)return this;if(null==name){var res={};for(var a in this.attrs)this.attrs[has](a)&&(res[a]=this.attrs[a]);return res.gradient&&\"none\"==res.fill&&(res.fill=res.gradient)&&delete res.gradient,res.transform=this._.transform,res}if(null==value&&R.is(name,\"string\")){if(name==fillString&&\"none\"==this.attrs.fill&&this.attrs.gradient)return this.attrs.gradient;for(var names=name.split(separator),out={},i=0,ii=names.length;i<ii;i++)name=names[i],name in this.attrs?out[name]=this.attrs[name]:R.is(this.paper.customAttributes[name],\"function\")?out[name]=this.paper.customAttributes[name].def:out[name]=R._availableAttrs[name];return ii-1?out:out[names[0]]}if(this.attrs&&null==value&&R.is(name,\"array\")){for(out={},i=0,ii=name.length;i<ii;i++)out[name[i]]=this.attr(name[i]);return out}var params;null!=value&&(params={},params[name]=value),null==value&&R.is(name,\"object\")&&(params=name);for(var key in params)eve(\"raphael.attr.\"+key+\".\"+this.id,this,params[key]);if(params){for(key in this.paper.customAttributes)if(this.paper.customAttributes[has](key)&&params[has](key)&&R.is(this.paper.customAttributes[key],\"function\")){var par=this.paper.customAttributes[key].apply(this,[].concat(params[key]));this.attrs[key]=params[key];for(var subkey in par)par[has](subkey)&&(params[subkey]=par[subkey])}params.text&&\"text\"==this.type&&(this.textpath.string=params.text),setFillAndStroke(this,params)}return this},elproto.toFront=function(){return!this.removed&&this.node.parentNode.appendChild(this.node),this.paper&&this.paper.top!=this&&R._tofront(this,this.paper),this},elproto.toBack=function(){return this.removed?this:(this.node.parentNode.firstChild!=this.node&&(this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild),R._toback(this,this.paper)),this)},elproto.insertAfter=function(element){return this.removed?this:(element.constructor==R.st.constructor&&(element=element[element.length-1]),element.node.nextSibling?element.node.parentNode.insertBefore(this.node,element.node.nextSibling):element.node.parentNode.appendChild(this.node),R._insertafter(this,element,this.paper),this)},elproto.insertBefore=function(element){return this.removed?this:(element.constructor==R.st.constructor&&(element=element[0]),element.node.parentNode.insertBefore(this.node,element.node),R._insertbefore(this,element,this.paper),this)},elproto.blur=function(size){var s=this.node.runtimeStyle,f=s.filter;return f=f.replace(blurregexp,E),0!==+size?(this.attrs.blur=size,s.filter=f+S+ms+\".Blur(pixelradius=\"+(+size||1.5)+\")\",s.margin=R.format(\"-{0}px 0 0 -{0}px\",round(+size||1.5))):(s.filter=f,s.margin=0,delete this.attrs.blur),this},R._engine.path=function(pathString,vml){var el=createNode(\"shape\");el.style.cssText=cssDot,el.coordsize=zoom+S+zoom,el.coordorigin=vml.coordorigin;var p=new Element(el,vml),attr={fill:\"none\",stroke:\"#000\"};pathString&&(attr.path=pathString),p.type=\"path\",p.path=[],p.Path=E,setFillAndStroke(p,attr),vml.canvas.appendChild(el);var skew=createNode(\"skew\");return skew.on=!0,el.appendChild(skew),p.skew=skew,p.transform(E),p},R._engine.rect=function(vml,x,y,w,h,r){var path=R._rectPath(x,y,w,h,r),res=vml.path(path),a=res.attrs;return res.X=a.x=x,res.Y=a.y=y,res.W=a.width=w,res.H=a.height=h,a.r=r,a.path=path,res.type=\"rect\",res},R._engine.ellipse=function(vml,x,y,rx,ry){var res=vml.path();res.attrs;return res.X=x-rx,res.Y=y-ry,res.W=2*rx,res.H=2*ry,res.type=\"ellipse\",setFillAndStroke(res,{cx:x,cy:y,rx:rx,ry:ry}),res},R._engine.circle=function(vml,x,y,r){var res=vml.path();res.attrs;return res.X=x-r,res.Y=y-r,res.W=res.H=2*r,res.type=\"circle\",setFillAndStroke(res,{cx:x,cy:y,r:r}),res},R._engine.image=function(vml,src,x,y,w,h){var path=R._rectPath(x,y,w,h),res=vml.path(path).attr({stroke:\"none\"}),a=res.attrs,node=res.node,fill=node.getElementsByTagName(fillString)[0];return a.src=src,res.X=a.x=x,res.Y=a.y=y,res.W=a.width=w,res.H=a.height=h,a.path=path,res.type=\"image\",fill.parentNode==node&&node.removeChild(fill),fill.rotate=!0,fill.src=src,fill.type=\"tile\",res._.fillpos=[x,y],res._.fillsize=[w,h],node.appendChild(fill),setCoords(res,1,1,0,0,0),res},R._engine.text=function(vml,x,y,text){var el=createNode(\"shape\"),path=createNode(\"path\"),o=createNode(\"textpath\");x=x||0,y=y||0,text=text||\"\",path.v=R.format(\"m{0},{1}l{2},{1}\",round(x*zoom),round(y*zoom),round(x*zoom)+1),path.textpathok=!0,o.string=Str(text),o.on=!0,el.style.cssText=cssDot,el.coordsize=zoom+S+zoom,el.coordorigin=\"0 0\";var p=new Element(el,vml),attr={fill:\"#000\",stroke:\"none\",font:R._availableAttrs.font,text:text};p.shape=el,p.path=path,p.textpath=o,p.type=\"text\",p.attrs.text=Str(text),p.attrs.x=x,p.attrs.y=y,p.attrs.w=1,p.attrs.h=1,setFillAndStroke(p,attr),el.appendChild(o),el.appendChild(path),vml.canvas.appendChild(el);var skew=createNode(\"skew\");return skew.on=!0,el.appendChild(skew),p.skew=skew,p.transform(E),p},R._engine.setSize=function(width,height){var cs=this.canvas.style;return this.width=width,this.height=height,width==+width&&(width+=\"px\"),height==+height&&(height+=\"px\"),cs.width=width,cs.height=height,cs.clip=\"rect(0 \"+width+\" \"+height+\" 0)\",this._viewBox&&R._engine.setViewBox.apply(this,this._viewBox),this},R._engine.setViewBox=function(x,y,w,h,fit){R.eve(\"raphael.setViewBox\",this,this._viewBox,[x,y,w,h,fit]);var H,W,width=this.width,height=this.height,size=1/mmax(w/width,h/height);return fit&&(H=height/h,W=width/w,w*H<width&&(x-=(width-w*H)/2/H),h*W<height&&(y-=(height-h*W)/2/W)),this._viewBox=[x,y,w,h,!!fit],this._viewBoxShift={dx:-x,dy:-y,scale:size},this.forEach(function(el){el.transform(\"...\")}),this};var createNode;R._engine.initWin=function(win){var doc=win.document;doc.createStyleSheet().addRule(\".rvml\",\"behavior:url(#default#VML)\");try{!doc.namespaces.rvml&&doc.namespaces.add(\"rvml\",\"urn:schemas-microsoft-com:vml\"),createNode=function(tagName){return doc.createElement(\"<rvml:\"+tagName+' class=\"rvml\">')}}catch(e){createNode=function(tagName){return doc.createElement(\"<\"+tagName+' xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">')}}},R._engine.initWin(R._g.win),R._engine.create=function(){var con=R._getContainer.apply(0,arguments),container=con.container,height=con.height,width=con.width,x=con.x,y=con.y;if(!container)throw new Error(\"VML container not found.\");var res=new R._Paper,c=res.canvas=R._g.doc.createElement(\"div\"),cs=c.style;return x=x||0,y=y||0,width=width||512,height=height||342,res.width=width,res.height=height,width==+width&&(width+=\"px\"),height==+height&&(height+=\"px\"),res.coordsize=1e3*zoom+S+1e3*zoom,res.coordorigin=\"0 0\",res.span=R._g.doc.createElement(\"span\"),res.span.style.cssText=\"position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;\",c.appendChild(res.span),cs.cssText=R.format(\"top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden\",width,height),1==container?(R._g.doc.body.appendChild(c),cs.left=x+\"px\",cs.top=y+\"px\",cs.position=\"absolute\"):container.firstChild?container.insertBefore(c,container.firstChild):container.appendChild(c),res.renderfix=function(){},res},R.prototype.clear=function(){R.eve(\"raphael.clear\",this),this.canvas.innerHTML=E,this.span=R._g.doc.createElement(\"span\"),this.span.style.cssText=\"position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;\",this.canvas.appendChild(this.span),this.bottom=this.top=null},R.prototype.remove=function(){R.eve(\"raphael.remove\",this),this.canvas.parentNode.removeChild(this.canvas);for(var i in this)this[i]=\"function\"==typeof this[i]?R._removedFactory(i):null;return!0};var setproto=R.st;for(var method in elproto)elproto[has](method)&&!setproto[has](method)&&(setproto[method]=function(methodname){return function(){var arg=arguments;return this.forEach(function(el){el[methodname].apply(el,arg)})}}(method))}}(),oldRaphael.was?g.win.Raphael=R:Raphael=R,R}),window.ABCJS||(window.ABCJS={}),function(){\"use strict\";function hasClass(element,cls){var elClass=element.getAttribute(\"class\"),rclass=/[\\t\\r\\n\\f]/g,className=\" \"+cls+\" \";return 1===element.nodeType&&(\" \"+elClass+\" \").replace(rclass,\" \").indexOf(className)>=0}function getAllElementsByClasses(startingEl,class1,class2){for(var els=startingEl.getElementsByClassName(class1),ret=[],i=0;i<els.length;i++)hasClass(els[i],class2)&&ret.push(els[i]);return ret}function getCssRule(selector){for(var rule,i=0;i<document.styleSheets.length&&void 0===rule;i++){var css=document.styleSheets[i],rules=css.rules;if(rules)for(var j=0;j<rules.length&&void 0===rule;j++)rules[j].selectorText&&rules[j].selectorText===selector&&(rule=rules[j])}return rule?rule:(document.styleSheets[0].insertRule(selector+\" { }\",1),getCssRule(selector))}function getBeatsPerMinute(tune,options){var bpm;return bpm=options.bpm?options.bpm:tune&&tune.metaText&&tune.metaText.tempo&&tune.metaText.tempo.bpm?tune.metaText.tempo.bpm:120}function setMargin(margin){cssRule.style.marginTop=-margin+\"px\",currentMargin=margin}var scrollTimer,animateTimer,cssRule,currentMargin,animationTarget,shouldResetOverflow,cursor,stopNextTime=!1;ABCJS.startAnimation=function(paper,tune,options){function scrolling(){var currentPosition=paper.style.marginLeft;currentPosition=\"\"===currentPosition?0:parseInt(currentPosition),currentPosition-=distance,paper.style.marginLeft=currentPosition+\"px\",currentPosition>outer.offsetWidth-paper.scrollWidth&&(scrollTimer=setTimeout(scrolling,interval))}function processMeasureHider(lineNum,measureNum){var els=getAllElementsByClasses(paper,\"l\"+lineNum,\"m\"+measureNum);if(els.length>0)for(var i=0;i<els.length;i++){var el=els[i];hasClass(el,\"bar\")||(el.style.display=\"none\")}}function addVerticalInfo(timingEvents){for(var lastBarTop,lastBarBottom,lastEventTop,lastEventBottom,e=timingEvents.length-1;e>=0;e--){var ev=timingEvents[e];\"bar\"===ev.type?(ev.top=lastEventTop,ev.nextTop=lastBarTop,lastBarTop=lastEventTop,ev.bottom=lastEventBottom,ev.nextBottom=lastBarBottom,lastBarBottom=lastEventBottom):\"event\"===ev.type&&(lastEventTop=ev.top,lastEventBottom=ev.top+ev.height)}}function makeSortedArray(hash){var arr=[];for(var k in hash)hash.hasOwnProperty(k)&&arr.push(hash[k]);return arr=arr.sort(function(a,b){var diff=a.time-b.time;return 0!==diff?diff:\"bar\"===a.type?-1:1})}function setupEvents(engraver){for(var eventHash={},time=0,isTiedState=!1,line=0;line<engraver.staffgroups.length;line++){var group=engraver.staffgroups[line],voices=group.voices,firstStaff=group.staffs[0],middleC=firstStaff.absoluteY,top=middleC-firstStaff.top*ABCJS.write.spacing.STEP,lastStaff=group.staffs[group.staffs.length-1];middleC=lastStaff.absoluteY;for(var bottom=middleC-lastStaff.bottom*ABCJS.write.spacing.STEP,height=bottom-top,maxVoiceTime=0,v=0;v<voices.length;v++){for(var voiceTime=time,elements=voices[v].children,elem=0;elem<elements.length;elem++){var element=elements[elem];if(element.hint)break;if(element.duration>0){var isTiedToNext=element.startTie;isTiedState?isTiedToNext||(isTiedState=!1):(eventHash[\"event\"+voiceTime]?eventHash[\"event\"+voiceTime].left=Math.min(eventHash[\"event\"+voiceTime].left,element.x):eventHash[\"event\"+voiceTime]={type:\"event\",time:voiceTime,top:top,height:height,left:element.x,width:element.w},isTiedToNext&&(isTiedState=!0)),voiceTime+=element.duration}if(\"bar\"===element.type&&(0===timingEvents.length||\"bar\"!==timingEvents[timingEvents.length-1])&&element.elemset&&element.elemset.length>0&&element.elemset[0].attrs){for(var lineNum,measureNum,klass=element.elemset[0].attrs.class,arr=klass.split(\" \"),i=0;i<arr.length;i++){var match=/m(\\d+)/.exec(arr[i]);match&&(measureNum=match[1]),match=/l(\\d+)/.exec(arr[i]),match&&(lineNum=match[1])}eventHash[\"bar\"+voiceTime]={type:\"bar\",time:voiceTime,lineNum:lineNum,measureNum:measureNum}}}maxVoiceTime=Math.max(maxVoiceTime,voiceTime)}time=maxVoiceTime}timingEvents=makeSortedArray(eventHash),totalBeats=timingEvents[timingEvents.length-1].time/beatLength,options.scrollVertical&&addVerticalInfo(timingEvents)}function isEndOfLine(currentNote){return currentNote.top!==currentNote.nextTop&&void 0!==currentNote.nextTop}function shouldScroll(outer,scrollPos,currentNote){var height=parseInt(outer.clientHeight,10),isVisible=currentNote.nextBottom-scrollPos<height;return!isVisible}function processShowCursor(){var currentNote=timingEvents.shift();return currentNote?\"bar\"===currentNote.type?(options.scrollVertical&&isEndOfLine(currentNote)&&shouldScroll(outer,currentMargin,currentNote)&&setTimeout(function(){setMargin(currentNote.nextTop)},millisecondsPerHalfMeasure),options.hideFinishedMeasures&&processMeasureHider(currentNote.lineNum,currentNote.measureNum),timingEvents.length>0?timingEvents[0].time/beatLength:0):(options.scrollHint&&lastTop!==currentNote.top&&(lastTop=currentNote.top,setMargin(lastTop)),options.showCursor&&cursor.css({left:currentNote.left+\"px\",top:currentNote.top+\"px\",width:currentNote.width+\"px\",height:currentNote.height+\"px\"}),timingEvents.length>0?timingEvents[0].time/beatLength:(stopNextTime=!0,0)):(stopNextTime=!0,0)}function processNext(){if(stopNextTime)return void ABCJS.stopAnimation();var currentTime=(new Date).getTime();if(isPaused)return void(pausedDifference=currentTime-pausedTime);var nextTimeInBeats=processShowCursor(),nextTimeInMilliseconds=nextTimeInBeats/beatsPerMillisecond,interval=startTime+nextTimeInMilliseconds-currentTime;interval<=0?processNext():animateTimer=setTimeout(processNext,interval)}if(void 0===paper.getElementsByClassName)return void console.error(\"ABCJS.startAnimation: The first parameter must be a regular DOM element. (Did you pass a jQuery object or an ID?)\");if(void 0===tune.getBeatLength)return void console.error(\"ABCJS.startAnimation: The second parameter must be a single tune. (Did you pass the entire array of tunes?)\");if((options.scrollHorizontal||options.scrollVertical||options.scrollHint)&&(hasClass(paper,\"abcjs-inner\")||(paper.scrollTop=0,paper.style.overflow=\"hidden\",paper=paper.children[0]),!hasClass(paper,\"abcjs-inner\")))return void console.error(\"ABCJS.startAnimation: When using scrollHorizontal/scrollVertical/scrollHint, the music must have been rendered using viewportHorizontal/viewportVertical.\");ABCJS.stopAnimation(),animationTarget=paper,shouldResetOverflow=options.scrollVertical||options.scrollHint,options.showCursor&&(cursor=$('<div class=\"cursor\" style=\"position: absolute;\"></div>'),$(paper).append(cursor),$(paper).css({position:\"relative\"})),stopNextTime=!1;var millisecondsPerHalfMeasure,beatsPerMinute=getBeatsPerMinute(tune,options),beatsPerMillisecond=beatsPerMinute/6e4,beatLength=tune.getBeatLength(),totalBeats=0;if(options.scrollVertical){var millisecondsPerBeat=1/beatsPerMillisecond,beatsPerMeasure=1/beatLength,millisecondsPerMeasure=millisecondsPerBeat*beatsPerMeasure;millisecondsPerHalfMeasure=millisecondsPerMeasure/2,cssRule=getCssRule(\".abcjs-inner\")}var startTime,pausedTime,pausedDifference,isPaused=!1,initialWait=2700,interval=11,distance=1,outer=paper.parentNode;options.scrollHorizontal&&(paper.style.marginLeft=\"0px\",scrollTimer=setTimeout(scrolling,initialWait));var timingEvents=[];setupEvents(tune.engraver);var lastTop=-1;$(outer).find(\".abcjs-inner\");currentMargin=0,options.scrollVertical&&setMargin(0),startTime=new Date,startTime=startTime.getTime(),isPaused=!1,processNext(),ABCJS.pauseAnimation=function(pause){if(pause&&!isPaused)isPaused=!0,pausedTime=(new Date).getTime();else if(!pause&&isPaused){var nowTime=(new Date).getTime(),elapsedTimeWhenPaused=nowTime-pausedTime;startTime+=elapsedTimeWhenPaused,pausedTime=void 0,isPaused=!1,animateTimer=setTimeout(processNext,pausedDifference),pausedDifference=void 0}}},ABCJS.stopAnimation=function(){clearTimeout(animateTimer),clearTimeout(scrollTimer),cursor&&(cursor.remove(),cursor=null),shouldResetOverflow&&(animationTarget&&animationTarget.parentNode&&(animationTarget.parentNode.style.overflowY=\"auto\"),setMargin(0))}}(),window.ABCJS||(window.ABCJS={}),function(){\"use strict\";function renderEngine(callback,output,abc,parserParams,renderParams){var ret=[],isArray=function(testObject){return testObject&&!testObject.propertyIsEnumerable(\"length\")&&\"object\"==typeof testObject&&\"number\"==typeof testObject.length};if(void 0!==output&&void 0!==abc){isArray(output)||(output=[output]),void 0===parserParams&&(parserParams={}),void 0===renderParams&&(renderParams={});for(var currentTune=renderParams.startingTune?renderParams.startingTune:0,book=new ABCJS.TuneBook(abc),abcParser=new window.ABCJS.parse.Parse,i=0;i<output.length;i++){var div=output[i];if(\"string\"==typeof div&&(div=document.getElementById(div)),div&&(div.innerHTML=\"\",currentTune<book.tunes.length)){abcParser.parse(book.tunes[currentTune].abc,parserParams);var tune=abcParser.getTune();ret.push(tune),callback(div,tune,i)}currentTune++}return ret}}function resizeOuter(){var width=window.innerWidth;for(var id in resizeDivs)if(resizeDivs.hasOwnProperty(id)){var outer=resizeDivs[id],ofs=outer.offsetLeft;width-=2*ofs,outer.style.width=width+\"px\"}}function renderOne(div,tune,renderParams,engraverParams){var width=renderParams.width?renderParams.width:800;renderParams.viewportHorizontal?(div.innerHTML='<div class=\"abcjs-inner\"></div>',renderParams.scrollHorizontal?(div.style.overflowX=\"auto\",div.style.overflowY=\"hidden\"):div.style.overflow=\"hidden\",resizeDivs[div.id]=div,div=div.children[0]):renderParams.viewportVertical&&(div.innerHTML='<div class=\"abcjs-inner scroll-amount\"></div>',div.style.overflowX=\"hidden\",div.style.overflowY=\"auto\",div=div.children[0]);var paper=Raphael(div,width,400);void 0===engraverParams&&(engraverParams={});var engraver_controller=new ABCJS.write.EngraverController(paper,engraverParams);if(engraver_controller.engraveABC(tune),tune.engraver=engraver_controller,renderParams.viewportVertical||renderParams.viewportHorizontal){var parent=div.parentNode;parent.style.width=div.style.width}}function renderEachLineSeparately(div,tune,renderParams,engraverParams){function initializeTuneLine(tune){return{formatting:tune.formatting,media:tune.media,version:tune.version,metaText:{},lines:[]}}for(var tuneLine,tunes=[],i=0;i<tune.lines.length;i++){var line=tune.lines[i];tuneLine||(tuneLine=initializeTuneLine(tune)),0===i&&(tuneLine.metaText.tempo=tune.metaText.tempo,tuneLine.metaText.title=tune.metaText.title,tuneLine.metaText.header=tune.metaText.header,tuneLine.metaText.rhythm=tune.metaText.rhythm,tuneLine.metaText.origin=tune.metaText.origin,tuneLine.metaText.composer=tune.metaText.composer,tuneLine.metaText.author=tune.metaText.author,tuneLine.metaText.partOrder=tune.metaText.partOrder),tuneLine.lines.push(line),line.staff&&(tunes.push(tuneLine),tuneLine=void 0)}if(tuneLine)for(var lastLine=tunes[tunes.length-1],j=0;j<tuneLine.lines.length;j++)lastLine.lines.push(tuneLine.lines[j]);tuneLine=tunes[tunes.length-1],tuneLine.metaText.unalignedWords=tune.metaText.unalignedWords,tuneLine.metaText.book=tune.metaText.book,tuneLine.metaText.source=tune.metaText.source,tuneLine.metaText.discography=tune.metaText.discography,tuneLine.metaText.notes=tune.metaText.notes,tuneLine.metaText.transcription=tune.metaText.transcription,tuneLine.metaText.history=tune.metaText.history,tuneLine.metaText[\"abc-copyright\"]=tune.metaText[\"abc-copyright\"],tuneLine.metaText[\"abc-creator\"]=tune.metaText[\"abc-creator\"],tuneLine.metaText[\"abc-edited-by\"]=tune.metaText[\"abc-edited-by\"],tuneLine.metaText.footer=tune.metaText.footer;var eParamsFirst=JSON.parse(JSON.stringify(engraverParams)),eParamsMid=JSON.parse(JSON.stringify(engraverParams)),eParamsLast=JSON.parse(JSON.stringify(engraverParams));\neParamsFirst.paddingbottom=-20,eParamsMid.paddingbottom=-20,eParamsMid.paddingtop=10,eParamsLast.paddingtop=10;for(var k=0;k<tunes.length;k++){var lineEl=document.createElement(\"div\");div.appendChild(lineEl);var ep=0===k?eParamsFirst:k===tunes.length-1?eParamsLast:eParamsMid;renderOne(lineEl,tunes[k],renderParams,ep)}}ABCJS.numberOfTunes=function(abc){var tunes=abc.split(\"\\nX:\"),num=tunes.length;return 0===num&&(num=1),num},ABCJS.TuneBook=function(book){var This=this,directives=\"\";book=window.ABCJS.parse.strip(book);for(var tunes=book.split(\"\\nX:\"),i=1;i<tunes.length;i++)tunes[i]=\"X:\"+tunes[i];var pos=0;if(This.tunes=[],window.ABCJS.parse.each(tunes,function(tune){This.tunes.push({abc:tune,startPos:pos}),pos+=tune.length}),This.tunes.length>1&&!window.ABCJS.parse.startsWith(This.tunes[0].abc,\"X:\")){var dir=This.tunes.shift(),arrDir=dir.abc.split(\"\\n\");window.ABCJS.parse.each(arrDir,function(line){window.ABCJS.parse.startsWith(line,\"%%\")&&(directives+=line+\"\\n\")})}This.header=directives,window.ABCJS.parse.each(This.tunes,function(tune){var end=tune.abc.indexOf(\"\\n\\n\");end>0&&(tune.abc=tune.abc.substring(0,end)),tune.pure=tune.abc,tune.abc=directives+tune.abc;var title=tune.pure.split(\"T:\");title.length>1?(title=title[1].split(\"\\n\"),tune.title=title[0].replace(/^\\s+|\\s+$/g,\"\")):tune.title=\"\";var id=tune.pure.substring(2,tune.pure.indexOf(\"\\n\"));tune.id=id.replace(/^\\s+|\\s+$/g,\"\")})},ABCJS.TuneBook.prototype.getTuneById=function(id){for(var i=0;i<this.tunes.length;i++)if(this.tunes[i].id===id)return this.tunes[i];return null},ABCJS.TuneBook.prototype.getTuneByTitle=function(title){for(var i=0;i<this.tunes.length;i++)if(this.tunes[i].title===title)return this.tunes[i];return null};var resizeDivs={};window.addEventListener(\"resize\",resizeOuter),window.addEventListener(\"orientationChange\",resizeOuter),ABCJS.renderAbc=function(output,abc,parserParams,engraverParams,renderParams){function callback(div,tune){!renderParams.oneSvgPerLine||tune.lines.length<2?renderOne(div,tune,renderParams,engraverParams):renderEachLineSeparately(div,tune,renderParams,engraverParams)}return void 0===renderParams&&(renderParams={}),renderEngine(callback,output,abc,parserParams,renderParams)},ABCJS.renderMidi=function(output,abc,parserParams,midiParams,renderParams){function callback(div,tune,index){var html=\"\",midi=window.ABCJS.midi.create(tune,midiParams);if(midiParams.generateInline){var inlineMidi=midi.inline?midi.inline:midi;html+=window.ABCJS.midi.generateMidiControls(tune,midiParams,inlineMidi,index)}if(midiParams.generateDownload){var downloadMidi=midi.download?midi.download:midi;html+=window.ABCJS.midi.generateMidiDownloadLink(tune,midiParams,downloadMidi,index)}div.innerHTML=html;var find=function(element,cls){var els=element.getElementsByClassName(cls);return 0===els.length?null:els[0]};if(midiParams.generateInline&&(midiParams.animate||midiParams.listener)){var parent=find(div,\"abcjs-inline-midi\");if(parent.abcjsTune=tune,parent.abcjsListener=midiParams.listener,parent.abcjsQpm=midiParams.qpm,midiParams.animate){var drumIntro=midiParams.drumIntro?midiParams.drumIntro:0;parent.abcjsAnimate=midiParams.animate.listener,parent.abcjsTune=midiParams.animate.target,parent.abcjsTune.setTiming(midiParams.qpm,drumIntro)}}if(midiParams.generateInline&&midiParams.inlineControls&&midiParams.inlineControls.startPlaying){var startButton=find(div,\"abcjs-midi-start\");window.ABCJS.midi.startPlaying(startButton)}}return void 0===midiParams&&(midiParams={}),void 0===midiParams.generateInline&&(midiParams.generateInline=!0),midiParams.inlineControls&&(midiParams.inlineControls.selectionToggle=!1),renderEngine(callback,output,abc,parserParams,renderParams)}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.data||(window.ABCJS.data={}),window.ABCJS.data.Tune=function(){function addVerticalInfo(timingEvents){for(var lastBarTop,lastBarBottom,lastEventTop,lastEventBottom,e=timingEvents.length-1;e>=0;e--){var ev=timingEvents[e];\"bar\"===ev.type?(ev.top=lastEventTop,ev.nextTop=lastBarTop,lastBarTop=lastEventTop,ev.bottom=lastEventBottom,ev.nextBottom=lastBarBottom,lastBarBottom=lastEventBottom):\"event\"===ev.type&&(lastEventTop=ev.top,lastEventBottom=ev.top+ev.height)}}function makeSortedArray(hash){var arr=[];for(var k in hash)hash.hasOwnProperty(k)&&arr.push(hash[k]);return arr=arr.sort(function(a,b){var diff=a.seconds-b.seconds;return 0!==diff?diff:\"bar\"===a.type?-1:1})}this.getBeatLength=function(){for(var i=0;i<this.lines.length;i++)if(this.lines[i].staff)for(var j=0;j<this.lines[i].staff.length;j++)if(this.lines[i].staff[j].meter){var meter=this.lines[i].staff[j].meter;if(\"specified\"===meter.type){if(meter.value.length>0){var num=parseInt(meter.value[0].num,10),den=parseInt(meter.value[0].den,10);return 6===num&&8===den?3/8:9===num&&8===den?3/8:12===num&&8===den?3/8:1/den}return null}return\"cut_time\"===meter.type?.5:.25}return null},this.reset=function(){this.version=\"1.0.1\",this.media=\"screen\",this.metaText={},this.formatting={},this.lines=[],this.staffNum=0,this.voiceNum=0,this.lineNum=0},this.cleanUp=function(defWidth,defLength,barsperstaff,staffnonote,currSlur){function cleanUpSlursInLine(line){for(var x,addEndSlur=function(obj,num,chordPos){if(void 0===currSlur[chordPos]){for(x=0;x<currSlur.length;x++)if(void 0!==currSlur[x]){chordPos=x;break}if(void 0===currSlur[chordPos]){var offNum=100*chordPos+1;window.ABCJS.parse.each(obj.endSlur,function(x){offNum===x&&--offNum}),currSlur[chordPos]=[offNum]}}for(var slurNum,i=0;i<num;i++)slurNum=currSlur[chordPos].pop(),obj.endSlur.push(slurNum);return 0===currSlur[chordPos].length&&delete currSlur[chordPos],slurNum},addStartSlur=function(obj,num,chordPos,usedNums){obj.startSlur=[],void 0===currSlur[chordPos]&&(currSlur[chordPos]=[]);for(var nextNum=100*chordPos+1,i=0;i<num;i++)usedNums&&(window.ABCJS.parse.each(usedNums,function(x){nextNum===x&&++nextNum}),window.ABCJS.parse.each(usedNums,function(x){nextNum===x&&++nextNum}),window.ABCJS.parse.each(usedNums,function(x){nextNum===x&&++nextNum})),window.ABCJS.parse.each(currSlur[chordPos],function(x){nextNum===x&&++nextNum}),window.ABCJS.parse.each(currSlur[chordPos],function(x){nextNum===x&&++nextNum}),currSlur[chordPos].push(nextNum),obj.startSlur.push({label:nextNum}),nextNum++},i=0;i<line.length;i++){var el=line[i];if(\"note\"===el.el_type){if(el.gracenotes)for(var g=0;g<el.gracenotes.length;g++){if(el.gracenotes[g].endSlur){var gg=el.gracenotes[g].endSlur;el.gracenotes[g].endSlur=[];for(var ggg=0;ggg<gg;ggg++)addEndSlur(el.gracenotes[g],1,20)}el.gracenotes[g].startSlur&&(x=el.gracenotes[g].startSlur,addStartSlur(el.gracenotes[g],x,20))}if(el.endSlur&&(x=el.endSlur,el.endSlur=[],addEndSlur(el,x,0)),el.startSlur&&(x=el.startSlur,addStartSlur(el,x,0)),el.pitches){for(var usedNums=[],p=0;p<el.pitches.length;p++)if(el.pitches[p].endSlur){var k=el.pitches[p].endSlur;el.pitches[p].endSlur=[];for(var j=0;j<k;j++){var slurNum=addEndSlur(el.pitches[p],1,p+1);usedNums.push(slurNum)}}for(p=0;p<el.pitches.length;p++)el.pitches[p].startSlur&&(x=el.pitches[p].startSlur,addStartSlur(el.pitches[p],x,p+1,usedNums));el.gracenotes&&el.pitches[0].endSlur&&100===el.pitches[0].endSlur[0]&&el.pitches[0].startSlur&&(el.gracenotes[0].endSlur?el.gracenotes[0].endSlur.push(el.pitches[0].startSlur[0].label):el.gracenotes[0].endSlur=[el.pitches[0].startSlur[0].label],1===el.pitches[0].endSlur.length?delete el.pitches[0].endSlur:100===el.pitches[0].endSlur[0]?el.pitches[0].endSlur.shift():100===el.pitches[0].endSlur[el.pitches[0].endSlur.length-1]&&el.pitches[0].endSlur.pop(),1===currSlur[1].length?delete currSlur[1]:currSlur[1].pop())}}}}function fixClefPlacement(el){window.ABCJS.parse.parseKeyVoice.fixClef(el)}function getNextMusicLine(lines,currentLine){for(currentLine++;lines.length>currentLine;){if(lines[currentLine].staff)return lines[currentLine];currentLine++}return null}this.closeLine();var i,s,v,anyDeleted=!1;for(i=0;i<this.lines.length;i++)if(void 0!==this.lines[i].staff){var hasAny=!1;for(s=0;s<this.lines[i].staff.length;s++)if(void 0===this.lines[i].staff[s])anyDeleted=!0,this.lines[i].staff[s]=null;else for(v=0;v<this.lines[i].staff[s].voices.length;v++)void 0===this.lines[i].staff[s].voices[v]?this.lines[i].staff[s].voices[v]=[]:this.containsNotes(this.lines[i].staff[s].voices[v])&&(hasAny=!0);hasAny||(this.lines[i]=null,anyDeleted=!0)}if(anyDeleted&&(this.lines=window.ABCJS.parse.compact(this.lines),window.ABCJS.parse.each(this.lines,function(line){line.staff&&(line.staff=window.ABCJS.parse.compact(line.staff))})),barsperstaff)for(i=0;i<this.lines.length;i++)if(void 0!==this.lines[i].staff)for(s=0;s<this.lines[i].staff.length;s++)for(v=0;v<this.lines[i].staff[s].voices.length;v++)for(var barNumThisLine=0,n=0;n<this.lines[i].staff[s].voices[v].length;n++)if(\"bar\"===this.lines[i].staff[s].voices[v][n].el_type&&(barNumThisLine++,barNumThisLine>=barsperstaff&&n<this.lines[i].staff[s].voices[v].length-1)){if(i===this.lines.length-1){var cp=JSON.parse(JSON.stringify(this.lines[i]));this.lines.push(window.ABCJS.parse.clone(cp));for(var ss=0;ss<this.lines[i+1].staff.length;ss++)for(var vv=0;vv<this.lines[i+1].staff[ss].voices.length;vv++)this.lines[i+1].staff[ss].voices[vv]=[]}var startElement=n+1,section=this.lines[i].staff[s].voices[v].slice(startElement);this.lines[i].staff[s].voices[v]=this.lines[i].staff[s].voices[v].slice(0,startElement),this.lines[i+1].staff[s].voices[v]=section.concat(this.lines[i+1].staff[s].voices[v])}if(barsperstaff){for(anyDeleted=!1,i=0;i<this.lines.length;i++)if(void 0!==this.lines[i].staff)for(s=0;s<this.lines[i].staff.length;s++){var keepThis=!1;for(v=0;v<this.lines[i].staff[s].voices.length;v++)this.containsNotesStrict(this.lines[i].staff[s].voices[v])&&(keepThis=!0);keepThis||(anyDeleted=!0,this.lines[i].staff[s]=null)}anyDeleted&&window.ABCJS.parse.each(this.lines,function(line){line.staff&&(line.staff=window.ABCJS.parse.compact(line.staff))})}for(i=0;i<this.lines.length;i++)if(this.lines[i].staff)for(s=0;s<this.lines[i].staff.length;s++)delete this.lines[i].staff[s].workingClef;for(this.lineNum=0;this.lineNum<this.lines.length;this.lineNum++){var staff=this.lines[this.lineNum].staff;if(staff)for(this.staffNum=0;this.staffNum<staff.length;this.staffNum++)for(staff[this.staffNum].clef&&fixClefPlacement(staff[this.staffNum].clef),this.voiceNum=0;this.voiceNum<staff[this.staffNum].voices.length;this.voiceNum++){var voice=staff[this.staffNum].voices[this.voiceNum];cleanUpSlursInLine(voice);for(var j=0;j<voice.length;j++)\"clef\"===voice[j].el_type&&fixClefPlacement(voice[j]);if(voice.length>0&&voice[voice.length-1].barNumber){var nextLine=getNextMusicLine(this.lines,this.lineNum);nextLine&&(nextLine.staff[0].barNumber=voice[voice.length-1].barNumber),delete voice[voice.length-1].barNumber}}}return this.formatting.pagewidth||(this.formatting.pagewidth=defWidth),this.formatting.pageheight||(this.formatting.pageheight=defLength),delete this.staffNum,delete this.voiceNum,delete this.lineNum,delete this.potentialStartBeam,delete this.potentialEndBeam,delete this.vskipPending,currSlur},this.reset(),this.getLastNote=function(){if(this.lines[this.lineNum]&&this.lines[this.lineNum].staff&&this.lines[this.lineNum].staff[this.staffNum]&&this.lines[this.lineNum].staff[this.staffNum].voices[this.voiceNum])for(var i=this.lines[this.lineNum].staff[this.staffNum].voices[this.voiceNum].length-1;i>=0;i--){var el=this.lines[this.lineNum].staff[this.staffNum].voices[this.voiceNum][i];if(\"note\"===el.el_type)return el}return null},this.addTieToLastNote=function(){var el=this.getLastNote();return!!(el&&el.pitches&&el.pitches.length>0)&&(el.pitches[0].startTie={},!0)},this.getDuration=function(el){return el.duration?el.duration:0},this.closeLine=function(){this.potentialStartBeam&&this.potentialEndBeam&&(this.potentialStartBeam.startBeam=!0,this.potentialEndBeam.endBeam=!0),delete this.potentialStartBeam,delete this.potentialEndBeam},this.appendElement=function(type,startChar,endChar,hashParams){var This=this,pushNote=function(hp){if(void 0!==hp.pitches){var mid=This.lines[This.lineNum].staff[This.staffNum].workingClef.verticalPos;window.ABCJS.parse.each(hp.pitches,function(p){p.verticalPos=p.pitch-mid})}if(void 0!==hp.gracenotes){var mid2=This.lines[This.lineNum].staff[This.staffNum].workingClef.verticalPos;window.ABCJS.parse.each(hp.gracenotes,function(p){p.verticalPos=p.pitch-mid2})}This.lines[This.lineNum].staff[This.staffNum].voices[This.voiceNum].push(hp)};hashParams.el_type=type,null!==startChar&&(hashParams.startChar=startChar),null!==endChar&&(hashParams.endChar=endChar);var endBeamHere=function(){This.potentialStartBeam.startBeam=!0,hashParams.endBeam=!0,delete This.potentialStartBeam,delete This.potentialEndBeam},endBeamLast=function(){void 0!==This.potentialStartBeam&&void 0!==This.potentialEndBeam&&(This.potentialStartBeam.startBeam=!0,This.potentialEndBeam.endBeam=!0),delete This.potentialStartBeam,delete This.potentialEndBeam};if(\"note\"===type){var dur=This.getDuration(hashParams);dur>=.25?endBeamLast():hashParams.force_end_beam_last&&void 0!==This.potentialStartBeam?endBeamLast():hashParams.end_beam&&void 0!==This.potentialStartBeam?void 0===hashParams.rest?endBeamHere():endBeamLast():void 0===hashParams.rest&&(void 0===This.potentialStartBeam?hashParams.end_beam||(This.potentialStartBeam=hashParams,delete This.potentialEndBeam):This.potentialEndBeam=hashParams)}else endBeamLast();delete hashParams.end_beam,delete hashParams.force_end_beam_last,pushNote(hashParams)},this.appendStartingElement=function(type,startChar,endChar,hashParams2){this.closeLine();var impliedNaturals;\"key\"===type&&(impliedNaturals=hashParams2.impliedNaturals,delete hashParams2.impliedNaturals);var hashParams=window.ABCJS.parse.clone(hashParams2);if(this.lines[this.lineNum].staff){\"clef\"===type&&(this.lines[this.lineNum].staff[this.staffNum].workingClef=hashParams),this.lines[this.lineNum].staff.length<=this.staffNum&&(this.lines[this.lineNum].staff[this.staffNum]={},this.lines[this.lineNum].staff[this.staffNum].clef=window.ABCJS.parse.clone(this.lines[this.lineNum].staff[0].clef),this.lines[this.lineNum].staff[this.staffNum].key=window.ABCJS.parse.clone(this.lines[this.lineNum].staff[0].key),this.lines[this.lineNum].staff[this.staffNum].meter=window.ABCJS.parse.clone(this.lines[this.lineNum].staff[0].meter),this.lines[this.lineNum].staff[this.staffNum].workingClef=window.ABCJS.parse.clone(this.lines[this.lineNum].staff[0].workingClef),this.lines[this.lineNum].staff[this.staffNum].voices=[[]]);for(var voice=this.lines[this.lineNum].staff[this.staffNum].voices[this.voiceNum],i=0;i<voice.length;i++){if(\"note\"===voice[i].el_type||\"bar\"===voice[i].el_type)return hashParams.el_type=type,hashParams.startChar=startChar,hashParams.endChar=endChar,impliedNaturals&&(hashParams.accidentals=impliedNaturals.concat(hashParams.accidentals)),void voice.push(hashParams);if(voice[i].el_type===type)return hashParams.el_type=type,hashParams.startChar=startChar,hashParams.endChar=endChar,impliedNaturals&&(hashParams.accidentals=impliedNaturals.concat(hashParams.accidentals)),void(voice[i]=hashParams)}this.lines[this.lineNum].staff[this.staffNum][type]=hashParams2}},this.getNumLines=function(){return this.lines.length},this.pushLine=function(hash){this.vskipPending&&(hash.vskip=this.vskipPending,delete this.vskipPending),this.lines.push(hash)},this.addSubtitle=function(str){this.pushLine({subtitle:str})},this.addSpacing=function(num){this.vskipPending=num},this.addNewPage=function(num){this.pushLine({newpage:num})},this.addSeparator=function(spaceAbove,spaceBelow,lineLength){this.pushLine({separator:{spaceAbove:spaceAbove,spaceBelow:spaceBelow,lineLength:lineLength}})},this.addText=function(str){this.pushLine({text:str})},this.addCentered=function(str){this.pushLine({text:[{text:str,center:!0}]})},this.containsNotes=function(voice){for(var i=0;i<voice.length;i++)if(\"note\"===voice[i].el_type||\"bar\"===voice[i].el_type)return!0;return!1},this.containsNotesStrict=function(voice){for(var i=0;i<voice.length;i++)if(\"note\"===voice[i].el_type&&void 0===voice[i].rest)return!0;return!1},this.startNewLine=function(params){var This=this;this.closeLine();var createVoice=function(params){if(This.lines[This.lineNum].staff[This.staffNum].voices[This.voiceNum]=[],This.isFirstLine(This.lineNum)?params.name&&(This.lines[This.lineNum].staff[This.staffNum].title||(This.lines[This.lineNum].staff[This.staffNum].title=[]),This.lines[This.lineNum].staff[This.staffNum].title[This.voiceNum]=params.name):params.subname&&(This.lines[This.lineNum].staff[This.staffNum].title||(This.lines[This.lineNum].staff[This.staffNum].title=[]),This.lines[This.lineNum].staff[This.staffNum].title[This.voiceNum]=params.subname),params.style&&This.appendElement(\"style\",null,null,{head:params.style}),params.stem)This.appendElement(\"stem\",null,null,{direction:params.stem});else if(This.voiceNum>0){if(void 0!==This.lines[This.lineNum].staff[This.staffNum].voices[0]){for(var found=!1,i=0;i<This.lines[This.lineNum].staff[This.staffNum].voices[0].length;i++)\"stem\"===This.lines[This.lineNum].staff[This.staffNum].voices[0].el_type&&(found=!0);if(!found){var stem={el_type:\"stem\",direction:\"up\"};This.lines[This.lineNum].staff[This.staffNum].voices[0].splice(0,0,stem)}}This.appendElement(\"stem\",null,null,{direction:\"down\"})}params.scale&&This.appendElement(\"scale\",null,null,{size:params.scale})},createStaff=function(params){This.lines[This.lineNum].staff[This.staffNum]={voices:[],clef:params.clef,key:params.key,workingClef:params.clef},params.vocalfont&&(This.lines[This.lineNum].staff[This.staffNum].vocalfont=params.vocalfont),params.bracket&&(This.lines[This.lineNum].staff[This.staffNum].bracket=params.bracket),params.brace&&(This.lines[This.lineNum].staff[This.staffNum].brace=params.brace),params.connectBarLines&&(This.lines[This.lineNum].staff[This.staffNum].connectBarLines=params.connectBarLines),params.barNumber&&(This.lines[This.lineNum].staff[This.staffNum].barNumber=params.barNumber),createVoice(params),params.part&&This.appendElement(\"part\",params.startChar,params.endChar,{title:params.part}),void 0!==params.meter&&(This.lines[This.lineNum].staff[This.staffNum].meter=params.meter)},createLine=function(params){This.lines[This.lineNum]={staff:[]},createStaff(params)};if(void 0===this.lines[this.lineNum])createLine(params);else if(void 0===this.lines[this.lineNum].staff)this.lineNum++,this.startNewLine(params);else if(void 0===this.lines[this.lineNum].staff[this.staffNum])createStaff(params);else if(void 0===this.lines[this.lineNum].staff[this.staffNum].voices[this.voiceNum])createVoice(params);else{if(!this.containsNotes(this.lines[this.lineNum].staff[this.staffNum].voices[this.voiceNum]))return;this.lineNum++,this.startNewLine(params)}},this.hasBeginMusic=function(){for(var i=0;i<this.lines.length;i++)if(this.lines[i].staff)return!0;return!1},this.isFirstLine=function(index){for(var i=index-1;i>=0;i--)if(void 0!==this.lines[i].staff)return!1;return!0},this.getMeter=function(){for(var i=0;i<this.lines.length;i++){var line=this.lines[i];if(line.staff)for(var j=0;j<line.staff.length;j++){var meter=line.staff[j].meter;if(meter)return meter}}return{type:\"common_time\"}},this.getCurrentVoice=function(){return void 0!==this.lines[this.lineNum]&&void 0!==this.lines[this.lineNum].staff[this.staffNum]&&void 0!==this.lines[this.lineNum].staff[this.staffNum].voices[this.voiceNum]?this.lines[this.lineNum].staff[this.staffNum].voices[this.voiceNum]:null},this.setCurrentVoice=function(staffNum,voiceNum){this.staffNum=staffNum,this.voiceNum=voiceNum;for(var i=0;i<this.lines.length;i++)if(this.lines[i].staff&&(void 0===this.lines[i].staff[staffNum]||void 0===this.lines[i].staff[staffNum].voices[voiceNum]||!this.containsNotes(this.lines[i].staff[staffNum].voices[voiceNum])))return void(this.lineNum=i);this.lineNum=i},this.addMetaText=function(key,value){void 0===this.metaText[key]?this.metaText[key]=value:this.metaText[key]+=\"\\n\"+value},this.addMetaTextArray=function(key,value){void 0===this.metaText[key]?this.metaText[key]=[value]:this.metaText[key].push(value)},this.addMetaTextObj=function(key,value){this.metaText[key]=value},this.setupEvents=function(startingDelay,timeDivider){for(var timingEvents=[],eventHash={},time=startingDelay,isTiedState=!1,line=0;line<this.engraver.staffgroups.length;line++){var group=this.engraver.staffgroups[line],voices=group.voices,firstStaff=group.staffs[0],middleC=firstStaff.absoluteY,top=middleC-firstStaff.top*ABCJS.write.spacing.STEP,lastStaff=group.staffs[group.staffs.length-1];middleC=lastStaff.absoluteY;for(var bottom=middleC-lastStaff.bottom*ABCJS.write.spacing.STEP,height=bottom-top,maxVoiceTime=0,v=0;v<voices.length;v++){for(var voiceTime=time,elements=voices[v].children,elem=0;elem<elements.length;elem++){var element=elements[elem];if(element.hint)break;if(element.duration>0){var isTiedToNext=element.startTie;isTiedState?isTiedToNext||(isTiedState=!1):(eventHash[\"event\"+voiceTime]?(eventHash[\"event\"+voiceTime].left=Math.min(eventHash[\"event\"+voiceTime].left,element.x),eventHash[\"event\"+voiceTime].elements.push(element.elemset)):eventHash[\"event\"+voiceTime]={type:\"event\",seconds:voiceTime,top:top,height:height,left:element.x,width:element.w,elements:[element.elemset]},isTiedToNext&&(isTiedState=!0)),voiceTime+=element.duration/timeDivider}}maxVoiceTime=Math.max(maxVoiceTime,voiceTime)}time=maxVoiceTime}return timingEvents=makeSortedArray(eventHash),addVerticalInfo(timingEvents),timingEvents},this.setTiming=function(bpm,measuresOfDelay){var meter=this.getMeter();this.barTimings=[];var measureLength,beatLength=this.getBeatLength(),beatsPerSecond=bpm/60;switch(meter.type){case\"common_time\":measureLength=1,this.meter={num:4,den:4};break;case\"cut_time\":measureLength=1,this.meter={num:2,den:2};break;default:measureLength=meter.value[0].num/meter.value[0].den,this.meter={num:meter.value[0].num,den:meter.value[0].den}}var startingDelay=measureLength/beatLength*measuresOfDelay/beatsPerSecond,timeDivider=beatLength*beatsPerSecond;this.noteTimings=this.setupEvents(startingDelay,timeDivider)}},window.ABCJS||(window.ABCJS={}),window.ABCJS.midi||(window.ABCJS.midi={}),function(){\"use strict\";function isFunction(functionToCheck){var getType={};return functionToCheck&&\"[object Function]\"===getType.toString.call(functionToCheck)}function preprocessLabel(label,title){return label.replace(/%T/g,title)}function hasClass(element,cls){return!!element&&(\" \"+element.className+\" \").indexOf(\" \"+cls+\" \")>-1}function addClass(element,cls){element&&(hasClass(element,cls)||(element.className=element.className+\" \"+cls))}function removeClass(element,cls){element&&(element.className=element.className.replace(cls,\"\").trim().replace(\"  \",\" \"))}function toggleClass(element,cls){element&&(hasClass(element,cls)?removeClass(element,cls):addClass(element,cls))}function closest(element,cls){if(!element)return null;for(;element!==document.body;){if(hasClass(element,cls))return element;element=element.parentNode}return null}function find(element,cls){if(!element)return null;var els=element.getElementsByClassName(cls);return 0===els.length?null:els[0]}function addLoadEvent(func){var oldOnLoad=window.onload;\"function\"!=typeof window.onload?window.onload=func:window.onload=function(){oldOnLoad&&oldOnLoad(),func()}}function afterSetup(timeWarp,data,onSuccess){MIDI.player.currentTime=0,MIDI.player.warp=timeWarp,MIDI.player.load({events:data}),onSuccess()}function setCurrentMidiTune(timeWarp,data,onSuccess){midiJsInitialized?afterSetup(timeWarp,data,onSuccess):MIDI.setup({debug:!0,soundfontUrl:window.ABCJS.midi.soundfontUrl}).then(function(){midiJsInitialized=!0,afterSetup(timeWarp,data,onSuccess)})}function startCurrentlySelectedTune(){MIDI.player.start(MIDI.player.currentTime)}function stopCurrentlyPlayingTune(){MIDI.player.stop()}function pauseCurrentlyPlayingTune(){MIDI.player.pause()}function setMidiCallback(midiJsListener){MIDI.player.setAnimation(midiJsListener)}function jumpToMidiPosition(play,offset,width){var ratio=offset/width,endTime=MIDI.player.duration;play&&pauseCurrentlyPlayingTune(),MIDI.player.currentTime=endTime*ratio,play&&startCurrentlySelectedTune()}function setTimeWarp(percent){MIDI.player.warp=percent>0?100/percent:1}function loadMidi(target,onSuccess){var dataEl=find(target,\"abcjs-data\"),data=JSON.parse(dataEl.innerHTML),timeWarp=1,tempoEl=find(target,\"abcjs-midi-tempo\");if(tempoEl){var percent=parseInt(tempoEl.value,10);percent>0&&(timeWarp=100/percent)}setCurrentMidiTune(timeWarp,data,onSuccess)}function deselectMidiControl(){var otherMidi=find(document,\"abcjs-midi-current\");if(otherMidi){stopCurrentlyPlayingTune(),removeClass(otherMidi,\"abcjs-midi-current\");var otherMidiStart=find(otherMidi,\"abcjs-midi-start\");removeClass(otherMidiStart,\"abcjs-pushed\")}}function findElements(visualItems,currentTime,epsilon){for(var currentIndex,currentElement,minIndex=0,maxIndex=visualItems.length-1;minIndex<=maxIndex;)if(currentIndex=(minIndex+maxIndex)/2|0,currentElement=visualItems[currentIndex],currentElement.seconds-epsilon<currentTime)minIndex=currentIndex+1;else{if(!(currentElement.seconds-epsilon>currentTime))return currentIndex;maxIndex=currentIndex-1}for(;visualItems[currentIndex].seconds-epsilon>=currentTime&&currentIndex>0;)currentIndex--;return 0===currentIndex&&visualItems[currentIndex].seconds-epsilon>=currentTime?-1:currentIndex}function midiJsListener(position){var midiControl;if(position.duration>0&&lastNow!==position.progress&&(lastNow=position.progress,midiControl=find(document,\"abcjs-midi-current\"))){var startButton=find(midiControl,\"abcjs-midi-start\");if(hasClass(startButton,\"abcjs-pushed\")){var progressBackground=find(midiControl,\"abcjs-midi-progress-background\"),totalWidth=progressBackground.offsetWidth,progressIndicator=find(midiControl,\"abcjs-midi-progress-indicator\"),scaled=totalWidth*lastNow;progressIndicator.style.left=scaled+\"px\";var clock=find(midiControl,\"abcjs-midi-clock\");if(clock){var seconds=Math.floor(position.currentTime),minutes=Math.floor(seconds/60);seconds%=60,seconds<10&&(seconds=\"0\"+seconds),minutes<10&&(minutes=\" \"+minutes),clock.innerHTML=minutes+\":\"+seconds}var beatsPerSecond=parseInt(midiControl.abcjsQpm,10)/60,currentTime=position.currentTime;if(midiControl.abcjsListener){var thisBeat=Math.floor(currentTime/beatsPerSecond);position.newBeat=thisBeat!==midiControl.abcjsLastBeat,midiControl.abcjsLastBeat=thisBeat,midiControl.abcjsListener(midiControl,position)}if(midiControl.abcjsAnimate){var epsilon=beatsPerSecond/64,index=findElements(midiControl.abcjsTune.noteTimings,currentTime,epsilon);if(index!==midiControl.abcjsLastIndex){var last=midiControl.abcjsLastIndex>=0?midiControl.abcjsTune.noteTimings[midiControl.abcjsLastIndex]:null;midiControl.abcjsAnimate(last,midiControl.abcjsTune.noteTimings[index]),midiControl.abcjsLastIndex=index}}}}if(1===position.progress){midiControl=find(document,\"abcjs-midi-current\");var loopControl=find(midiControl,\"abcjs-midi-loop\"),finishedResetting=function(){loopControl&&hasClass(loopControl,\"abcjs-pushed\")&&onStart(find(midiControl,\"abcjs-midi-start\"))};setTimeout(function(){doReset(midiControl,finishedResetting),midiControl.abcjsAnimate&&midiControl.abcjsAnimate(midiControl.abcjsTune.noteTimings[midiControl.abcjsLastIndex],null)},1)}}function onStart(target){var parent=closest(target,\"abcjs-inline-midi\");if(hasClass(target,\"abcjs-pushed\"))pauseCurrentlyPlayingTune(),removeClass(target,\"abcjs-pushed\");else{if(hasClass(parent,\"abcjs-midi-current\"))startCurrentlySelectedTune();else{deselectMidiControl();var onSuccess=function(){startCurrentlySelectedTune(),addClass(parent,\"abcjs-midi-current\")};loadMidi(parent,onSuccess)}addClass(target,\"abcjs-pushed\")}parent.abcjsLastBeat=-1,parent.abcjsLastIndex=-1,setMidiCallback(midiJsListener)}function onSelection(target){toggleClass(target,\"abcjs-pushed\")}function onLoop(target){toggleClass(target,\"abcjs-pushed\")}function doReset(target,callback){function onSuccess(){addClass(parent,\"abcjs-midi-current\");var progressIndicator=find(parent,\"abcjs-midi-progress-indicator\");progressIndicator.style.left=\"0px\";var clock=find(parent,\"abcjs-midi-clock\");clock.innerHTML=\" 0:00\",callback&&callback()}var parent=closest(target,\"abcjs-inline-midi\");deselectMidiControl(),parent&&loadMidi(parent,onSuccess)}function onReset(target){function keepPlaying(){play&&(startCurrentlySelectedTune(),addClass(playEl,\"abcjs-pushed\"))}var parent=closest(target,\"abcjs-inline-midi\"),playEl=find(parent,\"abcjs-midi-start\"),play=hasClass(playEl,\"abcjs-pushed\");hasClass(parent,\"abcjs-midi-current\")&&doReset(target,keepPlaying)}function relMouseX(target,event){var totalOffsetX=0;do totalOffsetX+=target.offsetLeft-target.scrollLeft,target=target.offsetParent;while(target);return event.pageX-totalOffsetX}function onProgress(target,event){var parent=closest(target,\"abcjs-inline-midi\");if(hasClass(parent,\"abcjs-midi-current\")){var play=find(parent,\"abcjs-midi-start\");play=hasClass(play,\"abcjs-pushed\");var width=target.offsetWidth,offset=relMouseX(target,event);jumpToMidiPosition(play,offset,width)}}function onTempo(el){for(var percent=parseInt(el.value,10),startTempo=parseInt(el.getAttribute(\"data-start-tempo\"),10);el&&!hasClass(el,\"abcjs-midi-current-tempo\");)el=el.nextSibling;el.innerHTML=Math.floor(percent*startTempo/100),setTimeWarp(percent)}function addDelegates(){if(document.body.addEventListener(\"click\",function(event){event=event||window.event;for(var target=event.target||event.srcElement;target&&target!==document.body;){if(hasClass(target,\"abcjs-midi-start\"))return void onStart(target,event);if(hasClass(target,\"abcjs-midi-selection\"))return void onSelection(target,event);if(hasClass(target,\"abcjs-midi-loop\"))return void onLoop(target,event);if(hasClass(target,\"abcjs-midi-reset\"))return void onReset(target,event);if(hasClass(target,\"abcjs-midi-progress-background\"))return void onProgress(target,event);target=target.parentNode}}),document.body.addEventListener(\"change\",function(event){event=event||window.event;for(var target=event.target||event.srcElement;target!==document.body;)hasClass(target,\"abcjs-midi-tempo\")&&onTempo(target,event),target=target.parentNode}),void 0===window.MIDI){window.ABCJS.midi.midiInlineInitialized=\"not loaded\";for(var els=document.getElementsByClassName(\"abcjs-inline-midi\"),i=0;i<els.length;i++)els[i].innerHTML=\"MIDI NOT PRESENT\"}}window.ABCJS.midi.generateMidiDownloadLink=function(tune,midiParams,midi,index){var html='<div class=\"download-midi midi-'+index+'\">';midiParams.preTextDownload&&(html+=midiParams.preTextDownload);var label,title=tune.metaText&&tune.metaText.title?tune.metaText.title:\"Untitled\";return label=midiParams.downloadLabel&&isFunction(midiParams.downloadLabel)?midiParams.downloadLabel(tune,index):midiParams.downloadLabel?midiParams.downloadLabel.replace(/%T/,title):'Download MIDI for \"'+title+'\"',title=title.toLowerCase().replace(/'/g,\"\").replace(/\\W/g,\"_\").replace(/__/g,\"_\"),html+='<a download=\"'+title+'.midi\" href=\"'+midi+'\">'+label+\"</a>\",midiParams.postTextDownload&&(html+=midiParams.postTextDownload),html+\"</div>\"},window.ABCJS.midi.generateMidiControls=function(tune,midiParams,midi,index){if(\"failed\"===window.ABCJS.midiInlineInitialized)return'<div class=\"abcjs-inline-midi abcjs-midi-'+index+'\">ERROR</div>';if(\"not loaded\"===window.ABCJS.midiInlineInitialized)return'<div class=\"abcjs-inline-midi abcjs-midi-'+index+'\">MIDI NOT PRESENT</div>';var title=tune.metaText&&tune.metaText.title?tune.metaText.title:\"Untitled\",options=midiParams.inlineControls||{};void 0===options.standard&&(options.standard=!0),void 0===options.tooltipSelection&&(options.tooltipSelection=\"Click to toggle play selection/play all.\"),void 0===options.tooltipLoop&&(options.tooltipLoop=\"Click to toggle play once/repeat.\"),void 0===options.tooltipReset&&(options.tooltipReset=\"Click to go to beginning.\"),void 0===options.tooltipPlay&&(options.tooltipPlay=\"Click to play/pause.\"),void 0===options.tooltipProgress&&(options.tooltipProgress=\"Click to change the playback position.\"),\nvoid 0===options.tooltipTempo&&(options.tooltipTempo=\"Change the playback speed.\");var style=\"\";options.hide&&(style='style=\"display:none;\"');var html='<div class=\"abcjs-inline-midi abcjs-midi-'+index+'\" '+style+\">\";if(html+='<span class=\"abcjs-data\" style=\"display:none;\">'+JSON.stringify(midi)+\"</span>\",midiParams.preTextInline&&(html+='<span class=\"abcjs-midi-pre\">'+preprocessLabel(midiParams.preTextInline,title)+\"</span>\"),options.selectionToggle&&(html+='<button class=\"abcjs-midi-selection abcjs-btn\" title=\"'+options.tooltipSelection+'\"></button>'),options.loopToggle&&(html+='<button class=\"abcjs-midi-loop abcjs-btn\" title=\"'+options.tooltipLoop+'\"></button>'),options.standard&&(html+='<button class=\"abcjs-midi-reset abcjs-btn\" title=\"'+options.tooltipReset+'\"></button><button class=\"abcjs-midi-start abcjs-btn\" title=\"'+options.tooltipPlay+'\"></button><button class=\"abcjs-midi-progress-background\" title=\"'+options.tooltipProgress+'\"><span class=\"abcjs-midi-progress-indicator\"></span></button><span class=\"abcjs-midi-clock\"> 0:00</span>'),options.tempo){var startTempo=tune&&tune.metaText&&tune.metaText.tempo?tune.metaText.tempo.bpm:180;html+='<span class=\"abcjs-tempo-wrapper\"><input class=\"abcjs-midi-tempo\" value=\"100\" type=\"number\" min=\"1\" max=\"300\" data-start-tempo=\"'+startTempo+'\" title=\"'+options.tooltipTempo+'\" />% (<span class=\"abcjs-midi-current-tempo\">'+startTempo+\"</span> BPM)</span>\"}return midiParams.postTextInline&&(html+='<span class=\"abcjs-midi-post\">'+preprocessLabel(midiParams.postTextInline,title)+\"</span>\"),html+\"</div>\"},window.ABCJS.midi.soundfontUrl=\"/soundfont/\";var lastNow,midiJsInitialized=!1;window.ABCJS.midi.startPlaying=function(target){onStart(target)},window.ABCJS.midi.stopPlaying=function(){stopCurrentlyPlayingTune()},addLoadEvent(addDelegates)}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.midi||(window.ABCJS.midi={}),function(){\"use strict\";function convertPitch(pitch){return 60+pitch}var baseDuration=1920;window.ABCJS.midi.create=function(abcTune,options){void 0===options&&(options={});var sequence=window.ABCJS.midi.sequence(abcTune,options),commands=window.ABCJS.midi.flatten(sequence,options),midi=window.ABCJS.midi.rendererFactory(),midiJs=new window.ABCJS.midi.Preparer,title=abcTune.metaText?abcTune.metaText.title:void 0;title&&title.length>128&&(title=title.substring(0,124)+\"...\"),midi.setGlobalInfo(commands.tempo,title),midiJs.setGlobalInfo(commands.tempo,title),void 0!==commands.instrument&&(midi.setInstrument(commands.instrument),midiJs.setInstrument(commands.instrument)),void 0!==commands.channel&&(midi.setChannel(commands.channel),midiJs.setChannel(commands.channel));for(var i=0;i<commands.tracks.length;i++){midi.startTrack(),midiJs.startTrack();for(var j=0;j<commands.tracks[i].length;j++){var event=commands.tracks[i][j];switch(event.cmd){case\"instrument\":midi.setInstrument(event.instrument),midiJs.setInstrument(event.instrument);break;case\"channel\":midi.setChannel(event.channel),midiJs.setChannel(event.channel);break;case\"start\":midi.startNote(convertPitch(event.pitch),event.volume),midiJs.startNote(convertPitch(event.pitch),event.volume);break;case\"stop\":midi.endNote(convertPitch(event.pitch),0),midiJs.endNote(convertPitch(event.pitch));break;case\"move\":midi.addRest(event.duration*baseDuration),midiJs.addRest(event.duration*baseDuration);break;default:console.log(\"MIDI create Unknown: \"+event.cmd)}}midi.endTrack(),midiJs.endTrack()}var midiFile=midi.getData(),midiInline=midiJs.getData();return void 0===options.generateInline&&(options.generateInline=!0),options.generateInline&&options.generateDownload?{download:midiFile,inline:midiInline}:options.generateInline?midiInline:midiFile}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.midi||(window.ABCJS.midi={}),function(){\"use strict\";function findChord(elem){if(chordTrackFinished||!elem.chord||0===elem.chord.length)return null;for(var i=0;i<elem.chord.length;i++){var ch=elem.chord[i];if(\"default\"===ch.position)return ch.name;if(breakSynonyms.indexOf(ch.name.toLowerCase())>=0)return\"break\"}return null}function timeFromStart(){for(var distance=0,ct=0;ct<currentTrack.length;ct++)\"move\"===currentTrack[ct].cmd&&(distance+=currentTrack[ct].duration);return distance}function writeNote(elem,voiceOff){var velocity=voiceOff?0:64,chord=findChord(elem);if(chord){var c=interpretChord(chord);if(c){if(0===chordTrack.length){chordTrack.push({cmd:\"instrument\",instrument:0});var distance=timeFromStart();distance>0&&chordTrack.push({cmd:\"move\",duration:distance*tempoChangeFactor})}lastChord=c,currentChords.push({chord:lastChord,beat:barBeat})}}elem.startTriplet&&(multiplier=2===elem.startTriplet?1.5:(elem.startTriplet-1)/elem.startTriplet);var duration=elem.duration*multiplier;barBeat+=duration;var graces;if(elem.gracenotes){var stealFromCurrent=bagpipes||lastNoteDurationPosition<0||0===currentTrack.length,stealFromDuration=stealFromCurrent?duration:currentTrack[lastNoteDurationPosition].duration;graces=processGraceNotes(elem.gracenotes,stealFromDuration),bagpipes||(duration=writeGraceNotes(graces,stealFromCurrent,duration,null,velocity))}if(elem.pitches){graces&&bagpipes&&(duration=writeGraceNotes(graces,!0,duration,null,velocity));for(var pitches=[],i=0;i<elem.pitches.length;i++){var note=elem.pitches[i],actualPitch=adjustPitch(note);pitches.push({pitch:actualPitch,startTie:note.startTie}),pitchesTied[\"\"+actualPitch]||currentTrack.push({cmd:\"start\",pitch:actualPitch,volume:velocity}),note.startTie?pitchesTied[\"\"+actualPitch]=!0:note.endTie&&(pitchesTied[\"\"+actualPitch]=!1)}currentTrack.push({cmd:\"move\",duration:(duration-normalBreakBetweenNotes)*tempoChangeFactor}),lastNoteDurationPosition=currentTrack.length-1;for(var ii=0;ii<pitches.length;ii++)pitchesTied[\"\"+pitches[ii].pitch]||currentTrack.push({cmd:\"stop\",pitch:pitches[ii].pitch});currentTrack.push({cmd:\"move\",duration:normalBreakBetweenNotes*tempoChangeFactor})}else elem.rest&&currentTrack.push({cmd:\"move\",duration:duration*tempoChangeFactor});elem.endTriplet&&(multiplier=1)}function adjustPitch(note){var pitch=note.pitch;if(note.accidental)switch(note.accidental){case\"sharp\":barAccidentals[pitch]=1;break;case\"flat\":barAccidentals[pitch]=-1;break;case\"natural\":barAccidentals[pitch]=0;break;case\"dblsharp\":barAccidentals[pitch]=2;break;case\"dblflat\":barAccidentals[pitch]=-2}var actualPitch=12*extractOctave(pitch)+scale[extractNote(pitch)];return actualPitch+=void 0!==barAccidentals[pitch]?barAccidentals[pitch]:accidentals[extractNote(pitch)],actualPitch+=transpose}function setKeySignature(elem){var accidentals=[0,0,0,0,0,0,0];if(!elem.accidentals)return accidentals;for(var i=0;i<elem.accidentals.length;i++){var acc=elem.accidentals[i],d=\"sharp\"===acc.acc?1:\"natural\"===acc.acc?0:-1,lowercase=acc.note.toLowerCase(),note=extractNote(lowercase.charCodeAt(0)-\"c\".charCodeAt(0));accidentals[note]+=d}return accidentals}function processGraceNotes(graces,companionDuration){for(var grace,graceDuration=0,ret=[],g=0;g<graces.length;g++)grace=graces[g],graceDuration+=grace.duration;graceDuration/=graceDivider;var multiplier=2*graceDuration>companionDuration?companionDuration/(2*graceDuration):1;for(g=0;g<graces.length;g++)grace=graces[g],ret.push({pitch:grace.pitch,duration:grace.duration/graceDivider*multiplier});return ret}function writeGraceNotes(graces,stealFromCurrent,duration,skipNote,velocity){for(var g=0;g<graces.length;g++){var gp=adjustPitch(graces[g]);gp!==skipNote&&currentTrack.push({cmd:\"start\",pitch:gp,volume:velocity}),currentTrack.push({cmd:\"move\",duration:graces[g].duration*tempoChangeFactor}),gp!==skipNote&&currentTrack.push({cmd:\"stop\",pitch:gp}),stealFromCurrent||(currentTrack[lastNoteDurationPosition].duration-=graces[g].duration),duration-=graces[g].duration}return duration}function extractOctave(pitch){return Math.floor(pitch/7)}function extractNote(pitch){return pitch%=7,pitch<0&&(pitch+=7),pitch}function interpretChord(name){if(0!==name.length){if(\"break\"===name)return{chick:[]};var root=name.substring(0,1);if(\"(\"===root){if(name=name.substring(1,name.length-2),0===name.length)return;root=name.substring(0,1)}var bass=basses[root];if(bass){bass+=transpose;var chick,bass2=bass-5;1===name.length&&(chick=chordNotes(bass,\"\"));var remaining=name.substring(1),acc=remaining.substring(0,1);\"b\"===acc||\"♭\"===acc?(bass--,bass2--,remaining=remaining.substring(1)):\"#\"!==acc&&\"♯\"!==acc||(bass++,bass2++,remaining=remaining.substring(1));var arr=remaining.split(\"/\");if(chick=chordNotes(bass,arr[0]),2===arr.length){var explicitBass=basses[arr[1]];explicitBass&&(bass=basses[arr[1]]+transpose,bass2=bass)}return{boom:bass,boom2:bass2,chick:chick}}}}function chordNotes(bass,modifier){var intervals=chordIntervals[modifier];intervals||(intervals=chordIntervals.M),bass+=12;for(var notes=[],i=0;i<intervals.length;i++)notes.push(bass+intervals[i]);return notes}function writeBoom(boom,beatLength){void 0!==boom&&chordTrack.push({cmd:\"start\",pitch:boom,volume:64}),chordTrack.push({cmd:\"move\",duration:beatLength/2*tempoChangeFactor}),void 0!==boom&&chordTrack.push({cmd:\"stop\",pitch:boom}),chordTrack.push({cmd:\"move\",duration:beatLength/2*tempoChangeFactor})}function writeChick(chick,beatLength){for(var c=0;c<chick.length;c++)chordTrack.push({cmd:\"start\",pitch:chick[c],volume:48});for(chordTrack.push({cmd:\"move\",duration:beatLength/2*tempoChangeFactor}),c=0;c<chick.length;c++)chordTrack.push({cmd:\"stop\",pitch:chick[c]});chordTrack.push({cmd:\"move\",duration:beatLength/2*tempoChangeFactor})}function resolveChords(){var num=meter.num,den=meter.den,beatLength=1/den,pattern=rhythmPatterns[num+\"/\"+den],thisMeasureLength=parseInt(num,10)/parseInt(den,10),portionOfAMeasure=Math.abs(thisMeasureLength-barBeat);if(!pattern||portionOfAMeasure>.0078125){pattern=[];for(var beatsPresent=barBeat/beatLength,p=0;p<beatsPresent;p++)pattern.push(\"chick\")}if(0===currentChords.length&&currentChords.push({beat:0,chord:lastChord}),0!==currentChords[0].beat&&lastChord&&currentChords.unshift({beat:0,chord:lastChord}),1!==currentChords.length){for(var beats={},i=0;i<currentChords.length;i++){var cc=currentChords[i],beat=Math.floor(cc.beat/beatLength);beats[\"\"+beat]=cc}for(var m2=0;m2<pattern.length;m2++){var thisChord;switch(beats[\"\"+m2]&&(thisChord=beats[\"\"+m2]),pattern[m2]){case\"boom\":beats[\"\"+(m2+1)]?writeChick(thisChord.chord.chick,beatLength):writeBoom(thisChord.chord.boom,beatLength);break;case\"boom2\":beats[\"\"+(m2+1)]?writeChick(thisChord.chord.chick,beatLength):writeBoom(thisChord.chord.boom2,beatLength);break;case\"chick\":writeChick(thisChord.chord.chick,beatLength);break;case\"\":beats[\"\"+m2]?writeChick(thisChord.chord.chick,beatLength):chordTrack.push({cmd:\"move\",duration:beatLength*tempoChangeFactor})}}}else for(var m=0;m<pattern.length;m++)switch(pattern[m]){case\"boom\":writeBoom(currentChords[0].chord.boom,beatLength);break;case\"boom2\":writeBoom(currentChords[0].chord.boom2,beatLength);break;case\"chick\":writeChick(currentChords[0].chord.chick,beatLength);break;case\"\":chordTrack.push({cmd:\"move\",duration:beatLength*tempoChangeFactor})}}function normalizeDrumDefinition(params){if(0===params.pattern.length||params.on===!1)return{on:!1};for(var str=params.pattern[0],events=[],event=\"\",totalPlay=0,i=0;i<str.length;i++)if(\"d\"===str[i]&&totalPlay++,\"d\"===str[i]||\"z\"===str[i])0!==event.length?(events.push(event),event=str[i]):event+=str[i];else{if(0===event.length)return{on:!1};event+=str[i]}if(0!==event.length&&events.push(event),params.pattern.length!==2*totalPlay+1)return{on:!1};for(var ret={on:!0,bars:params.bars,pattern:[]},beatLength=1/meter.den,playCount=0,j=0;j<events.length;j++){event=events[j];for(var len=1,div=!1,num=0,k=1;k<event.length;k++)switch(event[k]){case\"/\":0!==num&&(len*=num),num=0,div=!0;break;case\"1\":case\"2\":case\"3\":case\"4\":case\"5\":case\"6\":case\"7\":case\"8\":case\"9\":num=10*num+event[k];break;default:return{on:!1}}div?(0===num&&(num=2),len/=num):num&&(len*=num),\"d\"===event[0]?(ret.pattern.push({len:len*beatLength,pitch:params.pattern[1+playCount],velocity:params.pattern[1+playCount+totalPlay]}),playCount++):ret.pattern.push({len:len*beatLength,pitch:null})}for(var totalTime=0,measuresPerBeat=meter.num/meter.den,ii=0;ii<ret.pattern.length;ii++)totalTime+=ret.pattern[ii].len;var numBars=params.bars?params.bars:1,factor=totalTime/numBars/measuresPerBeat;for(ii=0;ii<ret.pattern.length;ii++)ret.pattern[ii].len=ret.pattern[ii].len/factor;return ret}function drumBeat(pitch,soundLength,volume){drumTrack.push({cmd:\"start\",pitch:pitch-60,volume:volume}),drumTrack.push({cmd:\"move\",duration:soundLength}),drumTrack.push({cmd:\"stop\",pitch:pitch-60})}function writeDrum(){if(0!==drumTrack.length||drumDefinition.on){var measureLen=meter.num/meter.den;if(0===drumTrack.length){drumTrack.push({cmd:\"channel\",channel:10}),drumTrack.push({cmd:\"instrument\",instrument:10});var distance=timeFromStart();if(distance>0&&distance<measureLen-.01)return void drumTrack.push({cmd:\"move\",duration:distance*tempoChangeFactor})}if(!drumDefinition.on)return void drumTrack.push({cmd:\"move\",duration:measureLen*tempoChangeFactor});for(var i=0;i<drumDefinition.pattern.length;i++){var len=drumDefinition.pattern[i].len*tempoChangeFactor;drumDefinition.pattern[i].pitch?drumBeat(drumDefinition.pattern[i].pitch,len,drumDefinition.pattern[i].velocity):drumTrack.push({cmd:\"move\",duration:len})}}}var barAccidentals,accidentals,transpose,bagpipes,multiplier,tracks,startingTempo,startingMeter,instrument,channel,currentTrack,pitchesTied,lastNoteDurationPosition,chordTrack,chordTrackFinished,currentChords,lastChord,barBeat,drumTrack,drumTrackFinished,tempoChangeFactor=1,meter={num:4,den:4},drumDefinition={},normalBreakBetweenNotes=1/128;window.ABCJS.midi.flatten=function(voices,options){options||(options={}),barAccidentals=[],accidentals=[0,0,0,0,0,0,0],bagpipes=!1,multiplier=1,tracks=[],startingTempo=void 0,startingMeter=void 0,tempoChangeFactor=1,instrument=void 0,channel=void 0,currentTrack=void 0,pitchesTied={},meter={num:4,den:4},chordTrack=[],chordTrackFinished=!1,currentChords=[],lastChord=void 0,barBeat=0,drumTrack=[],drumTrackFinished=!1,drumDefinition={};for(var i=0;i<voices.length;i++){transpose=0,lastNoteDurationPosition=-1;var voice=voices[i];currentTrack=[],pitchesTied={};for(var j=0;j<voice.length;j++){var element=voice[j];switch(element.el_type){case\"note\":writeNote(element,options.voicesOff);break;case\"key\":accidentals=setKeySignature(element);break;case\"meter\":startingMeter||(startingMeter=element),meter=element;break;case\"tempo\":startingTempo?tempoChangeFactor=element.qpm?startingTempo/element.qpm:1:startingTempo=element.qpm;break;case\"transpose\":transpose=element.transpose;break;case\"bar\":chordTrack.length>0&&(resolveChords(),currentChords=[]),barBeat=0,barAccidentals=[],0===i&&writeDrum();break;case\"bagpipes\":bagpipes=!0;break;case\"instrument\":instrument=element.program;break;case\"channel\":channel=element.channel;break;case\"drum\":drumDefinition=normalizeDrumDefinition(element.params);break;default:console.log(\"MIDI creation. Unknown el_type: \"+element.el_type+\"\\n\")}}tracks.push(currentTrack),chordTrack.length>0&&(chordTrackFinished=!0),drumTrack.length>0&&(drumTrackFinished=!0)}chordTrack.length>0&&tracks.push(chordTrack),drumTrack.length>0&&tracks.push(drumTrack);var num=parseInt(startingMeter.num,10),den=parseInt(startingMeter.den,10);return 2===den?startingTempo*=2:8===den?parseInt(num,10)%3===0?startingTempo*=1.5:startingTempo/=2:16===den&&(num%3===0?startingTempo*=.75:startingTempo/=4),{tempo:startingTempo,instrument:instrument,channel:channel,tracks:tracks}};var breakSynonyms=[\"break\",\"(break)\",\"no chord\",\"n.c.\",\"tacet\"],scale=[0,2,4,5,7,9,11],graceDivider=8,basses={A:-27,B:-25,C:-24,D:-22,E:-20,F:-19,G:-17},chordIntervals={M:[0,4,7],6:[0,4,7,9],7:[0,4,7,10],\"+7\":[0,4,8,10],aug7:[0,4,8,10],maj7:[0,4,7,11],\"∆7\":[0,4,7,11],9:[0,4,7,10,14],11:[0,4,7,10,14,16],13:[0,4,7,10,14,18],\"+\":[0,4,8],\"7#5\":[0,4,8,10],\"7+5\":[0,4,8,10],\"7b9\":[0,4,7,10,13],\"7b5\":[0,4,6,10],\"9#5\":[0,4,8,10,14],\"9+5\":[0,4,8,10,14],m:[0,3,7],\"-\":[0,3,7],m6:[0,3,7,9],\"-6\":[0,3,7,9],m7:[0,3,7,10],\"-7\":[0,3,7,10],dim:[0,3,6],dim7:[0,3,6,9],\"°7\":[0,3,6,9],\"ø7\":[0,3,6,9],\"7sus4\":[0,5,7,10],m7sus4:[0,5,7,10],sus4:[0,5,7]},rhythmPatterns={\"2/2\":[\"boom\",\"chick\"],\"2/4\":[\"boom\",\"chick\"],\"3/4\":[\"boom\",\"chick\",\"chick\"],\"4/4\":[\"boom\",\"chick\",\"boom2\",\"chick\"],\"6/8\":[\"boom\",\"\",\"chick\",\"boom2\",\"\",\"chick\"]}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.midi||(window.ABCJS.midi={}),function(){\"use strict\";function addAbsoluteTime(tracks){for(var i=0;i<tracks.length;i++)for(var absTime=0,j=0;j<tracks[i].length;j++)absTime+=tracks[i][j][1],tracks[i][j].absTime=absTime}function combineTracks(tracks){for(var output=[],i=0;i<tracks.length;i++)for(var j=0;j<tracks[i].length;j++)output.push(tracks[i][j]);return output}function sortTracks(output){return output.sort(function(a,b){return a.absTime>b.absTime?1:-1})}function adjustTime(output){for(var lastTime=0,i=0;i<output.length;i++){var thisTime=output[i].absTime;output[i][1]=thisTime-lastTime,lastTime=thisTime}}function weaveTracks(tracks){addAbsoluteTime(tracks);var output=combineTracks(tracks);return output=sortTracks(output),adjustTime(output),output}window.ABCJS.midi.Preparer=function(){this.tempo=0,this.timeFactor=0,this.output=[],this.currentChannel=0,this.currentInstrument=0,this.track=0,this.nextDuration=0,this.tracks=[[]]};var Preparer=window.ABCJS.midi.Preparer;Preparer.prototype.setInstrument=function(instrument){var ev=[{ticksToEvent:0,track:this.track,event:{channel:this.currentChannel,deltaTime:0,programNumber:this.currentInstrument,subtype:\"programChange\",type:\"channel\"}},this.nextDuration*this.timeFactor];this.tracks[this.track].push(ev)},Preparer.prototype.setChannel=function(channel){},Preparer.prototype.startTrack=function(){this.track++,this.tracks[this.track]=[],this.nextDuration=0},Preparer.prototype.setGlobalInfo=function(tempo,title){this.tempo=tempo;var mspb=Math.round(1/tempo*6e7);this.timeFactor=mspb/48e4;var ev=[{ticksToEvent:0,track:this.track,event:{deltaTime:0,microsecondsPerBeat:mspb,subtype:\"setTempo\",type:\"meta\"}},this.nextDuration*this.timeFactor];ev=[{ticksToEvent:0,track:this.track,event:{deltaTime:0,subtype:\"trackName\",text:title,type:\"meta\"}},this.nextDuration*this.timeFactor],ev=[{ticksToEvent:0,track:this.track,event:{deltaTime:0,subtype:\"endOfTrack\",type:\"meta\"}},this.nextDuration*this.timeFactor]},Preparer.prototype.startNote=function(pitch,volume){var deltaTime=5*Math.floor(this.nextDuration/5),ev=[{ticksToEvent:deltaTime,track:this.track,event:{deltaTime:deltaTime,channel:this.currentChannel,type:\"channel\",noteNumber:pitch,velocity:volume,subtype:\"noteOn\"}},this.nextDuration*this.timeFactor];this.tracks[this.track].push(ev),this.nextDuration=0},Preparer.prototype.endNote=function(pitch){var deltaTime=5*Math.floor(this.nextDuration/5),ev=[{ticksToEvent:deltaTime,track:this.track,event:{deltaTime:deltaTime,channel:this.currentChannel,type:\"channel\",noteNumber:pitch,velocity:0,subtype:\"noteOff\"}},this.nextDuration*this.timeFactor];this.tracks[this.track].push(ev),this.nextDuration=0},Preparer.prototype.addRest=function(duration){this.nextDuration+=duration},Preparer.prototype.endTrack=function(){[{ticksToEvent:0,track:this.track,event:{deltaTime:0,type:\"meta\",subtype:\"endOfTrack\"}},0]},Preparer.prototype.getData=function(){return weaveTracks(this.tracks)}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.midi||(window.ABCJS.midi={}),function(){\"use strict\";function setAttributes(elm,attrs){for(var attr in attrs)attrs.hasOwnProperty(attr)&&elm.setAttribute(attr,attrs[attr]);return elm}function Midi(){this.trackstrings=\"\",this.trackcount=0,this.noteOnAndChannel=\"%90\"}function encodeHex(s){for(var ret=\"\",i=0;i<s.length;i+=2)ret+=\"%\",ret+=s.substr(i,2);return ret}function toHex(n,padding){for(var s=n.toString(16);s.length<padding;)s=\"0\"+s;return encodeHex(s)}function toDurationHex(n){for(var res=0,a=[];0!==n;)a.push(127&n),n>>=7;for(var i=a.length-1;i>=0;i--){res<<=8;var bits=a[i];0!==i&&(bits|=128),res|=bits}var padding=res.toString(16).length;return padding+=padding%2,toHex(res,padding)}Midi.prototype.setTempo=function(qpm){0===this.trackcount&&(this.startTrack(),this.track+=\"%00%FF%51%03\"+toHex(Math.round(6e7/qpm),6),this.endTrack())},Midi.prototype.setGlobalInfo=function(qpm,name){if(0===this.trackcount){if(this.startTrack(),this.track+=\"%00%FF%51%03\"+toHex(Math.round(6e7/qpm),6),name){this.track+=\"%00%FF%03\"+toHex(name.length,2);for(var i=0;i<name.length;i++)this.track+=toHex(name.charCodeAt(i),2)}this.endTrack()}},Midi.prototype.startTrack=function(){this.track=\"\",this.silencelength=0,this.trackcount++,this.first=!0,this.instrument&&this.setInstrument(this.instrument)},Midi.prototype.endTrack=function(){var tracklength=toHex(this.track.length/3+4,8);this.track=\"MTrk\"+tracklength+this.track+\"%00%FF%2F%00\",this.trackstrings+=this.track},Midi.prototype.setInstrument=function(number){this.track?this.track=\"%00%C0\"+toHex(number,2)+this.track:this.track=\"%00%C0\"+toHex(number,2),this.instrument=number},Midi.prototype.setChannel=function(number){this.channel=number-1,this.noteOnAndChannel=\"%9\"+this.channel.toString(16)},Midi.prototype.startNote=function(pitch,loudness){this.track+=toDurationHex(this.silencelength),this.silencelength=0,this.first&&(this.first=!1,this.track+=this.noteOnAndChannel),this.track+=\"%\"+pitch.toString(16)+toHex(loudness,2)},Midi.prototype.endNote=function(pitch,length){this.track+=toDurationHex(this.silencelength+length),this.silencelength=0,this.track+=\"%\"+pitch.toString(16)+\"%00\"},Midi.prototype.addRest=function(length){this.silencelength+=length},Midi.prototype.getData=function(){return\"data:audio/midi,MThd%00%00%00%06%00%01\"+toHex(this.trackcount,4)+\"%01%e0\"+this.trackstrings},Midi.prototype.embed=function(parent,noplayer){var data=this.getData(),link=setAttributes(document.createElement(\"a\"),{href:data});if(link.innerHTML=\"download midi\",parent.insertBefore(link,parent.firstChild),!noplayer){var embed=setAttributes(document.createElement(\"embed\"),{src:data,type:\"video/quicktime\",controller:\"true\",autoplay:\"false\",loop:\"false\",enablejavascript:\"true\",style:\"display:block; height: 20px;\"});parent.insertBefore(embed,parent.firstChild)}},window.ABCJS.midi.rendererFactory=function(){return new Midi}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.midi||(window.ABCJS.midi={}),function(){\"use strict\";function interpretTempo(element){var duration=.25;element.duration&&(duration=element.duration[0]);var bpm=60;return element.bpm&&(bpm=element.bpm),bpm*duration*4}function interpretMeter(element){var meter;switch(element.type){case\"common_time\":meter={el_type:\"meter\",num:4,den:4};break;case\"cut_time\":meter={el_type:\"meter\",num:2,den:2};break;case\"specified\":meter={el_type:\"meter\",num:element.value[0].num,den:element.value[0].den};break;default:meter={el_type:\"meter\"}}return measureLength=meter.num/meter.den,meter}var measureLength;window.ABCJS.midi.sequence=function(abctune,options){options=options||{};var qpm=180,program=options.program||0,transpose=options.transpose||0,channel=options.channel||0,drumPattern=options.drum||\"\",drumBars=options.drumBars||1,drumIntro=options.drumIntro||0,drumOn=\"\"!==drumPattern;program=parseInt(program,10),transpose=parseInt(transpose,10),channel=parseInt(channel,10),drumPattern=drumPattern.split(\" \"),drumBars=parseInt(drumBars,10),drumIntro=parseInt(drumIntro,10);var bagpipes=abctune.formatting.bagpipes;if(bagpipes&&(program=71),abctune.formatting.midi){var globals=abctune.formatting.midi;globals.program&&(program=globals.program[0],globals.program.length>1&&(channel=globals.program[1])),globals.transpose&&(transpose=globals.transpose[0]),globals.channel&&(channel=globals.channel[0]),globals.drum&&(drumPattern=globals.drum),globals.drumbars&&(drumBars=globals.drumbars[0]),globals.drumon&&(drumOn=!0)}abctune.metaText.tempo&&(qpm=interpretTempo(abctune.metaText.tempo)),options.qpm&&(qpm=parseInt(options.qpm,10));var startVoice=[];bagpipes&&startVoice.push({el_type:\"bagpipes\"}),startVoice.push({el_type:\"instrument\",program:program}),channel&&startVoice.push({el_type:\"channel\",channel:channel}),transpose&&startVoice.push({el_type:\"transpose\",transpose:transpose}),startVoice.push({el_type:\"tempo\",qpm:qpm});for(var voices=[],startRepeatPlaceholder=[],skipEndingPlaceholder=[],startingDrumSet=!1,i=0;i<abctune.lines.length;i++){var line=abctune.lines[i];if(line.staff)for(var staves=line.staff,voiceNumber=0,j=0;j<staves.length;j++)for(var staff=staves[j],k=0;k<staff.voices.length;k++){var voice=staff.voices[k];voices[voiceNumber]||(voices[voiceNumber]=[].concat(startVoice)),staff.key&&(\"HP\"===staff.key.root?voices[voiceNumber].push({el_type:\"key\",accidentals:[{acc:\"natural\",note:\"g\"},{acc:\"sharp\",note:\"f\"},{acc:\"sharp\",note:\"c\"}]}):voices[voiceNumber].push({el_type:\"key\",accidentals:staff.key.accidentals})),staff.meter&&voices[voiceNumber].push(interpretMeter(staff.meter)),!startingDrumSet&&drumOn&&(voices[voiceNumber].push({el_type:\"drum\",params:{pattern:drumPattern,bars:drumBars,on:drumOn,intro:drumIntro}}),startingDrumSet=!0),staff.clef&&staff.clef.transpose&&(staff.clef.el_type=\"clef\",voices[voiceNumber].push({el_type:\"transpose\",transpose:staff.clef.transpose})),abctune.formatting.midi&&abctune.formatting.midi.drumoff&&(voices[voiceNumber].push({el_type:\"bar\"}),voices[voiceNumber].push({el_type:\"drum\",params:{pattern:\"\",on:!1}}));for(var noteEventsInBar=0,v=0;v<voice.length;v++){var elem=voice[v];switch(elem.el_type){case\"note\":elem.rest&&\"spacer\"===elem.rest.type||(voices[voiceNumber].push(elem),noteEventsInBar++);break;case\"key\":\"HP\"===elem.root?voices[voiceNumber].push({el_type:\"key\",accidentals:[{acc:\"natural\",note:\"g\"},{acc:\"sharp\",note:\"f\"},{acc:\"sharp\",note:\"c\"}]}):voices[voiceNumber].push({el_type:\"key\",accidentals:elem.accidentals});break;case\"meter\":voices[voiceNumber].push(interpretMeter(elem));break;case\"clef\":elem.transpose&&voices[voiceNumber].push({el_type:\"transpose\",transpose:elem.transpose});break;case\"tempo\":qpm=interpretTempo(elem),voices[voiceNumber].push({el_type:\"tempo\",qpm:qpm});break;case\"bar\":noteEventsInBar>0&&voices[voiceNumber].push({el_type:\"bar\"}),noteEventsInBar=0;var endRepeat=\"bar_right_repeat\"===elem.type||\"bar_dbl_repeat\"===elem.type,startEnding=\"1\"===elem.startEnding,startRepeat=\"bar_left_repeat\"===elem.type||\"bar_dbl_repeat\"===elem.type||\"bar_thick_thin\"===elem.type||\"bar_thin_thick\"===elem.type||\"bar_thin_thin\"===elem.type||\"bar_right_repeat\"===elem.type;if(endRepeat){var s=startRepeatPlaceholder[voiceNumber];s||(s=0);var e=skipEndingPlaceholder[voiceNumber];e||(e=voices[voiceNumber].length),voices[voiceNumber]=voices[voiceNumber].concat(voices[voiceNumber].slice(s,e)),skipEndingPlaceholder[voiceNumber]=void 0,startRepeatPlaceholder[voiceNumber]=void 0}startEnding&&(skipEndingPlaceholder[voiceNumber]=voices[voiceNumber].length),startRepeat&&(startRepeatPlaceholder[voiceNumber]=voices[voiceNumber].length);break;case\"style\":break;case\"part\":break;case\"stem\":case\"scale\":break;case\"midi\":var drumChange=!1;switch(elem.cmd){case\"drumon\":drumOn=!0,drumChange=!0;break;case\"drumoff\":drumOn=!1,drumChange=!0;break;case\"drum\":drumPattern=elem.params,drumChange=!0;break;case\"drumbars\":drumBars=elem.params[0],drumChange=!0}drumChange&&(voices[0].push({el_type:\"drum\",params:{pattern:drumPattern,bars:drumBars,intro:drumIntro,on:drumOn}}),startingDrumSet=!0);break;default:console.log(\"MIDI: element type \"+elem.el_type+\" not handled.\")}}voiceNumber++}}if(drumIntro)for(var vv=0;vv<voices.length;vv++){for(var insertPoint=0;\"note\"!==voices[vv][insertPoint].el_type&&voices[vv].length>insertPoint;)insertPoint++;if(voices[vv].length>insertPoint)for(var w=0;w<drumIntro;w++)voices[vv].splice(insertPoint,0,{el_type:\"note\",rest:{type:\"rest\"},duration:measureLength},{el_type:\"bar\"})}return voices}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.parse||(window.ABCJS.parse={}),window.ABCJS.parse.clone=function(source){var destination={};for(var property in source)source.hasOwnProperty(property)&&(destination[property]=source[property]);return destination},window.ABCJS.parse.cloneArray=function(source){for(var destination=[],i=0;i<source.length;i++)destination.push(ABCJS.parse.clone(source[i]));return destination},window.ABCJS.parse.cloneHashOfHash=function(source){var destination={};for(var property in source)source.hasOwnProperty(property)&&(destination[property]=ABCJS.parse.clone(source[property]));return destination},window.ABCJS.parse.cloneHashOfArrayOfHash=function(source){var destination={};for(var property in source)source.hasOwnProperty(property)&&(destination[property]=ABCJS.parse.cloneArray(source[property]));return destination},window.ABCJS.parse.gsub=function(source,pattern,replacement){return source.split(pattern).join(replacement)},window.ABCJS.parse.strip=function(str){return str.replace(/^\\s+/,\"\").replace(/\\s+$/,\"\")},window.ABCJS.parse.startsWith=function(str,pattern){return 0===str.indexOf(pattern)},window.ABCJS.parse.endsWith=function(str,pattern){var d=str.length-pattern.length;return d>=0&&str.lastIndexOf(pattern)===d},window.ABCJS.parse.each=function(arr,iterator,context){for(var i=0,length=arr.length;i<length;i++)iterator.apply(context,[arr[i],i])},window.ABCJS.parse.last=function(arr){return 0===arr.length?null:arr[arr.length-1]},window.ABCJS.parse.compact=function(arr){for(var output=[],i=0;i<arr.length;i++)arr[i]&&output.push(arr[i]);return output},window.ABCJS.parse.detect=function(arr,iterator){for(var i=0;i<arr.length;i++)if(iterator(arr[i]))return!0;return!1},window.ABCJS||(window.ABCJS={}),window.ABCJS.parse||(window.ABCJS.parse={}),window.ABCJS.parse.Parse=function(){\"use strict\";function addPositioning(el,type,value){el.positioning||(el.positioning={}),el.positioning[type]=value}function addFont(el,type,value){el.fonts||(el.fonts={}),el.fonts[type]=value}function startNewLine(){var params={startChar:-1,endChar:-1};if(multilineVars.partForNextLine.length&&(params.part=multilineVars.partForNextLine),params.clef=multilineVars.currentVoice&&void 0!==multilineVars.staves[multilineVars.currentVoice.staffNum].clef?window.ABCJS.parse.clone(multilineVars.staves[multilineVars.currentVoice.staffNum].clef):window.ABCJS.parse.clone(multilineVars.clef),params.key=window.ABCJS.parse.parseKeyVoice.deepCopyKey(multilineVars.key),window.ABCJS.parse.parseKeyVoice.addPosToKey(params.clef,params.key),null!==multilineVars.meter?(multilineVars.currentVoice?(window.ABCJS.parse.each(multilineVars.staves,function(st){st.meter=multilineVars.meter}),params.meter=multilineVars.staves[multilineVars.currentVoice.staffNum].meter,multilineVars.staves[multilineVars.currentVoice.staffNum].meter=null):params.meter=multilineVars.meter,multilineVars.meter=null):multilineVars.currentVoice&&multilineVars.staves[multilineVars.currentVoice.staffNum].meter&&(params.meter=multilineVars.staves[multilineVars.currentVoice.staffNum].meter,multilineVars.staves[multilineVars.currentVoice.staffNum].meter=null),multilineVars.currentVoice&&multilineVars.currentVoice.name&&(params.name=multilineVars.currentVoice.name),multilineVars.vocalfont&&(params.vocalfont=multilineVars.vocalfont),multilineVars.style&&(params.style=multilineVars.style),multilineVars.currentVoice){var staff=multilineVars.staves[multilineVars.currentVoice.staffNum];staff.brace&&(params.brace=staff.brace),staff.bracket&&(params.bracket=staff.bracket),staff.connectBarLines&&(params.connectBarLines=staff.connectBarLines),staff.name&&(params.name=staff.name[multilineVars.currentVoice.index]),staff.subname&&(params.subname=staff.subname[multilineVars.currentVoice.index]),multilineVars.currentVoice.stem&&(params.stem=multilineVars.currentVoice.stem),multilineVars.currentVoice.scale&&(params.scale=multilineVars.currentVoice.scale),multilineVars.currentVoice.style&&(params.style=multilineVars.currentVoice.style),multilineVars.currentVoice.transpose&&(params.clef.transpose=multilineVars.currentVoice.transpose)}var isFirstVoice=void 0===multilineVars.currentVoice||0===multilineVars.currentVoice.staffNum&&0===multilineVars.currentVoice.index;\n0===multilineVars.barNumbers&&isFirstVoice&&1!==multilineVars.currBarNumber&&(params.barNumber=multilineVars.currBarNumber),tune.startNewLine(params),multilineVars.partForNextLine=\"\"}function durationOfMeasure(multilineVars){var meter=multilineVars.origMeter;return meter&&\"specified\"===meter.type&&meter.value&&0!==meter.value.length?parseInt(meter.value[0].num,10)/parseInt(meter.value[0].den,10):1}function appendLastMeasure(voice,nextVoice){voice.push({el_type:\"hint\"});for(var i=0;i<nextVoice.length;i++){var element=nextVoice[i],hint=window.ABCJS.parse.clone(element);if(voice.push(hint),\"bar\"===element.el_type)return}}function addHintMeasure(staff,nextStaff){for(var i=0;i<staff.length;i++){var stave=staff[i],nextStave=nextStaff[i];if(nextStave)for(var j=0;j<nextStave.voices.length;j++){var nextVoice=nextStave.voices[j],voice=stave.voices[j];voice&&appendLastMeasure(voice,nextVoice)}}}function addHintMeasures(){for(var i=0;i<tune.lines.length;i++){var line=tune.lines[i].staff;if(line){for(var j=i+1;j<tune.lines.length&&void 0===tune.lines[j].staff;)j++;if(j<tune.lines.length){var nextLine=tune.lines[j].staff;addHintMeasure(line,nextLine)}}}}var tune=new window.ABCJS.data.Tune,tokenizer=new window.ABCJS.parse.tokenizer;this.getTune=function(){return tune};var multilineVars={reset:function(){for(var property in this)this.hasOwnProperty(property)&&\"function\"!=typeof this[property]&&delete this[property];this.iChar=0,this.key={accidentals:[],root:\"none\",acc:\"\",mode:\"\"},this.meter={type:\"specified\",value:[{num:\"4\",den:\"4\"}]},this.origMeter={type:\"specified\",value:[{num:\"4\",den:\"4\"}]},this.hasMainTitle=!1,this.default_length=.125,this.clef={type:\"treble\",verticalPos:0},this.next_note_duration=0,this.start_new_line=!0,this.is_in_header=!0,this.is_in_history=!1,this.partForNextLine=\"\",this.havent_set_length=!0,this.voices={},this.staves=[],this.macros={},this.currBarNumber=1,this.inTextBlock=!1,this.inPsBlock=!1,this.ignoredDecorations=[],this.textBlock=\"\",this.score_is_present=!1,this.inEnding=!1,this.inTie=!1,this.inTieChord={},this.vocalPosition=\"auto\",this.dynamicPosition=\"auto\",this.chordPosition=\"auto\",this.ornamentPosition=\"auto\",this.volumePosition=\"auto\",this.openSlurs=[]},differentFont:function(type,defaultFonts){return this[type].decoration!==defaultFonts[type].decoration||(this[type].face!==defaultFonts[type].face||(this[type].size!==defaultFonts[type].size||(this[type].style!==defaultFonts[type].style||this[type].weight!==defaultFonts[type].weight)))},addFormattingOptions:function(el,defaultFonts,elType){\"note\"===elType?(\"auto\"!==this.vocalPosition&&addPositioning(el,\"vocalPosition\",this.vocalPosition),\"auto\"!==this.dynamicPosition&&addPositioning(el,\"dynamicPosition\",this.dynamicPosition),\"auto\"!==this.chordPosition&&addPositioning(el,\"chordPosition\",this.chordPosition),\"auto\"!==this.ornamentPosition&&addPositioning(el,\"ornamentPosition\",this.ornamentPosition),\"auto\"!==this.volumePosition&&addPositioning(el,\"volumePosition\",this.volumePosition),this.differentFont(\"annotationfont\",defaultFonts)&&addFont(el,\"annotationfont\",this.annotationfont),this.differentFont(\"gchordfont\",defaultFonts)&&addFont(el,\"gchordfont\",this.gchordfont),this.differentFont(\"vocalfont\",defaultFonts)&&addFont(el,\"vocalfont\",this.vocalfont)):\"bar\"===elType&&(\"auto\"!==this.dynamicPosition&&addPositioning(el,\"dynamicPosition\",this.dynamicPosition),\"auto\"!==this.chordPosition&&addPositioning(el,\"chordPosition\",this.chordPosition),\"auto\"!==this.ornamentPosition&&addPositioning(el,\"ornamentPosition\",this.ornamentPosition),\"auto\"!==this.volumePosition&&addPositioning(el,\"volumePosition\",this.volumePosition),this.differentFont(\"measurefont\",defaultFonts)&&addFont(el,\"measurefont\",this.measurefont),this.differentFont(\"repeatfont\",defaultFonts)&&addFont(el,\"repeatfont\",this.repeatfont))}},addWarning=function(str){multilineVars.warnings||(multilineVars.warnings=[]),multilineVars.warnings.push(str)},encode=function(str){var ret=window.ABCJS.parse.gsub(str,\"\u0012\",\" \");return ret=window.ABCJS.parse.gsub(ret,\"&\",\"&amp;\"),ret=window.ABCJS.parse.gsub(ret,\"<\",\"&lt;\"),window.ABCJS.parse.gsub(ret,\">\",\"&gt;\")},warn=function(str,line,col_num){line||(line=\" \");var bad_char=line.charAt(col_num);\" \"===bad_char&&(bad_char=\"SPACE\");var clean_line=encode(line.substring(0,col_num))+'<span style=\"text-decoration:underline;font-size:1.3em;font-weight:bold;\">'+bad_char+\"</span>\"+encode(line.substring(col_num+1));addWarning(\"Music Line:\"+tune.getNumLines()+\":\"+(col_num+1)+\": \"+str+\":  \"+clean_line)},header=new window.ABCJS.parse.ParseHeader(tokenizer,warn,multilineVars,tune);this.getWarnings=function(){return multilineVars.warnings};var letter_to_chord=function(line,i){if('\"'===line.charAt(i)){var chord=tokenizer.getBrackettedSubstring(line,i,5);if(chord[2]||warn(\"Missing the closing quote while parsing the chord symbol\",line,i),chord[0]>0&&chord[1].length>0&&\"^\"===chord[1].charAt(0))chord[1]=chord[1].substring(1),chord[2]=\"above\";else if(chord[0]>0&&chord[1].length>0&&\"_\"===chord[1].charAt(0))chord[1]=chord[1].substring(1),chord[2]=\"below\";else if(chord[0]>0&&chord[1].length>0&&\"<\"===chord[1].charAt(0))chord[1]=chord[1].substring(1),chord[2]=\"left\";else if(chord[0]>0&&chord[1].length>0&&\">\"===chord[1].charAt(0))chord[1]=chord[1].substring(1),chord[2]=\"right\";else if(chord[0]>0&&chord[1].length>0&&\"@\"===chord[1].charAt(0)){chord[1]=chord[1].substring(1);var x=tokenizer.getFloat(chord[1]);0===x.digits&&warn(\"Missing first position in absolutely positioned annotation.\",line,i),chord[1]=chord[1].substring(x.digits),\",\"!==chord[1][0]&&warn(\"Missing comma absolutely positioned annotation.\",line,i),chord[1]=chord[1].substring(1);var y=tokenizer.getFloat(chord[1]);0===y.digits&&warn(\"Missing second position in absolutely positioned annotation.\",line,i),chord[1]=chord[1].substring(y.digits);var ws=tokenizer.skipWhiteSpace(chord[1]);chord[1]=chord[1].substring(ws),chord[2]=null,chord[3]={x:x.value,y:y.value}}else chord[1]=chord[1].replace(/([ABCDEFG])b/g,\"$1♭\"),chord[1]=chord[1].replace(/([ABCDEFG])#/g,\"$1♯\"),chord[2]=\"default\";return chord}return[0,\"\"]},legalAccents=[\"trill\",\"lowermordent\",\"uppermordent\",\"mordent\",\"pralltriller\",\"accent\",\"fermata\",\"invertedfermata\",\"tenuto\",\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"+\",\"wedge\",\"open\",\"thumb\",\"snap\",\"turn\",\"roll\",\"breath\",\"shortphrase\",\"mediumphrase\",\"longphrase\",\"segno\",\"coda\",\"D.S.\",\"D.C.\",\"fine\",\"slide\",\"^\",\"marcato\",\"upbow\",\"downbow\",\"/\",\"//\",\"///\",\"////\",\"trem1\",\"trem2\",\"trem3\",\"trem4\",\"turnx\",\"invertedturn\",\"invertedturnx\",\"trill(\",\"trill)\",\"arpeggio\",\"xstem\",\"mark\",\"umarcato\",\"style=normal\",\"style=harmonic\",\"style=rhythm\",\"style=x\"],volumeDecorations=[\"p\",\"pp\",\"f\",\"ff\",\"mf\",\"mp\",\"ppp\",\"pppp\",\"fff\",\"ffff\",\"sfz\"],dynamicDecorations=[\"crescendo(\",\"crescendo)\",\"diminuendo(\",\"diminuendo)\"],accentPseudonyms=[[\"<\",\"accent\"],[\">\",\"accent\"],[\"tr\",\"trill\"],[\"plus\",\"+\"],[\"emphasis\",\"accent\"],[\"^\",\"umarcato\"],[\"marcato\",\"umarcato\"]],accentDynamicPseudonyms=[[\"<(\",\"crescendo(\"],[\"<)\",\"crescendo)\"],[\">(\",\"diminuendo(\"],[\">)\",\"diminuendo)\"]],letter_to_accent=function(line,i){var macro=multilineVars.macros[line.charAt(i)];if(void 0!==macro)return\"!\"!==macro.charAt(0)&&\"+\"!==macro.charAt(0)||(macro=macro.substring(1)),\"!\"!==macro.charAt(macro.length-1)&&\"+\"!==macro.charAt(macro.length-1)||(macro=macro.substring(0,macro.length-1)),window.ABCJS.parse.detect(legalAccents,function(acc){return macro===acc})?[1,macro]:window.ABCJS.parse.detect(volumeDecorations,function(acc){return macro===acc})?(\"hidden\"===multilineVars.volumePosition&&(macro=\"\"),[1,macro]):window.ABCJS.parse.detect(dynamicDecorations,function(acc){return\"hidden\"===multilineVars.dynamicPosition&&(macro=\"\"),macro===acc})?[1,macro]:(window.ABCJS.parse.detect(multilineVars.ignoredDecorations,function(dec){return macro===dec})||warn(\"Unknown macro: \"+macro,line,i),[1,\"\"]);switch(line.charAt(i)){case\".\":return[1,\"staccato\"];case\"u\":return[1,\"upbow\"];case\"v\":return[1,\"downbow\"];case\"~\":return[1,\"irishroll\"];case\"!\":case\"+\":var ret=tokenizer.getBrackettedSubstring(line,i,5);return ret[1].length>0&&(\"^\"===ret[1].charAt(0)||\"_\"===ret[1].charAt(0))&&(ret[1]=ret[1].substring(1)),window.ABCJS.parse.detect(legalAccents,function(acc){return ret[1]===acc})?ret:window.ABCJS.parse.detect(volumeDecorations,function(acc){return ret[1]===acc})?(\"hidden\"===multilineVars.volumePosition&&(ret[1]=\"\"),ret):window.ABCJS.parse.detect(dynamicDecorations,function(acc){return ret[1]===acc})?(\"hidden\"===multilineVars.dynamicPosition&&(ret[1]=\"\"),ret):window.ABCJS.parse.detect(accentPseudonyms,function(acc){return ret[1]===acc[0]&&(ret[1]=acc[1],!0)})?ret:window.ABCJS.parse.detect(accentDynamicPseudonyms,function(acc){return ret[1]===acc[0]&&(ret[1]=acc[1],!0)})?(\"hidden\"===multilineVars.dynamicPosition&&(ret[1]=\"\"),ret):\"!\"!==line.charAt(i)||1!==ret[0]&&\"!\"===line.charAt(i+ret[0]-1)?(warn(\"Unknown decoration: \"+ret[1],line,i),ret[1]=\"\",ret):[1,null];case\"H\":return[1,\"fermata\"];case\"J\":return[1,\"slide\"];case\"L\":return[1,\"accent\"];case\"M\":return[1,\"mordent\"];case\"O\":return[1,\"coda\"];case\"P\":return[1,\"pralltriller\"];case\"R\":return[1,\"roll\"];case\"S\":return[1,\"segno\"];case\"T\":return[1,\"trill\"]}return[0,0]},letter_to_spacer=function(line,i){for(var start=i;tokenizer.isWhiteSpace(line.charAt(i));)i++;return[i-start]},letter_to_bar=function(line,curr_pos){var ret=tokenizer.getBarLine(line,curr_pos);if(0===ret.len)return[0,\"\"];if(ret.warn)return warn(ret.warn,line,curr_pos),[ret.len,\"\"];for(var ws=0;ws<line.length&&\" \"===line.charAt(curr_pos+ret.len+ws);ws++);var orig_bar_len=ret.len;if(\"[\"===line.charAt(curr_pos+ret.len+ws)&&(ret.len+=ws+1),'\"'===line.charAt(curr_pos+ret.len)&&\"[\"===line.charAt(curr_pos+ret.len-1)){var ending=tokenizer.getBrackettedSubstring(line,curr_pos+ret.len,5);return[ret.len+ending[0],ret.token,ending[1]]}var retRep=tokenizer.getTokenOf(line.substring(curr_pos+ret.len),\"1234567890-,\");return 0===retRep.len||\"-\"===retRep.token[0]?[orig_bar_len,ret.token]:[ret.len+retRep.len,ret.token,retRep.token]},letter_to_open_slurs_and_triplets=function(line,i){for(var ret={},start=i;\"(\"===line.charAt(i)||tokenizer.isWhiteSpace(line.charAt(i));)\"(\"===line.charAt(i)&&(i+1<line.length&&line.charAt(i+1)>=\"2\"&&line.charAt(i+1)<=\"9\"?(void 0!==ret.triplet?warn(\"Can't nest triplets\",line,i):(ret.triplet=line.charAt(i+1)-\"0\",i+2<line.length&&\":\"===line.charAt(i+2)&&(i+3<line.length&&\":\"===line.charAt(i+3)?i+4<line.length&&line.charAt(i+4)>=\"1\"&&line.charAt(i+4)<=\"9\"?(ret.num_notes=line.charAt(i+4)-\"0\",i+=3):warn(\"expected number after the two colons after the triplet to mark the duration\",line,i):i+3<line.length&&line.charAt(i+3)>=\"1\"&&line.charAt(i+3)<=\"9\"?i+4<line.length&&\":\"===line.charAt(i+4)?i+5<line.length&&line.charAt(i+5)>=\"1\"&&line.charAt(i+5)<=\"9\"&&(ret.num_notes=line.charAt(i+5)-\"0\",i+=4):(ret.num_notes=ret.triplet,i+=3):warn(\"expected number after the triplet to mark the duration\",line,i))),i++):void 0===ret.startSlur?ret.startSlur=1:ret.startSlur++),i++;return ret.consumed=i-start,ret},addWords=function(line,words){if(!line)return void warn(\"Can't add words before the first line of music\",line,0);words=window.ABCJS.parse.strip(words),\"-\"!==words.charAt(words.length-1)&&(words+=\" \");for(var word_list=[],last_divider=0,replace=!1,addWord=function(i){var word=window.ABCJS.parse.strip(words.substring(last_divider,i));if(last_divider=i+1,word.length>0){replace&&(word=window.ABCJS.parse.gsub(word,\"~\",\" \"));var div=words.charAt(i);return\"_\"!==div&&\"-\"!==div&&(div=\" \"),word_list.push({syllable:tokenizer.translateString(word),divider:div}),replace=!1,!0}return!1},i=0;i<words.length;i++)switch(words.charAt(i)){case\" \":case\"\u0012\":addWord(i);break;case\"-\":!addWord(i)&&word_list.length>0&&(window.ABCJS.parse.last(word_list).divider=\"-\",word_list.push({skip:!0,to:\"next\"}));break;case\"_\":addWord(i),word_list.push({skip:!0,to:\"slur\"});break;case\"*\":addWord(i),word_list.push({skip:!0,to:\"next\"});break;case\"|\":addWord(i),word_list.push({skip:!0,to:\"bar\"});break;case\"~\":replace=!0}var inSlur=!1;window.ABCJS.parse.each(line,function(el){if(0!==word_list.length)if(word_list[0].skip)switch(word_list[0].to){case\"next\":\"note\"!==el.el_type||null===el.pitches||inSlur||word_list.shift();break;case\"slur\":\"note\"===el.el_type&&null!==el.pitches&&word_list.shift();break;case\"bar\":\"bar\"===el.el_type&&word_list.shift()}else if(\"note\"===el.el_type&&void 0===el.rest&&!inSlur){var lyric=word_list.shift();void 0===el.lyric?el.lyric=[lyric]:el.lyric.push(lyric)}})},addSymbols=function(line,words){if(!line)return void warn(\"Can't add symbols before the first line of music\",line,0);words=window.ABCJS.parse.strip(words),\"-\"!==words.charAt(words.length-1)&&(words+=\" \");for(var word_list=[],last_divider=0,replace=!1,addWord=function(i){var word=window.ABCJS.parse.strip(words.substring(last_divider,i));if(last_divider=i+1,word.length>0){replace&&(word=window.ABCJS.parse.gsub(word,\"~\",\" \"));var div=words.charAt(i);return\"_\"!==div&&\"-\"!==div&&(div=\" \"),word_list.push({syllable:tokenizer.translateString(word),divider:div}),replace=!1,!0}return!1},i=0;i<words.length;i++)switch(words.charAt(i)){case\" \":case\"\u0012\":addWord(i);break;case\"-\":!addWord(i)&&word_list.length>0&&(window.ABCJS.parse.last(word_list).divider=\"-\",word_list.push({skip:!0,to:\"next\"}));break;case\"_\":addWord(i),word_list.push({skip:!0,to:\"slur\"});break;case\"*\":addWord(i),word_list.push({skip:!0,to:\"next\"});break;case\"|\":addWord(i),word_list.push({skip:!0,to:\"bar\"});break;case\"~\":replace=!0}var inSlur=!1;window.ABCJS.parse.each(line,function(el){if(0!==word_list.length)if(word_list[0].skip)switch(word_list[0].to){case\"next\":\"note\"!==el.el_type||null===el.pitches||inSlur||word_list.shift();break;case\"slur\":\"note\"===el.el_type&&null!==el.pitches&&word_list.shift();break;case\"bar\":\"bar\"===el.el_type&&word_list.shift()}else if(\"note\"===el.el_type&&void 0===el.rest&&!inSlur){var lyric=word_list.shift();void 0===el.lyric?el.lyric=[lyric]:el.lyric.push(lyric)}})},getBrokenRhythm=function(line,index){switch(line.charAt(index)){case\">\":return index<line.length-1&&\">\"===line.charAt(index+1)?[2,1.75,.25]:[1,1.5,.5];case\"<\":return index<line.length-1&&\"<\"===line.charAt(index+1)?[2,.25,1.75]:[1,.5,1.5]}return null},addEndBeam=function(el){return void 0!==el.duration&&el.duration<.25&&(el.end_beam=!0),el},pitches={A:5,B:6,C:0,D:1,E:2,F:3,G:4,a:12,b:13,c:7,d:8,e:9,f:10,g:11},rests={x:\"invisible\",y:\"spacer\",z:\"rest\",Z:\"multimeasure\"},getCoreNote=function(line,index,el,canHaveBrokenRhythm){for(var isComplete=function(state){return\"octave\"===state||\"duration\"===state||\"Zduration\"===state||\"broken_rhythm\"===state||\"end_slur\"===state},state=\"startSlur\",durationSetByPreviousNote=!1;;){switch(line.charAt(index)){case\"(\":if(\"startSlur\"!==state)return isComplete(state)?(el.endChar=index,el):null;void 0===el.startSlur?el.startSlur=1:el.startSlur++;break;case\")\":if(!isComplete(state))return null;void 0===el.endSlur?el.endSlur=1:el.endSlur++;break;case\"^\":if(\"startSlur\"===state)el.accidental=\"sharp\",state=\"sharp2\";else{if(\"sharp2\"!==state)return isComplete(state)?(el.endChar=index,el):null;el.accidental=\"dblsharp\",state=\"pitch\"}break;case\"_\":if(\"startSlur\"===state)el.accidental=\"flat\",state=\"flat2\";else{if(\"flat2\"!==state)return isComplete(state)?(el.endChar=index,el):null;el.accidental=\"dblflat\",state=\"pitch\"}break;case\"=\":if(\"startSlur\"!==state)return isComplete(state)?(el.endChar=index,el):null;el.accidental=\"natural\",state=\"pitch\";break;case\"A\":case\"B\":case\"C\":case\"D\":case\"E\":case\"F\":case\"G\":case\"a\":case\"b\":case\"c\":case\"d\":case\"e\":case\"f\":case\"g\":if(\"startSlur\"!==state&&\"sharp2\"!==state&&\"flat2\"!==state&&\"pitch\"!==state)return isComplete(state)?(el.endChar=index,el):null;el.pitch=pitches[line.charAt(index)],state=\"octave\",canHaveBrokenRhythm&&0!==multilineVars.next_note_duration?(el.duration=multilineVars.default_length*multilineVars.next_note_duration,multilineVars.next_note_duration=0,durationSetByPreviousNote=!0):el.duration=multilineVars.default_length;break;case\",\":if(\"octave\"!==state)return isComplete(state)?(el.endChar=index,el):null;el.pitch-=7;break;case\"'\":if(\"octave\"!==state)return isComplete(state)?(el.endChar=index,el):null;el.pitch+=7;break;case\"x\":case\"y\":case\"z\":case\"Z\":if(\"startSlur\"!==state)return isComplete(state)?(el.endChar=index,el):null;el.rest={type:rests[line.charAt(index)]},delete el.accidental,delete el.startSlur,delete el.startTie,delete el.endSlur,delete el.endTie,delete el.end_beam,delete el.grace_notes,\"multimeasure\"===el.rest.type?(el.duration=1,state=\"Zduration\"):(canHaveBrokenRhythm&&0!==multilineVars.next_note_duration?(el.duration=multilineVars.default_length*multilineVars.next_note_duration,multilineVars.next_note_duration=0,durationSetByPreviousNote=!0):el.duration=multilineVars.default_length,state=\"duration\");break;case\"1\":case\"2\":case\"3\":case\"4\":case\"5\":case\"6\":case\"7\":case\"8\":case\"9\":case\"0\":case\"/\":if(\"octave\"===state||\"duration\"===state){var fraction=tokenizer.getFraction(line,index);for(el.duration=el.duration*fraction.value,el.endChar=fraction.index;fraction.index<line.length&&(tokenizer.isWhiteSpace(line.charAt(fraction.index))||\"-\"===line.charAt(fraction.index));)\"-\"===line.charAt(fraction.index)?el.startTie={}:el=addEndBeam(el),fraction.index++;index=fraction.index-1,state=\"broken_rhythm\"}else if(\"sharp2\"===state)el.accidental=\"quartersharp\",state=\"pitch\";else{if(\"flat2\"!==state){if(\"Zduration\"===state){var num=tokenizer.getNumber(line,index);return el.duration=num.num,el.endChar=num.index,el}return null}el.accidental=\"quarterflat\",state=\"pitch\"}break;case\"-\":if(\"startSlur\"===state)tune.addTieToLastNote(),el.endTie=!0;else{if(\"octave\"!==state&&\"duration\"!==state&&\"end_slur\"!==state)return\"broken_rhythm\"===state?(el.endChar=index,el):null;if(el.startTie={},durationSetByPreviousNote||!canHaveBrokenRhythm)return tokenizer.isWhiteSpace(line.charAt(index+1))&&addEndBeam(el),el.endChar=index+1,el;state=\"broken_rhythm\"}break;case\" \":case\"\\t\":if(!isComplete(state))return null;el.end_beam=!0;do\"-\"===line.charAt(index)&&(el.startTie={}),index++;while(index<line.length&&(tokenizer.isWhiteSpace(line.charAt(index))||\"-\"===line.charAt(index)));if(el.endChar=index,durationSetByPreviousNote||!canHaveBrokenRhythm||\"<\"!==line.charAt(index)&&\">\"!==line.charAt(index))return el;index--,state=\"broken_rhythm\";break;case\">\":case\"<\":if(!isComplete(state))return null;if(!canHaveBrokenRhythm)return el.endChar=index,el;var br2=getBrokenRhythm(line,index);index+=br2[0]-1,multilineVars.next_note_duration=br2[2],el.duration=br2[1]*el.duration,state=\"end_slur\";break;default:return isComplete(state)?(el.endChar=index,el):null}if(index++,index===line.length)return isComplete(state)?(el.endChar=index,el):null}return null},letter_to_grace=function(line,i){if(\"{\"===line.charAt(i)){var gra=tokenizer.getBrackettedSubstring(line,i,1,\"}\");gra[2]||warn(\"Missing the closing '}' while parsing grace note\",line,i),\")\"===line[i+gra[0]]&&(gra[0]++,gra[1]+=\")\");for(var gracenotes=[],ii=0,inTie=!1;ii<gra[1].length;){var acciaccatura=!1;\"/\"===gra[1].charAt(ii)&&(acciaccatura=!0,ii++);var note=getCoreNote(gra[1],ii,{},!1);null!==note?(note.duration=note.duration/(8*multilineVars.default_length),acciaccatura&&(note.acciaccatura=!0),gracenotes.push(note),inTie&&(note.endTie=!0,inTie=!1),note.startTie&&(inTie=!0),ii=note.endChar,delete note.endChar):(\" \"===gra[1].charAt(ii)?gracenotes.length>0&&(gracenotes[gracenotes.length-1].end_beam=!0):warn(\"Unknown character '\"+gra[1].charAt(ii)+\"' while parsing grace note\",line,i),ii++)}if(gracenotes.length)return[gra[0],gracenotes]}return[0]},nonDecorations=\"ABCDEFGabcdefgxyzZ[]|^_{\",parseRegularMusicLine=function(line){header.resolveTempo(),multilineVars.is_in_header=!1;for(var i=0,startOfLine=multilineVars.iChar;tokenizer.isWhiteSpace(line.charAt(i))&&i<line.length;)i++;if(i!==line.length&&\"%\"!==line.charAt(i)){var delayStartNewLine=multilineVars.start_new_line;void 0===multilineVars.continueall?multilineVars.start_new_line=!0:multilineVars.start_new_line=!1;var tripletNotesLeft=0,retHeader=header.letter_to_body_header(line,i);retHeader[0]>0&&(i+=retHeader[0]);for(var el={};i<line.length;){var startI=i;if(\"%\"===line.charAt(i))break;var retInlineHeader=header.letter_to_inline_header(line,i);if(retInlineHeader[0]>0)i+=retInlineHeader[0];else{delayStartNewLine&&(startNewLine(),delayStartNewLine=!1);for(var ret;;)if(ret=tokenizer.eatWhiteSpace(line,i),ret>0&&(i+=ret),i>0&&\"\u0012\"===line.charAt(i-1)&&(ret=header.letter_to_body_header(line,i),ret[0]>0&&(i=ret[0],multilineVars.start_new_line=!1)),ret=letter_to_spacer(line,i),ret[0]>0&&(i+=ret[0]),ret=letter_to_chord(line,i),ret[0]>0){el.chord||(el.chord=[]);var chordName=tokenizer.translateString(ret[1]);chordName=chordName.replace(/;/g,\"\\n\");for(var addedChord=!1,ci=0;ci<el.chord.length;ci++)el.chord[ci].position===ret[2]&&(addedChord=!0,el.chord[ci].name+=\"\\n\"+chordName);addedChord===!1&&(null===ret[2]&&ret[3]?el.chord.push({name:chordName,rel_position:ret[3]}):el.chord.push({name:chordName,position:ret[2]})),i+=ret[0];var ii=tokenizer.skipWhiteSpace(line.substring(i));ii>0&&(el.force_end_beam_last=!0),i+=ii}else if(ret=nonDecorations.indexOf(line.charAt(i))===-1?letter_to_accent(line,i):[0],ret[0]>0)null===ret[1]?i+1<line.length&&startNewLine():ret[1].length>0&&(0===ret[1].indexOf(\"style=\")?el.style=ret[1].substr(6):(void 0===el.decoration&&(el.decoration=[]),el.decoration.push(ret[1]))),i+=ret[0];else{if(ret=letter_to_grace(line,i),!(ret[0]>0))break;el.gracenotes=ret[1],i+=ret[0]}if(ret=letter_to_bar(line,i),ret[0]>0){void 0!==el.gracenotes&&(el.rest={type:\"spacer\"},el.duration=.125,multilineVars.addFormattingOptions(el,tune.formatting,\"note\"),tune.appendElement(\"note\",startOfLine+i,startOfLine+i+ret[0],el),multilineVars.measureNotEmpty=!0,el={});var bar={type:ret[1]};if(0===bar.type.length)warn(\"Unknown bar type\",line,i);else{if(multilineVars.inEnding&&\"bar_thin\"!==bar.type&&(bar.endEnding=!0,multilineVars.inEnding=!1),ret[2]&&(bar.startEnding=ret[2],multilineVars.inEnding&&(bar.endEnding=!0),multilineVars.inEnding=!0),void 0!==el.decoration&&(bar.decoration=el.decoration),void 0!==el.chord&&(bar.chord=el.chord),bar.startEnding&&void 0===multilineVars.barFirstEndingNum?multilineVars.barFirstEndingNum=multilineVars.currBarNumber:bar.startEnding&&bar.endEnding&&multilineVars.barFirstEndingNum?multilineVars.currBarNumber=multilineVars.barFirstEndingNum:bar.endEnding&&(multilineVars.barFirstEndingNum=void 0),\"bar_invisible\"!==bar.type&&multilineVars.measureNotEmpty){var isFirstVoice=void 0===multilineVars.currentVoice||0===multilineVars.currentVoice.staffNum&&0===multilineVars.currentVoice.index;isFirstVoice&&(multilineVars.currBarNumber++,multilineVars.barNumbers&&multilineVars.currBarNumber%multilineVars.barNumbers===0&&(bar.barNumber=multilineVars.currBarNumber))}multilineVars.addFormattingOptions(el,tune.formatting,\"bar\"),tune.appendElement(\"bar\",startOfLine+i,startOfLine+i+ret[0],bar),multilineVars.measureNotEmpty=!1,el={}}i+=ret[0]}else if(\"&\"===line[i])warn(\"Overlay not yet supported\",line,i),i++;else{if(ret=letter_to_open_slurs_and_triplets(line,i),ret.consumed>0&&(void 0!==ret.startSlur&&(el.startSlur=ret.startSlur),void 0!==ret.triplet&&(tripletNotesLeft>0?warn(\"Can't nest triplets\",line,i):(el.startTriplet=ret.triplet,tripletNotesLeft=void 0===ret.num_notes?ret.triplet:ret.num_notes)),i+=ret.consumed),\"[\"===line.charAt(i)){var chordStartChar=i;i++;for(var chordDuration=null,done=!1;!done;){var chordNote=getCoreNote(line,i,{},!1);if(null!==chordNote)chordNote.end_beam&&(el.end_beam=!0,delete chordNote.end_beam),void 0===el.pitches?(el.duration=chordNote.duration,el.pitches=[chordNote]):el.pitches.push(chordNote),delete chordNote.duration,multilineVars.inTieChord[el.pitches.length]&&(chordNote.endTie=!0,multilineVars.inTieChord[el.pitches.length]=void 0),chordNote.startTie&&(multilineVars.inTieChord[el.pitches.length]=!0),i=chordNote.endChar,delete chordNote.endChar;else if(\" \"===line.charAt(i))warn(\"Spaces are not allowed in chords\",line,i),i++;else{if(i<line.length&&\"]\"===line.charAt(i)){i++,0!==multilineVars.next_note_duration&&(el.duration=el.duration*multilineVars.next_note_duration,multilineVars.next_note_duration=0),multilineVars.inTie&&(window.ABCJS.parse.each(el.pitches,function(pitch){pitch.endTie=!0}),multilineVars.inTie=!1),tripletNotesLeft>0&&(tripletNotesLeft--,0===tripletNotesLeft&&(el.endTriplet=!0));for(var postChordDone=!1;i<line.length&&!postChordDone;){switch(line.charAt(i)){case\" \":case\"\\t\":addEndBeam(el);break;case\")\":void 0===el.endSlur?el.endSlur=1:el.endSlur++;break;case\"-\":window.ABCJS.parse.each(el.pitches,function(pitch){pitch.startTie={}}),multilineVars.inTie=!0;break;case\">\":case\"<\":var br2=getBrokenRhythm(line,i);i+=br2[0]-1,multilineVars.next_note_duration=br2[2],chordDuration?chordDuration*=br2[1]:chordDuration=br2[1];break;case\"1\":case\"2\":case\"3\":case\"4\":case\"5\":case\"6\":case\"7\":case\"8\":case\"9\":case\"/\":var fraction=tokenizer.getFraction(line,i);chordDuration=fraction.value,i=fraction.index,\"-\"===line.charAt(i)||\")\"===line.charAt(i)||\" \"===line.charAt(i)||\"<\"===line.charAt(i)||\">\"===line.charAt(i)?i--:postChordDone=!0;break;default:postChordDone=!0}postChordDone||i++}}else warn(\"Expected ']' to end the chords\",line,i);void 0!==el.pitches&&(null!==chordDuration&&(el.duration=el.duration*chordDuration),multilineVars.addFormattingOptions(el,tune.formatting,\"note\"),tune.appendElement(\"note\",startOfLine+chordStartChar,startOfLine+i,el),multilineVars.measureNotEmpty=!0,el={}),done=!0}}}else{var el2={},core=getCoreNote(line,i,el2,!0);void 0!==el2.endTie&&(multilineVars.inTie=!0),null!==core&&(void 0!==core.pitch?(el.pitches=[{}],void 0!==core.accidental&&(el.pitches[0].accidental=core.accidental),el.pitches[0].pitch=core.pitch,void 0!==core.endSlur&&(el.pitches[0].endSlur=core.endSlur),void 0!==core.endTie&&(el.pitches[0].endTie=core.endTie),void 0!==core.startSlur&&(el.pitches[0].startSlur=core.startSlur),void 0!==el.startSlur&&(el.pitches[0].startSlur=el.startSlur),void 0!==core.startTie&&(el.pitches[0].startTie=core.startTie),void 0!==el.startTie&&(el.pitches[0].startTie=el.startTie)):(el.rest=core.rest,void 0!==core.endSlur&&(el.endSlur=core.endSlur),void 0!==core.endTie&&(el.rest.endTie=core.endTie),void 0!==core.startSlur&&(el.startSlur=core.startSlur),void 0!==core.startTie&&(el.rest.startTie=core.startTie),void 0!==el.startTie&&(el.rest.startTie=el.startTie)),void 0!==core.chord&&(el.chord=core.chord),void 0!==core.duration&&(el.duration=core.duration),void 0!==core.decoration&&(el.decoration=core.decoration),void 0!==core.graceNotes&&(el.graceNotes=core.graceNotes),delete el.startSlur,multilineVars.inTie&&(void 0!==el.pitches?(el.pitches[0].endTie=!0,multilineVars.inTie=!1):\"spacer\"!==el.rest.type&&(el.rest.endTie=!0,multilineVars.inTie=!1)),(core.startTie||el.startTie)&&(multilineVars.inTie=!0),i=core.endChar,tripletNotesLeft>0&&(tripletNotesLeft--,0===tripletNotesLeft&&(el.endTriplet=!0)),core.end_beam&&addEndBeam(el),el.rest&&\"rest\"===el.rest.type&&1===el.duration&&(el.rest.type=\"whole\",el.duration=durationOfMeasure(multilineVars)),multilineVars.addFormattingOptions(el,tune.formatting,\"note\"),tune.appendElement(\"note\",startOfLine+startI,startOfLine+i,el),multilineVars.measureNotEmpty=!0,el={})}i===startI&&(\" \"!==line.charAt(i)&&\"`\"!==line.charAt(i)&&warn(\"Unknown character ignored\",line,i),i++)}}}}},parseLine=function(line){var ret=header.parseHeader(line);ret.regular&&parseRegularMusicLine(ret.str),ret.newline&&void 0===multilineVars.continueall&&startNewLine(),ret.words&&addWords(tune.getCurrentVoice(),line.substring(2)),ret.symbols&&addSymbols(tune.getCurrentVoice(),line.substring(2)),ret.recurse&&parseLine(ret.str)};this.parse=function(strTune,switches){switches||(switches={}),tune.reset(),switches.print&&(tune.media=\"print\"),multilineVars.reset(),header.reset(tokenizer,warn,multilineVars,tune),strTune=window.ABCJS.parse.gsub(strTune,\"\\r\\n\",\"\\n\"),strTune=window.ABCJS.parse.gsub(strTune,\"\\r\",\"\\n\"),strTune+=\"\\n\",strTune=strTune.replace(/\\n\\\\.*\\n/g,\"\\n\");var continuationReplacement=function(all,backslash,comment){var spaces=\"                                                                                                                                                                                                     \",padding=comment?spaces.substring(0,comment.length):\"\";return backslash+\" \u0012\"+padding};strTune=strTune.replace(/\\\\([ \\t]*)(%.*)*\\n/g,continuationReplacement);var lines=strTune.split(\"\\n\");0===window.ABCJS.parse.last(lines).length&&lines.pop();try{switches.format&&window.ABCJS.parse.parseDirective.globalFormatting(switches.format),window.ABCJS.parse.each(lines,function(line){if(switches.header_only&&multilineVars.is_in_header===!1)throw\"normal_abort\";if(switches.stop_on_warning&&multilineVars.warnings)throw\"normal_abort\";multilineVars.is_in_history?\":\"===line.charAt(1)?(multilineVars.is_in_history=!1,parseLine(line)):tune.addMetaText(\"history\",tokenizer.translateString(tokenizer.stripComment(line))):multilineVars.inTextBlock?window.ABCJS.parse.startsWith(line,\"%%endtext\")?(tune.addText(multilineVars.textBlock),multilineVars.inTextBlock=!1):window.ABCJS.parse.startsWith(line,\"%%\")?multilineVars.textBlock+=\" \"+line.substring(2):multilineVars.textBlock+=\" \"+line:multilineVars.inPsBlock?window.ABCJS.parse.startsWith(line,\"%%endps\")?multilineVars.inPsBlock=!1:multilineVars.textBlock+=\" \"+line:parseLine(line),multilineVars.iChar+=line.length+1});var ph=792,pl=612;switch(multilineVars.papersize){case\"legal\":ph=1008,pl=612;break;case\"A4\":ph=842.4,pl=597.6}if(multilineVars.landscape){var x=ph;ph=pl,pl=x}multilineVars.openSlurs=tune.cleanUp(pl,ph,multilineVars.barsperstaff,multilineVars.staffnonote,multilineVars.openSlurs)}catch(err){if(\"normal_abort\"!==err)throw err}switches.hint_measures&&addHintMeasures()}},window.ABCJS||(window.ABCJS={}),window.ABCJS.parse||(window.ABCJS.parse={}),window.ABCJS.parse.parseDirective={},function(){\"use strict\";function initializeFonts(){multilineVars.annotationfont={face:\"Helvetica\",size:12,weight:\"normal\",style:\"normal\",decoration:\"none\"},multilineVars.gchordfont={face:\"Helvetica\",size:12,weight:\"normal\",style:\"normal\",decoration:\"none\"},multilineVars.historyfont={face:'\"Times New Roman\"',size:16,weight:\"normal\",style:\"normal\",decoration:\"none\"},multilineVars.infofont={face:'\"Times New Roman\"',size:14,weight:\"normal\",style:\"italic\",decoration:\"none\"},multilineVars.measurefont={face:'\"Times New Roman\"',size:14,weight:\"normal\",style:\"italic\",decoration:\"none\"},multilineVars.partsfont={face:'\"Times New Roman\"',size:15,weight:\"normal\",style:\"normal\",decoration:\"none\"},multilineVars.repeatfont={face:'\"Times New Roman\"',size:13,weight:\"normal\",style:\"normal\",decoration:\"none\"},multilineVars.textfont={face:'\"Times New Roman\"',size:16,weight:\"normal\",style:\"normal\",decoration:\"none\"},multilineVars.vocalfont={face:'\"Times New Roman\"',size:13,weight:\"bold\",style:\"normal\",decoration:\"none\"},multilineVars.wordsfont={face:'\"Times New Roman\"',size:16,weight:\"normal\",style:\"normal\",decoration:\"none\"},tune.formatting.composerfont={face:'\"Times New Roman\"',size:14,weight:\"normal\",style:\"italic\",decoration:\"none\"},tune.formatting.subtitlefont={face:'\"Times New Roman\"',size:16,weight:\"normal\",style:\"normal\",decoration:\"none\"},tune.formatting.tempofont={face:'\"Times New Roman\"',size:15,weight:\"bold\",style:\"normal\",decoration:\"none\"},tune.formatting.titlefont={face:'\"Times New Roman\"',size:20,weight:\"normal\",style:\"normal\",decoration:\"none\"},tune.formatting.footerfont={face:'\"Times New Roman\"',size:12,weight:\"normal\",style:\"normal\",decoration:\"none\"},tune.formatting.headerfont={face:'\"Times New Roman\"',size:12,weight:\"normal\",style:\"normal\",decoration:\"none\"},tune.formatting.voicefont={face:'\"Times New Roman\"',size:13,weight:\"bold\",style:\"normal\",decoration:\"none\"},tune.formatting.annotationfont=multilineVars.annotationfont,tune.formatting.gchordfont=multilineVars.gchordfont,tune.formatting.historyfont=multilineVars.historyfont,tune.formatting.infofont=multilineVars.infofont,\ntune.formatting.measurefont=multilineVars.measurefont,tune.formatting.partsfont=multilineVars.partsfont,tune.formatting.repeatfont=multilineVars.repeatfont,tune.formatting.textfont=multilineVars.textfont,tune.formatting.vocalfont=multilineVars.vocalfont,tune.formatting.wordsfont=multilineVars.wordsfont}var tokenizer,warn,multilineVars,tune;window.ABCJS.parse.parseDirective.initialize=function(tokenizer_,warn_,multilineVars_,tune_){tokenizer=tokenizer_,warn=warn_,multilineVars=multilineVars_,tune=tune_,initializeFonts()};var fontTypeCanHaveBox={gchordfont:!0,measurefont:!0,partsfont:!0},fontTranslation=function(fontFace){switch(fontFace){case\"Arial-Italic\":return{face:\"Arial\",weight:\"normal\",style:\"italic\",decoration:\"none\"};case\"Arial-Bold\":return{face:\"Arial\",weight:\"bold\",style:\"normal\",decoration:\"none\"};case\"Bookman-Demi\":return{face:\"Bookman,serif\",weight:\"bold\",style:\"normal\",decoration:\"none\"};case\"Bookman-DemiItalic\":return{face:\"Bookman,serif\",weight:\"bold\",style:\"italic\",decoration:\"none\"};case\"Bookman-Light\":return{face:\"Bookman,serif\",weight:\"normal\",style:\"normal\",decoration:\"none\"};case\"Bookman-LightItalic\":return{face:\"Bookman,serif\",weight:\"normal\",style:\"italic\",decoration:\"none\"};case\"Courier\":return{face:'\"Courier New\"',weight:\"normal\",style:\"normal\",decoration:\"none\"};case\"Courier-Oblique\":return{face:'\"Courier New\"',weight:\"normal\",style:\"italic\",decoration:\"none\"};case\"Courier-Bold\":return{face:'\"Courier New\"',weight:\"bold\",style:\"normal\",decoration:\"none\"};case\"Courier-BoldOblique\":return{face:'\"Courier New\"',weight:\"bold\",style:\"italic\",decoration:\"none\"};case\"AvantGarde-Book\":return{face:\"AvantGarde,Arial\",weight:\"normal\",style:\"normal\",decoration:\"none\"};case\"AvantGarde-BookOblique\":return{face:\"AvantGarde,Arial\",weight:\"normal\",style:\"italic\",decoration:\"none\"};case\"AvantGarde-Demi\":case\"Avant-Garde-Demi\":return{face:\"AvantGarde,Arial\",weight:\"bold\",style:\"normal\",decoration:\"none\"};case\"AvantGarde-DemiOblique\":return{face:\"AvantGarde,Arial\",weight:\"bold\",style:\"italic\",decoration:\"none\"};case\"Helvetica-Oblique\":return{face:\"Helvetica\",weight:\"normal\",style:\"italic\",decoration:\"none\"};case\"Helvetica-Bold\":return{face:\"Helvetica\",weight:\"bold\",style:\"normal\",decoration:\"none\"};case\"Helvetica-BoldOblique\":return{face:\"Helvetica\",weight:\"bold\",style:\"italic\",decoration:\"none\"};case\"Helvetica-Narrow\":return{face:'\"Helvetica Narrow\",Helvetica',weight:\"normal\",style:\"normal\",decoration:\"none\"};case\"Helvetica-Narrow-Oblique\":return{face:'\"Helvetica Narrow\",Helvetica',weight:\"normal\",style:\"italic\",decoration:\"none\"};case\"Helvetica-Narrow-Bold\":return{face:'\"Helvetica Narrow\",Helvetica',weight:\"bold\",style:\"normal\",decoration:\"none\"};case\"Helvetica-Narrow-BoldOblique\":return{face:'\"Helvetica Narrow\",Helvetica',weight:\"bold\",style:\"italic\",decoration:\"none\"};case\"Palatino-Roman\":return{face:\"Palatino\",weight:\"normal\",style:\"normal\",decoration:\"none\"};case\"Palatino-Italic\":return{face:\"Palatino\",weight:\"normal\",style:\"italic\",decoration:\"none\"};case\"Palatino-Bold\":return{face:\"Palatino\",weight:\"bold\",style:\"normal\",decoration:\"none\"};case\"Palatino-BoldItalic\":return{face:\"Palatino\",weight:\"bold\",style:\"italic\",decoration:\"none\"};case\"NewCenturySchlbk-Roman\":return{face:'\"New Century\",serif',weight:\"normal\",style:\"normal\",decoration:\"none\"};case\"NewCenturySchlbk-Italic\":return{face:'\"New Century\",serif',weight:\"normal\",style:\"italic\",decoration:\"none\"};case\"NewCenturySchlbk-Bold\":return{face:'\"New Century\",serif',weight:\"bold\",style:\"normal\",decoration:\"none\"};case\"NewCenturySchlbk-BoldItalic\":return{face:'\"New Century\",serif',weight:\"bold\",style:\"italic\",decoration:\"none\"};case\"Times\":case\"Times-Roman\":case\"Times-Narrow\":case\"Times-Courier\":case\"Times-New-Roman\":return{face:'\"Times New Roman\"',weight:\"normal\",style:\"normal\",decoration:\"none\"};case\"Times-Italic\":case\"Times-Italics\":return{face:'\"Times New Roman\"',weight:\"normal\",style:\"italic\",decoration:\"none\"};case\"Times-Bold\":return{face:'\"Times New Roman\"',weight:\"bold\",style:\"normal\",decoration:\"none\"};case\"Times-BoldItalic\":return{face:'\"Times New Roman\"',weight:\"bold\",style:\"italic\",decoration:\"none\"};case\"ZapfChancery-MediumItalic\":return{face:'\"Zapf Chancery\",cursive,serif',weight:\"normal\",style:\"normal\",decoration:\"none\"};default:return null}},getFontParameter=function(tokens,currentSetting,str,position,cmd){function processNumberOnly(){var size=parseInt(tokens[0].token);return tokens.shift(),currentSetting?0===tokens.length?{face:currentSetting.face,weight:currentSetting.weight,style:currentSetting.style,decoration:currentSetting.decoration,size:size}:1===tokens.length&&\"box\"===tokens[0].token&&fontTypeCanHaveBox[cmd]?{face:currentSetting.face,weight:currentSetting.weight,style:currentSetting.style,decoration:currentSetting.decoration,size:size,box:!0}:(warn(\"Extra parameters in font definition.\",str,position),{face:currentSetting.face,weight:currentSetting.weight,style:currentSetting.style,decoration:currentSetting.decoration,size:size}):(warn(\"Can't set just the size of the font since there is no default value.\",str,position),{face:'\"Times New Roman\"',weight:\"normal\",style:\"normal\",decoration:\"none\",size:size})}if(\"*\"===tokens[0].token){if(tokens.shift(),\"number\"===tokens[0].type)return processNumberOnly();warn(\"Expected font size number after *.\",str,position)}if(\"number\"===tokens[0].type)return processNumberOnly();for(var size,face=[],weight=\"normal\",style=\"normal\",decoration=\"none\",box=!1,state=\"face\",hyphenLast=!1;tokens.length;){var currToken=tokens.shift(),word=currToken.token.toLowerCase();switch(state){case\"face\":hyphenLast||\"utf\"!==word&&\"number\"!==currToken.type&&\"bold\"!==word&&\"italic\"!==word&&\"underline\"!==word&&\"box\"!==word?face.length>0&&\"-\"===currToken.token?(hyphenLast=!0,face[face.length-1]=face[face.length-1]+currToken.token):hyphenLast?(hyphenLast=!1,face[face.length-1]=face[face.length-1]+currToken.token):face.push(currToken.token):\"number\"===currToken.type?(size?warn(\"Font size specified twice in font definition.\",str,position):size=currToken.token,state=\"modifier\"):\"bold\"===word?weight=\"bold\":\"italic\"===word?style=\"italic\":\"underline\"===word?decoration=\"underline\":\"box\"===word?(fontTypeCanHaveBox[cmd]?box=!0:warn('This font style doesn\\'t support \"box\"',str,position),state=\"finished\"):\"utf\"===word?(currToken=tokens.shift(),state=\"size\"):warn(\"Unknown parameter \"+currToken.token+\" in font definition.\",str,position);break;case\"size\":\"number\"===currToken.type?size?warn(\"Font size specified twice in font definition.\",str,position):size=currToken.token:warn(\"Expected font size in font definition.\",str,position),state=\"modifier\";break;case\"modifier\":\"bold\"===word?weight=\"bold\":\"italic\"===word?style=\"italic\":\"underline\"===word?decoration=\"underline\":\"box\"===word?(fontTypeCanHaveBox[cmd]?box=!0:warn('This font style doesn\\'t support \"box\"',str,position),state=\"finished\"):warn(\"Unknown parameter \"+currToken.token+\" in font definition.\",str,position);break;case\"finished\":warn('Extra characters found after \"box\" in font definition.',str,position)}}void 0===size?currentSetting?size=currentSetting.size:(warn(\"Must specify the size of the font since there is no default value.\",str,position),size=12):size=parseFloat(size),face=face.join(\" \");var psFont=fontTranslation(face),font={};return psFont?(font.face=psFont.face,font.weight=psFont.weight,font.style=psFont.style,font.decoration=psFont.decoration,font.size=size,box&&(font.box=!0),font):(font.face=face,font.weight=weight,font.style=style,font.decoration=decoration,font.size=size,box&&(font.box=!0),font)},getChangingFont=function(cmd,tokens,str){return 0===tokens.length?'Directive \"'+cmd+'\" requires a font as a parameter.':(multilineVars[cmd]=getFontParameter(tokens,multilineVars[cmd],str,0,cmd),multilineVars.is_in_header&&(tune.formatting[cmd]=multilineVars[cmd]),null)},getGlobalFont=function(cmd,tokens,str){return 0===tokens.length?'Directive \"'+cmd+'\" requires a font as a parameter.':(tune.formatting[cmd]=getFontParameter(tokens,tune.formatting[cmd],str,0,cmd),null)},setScale=function(cmd,tokens){var scratch=\"\";window.ABCJS.parse.each(tokens,function(tok){scratch+=tok.token});var num=parseFloat(scratch);return isNaN(num)||0===num?'Directive \"'+cmd+'\" requires a number as a parameter.':void(tune.formatting.scale=num)},getRequiredMeasurement=function(cmd,tokens){var points=tokenizer.getMeasurement(tokens);return 0===points.used||0!==tokens.length?{error:'Directive \"'+cmd+'\" requires a measurement as a parameter.'}:points.value},oneParameterMeasurement=function(cmd,tokens){var points=tokenizer.getMeasurement(tokens);return 0===points.used||0!==tokens.length?'Directive \"'+cmd+'\" requires a measurement as a parameter.':(tune.formatting[cmd]=points.value,null)},addMultilineVar=function(key,cmd,tokens,min,max){if(1!==tokens.length||\"number\"!==tokens[0].type)return'Directive \"'+cmd+'\" requires a number as a parameter.';var i=tokens[0].intt;return void 0!==min&&i<min?'Directive \"'+cmd+'\" requires a number greater than or equal to '+min+\" as a parameter.\":void 0!==max&&i>max?'Directive \"'+cmd+'\" requires a number less than or equal to '+max+\" as a parameter.\":(multilineVars[key]=i,null)},addMultilineVarBool=function(key,cmd,tokens){var str=addMultilineVar(key,cmd,tokens,0,1);return null!==str?str:(multilineVars[key]=1===multilineVars[key],null)},addMultilineVarOneParamChoice=function(key,cmd,tokens,choices){if(1!==tokens.length)return'Directive \"'+cmd+'\" requires one of [ '+choices.join(\", \")+\" ] as a parameter.\";for(var choice=tokens[0].token,found=!1,i=0;!found&&i<choices.length;i++)choices[i]===choice&&(found=!0);return found?(multilineVars[key]=choice,null):'Directive \"'+cmd+'\" requires one of [ '+choices.join(\", \")+\" ] as a parameter.\"},midiCmdParam0=[\"nobarlines\",\"barlines\",\"beataccents\",\"nobeataccents\",\"droneon\",\"droneoff\",\"drumon\",\"drumoff\",\"fermatafixed\",\"fermataproportional\",\"gchordon\",\"gchordoff\",\"controlcombo\",\"temperamentnormal\",\"noportamento\"],midiCmdParam1String=[\"gchord\",\"ptstress\",\"beatstring\"],midiCmdParam1Integer=[\"bassvol\",\"chordvol\",\"c\",\"channel\",\"beatmod\",\"deltaloudness\",\"drumbars\",\"gracedivider\",\"makechordchannels\",\"randomchordattack\",\"chordattack\",\"stressmodel\",\"transpose\",\"rtranspose\",\"volinc\"],midiCmdParam1Integer1OptionalInteger=[\"program\"],midiCmdParam2Integer=[\"ratio\",\"snt\",\"bendvelocity\",\"pitchbend\",\"control\",\"temperamentlinear\"],midiCmdParam4Integer=[\"beat\"],midiCmdParam5Integer=[\"drone\"],midiCmdParam1String1Integer=[\"drummap\",\"portamento\"],midiCmdParamFraction=[\"expand\",\"grace\",\"trim\"],midiCmdParam1StringVariableIntegers=[\"drum\",\"chordname\"],parseMidiCommand=function(midi,tune,restOfString){var midi_cmd=midi.shift().token,midi_params=[];if(midiCmdParam0.indexOf(midi_cmd)>=0)0!==midi.length&&warn(\"Unexpected parameter in MIDI \"+midi_cmd,restOfString,0);else if(midiCmdParam1String.indexOf(midi_cmd)>=0)1!==midi.length?warn(\"Expected one parameter in MIDI \"+midi_cmd,restOfString,0):midi_params.push(midi[0].token);else if(midiCmdParam1Integer.indexOf(midi_cmd)>=0)1!==midi.length?warn(\"Expected one parameter in MIDI \"+midi_cmd,restOfString,0):\"number\"!==midi[0].type?warn(\"Expected one integer parameter in MIDI \"+midi_cmd,restOfString,0):midi_params.push(midi[0].intt);else if(midiCmdParam1Integer1OptionalInteger.indexOf(midi_cmd)>=0)1!==midi.length&&2!==midi.length?warn(\"Expected one or two parameters in MIDI \"+midi_cmd,restOfString,0):\"number\"!==midi[0].type?warn(\"Expected integer parameter in MIDI \"+midi_cmd,restOfString,0):2===midi.length&&\"number\"!==midi[1].type?warn(\"Expected integer parameter in MIDI \"+midi_cmd,restOfString,0):(midi_params.push(midi[0].intt),2===midi.length&&midi_params.push(midi[1].intt));else if(midiCmdParam2Integer.indexOf(midi_cmd)>=0)2!==midi.length?warn(\"Expected two parameters in MIDI \"+midi_cmd,restOfString,0):\"number\"!==midi[0].type||\"number\"!==midi[1].type?warn(\"Expected two integer parameters in MIDI \"+midi_cmd,restOfString,0):(midi_params.push(midi[0].intt),midi_params.push(midi[1].intt));else if(midiCmdParam1String1Integer.indexOf(midi_cmd)>=0)2!==midi.length?warn(\"Expected two parameters in MIDI \"+midi_cmd,restOfString,0):\"alpha\"!==midi[0].type||\"number\"!==midi[1].type?warn(\"Expected one string and one integer parameters in MIDI \"+midi_cmd,restOfString,0):(midi_params.push(midi[0].token),midi_params.push(midi[1].intt));else if(midiCmdParamFraction.indexOf(midi_cmd)>=0)3!==midi.length?warn(\"Expected fraction parameter in MIDI \"+midi_cmd,restOfString,0):\"number\"!==midi[0].type||\"/\"!==midi[1].token||\"number\"!==midi[2].type?warn(\"Expected fraction parameter in MIDI \"+midi_cmd,restOfString,0):(midi_params.push(midi[0].intt),midi_params.push(midi[2].intt));else if(midiCmdParam4Integer.indexOf(midi_cmd)>=0)4!==midi.length?warn(\"Expected four parameters in MIDI \"+midi_cmd,restOfString,0):\"number\"!==midi[0].type||\"number\"!==midi[1].type||\"number\"!==midi[2].type||\"number\"!==midi[3].type?warn(\"Expected four integer parameters in MIDI \"+midi_cmd,restOfString,0):(midi_params.push(midi[0].intt),midi_params.push(midi[1].intt),midi_params.push(midi[2].intt),midi_params.push(midi[3].intt));else if(midiCmdParam5Integer.indexOf(midi_cmd)>=0)5!==midi.length?warn(\"Expected five parameters in MIDI \"+midi_cmd,restOfString,0):\"number\"!==midi[0].type||\"number\"!==midi[1].type||\"number\"!==midi[2].type||\"number\"!==midi[3].type||\"number\"!==midi[4].type?warn(\"Expected five integer parameters in MIDI \"+midi_cmd,restOfString,0):(midi_params.push(midi[0].intt),midi_params.push(midi[1].intt),midi_params.push(midi[2].intt),midi_params.push(midi[3].intt),midi_params.push(midi[4].intt));else if(midiCmdParam1Integer1OptionalInteger.indexOf(midi_cmd)>=0)1!==midi.length||4!==midi.length?warn(\"Expected one or two parameters in MIDI \"+midi_cmd,restOfString,0):\"number\"!==midi[0].type?warn(\"Expected integer parameter in MIDI \"+midi_cmd,restOfString,0):4===midi.length?(\"octave\"!==midi[1].token&&warn(\"Expected octave parameter in MIDI \"+midi_cmd,restOfString,0),\"=\"!==midi[2].token&&warn(\"Expected octave parameter in MIDI \"+midi_cmd,restOfString,0),\"number\"!==midi[3].type&&warn(\"Expected integer parameter for octave in MIDI \"+midi_cmd,restOfString,0)):(midi_params.push(midi[0].intt),4===midi.length&&midi_params.push(midi[3].intt));else if(midiCmdParam1StringVariableIntegers.indexOf(midi_cmd)>=0)if(midi.length<2)warn(\"Expected string parameter and at least one integer parameter in MIDI \"+midi_cmd,restOfString,0);else if(\"alpha\"!==midi[0].type)warn(\"Expected string parameter and at least one integer parameter in MIDI \"+midi_cmd,restOfString,0);else{var p=midi.shift();for(midi_params.push(p.token);midi.length>0;)p=midi.shift(),\"number\"!==p.type&&warn(\"Expected integer parameter in MIDI \"+midi_cmd,restOfString,0),midi_params.push(p.intt)}tune.hasBeginMusic()?tune.appendElement(\"midi\",-1,-1,{cmd:midi_cmd,params:midi_params}):(void 0===tune.formatting.midi&&(tune.formatting.midi={}),tune.formatting.midi[midi_cmd]=midi_params)};window.ABCJS.parse.parseDirective.parseFontChangeLine=function(textstr){var textParts=textstr.split(\"$\");if(textParts.length>1&&multilineVars.setfont){for(var textarr=[{text:textParts[0]}],i=1;i<textParts.length;i++)\"0\"===textParts[i].charAt(0)?textarr.push({text:textParts[i].substring(1)}):\"1\"===textParts[i].charAt(0)&&multilineVars.setfont[1]?textarr.push({font:multilineVars.setfont[1],text:textParts[i].substring(1)}):\"2\"===textParts[i].charAt(0)&&multilineVars.setfont[2]?textarr.push({font:multilineVars.setfont[2],text:textParts[i].substring(1)}):\"3\"===textParts[i].charAt(0)&&multilineVars.setfont[3]?textarr.push({font:multilineVars.setfont[3],text:textParts[i].substring(1)}):\"4\"===textParts[i].charAt(0)&&multilineVars.setfont[4]?textarr.push({font:multilineVars.setfont[4],text:textParts[i].substring(1)}):textarr[textarr.length-1].text+=\"$\"+textParts[i];if(textarr.length>1)return textarr}return textstr};var positionChoices=[\"auto\",\"above\",\"below\",\"hidden\"];window.ABCJS.parse.parseDirective.addDirective=function(str){var tokens=tokenizer.tokenize(str,0,str.length);if(0===tokens.length||\"alpha\"!==tokens[0].type)return null;var restOfString=str.substring(str.indexOf(tokens[0].token)+tokens[0].token.length);restOfString=tokenizer.stripComment(restOfString);var cmd=tokens.shift().token.toLowerCase(),scratch=\"\";switch(cmd){case\"bagpipes\":tune.formatting.bagpipes=!0;break;case\"landscape\":multilineVars.landscape=!0;break;case\"papersize\":multilineVars.papersize=restOfString;break;case\"slurgraces\":tune.formatting.slurgraces=!0;break;case\"stretchlast\":tune.formatting.stretchlast=!0;break;case\"titlecaps\":multilineVars.titlecaps=!0;break;case\"titleleft\":tune.formatting.titleleft=!0;break;case\"measurebox\":tune.formatting.measurebox=!0;break;case\"vocal\":return addMultilineVarOneParamChoice(\"vocalPosition\",cmd,tokens,positionChoices);case\"dynamic\":return addMultilineVarOneParamChoice(\"dynamicPosition\",cmd,tokens,positionChoices);case\"gchord\":return addMultilineVarOneParamChoice(\"chordPosition\",cmd,tokens,positionChoices);case\"ornament\":return addMultilineVarOneParamChoice(\"ornamentPosition\",cmd,tokens,positionChoices);case\"volume\":return addMultilineVarOneParamChoice(\"volumePosition\",cmd,tokens,positionChoices);case\"botmargin\":case\"botspace\":case\"composerspace\":case\"indent\":case\"leftmargin\":case\"linesep\":case\"musicspace\":case\"partsspace\":case\"pageheight\":case\"pagewidth\":case\"rightmargin\":case\"staffsep\":case\"staffwidth\":case\"subtitlespace\":case\"sysstaffsep\":case\"systemsep\":case\"textspace\":case\"titlespace\":case\"topmargin\":case\"topspace\":case\"vocalspace\":case\"wordsspace\":return oneParameterMeasurement(cmd,tokens);case\"vskip\":var vskip=getRequiredMeasurement(cmd,tokens);return vskip.error?vskip.error:(tune.addSpacing(vskip),null);case\"scale\":setScale(cmd,tokens);break;case\"sep\":if(0===tokens.length)tune.addSeparator();else{var points=tokenizer.getMeasurement(tokens);if(0===points.used)return'Directive \"'+cmd+'\" requires 3 numbers: space above, space below, length of line';var spaceAbove=points.value;if(points=tokenizer.getMeasurement(tokens),0===points.used)return'Directive \"'+cmd+'\" requires 3 numbers: space above, space below, length of line';var spaceBelow=points.value;if(points=tokenizer.getMeasurement(tokens),0===points.used||0!==tokens.length)return'Directive \"'+cmd+'\" requires 3 numbers: space above, space below, length of line';var lenLine=points.value;tune.addSeparator(spaceAbove,spaceBelow,lenLine)}break;case\"barsperstaff\":if(scratch=addMultilineVar(\"barsperstaff\",cmd,tokens),null!==scratch)return scratch;break;case\"staffnonote\":if(scratch=addMultilineVarBool(\"staffnonote\",cmd,tokens),null!==scratch)return scratch;break;case\"printtempo\":if(scratch=addMultilineVarBool(\"printTempo\",cmd,tokens),null!==scratch)return scratch;break;case\"partsbox\":if(scratch=addMultilineVarBool(\"partsBox\",cmd,tokens),null!==scratch)return scratch;break;case\"measurenb\":case\"barnumbers\":if(scratch=addMultilineVar(\"barNumbers\",cmd,tokens),null!==scratch)return scratch;break;case\"begintext\":multilineVars.inTextBlock=!0;break;case\"continueall\":multilineVars.continueall=!0;break;case\"beginps\":multilineVars.inPsBlock=!0,warn(\"Postscript ignored\",str,0);break;case\"deco\":restOfString.length>0&&multilineVars.ignoredDecorations.push(restOfString.substring(0,restOfString.indexOf(\" \"))),warn(\"Decoration redefinition ignored\",str,0);break;case\"text\":var textstr=tokenizer.translateString(restOfString);tune.addText(window.ABCJS.parse.parseDirective.parseFontChangeLine(textstr));break;case\"center\":var centerstr=tokenizer.translateString(restOfString);tune.addCentered(window.ABCJS.parse.parseDirective.parseFontChangeLine(centerstr));break;case\"font\":break;case\"setfont\":var sfTokens=tokenizer.tokenize(restOfString,0,restOfString.length);if(sfTokens.length>=4&&\"-\"===sfTokens[0].token&&\"number\"===sfTokens[1].type){var sfNum=parseInt(sfTokens[1].token);sfNum>=1&&sfNum<=4&&(multilineVars.setfont||(multilineVars.setfont=[]),sfTokens.shift(),sfTokens.shift(),multilineVars.setfont[sfNum]=getFontParameter(sfTokens,multilineVars.setfont[sfNum],str,0,\"setfont\"))}break;case\"gchordfont\":case\"partsfont\":case\"vocalfont\":case\"textfont\":case\"annotationfont\":case\"historyfont\":case\"infofont\":case\"measurefont\":case\"repeatfont\":case\"wordsfont\":return getChangingFont(cmd,tokens,str);case\"composerfont\":case\"subtitlefont\":case\"tempofont\":case\"titlefont\":case\"voicefont\":case\"footerfont\":case\"headerfont\":return getGlobalFont(cmd,tokens,str);case\"barlabelfont\":case\"barnumberfont\":case\"barnumfont\":return getChangingFont(\"measurefont\",tokens,str);case\"staves\":case\"score\":multilineVars.score_is_present=!0;for(var lastVoice,addVoice=function(id,newStaff,bracket,brace,continueBar){(newStaff||0===multilineVars.staves.length)&&multilineVars.staves.push({index:multilineVars.staves.length,numVoices:0});var staff=window.ABCJS.parse.last(multilineVars.staves);void 0!==bracket&&(staff.bracket=bracket),void 0!==brace&&(staff.brace=brace),continueBar&&(staff.connectBarLines=\"end\"),void 0===multilineVars.voices[id]&&(multilineVars.voices[id]={staffNum:staff.index,index:staff.numVoices},staff.numVoices++)},openParen=!1,openBracket=!1,openBrace=!1,justOpenParen=!1,justOpenBracket=!1,justOpenBrace=!1,continueBar=!1,addContinueBar=function(){if(continueBar=!0,lastVoice){var ty=\"start\";lastVoice.staffNum>0&&(\"start\"!==multilineVars.staves[lastVoice.staffNum-1].connectBarLines&&\"continue\"!==multilineVars.staves[lastVoice.staffNum-1].connectBarLines||(ty=\"continue\")),multilineVars.staves[lastVoice.staffNum].connectBarLines=ty}};tokens.length;){var t=tokens.shift();switch(t.token){case\"(\":openParen?warn(\"Can't nest parenthesis in %%score\",str,t.start):(openParen=!0,justOpenParen=!0);break;case\")\":!openParen||justOpenParen?warn(\"Unexpected close parenthesis in %%score\",str,t.start):openParen=!1;break;case\"[\":openBracket?warn(\"Can't nest brackets in %%score\",str,t.start):(openBracket=!0,justOpenBracket=!0);break;case\"]\":!openBracket||justOpenBracket?warn(\"Unexpected close bracket in %%score\",str,t.start):(openBracket=!1,multilineVars.staves[lastVoice.staffNum].bracket=\"end\");break;case\"{\":openBrace?warn(\"Can't nest braces in %%score\",str,t.start):(openBrace=!0,justOpenBrace=!0);break;case\"}\":!openBrace||justOpenBrace?warn(\"Unexpected close brace in %%score\",str,t.start):(openBrace=!1,multilineVars.staves[lastVoice.staffNum].brace=\"end\");break;case\"|\":addContinueBar();break;default:for(var vc=\"\";(\"alpha\"===t.type||\"number\"===t.type)&&(vc+=t.token,t.continueId);)t=tokens.shift();var newStaff=!openParen||justOpenParen,bracket=justOpenBracket?\"start\":openBracket?\"continue\":void 0,brace=justOpenBrace?\"start\":openBrace?\"continue\":void 0;addVoice(vc,newStaff,bracket,brace,continueBar),justOpenParen=!1,justOpenBracket=!1,justOpenBrace=!1,continueBar=!1,lastVoice=multilineVars.voices[vc],\"staves\"===cmd&&addContinueBar()}}break;case\"newpage\":var pgNum=tokenizer.getInt(restOfString);tune.addNewPage(0===pgNum.digits?-1:pgNum.value);break;case\"abc\":var arr=restOfString.split(\" \");switch(arr[0]){case\"-copyright\":case\"-creator\":case\"-edited-by\":case\"-version\":case\"-charset\":var subCmd=arr.shift();tune.addMetaText(cmd+subCmd,arr.join(\" \"));break;default:return\"Unknown directive: \"+cmd+arr[0]}break;case\"header\":case\"footer\":var footerStr=tokenizer.getMeat(restOfString,0,restOfString.length);footerStr=restOfString.substring(footerStr.start,footerStr.end),'\"'===footerStr.charAt(0)&&'\"'===footerStr.charAt(footerStr.length-1)&&(footerStr=footerStr.substring(1,footerStr.length-1));var footerArr=footerStr.split(\"\\t\"),footer={};footer=1===footerArr.length?{left:\"\",center:footerArr[0],right:\"\"}:2===footerArr.length?{left:footerArr[0],center:footerArr[1],right:\"\"}:{left:footerArr[0],center:footerArr[1],right:footerArr[2]},footerArr.length>3&&warn(\"Too many tabs in \"+cmd+\": \"+footerArr.length+\" found.\",restOfString,0),tune.addMetaTextObj(cmd,footer);break;case\"midi\":var midi=tokenizer.tokenize(restOfString,0,restOfString.length,!0);midi.length>0&&\"=\"===midi[0].token&&midi.shift(),0===midi.length?warn(\"Expected midi command\",restOfString,0):parseMidiCommand(midi,tune,restOfString);break;case\"playtempo\":case\"auquality\":case\"continuous\":case\"nobarcheck\":tune.formatting[cmd]=restOfString;break;default:return\"Unknown directive: \"+cmd}return null},window.ABCJS.parse.parseDirective.globalFormatting=function(formatHash){for(var cmd in formatHash)if(formatHash.hasOwnProperty(cmd)){var scratch,value=\"\"+formatHash[cmd],tokens=tokenizer.tokenize(value,0,value.length);switch(cmd){case\"titlefont\":case\"gchordfont\":getChangingFont(cmd,tokens,value);break;case\"scale\":setScale(cmd,tokens);break;case\"partsbox\":scratch=addMultilineVarBool(\"partsBox\",cmd,tokens),null!==scratch&&warn(scratch);break;default:warn(\"Formatting directive unrecognized: \",cmd,0)}}}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.parse||(window.ABCJS.parse={}),window.ABCJS.parse.ParseHeader=function(tokenizer,warn,multilineVars,tune){this.reset=function(tokenizer,warn,multilineVars,tune){window.ABCJS.parse.parseKeyVoice.initialize(tokenizer,warn,multilineVars,tune),window.ABCJS.parse.parseDirective.initialize(tokenizer,warn,multilineVars,tune)},this.reset(tokenizer,warn,multilineVars,tune),this.setTitle=function(title){if(multilineVars.hasMainTitle)tune.addSubtitle(tokenizer.translateString(tokenizer.stripComment(title)));else{var titleStr=tokenizer.translateString(tokenizer.theReverser(tokenizer.stripComment(title)));multilineVars.titlecaps&&(titleStr=titleStr.toUpperCase()),tune.addMetaText(\"title\",titleStr),multilineVars.hasMainTitle=!0}},this.setMeter=function(line){if(line=tokenizer.stripComment(line),\"C\"===line)return multilineVars.havent_set_length===!0&&(multilineVars.default_length=.125),{type:\"common_time\"};if(\"C|\"===line)return multilineVars.havent_set_length===!0&&(multilineVars.default_length=.125),{type:\"cut_time\"};if(\"o\"===line)return multilineVars.havent_set_length===!0&&(multilineVars.default_length=.125),{type:\"tempus_perfectum\"};if(\"c\"===line)return multilineVars.havent_set_length===!0&&(multilineVars.default_length=.125),{type:\"tempus_imperfectum\"};if(\"o.\"===line)return multilineVars.havent_set_length===!0&&(multilineVars.default_length=.125),{type:\"tempus_perfectum_prolatio\"};if(\"c.\"===line)return multilineVars.havent_set_length===!0&&(multilineVars.default_length=.125),{type:\"tempus_imperfectum_prolatio\"};if(0===line.length||\"none\"===line.toLowerCase())return multilineVars.havent_set_length===!0&&(multilineVars.default_length=.125),null;var tokens=tokenizer.tokenize(line,0,line.length);try{var parseNum=function(){var ret={value:0,num:\"\"},tok=tokens.shift();for(\"(\"===tok.token&&(tok=tokens.shift());;){if(\"number\"!==tok.type)throw\"Expected top number of meter\";if(ret.value+=parseInt(tok.token),ret.num+=tok.token,0===tokens.length||\"/\"===tokens[0].token)return ret;if(tok=tokens.shift(),\")\"===tok.token){if(0===tokens.length||\"/\"===tokens[0].token)return ret;throw\"Unexpected paren in meter\"}if(\".\"!==tok.token&&\"+\"!==tok.token)throw\"Expected top number of meter\";if(ret.num+=tok.token,0===tokens.length)throw\"Expected top number of meter\";tok=tokens.shift()}return ret},parseFraction=function(){var ret=parseNum();if(0===tokens.length)return ret;var tok=tokens.shift();if(\"/\"!==tok.token)throw\"Expected slash in meter\";if(tok=tokens.shift(),\"number\"!==tok.type)throw\"Expected bottom number of meter\";return ret.den=tok.token,ret.value=ret.value/parseInt(ret.den),ret};if(0===tokens.length)throw\"Expected meter definition in M: line\";for(var meter={type:\"specified\",value:[]},totalLength=0;;){var ret=parseFraction();totalLength+=ret.value;var mv={num:ret.num};if(void 0!==ret.den&&(mv.den=ret.den),meter.value.push(mv),0===tokens.length)break}return multilineVars.havent_set_length===!0&&(multilineVars.default_length=totalLength<.75?.0625:.125),meter}catch(e){warn(e,line,0)}return null},this.calcTempo=function(relTempo){var dur=.25;multilineVars.meter&&\"specified\"===multilineVars.meter.type?dur=1/parseInt(multilineVars.meter.value[0].den):multilineVars.origMeter&&\"specified\"===multilineVars.origMeter.type&&(dur=1/parseInt(multilineVars.origMeter.value[0].den));for(var i=0;i<relTempo.duration;i++)relTempo.duration[i]=dur*relTempo.duration[i];return relTempo},this.resolveTempo=function(){multilineVars.tempo&&(this.calcTempo(multilineVars.tempo),tune.metaText.tempo=multilineVars.tempo,delete multilineVars.tempo)},this.addUserDefinition=function(line,start,end){var equals=line.indexOf(\"=\",start);if(equals===-1)return void warn(\"Need an = in a macro definition\",line,start);var before=window.ABCJS.parse.strip(line.substring(start,equals)),after=window.ABCJS.parse.strip(line.substring(equals+1));if(1!==before.length)return void warn(\"Macro definitions can only be one character\",line,start);var legalChars=\"HIJKLMNOPQRSTUVWXYhijklmnopqrstuvw~\";return legalChars.indexOf(before)===-1?void warn(\"Macro definitions must be H-Y, h-w, or tilde\",line,start):0===after.length?void warn(\"Missing macro definition\",line,start):(void 0===multilineVars.macros&&(multilineVars.macros={}),void(multilineVars.macros[before]=after))},this.setDefaultLength=function(line,start,end){var len=window.ABCJS.parse.gsub(line.substring(start,end),\" \",\"\"),len_arr=len.split(\"/\");if(2===len_arr.length){var n=parseInt(len_arr[0]),d=parseInt(len_arr[1]);d>0&&(multilineVars.default_length=n/d,multilineVars.havent_set_length=!1)}},this.setTempo=function(line,start,end){try{var tokens=tokenizer.tokenize(line,start,end);if(0===tokens.length)throw\"Missing parameter in Q: field\";var tempo={},delaySet=!0,token=tokens.shift();if(\"quote\"===token.type&&(tempo.preString=token.token,token=tokens.shift(),0===tokens.length))return{type:\"immediate\",tempo:tempo};if(\"alpha\"===token.type&&\"C\"===token.token){if(0===tokens.length)throw\"Missing tempo after C in Q: field\";if(token=tokens.shift(),\"punct\"===token.type&&\"=\"===token.token){if(0===tokens.length)throw\"Missing tempo after = in Q: field\";if(token=tokens.shift(),\"number\"!==token.type)throw\"Expected number after = in Q: field\";tempo.duration=[1],tempo.bpm=parseInt(token.token)}else{if(\"number\"!==token.type)throw\"Expected number or equal after C in Q: field\";if(tempo.duration=[parseInt(token.token)],0===tokens.length)throw\"Missing = after duration in Q: field\";if(token=tokens.shift(),\"punct\"!==token.type||\"=\"!==token.token)throw\"Expected = after duration in Q: field\";if(0===tokens.length)throw\"Missing tempo after = in Q: field\";if(token=tokens.shift(),\"number\"!==token.type)throw\"Expected number after = in Q: field\";tempo.bpm=parseInt(token.token)}}else{if(\"number\"!==token.type)throw\"Unknown value in Q: field\";var num=parseInt(token.token);if(0===tokens.length||\"quote\"===tokens[0].type)tempo.duration=[1],tempo.bpm=num;else{if(delaySet=!1,token=tokens.shift(),\"punct\"!==token.type&&\"/\"!==token.token)throw\"Expected fraction in Q: field\";if(token=tokens.shift(),\"number\"!==token.type)throw\"Expected fraction in Q: field\";var den=parseInt(token.token);for(tempo.duration=[num/den];tokens.length>0&&\"=\"!==tokens[0].token&&\"quote\"!==tokens[0].type;){if(token=tokens.shift(),\"number\"!==token.type)throw\"Expected fraction in Q: field\";if(num=parseInt(token.token),token=tokens.shift(),\"punct\"!==token.type&&\"/\"!==token.token)throw\"Expected fraction in Q: field\";if(token=tokens.shift(),\"number\"!==token.type)throw\"Expected fraction in Q: field\";den=parseInt(token.token),tempo.duration.push(num/den)}if(token=tokens.shift(),\"punct\"!==token.type&&\"=\"!==token.token)throw\"Expected = in Q: field\";if(token=tokens.shift(),\"number\"!==token.type)throw\"Expected tempo in Q: field\";tempo.bpm=parseInt(token.token)}}if(0!==tokens.length&&(token=tokens.shift(),\"quote\"===token.type&&(tempo.postString=token.token,token=tokens.shift()),0!==tokens.length))throw\"Unexpected string at end of Q: field\";return multilineVars.printTempo===!1&&(tempo.suppress=!0),{type:delaySet?\"delaySet\":\"immediate\",tempo:tempo}}catch(msg){return warn(msg,line,start),{type:\"none\"}}},this.letter_to_inline_header=function(line,i){var ws=tokenizer.eatWhiteSpace(line,i);\nif(i+=ws,line.length>=i+5&&\"[\"===line.charAt(i)&&\":\"===line.charAt(i+2)){var e=line.indexOf(\"]\",i);switch(line.substring(i,i+3)){case\"[I:\":var err=window.ABCJS.parse.parseDirective.addDirective(line.substring(i+3,e));return err&&warn(err,line,i),[e-i+1+ws];case\"[M:\":var meter=this.setMeter(line.substring(i+3,e));return tune.hasBeginMusic()&&meter?tune.appendStartingElement(\"meter\",-1,-1,meter):multilineVars.meter=meter,[e-i+1+ws];case\"[K:\":var result=window.ABCJS.parse.parseKeyVoice.parseKey(line.substring(i+3,e));return result.foundClef&&tune.hasBeginMusic()&&tune.appendStartingElement(\"clef\",-1,-1,multilineVars.clef),result.foundKey&&tune.hasBeginMusic()&&tune.appendStartingElement(\"key\",-1,-1,window.ABCJS.parse.parseKeyVoice.fixKey(multilineVars.clef,multilineVars.key)),[e-i+1+ws];case\"[P:\":return tune.lines.length<=tune.lineNum?multilineVars.partForNextLine=line.substring(i+3,e):tune.appendElement(\"part\",-1,-1,{title:line.substring(i+3,e)}),[e-i+1+ws];case\"[L:\":return this.setDefaultLength(line,i+3,e),[e-i+1+ws];case\"[Q:\":if(e>0){var tempo=this.setTempo(line,i+3,e);return\"delaySet\"===tempo.type?tune.appendElement(\"tempo\",-1,-1,this.calcTempo(tempo.tempo)):\"immediate\"===tempo.type&&tune.appendElement(\"tempo\",-1,-1,tempo.tempo),[e-i+1+ws,line.charAt(i+1),line.substring(i+3,e)]}break;case\"[V:\":if(e>0)return window.ABCJS.parse.parseKeyVoice.parseVoice(line,i+3,e),[e-i+1+ws,line.charAt(i+1),line.substring(i+3,e)]}}return[0]},this.letter_to_body_header=function(line,i){if(line.length>=i+3)switch(line.substring(i,i+2)){case\"I:\":var err=window.ABCJS.parse.parseDirective.addDirective(line.substring(i+2));return err&&warn(err,line,i),[line.length];case\"M:\":var meter=this.setMeter(line.substring(i+2));return tune.hasBeginMusic()&&meter&&tune.appendStartingElement(\"meter\",-1,-1,meter),[line.length];case\"K:\":var result=window.ABCJS.parse.parseKeyVoice.parseKey(line.substring(i+2));return result.foundClef&&tune.hasBeginMusic()&&tune.appendStartingElement(\"clef\",-1,-1,multilineVars.clef),result.foundKey&&tune.hasBeginMusic()&&tune.appendStartingElement(\"key\",-1,-1,window.ABCJS.parse.parseKeyVoice.fixKey(multilineVars.clef,multilineVars.key)),[line.length];case\"P:\":return tune.hasBeginMusic()&&tune.appendElement(\"part\",-1,-1,{title:line.substring(i+2)}),[line.length];case\"L:\":return this.setDefaultLength(line,i+2,line.length),[line.length];case\"Q:\":var e=line.indexOf(\"\u0012\",i+2);e===-1&&(e=line.length);var tempo=this.setTempo(line,i+2,e);return\"delaySet\"===tempo.type?tune.appendElement(\"tempo\",-1,-1,this.calcTempo(tempo.tempo)):\"immediate\"===tempo.type&&tune.appendElement(\"tempo\",-1,-1,tempo.tempo),[e,line.charAt(i),window.ABCJS.parse.strip(line.substring(i+2))];case\"V:\":return window.ABCJS.parse.parseKeyVoice.parseVoice(line,2,line.length),[line.length,line.charAt(i),window.ABCJS.parse(line.substring(i+2))]}return[0]};var metaTextHeaders={A:\"author\",B:\"book\",C:\"composer\",D:\"discography\",F:\"url\",G:\"group\",I:\"instruction\",N:\"notes\",O:\"origin\",R:\"rhythm\",S:\"source\",W:\"unalignedWords\",Z:\"transcription\"};this.parseHeader=function(line){if(window.ABCJS.parse.startsWith(line,\"%%\")){var err=window.ABCJS.parse.parseDirective.addDirective(line.substring(2));return err&&warn(err,line,2),{}}var i=line.indexOf(\"%\");if(i>=0&&(line=line.substring(0,i)),line=line.replace(/\\s+$/,\"\"),0===line.length)return{};if(line.length>=2&&\":\"===line.charAt(1)){var nextLine=\"\";line.indexOf(\"\u0012\")>=0&&\"w\"!==line.charAt(0)&&(nextLine=line.substring(line.indexOf(\"\u0012\")+1),line=line.substring(0,line.indexOf(\"\u0012\")));var field=metaTextHeaders[line.charAt(0)];if(void 0!==field)return\"unalignedWords\"===field?tune.addMetaTextArray(field,window.ABCJS.parse.parseDirective.parseFontChangeLine(tokenizer.translateString(tokenizer.stripComment(line.substring(2))))):tune.addMetaText(field,tokenizer.translateString(tokenizer.stripComment(line.substring(2)))),{};switch(line.charAt(0)){case\"H\":tune.addMetaText(\"history\",tokenizer.translateString(tokenizer.stripComment(line.substring(2)))),multilineVars.is_in_history=!0;break;case\"K\":this.resolveTempo();var result=window.ABCJS.parse.parseKeyVoice.parseKey(line.substring(2));!multilineVars.is_in_header&&tune.hasBeginMusic()&&(result.foundClef&&tune.appendStartingElement(\"clef\",-1,-1,multilineVars.clef),result.foundKey&&tune.appendStartingElement(\"key\",-1,-1,window.ABCJS.parse.parseKeyVoice.fixKey(multilineVars.clef,multilineVars.key))),multilineVars.is_in_header=!1;break;case\"L\":this.setDefaultLength(line,2,line.length);break;case\"M\":multilineVars.origMeter=multilineVars.meter=this.setMeter(line.substring(2));break;case\"P\":multilineVars.is_in_header?tune.addMetaText(\"partOrder\",tokenizer.translateString(tokenizer.stripComment(line.substring(2)))):multilineVars.partForNextLine=tokenizer.translateString(tokenizer.stripComment(line.substring(2)));break;case\"Q\":var tempo=this.setTempo(line,2,line.length);\"delaySet\"===tempo.type?multilineVars.tempo=tempo.tempo:\"immediate\"===tempo.type&&(tune.metaText.tempo=tempo.tempo);break;case\"T\":this.setTitle(line.substring(2));break;case\"U\":this.addUserDefinition(line,2,line.length);break;case\"V\":if(window.ABCJS.parse.parseKeyVoice.parseVoice(line,2,line.length),!multilineVars.is_in_header)return{newline:!0};break;case\"s\":return{symbols:!0};case\"w\":return{words:!0};case\"X\":break;case\"E\":case\"m\":warn(\"Ignored header\",line,0);break;default:return nextLine.length&&(nextLine=\"\u0012\"+nextLine),{regular:!0,str:line+nextLine}}return nextLine.length>0?{recurse:!0,str:nextLine}:{}}return{regular:!0,str:line}}},window.ABCJS||(window.ABCJS={}),window.ABCJS.parse||(window.ABCJS.parse={}),window.ABCJS.parse.parseKeyVoice={},function(){var tokenizer,warn,multilineVars,tune;window.ABCJS.parse.parseKeyVoice.initialize=function(tokenizer_,warn_,multilineVars_,tune_){tokenizer=tokenizer_,warn=warn_,multilineVars=multilineVars_,tune=tune_},window.ABCJS.parse.parseKeyVoice.standardKey=function(keyName){var key1sharp={acc:\"sharp\",note:\"f\"},key2sharp={acc:\"sharp\",note:\"c\"},key3sharp={acc:\"sharp\",note:\"g\"},key4sharp={acc:\"sharp\",note:\"d\"},key5sharp={acc:\"sharp\",note:\"A\"},key6sharp={acc:\"sharp\",note:\"e\"},key7sharp={acc:\"sharp\",note:\"B\"},key1flat={acc:\"flat\",note:\"B\"},key2flat={acc:\"flat\",note:\"e\"},key3flat={acc:\"flat\",note:\"A\"},key4flat={acc:\"flat\",note:\"d\"},key5flat={acc:\"flat\",note:\"G\"},key6flat={acc:\"flat\",note:\"c\"},key7flat={acc:\"flat\",note:\"F\"},keys={\"C#\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp,key7sharp],\"A#m\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp,key7sharp],\"G#Mix\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp,key7sharp],\"D#Dor\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp,key7sharp],\"E#Phr\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp,key7sharp],\"F#Lyd\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp,key7sharp],\"B#Loc\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp,key7sharp],\"F#\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp],\"D#m\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp],\"C#Mix\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp],\"G#Dor\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp],\"A#Phr\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp],BLyd:[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp],\"E#Loc\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp],B:[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp],\"G#m\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp],\"F#Mix\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp],\"C#Dor\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp],\"D#Phr\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp],ELyd:[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp],\"A#Loc\":[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp],E:[key1sharp,key2sharp,key3sharp,key4sharp],\"C#m\":[key1sharp,key2sharp,key3sharp,key4sharp],BMix:[key1sharp,key2sharp,key3sharp,key4sharp],\"F#Dor\":[key1sharp,key2sharp,key3sharp,key4sharp],\"G#Phr\":[key1sharp,key2sharp,key3sharp,key4sharp],ALyd:[key1sharp,key2sharp,key3sharp,key4sharp],\"D#Loc\":[key1sharp,key2sharp,key3sharp,key4sharp],A:[key1sharp,key2sharp,key3sharp],\"F#m\":[key1sharp,key2sharp,key3sharp],EMix:[key1sharp,key2sharp,key3sharp],BDor:[key1sharp,key2sharp,key3sharp],\"C#Phr\":[key1sharp,key2sharp,key3sharp],DLyd:[key1sharp,key2sharp,key3sharp],\"G#Loc\":[key1sharp,key2sharp,key3sharp],D:[key1sharp,key2sharp],Bm:[key1sharp,key2sharp],AMix:[key1sharp,key2sharp],EDor:[key1sharp,key2sharp],\"F#Phr\":[key1sharp,key2sharp],GLyd:[key1sharp,key2sharp],\"C#Loc\":[key1sharp,key2sharp],G:[key1sharp],Em:[key1sharp],DMix:[key1sharp],ADor:[key1sharp],BPhr:[key1sharp],CLyd:[key1sharp],\"F#Loc\":[key1sharp],C:[],Am:[],GMix:[],DDor:[],EPhr:[],FLyd:[],BLoc:[],F:[key1flat],Dm:[key1flat],CMix:[key1flat],GDor:[key1flat],APhr:[key1flat],BbLyd:[key1flat],ELoc:[key1flat],Bb:[key1flat,key2flat],Gm:[key1flat,key2flat],FMix:[key1flat,key2flat],CDor:[key1flat,key2flat],DPhr:[key1flat,key2flat],EbLyd:[key1flat,key2flat],ALoc:[key1flat,key2flat],Eb:[key1flat,key2flat,key3flat],Cm:[key1flat,key2flat,key3flat],BbMix:[key1flat,key2flat,key3flat],FDor:[key1flat,key2flat,key3flat],GPhr:[key1flat,key2flat,key3flat],AbLyd:[key1flat,key2flat,key3flat],DLoc:[key1flat,key2flat,key3flat],Ab:[key1flat,key2flat,key3flat,key4flat],Fm:[key1flat,key2flat,key3flat,key4flat],EbMix:[key1flat,key2flat,key3flat,key4flat],BbDor:[key1flat,key2flat,key3flat,key4flat],CPhr:[key1flat,key2flat,key3flat,key4flat],DbLyd:[key1flat,key2flat,key3flat,key4flat],GLoc:[key1flat,key2flat,key3flat,key4flat],Db:[key1flat,key2flat,key3flat,key4flat,key5flat],Bbm:[key1flat,key2flat,key3flat,key4flat,key5flat],AbMix:[key1flat,key2flat,key3flat,key4flat,key5flat],EbDor:[key1flat,key2flat,key3flat,key4flat,key5flat],FPhr:[key1flat,key2flat,key3flat,key4flat,key5flat],GbLyd:[key1flat,key2flat,key3flat,key4flat,key5flat],CLoc:[key1flat,key2flat,key3flat,key4flat,key5flat],Gb:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat],Ebm:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat],DbMix:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat],AbDor:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat],BbPhr:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat],CbLyd:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat],FLoc:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat],Cb:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat,key7flat],Abm:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat,key7flat],GbMix:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat,key7flat],DbDor:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat,key7flat],EbPhr:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat,key7flat],FbLyd:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat,key7flat],BbLoc:[key1flat,key2flat,key3flat,key4flat,key5flat,key6flat,key7flat],\"A#\":[key1flat,key2flat],\"B#\":[],\"D#\":[key1flat,key2flat,key3flat],\"E#\":[key1flat],\"G#\":[key1flat,key2flat,key3flat,key4flat],Gbm:[key1sharp,key2sharp,key3sharp,key4sharp,key5sharp,key6sharp,key7sharp]};return keys[keyName]};var clefLines={treble:{clef:\"treble\",pitch:4,mid:0},\"treble+8\":{clef:\"treble+8\",pitch:4,mid:0},\"treble-8\":{clef:\"treble-8\",pitch:4,mid:0},treble1:{clef:\"treble\",pitch:2,mid:2},treble2:{clef:\"treble\",pitch:4,mid:0},treble3:{clef:\"treble\",pitch:6,mid:-2},treble4:{clef:\"treble\",pitch:8,mid:-4},treble5:{clef:\"treble\",pitch:10,mid:-6},perc:{clef:\"perc\",pitch:6,mid:0},none:{clef:\"none\",mid:0},bass:{clef:\"bass\",pitch:8,mid:-12},\"bass+8\":{clef:\"bass+8\",pitch:8,mid:-12},\"bass-8\":{clef:\"bass-8\",pitch:8,mid:-12},\"bass+16\":{clef:\"bass\",pitch:8,mid:-12},\"bass-16\":{clef:\"bass\",pitch:8,mid:-12},bass1:{clef:\"bass\",pitch:2,mid:-6},bass2:{clef:\"bass\",pitch:4,mid:-8},bass3:{clef:\"bass\",pitch:6,mid:-10},bass4:{clef:\"bass\",pitch:8,mid:-12},bass5:{clef:\"bass\",pitch:10,mid:-14},tenor:{clef:\"alto\",pitch:8,mid:-8},tenor1:{clef:\"alto\",pitch:2,mid:-2},tenor2:{clef:\"alto\",pitch:4,mid:-4},tenor3:{clef:\"alto\",pitch:6,mid:-6},tenor4:{clef:\"alto\",pitch:8,mid:-8},tenor5:{clef:\"alto\",pitch:10,mid:-10},alto:{clef:\"alto\",pitch:6,mid:-6},alto1:{clef:\"alto\",pitch:2,mid:-2},alto2:{clef:\"alto\",pitch:4,mid:-4},alto3:{clef:\"alto\",pitch:6,mid:-6},alto4:{clef:\"alto\",pitch:8,mid:-8},alto5:{clef:\"alto\",pitch:10,mid:-10},\"alto+8\":{clef:\"alto+8\",pitch:6,mid:-6},\"alto-8\":{clef:\"alto-8\",pitch:6,mid:-6}},calcMiddle=function(clef,oct){var value=clefLines[clef],mid=value?value.mid:0;return mid+oct};window.ABCJS.parse.parseKeyVoice.fixClef=function(clef){var value=clefLines[clef.type];value&&(clef.clefPos=value.pitch,clef.type=value.clef)},window.ABCJS.parse.parseKeyVoice.deepCopyKey=function(key){var ret={accidentals:[],root:key.root,acc:key.acc,mode:key.mode};return window.ABCJS.parse.each(key.accidentals,function(k){ret.accidentals.push(window.ABCJS.parse.clone(k))}),ret};var pitches={A:5,B:6,C:0,D:1,E:2,F:3,G:4,a:12,b:13,c:7,d:8,e:9,f:10,g:11};window.ABCJS.parse.parseKeyVoice.addPosToKey=function(clef,key){var mid=clef.verticalPos;window.ABCJS.parse.each(key.accidentals,function(acc){var pitch=pitches[acc.note];pitch-=mid,acc.verticalPos=pitch}),key.impliedNaturals&&window.ABCJS.parse.each(key.impliedNaturals,function(acc){var pitch=pitches[acc.note];pitch-=mid,acc.verticalPos=pitch}),mid<-10?(window.ABCJS.parse.each(key.accidentals,function(acc){acc.verticalPos-=7,(acc.verticalPos>=11||10===acc.verticalPos&&\"flat\"===acc.acc)&&(acc.verticalPos-=7),\"A\"===acc.note&&\"sharp\"===acc.acc&&(acc.verticalPos-=7),\"G\"!==acc.note&&\"F\"!==acc.note||\"flat\"!==acc.acc||(acc.verticalPos-=7)}),key.impliedNaturals&&window.ABCJS.parse.each(key.impliedNaturals,function(acc){acc.verticalPos-=7,(acc.verticalPos>=11||10===acc.verticalPos&&\"flat\"===acc.acc)&&(acc.verticalPos-=7),\"A\"===acc.note&&\"sharp\"===acc.acc&&(acc.verticalPos-=7),\"G\"!==acc.note&&\"F\"!==acc.note||\"flat\"!==acc.acc||(acc.verticalPos-=7)})):mid<-4?(window.ABCJS.parse.each(key.accidentals,function(acc){acc.verticalPos-=7,mid!==-8||\"f\"!==acc.note&&\"g\"!==acc.note||\"sharp\"!==acc.acc||(acc.verticalPos-=7)}),key.impliedNaturals&&window.ABCJS.parse.each(key.impliedNaturals,function(acc){acc.verticalPos-=7,mid!==-8||\"f\"!==acc.note&&\"g\"!==acc.note||\"sharp\"!==acc.acc||(acc.verticalPos-=7)})):mid>=7&&(window.ABCJS.parse.each(key.accidentals,function(acc){acc.verticalPos+=7}),key.impliedNaturals&&window.ABCJS.parse.each(key.impliedNaturals,function(acc){acc.verticalPos+=7}))},window.ABCJS.parse.parseKeyVoice.fixKey=function(clef,key){var fixedKey=window.ABCJS.parse.clone(key);return window.ABCJS.parse.parseKeyVoice.addPosToKey(clef,fixedKey),fixedKey};var parseMiddle=function(str){for(var mid=pitches[str.charAt(0)],i=1;i<str.length;i++)if(\",\"===str.charAt(i))mid-=7;else{if(\",\"!==str.charAt(i))break;mid+=7}return{mid:mid-6,str:str.substring(i)}},normalizeAccidentals=function(accs){for(var i=0;i<accs.length;i++)\"b\"===accs[i].note?accs[i].note=\"B\":\"a\"===accs[i].note?accs[i].note=\"A\":\"F\"===accs[i].note?accs[i].note=\"f\":\"E\"===accs[i].note?accs[i].note=\"e\":\"D\"===accs[i].note?accs[i].note=\"d\":\"C\"===accs[i].note?accs[i].note=\"c\":\"G\"===accs[i].note&&\"sharp\"===accs[i].acc?accs[i].note=\"g\":\"g\"===accs[i].note&&\"flat\"===accs[i].acc&&(accs[i].note=\"G\")};window.ABCJS.parse.parseKeyVoice.parseKey=function(str){0===str.length&&(str=\"none\");var tokens=tokenizer.tokenize(str,0,str.length),ret={};switch(tokens[0].token){case\"HP\":window.ABCJS.parse.parseDirective.addDirective(\"bagpipes\"),multilineVars.key={root:\"HP\",accidentals:[],acc:\"\",mode:\"\"},ret.foundKey=!0,tokens.shift();break;case\"Hp\":window.ABCJS.parse.parseDirective.addDirective(\"bagpipes\"),multilineVars.key={root:\"Hp\",accidentals:[{acc:\"natural\",note:\"g\"},{acc:\"sharp\",note:\"f\"},{acc:\"sharp\",note:\"c\"}],acc:\"\",mode:\"\"},ret.foundKey=!0,tokens.shift();break;case\"none\":multilineVars.key={root:\"none\",accidentals:[],acc:\"\",mode:\"\"},ret.foundKey=!0,tokens.shift();break;default:var retPitch=tokenizer.getKeyPitch(tokens[0].token);if(retPitch.len>0){ret.foundKey=!0;var acc=\"\",mode=\"\";tokens[0].token.length>1?tokens[0].token=tokens[0].token.substring(1):tokens.shift();var key=retPitch.token;if(tokens.length>0){var retAcc=tokenizer.getSharpFlat(tokens[0].token);if(retAcc.len>0&&(tokens[0].token.length>1?tokens[0].token=tokens[0].token.substring(1):tokens.shift(),key+=retAcc.token,acc=retAcc.token),tokens.length>0){var retMode=tokenizer.getMode(tokens[0].token);retMode.len>0&&(tokens.shift(),key+=retMode.token,mode=retMode.token)}if(void 0===window.ABCJS.parse.parseKeyVoice.standardKey(key))return warn(\"Unsupported key signature: \"+key,str,0),ret}var oldKey=window.ABCJS.parse.parseKeyVoice.deepCopyKey(multilineVars.key);if(multilineVars.key=window.ABCJS.parse.parseKeyVoice.deepCopyKey({accidentals:window.ABCJS.parse.parseKeyVoice.standardKey(key)}),multilineVars.key.root=retPitch.token,multilineVars.key.acc=acc,multilineVars.key.mode=mode,oldKey){for(var kk,k=0;k<multilineVars.key.accidentals.length;k++)for(kk=0;kk<oldKey.accidentals.length;kk++)oldKey.accidentals[kk].note&&multilineVars.key.accidentals[k].note.toLowerCase()===oldKey.accidentals[kk].note.toLowerCase()&&(oldKey.accidentals[kk].note=null);for(kk=0;kk<oldKey.accidentals.length;kk++)oldKey.accidentals[kk].note&&(multilineVars.key.impliedNaturals||(multilineVars.key.impliedNaturals=[]),multilineVars.key.impliedNaturals.push({acc:\"natural\",note:oldKey.accidentals[kk].note}))}}}if(0===tokens.length)return ret;if(\"exp\"===tokens[0].token&&tokens.shift(),0===tokens.length)return ret;if(\"oct\"===tokens[0].token&&tokens.shift(),0===tokens.length)return ret;var accs=tokenizer.getKeyAccidentals2(tokens);if(accs.warn&&warn(accs.warn,str,0),accs.accs){ret.foundKey||(ret.foundKey=!0,multilineVars.key={root:\"none\",acc:\"\",mode:\"\",accidentals:[]}),normalizeAccidentals(accs.accs);for(var i=0;i<accs.accs.length;i++){for(var found=!1,j=0;j<multilineVars.key.accidentals.length&&!found;j++)multilineVars.key.accidentals[j].note===accs.accs[i].note&&(found=!0,multilineVars.key.accidentals[j].acc=accs.accs[i].acc);if(!found&&(multilineVars.key.accidentals.push(accs.accs[i]),multilineVars.key.impliedNaturals))for(var kkk=0;kkk<multilineVars.key.impliedNaturals.length;kkk++)multilineVars.key.impliedNaturals[kkk].note===accs.accs[i].note&&multilineVars.key.impliedNaturals.splice(kkk,1)}}for(var token;tokens.length>0;)switch(tokens[0].token){case\"m\":case\"middle\":if(tokens.shift(),0===tokens.length)return warn(\"Expected = after middle\",str,0),ret;if(token=tokens.shift(),\"=\"!==token.token){warn(\"Expected = after middle\",str,token.start);break}if(0===tokens.length)return warn(\"Expected parameter after middle=\",str,0),ret;var pitch=tokenizer.getPitchFromTokens(tokens);pitch.warn&&warn(pitch.warn,str,0),pitch.position&&(multilineVars.clef.verticalPos=pitch.position-6);break;case\"transpose\":if(tokens.shift(),0===tokens.length)return warn(\"Expected = after transpose\",str,0),ret;if(token=tokens.shift(),\"=\"!==token.token){warn(\"Expected = after transpose\",str,token.start);break}if(0===tokens.length)return warn(\"Expected parameter after transpose=\",str,0),ret;if(\"number\"!==tokens[0].type){warn(\"Expected number after transpose\",str,tokens[0].start);break}multilineVars.clef.transpose=tokens[0].intt,tokens.shift();break;case\"stafflines\":if(tokens.shift(),0===tokens.length)return warn(\"Expected = after stafflines\",str,0),ret;if(token=tokens.shift(),\"=\"!==token.token){warn(\"Expected = after stafflines\",str,token.start);break}if(0===tokens.length)return warn(\"Expected parameter after stafflines=\",str,0),ret;if(\"number\"!==tokens[0].type){warn(\"Expected number after stafflines\",str,tokens[0].start);break}multilineVars.clef.stafflines=tokens[0].intt,tokens.shift();break;case\"staffscale\":if(tokens.shift(),0===tokens.length)return warn(\"Expected = after staffscale\",str,0),ret;if(token=tokens.shift(),\"=\"!==token.token){warn(\"Expected = after staffscale\",str,token.start);break}if(0===tokens.length)return warn(\"Expected parameter after staffscale=\",str,0),ret;if(\"number\"!==tokens[0].type){warn(\"Expected number after staffscale\",str,tokens[0].start);break}multilineVars.clef.staffscale=tokens[0].floatt,tokens.shift();break;case\"style\":if(tokens.shift(),0===tokens.length)return warn(\"Expected = after style\",str,0),ret;if(token=tokens.shift(),\"=\"!==token.token){warn(\"Expected = after style\",str,token.start);break}if(0===tokens.length)return warn(\"Expected parameter after style=\",str,0),ret;switch(tokens[0].token){case\"normal\":case\"harmonic\":case\"rhythm\":case\"x\":multilineVars.style=tokens[0].token,tokens.shift();break;default:warn(\"error parsing style element: \"+tokens[0].token,str,tokens[0].start)}break;case\"clef\":if(tokens.shift(),0===tokens.length)return warn(\"Expected = after clef\",str,0),ret;if(token=tokens.shift(),\"=\"!==token.token){warn(\"Expected = after clef\",str,token.start);break}if(0===tokens.length)return warn(\"Expected parameter after clef=\",str,0),ret;case\"treble\":case\"bass\":case\"alto\":case\"tenor\":case\"perc\":var clef=tokens.shift();switch(clef.token){case\"treble\":case\"tenor\":case\"alto\":case\"bass\":case\"perc\":case\"none\":break;case\"C\":clef.token=\"alto\";break;case\"F\":clef.token=\"bass\";break;case\"G\":clef.token=\"treble\";break;case\"c\":clef.token=\"alto\";break;case\"f\":clef.token=\"bass\";break;case\"g\":clef.token=\"treble\";break;default:warn(\"Expected clef name. Found \"+clef.token,str,clef.start)}tokens.length>0&&\"number\"===tokens[0].type&&(clef.token+=tokens[0].token,tokens.shift()),tokens.length>1&&(\"-\"===tokens[0].token||\"+\"===tokens[0].token)&&\"8\"===tokens[1].token&&(clef.token+=tokens[0].token+tokens[1].token,tokens.shift(),tokens.shift()),multilineVars.clef={type:clef.token,verticalPos:calcMiddle(clef.token,0)},multilineVars.currentVoice&&void 0!==multilineVars.currentVoice.transpose&&(multilineVars.clef.transpose=multilineVars.currentVoice.transpose),ret.foundClef=!0;break;default:warn(\"Unknown parameter: \"+tokens[0].token,str,tokens[0].start),tokens.shift()}return ret};var setCurrentVoice=function(id){multilineVars.currentVoice=multilineVars.voices[id],tune.setCurrentVoice(multilineVars.currentVoice.staffNum,multilineVars.currentVoice.index)};window.ABCJS.parse.parseKeyVoice.parseVoice=function(line,i,e){var ret=tokenizer.getMeat(line,i,e),start=ret.start,end=ret.end,id=tokenizer.getToken(line,start,end);if(0===id.length)return void warn(\"Expected a voice id\",line,start);var isNew=!1;void 0===multilineVars.voices[id]&&(multilineVars.voices[id]={},isNew=!0,multilineVars.score_is_present&&warn(\"Can't have an unknown V: id when the %score directive is present\",line,start)),start+=id.length,start+=tokenizer.eatWhiteSpace(line,start);for(var staffInfo={startStaff:isNew},addNextTokenToStaffInfo=function(name){var attr=tokenizer.getVoiceToken(line,start,end);void 0!==attr.warn?warn(\"Expected value for \"+name+\" in voice: \"+attr.warn,line,start):0===attr.token.length&&'\"'!==line.charAt(start)?warn(\"Expected value for \"+name+\" in voice\",line,start):staffInfo[name]=attr.token,start+=attr.len},addNextTokenToVoiceInfo=function(id,name,type){var attr=tokenizer.getVoiceToken(line,start,end);void 0!==attr.warn?warn(\"Expected value for \"+name+\" in voice: \"+attr.warn,line,start):0===attr.token.length&&'\"'!==line.charAt(start)?warn(\"Expected value for \"+name+\" in voice\",line,start):(\"number\"===type&&(attr.token=parseFloat(attr.token)),multilineVars.voices[id][name]=attr.token),start+=attr.len};start<end;){var token=tokenizer.getVoiceToken(line,start,end);if(start+=token.len,token.warn)warn(\"Error parsing voice: \"+token.warn,line,start);else{var attr=null;switch(token.token){case\"clef\":case\"cl\":addNextTokenToStaffInfo(\"clef\");var oct=0;void 0!==staffInfo.clef&&(staffInfo.clef=staffInfo.clef.replace(/[',]/g,\"\"),staffInfo.clef.indexOf(\"+16\")!==-1&&(oct+=14,staffInfo.clef=staffInfo.clef.replace(\"+16\",\"\")),staffInfo.verticalPos=calcMiddle(staffInfo.clef,oct));break;case\"treble\":case\"bass\":case\"tenor\":case\"alto\":case\"none\":case\"treble'\":case\"bass'\":case\"tenor'\":case\"alto'\":case\"none'\":case\"treble''\":case\"bass''\":case\"tenor''\":case\"alto''\":case\"none''\":case\"treble,\":case\"bass,\":case\"tenor,\":case\"alto,\":case\"none,\":case\"treble,,\":case\"bass,,\":case\"tenor,,\":case\"alto,,\":case\"none,,\":var oct2=0;staffInfo.clef=token.token.replace(/[',]/g,\"\"),staffInfo.verticalPos=calcMiddle(staffInfo.clef,oct2);break;case\"staves\":case\"stave\":case\"stv\":addNextTokenToStaffInfo(\"staves\");break;case\"brace\":case\"brc\":addNextTokenToStaffInfo(\"brace\");break;case\"bracket\":case\"brk\":addNextTokenToStaffInfo(\"bracket\");break;case\"name\":case\"nm\":addNextTokenToStaffInfo(\"name\");break;case\"subname\":case\"sname\":case\"snm\":addNextTokenToStaffInfo(\"subname\");break;case\"merge\":staffInfo.startStaff=!1;break;case\"stems\":attr=tokenizer.getVoiceToken(line,start,end),void 0!==attr.warn?warn(\"Expected value for stems in voice: \"+attr.warn,line,start):\"up\"===attr.token||\"down\"===attr.token?multilineVars.voices[id].stem=attr.token:warn(\"Expected up or down for voice stem\",line,start),start+=attr.len;break;case\"up\":case\"down\":multilineVars.voices[id].stem=token.token;break;case\"middle\":case\"m\":addNextTokenToStaffInfo(\"verticalPos\"),staffInfo.verticalPos=parseMiddle(staffInfo.verticalPos).mid;break;case\"gchords\":case\"gch\":multilineVars.voices[id].suppressChords=!0;break;case\"space\":case\"spc\":addNextTokenToStaffInfo(\"spacing\");break;case\"scale\":addNextTokenToVoiceInfo(id,\"scale\",\"number\");break;case\"transpose\":addNextTokenToVoiceInfo(id,\"transpose\",\"number\")}}start+=tokenizer.eatWhiteSpace(line,start)}if((staffInfo.startStaff||0===multilineVars.staves.length)&&(multilineVars.staves.push({index:multilineVars.staves.length,meter:multilineVars.origMeter}),multilineVars.score_is_present||(multilineVars.staves[multilineVars.staves.length-1].numVoices=0)),void 0===multilineVars.voices[id].staffNum){multilineVars.voices[id].staffNum=multilineVars.staves.length-1;var vi=0;for(var v in multilineVars.voices)multilineVars.voices.hasOwnProperty(v)&&multilineVars.voices[v].staffNum===multilineVars.voices[id].staffNum&&vi++;multilineVars.voices[id].index=vi-1}var s=multilineVars.staves[multilineVars.voices[id].staffNum];multilineVars.score_is_present||s.numVoices++,staffInfo.clef&&(s.clef={type:staffInfo.clef,verticalPos:staffInfo.verticalPos}),staffInfo.spacing&&(s.spacing_below_offset=staffInfo.spacing),staffInfo.verticalPos&&(s.verticalPos=staffInfo.verticalPos),staffInfo.name&&(s.name?s.name.push(staffInfo.name):s.name=[staffInfo.name]),staffInfo.subname&&(s.subname?s.subname.push(staffInfo.subname):s.subname=[staffInfo.subname]),setCurrentVoice(id)}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.parse||(window.ABCJS.parse={}),window.ABCJS.parse.tokenizer=function(){this.skipWhiteSpace=function(str){for(var i=0;i<str.length;i++)if(!this.isWhiteSpace(str.charAt(i)))return i;return str.length};var finished=function(str,i){return i>=str.length};this.eatWhiteSpace=function(line,index){for(var i=index;i<line.length;i++)if(!this.isWhiteSpace(line.charAt(i)))return i-index;return i-index},this.getKeyPitch=function(str){var i=this.skipWhiteSpace(str);if(finished(str,i))return{len:0};switch(str.charAt(i)){case\"A\":return{len:i+1,token:\"A\"};case\"B\":return{len:i+1,token:\"B\"};case\"C\":return{len:i+1,token:\"C\"};case\"D\":return{len:i+1,token:\"D\"};case\"E\":return{len:i+1,token:\"E\"};case\"F\":return{len:i+1,token:\"F\"};case\"G\":return{len:i+1,token:\"G\"}}return{len:0}},this.getSharpFlat=function(str){if(\"bass\"===str)return{len:0};switch(str.charAt(0)){case\"#\":return{len:1,token:\"#\"};case\"b\":return{len:1,token:\"b\"}}return{len:0}},this.getMode=function(str){var skipAlpha=function(str,start){for(;start<str.length&&(str.charAt(start)>=\"a\"&&str.charAt(start)<=\"z\"||str.charAt(start)>=\"A\"&&str.charAt(start)<=\"Z\");)start++;return start},i=this.skipWhiteSpace(str);if(finished(str,i))return{len:0};var firstThree=str.substring(i,i+3).toLowerCase();switch((firstThree.length>1&&\" \"===firstThree.charAt(1)||\"^\"===firstThree.charAt(1)||\"_\"===firstThree.charAt(1)||\"=\"===firstThree.charAt(1))&&(firstThree=firstThree.charAt(0)),firstThree){case\"mix\":return{len:skipAlpha(str,i),token:\"Mix\"};case\"dor\":return{len:skipAlpha(str,i),token:\"Dor\"};case\"phr\":return{len:skipAlpha(str,i),token:\"Phr\"};case\"lyd\":return{len:skipAlpha(str,i),token:\"Lyd\"};case\"loc\":return{len:skipAlpha(str,i),token:\"Loc\"};case\"aeo\":return{len:skipAlpha(str,i),token:\"m\"};case\"maj\":return{len:skipAlpha(str,i),token:\"\"};case\"ion\":return{len:skipAlpha(str,i),token:\"\"};case\"min\":return{len:skipAlpha(str,i),token:\"m\"};case\"m\":return{len:skipAlpha(str,i),token:\"m\"}}return{len:0}},this.getClef=function(str,bExplicitOnly){var strOrig=str,i=this.skipWhiteSpace(str);if(finished(str,i))return{len:0};var needsClef=!1,strClef=str.substring(i);if(window.ABCJS.parse.startsWith(strClef,\"clef=\")&&(needsClef=!0,strClef=strClef.substring(5),i+=5),0===strClef.length&&needsClef)return{len:i+5,warn:\"No clef specified: \"+strOrig};var j=this.skipWhiteSpace(strClef);if(finished(strClef,j))return{len:0};j>0&&(i+=j,strClef=strClef.substring(j));var name=null;if(window.ABCJS.parse.startsWith(strClef,\"treble\"))name=\"treble\";else if(window.ABCJS.parse.startsWith(strClef,\"bass3\"))name=\"bass3\";else if(window.ABCJS.parse.startsWith(strClef,\"bass\"))name=\"bass\";else if(window.ABCJS.parse.startsWith(strClef,\"tenor\"))name=\"tenor\";else if(window.ABCJS.parse.startsWith(strClef,\"alto2\"))name=\"alto2\";else if(window.ABCJS.parse.startsWith(strClef,\"alto1\"))name=\"alto1\";else if(window.ABCJS.parse.startsWith(strClef,\"alto\"))name=\"alto\";else if(!bExplicitOnly&&needsClef&&window.ABCJS.parse.startsWith(strClef,\"none\"))name=\"none\";else if(window.ABCJS.parse.startsWith(strClef,\"perc\"))name=\"perc\";else if(!bExplicitOnly&&needsClef&&window.ABCJS.parse.startsWith(strClef,\"C\"))name=\"tenor\";else if(!bExplicitOnly&&needsClef&&window.ABCJS.parse.startsWith(strClef,\"F\"))name=\"bass\";else{if(bExplicitOnly||!needsClef||!window.ABCJS.parse.startsWith(strClef,\"G\"))return{len:i+5,warn:\"Unknown clef specified: \"+strOrig};name=\"treble\"}return strClef=strClef.substring(name.length),j=this.isMatch(strClef,\"+8\"),j>0?name+=\"+8\":(j=this.isMatch(strClef,\"-8\"),j>0&&(name+=\"-8\")),{len:i+name.length,token:name,explicit:needsClef}},this.getBarLine=function(line,i){switch(line.charAt(i)){case\"]\":switch(++i,line.charAt(i)){case\"|\":return{len:2,token:\"bar_thick_thin\"};case\"[\":return++i,line.charAt(i)>=\"1\"&&line.charAt(i)<=\"9\"||'\"'===line.charAt(i)?{len:2,token:\"bar_invisible\"}:{len:1,warn:\"Unknown bar symbol\"};default:return{len:1,token:\"bar_invisible\"}}break;case\":\":switch(++i,line.charAt(i)){case\":\":return{len:2,token:\"bar_dbl_repeat\"};case\"|\":switch(++i,line.charAt(i)){case\"]\":switch(++i,line.charAt(i)){case\"|\":return++i,\":\"===line.charAt(i)?{len:5,token:\"bar_dbl_repeat\"}:{len:3,token:\"bar_right_repeat\"};default:return{len:3,token:\"bar_right_repeat\"}}break;case\"|\":return++i,\":\"===line.charAt(i)?{len:4,token:\"bar_dbl_repeat\"}:{len:3,token:\"bar_right_repeat\"};default:return{len:2,token:\"bar_right_repeat\"}}break;default:return{len:1,warn:\"Unknown bar symbol\"}}break;case\"[\":if(++i,\"|\"!==line.charAt(i))return line.charAt(i)>=\"1\"&&line.charAt(i)<=\"9\"||'\"'===line.charAt(i)?{len:1,token:\"bar_invisible\"}:{len:0};switch(++i,line.charAt(i)){case\":\":return{len:3,token:\"bar_left_repeat\"};case\"]\":return{len:3,token:\"bar_invisible\"};default:return{len:2,token:\"bar_thick_thin\"}}break;case\"|\":switch(++i,line.charAt(i)){case\"]\":return{len:2,token:\"bar_thin_thick\"};case\"|\":return++i,\":\"===line.charAt(i)?{len:3,token:\"bar_left_repeat\"}:{len:2,token:\"bar_thin_thin\"};case\":\":for(var colons=0;\":\"===line.charAt(i+colons);)colons++;return{len:1+colons,token:\"bar_left_repeat\"};default:return{len:1,token:\"bar_thin\"}}}return{len:0}},this.getTokenOf=function(str,legalChars){for(var i=0;i<str.length;i++)if(legalChars.indexOf(str.charAt(i))<0)return{len:i,token:str.substring(0,i)};return{len:i,token:str}},this.getToken=function(str,start,end){for(var i=start;i<end&&!this.isWhiteSpace(str.charAt(i));)i++;return str.substring(start,i)},this.isMatch=function(str,match){var i=this.skipWhiteSpace(str);return finished(str,i)?0:window.ABCJS.parse.startsWith(str.substring(i),match)?i+match.length:0;\n},this.getPitchFromTokens=function(tokens){var ret={},pitches={A:5,B:6,C:0,D:1,E:2,F:3,G:4,a:12,b:13,c:7,d:8,e:9,f:10,g:11};if(ret.position=pitches[tokens[0].token],void 0===ret.position)return{warn:\"Pitch expected. Found: \"+tokens[0].token};for(tokens.shift();tokens.length;)switch(tokens[0].token){case\",\":ret.position-=7,tokens.shift();break;case\"'\":ret.position+=7,tokens.shift();break;default:return ret}return ret},this.getKeyAccidentals2=function(tokens){for(var accs;tokens.length>0;){var acc;if(\"^\"===tokens[0].token){if(acc=\"sharp\",tokens.shift(),0===tokens.length)return{accs:accs,warn:\"Expected note name after \"+acc};switch(tokens[0].token){case\"^\":acc=\"dblsharp\",tokens.shift();break;case\"/\":acc=\"quartersharp\",tokens.shift()}}else if(\"=\"===tokens[0].token)acc=\"natural\",tokens.shift();else{if(\"_\"!==tokens[0].token)return{accs:accs};if(acc=\"flat\",tokens.shift(),0===tokens.length)return{accs:accs,warn:\"Expected note name after \"+acc};switch(tokens[0].token){case\"_\":acc=\"dblflat\",tokens.shift();break;case\"/\":acc=\"quarterflat\",tokens.shift()}}if(0===tokens.length)return{accs:accs,warn:\"Expected note name after \"+acc};switch(tokens[0].token.charAt(0)){case\"a\":case\"b\":case\"c\":case\"d\":case\"e\":case\"f\":case\"g\":case\"A\":case\"B\":case\"C\":case\"D\":case\"E\":case\"F\":case\"G\":void 0===accs&&(accs=[]),accs.push({acc:acc,note:tokens[0].token.charAt(0)}),1===tokens[0].token.length?tokens.shift():tokens[0].token=tokens[0].token.substring(1);break;default:return{accs:accs,warn:\"Expected note name after \"+acc+\" Found: \"+tokens[0].token}}}return{accs:accs}},this.getKeyAccidental=function(str){var accTranslation={\"^\":\"sharp\",\"^^\":\"dblsharp\",\"=\":\"natural\",_:\"flat\",__:\"dblflat\",\"_/\":\"quarterflat\",\"^/\":\"quartersharp\"},i=this.skipWhiteSpace(str);if(finished(str,i))return{len:0};var acc=null;switch(str.charAt(i)){case\"^\":case\"_\":case\"=\":acc=str.charAt(i);break;default:return{len:0}}if(i++,finished(str,i))return{len:1,warn:\"Expected note name after accidental\"};switch(str.charAt(i)){case\"a\":case\"b\":case\"c\":case\"d\":case\"e\":case\"f\":case\"g\":case\"A\":case\"B\":case\"C\":case\"D\":case\"E\":case\"F\":case\"G\":return{len:i+1,token:{acc:accTranslation[acc],note:str.charAt(i)}};case\"^\":case\"_\":case\"/\":if(acc+=str.charAt(i),i++,finished(str,i))return{len:2,warn:\"Expected note name after accidental\"};switch(str.charAt(i)){case\"a\":case\"b\":case\"c\":case\"d\":case\"e\":case\"f\":case\"g\":case\"A\":case\"B\":case\"C\":case\"D\":case\"E\":case\"F\":case\"G\":return{len:i+1,token:{acc:accTranslation[acc],note:str.charAt(i)}};default:return{len:2,warn:\"Expected note name after accidental\"}}break;default:return{len:1,warn:\"Expected note name after accidental\"}}},this.isWhiteSpace=function(ch){return\" \"===ch||\"\\t\"===ch||\"\u0012\"===ch},this.getMeat=function(line,start,end){var comment=line.indexOf(\"%\",start);for(comment>=0&&comment<end&&(end=comment);start<end&&(\" \"===line.charAt(start)||\"\\t\"===line.charAt(start)||\"\u0012\"===line.charAt(start));)start++;for(;start<end&&(\" \"===line.charAt(end-1)||\"\\t\"===line.charAt(end-1)||\"\u0012\"===line.charAt(end-1));)end--;return{start:start,end:end}};var isLetter=function(ch){return ch>=\"A\"&&ch<=\"Z\"||ch>=\"a\"&&ch<=\"z\"},isNumber=function(ch){return ch>=\"0\"&&ch<=\"9\"};this.tokenize=function(line,start,end,alphaUntilWhiteSpace){var ret=this.getMeat(line,start,end);start=ret.start,end=ret.end;for(var i,tokens=[];start<end;){if('\"'===line.charAt(start)){for(i=start+1;i<end&&'\"'!==line.charAt(i);)i++;tokens.push({type:\"quote\",token:line.substring(start+1,i),start:start+1,end:i}),i++}else if(isLetter(line.charAt(start))){if(i=start+1,alphaUntilWhiteSpace)for(;i<end&&!this.isWhiteSpace(line.charAt(i));)i++;else for(;i<end&&isLetter(line.charAt(i));)i++;tokens.push({type:\"alpha\",token:line.substring(start,i),continueId:isNumber(line.charAt(i)),start:start,end:i}),start=i+1}else if(\".\"===line.charAt(start)&&isNumber(line.charAt(i+1))){i=start+1;for(var int2=null,float2=null;i<end&&isNumber(line.charAt(i));)i++;float2=parseFloat(line.substring(start,i)),tokens.push({type:\"number\",token:line.substring(start,i),intt:int2,floatt:float2,continueId:isLetter(line.charAt(i)),start:start,end:i}),start=i+1}else if(isNumber(line.charAt(start))||\"-\"===line.charAt(start)&&isNumber(line.charAt(i+1))){i=start+1;for(var intt=null,floatt=null;i<end&&isNumber(line.charAt(i));)i++;if(\".\"===line.charAt(i)&&isNumber(line.charAt(i+1)))for(i++;i<end&&isNumber(line.charAt(i));)i++;else intt=parseInt(line.substring(start,i));floatt=parseFloat(line.substring(start,i)),tokens.push({type:\"number\",token:line.substring(start,i),intt:intt,floatt:floatt,continueId:isLetter(line.charAt(i)),start:start,end:i}),start=i+1}else\" \"===line.charAt(start)||\"\\t\"===line.charAt(start)?i=start+1:(tokens.push({type:\"punct\",token:line.charAt(start),start:start,end:start+1}),i=start+1);start=i}return tokens},this.getVoiceToken=function(line,start,end){for(var i=start;i<end&&this.isWhiteSpace(line.charAt(i))||\"=\"===line.charAt(i);)i++;if('\"'===line.charAt(i)){var close=line.indexOf('\"',i+1);return close===-1||close>=end?{len:1,err:\"Missing close quote\"}:{len:close-start+1,token:this.translateString(line.substring(i+1,close))}}for(var ii=i;ii<end&&!this.isWhiteSpace(line.charAt(ii))&&\"=\"!==line.charAt(ii);)ii++;return{len:ii-start+1,token:line.substring(i,ii)}};var charMap={\"`a\":\"à\",\"'a\":\"á\",\"^a\":\"â\",\"~a\":\"ã\",'\"a':\"ä\",oa:\"å\",\"=a\":\"ā\",ua:\"ă\",\";a\":\"ą\",\"`e\":\"è\",\"'e\":\"é\",\"^e\":\"ê\",'\"e':\"ë\",\"=e\":\"ē\",ue:\"ĕ\",\";e\":\"ę\",\".e\":\"ė\",\"`i\":\"ì\",\"'i\":\"í\",\"^i\":\"î\",'\"i':\"ï\",\"=i\":\"ī\",ui:\"ĭ\",\";i\":\"į\",\"`o\":\"ò\",\"'o\":\"ó\",\"^o\":\"ô\",\"~o\":\"õ\",'\"o':\"ö\",\"=o\":\"ō\",uo:\"ŏ\",\"/o\":\"ø\",\"`u\":\"ù\",\"'u\":\"ú\",\"^u\":\"û\",\"~u\":\"ũ\",'\"u':\"ü\",ou:\"ů\",\"=u\":\"ū\",uu:\"ŭ\",\";u\":\"ų\",\"`A\":\"À\",\"'A\":\"Á\",\"^A\":\"Â\",\"~A\":\"Ã\",'\"A':\"Ä\",oA:\"Å\",\"=A\":\"Ā\",uA:\"Ă\",\";A\":\"Ą\",\"`E\":\"È\",\"'E\":\"É\",\"^E\":\"Ê\",'\"E':\"Ë\",\"=E\":\"Ē\",uE:\"Ĕ\",\";E\":\"Ę\",\".E\":\"Ė\",\"`I\":\"Ì\",\"'I\":\"Í\",\"^I\":\"Î\",\"~I\":\"Ĩ\",'\"I':\"Ï\",\"=I\":\"Ī\",uI:\"Ĭ\",\";I\":\"Į\",\".I\":\"İ\",\"`O\":\"Ò\",\"'O\":\"Ó\",\"^O\":\"Ô\",\"~O\":\"Õ\",'\"O':\"Ö\",\"=O\":\"Ō\",uO:\"Ŏ\",\"/O\":\"Ø\",\"`U\":\"Ù\",\"'U\":\"Ú\",\"^U\":\"Û\",\"~U\":\"Ũ\",'\"U':\"Ü\",oU:\"Ů\",\"=U\":\"Ū\",uU:\"Ŭ\",\";U\":\"Ų\",ae:\"æ\",AE:\"Æ\",oe:\"œ\",OE:\"Œ\",ss:\"ß\",\"'c\":\"ć\",\"^c\":\"ĉ\",uc:\"č\",cc:\"ç\",\".c\":\"ċ\",cC:\"Ç\",\"'C\":\"Ć\",\"^C\":\"Ĉ\",uC:\"Č\",\".C\":\"Ċ\",\"~n\":\"ñ\",\"=s\":\"š\",vs:\"š\",vz:\"ž\"},charMap1={\"#\":\"♯\",b:\"♭\",\"=\":\"♮\"},charMap2={201:\"♯\",202:\"♭\",203:\"♮\",241:\"¡\",242:\"¢\",252:\"a\",262:\"2\",272:\"o\",302:\"Â\",312:\"Ê\",322:\"Ò\",332:\"Ú\",342:\"â\",352:\"ê\",362:\"ò\",372:\"ú\",243:\"£\",253:\"«\",263:\"3\",273:\"»\",303:\"Ã\",313:\"Ë\",323:\"Ó\",333:\"Û\",343:\"ã\",353:\"ë\",363:\"ó\",373:\"û\",244:\"¤\",254:\"¬\",264:\"  ́\",274:\"1⁄4\",304:\"Ä\",314:\"Ì\",324:\"Ô\",334:\"Ü\",344:\"ä\",354:\"ì\",364:\"ô\",374:\"ü\",245:\"¥\",255:\"-\",265:\"μ\",275:\"1⁄2\",305:\"Å\",315:\"Í\",325:\"Õ\",335:\"Ý\",345:\"å\",355:\"í\",365:\"õ\",375:\"ý\",246:\"¦\",256:\"®\",266:\"¶\",276:\"3⁄4\",306:\"Æ\",316:\"Î\",326:\"Ö\",336:\"Þ\",346:\"æ\",356:\"î\",366:\"ö\",376:\"þ\",247:\"§\",257:\" ̄\",267:\"·\",277:\"¿\",307:\"Ç\",317:\"Ï\",327:\"×\",337:\"ß\",347:\"ç\",357:\"ï\",367:\"÷\",377:\"ÿ\",250:\" ̈\",260:\"°\",270:\" ̧\",300:\"À\",310:\"È\",320:\"Ð\",330:\"Ø\",340:\"à\",350:\"è\",360:\"ð\",370:\"ø\",251:\"©\",261:\"±\",271:\"1\",301:\"Á\",311:\"É\",321:\"Ñ\",331:\"Ù\",341:\"á\",351:\"é\",361:\"ñ\",371:\"ù\"};this.translateString=function(str){var arr=str.split(\"\\\\\");if(1===arr.length)return str;var out=null;return window.ABCJS.parse.each(arr,function(s){if(null===out)out=s;else{var c=charMap[s.substring(0,2)];void 0!==c?out+=c+s.substring(2):(c=charMap2[s.substring(0,3)],void 0!==c?out+=c+s.substring(3):(c=charMap1[s.substring(0,1)],out+=void 0!==c?c+s.substring(1):\"\\\\\"+s))}}),out},this.getNumber=function(line,index){for(var num=0;index<line.length;)switch(line.charAt(index)){case\"0\":num*=10,index++;break;case\"1\":num=10*num+1,index++;break;case\"2\":num=10*num+2,index++;break;case\"3\":num=10*num+3,index++;break;case\"4\":num=10*num+4,index++;break;case\"5\":num=10*num+5,index++;break;case\"6\":num=10*num+6,index++;break;case\"7\":num=10*num+7,index++;break;case\"8\":num=10*num+8,index++;break;case\"9\":num=10*num+9,index++;break;default:return{num:num,index:index}}return{num:num,index:index}},this.getFraction=function(line,index){var num=1,den=1;if(\"/\"!==line.charAt(index)){var ret=this.getNumber(line,index);num=ret.num,index=ret.index}if(\"/\"===line.charAt(index)){if(index++,\"/\"===line.charAt(index)){for(var div=.5;\"/\"===line.charAt(index++);)div/=2;return{value:num*div,index:index-1}}var iSave=index,ret2=this.getNumber(line,index);0===ret2.num&&iSave===index&&(ret2.num=2),0!==ret2.num&&(den=ret2.num),index=ret2.index}return{value:num/den,index:index}},this.theReverser=function(str){return window.ABCJS.parse.endsWith(str,\", The\")?\"The \"+str.substring(0,str.length-5):window.ABCJS.parse.endsWith(str,\", A\")?\"A \"+str.substring(0,str.length-3):str},this.stripComment=function(str){var i=str.indexOf(\"%\");return i>=0?window.ABCJS.parse.strip(str.substring(0,i)):window.ABCJS.parse.strip(str)},this.getInt=function(str){var x=parseInt(str);if(isNaN(x))return{digits:0};var s=\"\"+x,i=str.indexOf(s);return{value:x,digits:i+s.length}},this.getFloat=function(str){var x=parseFloat(str);if(isNaN(x))return{digits:0};var s=\"\"+x,i=str.indexOf(s);return{value:x,digits:i+s.length}},this.getMeasurement=function(tokens){if(0===tokens.length)return{used:0};var used=1,num=\"\";if(\"-\"===tokens[0].token)tokens.shift(),num=\"-\",used++;else if(\"number\"!==tokens[0].type)return{used:0};if(num+=tokens.shift().token,0===tokens.length)return{used:1,value:parseInt(num)};var x=tokens.shift();if(\".\"===x.token){if(used++,0===tokens.length)return{used:used,value:parseInt(num)};if(\"number\"===tokens[0].type&&(x=tokens.shift(),num=num+\".\"+x.token,used++,0===tokens.length))return{used:used,value:parseFloat(num)};x=tokens.shift()}switch(x.token){case\"pt\":return{used:used+1,value:parseFloat(num)};case\"cm\":return{used:used+1,value:parseFloat(num)/2.54*72};case\"in\":return{used:used+1,value:72*parseFloat(num)};default:return tokens.unshift(x),{used:used,value:parseFloat(num)}}return{used:0}};var substInChord=function(str){for(;str.indexOf(\"\\\\n\")!==-1;)str=str.replace(\"\\\\n\",\"\\n\");return str};this.getBrackettedSubstring=function(line,i,maxErrorChars,_matchChar){for(var matchChar=_matchChar||line.charAt(i),pos=i+1;pos<line.length&&line.charAt(pos)!==matchChar;)++pos;return line.charAt(pos)===matchChar?[pos-i+1,substInChord(line.substring(i+1,pos)),!0]:(pos=i+maxErrorChars,pos>line.length-1&&(pos=line.length-1),[pos-i+1,substInChord(line.substring(i+1,pos)),!1])}},window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.AbsoluteElement=function(abcelem,duration,minspacing,type,tuneNumber){this.tuneNumber=tuneNumber,this.abcelem=abcelem,this.duration=duration,this.minspacing=minspacing||0,this.x=0,this.children=[],this.heads=[],this.extra=[],this.extraw=0,this.w=0,this.right=[],this.invisible=!1,this.bottom=void 0,this.top=void 0,this.type=type,this.specialY={tempoHeightAbove:0,partHeightAbove:0,volumeHeightAbove:0,dynamicHeightAbove:0,endingHeightAbove:0,chordHeightAbove:0,lyricHeightAbove:0,lyricHeightBelow:0,chordHeightBelow:0,volumeHeightBelow:0,dynamicHeightBelow:0}},ABCJS.write.AbsoluteElement.prototype.setUpperAndLowerElements=function(specialYResolved){for(var i=0;i<this.children.length;i++){var child=this.children[i];for(var key in this.specialY)this.specialY.hasOwnProperty(key)&&child[key]&&(child.pitch=specialYResolved[key])}},ABCJS.write.AbsoluteElement.prototype.getMinWidth=function(){return this.w},ABCJS.write.AbsoluteElement.prototype.getExtraWidth=function(){return-this.extraw},ABCJS.write.AbsoluteElement.prototype.addExtra=function(extra){extra.dx<this.extraw&&(this.extraw=extra.dx),this.extra[this.extra.length]=extra,this.addChild(extra)},ABCJS.write.AbsoluteElement.prototype.addHead=function(head){head.dx<this.extraw&&(this.extraw=head.dx),this.heads[this.heads.length]=head,this.addRight(head)},ABCJS.write.AbsoluteElement.prototype.addRight=function(right){right.dx+right.w>this.w&&(this.w=right.dx+right.w),this.right[this.right.length]=right,this.addChild(right)},ABCJS.write.AbsoluteElement.prototype.addCentered=function(elem){var half=elem.w/2;-half<this.extraw&&(this.extraw=-half),this.extra[this.extra.length]=elem,elem.dx+half>this.w&&(this.w=elem.dx+half),this.right[this.right.length]=elem,this.addChild(elem)},ABCJS.write.AbsoluteElement.prototype.setLimit=function(member,child){child[member]&&(this.specialY[member]?this.specialY[member]=Math.max(this.specialY[member],child[member]):this.specialY[member]=child[member])},ABCJS.write.AbsoluteElement.prototype.addChild=function(child){child.parent=this,this.children[this.children.length]=child,this.pushTop(child.top),this.pushBottom(child.bottom),this.setLimit(\"tempoHeightAbove\",child),this.setLimit(\"partHeightAbove\",child),this.setLimit(\"volumeHeightAbove\",child),this.setLimit(\"dynamicHeightAbove\",child),this.setLimit(\"endingHeightAbove\",child),this.setLimit(\"chordHeightAbove\",child),this.setLimit(\"lyricHeightAbove\",child),this.setLimit(\"lyricHeightBelow\",child),this.setLimit(\"chordHeightBelow\",child),this.setLimit(\"volumeHeightBelow\",child),this.setLimit(\"dynamicHeightBelow\",child)},ABCJS.write.AbsoluteElement.prototype.pushTop=function(top){void 0!==top&&(void 0===this.top?this.top=top:this.top=Math.max(top,this.top))},ABCJS.write.AbsoluteElement.prototype.pushBottom=function(bottom){void 0!==bottom&&(void 0===this.bottom?this.bottom=bottom:this.bottom=Math.min(bottom,this.bottom))},ABCJS.write.AbsoluteElement.prototype.setX=function(x){this.x=x;for(var i=0;i<this.children.length;i++)this.children[i].setX(x)},ABCJS.write.AbsoluteElement.prototype.setHint=function(){this.hint=!0},ABCJS.write.AbsoluteElement.prototype.draw=function(renderer,bartop){if(this.elemset=renderer.paper.set(),!this.invisible){renderer.beginGroup();for(var i=0;i<this.children.length;i++)ABCJS.write.debugPlacement&&\"ornament\"===this.children[i].klass&&renderer.printShadedBox(this.x,renderer.calcY(this.children[i].top),this.w,renderer.calcY(this.children[i].bottom)-renderer.calcY(this.children[i].top),\"rgba(0,0,200,0.3)\"),this.elemset.push(this.children[i].draw(renderer,bartop));this.elemset.push(renderer.endGroup(this.type)),this.klass&&this.setClass(\"mark\",\"\",\"#00ff00\"),this.hint&&this.setClass(\"abcjs-hint\",\"\",null);var color=ABCJS.write.debugPlacement?\"rgba(0,0,0,0.3)\":\"rgba(0,0,0,0)\",target=renderer.printShadedBox(this.x,renderer.calcY(this.top),this.w,renderer.calcY(this.bottom)-renderer.calcY(this.top),color),self=this,controller=renderer.controller;target.mouseup(function(){controller.notifySelect(self,self.tuneNumber)}),this.abcelem.abselem=this;var spacing=ABCJS.write.spacing.STEP,start=function(){this.dy=0},move=function(dx,dy){dy=Math.round(dy/spacing)*spacing,this.translate(0,-this.dy),this.dy=dy,this.translate(0,this.dy)},up=function(){if(self.abcelem.pitches){var delta=-Math.round(this.dy/spacing);self.abcelem.pitches[0].pitch+=delta,self.abcelem.pitches[0].verticalPos+=delta,controller.notifyChange()}};\"note\"===this.abcelem.el_type&&controller.editable&&this.elemset.drag(move,start,up)}},ABCJS.write.AbsoluteElement.prototype.isIE=!1,ABCJS.write.AbsoluteElement.prototype.setClass=function(addClass,removeClass,color){if(null!==color&&this.elemset.attr({fill:color}),!this.isIE)for(var i=0;i<this.elemset.length;i++)if(this.elemset[i][0].setAttribute){var kls=this.elemset[i][0].getAttribute(\"class\");kls||(kls=\"\"),kls=kls.replace(removeClass,\"\"),kls=kls.replace(addClass,\"\"),addClass.length>0&&(kls.length>0&&\" \"!==kls.charAt(kls.length-1)&&(kls+=\" \"),kls+=addClass),this.elemset[i][0].setAttribute(\"class\",kls)}},ABCJS.write.AbsoluteElement.prototype.highlight=function(klass,color){void 0===klass&&(klass=\"note_selected\"),void 0===color&&(color=\"#ff0000\"),this.setClass(klass,\"\",color)},ABCJS.write.AbsoluteElement.prototype.unhighlight=function(klass,color){void 0===klass&&(klass=\"note_selected\"),void 0===color&&(color=\"#000000\"),this.setClass(\"\",klass,color)},window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),function(){\"use strict\";ABCJS.write.getDuration=function(elem){var d=0;return elem.duration&&(d=elem.duration),d},ABCJS.write.getDurlog=function(duration){return void 0===duration?0:Math.floor(Math.log(duration)/Math.log(2))},ABCJS.write.AbstractEngraver=function(bagpipes,renderer,tuneNumber){this.decoration=new ABCJS.write.Decoration,this.renderer=renderer,this.tuneNumber=tuneNumber,this.isBagpipes=bagpipes,this.chartable={rest:{0:\"rests.whole\",1:\"rests.half\",2:\"rests.quarter\",3:\"rests.8th\",4:\"rests.16th\",5:\"rests.32nd\",6:\"rests.64th\",7:\"rests.128th\"},note:{\"-1\":\"noteheads.dbl\",0:\"noteheads.whole\",1:\"noteheads.half\",2:\"noteheads.quarter\",3:\"noteheads.quarter\",4:\"noteheads.quarter\",5:\"noteheads.quarter\",6:\"noteheads.quarter\",7:\"noteheads.quarter\",nostem:\"noteheads.quarter\"},rhythm:{\"-1\":\"noteheads.slash.whole\",0:\"noteheads.slash.whole\",1:\"noteheads.slash.whole\",2:\"noteheads.slash.quarter\",3:\"noteheads.slash.quarter\",4:\"noteheads.slash.quarter\",5:\"noteheads.slash.quarter\",6:\"noteheads.slash.quarter\",7:\"noteheads.slash.quarter\",nostem:\"noteheads.slash.nostem\"},x:{\"-1\":\"noteheads.indeterminate\",0:\"noteheads.indeterminate\",1:\"noteheads.indeterminate\",2:\"noteheads.indeterminate\",3:\"noteheads.indeterminate\",4:\"noteheads.indeterminate\",5:\"noteheads.indeterminate\",6:\"noteheads.indeterminate\",7:\"noteheads.indeterminate\",nostem:\"noteheads.indeterminate\"},harmonic:{\"-1\":\"noteheads.harmonic.quarter\",0:\"noteheads.harmonic.quarter\",1:\"noteheads.harmonic.quarter\",2:\"noteheads.harmonic.quarter\",3:\"noteheads.harmonic.quarter\",4:\"noteheads.harmonic.quarter\",5:\"noteheads.harmonic.quarter\",6:\"noteheads.harmonic.quarter\",7:\"noteheads.harmonic.quarter\",nostem:\"noteheads.harmonic.quarter\"},uflags:{3:\"flags.u8th\",4:\"flags.u16th\",5:\"flags.u32nd\",6:\"flags.u64th\"},dflags:{3:\"flags.d8th\",4:\"flags.d16th\",5:\"flags.d32nd\",6:\"flags.d64th\"}},this.reset()},ABCJS.write.AbstractEngraver.prototype.reset=function(){this.slurs={},this.ties=[],this.slursbyvoice={},this.tiesbyvoice={},this.endingsbyvoice={},this.s=0,this.v=0,this.tripletmultiplier=1,this.abcline=void 0,this.accidentalSlot=void 0,this.accidentalshiftx=void 0,this.dotshiftx=void 0,this.hasVocals=!1,this.minY=void 0,this.partstartelem=void 0,this.pos=void 0,this.roomtaken=void 0,this.roomtakenright=void 0,this.staffgroup=void 0,this.startlimitelem=void 0,this.stemdir=void 0,this.voice=void 0},ABCJS.write.AbstractEngraver.prototype.setStemHeight=function(heightInPixels){this.stemHeight=heightInPixels/ABCJS.write.spacing.STEP},ABCJS.write.AbstractEngraver.prototype.getCurrentVoiceId=function(){return\"s\"+this.s+\"v\"+this.v},ABCJS.write.AbstractEngraver.prototype.pushCrossLineElems=function(){this.slursbyvoice[this.getCurrentVoiceId()]=this.slurs,this.tiesbyvoice[this.getCurrentVoiceId()]=this.ties,this.endingsbyvoice[this.getCurrentVoiceId()]=this.partstartelem},ABCJS.write.AbstractEngraver.prototype.popCrossLineElems=function(){this.slurs=this.slursbyvoice[this.getCurrentVoiceId()]||{},this.ties=this.tiesbyvoice[this.getCurrentVoiceId()]||[],this.partstartelem=this.endingsbyvoice[this.getCurrentVoiceId()]},ABCJS.write.AbstractEngraver.prototype.getElem=function(){return this.abcline.length<=this.pos?null:this.abcline[this.pos]},ABCJS.write.AbstractEngraver.prototype.getNextElem=function(){return this.abcline.length<=this.pos+1?null:this.abcline[this.pos+1]},ABCJS.write.AbstractEngraver.prototype.containsLyrics=function(staves){for(var i=0;i<staves.length;i++)for(var j=0;j<staves[i].voices.length;j++)for(var k=0;k<staves[i].voices[j].length;k++){var el=staves[i].voices[j][k];if(el.lyric)return void(el.positioning&&\"below\"!==el.positioning.vocalPosition||(this.hasVocals=!0))}},ABCJS.write.AbstractEngraver.prototype.createABCLine=function(staffs,tempo){for(this.minY=2,this.containsLyrics(staffs),this.staffgroup=new ABCJS.write.StaffGroupElement,this.tempoSet=!1,this.s=0;this.s<staffs.length;this.s++)ABCJS.write.hint&&this.restoreState(),ABCJS.write.hint=!1,this.createABCStaff(staffs[this.s],tempo);return this.staffgroup},ABCJS.write.AbstractEngraver.prototype.createABCStaff=function(abcstaff,tempo){for(this.v=0;this.v<abcstaff.voices.length;this.v++){this.voice=new ABCJS.write.VoiceElement(this.v,abcstaff.voices.length),0===this.v?(this.voice.barfrom=\"start\"===abcstaff.connectBarLines||\"continue\"===abcstaff.connectBarLines,this.voice.barto=\"continue\"===abcstaff.connectBarLines||\"end\"===abcstaff.connectBarLines):this.voice.duplicate=!0,abcstaff.title&&abcstaff.title[this.v]&&(this.voice.header=abcstaff.title[this.v]);var clef=ABCJS.write.createClef(abcstaff.clef,this.tuneNumber);clef&&(0===this.v&&abcstaff.barNumber&&this.addMeasureNumber(abcstaff.barNumber,clef),this.voice.addChild(clef));var keySig=ABCJS.write.createKeySignature(abcstaff.key,this.tuneNumber);if(keySig&&(this.voice.addChild(keySig),this.startlimitelem=keySig),abcstaff.meter){var ts=ABCJS.write.createTimeSignature(abcstaff.meter,this.tuneNumber);this.voice.addChild(ts),this.startlimitelem=ts}this.voice.duplicate&&(this.voice.children=[]);var staffLines=abcstaff.clef.stafflines||0===abcstaff.clef.stafflines?abcstaff.clef.stafflines:5;this.staffgroup.addVoice(this.voice,this.s,staffLines),this.createABCVoice(abcstaff.voices[this.v],tempo),this.staffgroup.setStaffLimits(this.voice),\"start\"===abcstaff.brace?this.staffgroup.brace=new ABCJS.write.BraceElem(1,!0):\"end\"===abcstaff.brace&&this.staffgroup.brace?this.staffgroup.brace.increaseStavesIncluded():\"continue\"===abcstaff.brace&&this.staffgroup.brace&&this.staffgroup.brace.increaseStavesIncluded()}},ABCJS.write.AbstractEngraver.prototype.createABCVoice=function(abcline,tempo){this.popCrossLineElems(),this.stemdir=this.isBagpipes?\"down\":null,this.abcline=abcline,this.partstartelem&&(this.partstartelem=new ABCJS.write.EndingElem(\"\",null,null),this.voice.addOther(this.partstartelem));for(var slur in this.slurs)this.slurs.hasOwnProperty(slur)&&(this.slurs[slur]=new ABCJS.write.TieElem(null,null,this.slurs[slur].above,this.slurs[slur].force,!1),ABCJS.write.hint&&this.slurs[slur].setHint(),this.voice.addOther(this.slurs[slur]));for(var i=0;i<this.ties.length;i++)this.ties[i]=new ABCJS.write.TieElem(null,null,this.ties[i].above,this.ties[i].force,!0),ABCJS.write.hint&&this.ties[i].setHint(),this.voice.addOther(this.ties[i]);for(this.pos=0;this.pos<this.abcline.length;this.pos++){var abselems=this.createABCElement();if(abselems)for(i=0;i<abselems.length;i++)this.tempoSet||!tempo||tempo.suppress||(this.tempoSet=!0,abselems[i].addChild(new ABCJS.write.TempoElement(tempo,this.tuneNumber))),this.voice.addChild(abselems[i])}this.pushCrossLineElems()},ABCJS.write.AbstractEngraver.prototype.saveState=function(){this.tiesSave=ABCJS.parse.cloneArray(this.ties),this.slursSave=ABCJS.parse.cloneHashOfHash(this.slurs),this.slursbyvoiceSave=ABCJS.parse.cloneHashOfHash(this.slursbyvoice),this.tiesbyvoiceSave=ABCJS.parse.cloneHashOfArrayOfHash(this.tiesbyvoice)},ABCJS.write.AbstractEngraver.prototype.restoreState=function(){this.ties=ABCJS.parse.cloneArray(this.tiesSave),this.slurs=ABCJS.parse.cloneHashOfHash(this.slursSave),this.slursbyvoice=ABCJS.parse.cloneHashOfHash(this.slursbyvoiceSave),this.tiesbyvoice=ABCJS.parse.cloneHashOfArrayOfHash(this.tiesbyvoiceSave)},ABCJS.write.AbstractEngraver.prototype.createABCElement=function(){var elemset=[],elem=this.getElem();switch(elem.el_type){case\"note\":elemset=this.createBeam();break;case\"bar\":elemset[0]=this.createBarLine(elem),this.voice.duplicate&&(elemset[0].invisible=!0);break;case\"meter\":elemset[0]=ABCJS.write.createTimeSignature(elem,this.tuneNumber),this.startlimitelem=elemset[0],this.voice.duplicate&&(elemset[0].invisible=!0);break;case\"clef\":if(elemset[0]=ABCJS.write.createClef(elem,this.tuneNumber),!elemset[0])return null;this.voice.duplicate&&(elemset[0].invisible=!0);break;case\"key\":var absKey=ABCJS.write.createKeySignature(elem,this.tuneNumber);absKey&&(elemset[0]=absKey,this.startlimitelem=elemset[0]),this.voice.duplicate&&(elemset[0].invisible=!0);break;case\"stem\":this.stemdir=elem.direction;break;case\"part\":var abselem=new ABCJS.write.AbsoluteElement(elem,0,0,\"part\",this.tuneNumber),dim=this.renderer.getTextSize(elem.title,\"partsfont\",\"part\");abselem.addChild(new ABCJS.write.RelativeElement(elem.title,0,0,void 0,{type:\"part\",height:dim.height/ABCJS.write.spacing.STEP})),elemset[0]=abselem;break;case\"tempo\":var abselem3=new ABCJS.write.AbsoluteElement(elem,0,0,\"tempo\",this.tuneNumber);abselem3.addChild(new ABCJS.write.TempoElement(elem,this.tuneNumber)),elemset[0]=abselem3;break;case\"style\":\"normal\"===elem.head?delete this.style:this.style=elem.head;break;case\"hint\":ABCJS.write.hint=!0,this.saveState();break;case\"midi\":break;default:var abselem2=new ABCJS.write.AbsoluteElement(elem,0,0,\"unsupported\",this.tuneNumber);abselem2.addChild(new ABCJS.write.RelativeElement(\"element type \"+elem.el_type,0,0,void 0,{type:\"debug\"})),elemset[0]=abselem2}return elemset},ABCJS.write.AbstractEngraver.prototype.calcBeamDir=function(){if(this.stemdir)return this.stemdir;for(var abselem,beamelem=new ABCJS.write.BeamElem(this.stemHeight,this.stemdir),oldPos=this.pos;this.getElem()&&(abselem=this.createNote(this.getElem(),!0,!0),beamelem.add(abselem),!this.getElem().endBeam);)this.pos++;var dir=beamelem.calcDir();return this.pos=oldPos,dir?\"up\":\"down\"},ABCJS.write.AbstractEngraver.prototype.createBeam=function(){var abselemset=[];if(this.getElem().startBeam&&!this.getElem().endBeam){var dir=this.calcBeamDir(),beamelem=new ABCJS.write.BeamElem(this.stemHeight,dir);ABCJS.write.hint&&beamelem.setHint();var oldDir=this.stemdir;for(this.stemdir=dir;this.getElem();){var abselem=this.createNote(this.getElem(),!0);if(abselemset.push(abselem),beamelem.add(abselem),this.triplet&&this.triplet.isClosed()&&(this.voice.addOther(this.triplet),this.triplet=null,this.tripletmultiplier=1),this.getElem().endBeam)break;this.pos++}this.stemdir=oldDir,this.voice.addBeam(beamelem)}else abselemset[0]=this.createNote(this.getElem()),this.triplet&&this.triplet.isClosed()&&(this.voice.addOther(this.triplet),this.triplet=null,this.tripletmultiplier=1);return abselemset},ABCJS.write.sortPitch=function(elem){var sorted;do{sorted=!0;for(var p=0;p<elem.pitches.length-1;p++)if(elem.pitches[p].pitch>elem.pitches[p+1].pitch){sorted=!1;var tmp=elem.pitches[p];elem.pitches[p]=elem.pitches[p+1],elem.pitches[p+1]=tmp}}while(!sorted)},ABCJS.write.ledgerLines=function(abselem,minPitch,maxPitch,isRest,c,additionalLedgers,dir,dx,scale){for(var i=maxPitch;i>11;i--)i%2!==0||isRest||abselem.addChild(new ABCJS.write.RelativeElement(null,dx,(ABCJS.write.glyphs.getSymbolWidth(c)+4)*scale,i,{type:\"ledger\"}));for(i=minPitch;i<1;i++)i%2!==0||isRest||abselem.addChild(new ABCJS.write.RelativeElement(null,dx,(ABCJS.write.glyphs.getSymbolWidth(c)+4)*scale,i,{type:\"ledger\"}));for(i=0;i<additionalLedgers.length;i++){var ofs=ABCJS.write.glyphs.getSymbolWidth(c);\"down\"===dir&&(ofs=-ofs),abselem.addChild(new ABCJS.write.RelativeElement(null,ofs+dx,(ABCJS.write.glyphs.getSymbolWidth(c)+4)*scale,additionalLedgers[i],{type:\"ledger\"}))}},ABCJS.write.AbstractEngraver.prototype.createNote=function(elem,nostem,dontDraw){var notehead=null,grace=null;this.roomtaken=0,this.roomtakenright=0;var p,i,pp,width,p1,p2,dx,dotshiftx=0,c=\"\",flag=null,additionalLedgers=[],duration=ABCJS.write.getDuration(elem),zeroDuration=!1;0===duration&&(zeroDuration=!0,duration=.25,nostem=!0);for(var durlog=Math.floor(Math.log(duration)/Math.log(2)),dot=0,tot=Math.pow(2,durlog),inc=tot/2;tot<duration;dot++,tot+=inc,inc/=2);elem.startTriplet&&(2===elem.startTriplet?this.tripletmultiplier=1.5:this.tripletmultiplier=(elem.startTriplet-1)/elem.startTriplet);var abselem=new ABCJS.write.AbsoluteElement(elem,duration*this.tripletmultiplier,1,\"note\",this.tuneNumber);if(ABCJS.write.hint&&abselem.setHint(),elem.rest){var restpitch=7;\"down\"===this.stemdir&&(restpitch=3),\"up\"===this.stemdir&&(restpitch=11);var numLines=this.staffgroup.staffs[this.staffgroup.staffs.length-1].lines;switch(1===numLines&&(restpitch=duration<.5?7:duration<1?6.8:4.8),elem.rest.type){case\"whole\":c=this.chartable.rest[0],elem.averagepitch=restpitch,elem.minpitch=restpitch,elem.maxpitch=restpitch,dot=0;break;case\"rest\":c=this.chartable.rest[-durlog],elem.averagepitch=restpitch,elem.minpitch=restpitch,elem.maxpitch=restpitch;break;case\"invisible\":case\"spacer\":c=\"\",elem.averagepitch=restpitch,elem.minpitch=restpitch,elem.maxpitch=restpitch}dontDraw||(notehead=this.createNoteHead(abselem,c,{verticalPos:restpitch},null,0,-this.roomtaken,null,dot,0,1)),notehead&&abselem.addHead(notehead),this.roomtaken+=this.accidentalshiftx,this.roomtakenright=Math.max(this.roomtakenright,this.dotshiftx)}else{ABCJS.write.sortPitch(elem);var sum=0;for(p=0,pp=elem.pitches.length;p<pp;p++)sum+=elem.pitches[p].verticalPos;elem.averagepitch=sum/elem.pitches.length,elem.minpitch=elem.pitches[0].verticalPos,this.minY=Math.min(elem.minpitch,this.minY),elem.maxpitch=elem.pitches[elem.pitches.length-1].verticalPos;var dir=elem.averagepitch>=6?\"down\":\"up\";this.stemdir&&(dir=this.stemdir);var style=elem.style?elem.style:this.style;style&&\"normal\"!==style||(style=\"note\");var noteSymbol;for(noteSymbol=zeroDuration?this.chartable[style].nostem:this.chartable[style][-durlog],noteSymbol||console.log(\"noteSymbol:\",style,durlog,zeroDuration),p=\"down\"===dir?elem.pitches.length-2:1;\"down\"===dir?p>=0:p<elem.pitches.length;p=\"down\"===dir?p-1:p+1){var prev=elem.pitches[\"down\"===dir?p+1:p-1],curr=elem.pitches[p],delta=\"down\"===dir?prev.pitch-curr.pitch:curr.pitch-prev.pitch;delta<=1&&!prev.printer_shift&&(curr.printer_shift=delta?\"different\":\"same\",(curr.verticalPos>11||curr.verticalPos<1)&&additionalLedgers.push(curr.verticalPos-curr.verticalPos%2),\"down\"===dir?this.roomtaken=ABCJS.write.glyphs.getSymbolWidth(noteSymbol)+2:dotshiftx=ABCJS.write.glyphs.getSymbolWidth(noteSymbol)+2)}for(this.accidentalSlot=[],p=0;p<elem.pitches.length;p++){nostem||(flag=\"down\"===dir&&0!==p||\"up\"===dir&&p!==pp-1?null:this.chartable[\"down\"===dir?\"dflags\":\"uflags\"][-durlog]),c=noteSymbol,elem.pitches[p].highestVert=elem.pitches[p].verticalPos;var isTopWhenStemIsDown=(\"up\"===this.stemdir||\"up\"===dir)&&0===p,isBottomWhenStemIsUp=(\"down\"===this.stemdir||\"down\"===dir)&&p===pp-1;if(!dontDraw&&(isTopWhenStemIsDown||isBottomWhenStemIsUp)){if((elem.startSlur||1===pp)&&(elem.pitches[p].highestVert=elem.pitches[pp-1].verticalPos,\"up\"!==this.stemdir&&\"up\"!==dir||(elem.pitches[p].highestVert+=6)),elem.startSlur)for(elem.pitches[p].startSlur||(elem.pitches[p].startSlur=[]),i=0;i<elem.startSlur.length;i++)elem.pitches[p].startSlur.push(elem.startSlur[i]);if(!dontDraw&&elem.endSlur)for(elem.pitches[p].highestVert=elem.pitches[pp-1].verticalPos,\"up\"!==this.stemdir&&\"up\"!==dir||(elem.pitches[p].highestVert+=6),elem.pitches[p].endSlur||(elem.pitches[p].endSlur=[]),i=0;i<elem.endSlur.length;i++)elem.pitches[p].endSlur.push(elem.endSlur[i])}var hasStem=!nostem&&durlog<=-1;dontDraw||(notehead=this.createNoteHead(abselem,c,elem.pitches[p],hasStem?dir:null,0,-this.roomtaken,flag,dot,dotshiftx,1)),notehead&&abselem.addHead(notehead),this.roomtaken+=this.accidentalshiftx,this.roomtakenright=Math.max(this.roomtakenright,this.dotshiftx)}hasStem&&(p1=\"down\"===dir?elem.minpitch-7:elem.minpitch+1/3,p1>6&&!this.stemdir&&(p1=6),p2=\"down\"===dir?elem.maxpitch-1/3:elem.maxpitch+7,p2<6&&!this.stemdir&&(p2=6),dx=\"down\"===dir||0===abselem.heads.length?0:abselem.heads[0].w,width=\"down\"===dir?1:-1,\"noteheads.slash.quarter\"===notehead.c&&(\"down\"===dir?p2-=1:p1+=1),abselem.addExtra(new ABCJS.write.RelativeElement(null,dx,0,p1,{type:\"stem\",pitch2:p2,linewidth:width})),this.minY=Math.min(p1,this.minY),this.minY=Math.min(p2,this.minY))}if(void 0!==elem.lyric){var lyricStr=\"\";window.ABCJS.parse.each(elem.lyric,function(ly){lyricStr+=ly.syllable+ly.divider+\"\\n\"});var lyricDim=this.renderer.getTextSize(lyricStr,\"vocalfont\",\"abc-lyric\"),position=elem.positioning?elem.positioning.vocalPosition:\"below\";abselem.addCentered(new ABCJS.write.RelativeElement(lyricStr,0,lyricDim.width,void 0,{type:\"lyric\",position:position,height:lyricDim.height/ABCJS.write.spacing.STEP}))}if(!dontDraw&&void 0!==elem.gracenotes){var gracescale=.6,graceScaleStem=.7,gracebeam=null;elem.gracenotes.length>1&&(gracebeam=new ABCJS.write.BeamElem(this.stemHeight*graceScaleStem,\"grace\",this.isBagpipes),\nABCJS.write.hint&&gracebeam.setHint(),gracebeam.mainNote=abselem);var graceoffsets=[];for(i=elem.gracenotes.length-1;i>=0;i--)this.roomtaken+=10,graceoffsets[i]=this.roomtaken,elem.gracenotes[i].accidental&&(this.roomtaken+=7);for(i=0;i<elem.gracenotes.length;i++){var gracepitch=elem.gracenotes[i].verticalPos;if(flag=gracebeam?null:this.chartable.uflags[this.isBagpipes?5:3],grace=this.createNoteHead(abselem,\"noteheads.quarter\",elem.gracenotes[i],\"up\",-graceoffsets[i],-graceoffsets[i],flag,0,0,gracescale),abselem.addExtra(grace),elem.gracenotes[i].acciaccatura){var pos=elem.gracenotes[i].verticalPos+7*gracescale,dAcciaccatura=gracebeam?5:6;abselem.addRight(new ABCJS.write.RelativeElement(\"flags.ugrace\",-graceoffsets[i]+dAcciaccatura,0,pos,{scalex:gracescale,scaley:gracescale}))}if(gracebeam){var graceDuration=elem.gracenotes[i].duration/2;this.isBagpipes&&(graceDuration/=2);var pseudoabselem={heads:[grace],abcelem:{averagepitch:gracepitch,minpitch:gracepitch,maxpitch:gracepitch,duration:graceDuration}};gracebeam.add(pseudoabselem)}else p1=gracepitch+1/3*gracescale,p2=gracepitch+7*gracescale,dx=grace.dx+grace.w,width=-.6,abselem.addExtra(new ABCJS.write.RelativeElement(null,dx,0,p1,{type:\"stem\",pitch2:p2,linewidth:width}));ABCJS.write.ledgerLines(abselem,gracepitch,gracepitch,!1,\"noteheads.quarter\",[],!0,grace.dx-1,.6),0!==i||this.isBagpipes||elem.rest&&(\"spacer\"===elem.rest.type||\"invisible\"===elem.rest.type)||this.voice.addOther(new ABCJS.write.TieElem(grace,notehead,!1,!0,!1))}gracebeam&&this.voice.addBeam(gracebeam)}!dontDraw&&elem.decoration&&this.decoration.createDecoration(this.voice,elem.decoration,abselem.top,notehead?notehead.w:0,abselem,this.roomtaken,dir,abselem.bottom,elem.positioning,this.hasVocals),elem.barNumber&&abselem.addChild(new ABCJS.write.RelativeElement(elem.barNumber,-10,0,0,{type:\"barNumber\"})),ABCJS.write.ledgerLines(abselem,elem.minpitch,elem.maxpitch,elem.rest,c,additionalLedgers,dir,-2,1);var chordMargin=8;if(void 0!==elem.chord)for(i=0;i<elem.chord.length;i++){var y,x=0,dim=this.renderer.getTextSize(elem.chord[i].name,\"annotationfont\",\"annotation\"),chordWidth=dim.width,chordHeight=dim.height/ABCJS.write.spacing.STEP;switch(elem.chord[i].position){case\"left\":this.roomtaken+=chordWidth+7,x=-this.roomtaken,y=elem.averagepitch,abselem.addExtra(new ABCJS.write.RelativeElement(elem.chord[i].name,x,chordWidth+4,y,{type:\"text\",height:chordHeight}));break;case\"right\":this.roomtakenright+=4,x=this.roomtakenright,y=elem.averagepitch,abselem.addRight(new ABCJS.write.RelativeElement(elem.chord[i].name,x,chordWidth+4,y,{type:\"text\",height:chordHeight}));break;case\"below\":for(var eachLine=elem.chord[i].name.split(\"\\n\"),ii=0;ii<eachLine.length;ii++)abselem.addRight(new ABCJS.write.RelativeElement(eachLine[ii],x,chordWidth+chordMargin,void 0,{type:\"text\",position:\"below\",height:chordHeight}));break;case\"above\":abselem.addRight(new ABCJS.write.RelativeElement(elem.chord[i].name,0,chordWidth+chordMargin,void 0,{type:\"text\",height:chordHeight}));break;default:if(elem.chord[i].rel_position){var relPositionY=elem.chord[i].rel_position.y+3*ABCJS.write.spacing.STEP;abselem.addChild(new ABCJS.write.RelativeElement(elem.chord[i].name,x+elem.chord[i].rel_position.x,0,elem.minpitch+relPositionY/ABCJS.write.spacing.STEP,{type:\"text\",height:chordHeight}))}else{var pos2=\"above\";elem.positioning&&elem.positioning.chordPosition&&(pos2=elem.positioning.chordPosition),dim=this.renderer.getTextSize(elem.chord[i].name,\"gchordfont\",\"chord\"),chordHeight=dim.height/ABCJS.write.spacing.STEP,chordWidth=dim.width,abselem.addCentered(new ABCJS.write.RelativeElement(elem.chord[i].name,x,chordWidth,void 0,{type:\"chord\",position:pos2,height:chordHeight}))}}}return elem.startTriplet&&!dontDraw&&(this.triplet=new ABCJS.write.TripletElem(elem.startTriplet,notehead)),elem.endTriplet&&this.triplet&&!dontDraw&&this.triplet.setCloseAnchor(notehead),abselem},ABCJS.write.AbstractEngraver.prototype.createNoteHead=function(abselem,c,pitchelem,dir,headx,extrax,flag,dot,dotshiftx,scale){var notehead,i,pitch=pitchelem.verticalPos;if(this.accidentalshiftx=0,this.dotshiftx=0,void 0===c)abselem.addChild(new ABCJS.write.RelativeElement(\"pitch is undefined\",0,0,0,{type:\"debug\"}));else if(\"\"===c)notehead=new ABCJS.write.RelativeElement(null,0,0,pitch);else{var shiftheadx=headx;if(pitchelem.printer_shift){var adjust=\"same\"===pitchelem.printer_shift?1:0;shiftheadx=\"down\"===dir?-ABCJS.write.glyphs.getSymbolWidth(c)*scale+adjust:ABCJS.write.glyphs.getSymbolWidth(c)*scale-adjust}var opts={scalex:scale,scaley:scale,thickness:ABCJS.write.glyphs.symbolHeightInPitches(c)*scale};if(notehead=new ABCJS.write.RelativeElement(c,shiftheadx,ABCJS.write.glyphs.getSymbolWidth(c)*scale,pitch,opts),flag){var pos=pitch+(\"down\"===dir?-7:7)*scale;(1===scale&&\"down\"===dir?pos>6:pos<6)&&(pos=6);var xdelta=\"down\"===dir?headx:headx+notehead.w-.6;abselem.addRight(new ABCJS.write.RelativeElement(flag,xdelta,ABCJS.write.glyphs.getSymbolWidth(flag)*scale,pos,{scalex:scale,scaley:scale}))}for(this.dotshiftx=notehead.w+dotshiftx-2+5*dot;dot>0;dot--){var dotadjusty=1-Math.abs(pitch)%2;abselem.addRight(new ABCJS.write.RelativeElement(\"dots.dot\",notehead.w+dotshiftx-2+5*dot,ABCJS.write.glyphs.getSymbolWidth(\"dots.dot\"),pitch+dotadjusty))}}if(notehead&&(notehead.highestVert=pitchelem.highestVert),pitchelem.accidental){var symb;switch(pitchelem.accidental){case\"quartersharp\":symb=\"accidentals.halfsharp\";break;case\"dblsharp\":symb=\"accidentals.dblsharp\";break;case\"sharp\":symb=\"accidentals.sharp\";break;case\"quarterflat\":symb=\"accidentals.halfflat\";break;case\"flat\":symb=\"accidentals.flat\";break;case\"dblflat\":symb=\"accidentals.dblflat\";break;case\"natural\":symb=\"accidentals.nat\"}for(var accSlotFound=!1,accPlace=extrax,j=0;j<this.accidentalSlot.length;j++)if(pitch-this.accidentalSlot[j][0]>=6){this.accidentalSlot[j][0]=pitch,accPlace=this.accidentalSlot[j][1],accSlotFound=!0;break}accSlotFound===!1&&(accPlace-=ABCJS.write.glyphs.getSymbolWidth(symb)*scale+2,this.accidentalSlot.push([pitch,accPlace]),this.accidentalshiftx=ABCJS.write.glyphs.getSymbolWidth(symb)*scale+2),abselem.addExtra(new ABCJS.write.RelativeElement(symb,accPlace,ABCJS.write.glyphs.getSymbolWidth(symb),pitch,{scalex:scale,scaley:scale}))}if(pitchelem.endTie&&this.ties[0]&&(this.ties[0].setEndAnchor(notehead),this.ties=this.ties.slice(1,this.ties.length)),pitchelem.startTie){var tie=new ABCJS.write.TieElem(notehead,null,(\"down\"===this.stemdir||\"down\"===dir)&&\"up\"!==this.stemdir,\"down\"===this.stemdir||\"up\"===this.stemdir,!0);ABCJS.write.hint&&tie.setHint(),this.ties[this.ties.length]=tie,this.voice.addOther(tie),abselem.startTie=!0}if(pitchelem.endSlur)for(i=0;i<pitchelem.endSlur.length;i++){var slur,slurid=pitchelem.endSlur[i];this.slurs[slurid]?(slur=this.slurs[slurid],slur.setEndAnchor(notehead),delete this.slurs[slurid]):(slur=new ABCJS.write.TieElem(null,notehead,\"down\"===dir,(\"up\"===this.stemdir||\"down\"===dir)&&\"down\"!==this.stemdir,!1),ABCJS.write.hint&&slur.setHint(),this.voice.addOther(slur)),this.startlimitelem&&slur.setStartX(this.startlimitelem)}if(pitchelem.startSlur)for(i=0;i<pitchelem.startSlur.length;i++){var slurid=pitchelem.startSlur[i].label,slur=new ABCJS.write.TieElem(notehead,null,(\"down\"===this.stemdir||\"down\"===dir)&&\"up\"!==this.stemdir,!1,!1);ABCJS.write.hint&&slur.setHint(),this.slurs[slurid]=slur,this.voice.addOther(slur)}return notehead},ABCJS.write.AbstractEngraver.prototype.addMeasureNumber=function(number,abselem){var measureNumHeight=this.renderer.getTextSize(number,\"measurefont\",\"bar-number\");abselem.addChild(new ABCJS.write.RelativeElement(number,0,0,11+measureNumHeight.height/ABCJS.write.spacing.STEP,{type:\"barNumber\"}))},ABCJS.write.AbstractEngraver.prototype.createBarLine=function(elem){var abselem=new ABCJS.write.AbsoluteElement(elem,0,10,\"bar\",this.tuneNumber),anchor=null,dx=0;elem.barNumber&&this.addMeasureNumber(elem.barNumber,abselem);var firstdots=\"bar_right_repeat\"===elem.type||\"bar_dbl_repeat\"===elem.type,firstthin=\"bar_left_repeat\"!==elem.type&&\"bar_thick_thin\"!==elem.type&&\"bar_invisible\"!==elem.type,thick=\"bar_right_repeat\"===elem.type||\"bar_dbl_repeat\"===elem.type||\"bar_left_repeat\"===elem.type||\"bar_thin_thick\"===elem.type||\"bar_thick_thin\"===elem.type,secondthin=\"bar_left_repeat\"===elem.type||\"bar_thick_thin\"===elem.type||\"bar_thin_thin\"===elem.type||\"bar_dbl_repeat\"===elem.type,seconddots=\"bar_left_repeat\"===elem.type||\"bar_dbl_repeat\"===elem.type;if(firstdots||seconddots){for(var slur in this.slurs)this.slurs.hasOwnProperty(slur)&&this.slurs[slur].setEndX(abselem);this.startlimitelem=abselem}if(firstdots&&(abselem.addRight(new ABCJS.write.RelativeElement(\"dots.dot\",dx,1,7)),abselem.addRight(new ABCJS.write.RelativeElement(\"dots.dot\",dx,1,5)),dx+=6),firstthin&&(anchor=new ABCJS.write.RelativeElement(null,dx,1,2,{type:\"bar\",pitch2:10,linewidth:.6}),abselem.addRight(anchor)),\"bar_invisible\"===elem.type&&(anchor=new ABCJS.write.RelativeElement(null,dx,1,2,{type:\"none\",pitch2:10,linewidth:.6}),abselem.addRight(anchor)),elem.decoration&&this.decoration.createDecoration(this.voice,elem.decoration,12,thick?3:1,abselem,0,\"down\",2,elem.positioning,this.hasVocals),thick&&(dx+=4,anchor=new ABCJS.write.RelativeElement(null,dx,4,2,{type:\"bar\",pitch2:10,linewidth:4}),abselem.addRight(anchor),dx+=5),this.partstartelem&&elem.endEnding&&(this.partstartelem.anchor2=anchor,this.partstartelem=null),secondthin&&(dx+=3,anchor=new ABCJS.write.RelativeElement(null,dx,1,2,{type:\"bar\",pitch2:10,linewidth:.6}),abselem.addRight(anchor)),seconddots&&(dx+=3,abselem.addRight(new ABCJS.write.RelativeElement(\"dots.dot\",dx,1,7)),abselem.addRight(new ABCJS.write.RelativeElement(\"dots.dot\",dx,1,5))),elem.startEnding){var textWidth=this.renderer.getTextSize(elem.startEnding,\"repeatfont\",\"\").width;abselem.minspacing+=textWidth+10,this.partstartelem=new ABCJS.write.EndingElem(elem.startEnding,anchor,null),this.voice.addOther(this.partstartelem)}return abselem}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),function(){\"use strict\";function minStem(element,stemsUp,referencePitch,minStemHeight){if(!element.children)return minStemHeight;for(var i=0;i<element.children.length;i++){var elem=element.children[i];stemsUp&&void 0!==elem.top&&\"flags.ugrace\"===elem.c?minStemHeight=Math.max(minStemHeight,elem.top-referencePitch):stemsUp||void 0===elem.bottom||\"flags.ugrace\"!==elem.c||(minStemHeight=Math.max(minStemHeight,referencePitch-elem.bottom+7))}return minStemHeight}function calcSlant(leftAveragePitch,rightAveragePitch,numStems,isFlat){if(isFlat)return 0;var slant=leftAveragePitch-rightAveragePitch,maxSlant=numStems/2;return slant>maxSlant&&(slant=maxSlant),slant<-maxSlant&&(slant=-maxSlant),slant}function calcAverage(total,numElements){return numElements?total/numElements:0}function getBarYAt(startx,starty,endx,endy,x){return starty+(endy-starty)/(endx-startx)*(x-startx)}function calcDy(asc,isGrace){var dy=asc?ABCJS.write.spacing.STEP:-ABCJS.write.spacing.STEP;return isGrace&&(dy*=.4),dy}function drawBeam(renderer,startX,startY,endX,endY,dy,isHint){var klass=\"beam-elem\";isHint&&(klass+=\" abcjs-hint\"),startY=renderer.calcY(startY),endY=renderer.calcY(endY);var pathString=\"M\"+startX+\" \"+startY+\" L\"+endX+\" \"+endY+\"L\"+endX+\" \"+(endY+dy)+\" L\"+startX+\" \"+(startY+dy)+\"z\";renderer.printPath({path:pathString,stroke:\"none\",fill:\"#000000\",class:renderer.addClasses(klass)})}function calcXPos(asc,firstElement,lastElement){var starthead=firstElement.heads[asc?0:firstElement.heads.length-1],endhead=lastElement.heads[asc?0:lastElement.heads.length-1],startX=starthead.x;asc&&(startX+=starthead.w-.6);var endX=endhead.x;return asc&&(endX+=endhead.w),[startX,endX]}function calcYPos(total,numElements,stemHeight,asc,firstAveragePitch,lastAveragePitch,isFlat,minPitch,maxPitch,isGrace){var average=calcAverage(total,numElements),barpos=stemHeight-2,barminpos=stemHeight-2,pos=Math.round(asc?Math.max(average+barpos,maxPitch+barminpos):Math.min(average-barpos,minPitch-barminpos)),slant=calcSlant(firstAveragePitch,lastAveragePitch,numElements,isFlat),startY=pos+Math.floor(slant/2),endY=pos+Math.floor(-slant/2);return isGrace||(asc&&pos<6?(startY=6,endY=6):!asc&&pos>6&&(startY=6,endY=6)),[startY,endY]}function createStems(elems,asc,beam,dy,mainNote){for(var i=0;i<elems.length;i++){var elem=elems[i];if(!elem.abcelem.rest){var isGrace=!elem.addExtra,parent=isGrace?mainNote:elem,furthestHead=elem.heads[asc?0:elem.heads.length-1],ovalDelta=.2,pitch=furthestHead.pitch+(asc?ovalDelta:-ovalDelta),dx=asc?furthestHead.w:0,x=furthestHead.x+dx,bary=getBarYAt(beam.startX,beam.startY,beam.endX,beam.endY,x),lineWidth=asc?-.6:.6;asc||(bary-=dy/2/ABCJS.write.spacing.STEP),isGrace&&(dx+=elem.heads[0].dx),\"noteheads.slash.quarter\"===furthestHead.c&&(asc?pitch+=1:pitch-=1);var stem=new ABCJS.write.RelativeElement(null,dx,0,pitch,{type:\"stem\",pitch2:bary,linewidth:lineWidth});stem.setX(parent.x),parent.addExtra(stem)}}}function createAdditionalBeams(elems,asc,beam,isGrace,dy){for(var beams=[],auxBeams=[],i=0;i<elems.length;i++){var elem=elems[i];if(!elem.abcelem.rest){var furthestHead=elem.heads[asc?0:elem.heads.length-1],x=furthestHead.x+(asc?furthestHead.w:0),bary=getBarYAt(beam.startX,beam.startY,beam.endX,beam.endY,x),sy=asc?-1.5:1.5;isGrace&&(sy=2*sy/3);var duration=elem.abcelem.duration;0===duration&&(duration=.25);for(var durlog=ABCJS.write.getDurlog(duration);durlog<-3;durlog++)auxBeams[-4-durlog]?auxBeams[-4-durlog].single=!1:auxBeams[-4-durlog]={x:x+(asc?-.6:0),y:bary+sy*(-4-durlog+1),durlog:durlog,single:!0};for(var j=auxBeams.length-1;j>=0;j--)if(i===elems.length-1||ABCJS.write.getDurlog(elems[i+1].abcelem.duration)>-j-4){var auxBeamEndX=x,auxBeamEndY=bary+sy*(j+1);auxBeams[j].single&&(auxBeamEndX=0===i?x+5:x-5,auxBeamEndY=getBarYAt(beam.startX,beam.startY,beam.endX,beam.endY,auxBeamEndX)+sy*(j+1)),beams.push({startX:auxBeams[j].x,endX:auxBeamEndX,startY:auxBeams[j].y,endY:auxBeamEndY,dy:dy}),auxBeams=auxBeams.slice(0,j)}}}return beams}ABCJS.write.BeamElem=function(stemHeight,type,flat){this.isflat=flat,this.isgrace=type&&\"grace\"===type,this.forceup=this.isgrace||type&&\"up\"===type,this.forcedown=type&&\"down\"===type,this.elems=[],this.total=0,this.allrests=!0,this.stemHeight=stemHeight,this.beams=[]},ABCJS.write.BeamElem.prototype.setHint=function(){this.hint=!0},ABCJS.write.BeamElem.prototype.add=function(abselem){var pitch=abselem.abcelem.averagepitch;void 0!==pitch&&(this.allrests=this.allrests&&abselem.abcelem.rest,abselem.beam=this,this.elems.push(abselem),this.total+=pitch,(!this.min||abselem.abcelem.minpitch<this.min)&&(this.min=abselem.abcelem.minpitch),(!this.max||abselem.abcelem.maxpitch>this.max)&&(this.max=abselem.abcelem.maxpitch))};var middleLine=6;ABCJS.write.BeamElem.prototype.calcDir=function(){if(this.forceup)return!0;if(this.forcedown)return!1;var average=calcAverage(this.total,this.elems.length);return average<middleLine},ABCJS.write.BeamElem.prototype.layout=function(){if(0!==this.elems.length&&!this.allrests){this.stemsUp=this.calcDir();var dy=calcDy(this.stemsUp,this.isgrace),firstElement=this.elems[0],lastElement=this.elems[this.elems.length-1],minStemHeight=0,referencePitch=this.stemsUp?firstElement.abcelem.maxpitch:firstElement.abcelem.minpitch;minStemHeight=minStem(firstElement,this.stemsUp,referencePitch,minStemHeight),minStemHeight=minStem(lastElement,this.stemsUp,referencePitch,minStemHeight),minStemHeight=Math.max(this.stemHeight,minStemHeight+3);var yPos=calcYPos(this.total,this.elems.length,minStemHeight,this.stemsUp,firstElement.abcelem.averagepitch,lastElement.abcelem.averagepitch,this.isflat,this.min,this.max,this.isgrace),xPos=calcXPos(this.stemsUp,firstElement,lastElement);this.beams.push({startX:xPos[0],endX:xPos[1],startY:yPos[0],endY:yPos[1],dy:dy});for(var beams=createAdditionalBeams(this.elems,this.stemsUp,this.beams[0],this.isgrace,dy),i=0;i<beams.length;i++)this.beams.push(beams[i]);createStems(this.elems,this.stemsUp,this.beams[0],dy,this.mainNote)}},ABCJS.write.BeamElem.prototype.isAbove=function(){return this.stemsUp},ABCJS.write.BeamElem.prototype.heightAtMidpoint=function(startX,endX){if(0===this.beams.length)return 0;var beam=this.beams[0],midPoint=startX+(endX-startX)/2;return getBarYAt(beam.startX,beam.startY,beam.endX,beam.endY,midPoint)},ABCJS.write.BeamElem.prototype.yAtNote=function(element){var beam=this.beams[0];return getBarYAt(beam.startX,beam.startY,beam.endX,beam.endY,element.x)},ABCJS.write.BeamElem.prototype.xAtMidpoint=function(startX,endX){return startX+(endX-startX)/2},ABCJS.write.BeamElem.prototype.draw=function(renderer){if(0!==this.beams.length){renderer.beginGroup();for(var i=0;i<this.beams.length;i++){var beam=this.beams[i];drawBeam(renderer,beam.startX,beam.startY,beam.endX,beam.endY,beam.dy,this.hint)}renderer.endGroup(\"beam-elem\")}}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.BraceElem=function(){this.length=1},ABCJS.write.BraceElem.prototype.increaseStavesIncluded=function(){this.length++},ABCJS.write.BraceElem.prototype.setLocation=function(x){this.x=x},ABCJS.write.BraceElem.prototype.getWidth=function(){return 10},ABCJS.write.BraceElem.prototype.layout=function(renderer,top,bottom){this.startY=top,this.endY=bottom},ABCJS.write.BraceElem.prototype.draw=function(renderer,top,bottom){this.layout(renderer,top,bottom),renderer.drawBrace(this.x,this.startY,this.endY)},window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),function(){\"use strict\";ABCJS.write.createClef=function(elem,tuneNumber){var clef,octave=0,abselem=new ABCJS.write.AbsoluteElement(elem,0,10,\"staff-extra\",tuneNumber);switch(elem.type){case\"treble\":clef=\"clefs.G\";break;case\"tenor\":clef=\"clefs.C\";break;case\"alto\":clef=\"clefs.C\";break;case\"bass\":clef=\"clefs.F\";break;case\"treble+8\":clef=\"clefs.G\",octave=1;break;case\"tenor+8\":clef=\"clefs.C\",octave=1;break;case\"bass+8\":clef=\"clefs.F\",octave=1;break;case\"alto+8\":clef=\"clefs.C\",octave=1;break;case\"treble-8\":clef=\"clefs.G\",octave=-1;break;case\"tenor-8\":clef=\"clefs.C\",octave=-1;break;case\"bass-8\":clef=\"clefs.F\",octave=-1;break;case\"alto-8\":clef=\"clefs.C\",octave=-1;break;case\"none\":return null;case\"perc\":clef=\"clefs.perc\";break;default:abselem.addChild(new ABCJS.write.RelativeElement(\"clef=\"+elem.type,0,0,void 0,{type:\"debug\"}))}var dx=5;if(clef&&(abselem.addRight(new ABCJS.write.RelativeElement(clef,dx,ABCJS.write.glyphs.getSymbolWidth(clef),elem.clefPos)),\"clefs.G\"===clef?(abselem.top=13,abselem.bottom=-1):(abselem.top=10,abselem.bottom=2),0!==octave)){var scale=2/3,adjustspacing=(ABCJS.write.glyphs.getSymbolWidth(clef)-ABCJS.write.glyphs.getSymbolWidth(\"8\")*scale)/2;abselem.addRight(new ABCJS.write.RelativeElement(\"8\",dx+adjustspacing,ABCJS.write.glyphs.getSymbolWidth(\"8\")*scale,octave>0?abselem.top+3:abselem.bottom-1,{scalex:scale,scaley:scale})),abselem.top+=2}return abselem}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),function(){\"use strict\";ABCJS.write.createKeySignature=function(elem,tuneNumber){if(!elem.accidentals||0===elem.accidentals.length)return null;var abselem=new ABCJS.write.AbsoluteElement(elem,0,10,\"staff-extra\",tuneNumber),dx=0;return window.ABCJS.parse.each(elem.accidentals,function(acc){var symbol=\"sharp\"===acc.acc?\"accidentals.sharp\":\"natural\"===acc.acc?\"accidentals.nat\":\"accidentals.flat\";abselem.addRight(new ABCJS.write.RelativeElement(symbol,dx,ABCJS.write.glyphs.getSymbolWidth(symbol),acc.verticalPos,{thickness:ABCJS.write.glyphs.symbolHeightInPitches(symbol)})),dx+=ABCJS.write.glyphs.getSymbolWidth(symbol)+2},this),abselem}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),function(){\"use strict\";ABCJS.write.createTimeSignature=function(elem,tuneNumber){var abselem=new ABCJS.write.AbsoluteElement(elem,0,10,\"staff-extra\",tuneNumber);if(\"specified\"===elem.type)for(var i=0;i<elem.value.length;i++)0!==i&&abselem.addRight(new ABCJS.write.RelativeElement(\"+\",20*i-9,ABCJS.write.glyphs.getSymbolWidth(\"+\"),6,{thickness:ABCJS.write.glyphs.symbolHeightInPitches(\"+\")})),elem.value[i].den?(abselem.addRight(new ABCJS.write.RelativeElement(elem.value[i].num,20*i,ABCJS.write.glyphs.getSymbolWidth(elem.value[i].num.charAt(0))*elem.value[i].num.length,8,{thickness:ABCJS.write.glyphs.symbolHeightInPitches(elem.value[i].num.charAt(0))})),abselem.addRight(new ABCJS.write.RelativeElement(elem.value[i].den,20*i,ABCJS.write.glyphs.getSymbolWidth(elem.value[i].den.charAt(0))*elem.value[i].den.length,4,{thickness:ABCJS.write.glyphs.symbolHeightInPitches(elem.value[i].den.charAt(0))}))):abselem.addRight(new ABCJS.write.RelativeElement(elem.value[i].num,20*i,ABCJS.write.glyphs.getSymbolWidth(elem.value[i].num.charAt(0))*elem.value[i].num.length,6,{thickness:ABCJS.write.glyphs.symbolHeightInPitches(elem.value[i].num.charAt(0))}));else\"common_time\"===elem.type?abselem.addRight(new ABCJS.write.RelativeElement(\"timesig.common\",0,ABCJS.write.glyphs.getSymbolWidth(\"timesig.common\"),6,{thickness:ABCJS.write.glyphs.symbolHeightInPitches(\"timesig.common\")})):\"cut_time\"===elem.type&&abselem.addRight(new ABCJS.write.RelativeElement(\"timesig.cut\",0,ABCJS.write.glyphs.getSymbolWidth(\"timesig.cut\"),6,{thickness:ABCJS.write.glyphs.symbolHeightInPitches(\"timesig.cut\")}));return abselem}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.CrescendoElem=function(anchor1,anchor2,dir,positioning){this.anchor1=anchor1,this.anchor2=anchor2,this.dir=dir,\"above\"===positioning?this.dynamicHeightAbove=4:this.dynamicHeightBelow=4,this.pitch=void 0},ABCJS.write.CrescendoElem.prototype.setUpperAndLowerElements=function(positionY){this.dynamicHeightAbove?this.pitch=positionY.dynamicHeightAbove:this.pitch=positionY.dynamicHeightBelow},ABCJS.write.CrescendoElem.prototype.draw=function(renderer){void 0===this.pitch&&window.console.error(\"Crescendo Element y-coordinate not set.\");var y=renderer.calcY(this.pitch)+4,height=8;\"<\"===this.dir?(this.drawLine(renderer,y+height/2,y),this.drawLine(renderer,y+height/2,y+height)):(this.drawLine(renderer,y,y+height/2),this.drawLine(renderer,y+height,y+height/2))},ABCJS.write.CrescendoElem.prototype.drawLine=function(renderer,y1,y2){var left=this.anchor1?this.anchor1.x:0,right=this.anchor2?this.anchor2.x:800,pathString=ABCJS.write.sprintf(\"M %f %f L %f %f\",left,y1,right,y2);renderer.printPath({path:pathString,stroke:\"#000000\",class:renderer.addClasses(\"decoration\")})},window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),function(){\"use strict\";ABCJS.write.Decoration=function(){this.startDiminuendoX=void 0,this.startCrescendoX=void 0,this.minTop=12,this.minBottom=0};var closeDecoration=function(voice,decoration,pitch,width,abselem,roomtaken,dir,minPitch){for(var yPos,i=0;i<decoration.length;i++){if(\"staccato\"===decoration[i]||\"tenuto\"===decoration[i]||\"accent\"===decoration[i]){var symbol=\"scripts.\"+decoration[i];if(\"accent\"===decoration[i]&&(symbol=\"scripts.sforzato\"),yPos=void 0===yPos?\"down\"===dir?pitch+2:minPitch-2:\"down\"===dir?yPos+2:yPos-2,\"accent\"===decoration[i])\"up\"===dir?yPos--:yPos++;else switch(yPos){case 2:case 4:case 6:case 8:case 10:\"up\"===dir?yPos--:yPos++}pitch>9&&yPos++;var deltaX=width/2;\"center\"!==ABCJS.write.glyphs.getSymbolAlign(symbol)&&(deltaX-=ABCJS.write.glyphs.getSymbolWidth(symbol)/2),abselem.addChild(new ABCJS.write.RelativeElement(symbol,deltaX,ABCJS.write.glyphs.getSymbolWidth(symbol),yPos))}if(\"slide\"===decoration[i]&&abselem.heads[0]){var yPos2=abselem.heads[0].pitch;yPos2-=2;var blank1=new ABCJS.write.RelativeElement(\"\",-roomtaken-15,0,yPos2-1),blank2=new ABCJS.write.RelativeElement(\"\",-roomtaken-5,0,yPos2+1);abselem.addChild(blank1),abselem.addChild(blank2),voice.addOther(new ABCJS.write.TieElem(blank1,blank2,!1,!1,!1))}}return void 0===yPos&&(yPos=pitch),{above:yPos,below:abselem.bottom}},volumeDecoration=function(voice,decoration,abselem,positioning){for(var i=0;i<decoration.length;i++)switch(decoration[i]){case\"p\":case\"mp\":case\"pp\":case\"ppp\":case\"pppp\":case\"f\":case\"ff\":case\"fff\":case\"ffff\":case\"sfz\":case\"mf\":var elem=new ABCJS.write.DynamicDecoration(abselem,decoration[i],positioning);voice.addOther(elem)}},compoundDecoration=function(decoration,pitch,width,abselem,dir){function highestPitch(){if(0===abselem.heads.length)return 10;for(var pitch=abselem.heads[0].pitch,i=1;i<abselem.heads.length;i++)pitch=Math.max(pitch,abselem.heads[i].pitch);return pitch}function lowestPitch(){if(0===abselem.heads.length)return 2;for(var pitch=abselem.heads[0].pitch,i=1;i<abselem.heads.length;i++)pitch=Math.min(pitch,abselem.heads[i].pitch);return pitch}function compoundDecoration(symbol,count){var placement=\"down\"===dir?lowestPitch()+1:highestPitch()+9;\"down\"!==dir&&1===count&&placement--;var deltaX=width/2;deltaX+=\"down\"===dir?-5:3;for(var i=0;i<count;i++)placement-=1,abselem.addChild(new ABCJS.write.RelativeElement(symbol,deltaX,ABCJS.write.glyphs.getSymbolWidth(symbol),placement))}for(var i=0;i<decoration.length;i++)switch(decoration[i]){case\"/\":compoundDecoration(\"flags.ugrace\",1);break;case\"//\":compoundDecoration(\"flags.ugrace\",2);break;case\"///\":compoundDecoration(\"flags.ugrace\",3);break;case\"////\":compoundDecoration(\"flags.ugrace\",4)}},stackedDecoration=function(decoration,width,abselem,yPos,positioning,minTop,minBottom){function incrementPlacement(placement,height){\"above\"===placement?yPos.above+=height:yPos.below-=height}function getPlacement(placement){var y;return\"above\"===placement?(y=yPos.above,y<minTop&&(y=minTop)):(y=yPos.below,y>minBottom&&(y=minBottom)),y}function textDecoration(text,placement){var y=getPlacement(placement),textFudge=2,textHeight=5;abselem.addChild(new ABCJS.write.RelativeElement(text,width/2,0,y+textFudge,{type:\"decoration\",klass:\"ornament\",thickness:3})),incrementPlacement(placement,textHeight)}function symbolDecoration(symbol,placement){var deltaX=width/2;\"center\"!==ABCJS.write.glyphs.getSymbolAlign(symbol)&&(deltaX-=ABCJS.write.glyphs.getSymbolWidth(symbol)/2);var height=ABCJS.write.glyphs.symbolHeightInPitches(symbol)+1,y=getPlacement(placement);y=\"above\"===placement?y+height/2:y-height/2,abselem.addChild(new ABCJS.write.RelativeElement(symbol,deltaX,ABCJS.write.glyphs.getSymbolWidth(symbol),y,{klass:\"ornament\",thickness:ABCJS.write.glyphs.symbolHeightInPitches(symbol)})),incrementPlacement(placement,height)}for(var symbolList={\"+\":\"scripts.stopped\",open:\"scripts.open\",snap:\"scripts.snap\",wedge:\"scripts.wedge\",thumb:\"scripts.thumb\",shortphrase:\"scripts.shortphrase\",mediumphrase:\"scripts.mediumphrase\",longphrase:\"scripts.longphrase\",trill:\"scripts.trill\",roll:\"scripts.roll\",irishroll:\"scripts.roll\",marcato:\"scripts.umarcato\",dmarcato:\"scripts.dmarcato\",umarcato:\"scripts.umarcato\",turn:\"scripts.turn\",uppermordent:\"scripts.prall\",pralltriller:\"scripts.prall\",mordent:\"scripts.mordent\",lowermordent:\"scripts.mordent\",downbow:\"scripts.downbow\",upbow:\"scripts.upbow\",fermata:\"scripts.ufermata\",invertedfermata:\"scripts.dfermata\",breath:\",\",coda:\"scripts.coda\",segno:\"scripts.segno\"},hasOne=!1,i=0;i<decoration.length;i++)switch(decoration[i]){case\"0\":case\"1\":case\"2\":case\"3\":case\"4\":case\"5\":case\"D.C.\":case\"D.S.\":textDecoration(decoration[i],positioning),hasOne=!0;break;case\"fine\":textDecoration(\"FINE\",positioning),hasOne=!0;break;case\"+\":case\"open\":case\"snap\":case\"wedge\":case\"thumb\":case\"shortphrase\":case\"mediumphrase\":case\"longphrase\":case\"trill\":case\"roll\":case\"irishroll\":case\"marcato\":case\"dmarcato\":case\"turn\":case\"uppermordent\":case\"pralltriller\":case\"mordent\":case\"lowermordent\":case\"downbow\":case\"upbow\":case\"fermata\":case\"breath\":case\"umarcato\":case\"coda\":case\"segno\":symbolDecoration(symbolList[decoration[i]],positioning),hasOne=!0;break;case\"invertedfermata\":symbolDecoration(symbolList[decoration[i]],\"below\"),hasOne=!0;break;case\"mark\":abselem.klass=\"mark\"}return hasOne};ABCJS.write.Decoration.prototype.dynamicDecoration=function(voice,decoration,abselem,positioning){for(var diminuendo,crescendo,i=0;i<decoration.length;i++)switch(decoration[i]){case\"diminuendo(\":this.startDiminuendoX=abselem,diminuendo=void 0;break;case\"diminuendo)\":diminuendo={start:this.startDiminuendoX,stop:abselem},this.startDiminuendoX=void 0;break;case\"crescendo(\":this.startCrescendoX=abselem,crescendo=void 0;break;case\"crescendo)\":crescendo={start:this.startCrescendoX,stop:abselem},this.startCrescendoX=void 0}diminuendo&&voice.addOther(new ABCJS.write.CrescendoElem(diminuendo.start,diminuendo.stop,\">\",positioning)),crescendo&&voice.addOther(new ABCJS.write.CrescendoElem(crescendo.start,crescendo.stop,\"<\",positioning))},ABCJS.write.Decoration.prototype.createDecoration=function(voice,decoration,pitch,width,abselem,roomtaken,dir,minPitch,positioning,hasVocals){positioning||(positioning={ornamentPosition:\"above\",volumePosition:hasVocals?\"above\":\"below\",dynamicPosition:hasVocals?\"above\":\"below\"}),volumeDecoration(voice,decoration,abselem,positioning.volumePosition),this.dynamicDecoration(voice,decoration,abselem,positioning.dynamicPosition),compoundDecoration(decoration,pitch,width,abselem,dir);var yPos=closeDecoration(voice,decoration,pitch,width,abselem,roomtaken,dir,minPitch);yPos.above=Math.max(yPos.above,this.minTop);stackedDecoration(decoration,width,abselem,yPos,positioning.ornamentPosition,this.minTop,this.minBottom)}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.DynamicDecoration=function(anchor,dec,position){this.anchor=anchor,this.dec=dec,\"below\"===position?this.volumeHeightBelow=5:this.volumeHeightAbove=5,this.pitch=void 0},ABCJS.write.DynamicDecoration.prototype.setUpperAndLowerElements=function(positionY){this.volumeHeightAbove?this.pitch=positionY.volumeHeightAbove:this.pitch=positionY.volumeHeightBelow},ABCJS.write.DynamicDecoration.prototype.draw=function(renderer,linestartx,lineendx){void 0===this.pitch&&window.console.error(\"Dynamic Element y-coordinate not set.\");var scalex=1,scaley=1;renderer.printSymbol(this.anchor.x,this.pitch,this.dec,scalex,scaley,renderer.addClasses(\"decoration\"))},window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.EndingElem=function(text,anchor1,anchor2){this.text=text,this.anchor1=anchor1,this.anchor2=anchor2,this.endingHeightAbove=5,this.pitch=void 0},ABCJS.write.EndingElem.prototype.setUpperAndLowerElements=function(positionY){this.pitch=positionY.endingHeightAbove},ABCJS.write.EndingElem.prototype.draw=function(renderer,linestartx,lineendx){void 0===this.pitch&&window.console.error(\"Ending Element y-coordinate not set.\");var pathString,y=renderer.calcY(this.pitch),height=20;this.anchor1&&(linestartx=this.anchor1.x+this.anchor1.w,pathString=ABCJS.write.sprintf(\"M %f %f L %f %f\",linestartx,y,linestartx,y+height),renderer.printPath({path:pathString,stroke:\"#000000\",fill:\"#000000\",class:renderer.addClasses(\"ending\")}),renderer.renderText(linestartx+5,renderer.calcY(this.pitch-.5),this.text,\"repeatfont\",\"ending\",\"start\")),this.anchor2&&(lineendx=this.anchor2.x,pathString=ABCJS.write.sprintf(\"M %f %f L %f %f\",lineendx,y,lineendx,y+height),renderer.printPath({path:pathString,stroke:\"#000000\",fill:\"#000000\",class:renderer.addClasses(\"ending\")})),pathString=ABCJS.write.sprintf(\"M %f %f L %f %f\",linestartx,y,lineendx,y),renderer.printPath({path:pathString,stroke:\"#000000\",fill:\"#000000\",class:renderer.addClasses(\"ending\")})},window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.spacing=function(){},ABCJS.write.spacing.FONTEM=360,ABCJS.write.spacing.FONTSIZE=30,ABCJS.write.spacing.STEP=93*ABCJS.write.spacing.FONTSIZE/720,ABCJS.write.spacing.SPACE=10,ABCJS.write.spacing.TOPNOTE=15,ABCJS.write.spacing.STAVEHEIGHT=100,ABCJS.write.spacing.INDENT=50,ABCJS.write.debugPlacement=!1,ABCJS.write.EngraverController=function(paper,params){params=params||{},this.space=3*ABCJS.write.spacing.SPACE,this.scale=params.scale||void 0,params.staffwidth?(this.staffwidthScreen=params.staffwidth,this.staffwidthPrint=params.staffwidth):(this.staffwidthScreen=740,this.staffwidthPrint=680),\nthis.editable=params.editable||!1,this.listeners=[],params.listener&&this.addSelectListener(params.listener),this.usingSvg=!(!window.SVGAngle&&!document.implementation.hasFeature(\"http://www.w3.org/TR/SVG11/feature#BasicStructure\",\"1.1\")),this.usingSvg&&params.add_classes&&(Raphael._availableAttrs.class=\"\"),Raphael._availableAttrs[\"text-decoration\"]=\"\",Raphael._availableAttrs[\"data-vertical\"]=\"\",this.renderer=new ABCJS.write.Renderer(paper,params.regression),this.renderer.setPaddingOverride(params),this.renderer.controller=this,this.reset()},ABCJS.write.EngraverController.prototype.reset=function(){this.selected=[],this.ingroup=!1,this.staffgroups=[],this.lastStaffGroupIndex=-1,this.engraver&&this.engraver.reset(),this.engraver=null,this.renderer.reset()},ABCJS.write.EngraverController.prototype.engraveABC=function(abctunes){void 0===abctunes[0]&&(abctunes=[abctunes]),this.reset();for(var i=0;i<abctunes.length;i++)this.engraveTune(abctunes[i],i);if(this.renderer.doRegression)return this.renderer.regressionLines.join(\"\\n\")},ABCJS.write.EngraverController.prototype.adjustNonScaledItems=function(scale){this.width/=scale,this.renderer.adjustNonScaledItems(scale)},ABCJS.write.EngraverController.prototype.engraveTune=function(abctune,tuneNumber){this.renderer.lineNumber=null,abctune.formatting.tripletfont={face:\"Times\",size:11,weight:\"normal\",style:\"italic\",decoration:\"none\"},this.renderer.abctune=abctune,this.renderer.setVerticalSpace(abctune.formatting),this.renderer.measureNumber=null,this.renderer.setPrintMode(\"print\"===abctune.media);var scale=abctune.formatting.scale?abctune.formatting.scale:this.scale;void 0===scale&&(scale=this.renderer.isPrint?.75:1),this.renderer.setPadding(abctune),this.engraver=new ABCJS.write.AbstractEngraver(abctune.formatting.bagpipes,this.renderer,tuneNumber),this.engraver.setStemHeight(this.renderer.spacing.stemHeight),this.renderer.engraver=this.engraver,abctune.formatting.staffwidth?this.width=1.33*abctune.formatting.staffwidth:this.width=this.renderer.isPrint?this.staffwidthPrint:this.staffwidthScreen,this.adjustNonScaledItems(scale);var i,abcLine,hasPrintedTempo=!1;for(i=0;i<abctune.lines.length;i++)abcLine=abctune.lines[i],abcLine.staff&&(abcLine.staffGroup=this.engraver.createABCLine(abcLine.staff,hasPrintedTempo?null:abctune.metaText.tempo),hasPrintedTempo=!0);var maxWidth=this.width;for(i=0;i<abctune.lines.length;i++)abcLine=abctune.lines[i],abcLine.staff&&(this.setXSpacing(abcLine.staffGroup,abctune.formatting,i===abctune.lines.length-1),abcLine.staffGroup.w>maxWidth&&(maxWidth=abcLine.staffGroup.w));for(i=0;i<abctune.lines.length;i++)if(abcLine=abctune.lines[i],abcLine.staffGroup&&abcLine.staffGroup.voices){for(var j=0;j<abcLine.staffGroup.voices.length;j++)abcLine.staffGroup.voices[j].layoutBeams();abcLine.staffGroup.setUpperAndLowerElements(this.renderer)}for(i=0;i<abctune.lines.length;i++)abcLine=abctune.lines[i],abcLine.staffGroup&&(abcLine.staffGroup.height=abcLine.staffGroup.calcHeight());this.renderer.topMargin(abctune),this.renderer.engraveTopText(this.width,abctune),this.renderer.addMusicPadding(),this.staffgroups=[],this.lastStaffGroupIndex=-1;for(var line=0;line<abctune.lines.length;line++)this.renderer.lineNumber=line,abcLine=abctune.lines[line],abcLine.staff?this.engraveStaffLine(abcLine.staffGroup):abcLine.subtitle&&0!==line?this.renderer.outputSubtitle(this.width,abcLine.subtitle):void 0!==abcLine.text&&this.renderer.outputFreeText(abcLine.text);this.renderer.moveY(24),this.renderer.engraveExtraText(this.width,abctune),this.renderer.setPaperSize(maxWidth,scale)},ABCJS.write.EngraverController.prototype.setXSpacing=function(staffGroup,formatting,isLastLine){for(var newspace=this.space,it=0;it<3;it++){staffGroup.layout(newspace,this.renderer,!1);var stretchLast=!!formatting.stretchlast&&formatting.stretchlast;if(newspace=calcHorizontalSpacing(isLastLine,stretchLast,this.width+this.renderer.padding.left,staffGroup.w,newspace,staffGroup.spacingunits,staffGroup.minspace),null===newspace)break}centerWholeRests(staffGroup.voices)},ABCJS.write.EngraverController.prototype.engraveStaffLine=function(staffGroup){this.lastStaffGroupIndex>-1&&this.renderer.addStaffPadding(this.staffgroups[this.lastStaffGroupIndex],staffGroup),this.renderer.voiceNumber=null,staffGroup.draw(this.renderer);var height=staffGroup.height*ABCJS.write.spacing.STEP;this.staffgroups[this.staffgroups.length]=staffGroup,this.lastStaffGroupIndex=this.staffgroups.length-1,this.renderer.y+=height},ABCJS.write.EngraverController.prototype.notifySelect=function(abselem,tuneNumber){this.clearSelection(),abselem.highlight&&(this.selected=[abselem],abselem.highlight());for(var abcelem=abselem.abcelem||{},i=0;i<this.listeners.length;i++)this.listeners[i].highlight&&this.listeners[i].highlight(abcelem,tuneNumber)},ABCJS.write.EngraverController.prototype.notifyChange=function(){for(var i=0;i<this.listeners.length;i++)this.listeners[i].modelChanged&&this.listeners[i].modelChanged()},ABCJS.write.EngraverController.prototype.clearSelection=function(){for(var i=0;i<this.selected.length;i++)this.selected[i].unhighlight();this.selected=[]},ABCJS.write.EngraverController.prototype.addSelectListener=function(listener){this.listeners[this.listeners.length]=listener},ABCJS.write.EngraverController.prototype.rangeHighlight=function(start,end){this.clearSelection();for(var line=0;line<this.staffgroups.length;line++)for(var voices=this.staffgroups[line].voices,voice=0;voice<voices.length;voice++)for(var elems=voices[voice].children,elem=0;elem<elems.length;elem++){var elStart=elems[elem].abcelem.startChar,elEnd=elems[elem].abcelem.endChar;(end>elStart&&start<elEnd||end===start&&end===elEnd)&&(this.selected[this.selected.length]=elems[elem],elems[elem].highlight())}},window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.Glyphs=function(){\"use strict\";var glyphs={0:{d:[[\"M\",4.83,-14.97],[\"c\",.33,-.03,1.11,0,1.47,.06],[\"c\",1.68,.36,2.97,1.59,3.78,3.6],[\"c\",1.2,2.97,.81,6.96,-.9,9.27],[\"c\",-.78,1.08,-1.71,1.71,-2.91,1.95],[\"c\",-.45,.09,-1.32,.09,-1.77,0],[\"c\",-.81,-.18,-1.47,-.51,-2.07,-1.02],[\"c\",-2.34,-2.07,-3.15,-6.72,-1.74,-10.2],[\"c\",.87,-2.16,2.28,-3.42,4.14,-3.66],[\"z\"],[\"m\",1.11,.87],[\"c\",-.21,-.06,-.69,-.09,-.87,-.06],[\"c\",-.54,.12,-.87,.42,-1.17,.99],[\"c\",-.36,.66,-.51,1.56,-.6,3],[\"c\",-.03,.75,-.03,4.59,0,5.31],[\"c\",.09,1.5,.27,2.4,.6,3.06],[\"c\",.24,.48,.57,.78,.96,.9],[\"c\",.27,.09,.78,.09,1.05,0],[\"c\",.39,-.12,.72,-.42,.96,-.9],[\"c\",.33,-.66,.51,-1.56,.6,-3.06],[\"c\",.03,-.72,.03,-4.56,0,-5.31],[\"c\",-.09,-1.47,-.27,-2.37,-.6,-3.03],[\"c\",-.24,-.48,-.54,-.78,-.93,-.9],[\"z\"]],w:10.78,h:14.959},1:{d:[[\"M\",3.3,-15.06],[\"c\",.06,-.06,.21,-.03,.66,.15],[\"c\",.81,.39,1.08,.39,1.83,.03],[\"c\",.21,-.09,.39,-.15,.42,-.15],[\"c\",.12,0,.21,.09,.27,.21],[\"c\",.06,.12,.06,.33,.06,5.94],[\"c\",0,3.93,0,5.85,.03,6.03],[\"c\",.06,.36,.15,.69,.27,.96],[\"c\",.36,.75,.93,1.17,1.68,1.26],[\"c\",.3,.03,.39,.09,.39,.3],[\"c\",0,.15,-.03,.18,-.09,.24],[\"c\",-.06,.06,-.09,.06,-.48,.06],[\"c\",-.42,0,-.69,-.03,-2.1,-.24],[\"c\",-.9,-.15,-1.77,-.15,-2.67,0],[\"c\",-1.41,.21,-1.68,.24,-2.1,.24],[\"c\",-.39,0,-.42,0,-.48,-.06],[\"c\",-.06,-.06,-.06,-.09,-.06,-.24],[\"c\",0,-.21,.06,-.27,.36,-.3],[\"c\",.75,-.09,1.32,-.51,1.68,-1.26],[\"c\",.12,-.27,.21,-.6,.27,-.96],[\"c\",.03,-.18,.03,-1.59,.03,-4.29],[\"c\",0,-3.87,0,-4.05,-.06,-4.14],[\"c\",-.09,-.15,-.18,-.24,-.39,-.24],[\"c\",-.12,0,-.15,.03,-.21,.06],[\"c\",-.03,.06,-.45,.99,-.96,2.13],[\"c\",-.48,1.14,-.9,2.1,-.93,2.16],[\"c\",-.06,.15,-.21,.24,-.33,.24],[\"c\",-.24,0,-.42,-.18,-.42,-.39],[\"c\",0,-.06,3.27,-7.62,3.33,-7.74],[\"z\"]],w:8.94,h:15.058},2:{d:[[\"M\",4.23,-14.97],[\"c\",.57,-.06,1.68,0,2.34,.18],[\"c\",.69,.18,1.5,.54,2.01,.9],[\"c\",1.35,.96,1.95,2.25,1.77,3.81],[\"c\",-.15,1.35,-.66,2.34,-1.68,3.15],[\"c\",-.6,.48,-1.44,.93,-3.12,1.65],[\"c\",-1.32,.57,-1.8,.81,-2.37,1.14],[\"c\",-.57,.33,-.57,.33,-.24,.27],[\"c\",.39,-.09,1.26,-.09,1.68,0],[\"c\",.72,.15,1.41,.45,2.1,.9],[\"c\",.99,.63,1.86,.87,2.55,.75],[\"c\",.24,-.06,.42,-.15,.57,-.3],[\"c\",.12,-.09,.3,-.42,.3,-.51],[\"c\",0,-.09,.12,-.21,.24,-.24],[\"c\",.18,-.03,.39,.12,.39,.3],[\"c\",0,.12,-.15,.57,-.3,.87],[\"c\",-.54,1.02,-1.56,1.74,-2.79,2.01],[\"c\",-.42,.09,-1.23,.09,-1.62,.03],[\"c\",-.81,-.18,-1.32,-.45,-2.01,-1.11],[\"c\",-.45,-.45,-.63,-.57,-.96,-.69],[\"c\",-.84,-.27,-1.89,.12,-2.25,.9],[\"c\",-.12,.21,-.21,.54,-.21,.72],[\"c\",0,.12,-.12,.21,-.27,.24],[\"c\",-.15,0,-.27,-.03,-.33,-.15],[\"c\",-.09,-.21,.09,-1.08,.33,-1.71],[\"c\",.24,-.66,.66,-1.26,1.29,-1.89],[\"c\",.45,-.45,.9,-.81,1.92,-1.56],[\"c\",1.29,-.93,1.89,-1.44,2.34,-1.98],[\"c\",.87,-1.05,1.26,-2.19,1.2,-3.63],[\"c\",-.06,-1.29,-.39,-2.31,-.96,-2.91],[\"c\",-.36,-.33,-.72,-.51,-1.17,-.54],[\"c\",-.84,-.03,-1.53,.42,-1.59,1.05],[\"c\",-.03,.33,.12,.6,.57,1.14],[\"c\",.45,.54,.54,.87,.42,1.41],[\"c\",-.15,.63,-.54,1.11,-1.08,1.38],[\"c\",-.63,.33,-1.2,.33,-1.83,0],[\"c\",-.24,-.12,-.33,-.18,-.54,-.39],[\"c\",-.18,-.18,-.27,-.3,-.36,-.51],[\"c\",-.24,-.45,-.27,-.84,-.21,-1.38],[\"c\",.12,-.75,.45,-1.41,1.02,-1.98],[\"c\",.72,-.72,1.74,-1.17,2.85,-1.32],[\"z\"]],w:10.764,h:14.97},3:{d:[[\"M\",3.78,-14.97],[\"c\",.3,-.03,1.41,0,1.83,.06],[\"c\",2.22,.3,3.51,1.32,3.72,2.91],[\"c\",.03,.33,.03,1.26,-.03,1.65],[\"c\",-.12,.84,-.48,1.47,-1.05,1.77],[\"c\",-.27,.15,-.36,.24,-.45,.39],[\"c\",-.09,.21,-.09,.36,0,.57],[\"c\",.09,.15,.18,.24,.51,.39],[\"c\",.75,.42,1.23,1.14,1.41,2.13],[\"c\",.06,.42,.06,1.35,0,1.71],[\"c\",-.18,.81,-.48,1.38,-1.02,1.95],[\"c\",-.75,.72,-1.8,1.2,-3.18,1.38],[\"c\",-.42,.06,-1.56,.06,-1.95,0],[\"c\",-1.89,-.33,-3.18,-1.29,-3.51,-2.64],[\"c\",-.03,-.12,-.03,-.33,-.03,-.6],[\"c\",0,-.36,0,-.42,.06,-.63],[\"c\",.12,-.3,.27,-.51,.51,-.75],[\"c\",.24,-.24,.45,-.39,.75,-.51],[\"c\",.21,-.06,.27,-.06,.6,-.06],[\"c\",.33,0,.39,0,.6,.06],[\"c\",.3,.12,.51,.27,.75,.51],[\"c\",.36,.33,.57,.75,.6,1.2],[\"c\",0,.21,0,.27,-.06,.42],[\"c\",-.09,.18,-.12,.24,-.54,.54],[\"c\",-.51,.36,-.63,.54,-.6,.87],[\"c\",.06,.54,.54,.9,1.38,.99],[\"c\",.36,.06,.72,.03,.96,-.06],[\"c\",.81,-.27,1.29,-1.23,1.44,-2.79],[\"c\",.03,-.45,.03,-1.95,-.03,-2.37],[\"c\",-.09,-.75,-.33,-1.23,-.75,-1.44],[\"c\",-.33,-.18,-.45,-.18,-1.98,-.18],[\"c\",-1.35,0,-1.41,0,-1.5,-.06],[\"c\",-.18,-.12,-.24,-.39,-.12,-.6],[\"c\",.12,-.15,.15,-.15,1.68,-.15],[\"c\",1.5,0,1.62,0,1.89,-.15],[\"c\",.18,-.09,.42,-.36,.54,-.57],[\"c\",.18,-.42,.27,-.9,.3,-1.95],[\"c\",.03,-1.2,-.06,-1.8,-.36,-2.37],[\"c\",-.24,-.48,-.63,-.81,-1.14,-.96],[\"c\",-.3,-.06,-1.08,-.06,-1.38,.03],[\"c\",-.6,.15,-.9,.42,-.96,.84],[\"c\",-.03,.3,.06,.45,.63,.84],[\"c\",.33,.24,.42,.39,.45,.63],[\"c\",.03,.72,-.57,1.5,-1.32,1.65],[\"c\",-1.05,.27,-2.1,-.57,-2.1,-1.65],[\"c\",0,-.45,.15,-.96,.39,-1.38],[\"c\",.12,-.21,.54,-.63,.81,-.81],[\"c\",.57,-.42,1.38,-.69,2.25,-.81],[\"z\"]],w:9.735,h:14.967},4:{d:[[\"M\",8.64,-14.94],[\"c\",.27,-.09,.42,-.12,.54,-.03],[\"c\",.09,.06,.15,.21,.15,.3],[\"c\",-.03,.06,-1.92,2.31,-4.23,5.04],[\"c\",-2.31,2.73,-4.23,4.98,-4.26,5.01],[\"c\",-.03,.06,.12,.06,2.55,.06],[\"l\",2.61,0],[\"l\",0,-2.37],[\"c\",0,-2.19,.03,-2.37,.06,-2.46],[\"c\",.03,-.06,.21,-.18,.57,-.42],[\"c\",1.08,-.72,1.38,-1.08,1.86,-2.16],[\"c\",.12,-.3,.24,-.54,.27,-.57],[\"c\",.12,-.12,.39,-.06,.45,.12],[\"c\",.06,.09,.06,.57,.06,3.96],[\"l\",0,3.9],[\"l\",1.08,0],[\"c\",1.05,0,1.11,0,1.2,.06],[\"c\",.24,.15,.24,.54,0,.69],[\"c\",-.09,.06,-.15,.06,-1.2,.06],[\"l\",-1.08,0],[\"l\",0,.33],[\"c\",0,.57,.09,1.11,.3,1.53],[\"c\",.36,.75,.93,1.17,1.68,1.26],[\"c\",.3,.03,.39,.09,.39,.3],[\"c\",0,.15,-.03,.18,-.09,.24],[\"c\",-.06,.06,-.09,.06,-.48,.06],[\"c\",-.42,0,-.69,-.03,-2.1,-.24],[\"c\",-.9,-.15,-1.77,-.15,-2.67,0],[\"c\",-1.41,.21,-1.68,.24,-2.1,.24],[\"c\",-.39,0,-.42,0,-.48,-.06],[\"c\",-.06,-.06,-.06,-.09,-.06,-.24],[\"c\",0,-.21,.06,-.27,.36,-.3],[\"c\",.75,-.09,1.32,-.51,1.68,-1.26],[\"c\",.21,-.42,.3,-.96,.3,-1.53],[\"l\",0,-.33],[\"l\",-2.7,0],[\"c\",-2.91,0,-2.85,0,-3.09,-.15],[\"c\",-.18,-.12,-.3,-.39,-.27,-.54],[\"c\",.03,-.06,.18,-.24,.33,-.45],[\"c\",.75,-.9,1.59,-2.07,2.13,-3.03],[\"c\",.33,-.54,.84,-1.62,1.05,-2.16],[\"c\",.57,-1.41,.84,-2.64,.9,-4.05],[\"c\",.03,-.63,.06,-.72,.24,-.81],[\"l\",.12,-.06],[\"l\",.45,.12],[\"c\",.66,.18,1.02,.24,1.47,.27],[\"c\",.6,.03,1.23,-.09,2.01,-.33],[\"z\"]],w:11.795,h:14.994},5:{d:[[\"M\",1.02,-14.94],[\"c\",.12,-.09,.03,-.09,1.08,.06],[\"c\",2.49,.36,4.35,.36,6.96,-.06],[\"c\",.57,-.09,.66,-.06,.81,.06],[\"c\",.15,.18,.12,.24,-.15,.51],[\"c\",-1.29,1.26,-3.24,2.04,-5.58,2.31],[\"c\",-.6,.09,-1.2,.12,-1.71,.12],[\"c\",-.39,0,-.45,0,-.57,.06],[\"c\",-.09,.06,-.15,.12,-.21,.21],[\"l\",-.06,.12],[\"l\",0,1.65],[\"l\",0,1.65],[\"l\",.21,-.21],[\"c\",.66,-.57,1.41,-.96,2.19,-1.14],[\"c\",.33,-.06,1.41,-.06,1.95,0],[\"c\",2.61,.36,4.02,1.74,4.26,4.14],[\"c\",.03,.45,.03,1.08,-.03,1.44],[\"c\",-.18,1.02,-.78,2.01,-1.59,2.7],[\"c\",-.72,.57,-1.62,1.02,-2.49,1.2],[\"c\",-1.38,.27,-3.03,.06,-4.2,-.54],[\"c\",-1.08,-.54,-1.71,-1.32,-1.86,-2.28],[\"c\",-.09,-.69,.09,-1.29,.57,-1.74],[\"c\",.24,-.24,.45,-.39,.75,-.51],[\"c\",.21,-.06,.27,-.06,.6,-.06],[\"c\",.33,0,.39,0,.6,.06],[\"c\",.3,.12,.51,.27,.75,.51],[\"c\",.36,.33,.57,.75,.6,1.2],[\"c\",0,.21,0,.27,-.06,.42],[\"c\",-.09,.18,-.12,.24,-.54,.54],[\"c\",-.18,.12,-.36,.3,-.42,.33],[\"c\",-.36,.42,-.18,.99,.36,1.26],[\"c\",.51,.27,1.47,.36,2.01,.27],[\"c\",.93,-.21,1.47,-1.17,1.65,-2.91],[\"c\",.06,-.45,.06,-1.89,0,-2.31],[\"c\",-.15,-1.2,-.51,-2.1,-1.05,-2.55],[\"c\",-.21,-.18,-.54,-.36,-.81,-.39],[\"c\",-.3,-.06,-.84,-.03,-1.26,.06],[\"c\",-.93,.18,-1.65,.6,-2.16,1.2],[\"c\",-.15,.21,-.27,.3,-.39,.3],[\"c\",-.15,0,-.3,-.09,-.36,-.18],[\"c\",-.06,-.09,-.06,-.15,-.06,-3.66],[\"c\",0,-3.39,0,-3.57,.06,-3.66],[\"c\",.03,-.06,.09,-.15,.15,-.18],[\"z\"]],w:10.212,h:14.997},6:{d:[[\"M\",4.98,-14.97],[\"c\",.36,-.03,1.2,0,1.59,.06],[\"c\",.9,.15,1.68,.51,2.25,1.05],[\"c\",.57,.51,.87,1.23,.84,1.98],[\"c\",-.03,.51,-.21,.9,-.6,1.26],[\"c\",-.24,.24,-.45,.39,-.75,.51],[\"c\",-.21,.06,-.27,.06,-.6,.06],[\"c\",-.33,0,-.39,0,-.6,-.06],[\"c\",-.3,-.12,-.51,-.27,-.75,-.51],[\"c\",-.39,-.36,-.57,-.78,-.57,-1.26],[\"c\",0,-.27,0,-.3,.09,-.42],[\"c\",.03,-.09,.18,-.21,.3,-.3],[\"c\",.12,-.09,.3,-.21,.39,-.27],[\"c\",.09,-.06,.21,-.18,.27,-.24],[\"c\",.06,-.12,.09,-.15,.09,-.33],[\"c\",0,-.18,-.03,-.24,-.09,-.36],[\"c\",-.24,-.39,-.75,-.6,-1.38,-.57],[\"c\",-.54,.03,-.9,.18,-1.23,.48],[\"c\",-.81,.72,-1.08,2.16,-.96,5.37],[\"l\",0,.63],[\"l\",.3,-.12],[\"c\",.78,-.27,1.29,-.33,2.1,-.27],[\"c\",1.47,.12,2.49,.54,3.27,1.29],[\"c\",.48,.51,.81,1.11,.96,1.89],[\"c\",.06,.27,.06,.42,.06,.93],[\"c\",0,.54,0,.69,-.06,.96],[\"c\",-.15,.78,-.48,1.38,-.96,1.89],[\"c\",-.54,.51,-1.17,.87,-1.98,1.08],[\"c\",-1.14,.3,-2.4,.33,-3.24,.03],[\"c\",-1.5,-.48,-2.64,-1.89,-3.27,-4.02],[\"c\",-.36,-1.23,-.51,-2.82,-.42,-4.08],[\"c\",.3,-3.66,2.28,-6.3,4.95,-6.66],[\"z\"],[\"m\",.66,7.41],[\"c\",-.27,-.09,-.81,-.12,-1.08,-.06],[\"c\",-.72,.18,-1.08,.69,-1.23,1.71],[\"c\",-.06,.54,-.06,3,0,3.54],[\"c\",.18,1.26,.72,1.77,1.8,1.74],[\"c\",.39,-.03,.63,-.09,.9,-.27],[\"c\",.66,-.42,.9,-1.32,.9,-3.24],[\"c\",0,-2.22,-.36,-3.12,-1.29,-3.42],[\"z\"]],w:9.956,h:14.982},7:{d:[[\"M\",.21,-14.97],[\"c\",.21,-.06,.45,0,.54,.15],[\"c\",.06,.09,.06,.15,.06,.39],[\"c\",0,.24,0,.33,.06,.42],[\"c\",.06,.12,.21,.24,.27,.24],[\"c\",.03,0,.12,-.12,.24,-.21],[\"c\",.96,-1.2,2.58,-1.35,3.99,-.42],[\"c\",.15,.12,.42,.3,.54,.45],[\"c\",.48,.39,.81,.57,1.29,.6],[\"c\",.69,.03,1.5,-.3,2.13,-.87],[\"c\",.09,-.09,.27,-.3,.39,-.45],[\"c\",.12,-.15,.24,-.27,.3,-.3],[\"c\",.18,-.06,.39,.03,.51,.21],[\"c\",.06,.18,.06,.24,-.27,.72],[\"c\",-.18,.24,-.54,.78,-.78,1.17],[\"c\",-2.37,3.54,-3.54,6.27,-3.87,9],[\"c\",-.03,.33,-.03,.66,-.03,1.26],[\"c\",0,.9,0,1.08,.15,1.89],[\"c\",.06,.45,.06,.48,.03,.6],[\"c\",-.06,.09,-.21,.21,-.3,.21],[\"c\",-.03,0,-.27,-.06,-.54,-.15],[\"c\",-.84,-.27,-1.11,-.3,-1.65,-.3],[\"c\",-.57,0,-.84,.03,-1.56,.27],[\"c\",-.6,.18,-.69,.21,-.81,.15],[\"c\",-.12,-.06,-.21,-.18,-.21,-.3],[\"c\",0,-.15,.6,-1.44,1.2,-2.61],[\"c\",1.14,-2.22,2.73,-4.68,5.1,-8.01],[\"c\",.21,-.27,.36,-.48,.33,-.48],[\"c\",0,0,-.12,.06,-.27,.12],[\"c\",-.54,.3,-.99,.39,-1.56,.39],[\"c\",-.75,.03,-1.2,-.18,-1.83,-.75],[\"c\",-.99,-.9,-1.83,-1.17,-2.31,-.72],[\"c\",-.18,.15,-.36,.51,-.45,.84],[\"c\",-.06,.24,-.06,.33,-.09,1.98],[\"c\",0,1.62,-.03,1.74,-.06,1.8],[\"c\",-.15,.24,-.54,.24,-.69,0],[\"c\",-.06,-.09,-.06,-.15,-.06,-3.57],[\"c\",0,-3.42,0,-3.48,.06,-3.57],[\"c\",.03,-.06,.09,-.12,.15,-.15],[\"z\"]],w:10.561,h:15.093},8:{d:[[\"M\",4.98,-14.97],[\"c\",.33,-.03,1.02,-.03,1.32,0],[\"c\",1.32,.12,2.49,.6,3.21,1.32],[\"c\",.39,.39,.66,.81,.78,1.29],[\"c\",.09,.36,.09,1.08,0,1.44],[\"c\",-.21,.84,-.66,1.59,-1.59,2.55],[\"l\",-.3,.3],[\"l\",.27,.18],[\"c\",1.47,.93,2.31,2.31,2.25,3.75],[\"c\",-.03,.75,-.24,1.35,-.63,1.95],[\"c\",-.45,.66,-1.02,1.14,-1.83,1.53],[\"c\",-1.8,.87,-4.2,.87,-6,.03],[\"c\",-1.62,-.78,-2.52,-2.16,-2.46,-3.66],[\"c\",.06,-.99,.54,-1.77,1.8,-2.97],[\"c\",.54,-.51,.54,-.54,.48,-.57],[\"c\",-.39,-.27,-.96,-.78,-1.2,-1.14],[\"c\",-.75,-1.11,-.87,-2.4,-.3,-3.6],[\"c\",.69,-1.35,2.25,-2.25,4.2,-2.4],[\"z\"],[\"m\",1.53,.69],[\"c\",-.42,-.09,-1.11,-.12,-1.38,-.06],[\"c\",-.3,.06,-.6,.18,-.81,.3],[\"c\",-.21,.12,-.6,.51,-.72,.72],[\"c\",-.51,.87,-.42,1.89,.21,2.52],[\"c\",.21,.21,.36,.3,1.95,1.23],[\"c\",.96,.54,1.74,.99,1.77,1.02],[\"c\",.09,0,.63,-.6,.99,-1.11],[\"c\",.21,-.36,.48,-.87,.57,-1.23],[\"c\",.06,-.24,.06,-.36,.06,-.72],[\"c\",0,-.45,-.03,-.66,-.15,-.99],[\"c\",-.39,-.81,-1.29,-1.44,-2.49,-1.68],[\"z\"],[\"m\",-1.44,8.07],[\"l\",-1.89,-1.08],[\"c\",-.03,0,-.18,.15,-.39,.33],[\"c\",-1.2,1.08,-1.65,1.95,-1.59,3],[\"c\",.09,1.59,1.35,2.85,3.21,3.24],[\"c\",.33,.06,.45,.06,.93,.06],[\"c\",.63,0,.81,-.03,1.29,-.27],[\"c\",.9,-.42,1.47,-1.41,1.41,-2.4],[\"c\",-.06,-.66,-.39,-1.29,-.9,-1.65],[\"c\",-.12,-.09,-1.05,-.63,-2.07,-1.23],[\"z\"]],w:10.926,h:14.989},9:{d:[[\"M\",4.23,-14.97],[\"c\",.42,-.03,1.29,0,1.62,.06],[\"c\",.51,.12,.93,.3,1.38,.57],[\"c\",1.53,1.02,2.52,3.24,2.73,5.94],[\"c\",.18,2.55,-.48,4.98,-1.83,6.57],[\"c\",-1.05,1.26,-2.4,1.89,-3.93,1.83],[\"c\",-1.23,-.06,-2.31,-.45,-3.03,-1.14],[\"c\",-.57,-.51,-.87,-1.23,-.84,-1.98],[\"c\",.03,-.51,.21,-.9,.6,-1.26],[\"c\",.24,-.24,.45,-.39,.75,-.51],[\"c\",.21,-.06,.27,-.06,.6,-.06],[\"c\",.33,0,.39,0,.6,.06],[\"c\",.3,.12,.51,.27,.75,.51],[\"c\",.39,.36,.57,.78,.57,1.26],[\"c\",0,.27,0,.3,-.09,.42],[\"c\",-.03,.09,-.18,.21,-.3,.3],[\"c\",-.12,.09,-.3,.21,-.39,.27],[\"c\",-.09,.06,-.21,.18,-.27,.24],[\"c\",-.06,.12,-.06,.15,-.06,.33],[\"c\",0,.18,0,.24,.06,.36],[\"c\",.24,.39,.75,.6,1.38,.57],[\"c\",.54,-.03,.9,-.18,1.23,-.48],[\"c\",.81,-.72,1.08,-2.16,.96,-5.37],[\"l\",0,-.63],[\"l\",-.3,.12],[\"c\",-.78,.27,-1.29,.33,-2.1,.27],[\"c\",-1.47,-.12,-2.49,-.54,-3.27,-1.29],[\"c\",-.48,-.51,-.81,-1.11,-.96,-1.89],[\"c\",-.06,-.27,-.06,-.42,-.06,-.96],[\"c\",0,-.51,0,-.66,.06,-.93],[\"c\",.15,-.78,.48,-1.38,.96,-1.89],[\"c\",.15,-.12,.33,-.27,.42,-.36],[\"c\",.69,-.51,1.62,-.81,2.76,-.93],[\"z\"],[\"m\",1.17,.66],[\"c\",-.21,-.06,-.57,-.06,-.81,-.03],[\"c\",-.78,.12,-1.26,.69,-1.41,1.74],[\"c\",-.12,.63,-.15,1.95,-.09,2.79],[\"c\",.12,1.71,.63,2.4,1.77,2.46],[\"c\",1.08,.03,1.62,-.48,1.8,-1.74],[\"c\",.06,-.54,.06,-3,0,-3.54],[\"c\",-.15,-1.05,-.51,-1.53,-1.26,-1.68],[\"z\"]],w:9.959,h:14.986},\"rests.whole\":{d:[[\"M\",.06,.03],[\"l\",.09,-.06],[\"l\",5.46,0],[\"l\",5.49,0],[\"l\",.09,.06],[\"l\",.06,.09],[\"l\",0,2.19],[\"l\",0,2.19],[\"l\",-.06,.09],[\"l\",-.09,.06],[\"l\",-5.49,0],[\"l\",-5.46,0],[\"l\",-.09,-.06],[\"l\",-.06,-.09],[\"l\",0,-2.19],[\"l\",0,-2.19],[\"z\"]],w:11.25,h:4.68},\"rests.half\":{d:[[\"M\",.06,-4.62],[\"l\",.09,-.06],[\"l\",5.46,0],[\"l\",5.49,0],[\"l\",.09,.06],[\"l\",.06,.09],[\"l\",0,2.19],[\"l\",0,2.19],[\"l\",-.06,.09],[\"l\",-.09,.06],[\"l\",-5.49,0],[\"l\",-5.46,0],[\"l\",-.09,-.06],[\"l\",-.06,-.09],[\"l\",0,-2.19],[\"l\",0,-2.19],[\"z\"]],w:11.25,h:4.68},\"rests.quarter\":{d:[[\"M\",1.89,-11.82],[\"c\",.12,-.06,.24,-.06,.36,-.03],[\"c\",.09,.06,4.74,5.58,4.86,5.82],[\"c\",.21,.39,.15,.78,-.15,1.26],[\"c\",-.24,.33,-.72,.81,-1.62,1.56],[\"c\",-.45,.36,-.87,.75,-.96,.84],[\"c\",-.93,.99,-1.14,2.49,-.6,3.63],[\"c\",.18,.39,.27,.48,1.32,1.68],[\"c\",1.92,2.25,1.83,2.16,1.83,2.34],[\"c\",0,.18,-.18,.36,-.36,.39],[\"c\",-.15,0,-.27,-.06,-.48,-.27],[\"c\",-.75,-.75,-2.46,-1.29,-3.39,-1.08],[\"c\",-.45,.09,-.69,.27,-.9,.69],[\"c\",-.12,.3,-.21,.66,-.24,1.14],[\"c\",-.03,.66,.09,1.35,.3,2.01],[\"c\",.15,.42,.24,.66,.45,.96],[\"c\",.18,.24,.18,.33,.03,.42],[\"c\",-.12,.06,-.18,.03,-.45,-.3],[\"c\",-1.08,-1.38,-2.07,-3.36,-2.4,-4.83],[\"c\",-.27,-1.05,-.15,-1.77,.27,-2.07],[\"c\",.21,-.12,.42,-.15,.87,-.15],[\"c\",.87,.06,2.1,.39,3.3,.9],[\"l\",.39,.18],[\"l\",-1.65,-1.95],[\"c\",-2.52,-2.97,-2.61,-3.09,-2.7,-3.27],[\"c\",-.09,-.24,-.12,-.48,-.03,-.75],[\"c\",.15,-.48,.57,-.96,1.83,-2.01],[\"c\",.45,-.36,.84,-.72,.93,-.78],[\"c\",.69,-.75,1.02,-1.8,.9,-2.79],[\"c\",-.06,-.33,-.21,-.84,-.39,-1.11],[\"c\",-.09,-.15,-.45,-.6,-.81,-1.05],[\"c\",-.36,-.42,-.69,-.81,-.72,-.87],[\"c\",-.09,-.18,0,-.42,.21,-.51],[\"z\"]],w:7.888,h:21.435},\"rests.8th\":{d:[[\"M\",1.68,-6.12],[\"c\",.66,-.09,1.23,.09,1.68,.51],[\"c\",.27,.3,.39,.54,.57,1.26],[\"c\",.09,.33,.18,.66,.21,.72],[\"c\",.12,.27,.33,.45,.6,.48],[\"c\",.12,0,.18,0,.33,-.09],[\"c\",.39,-.18,1.32,-1.29,1.68,-1.98],[\"c\",.09,-.21,.24,-.3,.39,-.3],[\"c\",.12,0,.27,.09,.33,.18],[\"c\",.03,.06,-.27,1.11,-1.86,6.42],[\"c\",-1.02,3.48,-1.89,6.39,-1.92,6.42],[\"c\",0,.03,-.12,.12,-.24,.15],[\"c\",-.18,.09,-.21,.09,-.45,.09],[\"c\",-.24,0,-.3,0,-.48,-.06],[\"c\",-.09,-.06,-.21,-.12,-.21,-.15],[\"c\",-.06,-.03,.15,-.57,1.68,-4.92],[\"c\",.96,-2.67,1.74,-4.89,1.71,-4.89],[\"l\",-.51,.15],[\"c\",-1.08,.36,-1.74,.48,-2.55,.48],[\"c\",-.66,0,-.84,-.03,-1.32,-.27],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.33,-.45,.84,-.81,1.38,-.9],[\"z\"]],w:7.534,h:13.883},\"rests.16th\":{d:[[\"M\",3.33,-6.12],[\"c\",.66,-.09,1.23,.09,1.68,.51],[\"c\",.27,.3,.39,.54,.57,1.26],[\"c\",.09,.33,.18,.66,.21,.72],[\"c\",.15,.39,.57,.57,.87,.42],[\"c\",.39,-.18,1.2,-1.23,1.62,-2.07],[\"c\",.06,-.15,.24,-.24,.36,-.24],[\"c\",.12,0,.27,.09,.33,.18],[\"c\",.03,.06,-.45,1.86,-2.67,10.17],[\"c\",-1.5,5.55,-2.73,10.14,-2.76,10.17],[\"c\",-.03,.03,-.12,.12,-.24,.15],[\"c\",-.18,.09,-.21,.09,-.45,.09],[\"c\",-.24,0,-.3,0,-.48,-.06],[\"c\",-.09,-.06,-.21,-.12,-.21,-.15],[\"c\",-.06,-.03,.12,-.57,1.44,-4.92],[\"c\",.81,-2.67,1.47,-4.86,1.47,-4.89],[\"c\",-.03,0,-.27,.06,-.54,.15],[\"c\",-1.08,.36,-1.77,.48,-2.58,.48],[\"c\",-.66,0,-.84,-.03,-1.32,-.27],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.72,-1.05,2.22,-1.23,3.06,-.42],[\"c\",.3,.33,.42,.6,.6,1.38],[\"c\",.09,.45,.21,.78,.33,.9],[\"c\",.09,.09,.27,.18,.45,.21],[\"c\",.12,0,.18,0,.33,-.09],[\"c\",.33,-.15,1.02,-.93,1.41,-1.59],[\"c\",.12,-.21,.18,-.39,.39,-1.08],[\"c\",.66,-2.1,1.17,-3.84,1.17,-3.87],[\"c\",0,0,-.21,.06,-.42,.15],[\"c\",-.51,.15,-1.2,.33,-1.68,.42],[\"c\",-.33,.06,-.51,.06,-.96,.06],[\"c\",-.66,0,-.84,-.03,-1.32,-.27],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.33,-.45,.84,-.81,1.38,-.9],[\"z\"]],w:9.724,h:21.383},\"rests.32nd\":{d:[[\"M\",4.23,-13.62],[\"c\",.66,-.09,1.23,.09,1.68,.51],[\"c\",.27,.3,.39,.54,.57,1.26],[\"c\",.09,.33,.18,.66,.21,.72],[\"c\",.12,.27,.33,.45,.6,.48],[\"c\",.12,0,.18,0,.27,-.06],[\"c\",.33,-.21,.99,-1.11,1.44,-1.98],[\"c\",.09,-.24,.21,-.33,.39,-.33],[\"c\",.12,0,.27,.09,.33,.18],[\"c\",.03,.06,-.57,2.67,-3.21,13.89],[\"c\",-1.8,7.62,-3.3,13.89,-3.3,13.92],[\"c\",-.03,.06,-.12,.12,-.24,.18],[\"c\",-.21,.09,-.24,.09,-.48,.09],[\"c\",-.24,0,-.3,0,-.48,-.06],[\"c\",-.09,-.06,-.21,-.12,-.21,-.15],[\"c\",-.06,-.03,.09,-.57,1.23,-4.92],[\"c\",.69,-2.67,1.26,-4.86,1.29,-4.89],[\"c\",0,-.03,-.12,-.03,-.48,.12],[\"c\",-1.17,.39,-2.22,.57,-3,.54],[\"c\",-.42,-.03,-.75,-.12,-1.11,-.3],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.72,-1.05,2.22,-1.23,3.06,-.42],[\"c\",.3,.33,.42,.6,.6,1.38],[\"c\",.09,.45,.21,.78,.33,.9],[\"c\",.12,.09,.3,.18,.48,.21],[\"c\",.12,0,.18,0,.3,-.09],[\"c\",.42,-.21,1.29,-1.29,1.56,-1.89],[\"c\",.03,-.12,1.23,-4.59,1.23,-4.65],[\"c\",0,-.03,-.18,.03,-.39,.12],[\"c\",-.63,.18,-1.2,.36,-1.74,.45],[\"c\",-.39,.06,-.54,.06,-1.02,.06],[\"c\",-.66,0,-.84,-.03,-1.32,-.27],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.72,-1.05,2.22,-1.23,3.06,-.42],[\"c\",.3,.33,.42,.6,.6,1.38],[\"c\",.09,.45,.21,.78,.33,.9],[\"c\",.18,.18,.51,.27,.72,.15],[\"c\",.3,-.12,.69,-.57,1.08,-1.17],[\"c\",.42,-.6,.39,-.51,1.05,-3.03],[\"c\",.33,-1.26,.6,-2.31,.6,-2.34],[\"c\",0,0,-.21,.03,-.45,.12],[\"c\",-.57,.18,-1.14,.33,-1.62,.42],[\"c\",-.33,.06,-.51,.06,-.96,.06],[\"c\",-.66,0,-.84,-.03,-1.32,-.27],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.33,-.45,.84,-.81,1.38,-.9],[\"z\"]],w:11.373,h:28.883},\"rests.64th\":{d:[[\"M\",5.13,-13.62],[\"c\",.66,-.09,1.23,.09,1.68,.51],[\"c\",.27,.3,.39,.54,.57,1.26],[\"c\",.15,.63,.21,.81,.33,.96],[\"c\",.18,.21,.54,.3,.75,.18],[\"c\",.24,-.12,.63,-.66,1.08,-1.56],[\"c\",.33,-.66,.39,-.72,.6,-.72],[\"c\",.12,0,.27,.09,.33,.18],[\"c\",.03,.06,-.69,3.66,-3.54,17.64],[\"c\",-1.95,9.66,-3.57,17.61,-3.57,17.64],[\"c\",-.03,.06,-.12,.12,-.24,.18],[\"c\",-.21,.09,-.24,.09,-.48,.09],[\"c\",-.24,0,-.3,0,-.48,-.06],[\"c\",-.09,-.06,-.21,-.12,-.21,-.15],[\"c\",-.06,-.03,.06,-.57,1.05,-4.95],[\"c\",.6,-2.7,1.08,-4.89,1.08,-4.92],[\"c\",0,0,-.24,.06,-.51,.15],[\"c\",-.66,.24,-1.2,.36,-1.77,.48],[\"c\",-.42,.06,-.57,.06,-1.05,.06],[\"c\",-.69,0,-.87,-.03,-1.35,-.27],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.72,-1.05,2.22,-1.23,3.06,-.42],[\"c\",.3,.33,.42,.6,.6,1.38],[\"c\",.09,.45,.21,.78,.33,.9],[\"c\",.09,.09,.27,.18,.45,.21],[\"c\",.21,.03,.39,-.09,.72,-.42],[\"c\",.45,-.45,1.02,-1.26,1.17,-1.65],[\"c\",.03,-.09,.27,-1.14,.54,-2.34],[\"c\",.27,-1.2,.48,-2.19,.51,-2.22],[\"c\",0,-.03,-.09,-.03,-.48,.12],[\"c\",-1.17,.39,-2.22,.57,-3,.54],[\"c\",-.42,-.03,-.75,-.12,-1.11,-.3],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.36,-.54,.96,-.87,1.65,-.93],[\"c\",.54,-.03,1.02,.15,1.41,.54],[\"c\",.27,.3,.39,.54,.57,1.26],[\"c\",.09,.33,.18,.66,.21,.72],[\"c\",.15,.39,.57,.57,.9,.42],[\"c\",.36,-.18,1.2,-1.26,1.47,-1.89],[\"c\",.03,-.09,.3,-1.2,.57,-2.43],[\"l\",.51,-2.28],[\"l\",-.54,.18],[\"c\",-1.11,.36,-1.8,.48,-2.61,.48],[\"c\",-.66,0,-.84,-.03,-1.32,-.27],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.36,-.54,.96,-.87,1.65,-.93],[\"c\",.54,-.03,1.02,.15,1.41,.54],[\"c\",.27,.3,.39,.54,.57,1.26],[\"c\",.15,.63,.21,.81,.33,.96],[\"c\",.21,.21,.54,.3,.75,.18],[\"c\",.36,-.18,.93,-.93,1.29,-1.68],[\"c\",.12,-.24,.18,-.48,.63,-2.55],[\"l\",.51,-2.31],[\"c\",0,-.03,-.18,.03,-.39,.12],[\"c\",-1.14,.36,-2.1,.54,-2.82,.51],[\"c\",-.42,-.03,-.75,-.12,-1.11,-.3],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.33,-.45,.84,-.81,1.38,-.9],[\"z\"]],w:12.453,h:36.383},\"rests.128th\":{d:[[\"M\",6.03,-21.12],[\"c\",.66,-.09,1.23,.09,1.68,.51],[\"c\",.27,.3,.39,.54,.57,1.26],[\"c\",.09,.33,.18,.66,.21,.72],[\"c\",.12,.27,.33,.45,.6,.48],[\"c\",.21,0,.33,-.06,.54,-.36],[\"c\",.15,-.21,.54,-.93,.78,-1.47],[\"c\",.15,-.33,.18,-.39,.3,-.48],[\"c\",.18,-.09,.45,0,.51,.15],[\"c\",.03,.09,-7.11,42.75,-7.17,42.84],[\"c\",-.03,.03,-.15,.09,-.24,.15],[\"c\",-.18,.06,-.24,.06,-.45,.06],[\"c\",-.24,0,-.3,0,-.48,-.06],[\"c\",-.09,-.06,-.21,-.12,-.21,-.15],[\"c\",-.06,-.03,.03,-.57,.84,-4.98],[\"c\",.51,-2.7,.93,-4.92,.9,-4.92],[\"c\",0,0,-.15,.06,-.36,.12],[\"c\",-.78,.27,-1.62,.48,-2.31,.57],[\"c\",-.15,.03,-.54,.03,-.81,.03],[\"c\",-.66,0,-.84,-.03,-1.32,-.27],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.36,-.54,.96,-.87,1.65,-.93],[\"c\",.54,-.03,1.02,.15,1.41,.54],[\"c\",.27,.3,.39,.54,.57,1.26],[\"c\",.09,.33,.18,.66,.21,.72],[\"c\",.12,.27,.33,.45,.63,.48],[\"c\",.12,0,.18,0,.3,-.09],[\"c\",.42,-.21,1.14,-1.11,1.5,-1.83],[\"c\",.12,-.27,.12,-.27,.54,-2.52],[\"c\",.24,-1.23,.42,-2.25,.39,-2.25],[\"c\",0,0,-.24,.06,-.51,.18],[\"c\",-1.26,.39,-2.25,.57,-3.06,.54],[\"c\",-.42,-.03,-.75,-.12,-1.11,-.3],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.36,-.54,.96,-.87,1.65,-.93],[\"c\",.54,-.03,1.02,.15,1.41,.54],[\"c\",.27,.3,.39,.54,.57,1.26],[\"c\",.15,.63,.21,.81,.33,.96],[\"c\",.18,.21,.51,.3,.75,.18],[\"c\",.36,-.15,1.05,-.99,1.41,-1.77],[\"l\",.15,-.3],[\"l\",.42,-2.25],[\"c\",.21,-1.26,.42,-2.28,.39,-2.28],[\"l\",-.51,.15],[\"c\",-1.11,.39,-1.89,.51,-2.7,.51],[\"c\",-.66,0,-.84,-.03,-1.32,-.27],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.36,-.54,.96,-.87,1.65,-.93],[\"c\",.54,-.03,1.02,.15,1.41,.54],[\"c\",.27,.3,.39,.54,.57,1.26],[\"c\",.15,.63,.21,.81,.33,.96],[\"c\",.18,.18,.48,.27,.72,.21],[\"c\",.33,-.12,1.14,-1.26,1.41,-1.95],[\"c\",0,-.09,.21,-1.11,.45,-2.34],[\"c\",.21,-1.2,.39,-2.22,.39,-2.28],[\"c\",.03,-.03,0,-.03,-.45,.12],[\"c\",-.57,.18,-1.2,.33,-1.71,.42],[\"c\",-.3,.06,-.51,.06,-.93,.06],[\"c\",-.66,0,-.84,-.03,-1.32,-.27],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.36,-.54,.96,-.87,1.65,-.93],[\"c\",.54,-.03,1.02,.15,1.41,.54],[\"c\",.27,.3,.39,.54,.57,1.26],[\"c\",.09,.33,.18,.66,.21,.72],[\"c\",.12,.27,.33,.45,.6,.48],[\"c\",.18,0,.36,-.09,.57,-.33],[\"c\",.33,-.36,.78,-1.14,.93,-1.56],[\"c\",.03,-.12,.24,-1.2,.45,-2.4],[\"c\",.24,-1.2,.42,-2.22,.42,-2.28],[\"c\",.03,-.03,0,-.03,-.39,.09],[\"c\",-1.05,.36,-1.8,.48,-2.58,.48],[\"c\",-.63,0,-.84,-.03,-1.29,-.27],[\"c\",-1.32,-.63,-1.77,-2.16,-1.02,-3.3],[\"c\",.33,-.45,.84,-.81,1.38,-.9],[\"z\"]],w:12.992,h:43.883},\"accidentals.sharp\":{d:[[\"M\",5.73,-11.19],[\"c\",.21,-.12,.54,-.03,.66,.24],[\"c\",.06,.12,.06,.21,.06,2.31],[\"c\",0,1.23,0,2.22,.03,2.22],[\"c\",0,0,.27,-.12,.6,-.24],[\"c\",.69,-.27,.78,-.3,.96,-.15],[\"c\",.21,.15,.21,.18,.21,1.38],[\"c\",0,1.02,0,1.11,-.06,1.2],[\"c\",-.03,.06,-.09,.12,-.12,.15],[\"c\",-.06,.03,-.42,.21,-.84,.36],[\"l\",-.75,.33],[\"l\",-.03,2.43],[\"c\",0,1.32,0,2.43,.03,2.43],[\"c\",0,0,.27,-.12,.6,-.24],[\"c\",.69,-.27,.78,-.3,.96,-.15],[\"c\",.21,.15,.21,.18,.21,1.38],[\"c\",0,1.02,0,1.11,-.06,1.2],[\"c\",-.03,.06,-.09,.12,-.12,.15],[\"c\",-.06,.03,-.42,.21,-.84,.36],[\"l\",-.75,.33],[\"l\",-.03,2.52],[\"c\",0,2.28,-.03,2.55,-.06,2.64],[\"c\",-.21,.36,-.72,.36,-.93,0],[\"c\",-.03,-.09,-.06,-.33,-.06,-2.43],[\"l\",0,-2.31],[\"l\",-1.29,.51],[\"l\",-1.26,.51],[\"l\",0,2.43],[\"c\",0,2.58,0,2.52,-.15,2.67],[\"c\",-.06,.09,-.27,.18,-.36,.18],[\"c\",-.12,0,-.33,-.09,-.39,-.18],[\"c\",-.15,-.15,-.15,-.09,-.15,-2.43],[\"c\",0,-1.23,0,-2.22,-.03,-2.22],[\"c\",0,0,-.27,.12,-.6,.24],[\"c\",-.69,.27,-.78,.3,-.96,.15],[\"c\",-.21,-.15,-.21,-.18,-.21,-1.38],[\"c\",0,-1.02,0,-1.11,.06,-1.2],[\"c\",.03,-.06,.09,-.12,.12,-.15],[\"c\",.06,-.03,.42,-.21,.84,-.36],[\"l\",.78,-.33],[\"l\",0,-2.43],[\"c\",0,-1.32,0,-2.43,-.03,-2.43],[\"c\",0,0,-.27,.12,-.6,.24],[\"c\",-.69,.27,-.78,.3,-.96,.15],[\"c\",-.21,-.15,-.21,-.18,-.21,-1.38],[\"c\",0,-1.02,0,-1.11,.06,-1.2],[\"c\",.03,-.06,.09,-.12,.12,-.15],[\"c\",.06,-.03,.42,-.21,.84,-.36],[\"l\",.78,-.33],[\"l\",0,-2.52],[\"c\",0,-2.28,.03,-2.55,.06,-2.64],[\"c\",.21,-.36,.72,-.36,.93,0],[\"c\",.03,.09,.06,.33,.06,2.43],[\"l\",.03,2.31],[\"l\",1.26,-.51],[\"l\",1.26,-.51],[\"l\",0,-2.43],[\"c\",0,-2.28,0,-2.43,.06,-2.55],[\"c\",.06,-.12,.12,-.18,.27,-.24],[\"z\"],[\"m\",-.33,10.65],[\"l\",0,-2.43],[\"l\",-1.29,.51],[\"l\",-1.26,.51],[\"l\",0,2.46],[\"l\",0,2.43],[\"l\",.09,-.03],[\"c\",.06,-.03,.63,-.27,1.29,-.51],[\"l\",1.17,-.48],[\"l\",0,-2.46],[\"z\"]],w:8.25,h:22.462},\"accidentals.halfsharp\":{d:[[\"M\",2.43,-10.05],[\"c\",.21,-.12,.54,-.03,.66,.24],[\"c\",.06,.12,.06,.21,.06,2.01],[\"c\",0,1.05,0,1.89,.03,1.89],[\"l\",.72,-.48],[\"c\",.69,-.48,.69,-.51,.87,-.51],[\"c\",.15,0,.18,.03,.27,.09],[\"c\",.21,.15,.21,.18,.21,1.41],[\"c\",0,1.11,-.03,1.14,-.09,1.23],[\"c\",-.03,.03,-.48,.39,-1.02,.75],[\"l\",-.99,.66],[\"l\",0,2.37],[\"c\",0,1.32,0,2.37,.03,2.37],[\"l\",.72,-.48],[\"c\",.69,-.48,.69,-.51,.87,-.51],[\"c\",.15,0,.18,.03,.27,.09],[\"c\",.21,.15,.21,.18,.21,1.41],[\"c\",0,1.11,-.03,1.14,-.09,1.23],[\"c\",-.03,.03,-.48,.39,-1.02,.75],[\"l\",-.99,.66],[\"l\",0,2.25],[\"c\",0,1.95,0,2.28,-.06,2.37],[\"c\",-.06,.12,-.12,.21,-.24,.27],[\"c\",-.27,.12,-.54,.03,-.69,-.24],[\"c\",-.06,-.12,-.06,-.21,-.06,-2.01],[\"c\",0,-1.05,0,-1.89,-.03,-1.89],[\"l\",-.72,.48],[\"c\",-.69,.48,-.69,.48,-.87,.48],[\"c\",-.15,0,-.18,0,-.27,-.06],[\"c\",-.21,-.15,-.21,-.18,-.21,-1.41],[\"c\",0,-1.11,.03,-1.14,.09,-1.23],[\"c\",.03,-.03,.48,-.39,1.02,-.75],[\"l\",.99,-.66],[\"l\",0,-2.37],[\"c\",0,-1.32,0,-2.37,-.03,-2.37],[\"l\",-.72,.48],[\"c\",-.69,.48,-.69,.48,-.87,.48],[\"c\",-.15,0,-.18,0,-.27,-.06],[\"c\",-.21,-.15,-.21,-.18,-.21,-1.41],[\"c\",0,-1.11,.03,-1.14,.09,-1.23],[\"c\",.03,-.03,.48,-.39,1.02,-.75],[\"l\",.99,-.66],[\"l\",0,-2.25],[\"c\",0,-2.13,0,-2.28,.06,-2.4],[\"c\",.06,-.12,.12,-.18,.27,-.24],[\"z\"]],w:5.25,h:20.174},\"accidentals.nat\":{d:[[\"M\",.21,-11.4],[\"c\",.24,-.06,.78,0,.99,.15],[\"c\",.03,.03,.03,.48,0,2.61],[\"c\",-.03,1.44,-.03,2.61,-.03,2.61],[\"c\",0,.03,.75,-.09,1.68,-.24],[\"c\",.96,-.18,1.71,-.27,1.74,-.27],[\"c\",.15,.03,.27,.15,.36,.3],[\"l\",.06,.12],[\"l\",.09,8.67],[\"c\",.09,6.96,.12,8.67,.09,8.67],[\"c\",-.03,.03,-.12,.06,-.21,.09],[\"c\",-.24,.09,-.72,.09,-.96,0],[\"c\",-.09,-.03,-.18,-.06,-.21,-.09],[\"c\",-.03,-.03,-.03,-.48,0,-2.61],[\"c\",.03,-1.44,.03,-2.61,.03,-2.61],[\"c\",0,-.03,-.75,.09,-1.68,.24],[\"c\",-.96,.18,-1.71,.27,-1.74,.27],[\"c\",-.15,-.03,-.27,-.15,-.36,-.3],[\"l\",-.06,-.15],[\"l\",-.09,-7.53],[\"c\",-.06,-4.14,-.09,-8.04,-.12,-8.67],[\"l\",0,-1.11],[\"l\",.15,-.06],[\"c\",.09,-.03,.21,-.06,.27,-.09],[\"z\"],[\"m\",3.75,8.4],[\"c\",0,-.33,0,-.42,-.03,-.42],[\"c\",-.12,0,-2.79,.45,-2.79,.48],[\"c\",-.03,0,-.09,6.3,-.09,6.33],[\"c\",.03,0,2.79,-.45,2.82,-.48],[\"c\",0,0,.09,-4.53,.09,-5.91],[\"z\"]],w:5.4,h:22.8},\"accidentals.flat\":{\nd:[[\"M\",-.36,-14.07],[\"c\",.33,-.06,.87,0,1.08,.15],[\"c\",.06,.03,.06,.36,-.03,5.25],[\"c\",-.06,2.85,-.09,5.19,-.09,5.19],[\"c\",0,.03,.12,-.03,.24,-.12],[\"c\",.63,-.42,1.41,-.66,2.19,-.72],[\"c\",.81,-.03,1.47,.21,2.04,.78],[\"c\",.57,.54,.87,1.26,.93,2.04],[\"c\",.03,.57,-.09,1.08,-.36,1.62],[\"c\",-.42,.81,-1.02,1.38,-2.82,2.61],[\"c\",-1.14,.78,-1.44,1.02,-1.8,1.44],[\"c\",-.18,.18,-.39,.39,-.45,.42],[\"c\",-.27,.18,-.57,.15,-.81,-.06],[\"c\",-.06,-.09,-.12,-.18,-.15,-.27],[\"c\",-.03,-.06,-.09,-3.27,-.18,-8.34],[\"c\",-.09,-4.53,-.15,-8.58,-.18,-9.03],[\"l\",0,-.78],[\"l\",.12,-.06],[\"c\",.06,-.03,.18,-.09,.27,-.12],[\"z\"],[\"m\",3.18,11.01],[\"c\",-.21,-.12,-.54,-.15,-.81,-.06],[\"c\",-.54,.15,-.99,.63,-1.17,1.26],[\"c\",-.06,.3,-.12,2.88,-.06,3.87],[\"c\",.03,.42,.03,.81,.06,.9],[\"l\",.03,.12],[\"l\",.45,-.39],[\"c\",.63,-.54,1.26,-1.17,1.56,-1.59],[\"c\",.3,-.42,.6,-.99,.72,-1.41],[\"c\",.18,-.69,.09,-1.47,-.18,-2.07],[\"c\",-.15,-.3,-.33,-.51,-.6,-.63],[\"z\"]],w:6.75,h:18.801},\"accidentals.halfflat\":{d:[[\"M\",4.83,-14.07],[\"c\",.33,-.06,.87,0,1.08,.15],[\"c\",.06,.03,.06,.6,-.12,9.06],[\"c\",-.09,5.55,-.15,9.06,-.18,9.12],[\"c\",-.03,.09,-.09,.18,-.15,.27],[\"c\",-.24,.21,-.54,.24,-.81,.06],[\"c\",-.06,-.03,-.27,-.24,-.45,-.42],[\"c\",-.36,-.42,-.66,-.66,-1.8,-1.44],[\"c\",-1.23,-.84,-1.83,-1.32,-2.25,-1.77],[\"c\",-.66,-.78,-.96,-1.56,-.93,-2.46],[\"c\",.09,-1.41,1.11,-2.58,2.4,-2.79],[\"c\",.3,-.06,.84,-.03,1.23,.06],[\"c\",.54,.12,1.08,.33,1.53,.63],[\"c\",.12,.09,.24,.15,.24,.12],[\"c\",0,0,-.12,-8.37,-.18,-9.75],[\"l\",0,-.66],[\"l\",.12,-.06],[\"c\",.06,-.03,.18,-.09,.27,-.12],[\"z\"],[\"m\",-1.65,10.95],[\"c\",-.6,-.18,-1.08,.09,-1.38,.69],[\"c\",-.27,.6,-.36,1.38,-.18,2.07],[\"c\",.12,.42,.42,.99,.72,1.41],[\"c\",.3,.42,.93,1.05,1.56,1.59],[\"l\",.48,.39],[\"l\",0,-.12],[\"c\",.03,-.09,.03,-.48,.06,-.9],[\"c\",.03,-.57,.03,-1.08,0,-2.22],[\"c\",-.03,-1.62,-.03,-1.62,-.24,-2.07],[\"c\",-.21,-.42,-.6,-.75,-1.02,-.84],[\"z\"]],w:6.728,h:18.801},\"accidentals.dblflat\":{d:[[\"M\",-.36,-14.07],[\"c\",.33,-.06,.87,0,1.08,.15],[\"c\",.06,.03,.06,.33,-.03,4.89],[\"c\",-.06,2.67,-.09,5.01,-.09,5.22],[\"l\",0,.36],[\"l\",.15,-.15],[\"c\",.36,-.3,.75,-.51,1.2,-.63],[\"c\",.33,-.09,.96,-.09,1.26,-.03],[\"c\",.27,.09,.63,.27,.87,.45],[\"l\",.21,.15],[\"l\",0,-.27],[\"c\",0,-.15,-.03,-2.43,-.09,-5.1],[\"c\",-.09,-4.56,-.09,-4.86,-.03,-4.89],[\"c\",.15,-.12,.39,-.15,.72,-.15],[\"c\",.3,0,.54,.03,.69,.15],[\"c\",.06,.03,.06,.33,-.03,4.95],[\"c\",-.06,2.7,-.09,5.04,-.09,5.22],[\"l\",.03,.3],[\"l\",.21,-.15],[\"c\",.69,-.48,1.44,-.69,2.28,-.69],[\"c\",.51,0,.78,.03,1.2,.21],[\"c\",1.32,.63,2.01,2.28,1.53,3.69],[\"c\",-.21,.57,-.51,1.02,-1.05,1.56],[\"c\",-.42,.42,-.81,.72,-1.92,1.5],[\"c\",-1.26,.87,-1.5,1.08,-1.86,1.5],[\"c\",-.39,.45,-.54,.54,-.81,.51],[\"c\",-.18,0,-.21,0,-.33,-.06],[\"l\",-.21,-.21],[\"l\",-.06,-.12],[\"l\",-.03,-.99],[\"c\",-.03,-.54,-.03,-1.29,-.06,-1.68],[\"l\",0,-.69],[\"l\",-.21,.24],[\"c\",-.36,.42,-.75,.75,-1.8,1.62],[\"c\",-1.02,.84,-1.2,.99,-1.44,1.38],[\"c\",-.36,.51,-.54,.6,-.9,.51],[\"c\",-.15,-.03,-.39,-.27,-.42,-.42],[\"c\",-.03,-.06,-.09,-3.27,-.18,-8.34],[\"c\",-.09,-4.53,-.15,-8.58,-.18,-9.03],[\"l\",0,-.78],[\"l\",.12,-.06],[\"c\",.06,-.03,.18,-.09,.27,-.12],[\"z\"],[\"m\",2.52,10.98],[\"c\",-.18,-.09,-.48,-.12,-.66,-.06],[\"c\",-.39,.15,-.69,.54,-.84,1.14],[\"c\",-.06,.24,-.06,.39,-.09,1.74],[\"c\",-.03,1.44,0,2.73,.06,3.18],[\"l\",.03,.15],[\"l\",.27,-.27],[\"c\",.93,-.96,1.5,-1.95,1.74,-3.06],[\"c\",.06,-.27,.06,-.39,.06,-.96],[\"c\",0,-.54,0,-.69,-.06,-.93],[\"c\",-.09,-.51,-.27,-.81,-.51,-.93],[\"z\"],[\"m\",5.43,0],[\"c\",-.18,-.09,-.51,-.12,-.72,-.06],[\"c\",-.54,.12,-.96,.63,-1.17,1.26],[\"c\",-.06,.3,-.12,2.88,-.06,3.9],[\"c\",.03,.42,.03,.81,.06,.9],[\"l\",.03,.12],[\"l\",.36,-.3],[\"c\",.42,-.36,1.02,-.96,1.29,-1.29],[\"c\",.36,-.45,.66,-.99,.81,-1.41],[\"c\",.42,-1.23,.15,-2.76,-.6,-3.12],[\"z\"]],w:11.613,h:18.804},\"accidentals.dblsharp\":{d:[[\"M\",-.18,-3.96],[\"c\",.06,-.03,.12,-.06,.15,-.06],[\"c\",.09,0,2.76,.27,2.79,.3],[\"c\",.12,.03,.15,.12,.15,.51],[\"c\",.06,.96,.24,1.59,.57,2.1],[\"c\",.06,.09,.15,.21,.18,.24],[\"l\",.09,.06],[\"l\",.09,-.06],[\"c\",.03,-.03,.12,-.15,.18,-.24],[\"c\",.33,-.51,.51,-1.14,.57,-2.1],[\"c\",0,-.39,.03,-.45,.12,-.51],[\"c\",.03,0,.66,-.09,1.44,-.15],[\"c\",1.47,-.15,1.5,-.15,1.56,-.03],[\"c\",.03,.06,0,.42,-.09,1.44],[\"c\",-.09,.72,-.15,1.35,-.15,1.38],[\"c\",0,.03,-.03,.09,-.06,.12],[\"c\",-.06,.06,-.12,.09,-.51,.09],[\"c\",-1.08,.06,-1.8,.3,-2.28,.75],[\"l\",-.12,.09],[\"l\",.09,.09],[\"c\",.12,.15,.39,.33,.63,.45],[\"c\",.42,.18,.96,.27,1.68,.33],[\"c\",.39,0,.45,.03,.51,.09],[\"c\",.03,.03,.06,.09,.06,.12],[\"c\",0,.03,.06,.66,.15,1.38],[\"c\",.09,1.02,.12,1.38,.09,1.44],[\"c\",-.06,.12,-.09,.12,-1.56,-.03],[\"c\",-.78,-.06,-1.41,-.15,-1.44,-.15],[\"c\",-.09,-.06,-.12,-.12,-.12,-.54],[\"c\",-.06,-.93,-.24,-1.56,-.57,-2.07],[\"c\",-.06,-.09,-.15,-.21,-.18,-.24],[\"l\",-.09,-.06],[\"l\",-.09,.06],[\"c\",-.03,.03,-.12,.15,-.18,.24],[\"c\",-.33,.51,-.51,1.14,-.57,2.07],[\"c\",0,.42,-.03,.48,-.12,.54],[\"c\",-.03,0,-.66,.09,-1.44,.15],[\"c\",-1.47,.15,-1.5,.15,-1.56,.03],[\"c\",-.03,-.06,0,-.42,.09,-1.44],[\"c\",.09,-.72,.15,-1.35,.15,-1.38],[\"c\",0,-.03,.03,-.09,.06,-.12],[\"c\",.06,-.06,.12,-.09,.51,-.09],[\"c\",.72,-.06,1.26,-.15,1.68,-.33],[\"c\",.24,-.12,.51,-.3,.63,-.45],[\"l\",.09,-.09],[\"l\",-.12,-.09],[\"c\",-.48,-.45,-1.2,-.69,-2.28,-.75],[\"c\",-.39,0,-.45,-.03,-.51,-.09],[\"c\",-.03,-.03,-.06,-.09,-.06,-.12],[\"c\",0,-.03,-.06,-.63,-.12,-1.38],[\"c\",-.09,-.72,-.15,-1.35,-.15,-1.38],[\"z\"]],w:7.95,h:7.977},\"dots.dot\":{d:[[\"M\",1.32,-1.68],[\"c\",.09,-.03,.27,-.06,.39,-.06],[\"c\",.96,0,1.74,.78,1.74,1.71],[\"c\",0,.96,-.78,1.74,-1.71,1.74],[\"c\",-.96,0,-1.74,-.78,-1.74,-1.71],[\"c\",0,-.78,.54,-1.5,1.32,-1.68],[\"z\"]],w:3.45,h:3.45},\"noteheads.dbl\":{d:[[\"M\",-.69,-4.02],[\"c\",.18,-.09,.36,-.09,.54,0],[\"c\",.18,.09,.24,.15,.33,.3],[\"c\",.06,.15,.06,.18,.06,1.41],[\"l\",0,1.23],[\"l\",.12,-.18],[\"c\",.72,-1.26,2.64,-2.31,4.86,-2.64],[\"c\",.81,-.15,1.11,-.15,2.13,-.15],[\"c\",.99,0,1.29,0,2.1,.15],[\"c\",.75,.12,1.38,.27,2.04,.54],[\"c\",1.35,.51,2.34,1.26,2.82,2.1],[\"l\",.12,.18],[\"l\",0,-1.23],[\"c\",0,-1.2,0,-1.26,.06,-1.38],[\"c\",.09,-.18,.15,-.24,.33,-.33],[\"c\",.18,-.09,.36,-.09,.54,0],[\"c\",.18,.09,.24,.15,.33,.3],[\"l\",.06,.15],[\"l\",0,3.54],[\"l\",0,3.54],[\"l\",-.06,.15],[\"c\",-.09,.18,-.15,.24,-.33,.33],[\"c\",-.18,.09,-.36,.09,-.54,0],[\"c\",-.18,-.09,-.24,-.15,-.33,-.33],[\"c\",-.06,-.12,-.06,-.18,-.06,-1.38],[\"l\",0,-1.23],[\"l\",-.12,.18],[\"c\",-.48,.84,-1.47,1.59,-2.82,2.1],[\"c\",-.84,.33,-1.71,.54,-2.85,.66],[\"c\",-.45,.06,-2.16,.06,-2.61,0],[\"c\",-1.14,-.12,-2.01,-.33,-2.85,-.66],[\"c\",-1.35,-.51,-2.34,-1.26,-2.82,-2.1],[\"l\",-.12,-.18],[\"l\",0,1.23],[\"c\",0,1.23,0,1.26,-.06,1.38],[\"c\",-.09,.18,-.15,.24,-.33,.33],[\"c\",-.18,.09,-.36,.09,-.54,0],[\"c\",-.18,-.09,-.24,-.15,-.33,-.33],[\"l\",-.06,-.15],[\"l\",0,-3.54],[\"c\",0,-3.48,0,-3.54,.06,-3.66],[\"c\",.09,-.18,.15,-.24,.33,-.33],[\"z\"],[\"m\",7.71,.63],[\"c\",-.36,-.06,-.9,-.06,-1.14,0],[\"c\",-.3,.03,-.66,.24,-.87,.42],[\"c\",-.6,.54,-.9,1.62,-.75,2.82],[\"c\",.12,.93,.51,1.68,1.11,2.31],[\"c\",.75,.72,1.83,1.2,2.85,1.26],[\"c\",1.05,.06,1.83,-.54,2.1,-1.65],[\"c\",.21,-.9,.12,-1.95,-.24,-2.82],[\"c\",-.36,-.81,-1.08,-1.53,-1.95,-1.95],[\"c\",-.3,-.15,-.78,-.3,-1.11,-.39],[\"z\"]],w:16.83,h:8.145},\"noteheads.whole\":{d:[[\"M\",6.51,-4.05],[\"c\",.51,-.03,2.01,0,2.52,.03],[\"c\",1.41,.18,2.64,.51,3.72,1.08],[\"c\",1.2,.63,1.95,1.41,2.19,2.31],[\"c\",.09,.33,.09,.9,0,1.23],[\"c\",-.24,.9,-.99,1.68,-2.19,2.31],[\"c\",-1.08,.57,-2.28,.9,-3.75,1.08],[\"c\",-.66,.06,-2.31,.06,-2.97,0],[\"c\",-1.47,-.18,-2.67,-.51,-3.75,-1.08],[\"c\",-1.2,-.63,-1.95,-1.41,-2.19,-2.31],[\"c\",-.09,-.33,-.09,-.9,0,-1.23],[\"c\",.24,-.9,.99,-1.68,2.19,-2.31],[\"c\",1.2,-.63,2.61,-.99,4.23,-1.11],[\"z\"],[\"m\",.57,.66],[\"c\",-.87,-.15,-1.53,0,-2.04,.51],[\"c\",-.15,.15,-.24,.27,-.33,.48],[\"c\",-.24,.51,-.36,1.08,-.33,1.77],[\"c\",.03,.69,.18,1.26,.42,1.77],[\"c\",.6,1.17,1.74,1.98,3.18,2.22],[\"c\",1.11,.21,1.95,-.15,2.34,-.99],[\"c\",.24,-.51,.36,-1.08,.33,-1.8],[\"c\",-.06,-1.11,-.45,-2.04,-1.17,-2.76],[\"c\",-.63,-.63,-1.47,-1.05,-2.4,-1.2],[\"z\"]],w:14.985,h:8.097},\"noteheads.half\":{d:[[\"M\",7.44,-4.05],[\"c\",.06,-.03,.27,-.03,.48,-.03],[\"c\",1.05,0,1.71,.24,2.1,.81],[\"c\",.42,.6,.45,1.35,.18,2.4],[\"c\",-.42,1.59,-1.14,2.73,-2.16,3.39],[\"c\",-1.41,.93,-3.18,1.44,-5.4,1.53],[\"c\",-1.17,.03,-1.89,-.21,-2.28,-.81],[\"c\",-.42,-.6,-.45,-1.35,-.18,-2.4],[\"c\",.42,-1.59,1.14,-2.73,2.16,-3.39],[\"c\",.63,-.42,1.23,-.72,1.98,-.96],[\"c\",.9,-.3,1.65,-.42,3.12,-.54],[\"z\"],[\"m\",1.29,.87],[\"c\",-.27,-.09,-.63,-.12,-.9,-.03],[\"c\",-.72,.24,-1.53,.69,-3.27,1.8],[\"c\",-2.34,1.5,-3.3,2.25,-3.57,2.79],[\"c\",-.36,.72,-.06,1.5,.66,1.77],[\"c\",.24,.12,.69,.09,.99,0],[\"c\",.84,-.3,1.92,-.93,4.14,-2.37],[\"c\",1.62,-1.08,2.37,-1.71,2.61,-2.19],[\"c\",.36,-.72,.06,-1.5,-.66,-1.77],[\"z\"]],w:10.37,h:8.132},\"noteheads.quarter\":{d:[[\"M\",6.09,-4.05],[\"c\",.36,-.03,1.2,0,1.53,.06],[\"c\",1.17,.24,1.89,.84,2.16,1.83],[\"c\",.06,.18,.06,.3,.06,.66],[\"c\",0,.45,0,.63,-.15,1.08],[\"c\",-.66,2.04,-3.06,3.93,-5.52,4.38],[\"c\",-.54,.09,-1.44,.09,-1.83,.03],[\"c\",-1.23,-.27,-1.98,-.87,-2.25,-1.86],[\"c\",-.06,-.18,-.06,-.3,-.06,-.66],[\"c\",0,-.45,0,-.63,.15,-1.08],[\"c\",.24,-.78,.75,-1.53,1.44,-2.22],[\"c\",1.2,-1.2,2.85,-2.01,4.47,-2.22],[\"z\"]],w:9.81,h:8.094},\"noteheads.slash.nostem\":{d:[[\"M\",9.3,-7.77],[\"c\",.06,-.06,.18,-.06,1.71,-.06],[\"l\",1.65,0],[\"l\",.09,.09],[\"c\",.06,.06,.06,.09,.06,.15],[\"c\",-.03,.12,-9.21,15.24,-9.3,15.33],[\"c\",-.06,.06,-.18,.06,-1.71,.06],[\"l\",-1.65,0],[\"l\",-.09,-.09],[\"c\",-.06,-.06,-.06,-.09,-.06,-.15],[\"c\",.03,-.12,9.21,-15.24,9.3,-15.33],[\"z\"]],w:12.81,h:15.63},\"noteheads.indeterminate\":{d:[[\"M\",.78,-4.05],[\"c\",.12,-.03,.24,-.03,.36,.03],[\"c\",.03,.03,.93,.72,1.95,1.56],[\"l\",1.86,1.5],[\"l\",1.86,-1.5],[\"c\",1.02,-.84,1.92,-1.53,1.95,-1.56],[\"c\",.21,-.12,.33,-.09,.75,.24],[\"c\",.3,.27,.36,.36,.36,.54],[\"c\",0,.03,-.03,.12,-.06,.18],[\"c\",-.03,.06,-.9,.75,-1.89,1.56],[\"l\",-1.8,1.47],[\"c\",0,.03,.81,.69,1.8,1.5],[\"c\",.99,.81,1.86,1.5,1.89,1.56],[\"c\",.03,.06,.06,.15,.06,.18],[\"c\",0,.18,-.06,.27,-.36,.54],[\"c\",-.42,.33,-.54,.36,-.75,.24],[\"c\",-.03,-.03,-.93,-.72,-1.95,-1.56],[\"l\",-1.86,-1.5],[\"l\",-1.86,1.5],[\"c\",-1.02,.84,-1.92,1.53,-1.95,1.56],[\"c\",-.21,.12,-.33,.09,-.75,-.24],[\"c\",-.3,-.27,-.36,-.36,-.36,-.54],[\"c\",0,-.03,.03,-.12,.06,-.18],[\"c\",.03,-.06,.9,-.75,1.89,-1.56],[\"l\",1.8,-1.47],[\"c\",0,-.03,-.81,-.69,-1.8,-1.5],[\"c\",-.99,-.81,-1.86,-1.5,-1.89,-1.56],[\"c\",-.06,-.12,-.09,-.21,-.03,-.36],[\"c\",.03,-.09,.57,-.57,.72,-.63],[\"z\"]],w:9.843,h:8.139},\"scripts.ufermata\":{d:[[\"M\",-.75,-10.77],[\"c\",.12,0,.45,-.03,.69,-.03],[\"c\",2.91,-.03,5.55,1.53,7.41,4.35],[\"c\",1.17,1.71,1.95,3.72,2.43,6.03],[\"c\",.12,.51,.12,.57,.03,.69],[\"c\",-.12,.21,-.48,.27,-.69,.12],[\"c\",-.12,-.09,-.18,-.24,-.27,-.69],[\"c\",-.78,-3.63,-3.42,-6.54,-6.78,-7.38],[\"c\",-.78,-.21,-1.2,-.24,-2.07,-.24],[\"c\",-.63,0,-.84,0,-1.2,.06],[\"c\",-1.83,.27,-3.42,1.08,-4.8,2.37],[\"c\",-1.41,1.35,-2.4,3.21,-2.85,5.19],[\"c\",-.09,.45,-.15,.6,-.27,.69],[\"c\",-.21,.15,-.57,.09,-.69,-.12],[\"c\",-.09,-.12,-.09,-.18,.03,-.69],[\"c\",.33,-1.62,.78,-3,1.47,-4.38],[\"c\",1.77,-3.54,4.44,-5.67,7.56,-5.97],[\"z\"],[\"m\",.33,7.47],[\"c\",1.38,-.3,2.58,.9,2.31,2.25],[\"c\",-.15,.72,-.78,1.35,-1.47,1.5],[\"c\",-1.38,.27,-2.58,-.93,-2.31,-2.31],[\"c\",.15,-.69,.78,-1.29,1.47,-1.44],[\"z\"]],w:19.748,h:11.289},\"scripts.dfermata\":{d:[[\"M\",-9.63,-.42],[\"c\",.15,-.09,.36,-.06,.51,.03],[\"c\",.12,.09,.18,.24,.27,.66],[\"c\",.78,3.66,3.42,6.57,6.78,7.41],[\"c\",.78,.21,1.2,.24,2.07,.24],[\"c\",.63,0,.84,0,1.2,-.06],[\"c\",1.83,-.27,3.42,-1.08,4.8,-2.37],[\"c\",1.41,-1.35,2.4,-3.21,2.85,-5.22],[\"c\",.09,-.42,.15,-.57,.27,-.66],[\"c\",.21,-.15,.57,-.09,.69,.12],[\"c\",.09,.12,.09,.18,-.03,.69],[\"c\",-.33,1.62,-.78,3,-1.47,4.38],[\"c\",-1.92,3.84,-4.89,6,-8.31,6],[\"c\",-3.42,0,-6.39,-2.16,-8.31,-6],[\"c\",-.48,-.96,-.84,-1.92,-1.14,-2.97],[\"c\",-.18,-.69,-.42,-1.74,-.42,-1.92],[\"c\",0,-.12,.09,-.27,.24,-.33],[\"z\"],[\"m\",9.21,0],[\"c\",1.2,-.27,2.34,.63,2.34,1.86],[\"c\",0,.9,-.66,1.68,-1.5,1.89],[\"c\",-1.38,.27,-2.58,-.93,-2.31,-2.31],[\"c\",.15,-.69,.78,-1.29,1.47,-1.44],[\"z\"]],w:19.744,h:11.274},\"scripts.sforzato\":{d:[[\"M\",-6.45,-3.69],[\"c\",.06,-.03,.15,-.06,.18,-.06],[\"c\",.06,0,2.85,.72,6.24,1.59],[\"l\",6.33,1.65],[\"c\",.33,.06,.45,.21,.45,.51],[\"c\",0,.3,-.12,.45,-.45,.51],[\"l\",-6.33,1.65],[\"c\",-3.39,.87,-6.18,1.59,-6.21,1.59],[\"c\",-.21,0,-.48,-.24,-.51,-.45],[\"c\",0,-.15,.06,-.36,.18,-.45],[\"c\",.09,-.06,.87,-.27,3.84,-1.05],[\"c\",2.04,-.54,3.84,-.99,4.02,-1.02],[\"c\",.15,-.06,1.14,-.24,2.22,-.42],[\"c\",1.05,-.18,1.92,-.36,1.92,-.36],[\"c\",0,0,-.87,-.18,-1.92,-.36],[\"c\",-1.08,-.18,-2.07,-.36,-2.22,-.42],[\"c\",-.18,-.03,-1.98,-.48,-4.02,-1.02],[\"c\",-2.97,-.78,-3.75,-.99,-3.84,-1.05],[\"c\",-.12,-.09,-.18,-.3,-.18,-.45],[\"c\",.03,-.15,.15,-.3,.3,-.39],[\"z\"]],w:13.5,h:7.5},\"scripts.staccato\":{d:[[\"M\",-.36,-1.47],[\"c\",.93,-.21,1.86,.51,1.86,1.47],[\"c\",0,.93,-.87,1.65,-1.8,1.47],[\"c\",-.54,-.12,-1.02,-.57,-1.14,-1.08],[\"c\",-.21,-.81,.27,-1.65,1.08,-1.86],[\"z\"]],w:2.989,h:3.004},\"scripts.tenuto\":{d:[[\"M\",-4.2,-.48],[\"l\",.12,-.06],[\"l\",4.08,0],[\"l\",4.08,0],[\"l\",.12,.06],[\"c\",.39,.21,.39,.75,0,.96],[\"l\",-.12,.06],[\"l\",-4.08,0],[\"l\",-4.08,0],[\"l\",-.12,-.06],[\"c\",-.39,-.21,-.39,-.75,0,-.96],[\"z\"]],w:8.985,h:1.08},\"scripts.umarcato\":{d:[[\"M\",-.15,-8.19],[\"c\",.15,-.12,.36,-.03,.45,.15],[\"c\",.21,.42,3.45,7.65,3.45,7.71],[\"c\",0,.12,-.12,.27,-.21,.3],[\"c\",-.03,.03,-.51,.03,-1.14,.03],[\"c\",-1.05,0,-1.08,0,-1.17,-.06],[\"c\",-.09,-.06,-.24,-.36,-1.17,-2.4],[\"c\",-.57,-1.29,-1.05,-2.34,-1.08,-2.34],[\"c\",0,-.03,-.51,1.02,-1.08,2.34],[\"c\",-.93,2.07,-1.08,2.34,-1.14,2.4],[\"c\",-.06,.03,-.15,.06,-.18,.06],[\"c\",-.15,0,-.33,-.18,-.33,-.33],[\"c\",0,-.06,3.24,-7.32,3.45,-7.71],[\"c\",.03,-.06,.09,-.15,.15,-.15],[\"z\"]],w:7.5,h:8.245},\"scripts.dmarcato\":{d:[[\"M\",-3.57,.03],[\"c\",.03,0,.57,-.03,1.17,-.03],[\"c\",1.05,0,1.08,0,1.17,.06],[\"c\",.09,.06,.24,.36,1.17,2.4],[\"c\",.57,1.29,1.05,2.34,1.08,2.34],[\"c\",0,.03,.51,-1.02,1.08,-2.34],[\"c\",.93,-2.07,1.08,-2.34,1.14,-2.4],[\"c\",.06,-.03,.15,-.06,.18,-.06],[\"c\",.15,0,.33,.18,.33,.33],[\"c\",0,.09,-3.45,7.74,-3.54,7.83],[\"c\",-.12,.12,-.3,.12,-.42,0],[\"c\",-.09,-.09,-3.54,-7.74,-3.54,-7.83],[\"c\",0,-.09,.12,-.27,.18,-.3],[\"z\"]],w:7.5,h:8.25},\"scripts.stopped\":{d:[[\"M\",-.27,-4.08],[\"c\",.18,-.09,.36,-.09,.54,0],[\"c\",.18,.09,.24,.15,.33,.3],[\"l\",.06,.15],[\"l\",0,1.5],[\"l\",0,1.47],[\"l\",1.47,0],[\"l\",1.5,0],[\"l\",.15,.06],[\"c\",.15,.09,.21,.15,.3,.33],[\"c\",.09,.18,.09,.36,0,.54],[\"c\",-.09,.18,-.15,.24,-.33,.33],[\"c\",-.12,.06,-.18,.06,-1.62,.06],[\"l\",-1.47,0],[\"l\",0,1.47],[\"l\",0,1.47],[\"l\",-.06,.15],[\"c\",-.09,.18,-.15,.24,-.33,.33],[\"c\",-.18,.09,-.36,.09,-.54,0],[\"c\",-.18,-.09,-.24,-.15,-.33,-.33],[\"l\",-.06,-.15],[\"l\",0,-1.47],[\"l\",0,-1.47],[\"l\",-1.47,0],[\"c\",-1.44,0,-1.5,0,-1.62,-.06],[\"c\",-.18,-.09,-.24,-.15,-.33,-.33],[\"c\",-.09,-.18,-.09,-.36,0,-.54],[\"c\",.09,-.18,.15,-.24,.33,-.33],[\"l\",.15,-.06],[\"l\",1.47,0],[\"l\",1.47,0],[\"l\",0,-1.47],[\"c\",0,-1.44,0,-1.5,.06,-1.62],[\"c\",.09,-.18,.15,-.24,.33,-.33],[\"z\"]],w:8.295,h:8.295},\"scripts.upbow\":{d:[[\"M\",-4.65,-15.54],[\"c\",.12,-.09,.36,-.06,.48,.03],[\"c\",.03,.03,.09,.09,.12,.15],[\"c\",.03,.06,.66,2.13,1.41,4.62],[\"c\",1.35,4.41,1.38,4.56,2.01,6.96],[\"l\",.63,2.46],[\"l\",.63,-2.46],[\"c\",.63,-2.4,.66,-2.55,2.01,-6.96],[\"c\",.75,-2.49,1.38,-4.56,1.41,-4.62],[\"c\",.06,-.15,.18,-.21,.36,-.24],[\"c\",.15,0,.3,.06,.39,.18],[\"c\",.15,.21,.24,-.18,-2.1,7.56],[\"c\",-1.2,3.96,-2.22,7.32,-2.25,7.41],[\"c\",0,.12,-.06,.27,-.09,.3],[\"c\",-.12,.21,-.6,.21,-.72,0],[\"c\",-.03,-.03,-.09,-.18,-.09,-.3],[\"c\",-.03,-.09,-1.05,-3.45,-2.25,-7.41],[\"c\",-2.34,-7.74,-2.25,-7.35,-2.1,-7.56],[\"c\",.03,-.03,.09,-.09,.15,-.12],[\"z\"]],w:9.73,h:15.608},\"scripts.downbow\":{d:[[\"M\",-5.55,-9.93],[\"l\",.09,-.06],[\"l\",5.46,0],[\"l\",5.46,0],[\"l\",.09,.06],[\"l\",.06,.09],[\"l\",0,4.77],[\"c\",0,5.28,0,4.89,-.18,5.01],[\"c\",-.18,.12,-.42,.06,-.54,-.12],[\"c\",-.06,-.09,-.06,-.18,-.06,-2.97],[\"l\",0,-2.85],[\"l\",-4.83,0],[\"l\",-4.83,0],[\"l\",0,2.85],[\"c\",0,2.79,0,2.88,-.06,2.97],[\"c\",-.15,.24,-.51,.24,-.66,0],[\"c\",-.06,-.09,-.06,-.21,-.06,-4.89],[\"l\",0,-4.77],[\"z\"]],w:11.22,h:9.992},\"scripts.turn\":{d:[[\"M\",-4.77,-3.9],[\"c\",.36,-.06,1.05,-.06,1.44,.03],[\"c\",.78,.15,1.5,.51,2.34,1.14],[\"c\",.6,.45,1.05,.87,2.22,2.01],[\"c\",1.11,1.08,1.62,1.5,2.22,1.86],[\"c\",.6,.36,1.32,.57,1.92,.57],[\"c\",.9,0,1.71,-.57,1.89,-1.35],[\"c\",.24,-.93,-.39,-1.89,-1.35,-2.1],[\"l\",-.15,-.06],[\"l\",-.09,.15],[\"c\",-.03,.09,-.15,.24,-.24,.33],[\"c\",-.72,.72,-2.04,.54,-2.49,-.36],[\"c\",-.48,-.93,.03,-1.86,1.17,-2.19],[\"c\",.3,-.09,1.02,-.09,1.35,0],[\"c\",.99,.27,1.74,.87,2.25,1.83],[\"c\",.69,1.41,.63,3,-.21,4.26],[\"c\",-.21,.3,-.69,.81,-.99,1.02],[\"c\",-.3,.21,-.84,.45,-1.17,.54],[\"c\",-1.23,.36,-2.49,.15,-3.72,-.6],[\"c\",-.75,-.48,-1.41,-1.02,-2.85,-2.46],[\"c\",-1.11,-1.08,-1.62,-1.5,-2.22,-1.86],[\"c\",-.6,-.36,-1.32,-.57,-1.92,-.57],[\"c\",-.9,0,-1.71,.57,-1.89,1.35],[\"c\",-.24,.93,.39,1.89,1.35,2.1],[\"l\",.15,.06],[\"l\",.09,-.15],[\"c\",.03,-.09,.15,-.24,.24,-.33],[\"c\",.72,-.72,2.04,-.54,2.49,.36],[\"c\",.48,.93,-.03,1.86,-1.17,2.19],[\"c\",-.3,.09,-1.02,.09,-1.35,0],[\"c\",-.99,-.27,-1.74,-.87,-2.25,-1.83],[\"c\",-.69,-1.41,-.63,-3,.21,-4.26],[\"c\",.21,-.3,.69,-.81,.99,-1.02],[\"c\",.48,-.33,1.11,-.57,1.74,-.66],[\"z\"]],w:16.366,h:7.893},\"scripts.trill\":{d:[[\"M\",-.51,-16.02],[\"c\",.12,-.09,.21,-.18,.21,-.18],[\"l\",-.81,4.02],[\"l\",-.81,4.02],[\"c\",.03,0,.51,-.27,1.08,-.6],[\"c\",.6,-.3,1.14,-.63,1.26,-.66],[\"c\",1.14,-.54,2.31,-.6,3.09,-.18],[\"c\",.27,.15,.54,.36,.6,.51],[\"l\",.06,.12],[\"l\",.21,-.21],[\"c\",.9,-.81,2.22,-.99,3.12,-.42],[\"c\",.6,.42,.9,1.14,.78,2.07],[\"c\",-.15,1.29,-1.05,2.31,-1.95,2.25],[\"c\",-.48,-.03,-.78,-.3,-.96,-.81],[\"c\",-.09,-.27,-.09,-.9,-.03,-1.2],[\"c\",.21,-.75,.81,-1.23,1.59,-1.32],[\"l\",.24,-.03],[\"l\",-.09,-.12],[\"c\",-.51,-.66,-1.62,-.63,-2.31,.03],[\"c\",-.39,.42,-.3,.09,-1.23,4.77],[\"l\",-.81,4.14],[\"c\",-.03,0,-.12,-.03,-.21,-.09],[\"c\",-.33,-.15,-.54,-.18,-.99,-.18],[\"c\",-.42,0,-.66,.03,-1.05,.18],[\"c\",-.12,.06,-.21,.09,-.21,.09],[\"c\",0,-.03,.36,-1.86,.81,-4.11],[\"c\",.9,-4.47,.87,-4.26,.69,-4.53],[\"c\",-.21,-.36,-.66,-.51,-1.17,-.36],[\"c\",-.15,.06,-2.22,1.14,-2.58,1.38],[\"c\",-.12,.09,-.12,.09,-.21,.6],[\"l\",-.09,.51],[\"l\",.21,.24],[\"c\",.63,.75,1.02,1.47,1.2,2.19],[\"c\",.06,.27,.06,.36,.06,.81],[\"c\",0,.42,0,.54,-.06,.78],[\"c\",-.15,.54,-.33,.93,-.63,1.35],[\"c\",-.18,.24,-.57,.63,-.81,.78],[\"c\",-.24,.15,-.63,.36,-.84,.42],[\"c\",-.27,.06,-.66,.06,-.87,.03],[\"c\",-.81,-.18,-1.32,-1.05,-1.38,-2.46],[\"c\",-.03,-.6,.03,-.99,.33,-2.46],[\"c\",.21,-1.08,.24,-1.32,.21,-1.29],[\"c\",-1.2,.48,-2.4,.75,-3.21,.72],[\"c\",-.69,-.06,-1.17,-.3,-1.41,-.72],[\"c\",-.39,-.75,-.12,-1.8,.66,-2.46],[\"c\",.24,-.18,.69,-.42,1.02,-.51],[\"c\",.69,-.18,1.53,-.15,2.31,.09],[\"c\",.3,.09,.75,.3,.99,.45],[\"c\",.12,.09,.15,.09,.15,.03],[\"c\",.03,-.03,.33,-1.59,.72,-3.45],[\"c\",.36,-1.86,.66,-3.42,.69,-3.45],[\"c\",0,-.03,.03,-.03,.21,.03],[\"c\",.21,.06,.27,.06,.48,.06],[\"c\",.42,-.03,.78,-.18,1.26,-.48],[\"c\",.15,-.12,.36,-.27,.48,-.39],[\"z\"],[\"m\",-5.73,7.68],[\"c\",-.27,-.03,-.96,-.06,-1.2,-.03],[\"c\",-.81,.12,-1.35,.57,-1.5,1.2],[\"c\",-.18,.66,.12,1.14,.75,1.29],[\"c\",.66,.12,1.92,-.12,3.18,-.66],[\"l\",.33,-.15],[\"l\",.09,-.39],[\"c\",.06,-.21,.09,-.42,.09,-.45],[\"c\",0,-.03,-.45,-.3,-.75,-.45],[\"c\",-.27,-.15,-.66,-.27,-.99,-.36],[\"z\"],[\"m\",4.29,3.63],[\"c\",-.24,-.39,-.51,-.75,-.51,-.69],[\"c\",-.06,.12,-.39,1.92,-.45,2.28],[\"c\",-.09,.54,-.12,1.14,-.06,1.38],[\"c\",.06,.42,.21,.6,.51,.57],[\"c\",.39,-.06,.75,-.48,.93,-1.14],[\"c\",.09,-.33,.09,-1.05,0,-1.38],[\"c\",-.09,-.39,-.24,-.69,-.42,-1.02],[\"z\"]],w:17.963,h:16.49},\"scripts.segno\":{d:[[\"M\",-3.72,-11.22],[\"c\",.78,-.09,1.59,.03,2.31,.42],[\"c\",1.2,.6,2.01,1.71,2.31,3.09],[\"c\",.09,.42,.09,1.2,.03,1.5],[\"c\",-.15,.45,-.39,.81,-.66,.93],[\"c\",-.33,.18,-.84,.21,-1.23,.15],[\"c\",-.81,-.18,-1.32,-.93,-1.26,-1.89],[\"c\",.03,-.36,.09,-.57,.24,-.9],[\"c\",.15,-.33,.45,-.6,.72,-.75],[\"c\",.12,-.06,.18,-.09,.18,-.12],[\"c\",0,-.03,-.03,-.15,-.09,-.24],[\"c\",-.18,-.45,-.54,-.87,-.96,-1.08],[\"c\",-1.11,-.57,-2.34,-.18,-2.88,.9],[\"c\",-.24,.51,-.33,1.11,-.24,1.83],[\"c\",.27,1.92,1.5,3.54,3.93,5.13],[\"c\",.48,.33,1.26,.78,1.29,.78],[\"c\",.03,0,1.35,-2.19,2.94,-4.89],[\"l\",2.88,-4.89],[\"l\",.84,0],[\"l\",.87,0],[\"l\",-.03,.06],[\"c\",-.15,.21,-6.15,10.41,-6.15,10.44],[\"c\",0,0,.21,.15,.48,.27],[\"c\",2.61,1.47,4.35,3.03,5.13,4.65],[\"c\",1.14,2.34,.51,5.07,-1.44,6.39],[\"c\",-.66,.42,-1.32,.63,-2.13,.69],[\"c\",-2.01,.09,-3.81,-1.41,-4.26,-3.54],[\"c\",-.09,-.42,-.09,-1.2,-.03,-1.5],[\"c\",.15,-.45,.39,-.81,.66,-.93],[\"c\",.33,-.18,.84,-.21,1.23,-.15],[\"c\",.81,.18,1.32,.93,1.26,1.89],[\"c\",-.03,.36,-.09,.57,-.24,.9],[\"c\",-.15,.33,-.45,.6,-.72,.75],[\"c\",-.12,.06,-.18,.09,-.18,.12],[\"c\",0,.03,.03,.15,.09,.24],[\"c\",.18,.45,.54,.87,.96,1.08],[\"c\",1.11,.57,2.34,.18,2.88,-.9],[\"c\",.24,-.51,.33,-1.11,.24,-1.83],[\"c\",-.27,-1.92,-1.5,-3.54,-3.93,-5.13],[\"c\",-.48,-.33,-1.26,-.78,-1.29,-.78],[\"c\",-.03,0,-1.35,2.19,-2.91,4.89],[\"l\",-2.88,4.89],[\"l\",-.87,0],[\"l\",-.87,0],[\"l\",.03,-.06],[\"c\",.15,-.21,6.15,-10.41,6.15,-10.44],[\"c\",0,0,-.21,-.15,-.48,-.3],[\"c\",-2.61,-1.44,-4.35,-3,-5.13,-4.62],[\"c\",-.9,-1.89,-.72,-4.02,.48,-5.52],[\"c\",.69,-.84,1.68,-1.41,2.73,-1.53],[\"z\"],[\"m\",8.76,9.09],[\"c\",.03,-.03,.15,-.03,.27,-.03],[\"c\",.33,.03,.57,.18,.72,.48],[\"c\",.09,.18,.09,.57,0,.75],[\"c\",-.09,.18,-.21,.3,-.36,.39],[\"c\",-.15,.06,-.21,.06,-.39,.06],[\"c\",-.21,0,-.27,0,-.39,-.06],[\"c\",-.3,-.15,-.48,-.45,-.48,-.75],[\"c\",0,-.39,.24,-.72,.63,-.84],[\"z\"],[\"m\",-10.53,2.61],[\"c\",.03,-.03,.15,-.03,.27,-.03],[\"c\",.33,.03,.57,.18,.72,.48],[\"c\",.09,.18,.09,.57,0,.75],[\"c\",-.09,.18,-.21,.3,-.36,.39],[\"c\",-.15,.06,-.21,.06,-.39,.06],[\"c\",-.21,0,-.27,0,-.39,-.06],[\"c\",-.3,-.15,-.48,-.45,-.48,-.75],[\"c\",0,-.39,.24,-.72,.63,-.84],[\"z\"]],w:15,h:22.504},\"scripts.coda\":{d:[[\"M\",-.21,-10.47],[\"c\",.18,-.12,.42,-.06,.54,.12],[\"c\",.06,.09,.06,.18,.06,1.5],[\"l\",0,1.38],[\"l\",.18,0],[\"c\",.39,.06,.96,.24,1.38,.48],[\"c\",1.68,.93,2.82,3.24,3.03,6.12],[\"c\",.03,.24,.03,.45,.03,.45],[\"c\",0,.03,.6,.03,1.35,.03],[\"c\",1.5,0,1.47,0,1.59,.18],[\"c\",.09,.12,.09,.3,0,.42],[\"c\",-.12,.18,-.09,.18,-1.59,.18],[\"c\",-.75,0,-1.35,0,-1.35,.03],[\"c\",0,0,0,.21,-.03,.42],[\"c\",-.24,3.15,-1.53,5.58,-3.45,6.36],[\"c\",-.27,.12,-.72,.24,-.96,.27],[\"l\",-.18,0],[\"l\",0,1.38],[\"c\",0,1.32,0,1.41,-.06,1.5],[\"c\",-.15,.24,-.51,.24,-.66,0],[\"c\",-.06,-.09,-.06,-.18,-.06,-1.5],[\"l\",0,-1.38],[\"l\",-.18,0],[\"c\",-.39,-.06,-.96,-.24,-1.38,-.48],[\"c\",-1.68,-.93,-2.82,-3.24,-3.03,-6.15],[\"c\",-.03,-.21,-.03,-.42,-.03,-.42],[\"c\",0,-.03,-.6,-.03,-1.35,-.03],[\"c\",-1.5,0,-1.47,0,-1.59,-.18],[\"c\",-.09,-.12,-.09,-.3,0,-.42],[\"c\",.12,-.18,.09,-.18,1.59,-.18],[\"c\",.75,0,1.35,0,1.35,-.03],[\"c\",0,0,0,-.21,.03,-.45],[\"c\",.24,-3.12,1.53,-5.55,3.45,-6.33],[\"c\",.27,-.12,.72,-.24,.96,-.27],[\"l\",.18,0],[\"l\",0,-1.38],[\"c\",0,-1.53,0,-1.5,.18,-1.62],[\"z\"],[\"m\",-.18,6.93],[\"c\",0,-2.97,0,-3.15,-.06,-3.15],[\"c\",-.09,0,-.51,.15,-.66,.21],[\"c\",-.87,.51,-1.38,1.62,-1.56,3.51],[\"c\",-.06,.54,-.12,1.59,-.12,2.16],[\"l\",0,.42],[\"l\",1.2,0],[\"l\",1.2,0],[\"l\",0,-3.15],[\"z\"],[\"m\",1.17,-3.06],[\"c\",-.09,-.03,-.21,-.06,-.27,-.09],[\"l\",-.12,0],[\"l\",0,3.15],[\"l\",0,3.15],[\"l\",1.2,0],[\"l\",1.2,0],[\"l\",0,-.81],[\"c\",-.06,-2.4,-.33,-3.69,-.93,-4.59],[\"c\",-.27,-.39,-.66,-.69,-1.08,-.81],[\"z\"],[\"m\",-1.17,10.14],[\"l\",0,-3.15],[\"l\",-1.2,0],[\"l\",-1.2,0],[\"l\",0,.81],[\"c\",.03,.96,.06,1.47,.15,2.13],[\"c\",.24,2.04,.96,3.12,2.13,3.36],[\"l\",.12,0],[\"l\",0,-3.15],[\"z\"],[\"m\",3.18,-2.34],[\"l\",0,-.81],[\"l\",-1.2,0],[\"l\",-1.2,0],[\"l\",0,3.15],[\"l\",0,3.15],[\"l\",.12,0],[\"c\",1.17,-.24,1.89,-1.32,2.13,-3.36],[\"c\",.09,-.66,.12,-1.17,.15,-2.13],[\"z\"]],w:16.035,h:21.062},\"scripts.comma\":{d:[[\"M\",1.14,-4.62],[\"c\",.3,-.12,.69,-.03,.93,.15],[\"c\",.12,.12,.36,.45,.51,.78],[\"c\",.9,1.77,.54,4.05,-1.08,6.75],[\"c\",-.36,.63,-.87,1.38,-.96,1.44],[\"c\",-.18,.12,-.42,.06,-.54,-.12],[\"c\",-.09,-.18,-.09,-.3,.12,-.6],[\"c\",.96,-1.44,1.44,-2.97,1.38,-4.35],[\"c\",-.06,-.93,-.3,-1.68,-.78,-2.46],[\"c\",-.27,-.39,-.33,-.63,-.24,-.96],[\"c\",.09,-.27,.36,-.54,.66,-.63],[\"z\"]],w:3.042,h:9.237},\"scripts.roll\":{d:[[\"M\",1.95,-6],[\"c\",.21,-.09,.36,-.09,.57,0],[\"c\",.39,.15,.63,.39,1.47,1.35],[\"c\",.66,.75,.78,.87,1.08,1.05],[\"c\",.75,.45,1.65,.42,2.4,-.06],[\"c\",.12,-.09,.27,-.27,.54,-.6],[\"c\",.42,-.54,.51,-.63,.69,-.63],[\"c\",.09,0,.3,.12,.36,.21],[\"c\",.09,.12,.12,.3,.03,.42],[\"c\",-.06,.12,-3.15,3.9,-3.3,4.08],[\"c\",-.06,.06,-.18,.12,-.27,.18],[\"c\",-.27,.12,-.6,.06,-.99,-.27],[\"c\",-.27,-.21,-.42,-.39,-1.08,-1.14],[\"c\",-.63,-.72,-.81,-.9,-1.17,-1.08],[\"c\",-.36,-.18,-.57,-.21,-.99,-.21],[\"c\",-.39,0,-.63,.03,-.93,.18],[\"c\",-.36,.15,-.51,.27,-.9,.81],[\"c\",-.24,.27,-.45,.51,-.48,.54],[\"c\",-.12,.09,-.27,.06,-.39,0],[\"c\",-.24,-.15,-.33,-.39,-.21,-.6],[\"c\",.09,-.12,3.18,-3.87,3.33,-4.02],[\"c\",.06,-.06,.18,-.15,.24,-.21],[\"z\"]],w:10.817,h:6.125},\"scripts.prall\":{d:[[\"M\",-4.38,-3.69],[\"c\",.06,-.03,.18,-.06,.24,-.06],[\"c\",.3,0,.27,-.03,1.89,1.95],[\"l\",1.53,1.83],[\"c\",.03,0,.57,-.84,1.23,-1.83],[\"c\",1.14,-1.68,1.23,-1.83,1.35,-1.89],[\"c\",.06,-.03,.18,-.06,.24,-.06],[\"c\",.3,0,.27,-.03,1.89,1.95],[\"l\",1.53,1.83],[\"l\",.48,-.69],[\"c\",.51,-.78,.54,-.84,.69,-.9],[\"c\",.42,-.18,.87,.15,.81,.6],[\"c\",-.03,.12,-.3,.51,-1.5,2.37],[\"c\",-1.38,2.07,-1.5,2.22,-1.62,2.28],[\"c\",-.06,.03,-.18,.06,-.24,.06],[\"c\",-.3,0,-.27,.03,-1.89,-1.95],[\"l\",-1.53,-1.83],[\"c\",-.03,0,-.57,.84,-1.23,1.83],[\"c\",-1.14,1.68,-1.23,1.83,-1.35,1.89],[\"c\",-.06,.03,-.18,.06,-.24,.06],[\"c\",-.3,0,-.27,.03,-1.89,-1.95],[\"l\",-1.53,-1.83],[\"l\",-.48,.69],[\"c\",-.51,.78,-.54,.84,-.69,.9],[\"c\",-.42,.18,-.87,-.15,-.81,-.6],[\"c\",.03,-.12,.3,-.51,1.5,-2.37],[\"c\",1.38,-2.07,1.5,-2.22,1.62,-2.28],[\"z\"]],w:15.011,h:7.5},\"scripts.mordent\":{d:[[\"M\",-.21,-4.95],[\"c\",.27,-.15,.63,0,.75,.27],[\"c\",.06,.12,.06,.24,.06,1.44],[\"l\",0,1.29],[\"l\",.57,-.84],[\"c\",.51,-.75,.57,-.84,.69,-.9],[\"c\",.06,-.03,.18,-.06,.24,-.06],[\"c\",.3,0,.27,-.03,1.89,1.95],[\"l\",1.53,1.83],[\"l\",.48,-.69],[\"c\",.51,-.78,.54,-.84,.69,-.9],[\"c\",.42,-.18,.87,.15,.81,.6],[\"c\",-.03,.12,-.3,.51,-1.5,2.37],[\"c\",-1.38,2.07,-1.5,2.22,-1.62,2.28],[\"c\",-.06,.03,-.18,.06,-.24,.06],[\"c\",-.3,0,-.27,.03,-1.83,-1.89],[\"c\",-.81,-.99,-1.5,-1.8,-1.53,-1.86],[\"c\",-.06,-.03,-.06,-.03,-.12,.03],[\"c\",-.06,.06,-.06,.15,-.06,2.28],[\"c\",0,1.95,0,2.25,-.06,2.34],[\"c\",-.18,.45,-.81,.48,-1.05,.03],[\"c\",-.03,-.06,-.06,-.24,-.06,-1.41],[\"l\",0,-1.35],[\"l\",-.57,.84],[\"c\",-.54,.78,-.6,.87,-.72,.93],[\"c\",-.06,.03,-.18,.06,-.24,.06],[\"c\",-.3,0,-.27,.03,-1.89,-1.95],[\"l\",-1.53,-1.83],[\"l\",-.48,.69],[\"c\",-.51,.78,-.54,.84,-.69,.9],[\"c\",-.42,.18,-.87,-.15,-.81,-.6],[\"c\",.03,-.12,.3,-.51,1.5,-2.37],[\"c\",1.38,-2.07,1.5,-2.22,1.62,-2.28],[\"c\",.06,-.03,.18,-.06,.24,-.06],[\"c\",.3,0,.27,-.03,1.89,1.95],[\"l\",1.53,1.83],[\"c\",.03,0,.06,-.06,.09,-.09],[\"c\",.06,-.12,.06,-.15,.06,-2.28],[\"c\",0,-1.92,0,-2.22,.06,-2.31],[\"c\",.06,-.15,.15,-.24,.3,-.3],[\"z\"]],w:15.011,h:10.012},\"flags.u8th\":{d:[[\"M\",-.42,3.75],[\"l\",0,-3.75],[\"l\",.21,0],[\"l\",.21,0],[\"l\",0,.18],[\"c\",0,.3,.06,.84,.12,1.23],[\"c\",.24,1.53,.9,3.12,2.13,5.16],[\"l\",.99,1.59],[\"c\",.87,1.44,1.38,2.34,1.77,3.09],[\"c\",.81,1.68,1.2,3.06,1.26,4.53],[\"c\",.03,1.53,-.21,3.27,-.75,5.01],[\"c\",-.21,.69,-.51,1.5,-.6,1.59],[\"c\",-.09,.12,-.27,.21,-.42,.21],[\"c\",-.15,0,-.42,-.12,-.51,-.21],[\"c\",-.15,-.18,-.18,-.42,-.09,-.66],[\"c\",.15,-.33,.45,-1.2,.57,-1.62],[\"c\",.42,-1.38,.6,-2.58,.6,-3.9],[\"c\",0,-.66,0,-.81,-.06,-1.11],[\"c\",-.39,-2.07,-1.8,-4.26,-4.59,-7.14],[\"l\",-.42,-.45],[\"l\",-.21,0],[\"l\",-.21,0],[\"l\",0,-3.75],[\"z\"]],w:6.692,h:22.59},\"flags.u16th\":{d:[[\"M\",-.42,7.5],[\"l\",0,-7.5],[\"l\",.21,0],[\"l\",.21,0],[\"l\",0,.39],[\"c\",.06,1.08,.39,2.19,.99,3.39],[\"c\",.45,.9,.87,1.59,1.95,3.12],[\"c\",1.29,1.86,1.77,2.64,2.22,3.57],[\"c\",.45,.93,.72,1.8,.87,2.64],[\"c\",.06,.51,.06,1.5,0,1.92],[\"c\",-.12,.6,-.3,1.2,-.54,1.71],[\"l\",-.09,.24],[\"l\",.18,.45],[\"c\",.51,1.2,.72,2.22,.69,3.42],[\"c\",-.06,1.53,-.39,3.03,-.99,4.53],[\"c\",-.3,.75,-.36,.81,-.57,.9],[\"c\",-.15,.09,-.33,.06,-.48,0],[\"c\",-.18,-.09,-.27,-.18,-.33,-.33],[\"c\",-.09,-.18,-.06,-.3,.12,-.75],[\"c\",.66,-1.41,1.02,-2.88,1.08,-4.32],[\"c\",0,-.6,-.03,-1.05,-.18,-1.59],[\"c\",-.3,-1.2,-.99,-2.4,-2.25,-3.87],[\"c\",-.42,-.48,-1.53,-1.62,-2.19,-2.22],[\"l\",-.45,-.42],[\"l\",-.03,1.11],[\"l\",0,1.11],[\"l\",-.21,0],[\"l\",-.21,0],[\"l\",0,-7.5],[\"z\"],[\"m\",1.65,.09],[\"c\",-.3,-.3,-.69,-.72,-.9,-.87],[\"l\",-.33,-.33],[\"l\",0,.15],[\"c\",0,.3,.06,.81,.15,1.26],[\"c\",.27,1.29,.87,2.61,2.04,4.29],[\"c\",.15,.24,.6,.87,.96,1.38],[\"l\",1.08,1.53],[\"l\",.42,.63],[\"c\",.03,0,.12,-.36,.21,-.72],[\"c\",.06,-.33,.06,-1.2,0,-1.62],[\"c\",-.33,-1.71,-1.44,-3.48,-3.63,-5.7],[\"z\"]],w:6.693,h:26.337},\"flags.u32nd\":{d:[[\"M\",-.42,11.25],[\"l\",0,-11.25],[\"l\",.21,0],[\"l\",.21,0],[\"l\",0,.36],[\"c\",.09,1.68,.69,3.27,2.07,5.46],[\"l\",.87,1.35],[\"c\",1.02,1.62,1.47,2.37,1.86,3.18],[\"c\",.48,1.02,.78,1.92,.93,2.88],[\"c\",.06,.48,.06,1.5,0,1.89],[\"c\",-.09,.42,-.21,.87,-.36,1.26],[\"l\",-.12,.3],[\"l\",.15,.39],[\"c\",.69,1.56,.84,2.88,.54,4.38],[\"c\",-.09,.45,-.27,1.08,-.45,1.47],[\"l\",-.12,.24],[\"l\",.18,.36],[\"c\",.33,.72,.57,1.56,.69,2.34],[\"c\",.12,1.02,-.06,2.52,-.42,3.84],[\"c\",-.27,.93,-.75,2.13,-.93,2.31],[\"c\",-.18,.15,-.45,.18,-.66,.09],[\"c\",-.18,-.09,-.27,-.18,-.33,-.33],[\"c\",-.09,-.18,-.06,-.3,.06,-.6],[\"c\",.21,-.36,.42,-.9,.57,-1.38],[\"c\",.51,-1.41,.69,-3.06,.48,-4.08],[\"c\",-.15,-.81,-.57,-1.68,-1.2,-2.55],[\"c\",-.72,-.99,-1.83,-2.13,-3.3,-3.33],[\"l\",-.48,-.42],[\"l\",-.03,1.53],[\"l\",0,1.56],[\"l\",-.21,0],[\"l\",-.21,0],[\"l\",0,-11.25],[\"z\"],[\"m\",1.26,-3.96],[\"c\",-.27,-.3,-.54,-.6,-.66,-.72],[\"l\",-.18,-.21],[\"l\",0,.42],[\"c\",.06,.87,.24,1.74,.66,2.67],[\"c\",.36,.87,.96,1.86,1.92,3.18],[\"c\",.21,.33,.63,.87,.87,1.23],[\"c\",.27,.39,.6,.84,.75,1.08],[\"l\",.27,.39],[\"l\",.03,-.12],[\"c\",.12,-.45,.15,-1.05,.09,-1.59],[\"c\",-.27,-1.86,-1.38,-3.78,-3.75,-6.33],[\"z\"],[\"m\",-.27,6.09],[\"c\",-.27,-.21,-.48,-.42,-.51,-.45],[\"c\",-.06,-.03,-.06,-.03,-.06,.21],[\"c\",0,.9,.3,2.04,.81,3.09],[\"c\",.48,1.02,.96,1.77,2.37,3.63],[\"c\",.6,.78,1.05,1.44,1.29,1.77],[\"c\",.06,.12,.15,.21,.15,.18],[\"c\",.03,-.03,.18,-.57,.24,-.87],[\"c\",.06,-.45,.06,-1.32,-.03,-1.74],[\"c\",-.09,-.48,-.24,-.9,-.51,-1.44],[\"c\",-.66,-1.35,-1.83,-2.7,-3.75,-4.38],[\"z\"]],w:6.697,h:32.145},\"flags.u64th\":{d:[[\"M\",-.42,15],[\"l\",0,-15],[\"l\",.21,0],[\"l\",.21,0],[\"l\",0,.36],[\"c\",.06,1.2,.39,2.37,1.02,3.66],[\"c\",.39,.81,.84,1.56,1.8,3.09],[\"c\",.81,1.26,1.05,1.68,1.35,2.22],[\"c\",.87,1.5,1.35,2.79,1.56,4.08],[\"c\",.06,.54,.06,1.56,-.03,2.04],[\"c\",-.09,.48,-.21,.99,-.36,1.35],[\"l\",-.12,.27],[\"l\",.12,.27],[\"c\",.09,.15,.21,.45,.27,.66],[\"c\",.69,1.89,.63,3.66,-.18,5.46],[\"l\",-.18,.39],[\"l\",.15,.33],[\"c\",.3,.66,.51,1.44,.63,2.1],[\"c\",.06,.48,.06,1.35,0,1.71],[\"c\",-.15,.57,-.42,1.2,-.78,1.68],[\"l\",-.21,.27],[\"l\",.18,.33],[\"c\",.57,1.05,.93,2.13,1.02,3.18],[\"c\",.06,.72,0,1.83,-.21,2.79],[\"c\",-.18,1.02,-.63,2.34,-1.02,3.09],[\"c\",-.15,.33,-.48,.45,-.78,.3],[\"c\",-.18,-.09,-.27,-.18,-.33,-.33],[\"c\",-.09,-.18,-.06,-.3,.03,-.54],[\"c\",.75,-1.5,1.23,-3.45,1.17,-4.89],[\"c\",-.06,-1.02,-.42,-2.01,-1.17,-3.15],[\"c\",-.48,-.72,-1.02,-1.35,-1.89,-2.22],[\"c\",-.57,-.57,-1.56,-1.5,-1.92,-1.77],[\"l\",-.12,-.09],[\"l\",0,1.68],[\"l\",0,1.68],[\"l\",-.21,0],[\"l\",-.21,0],[\"l\",0,-15],[\"z\"],[\"m\",.93,-8.07],[\"c\",-.27,-.3,-.48,-.54,-.51,-.54],[\"c\",0,0,0,.69,.03,1.02],[\"c\",.15,1.47,.75,2.94,2.04,4.83],[\"l\",1.08,1.53],[\"c\",.39,.57,.84,1.2,.99,1.44],[\"c\",.15,.24,.3,.45,.3,.45],[\"c\",0,0,.03,-.09,.06,-.21],[\"c\",.36,-1.59,-.15,-3.33,-1.47,-5.4],[\"c\",-.63,-.93,-1.35,-1.83,-2.52,-3.12],[\"z\"],[\"m\",.06,6.72],[\"c\",-.24,-.21,-.48,-.42,-.51,-.45],[\"l\",-.06,-.06],[\"l\",0,.33],[\"c\",0,1.2,.3,2.34,.93,3.6],[\"c\",.45,.9,.96,1.68,2.25,3.51],[\"c\",.39,.54,.84,1.17,1.02,1.44],[\"c\",.21,.33,.33,.51,.33,.48],[\"c\",.06,-.09,.21,-.63,.3,-.99],[\"c\",.06,-.33,.06,-.45,.06,-.96],[\"c\",0,-.6,-.03,-.84,-.18,-1.35],[\"c\",-.3,-1.08,-1.02,-2.28,-2.13,-3.57],[\"c\",-.39,-.45,-1.44,-1.47,-2.01,-1.98],[\"z\"],[\"m\",0,6.72],[\"c\",-.24,-.21,-.48,-.39,-.51,-.42],[\"l\",-.06,-.06],[\"l\",0,.33],[\"c\",0,1.41,.45,2.82,1.38,4.35],[\"c\",.42,.72,.72,1.14,1.86,2.73],[\"c\",.36,.45,.75,.99,.87,1.2],[\"c\",.15,.21,.3,.36,.3,.36],[\"c\",.06,0,.3,-.48,.39,-.75],[\"c\",.09,-.36,.12,-.63,.12,-1.05],[\"c\",-.06,-1.05,-.45,-2.04,-1.2,-3.18],[\"c\",-.57,-.87,-1.11,-1.53,-2.07,-2.49],[\"c\",-.36,-.33,-.84,-.78,-1.08,-1.02],[\"z\"]],w:6.682,h:39.694},\"flags.d8th\":{d:[[\"M\",5.67,-21.63],[\"c\",.24,-.12,.54,-.06,.69,.15],[\"c\",.06,.06,.21,.36,.39,.66],[\"c\",.84,1.77,1.26,3.36,1.32,5.1],[\"c\",.03,1.29,-.21,2.37,-.81,3.63],[\"c\",-.6,1.23,-1.26,2.13,-3.21,4.38],[\"c\",-1.35,1.53,-1.86,2.19,-2.4,2.97],[\"c\",-.63,.93,-1.11,1.92,-1.38,2.79],[\"c\",-.15,.54,-.27,1.35,-.27,1.8],[\"l\",0,.15],[\"l\",-.21,0],[\"l\",-.21,0],[\"l\",0,-3.75],[\"l\",0,-3.75],[\"l\",.21,0],[\"l\",.21,0],[\"l\",.48,-.3],[\"c\",1.83,-1.11,3.12,-2.1,4.17,-3.12],[\"c\",.78,-.81,1.32,-1.53,1.71,-2.31],[\"c\",.45,-.93,.6,-1.74,.51,-2.88],[\"c\",-.12,-1.56,-.63,-3.18,-1.47,-4.68],[\"c\",-.12,-.21,-.15,-.33,-.06,-.51],[\"c\",.06,-.15,.15,-.24,.33,-.33],[\"z\"]],\nw:8.492,h:21.691},\"flags.ugrace\":{d:[[\"M\",6.03,6.93],[\"c\",.15,-.09,.33,-.06,.51,0],[\"c\",.15,.09,.21,.15,.3,.33],[\"c\",.09,.18,.06,.39,-.03,.54],[\"c\",-.06,.15,-10.89,8.88,-11.07,8.97],[\"c\",-.15,.09,-.33,.06,-.48,0],[\"c\",-.18,-.09,-.24,-.15,-.33,-.33],[\"c\",-.09,-.18,-.06,-.39,.03,-.54],[\"c\",.06,-.15,10.89,-8.88,11.07,-8.97],[\"z\"]],w:12.019,h:9.954},\"flags.dgrace\":{d:[[\"M\",-6.06,-15.93],[\"c\",.18,-.09,.33,-.12,.48,-.06],[\"c\",.18,.09,14.01,8.04,14.1,8.1],[\"c\",.12,.12,.18,.33,.18,.51],[\"c\",-.03,.21,-.15,.39,-.36,.48],[\"c\",-.18,.09,-.33,.12,-.48,.06],[\"c\",-.18,-.09,-14.01,-8.04,-14.1,-8.1],[\"c\",-.12,-.12,-.18,-.33,-.18,-.51],[\"c\",.03,-.21,.15,-.39,.36,-.48],[\"z\"]],w:15.12,h:9.212},\"flags.d16th\":{d:[[\"M\",6.84,-22.53],[\"c\",.27,-.12,.57,-.06,.72,.15],[\"c\",.15,.15,.33,.87,.45,1.56],[\"c\",.06,.33,.06,1.35,0,1.65],[\"c\",-.06,.33,-.15,.78,-.27,1.11],[\"c\",-.12,.33,-.45,.96,-.66,1.32],[\"l\",-.18,.27],[\"l\",.09,.18],[\"c\",.48,1.02,.72,2.25,.69,3.3],[\"c\",-.06,1.23,-.42,2.28,-1.26,3.45],[\"c\",-.57,.87,-.99,1.32,-3,3.39],[\"c\",-1.56,1.56,-2.22,2.4,-2.76,3.45],[\"c\",-.42,.84,-.66,1.8,-.66,2.55],[\"l\",0,.15],[\"l\",-.21,0],[\"l\",-.21,0],[\"l\",0,-7.5],[\"l\",0,-7.5],[\"l\",.21,0],[\"l\",.21,0],[\"l\",0,1.14],[\"l\",0,1.11],[\"l\",.27,-.15],[\"c\",1.11,-.57,1.77,-.99,2.52,-1.47],[\"c\",2.37,-1.56,3.69,-3.15,4.05,-4.83],[\"c\",.03,-.18,.03,-.39,.03,-.78],[\"c\",0,-.6,-.03,-.93,-.24,-1.5],[\"c\",-.06,-.18,-.12,-.39,-.15,-.45],[\"c\",-.03,-.24,.12,-.48,.36,-.6],[\"z\"],[\"m\",-.63,7.5],[\"c\",-.06,-.18,-.15,-.36,-.15,-.36],[\"c\",-.03,0,-.03,.03,-.06,.06],[\"c\",-.06,.12,-.96,1.02,-1.95,1.98],[\"c\",-.63,.57,-1.26,1.17,-1.44,1.35],[\"c\",-1.53,1.62,-2.28,2.85,-2.55,4.32],[\"c\",-.03,.18,-.03,.54,-.06,.99],[\"l\",0,.69],[\"l\",.18,-.09],[\"c\",.93,-.54,2.1,-1.29,2.82,-1.83],[\"c\",.69,-.51,1.02,-.81,1.53,-1.29],[\"c\",1.86,-1.89,2.37,-3.66,1.68,-5.82],[\"z\"]],w:8.475,h:22.591},\"flags.d32nd\":{d:[[\"M\",6.84,-29.13],[\"c\",.27,-.12,.57,-.06,.72,.15],[\"c\",.12,.12,.27,.63,.36,1.11],[\"c\",.33,1.59,.06,3.06,-.81,4.47],[\"l\",-.18,.27],[\"l\",.09,.15],[\"c\",.12,.24,.33,.69,.45,1.05],[\"c\",.63,1.83,.45,3.57,-.57,5.22],[\"l\",-.18,.3],[\"l\",.15,.27],[\"c\",.42,.87,.6,1.71,.57,2.61],[\"c\",-.06,1.29,-.48,2.46,-1.35,3.78],[\"c\",-.54,.81,-.93,1.29,-2.46,3],[\"c\",-.51,.54,-1.05,1.17,-1.26,1.41],[\"c\",-1.56,1.86,-2.25,3.36,-2.37,5.01],[\"l\",0,.33],[\"l\",-.21,0],[\"l\",-.21,0],[\"l\",0,-11.25],[\"l\",0,-11.25],[\"l\",.21,0],[\"l\",.21,0],[\"l\",0,1.35],[\"l\",.03,1.35],[\"l\",.78,-.39],[\"c\",1.38,-.69,2.34,-1.26,3.24,-1.92],[\"c\",1.38,-1.02,2.28,-2.13,2.64,-3.21],[\"c\",.15,-.48,.18,-.72,.18,-1.29],[\"c\",0,-.57,-.06,-.9,-.24,-1.47],[\"c\",-.06,-.18,-.12,-.39,-.15,-.45],[\"c\",-.03,-.24,.12,-.48,.36,-.6],[\"z\"],[\"m\",-.63,7.2],[\"c\",-.09,-.18,-.12,-.21,-.12,-.15],[\"c\",-.03,.09,-1.02,1.08,-2.04,2.04],[\"c\",-1.17,1.08,-1.65,1.56,-2.07,2.04],[\"c\",-.84,.96,-1.38,1.86,-1.68,2.76],[\"c\",-.21,.57,-.27,.99,-.3,1.65],[\"l\",0,.54],[\"l\",.66,-.33],[\"c\",3.57,-1.86,5.49,-3.69,5.94,-5.7],[\"c\",.06,-.39,.06,-1.2,-.03,-1.65],[\"c\",-.06,-.39,-.24,-.9,-.36,-1.2],[\"z\"],[\"m\",-.06,7.2],[\"c\",-.06,-.15,-.12,-.33,-.15,-.45],[\"l\",-.06,-.18],[\"l\",-.18,.21],[\"l\",-1.83,1.83],[\"c\",-.87,.9,-1.77,1.8,-1.95,2.01],[\"c\",-1.08,1.29,-1.62,2.31,-1.89,3.51],[\"c\",-.06,.3,-.06,.51,-.09,.93],[\"l\",0,.57],[\"l\",.09,-.06],[\"c\",.75,-.45,1.89,-1.26,2.52,-1.74],[\"c\",.81,-.66,1.74,-1.53,2.22,-2.16],[\"c\",1.26,-1.53,1.68,-3.06,1.32,-4.47],[\"z\"]],w:8.385,h:29.191},\"flags.d64th\":{d:[[\"M\",7.08,-32.88],[\"c\",.3,-.12,.66,-.03,.78,.24],[\"c\",.18,.33,.27,2.1,.15,2.64],[\"c\",-.09,.39,-.21,.78,-.39,1.08],[\"l\",-.15,.3],[\"l\",.09,.27],[\"c\",.03,.12,.09,.45,.12,.69],[\"c\",.27,1.44,.18,2.55,-.3,3.6],[\"l\",-.12,.33],[\"l\",.06,.42],[\"c\",.27,1.35,.33,2.82,.21,3.63],[\"c\",-.12,.6,-.3,1.23,-.57,1.8],[\"l\",-.15,.27],[\"l\",.03,.42],[\"c\",.06,1.02,.06,2.7,.03,3.06],[\"c\",-.15,1.47,-.66,2.76,-1.74,4.41],[\"c\",-.45,.69,-.75,1.11,-1.74,2.37],[\"c\",-1.05,1.38,-1.5,1.98,-1.95,2.73],[\"c\",-.93,1.5,-1.38,2.82,-1.44,4.2],[\"l\",0,.42],[\"l\",-.21,0],[\"l\",-.21,0],[\"l\",0,-15],[\"l\",0,-15],[\"l\",.21,0],[\"l\",.21,0],[\"l\",0,1.86],[\"l\",0,1.89],[\"c\",0,0,.21,-.03,.45,-.09],[\"c\",2.22,-.39,4.08,-1.11,5.19,-2.01],[\"c\",.63,-.54,1.02,-1.14,1.2,-1.8],[\"c\",.06,-.3,.06,-1.14,-.03,-1.65],[\"c\",-.03,-.18,-.06,-.39,-.09,-.48],[\"c\",-.03,-.24,.12,-.48,.36,-.6],[\"z\"],[\"m\",-.45,6.15],[\"c\",-.03,-.18,-.06,-.42,-.06,-.54],[\"l\",-.03,-.18],[\"l\",-.33,.3],[\"c\",-.42,.36,-.87,.72,-1.68,1.29],[\"c\",-1.98,1.38,-2.25,1.59,-2.85,2.16],[\"c\",-.75,.69,-1.23,1.44,-1.47,2.19],[\"c\",-.15,.45,-.18,.63,-.21,1.35],[\"l\",0,.66],[\"l\",.39,-.18],[\"c\",1.83,-.9,3.45,-1.95,4.47,-2.91],[\"c\",.93,-.9,1.53,-1.83,1.74,-2.82],[\"c\",.06,-.33,.06,-.87,.03,-1.32],[\"z\"],[\"m\",-.27,4.86],[\"c\",-.03,-.21,-.06,-.36,-.06,-.36],[\"c\",0,-.03,-.12,.09,-.24,.24],[\"c\",-.39,.48,-.99,1.08,-2.16,2.19],[\"c\",-1.47,1.38,-1.92,1.83,-2.46,2.49],[\"c\",-.66,.87,-1.08,1.74,-1.29,2.58],[\"c\",-.09,.42,-.15,.87,-.15,1.44],[\"l\",0,.54],[\"l\",.48,-.33],[\"c\",1.5,-1.02,2.58,-1.89,3.51,-2.82],[\"c\",1.47,-1.47,2.25,-2.85,2.4,-4.26],[\"c\",.03,-.39,.03,-1.17,-.03,-1.71],[\"z\"],[\"m\",-.66,7.68],[\"c\",.03,-.15,.03,-.6,.03,-.99],[\"l\",0,-.72],[\"l\",-.27,.33],[\"l\",-1.74,1.98],[\"c\",-1.77,1.92,-2.43,2.76,-2.97,3.9],[\"c\",-.51,1.02,-.72,1.77,-.75,2.91],[\"c\",0,.63,0,.63,.06,.6],[\"c\",.03,-.03,.3,-.27,.63,-.54],[\"c\",.66,-.6,1.86,-1.8,2.31,-2.31],[\"c\",1.65,-1.89,2.52,-3.54,2.7,-5.16],[\"z\"]],w:8.485,h:32.932},\"clefs.C\":{d:[[\"M\",.06,-14.94],[\"l\",.09,-.06],[\"l\",1.92,0],[\"l\",1.92,0],[\"l\",.09,.06],[\"l\",.06,.09],[\"l\",0,14.85],[\"l\",0,14.82],[\"l\",-.06,.09],[\"l\",-.09,.06],[\"l\",-1.92,0],[\"l\",-1.92,0],[\"l\",-.09,-.06],[\"l\",-.06,-.09],[\"l\",0,-14.82],[\"l\",0,-14.85],[\"z\"],[\"m\",5.37,0],[\"c\",.09,-.06,.09,-.06,.57,-.06],[\"c\",.45,0,.45,0,.54,.06],[\"l\",.06,.09],[\"l\",0,7.14],[\"l\",0,7.11],[\"l\",.09,-.06],[\"c\",.18,-.18,.72,-.84,.96,-1.2],[\"c\",.3,-.45,.66,-1.17,.84,-1.65],[\"c\",.36,-.9,.57,-1.83,.6,-2.79],[\"c\",.03,-.48,.03,-.54,.09,-.63],[\"c\",.12,-.18,.36,-.21,.54,-.12],[\"c\",.18,.09,.21,.15,.24,.66],[\"c\",.06,.87,.21,1.56,.57,2.22],[\"c\",.51,1.02,1.26,1.68,2.22,1.92],[\"c\",.21,.06,.33,.06,.78,.06],[\"c\",.45,0,.57,0,.84,-.06],[\"c\",.45,-.12,.81,-.33,1.08,-.6],[\"c\",.57,-.57,.87,-1.41,.99,-2.88],[\"c\",.06,-.54,.06,-3,0,-3.57],[\"c\",-.21,-2.58,-.84,-3.87,-2.16,-4.5],[\"c\",-.48,-.21,-1.17,-.36,-1.77,-.36],[\"c\",-.69,0,-1.29,.27,-1.5,.72],[\"c\",-.06,.15,-.06,.21,-.06,.42],[\"c\",0,.24,0,.3,.06,.45],[\"c\",.12,.24,.24,.39,.63,.66],[\"c\",.42,.3,.57,.48,.69,.72],[\"c\",.06,.15,.06,.21,.06,.48],[\"c\",0,.39,-.03,.63,-.21,.96],[\"c\",-.3,.6,-.87,1.08,-1.5,1.26],[\"c\",-.27,.06,-.87,.06,-1.14,0],[\"c\",-.78,-.24,-1.44,-.87,-1.65,-1.68],[\"c\",-.12,-.42,-.09,-1.17,.09,-1.71],[\"c\",.51,-1.65,1.98,-2.82,3.81,-3.09],[\"c\",.84,-.09,2.46,.03,3.51,.27],[\"c\",2.22,.57,3.69,1.8,4.44,3.75],[\"c\",.36,.93,.57,2.13,.57,3.36],[\"c\",0,1.44,-.48,2.73,-1.38,3.81],[\"c\",-1.26,1.5,-3.27,2.43,-5.28,2.43],[\"c\",-.48,0,-.51,0,-.75,-.09],[\"c\",-.15,-.03,-.48,-.21,-.78,-.36],[\"c\",-.69,-.36,-.87,-.42,-1.26,-.42],[\"c\",-.27,0,-.3,0,-.51,.09],[\"c\",-.57,.3,-.81,.9,-.81,2.1],[\"c\",0,1.23,.24,1.83,.81,2.13],[\"c\",.21,.09,.24,.09,.51,.09],[\"c\",.39,0,.57,-.06,1.26,-.42],[\"c\",.3,-.15,.63,-.33,.78,-.36],[\"c\",.24,-.09,.27,-.09,.75,-.09],[\"c\",2.01,0,4.02,.93,5.28,2.4],[\"c\",.9,1.11,1.38,2.4,1.38,3.84],[\"c\",0,1.5,-.3,2.88,-.84,3.96],[\"c\",-.78,1.59,-2.19,2.64,-4.17,3.15],[\"c\",-1.05,.24,-2.67,.36,-3.51,.27],[\"c\",-1.83,-.27,-3.3,-1.44,-3.81,-3.09],[\"c\",-.18,-.54,-.21,-1.29,-.09,-1.74],[\"c\",.15,-.6,.63,-1.2,1.23,-1.47],[\"c\",.36,-.18,.57,-.21,.99,-.21],[\"c\",.42,0,.63,.03,1.02,.21],[\"c\",.42,.21,.84,.63,1.05,1.05],[\"c\",.18,.36,.21,.6,.21,.96],[\"c\",0,.3,0,.36,-.06,.51],[\"c\",-.12,.24,-.27,.42,-.69,.72],[\"c\",-.57,.42,-.69,.63,-.69,1.08],[\"c\",0,.24,0,.3,.06,.45],[\"c\",.12,.21,.3,.39,.57,.54],[\"c\",.42,.18,.87,.21,1.53,.15],[\"c\",1.08,-.15,1.8,-.57,2.34,-1.32],[\"c\",.54,-.75,.84,-1.83,.99,-3.51],[\"c\",.06,-.57,.06,-3.03,0,-3.57],[\"c\",-.12,-1.47,-.42,-2.31,-.99,-2.88],[\"c\",-.27,-.27,-.63,-.48,-1.08,-.6],[\"c\",-.27,-.06,-.39,-.06,-.84,-.06],[\"c\",-.45,0,-.57,0,-.78,.06],[\"c\",-1.14,.27,-2.01,1.17,-2.46,2.49],[\"c\",-.21,.57,-.3,.99,-.33,1.65],[\"c\",-.03,.51,-.06,.57,-.24,.66],[\"c\",-.12,.06,-.27,.06,-.39,0],[\"c\",-.21,-.09,-.21,-.15,-.24,-.75],[\"c\",-.09,-1.92,-.78,-3.72,-2.01,-5.19],[\"c\",-.18,-.21,-.36,-.42,-.39,-.45],[\"l\",-.09,-.06],[\"l\",0,7.11],[\"l\",0,7.14],[\"l\",-.06,.09],[\"c\",-.09,.06,-.09,.06,-.54,.06],[\"c\",-.48,0,-.48,0,-.57,-.06],[\"l\",-.06,-.09],[\"l\",0,-14.82],[\"l\",0,-14.85],[\"z\"]],w:20.31,h:29.97},\"clefs.F\":{d:[[\"M\",6.3,-7.8],[\"c\",.36,-.03,1.65,0,2.13,.03],[\"c\",3.6,.42,6.03,2.1,6.93,4.86],[\"c\",.27,.84,.36,1.5,.36,2.58],[\"c\",0,.9,-.03,1.35,-.18,2.16],[\"c\",-.78,3.78,-3.54,7.08,-8.37,9.96],[\"c\",-1.74,1.05,-3.87,2.13,-6.18,3.12],[\"c\",-.39,.18,-.75,.33,-.81,.36],[\"c\",-.06,.03,-.15,.06,-.18,.06],[\"c\",-.15,0,-.33,-.18,-.33,-.33],[\"c\",0,-.15,.06,-.21,.51,-.48],[\"c\",3,-1.77,5.13,-3.21,6.84,-4.74],[\"c\",.51,-.45,1.59,-1.5,1.95,-1.95],[\"c\",1.89,-2.19,2.88,-4.32,3.15,-6.78],[\"c\",.06,-.42,.06,-1.77,0,-2.19],[\"c\",-.24,-2.01,-.93,-3.63,-2.04,-4.71],[\"c\",-.63,-.63,-1.29,-1.02,-2.07,-1.2],[\"c\",-1.62,-.39,-3.36,.15,-4.56,1.44],[\"c\",-.54,.6,-1.05,1.47,-1.32,2.22],[\"l\",-.09,.21],[\"l\",.24,-.12],[\"c\",.39,-.21,.63,-.24,1.11,-.24],[\"c\",.3,0,.45,0,.66,.06],[\"c\",1.92,.48,2.85,2.55,1.95,4.38],[\"c\",-.45,.99,-1.41,1.62,-2.46,1.71],[\"c\",-1.47,.09,-2.91,-.87,-3.39,-2.25],[\"c\",-.18,-.57,-.21,-1.32,-.03,-2.28],[\"c\",.39,-2.25,1.83,-4.2,3.81,-5.19],[\"c\",.69,-.36,1.59,-.6,2.37,-.69],[\"z\"],[\"m\",11.58,2.52],[\"c\",.84,-.21,1.71,.3,1.89,1.14],[\"c\",.3,1.17,-.72,2.19,-1.89,1.89],[\"c\",-.99,-.21,-1.5,-1.32,-1.02,-2.25],[\"c\",.18,-.39,.6,-.69,1.02,-.78],[\"z\"],[\"m\",0,7.5],[\"c\",.84,-.21,1.71,.3,1.89,1.14],[\"c\",.21,.87,-.3,1.71,-1.14,1.89],[\"c\",-.87,.21,-1.71,-.3,-1.89,-1.14],[\"c\",-.21,-.84,.3,-1.71,1.14,-1.89],[\"z\"]],w:20.153,h:23.142},\"clefs.G\":{d:[[\"M\",9.69,-37.41],[\"c\",.09,-.09,.24,-.06,.36,0],[\"c\",.12,.09,.57,.6,.96,1.11],[\"c\",1.77,2.34,3.21,5.85,3.57,8.73],[\"c\",.21,1.56,.03,3.27,-.45,4.86],[\"c\",-.69,2.31,-1.92,4.47,-4.23,7.44],[\"c\",-.3,.39,-.57,.72,-.6,.75],[\"c\",-.03,.06,0,.15,.18,.78],[\"c\",.54,1.68,1.38,4.44,1.68,5.49],[\"l\",.09,.42],[\"l\",.39,0],[\"c\",1.47,.09,2.76,.51,3.96,1.29],[\"c\",1.83,1.23,3.06,3.21,3.39,5.52],[\"c\",.09,.45,.12,1.29,.06,1.74],[\"c\",-.09,1.02,-.33,1.83,-.75,2.73],[\"c\",-.84,1.71,-2.28,3.06,-4.02,3.72],[\"l\",-.33,.12],[\"l\",.03,1.26],[\"c\",0,1.74,-.06,3.63,-.21,4.62],[\"c\",-.45,3.06,-2.19,5.49,-4.47,6.21],[\"c\",-.57,.18,-.9,.21,-1.59,.21],[\"c\",-.69,0,-1.02,-.03,-1.65,-.21],[\"c\",-1.14,-.27,-2.13,-.84,-2.94,-1.65],[\"c\",-.99,-.99,-1.56,-2.16,-1.71,-3.54],[\"c\",-.09,-.81,.06,-1.53,.45,-2.13],[\"c\",.63,-.99,1.83,-1.56,3,-1.53],[\"c\",1.5,.09,2.64,1.32,2.73,2.94],[\"c\",.06,1.47,-.93,2.7,-2.37,2.97],[\"c\",-.45,.06,-.84,.03,-1.29,-.09],[\"l\",-.21,-.09],[\"l\",.09,.12],[\"c\",.39,.54,.78,.93,1.32,1.26],[\"c\",1.35,.87,3.06,1.02,4.35,.36],[\"c\",1.44,-.72,2.52,-2.28,2.97,-4.35],[\"c\",.15,-.66,.24,-1.5,.3,-3.03],[\"c\",.03,-.84,.03,-2.94,0,-3],[\"c\",-.03,0,-.18,0,-.36,.03],[\"c\",-.66,.12,-.99,.12,-1.83,.12],[\"c\",-1.05,0,-1.71,-.06,-2.61,-.3],[\"c\",-4.02,-.99,-7.11,-4.35,-7.8,-8.46],[\"c\",-.12,-.66,-.12,-.99,-.12,-1.83],[\"c\",0,-.84,0,-1.14,.15,-1.92],[\"c\",.36,-2.28,1.41,-4.62,3.3,-7.29],[\"l\",2.79,-3.6],[\"c\",.54,-.66,.96,-1.2,.96,-1.23],[\"c\",0,-.03,-.09,-.33,-.18,-.69],[\"c\",-.96,-3.21,-1.41,-5.28,-1.59,-7.68],[\"c\",-.12,-1.38,-.15,-3.09,-.06,-3.96],[\"c\",.33,-2.67,1.38,-5.07,3.12,-7.08],[\"c\",.36,-.42,.99,-1.05,1.17,-1.14],[\"z\"],[\"m\",2.01,4.71],[\"c\",-.15,-.3,-.3,-.54,-.3,-.54],[\"c\",-.03,0,-.18,.09,-.3,.21],[\"c\",-2.4,1.74,-3.87,4.2,-4.26,7.11],[\"c\",-.06,.54,-.06,1.41,-.03,1.89],[\"c\",.09,1.29,.48,3.12,1.08,5.22],[\"c\",.15,.42,.24,.78,.24,.81],[\"c\",0,.03,.84,-1.11,1.23,-1.68],[\"c\",1.89,-2.73,2.88,-5.07,3.15,-7.53],[\"c\",.09,-.57,.12,-1.74,.06,-2.37],[\"c\",-.09,-1.23,-.27,-1.92,-.87,-3.12],[\"z\"],[\"m\",-2.94,20.7],[\"c\",-.21,-.72,-.39,-1.32,-.42,-1.32],[\"c\",0,0,-1.2,1.47,-1.86,2.37],[\"c\",-2.79,3.63,-4.02,6.3,-4.35,9.3],[\"c\",-.03,.21,-.03,.69,-.03,1.08],[\"c\",0,.69,0,.75,.06,1.11],[\"c\",.12,.54,.27,.99,.51,1.47],[\"c\",.69,1.38,1.83,2.55,3.42,3.42],[\"c\",.96,.54,2.07,.9,3.21,1.08],[\"c\",.78,.12,2.04,.12,2.94,-.03],[\"c\",.51,-.06,.45,-.03,.42,-.3],[\"c\",-.24,-3.33,-.72,-6.33,-1.62,-10.08],[\"c\",-.09,-.39,-.18,-.75,-.18,-.78],[\"c\",-.03,-.03,-.42,0,-.81,.09],[\"c\",-.9,.18,-1.65,.57,-2.22,1.14],[\"c\",-.72,.72,-1.08,1.65,-1.05,2.64],[\"c\",.06,.96,.48,1.83,1.23,2.58],[\"c\",.36,.36,.72,.63,1.17,.9],[\"c\",.33,.18,.36,.21,.42,.33],[\"c\",.18,.42,-.18,.9,-.6,.87],[\"c\",-.18,-.03,-.84,-.36,-1.26,-.63],[\"c\",-.78,-.51,-1.38,-1.11,-1.86,-1.83],[\"c\",-1.77,-2.7,-.99,-6.42,1.71,-8.19],[\"c\",.3,-.21,.81,-.48,1.17,-.63],[\"c\",.3,-.09,1.02,-.3,1.14,-.3],[\"c\",.06,0,.09,0,.09,-.03],[\"c\",.03,-.03,-.51,-1.92,-1.23,-4.26],[\"z\"],[\"m\",3.78,7.41],[\"c\",-.18,-.03,-.36,-.06,-.39,-.06],[\"c\",-.03,0,0,.21,.18,1.02],[\"c\",.75,3.18,1.26,6.3,1.5,9.09],[\"c\",.06,.72,0,.69,.51,.42],[\"c\",.78,-.36,1.44,-.96,1.98,-1.77],[\"c\",1.08,-1.62,1.2,-3.69,.3,-5.55],[\"c\",-.81,-1.62,-2.31,-2.79,-4.08,-3.15],[\"z\"]],w:19.051,h:57.057},\"clefs.perc\":{d:[[\"M\",5.07,-7.44],[\"l\",.09,-.06],[\"l\",1.53,0],[\"l\",1.53,0],[\"l\",.09,.06],[\"l\",.06,.09],[\"l\",0,7.35],[\"l\",0,7.32],[\"l\",-.06,.09],[\"l\",-.09,.06],[\"l\",-1.53,0],[\"l\",-1.53,0],[\"l\",-.09,-.06],[\"l\",-.06,-.09],[\"l\",0,-7.32],[\"l\",0,-7.35],[\"z\"],[\"m\",6.63,0],[\"l\",.09,-.06],[\"l\",1.53,0],[\"l\",1.53,0],[\"l\",.09,.06],[\"l\",.06,.09],[\"l\",0,7.35],[\"l\",0,7.32],[\"l\",-.06,.09],[\"l\",-.09,.06],[\"l\",-1.53,0],[\"l\",-1.53,0],[\"l\",-.09,-.06],[\"l\",-.06,-.09],[\"l\",0,-7.32],[\"l\",0,-7.35],[\"z\"]],w:9.99,h:14.97},\"timesig.common\":{d:[[\"M\",6.66,-7.83],[\"c\",.72,-.06,1.41,-.03,1.98,.09],[\"c\",1.2,.27,2.34,.96,3.09,1.92],[\"c\",.63,.81,1.08,1.86,1.14,2.73],[\"c\",.06,1.02,-.51,1.92,-1.44,2.22],[\"c\",-.24,.09,-.3,.09,-.63,.09],[\"c\",-.33,0,-.42,0,-.63,-.06],[\"c\",-.66,-.24,-1.14,-.63,-1.41,-1.2],[\"c\",-.15,-.3,-.21,-.51,-.24,-.9],[\"c\",-.06,-1.08,.57,-2.04,1.56,-2.37],[\"c\",.18,-.06,.27,-.06,.63,-.06],[\"l\",.45,0],[\"c\",.06,.03,.09,.03,.09,0],[\"c\",0,0,-.09,-.12,-.24,-.27],[\"c\",-1.02,-1.11,-2.55,-1.68,-4.08,-1.5],[\"c\",-1.29,.15,-2.04,.69,-2.4,1.74],[\"c\",-.36,.93,-.42,1.89,-.42,5.37],[\"c\",0,2.97,.06,3.96,.24,4.77],[\"c\",.24,1.08,.63,1.68,1.41,2.07],[\"c\",.81,.39,2.16,.45,3.18,.09],[\"c\",1.29,-.45,2.37,-1.53,3.03,-2.97],[\"c\",.15,-.33,.33,-.87,.39,-1.17],[\"c\",.09,-.24,.15,-.36,.3,-.39],[\"c\",.21,-.03,.42,.15,.39,.36],[\"c\",-.06,.39,-.42,1.38,-.69,1.89],[\"c\",-.96,1.8,-2.49,2.94,-4.23,3.18],[\"c\",-.99,.12,-2.58,-.06,-3.63,-.45],[\"c\",-.96,-.36,-1.71,-.84,-2.4,-1.5],[\"c\",-1.11,-1.11,-1.8,-2.61,-2.04,-4.56],[\"c\",-.06,-.6,-.06,-2.01,0,-2.61],[\"c\",.24,-1.95,.9,-3.45,2.01,-4.56],[\"c\",.69,-.66,1.44,-1.11,2.37,-1.47],[\"c\",.63,-.24,1.47,-.42,2.22,-.48],[\"z\"]],w:13.038,h:15.689},\"timesig.cut\":{d:[[\"M\",6.24,-10.44],[\"c\",.09,-.06,.09,-.06,.48,-.06],[\"c\",.36,0,.36,0,.45,.06],[\"l\",.06,.09],[\"l\",0,1.23],[\"l\",0,1.26],[\"l\",.27,0],[\"c\",1.26,0,2.49,.45,3.48,1.29],[\"c\",1.05,.87,1.8,2.28,1.89,3.48],[\"c\",.06,1.02,-.51,1.92,-1.44,2.22],[\"c\",-.24,.09,-.3,.09,-.63,.09],[\"c\",-.33,0,-.42,0,-.63,-.06],[\"c\",-.66,-.24,-1.14,-.63,-1.41,-1.2],[\"c\",-.15,-.3,-.21,-.51,-.24,-.9],[\"c\",-.06,-1.08,.57,-2.04,1.56,-2.37],[\"c\",.18,-.06,.27,-.06,.63,-.06],[\"l\",.45,0],[\"c\",.06,.03,.09,.03,.09,0],[\"c\",0,-.03,-.45,-.51,-.66,-.69],[\"c\",-.87,-.69,-1.83,-1.05,-2.94,-1.11],[\"l\",-.42,0],[\"l\",0,7.17],[\"l\",0,7.14],[\"l\",.42,0],[\"c\",.69,-.03,1.23,-.18,1.86,-.51],[\"c\",1.05,-.51,1.89,-1.47,2.46,-2.7],[\"c\",.15,-.33,.33,-.87,.39,-1.17],[\"c\",.09,-.24,.15,-.36,.3,-.39],[\"c\",.21,-.03,.42,.15,.39,.36],[\"c\",-.03,.24,-.21,.78,-.39,1.2],[\"c\",-.96,2.37,-2.94,3.9,-5.13,3.9],[\"l\",-.3,0],[\"l\",0,1.26],[\"l\",0,1.23],[\"l\",-.06,.09],[\"c\",-.09,.06,-.09,.06,-.45,.06],[\"c\",-.39,0,-.39,0,-.48,-.06],[\"l\",-.06,-.09],[\"l\",0,-1.29],[\"l\",0,-1.29],[\"l\",-.21,-.03],[\"c\",-1.23,-.21,-2.31,-.63,-3.21,-1.29],[\"c\",-.15,-.09,-.45,-.36,-.66,-.57],[\"c\",-1.11,-1.11,-1.8,-2.61,-2.04,-4.56],[\"c\",-.06,-.6,-.06,-2.01,0,-2.61],[\"c\",.24,-1.95,.93,-3.45,2.04,-4.59],[\"c\",.42,-.39,.78,-.66,1.26,-.93],[\"c\",.75,-.45,1.65,-.75,2.61,-.9],[\"l\",.21,-.03],[\"l\",0,-1.29],[\"l\",0,-1.29],[\"z\"],[\"m\",-.06,10.44],[\"c\",0,-5.58,0,-6.99,-.03,-6.99],[\"c\",-.15,0,-.63,.27,-.87,.45],[\"c\",-.45,.36,-.75,.93,-.93,1.77],[\"c\",-.18,.81,-.24,1.8,-.24,4.74],[\"c\",0,2.97,.06,3.96,.24,4.77],[\"c\",.24,1.08,.66,1.68,1.41,2.07],[\"c\",.12,.06,.3,.12,.33,.15],[\"l\",.09,0],[\"l\",0,-6.96],[\"z\"]],w:13.038,h:20.97},f:{d:[[\"M\",9.93,-14.28],[\"c\",1.53,-.18,2.88,.45,3.12,1.5],[\"c\",.12,.51,0,1.32,-.27,1.86],[\"c\",-.15,.3,-.42,.57,-.63,.69],[\"c\",-.69,.36,-1.56,.03,-1.83,-.69],[\"c\",-.09,-.24,-.09,-.69,0,-.87],[\"c\",.06,-.12,.21,-.24,.45,-.42],[\"c\",.42,-.24,.57,-.45,.6,-.72],[\"c\",.03,-.33,-.09,-.39,-.63,-.42],[\"c\",-.3,0,-.45,0,-.6,.03],[\"c\",-.81,.21,-1.35,.93,-1.74,2.46],[\"c\",-.06,.27,-.48,2.25,-.48,2.31],[\"c\",0,.03,.39,.03,.9,.03],[\"c\",.72,0,.9,0,.99,.06],[\"c\",.42,.15,.45,.72,.03,.9],[\"c\",-.12,.06,-.24,.06,-1.17,.06],[\"l\",-1.05,0],[\"l\",-.78,2.55],[\"c\",-.45,1.41,-.87,2.79,-.96,3.06],[\"c\",-.87,2.37,-2.37,4.74,-3.78,5.91],[\"c\",-1.05,.9,-2.04,1.23,-3.09,1.08],[\"c\",-1.11,-.18,-1.89,-.78,-2.04,-1.59],[\"c\",-.12,-.66,.15,-1.71,.54,-2.19],[\"c\",.69,-.75,1.86,-.54,2.22,.39],[\"c\",.06,.15,.09,.27,.09,.48],[\"c\",0,.24,-.03,.27,-.12,.42],[\"c\",-.03,.09,-.15,.18,-.27,.27],[\"c\",-.09,.06,-.27,.21,-.36,.27],[\"c\",-.24,.18,-.36,.36,-.39,.6],[\"c\",-.03,.33,.09,.39,.63,.42],[\"c\",.42,0,.63,-.03,.9,-.15],[\"c\",.6,-.3,.96,-.96,1.38,-2.64],[\"c\",.09,-.42,.63,-2.55,1.17,-4.77],[\"l\",1.02,-4.08],[\"c\",0,-.03,-.36,-.03,-.81,-.03],[\"c\",-.72,0,-.81,0,-.93,-.06],[\"c\",-.42,-.18,-.39,-.75,.03,-.9],[\"c\",.09,-.06,.27,-.06,1.05,-.06],[\"l\",.96,0],[\"l\",0,-.09],[\"c\",.06,-.18,.3,-.72,.51,-1.17],[\"c\",1.2,-2.46,3.3,-4.23,5.34,-4.5],[\"z\"]],w:16.155,h:19.445},m:{d:[[\"M\",2.79,-8.91],[\"c\",.09,0,.3,-.03,.45,-.03],[\"c\",.24,.03,.3,.03,.45,.12],[\"c\",.36,.15,.63,.54,.75,1.02],[\"l\",.03,.21],[\"l\",.33,-.3],[\"c\",.69,-.69,1.38,-1.02,2.07,-1.02],[\"c\",.27,0,.33,0,.48,.06],[\"c\",.21,.09,.48,.36,.63,.6],[\"c\",.03,.09,.12,.27,.18,.42],[\"c\",.03,.15,.09,.27,.12,.27],[\"c\",0,0,.09,-.09,.18,-.21],[\"c\",.33,-.39,.87,-.81,1.29,-.99],[\"c\",.78,-.33,1.47,-.21,2.01,.33],[\"c\",.3,.33,.48,.69,.6,1.14],[\"c\",.09,.42,.06,.54,-.54,3.06],[\"c\",-.33,1.29,-.57,2.4,-.57,2.43],[\"c\",0,.12,.09,.21,.21,.21],[\"c\",.24,0,.75,-.3,1.2,-.72],[\"c\",.45,-.39,.6,-.45,.78,-.27],[\"c\",.18,.18,.09,.36,-.45,.87],[\"c\",-1.05,.96,-1.83,1.47,-2.58,1.71],[\"c\",-.93,.33,-1.53,.21,-1.8,-.33],[\"c\",-.06,-.15,-.06,-.21,-.06,-.45],[\"c\",0,-.24,.03,-.48,.6,-2.82],[\"c\",.42,-1.71,.6,-2.64,.63,-2.79],[\"c\",.03,-.57,-.3,-.75,-.84,-.48],[\"c\",-.24,.12,-.54,.39,-.66,.63],[\"c\",-.03,.09,-.42,1.38,-.9,3],[\"c\",-.9,3.15,-.84,3,-1.14,3.15],[\"l\",-.15,.09],[\"l\",-.78,0],[\"c\",-.6,0,-.78,0,-.84,-.06],[\"c\",-.09,-.03,-.18,-.18,-.18,-.27],[\"c\",0,-.03,.36,-1.38,.84,-2.97],[\"c\",.57,-2.04,.81,-2.97,.84,-3.12],[\"c\",.03,-.54,-.3,-.72,-.84,-.45],[\"c\",-.24,.12,-.57,.42,-.66,.63],[\"c\",-.06,.09,-.51,1.44,-1.05,2.97],[\"c\",-.51,1.56,-.99,2.85,-.99,2.91],[\"c\",-.06,.12,-.21,.24,-.36,.3],[\"c\",-.12,.06,-.21,.06,-.9,.06],[\"c\",-.6,0,-.78,0,-.84,-.06],[\"c\",-.09,-.03,-.18,-.18,-.18,-.27],[\"c\",0,-.03,.45,-1.38,.99,-2.97],[\"c\",1.05,-3.18,1.05,-3.18,.93,-3.45],[\"c\",-.12,-.27,-.39,-.3,-.72,-.15],[\"c\",-.54,.27,-1.14,1.17,-1.56,2.4],[\"c\",-.06,.15,-.15,.3,-.18,.36],[\"c\",-.21,.21,-.57,.27,-.72,.09],[\"c\",-.09,-.09,-.06,-.21,.06,-.63],[\"c\",.48,-1.26,1.26,-2.46,2.01,-3.21],[\"c\",.57,-.54,1.2,-.87,1.83,-1.02],[\"z\"]],w:14.687,h:9.126},p:{d:[[\"M\",1.92,-8.7],[\"c\",.27,-.09,.81,-.06,1.11,.03],[\"c\",.54,.18,.93,.51,1.17,.99],[\"c\",.09,.15,.15,.33,.18,.36],[\"l\",0,.12],[\"l\",.3,-.27],[\"c\",.66,-.6,1.35,-1.02,2.13,-1.2],[\"c\",.21,-.06,.33,-.06,.78,-.06],[\"c\",.45,0,.51,0,.84,.09],[\"c\",1.29,.33,2.07,1.32,2.25,2.79],[\"c\",.09,.81,-.09,2.01,-.45,2.79],[\"c\",-.54,1.26,-1.86,2.55,-3.18,3.03],[\"c\",-.45,.18,-.81,.24,-1.29,.24],[\"c\",-.69,-.03,-1.35,-.18,-1.86,-.45],[\"c\",-.3,-.15,-.51,-.18,-.69,-.09],[\"c\",-.09,.03,-.18,.09,-.18,.12],[\"c\",-.09,.12,-1.05,2.94,-1.05,3.06],[\"c\",0,.24,.18,.48,.51,.63],[\"c\",.18,.06,.54,.15,.75,.15],[\"c\",.21,0,.36,.06,.42,.18],[\"c\",.12,.18,.06,.42,-.12,.54],[\"c\",-.09,.03,-.15,.03,-.78,0],[\"c\",-1.98,-.15,-3.81,-.15,-5.79,0],[\"c\",-.63,.03,-.69,.03,-.78,0],[\"c\",-.24,-.15,-.24,-.57,.03,-.66],[\"c\",.06,-.03,.48,-.09,.99,-.12],[\"c\",.87,-.06,1.11,-.09,1.35,-.21],[\"c\",.18,-.06,.33,-.18,.39,-.3],[\"c\",.06,-.12,3.24,-9.42,3.27,-9.6],[\"c\",.06,-.33,.03,-.57,-.15,-.69],[\"c\",-.09,-.06,-.12,-.06,-.3,-.06],[\"c\",-.69,.06,-1.53,1.02,-2.28,2.61],[\"c\",-.09,.21,-.21,.45,-.27,.51],[\"c\",-.09,.12,-.33,.24,-.48,.24],[\"c\",-.18,0,-.36,-.15,-.36,-.3],[\"c\",0,-.24,.78,-1.83,1.26,-2.55],[\"c\",.72,-1.11,1.47,-1.74,2.28,-1.92],[\"z\"],[\"m\",5.37,1.47],[\"c\",-.27,-.12,-.75,-.03,-1.14,.21],[\"c\",-.75,.48,-1.47,1.68,-1.89,3.15],[\"c\",-.45,1.47,-.42,2.34,0,2.7],[\"c\",.45,.39,1.26,.21,1.83,-.36],[\"c\",.51,-.51,.99,-1.68,1.38,-3.27],[\"c\",.3,-1.17,.33,-1.74,.15,-2.13],[\"c\",-.09,-.15,-.15,-.21,-.33,-.3],[\"z\"]],w:14.689,h:13.127},r:{d:[[\"M\",6.33,-9.12],[\"c\",.27,-.03,.93,0,1.2,.06],[\"c\",.84,.21,1.23,.81,1.02,1.53],[\"c\",-.24,.75,-.9,1.17,-1.56,.96],[\"c\",-.33,-.09,-.51,-.3,-.66,-.75],[\"c\",-.03,-.12,-.09,-.24,-.12,-.3],[\"c\",-.09,-.15,-.3,-.24,-.48,-.24],[\"c\",-.57,0,-1.38,.54,-1.65,1.08],[\"c\",-.06,.15,-.33,1.17,-.9,3.27],[\"c\",-.57,2.31,-.81,3.12,-.87,3.21],[\"c\",-.03,.06,-.12,.15,-.18,.21],[\"l\",-.12,.06],[\"l\",-.81,.03],[\"c\",-.69,0,-.81,0,-.9,-.03],[\"c\",-.09,-.06,-.18,-.21,-.18,-.3],[\"c\",0,-.06,.39,-1.62,.9,-3.51],[\"c\",.84,-3.24,.87,-3.45,.87,-3.72],[\"c\",0,-.21,0,-.27,-.03,-.36],[\"c\",-.12,-.15,-.21,-.24,-.42,-.24],[\"c\",-.24,0,-.45,.15,-.78,.42],[\"c\",-.33,.36,-.45,.54,-.72,1.14],[\"c\",-.03,.12,-.21,.24,-.36,.27],[\"c\",-.12,0,-.15,0,-.24,-.06],[\"c\",-.18,-.12,-.18,-.21,-.06,-.54],[\"c\",.21,-.57,.42,-.93,.78,-1.32],[\"c\",.54,-.51,1.2,-.81,1.95,-.87],[\"c\",.81,-.03,1.53,.3,1.92,.87],[\"l\",.12,.18],[\"l\",.09,-.09],[\"c\",.57,-.45,1.41,-.84,2.19,-.96],[\"z\"]],w:9.41,h:9.132},s:{d:[[\"M\",4.47,-8.73],[\"c\",.09,0,.36,-.03,.57,-.03],[\"c\",.75,.03,1.29,.24,1.71,.63],[\"c\",.51,.54,.66,1.26,.36,1.83],[\"c\",-.24,.42,-.63,.57,-1.11,.42],[\"c\",-.33,-.09,-.6,-.36,-.6,-.57],[\"c\",0,-.03,.06,-.21,.15,-.39],[\"c\",.12,-.21,.15,-.33,.18,-.48],[\"c\",0,-.24,-.06,-.48,-.15,-.6],[\"c\",-.15,-.21,-.42,-.24,-.75,-.15],[\"c\",-.27,.06,-.48,.18,-.69,.36],[\"c\",-.39,.39,-.51,.96,-.33,1.38],[\"c\",.09,.21,.42,.51,.78,.72],[\"c\",1.11,.69,1.59,1.11,1.89,1.68],[\"c\",.21,.39,.24,.78,.15,1.29],[\"c\",-.18,1.2,-1.17,2.16,-2.52,2.52],[\"c\",-1.02,.24,-1.95,.12,-2.7,-.42],[\"c\",-.72,-.51,-.99,-1.47,-.6,-2.19],[\"c\",.24,-.48,.72,-.63,1.17,-.42],[\"c\",.33,.18,.54,.45,.57,.81],[\"c\",0,.21,-.03,.3,-.33,.51],[\"c\",-.33,.24,-.39,.42,-.27,.69],[\"c\",.06,.15,.21,.27,.45,.33],[\"c\",.3,.09,.87,.09,1.2,0],[\"c\",.75,-.21,1.23,-.72,1.29,-1.35],[\"c\",.03,-.42,-.15,-.81,-.54,-1.2],[\"c\",-.24,-.24,-.48,-.42,-1.41,-1.02],[\"c\",-.69,-.42,-1.05,-.93,-1.05,-1.47],[\"c\",0,-.39,.12,-.87,.3,-1.23],[\"c\",.27,-.57,.78,-1.05,1.38,-1.35],[\"c\",.24,-.12,.63,-.27,.9,-.3],[\"z\"]],w:6.632,h:8.758},z:{d:[[\"M\",2.64,-7.95],[\"c\",.36,-.09,.81,-.03,1.71,.27],[\"c\",.78,.21,.96,.27,1.74,.3],[\"c\",.87,.06,1.02,.03,1.38,-.21],[\"c\",.21,-.15,.33,-.15,.48,-.06],[\"c\",.15,.09,.21,.3,.15,.45],[\"c\",-.03,.06,-1.26,1.26,-2.76,2.67],[\"l\",-2.73,2.55],[\"l\",.54,.03],[\"c\",.54,.03,.72,.03,2.01,.15],[\"c\",.36,.03,.9,.06,1.2,.09],[\"c\",.66,0,.81,-.03,1.02,-.24],[\"c\",.3,-.3,.39,-.72,.27,-1.23],[\"c\",-.06,-.27,-.06,-.27,-.03,-.39],[\"c\",.15,-.3,.54,-.27,.69,.03],[\"c\",.15,.33,.27,1.02,.27,1.5],[\"c\",0,1.47,-1.11,2.7,-2.52,2.79],[\"c\",-.57,.03,-1.02,-.09,-2.01,-.51],[\"c\",-1.02,-.42,-1.23,-.48,-2.13,-.54],[\"c\",-.81,-.06,-.96,-.03,-1.26,.18],[\"c\",-.12,.06,-.24,.12,-.27,.12],[\"c\",-.27,0,-.45,-.3,-.36,-.51],[\"c\",.03,-.06,1.32,-1.32,2.91,-2.79],[\"l\",2.88,-2.73],[\"c\",-.03,0,-.21,.03,-.42,.06],[\"c\",-.21,.03,-.78,.09,-1.23,.12],[\"c\",-1.11,.12,-1.23,.15,-1.95,.27],[\"c\",-.72,.15,-1.17,.18,-1.29,.09],[\"c\",-.27,-.18,-.21,-.75,.12,-1.26],[\"c\",.39,-.6,.93,-1.02,1.59,-1.2],[\"z\"]],w:8.573,h:8.743},\"+\":{d:[[\"M\",3.48,-9.3],[\"c\",.18,-.09,.36,-.09,.54,0],[\"c\",.18,.09,.24,.15,.33,.3],[\"l\",.06,.15],[\"l\",0,1.29],[\"l\",0,1.29],[\"l\",1.29,0],[\"c\",1.23,0,1.29,0,1.41,.06],[\"c\",.06,.03,.15,.09,.18,.12],[\"c\",.12,.09,.21,.33,.21,.48],[\"c\",0,.15,-.09,.39,-.21,.48],[\"c\",-.03,.03,-.12,.09,-.18,.12],[\"c\",-.12,.06,-.18,.06,-1.41,.06],[\"l\",-1.29,0],[\"l\",0,1.29],[\"c\",0,1.23,0,1.29,-.06,1.41],[\"c\",-.09,.18,-.15,.24,-.3,.33],[\"c\",-.21,.09,-.39,.09,-.57,0],[\"c\",-.18,-.09,-.24,-.15,-.33,-.33],[\"c\",-.06,-.12,-.06,-.18,-.06,-1.41],[\"l\",0,-1.29],[\"l\",-1.29,0],[\"c\",-1.23,0,-1.29,0,-1.41,-.06],[\"c\",-.18,-.09,-.24,-.15,-.33,-.33],[\"c\",-.09,-.18,-.09,-.36,0,-.54],[\"c\",.09,-.18,.15,-.24,.33,-.33],[\"l\",.15,-.06],[\"l\",1.26,0],[\"l\",1.29,0],[\"l\",0,-1.29],[\"c\",0,-1.23,0,-1.29,.06,-1.41],[\"c\",.09,-.18,.15,-.24,.33,-.33],[\"z\"]],w:7.507,h:7.515},\",\":{d:[[\"M\",1.32,-3.36],[\"c\",.57,-.15,1.17,.03,1.59,.45],[\"c\",.45,.45,.6,.96,.51,1.89],[\"c\",-.09,1.23,-.42,2.46,-.99,3.93],[\"c\",-.3,.72,-.72,1.62,-.78,1.68],[\"c\",-.18,.21,-.51,.18,-.66,-.06],[\"c\",-.03,-.06,-.06,-.15,-.06,-.18],[\"c\",0,-.06,.12,-.33,.24,-.63],[\"c\",.84,-1.8,1.02,-2.61,.69,-3.24],[\"c\",-.12,-.24,-.27,-.36,-.75,-.6],[\"c\",-.36,-.15,-.42,-.21,-.6,-.39],[\"c\",-.69,-.69,-.69,-1.71,0,-2.4],[\"c\",.21,-.21,.51,-.39,.81,-.45],[\"z\"]],w:3.452,h:8.143},\"-\":{d:[[\"M\",.18,-5.34],[\"c\",.09,-.06,.15,-.06,2.31,-.06],[\"c\",2.46,0,2.37,0,2.46,.21],[\"c\",.12,.21,.03,.42,-.15,.54],[\"c\",-.09,.06,-.15,.06,-2.28,.06],[\"c\",-2.16,0,-2.22,0,-2.31,-.06],[\"c\",-.27,-.15,-.27,-.54,-.03,-.69],[\"z\"]],w:5.001,h:.81},\".\":{d:[[\"M\",1.32,-3.36],[\"c\",1.05,-.27,2.1,.57,2.1,1.65],[\"c\",0,1.08,-1.05,1.92,-2.1,1.65],[\"c\",-.9,-.21,-1.5,-1.14,-1.26,-2.04],[\"c\",.12,-.63,.63,-1.11,1.26,-1.26],[\"z\"]],w:3.413,h:3.402},\"scripts.wedge\":{d:[[\"M\",-3.66,-7.44],[\"c\",.06,-.09,0,-.09,.81,.03],[\"c\",1.86,.3,3.84,.3,5.73,0],[\"c\",.78,-.12,.72,-.12,.78,-.03],[\"c\",.15,.15,.12,.24,-.24,.6],[\"c\",-.93,.93,-1.98,2.76,-2.67,4.62],[\"c\",-.3,.78,-.51,1.71,-.51,2.13],[\"c\",0,.15,0,.18,-.06,.27],[\"c\",-.12,.09,-.24,.09,-.36,0],[\"c\",-.06,-.09,-.06,-.12,-.06,-.27],[\"c\",0,-.42,-.21,-1.35,-.51,-2.13],[\"c\",-.69,-1.86,-1.74,-3.69,-2.67,-4.62],[\"c\",-.36,-.36,-.39,-.45,-.24,-.6],[\"z\"]],w:7.49,h:7.752},\"scripts.thumb\":{d:[[\"M\",-.54,-3.69],[\"c\",.15,-.03,.36,-.06,.51,-.06],[\"c\",1.44,0,2.58,1.11,2.94,2.85],[\"c\",.09,.48,.09,1.32,0,1.8],[\"c\",-.27,1.41,-1.08,2.43,-2.16,2.73],[\"l\",-.18,.06],[\"l\",0,.12],[\"c\",.03,.06,.06,.45,.09,.87],[\"c\",.03,.57,.03,.78,0,.84],[\"c\",-.09,.27,-.39,.48,-.66,.48],[\"c\",-.27,0,-.57,-.21,-.66,-.48],[\"c\",-.03,-.06,-.03,-.27,0,-.84],[\"c\",.03,-.42,.06,-.81,.09,-.87],[\"l\",0,-.12],[\"l\",-.18,-.06],[\"c\",-1.08,-.3,-1.89,-1.32,-2.16,-2.73],[\"c\",-.09,-.48,-.09,-1.32,0,-1.8],[\"c\",.15,-.84,.51,-1.53,1.02,-2.04],[\"c\",.39,-.39,.84,-.63,1.35,-.75],[\"z\"],[\"m\",1.05,.9],[\"c\",-.15,-.09,-.21,-.09,-.45,-.12],[\"c\",-.15,0,-.3,.03,-.39,.03],[\"c\",-.57,.18,-.9,.72,-1.08,1.74],[\"c\",-.06,.48,-.06,1.8,0,2.28],[\"c\",.15,.9,.42,1.44,.9,1.65],[\"c\",.18,.09,.21,.09,.51,.09],[\"c\",.3,0,.33,0,.51,-.09],[\"c\",.48,-.21,.75,-.75,.9,-1.65],[\"c\",.03,-.27,.03,-.54,.03,-1.14],[\"c\",0,-.6,0,-.87,-.03,-1.14],[\"c\",-.15,-.9,-.45,-1.44,-.9,-1.65],[\"z\"]],w:5.955,h:9.75},\"scripts.open\":{d:[[\"M\",-.54,-3.69],[\"c\",.15,-.03,.36,-.06,.51,-.06],[\"c\",1.44,0,2.58,1.11,2.94,2.85],[\"c\",.09,.48,.09,1.32,0,1.8],[\"c\",-.33,1.74,-1.47,2.85,-2.91,2.85],[\"c\",-1.44,0,-2.58,-1.11,-2.91,-2.85],[\"c\",-.09,-.48,-.09,-1.32,0,-1.8],[\"c\",.15,-.84,.51,-1.53,1.02,-2.04],[\"c\",.39,-.39,.84,-.63,1.35,-.75],[\"z\"],[\"m\",1.11,.9],[\"c\",-.21,-.09,-.27,-.09,-.51,-.12],[\"c\",-.3,0,-.42,.03,-.66,.15],[\"c\",-.24,.12,-.51,.39,-.66,.63],[\"c\",-.54,.93,-.63,2.64,-.21,3.81],[\"c\",.21,.54,.51,.9,.93,1.11],[\"c\",.21,.09,.24,.09,.54,.09],[\"c\",.3,0,.33,0,.54,-.09],[\"c\",.42,-.21,.72,-.57,.93,-1.11],[\"c\",.36,-.99,.36,-2.37,0,-3.36],[\"c\",-.21,-.54,-.51,-.9,-.9,-1.11],[\"z\"]],w:5.955,h:7.5},\"scripts.longphrase\":{d:[[\"M\",1.47,-15.09],[\"c\",.36,-.09,.66,-.18,.69,-.18],[\"c\",.06,0,.06,.54,.06,11.25],[\"l\",0,11.25],[\"l\",-.63,.15],[\"c\",-.66,.18,-1.44,.39,-1.5,.39],[\"c\",-.03,0,-.03,-3.39,-.03,-11.25],[\"l\",0,-11.25],[\"l\",.36,-.09],[\"c\",.21,-.06,.66,-.18,1.05,-.27],[\"z\"]],w:2.16,h:23.04},\"scripts.mediumphrase\":{d:[[\"M\",1.47,-7.59],[\"c\",.36,-.09,.66,-.18,.69,-.18],[\"c\",.06,0,.06,.39,.06,7.5],[\"l\",0,7.5],[\"l\",-.63,.15],[\"c\",-.66,.18,-1.44,.39,-1.5,.39],[\"c\",-.03,0,-.03,-2.28,-.03,-7.5],[\"l\",0,-7.5],[\"l\",.36,-.09],[\"c\",.21,-.06,.66,-.18,1.05,-.27],[\"z\"]],w:2.16,h:15.54},\"scripts.shortphrase\":{d:[[\"M\",1.47,-7.59],[\"c\",.36,-.09,.66,-.18,.69,-.18],[\"c\",.06,0,.06,.21,.06,3.75],[\"l\",0,3.75],[\"l\",-.42,.09],[\"c\",-.57,.18,-1.65,.45,-1.71,.45],[\"c\",-.03,0,-.03,-.72,-.03,-3.75],[\"l\",0,-3.75],[\"l\",.36,-.09],[\"c\",.21,-.06,.66,-.18,1.05,-.27],[\"z\"]],w:2.16,h:8.04},\"scripts.snap\":{d:[[\"M\",4.5,-3.39],[\"c\",.36,-.03,.96,-.03,1.35,0],[\"c\",1.56,.15,3.15,.9,4.2,2.01],[\"c\",.24,.27,.33,.42,.33,.6],[\"c\",0,.27,.03,.24,-2.46,2.22],[\"c\",-1.29,1.02,-2.4,1.86,-2.49,1.92],[\"c\",-.18,.09,-.3,.09,-.48,0],[\"c\",-.09,-.06,-1.2,-.9,-2.49,-1.92],[\"c\",-2.49,-1.98,-2.46,-1.95,-2.46,-2.22],[\"c\",0,-.18,.09,-.33,.33,-.6],[\"c\",1.05,-1.08,2.64,-1.86,4.17,-2.01],[\"z\"],[\"m\",1.29,1.17],[\"c\",-1.47,-.15,-2.97,.3,-4.14,1.2],[\"l\",-.18,.15],[\"l\",.06,.09],[\"c\",.15,.12,3.63,2.85,3.66,2.85],[\"c\",.03,0,3.51,-2.73,3.66,-2.85],[\"l\",.06,-.09],[\"l\",-.18,-.15],[\"c\",-.84,-.66,-1.89,-1.08,-2.94,-1.2],[\"z\"]],w:10.38,h:6.84}};glyphs[\"noteheads.slash.whole\"]={d:[[\"M\",5,-5],[\"l\",1,1],[\"l\",-5,5],[\"l\",-1,-1],[\"z\"],[\"m\",4,6],[\"l\",-5,-5],[\"l\",2,-2],[\"l\",5,5],[\"z\"],[\"m\",0,-2],[\"l\",1,1],[\"l\",-5,5],[\"l\",-1,-1],[\"z\"],[\"m\",-4,6],[\"l\",-5,-5],[\"l\",2,-2],[\"l\",5,5],[\"z\"]],w:10.81,h:15.63},glyphs[\"noteheads.slash.quarter\"]={d:[[\"M\",9,-6],[\"l\",0,4],[\"l\",-9,9],[\"l\",0,-4],[\"z\"]],w:9,h:9},glyphs[\"noteheads.harmonic.quarter\"]={d:[[\"M\",3.63,-4.02],[\"c\",.09,-.06,.18,-.09,.24,-.03],[\"c\",.03,.03,.87,.93,1.83,2.01],[\"c\",1.5,1.65,1.8,1.98,1.8,2.04],[\"c\",0,.06,-.3,.39,-1.8,2.04],[\"c\",-.96,1.08,-1.8,1.98,-1.83,2.01],[\"c\",-.06,.06,-.15,.03,-.24,-.03],[\"c\",-.12,-.09,-3.54,-3.84,-3.6,-3.93],[\"c\",-.03,-.03,-.03,-.09,-.03,-.15],[\"c\",.03,-.06,3.45,-3.84,3.63,-3.96],[\"z\"]],w:7.5,h:8.165},this.printSymbol=function(x,y,symb,paper,klass){if(!glyphs[symb])return null;var pathArray=this.pathClone(glyphs[symb].d);return pathArray[0][1]+=x,pathArray[0][2]+=y,paper.path().attr({path:pathArray,stroke:\"none\",fill:\"#000000\",class:klass})},this.getPathForSymbol=function(x,y,symb,scalex,scaley){if(scalex=scalex||1,scaley=scaley||1,!glyphs[symb])return null;var pathArray=this.pathClone(glyphs[symb].d);return 1===scalex&&1===scaley||this.pathScale(pathArray,scalex,scaley),pathArray[0][1]+=x,pathArray[0][2]+=y,pathArray},this.getSymbolWidth=function(symbol){return glyphs[symbol]?glyphs[symbol].w:0},this.getSymbolHeight=function(symbol){return glyphs[symbol]?glyphs[symbol].h:0},this.symbolHeightInPitches=function(symbol){return this.getSymbolHeight(symbol)/ABCJS.write.spacing.STEP},this.getSymbolAlign=function(symbol){return\"scripts\"===symbol.substring(0,7)&&\"scripts.roll\"!==symbol?\"center\":\"left\"},this.pathClone=function(pathArray){for(var res=[],i=0,ii=pathArray.length;i<ii;i++){res[i]=[];for(var j=0,jj=pathArray[i].length;j<jj;j++)res[i][j]=pathArray[i][j]}return res},this.pathScale=function(pathArray,kx,ky){for(var i=0,ii=pathArray.length;i<ii;i++){var j,jj,p=pathArray[i];for(j=1,jj=p.length;j<jj;j++)p[j]*=j%2?kx:ky}},this.getYCorr=function(symbol){switch(symbol){case\"0\":case\"1\":case\"2\":case\"3\":case\"4\":case\"5\":case\"6\":case\"7\":case\"8\":case\"9\":case\"+\":return-2;case\"timesig.common\":case\"timesig.cut\":return 0;case\"flags.d32nd\":return-1;case\"flags.d64th\":return-2;case\"flags.u32nd\":return 1;case\"flags.u64th\":return 3;case\"rests.whole\":return 1;case\"rests.half\":return-1;case\"rests.8th\":return-1;case\"rests.quarter\":return-1;case\"rests.16th\":return-1;case\"rests.32nd\":return-1;case\"rests.64th\":return-1;case\"f\":case\"m\":case\"p\":case\"s\":case\"z\":return-4;case\"scripts.trill\":case\"scripts.upbow\":case\"scripts.downbow\":return-2;case\"scripts.ufermata\":case\"scripts.wedge\":case\"scripts.roll\":case\"scripts.shortphrase\":case\"scripts.longphrase\":return-1;case\"scripts.dfermata\":return 1;default:return 0}}},ABCJS.write.glyphs=new ABCJS.write.Glyphs,window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.RelativeElement=function(c,dx,w,pitch,opt){opt=opt||{},this.x=0,this.c=c,this.dx=dx,this.w=w,this.pitch=pitch,this.scalex=opt.scalex||1,this.scaley=opt.scaley||1,this.type=opt.type||\"symbol\",this.pitch2=opt.pitch2,this.linewidth=opt.linewidth,this.klass=opt.klass,this.top=pitch,void 0!==this.pitch2&&this.pitch2>this.top&&(this.top=this.pitch2),this.bottom=pitch,void 0!==this.pitch2&&this.pitch2<this.bottom&&(this.bottom=this.pitch2),\nopt.thickness&&(this.top+=opt.thickness/2,this.bottom-=opt.thickness/2),opt.stemHeight&&(opt.stemHeight>0?this.top+=opt.stemHeight:this.bottom+=opt.stemHeight);var height=opt.height?opt.height:4;switch(this.centerVertically=!1,this.type){case\"debug\":this.chordHeightAbove=height;break;case\"lyric\":opt.position&&\"below\"===opt.position?this.lyricHeightBelow=height:this.lyricHeightAbove=height;break;case\"chord\":opt.position&&\"below\"===opt.position?this.chordHeightBelow=height:this.chordHeightAbove=height;break;case\"text\":void 0===this.pitch?opt.position&&\"below\"===opt.position?this.chordHeightBelow=height:this.chordHeightAbove=height:this.centerVertically=!0;break;case\"part\":this.partHeightAbove=height}},ABCJS.write.RelativeElement.prototype.setX=function(x){this.x=x+this.dx},ABCJS.write.RelativeElement.prototype.draw=function(renderer,bartop){void 0===this.pitch&&window.console.error(this.type+\" Relative Element y-coordinate not set.\");var y=renderer.calcY(this.pitch);switch(this.type){case\"symbol\":if(null===this.c)return null;var klass=\"symbol\";this.klass&&(klass+=\" \"+this.klass),this.graphelem=renderer.printSymbol(this.x,this.pitch,this.c,this.scalex,this.scaley,renderer.addClasses(klass));break;case\"debug\":this.graphelem=renderer.renderText(this.x,renderer.calcY(15),\"\"+this.c,\"debugfont\",\"debug-msg\",\"start\");break;case\"barNumber\":this.graphelem=renderer.renderText(this.x,y,\"\"+this.c,\"measurefont\",\"bar-number\",\"middle\");break;case\"lyric\":this.graphelem=renderer.renderText(this.x,y,this.c,\"vocalfont\",\"abc-lyric\",\"middle\");break;case\"chord\":this.graphelem=renderer.renderText(this.x,y,this.c,\"gchordfont\",\"chord\",\"middle\");break;case\"decoration\":this.graphelem=renderer.renderText(this.x,y,this.c,\"annotationfont\",\"annotation\",\"middle\",!0);break;case\"text\":this.graphelem=renderer.renderText(this.x,y,this.c,\"annotationfont\",\"annotation\",\"start\",this.centerVertically);break;case\"part\":this.graphelem=renderer.renderText(this.x,y,this.c,\"partsfont\",\"part\",\"start\");break;case\"bar\":this.graphelem=renderer.printStem(this.x,this.linewidth,y,bartop?bartop:renderer.calcY(this.pitch2));break;case\"stem\":this.graphelem=renderer.printStem(this.x,this.linewidth,y,renderer.calcY(this.pitch2));break;case\"ledger\":this.graphelem=renderer.printStaveLine(this.x,this.x+this.w,this.pitch)}return 1!==this.scalex&&this.graphelem&&this.graphelem.scale(this.scalex,this.scaley,this.x,y),this.graphelem},window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.Renderer=function(paper,doRegression){this.paper=paper,this.controller=null,this.space=3*ABCJS.write.spacing.SPACE,this.padding={},this.doRegression=doRegression,this.doRegression&&(this.regressionLines=[]),this.reset()},ABCJS.write.Renderer.prototype.reset=function(){this.paper.clear(),this.y=0,this.abctune=null,this.lastM=null,this.ingroup=!1,this.path=null,this.isPrint=!1,this.initVerticalSpace(),this.doRegression&&(this.regressionLines=[])},ABCJS.write.Renderer.prototype.setPrintMode=function(isPrint){this.isPrint=isPrint},ABCJS.write.Renderer.prototype.setPaperSize=function(maxwidth,scale){var w=(maxwidth+this.padding.right)*scale,h=(this.y+this.padding.bottom)*scale;this.isPrint&&(h=Math.max(h,1056)),this.doRegression&&this.regressionLines.push(\"PAPER SIZE: (\"+w+\",\"+h+\")\"),this.paper.setSize(w/scale,h/scale);var isIE=!1;isIE?(this.paper.canvas.parentNode.style.width=w+\"px\",this.paper.canvas.parentNode.style.height=\"\"+h+\"px\"):this.paper.canvas.parentNode.setAttribute(\"style\",\"width:\"+w+\"px\"),1!==scale?(this.paper.canvas.style.transform=\"scale(\"+scale+\",\"+scale+\")\",this.paper.canvas.style[\"-ms-transform\"]=\"scale(\"+scale+\",\"+scale+\")\",this.paper.canvas.style[\"-webkit-transform\"]=\"scale(\"+scale+\",\"+scale+\")\",this.paper.canvas.style[\"transform-origin\"]=\"0 0\",this.paper.canvas.style[\"-ms-transform-origin-x\"]=\"0\",this.paper.canvas.style[\"-ms-transform-origin-y\"]=\"0\",this.paper.canvas.style[\"-webkit-transform-origin-x\"]=\"0\",this.paper.canvas.style[\"-webkit-transform-origin-y\"]=\"0\"):(this.paper.canvas.style.transform=\"\",this.paper.canvas.style[\"-ms-transform\"]=\"\",this.paper.canvas.style[\"-webkit-transform\"]=\"\"),this.paper.canvas.parentNode.style.overflow=\"hidden\",this.paper.canvas.parentNode.style.height=\"\"+h+\"px\"},ABCJS.write.Renderer.prototype.setPaddingOverride=function(params){this.paddingOverride={top:params.paddingtop,bottom:params.paddingbottom,right:params.paddingright,left:params.paddingleft}},ABCJS.write.Renderer.prototype.setPadding=function(abctune){function setPaddingVariable(self,paddingKey,formattingKey,printDefault,screenDefault){void 0!==abctune.formatting[formattingKey]?self.padding[paddingKey]=abctune.formatting[formattingKey]:void 0!==self.paddingOverride[paddingKey]?self.padding[paddingKey]=self.paddingOverride[paddingKey]:self.isPrint?self.padding[paddingKey]=printDefault:self.padding[paddingKey]=screenDefault}setPaddingVariable(this,\"top\",\"topmargin\",38,15),setPaddingVariable(this,\"bottom\",\"botmargin\",38,15),setPaddingVariable(this,\"left\",\"leftmargin\",68,15),setPaddingVariable(this,\"right\",\"rightmargin\",68,15)},ABCJS.write.Renderer.prototype.adjustNonScaledItems=function(scale){this.padding.top/=scale,this.padding.bottom/=scale,this.padding.left/=scale,this.padding.right/=scale,this.abctune.formatting.headerfont.size/=scale,this.abctune.formatting.footerfont.size/=scale},ABCJS.write.Renderer.prototype.initVerticalSpace=function(){this.spacing={composer:7.56,graceBefore:8.67,graceInside:10.67,graceAfter:16,info:0,lineSkipFactor:1.1,music:7.56,paragraphSkipFactor:.4,parts:11.33,slurHeight:1,staffSeparation:61.33,stemHeight:36.67,subtitle:3.78,systemStaffSeparation:48,text:18.9,title:7.56,top:30.24,vocal:30.67,words:0}},ABCJS.write.Renderer.prototype.setVerticalSpace=function(formatting){void 0!==formatting.staffsep&&(this.spacing.staffSeparation=4*formatting.staffsep/3),void 0!==formatting.composerspace&&(this.spacing.composer=4*formatting.composerspace/3),void 0!==formatting.partsspace&&(this.spacing.parts=4*formatting.partsspace/3),void 0!==formatting.textspace&&(this.spacing.text=4*formatting.textspace/3),void 0!==formatting.musicspace&&(this.spacing.music=4*formatting.musicspace/3),void 0!==formatting.titlespace&&(this.spacing.title=4*formatting.titlespace/3),void 0!==formatting.sysstaffsep&&(this.spacing.systemStaffSeparation=4*formatting.sysstaffsep/3),void 0!==formatting.subtitlespace&&(this.spacing.subtitle=4*formatting.subtitlespace/3),void 0!==formatting.topspace&&(this.spacing.top=4*formatting.topspace/3),void 0!==formatting.vocalspace&&(this.spacing.vocal=4*formatting.vocalspace/3),void 0!==formatting.wordsspace&&(this.spacing.words=4*formatting.wordsspace/3)},ABCJS.write.Renderer.prototype.topMargin=function(abctune){this.moveY(this.padding.top)},ABCJS.write.Renderer.prototype.addMusicPadding=function(){this.moveY(this.spacing.music)},ABCJS.write.Renderer.prototype.addStaffPadding=function(lastStaffGroup,thisStaffGroup){var lastStaff=lastStaffGroup.staffs[lastStaffGroup.staffs.length-1],lastBottomLine=-(lastStaff.bottom-2),nextTopLine=thisStaffGroup.staffs[0].top-10,naturalSeparation=nextTopLine+lastBottomLine,separationInPixels=naturalSeparation*ABCJS.write.spacing.STEP;separationInPixels<this.spacing.staffSeparation&&this.moveY(this.spacing.staffSeparation-separationInPixels)},ABCJS.write.Renderer.prototype.engraveTopText=function(width,abctune){if(abctune.metaText.header&&this.isPrint){var headerTextHeight=this.getTextSize(\"XXXX\",\"headerfont\",\"header meta-top\").height;this.y-=headerTextHeight,this.outputTextIf(this.padding.left,abctune.metaText.header.left,\"headerfont\",\"header meta-top\",0,null,\"start\"),this.outputTextIf(this.padding.left+width/2,abctune.metaText.header.center,\"headerfont\",\"header meta-top\",0,null,\"middle\"),this.outputTextIf(this.padding.left+width,abctune.metaText.header.right,\"headerfont\",\"header meta-top\",0,null,\"end\"),this.y+=headerTextHeight}if(this.isPrint&&this.moveY(this.spacing.top),this.outputTextIf(this.padding.left+width/2,abctune.metaText.title,\"titlefont\",\"title meta-top\",this.spacing.title,0,\"middle\"),abctune.lines[0]&&this.outputTextIf(this.padding.left+width/2,abctune.lines[0].subtitle,\"subtitlefont\",\"text meta-top\",this.spacing.subtitle,0,\"middle\"),abctune.metaText.rhythm||abctune.metaText.origin||abctune.metaText.composer){this.moveY(this.spacing.composer);var rSpace=this.outputTextIf(this.padding.left,abctune.metaText.rhythm,\"infofont\",\"meta-top\",0,null,\"start\"),composerLine=\"\";if(abctune.metaText.composer&&(composerLine+=abctune.metaText.composer),abctune.metaText.origin&&(composerLine+=\" (\"+abctune.metaText.origin+\")\"),composerLine.length>0){var space=this.outputTextIf(this.padding.left+width,composerLine,\"composerfont\",\"meta-top\",0,null,\"end\");this.moveY(space[1])}else this.moveY(rSpace[1]);this.moveY(-6)}this.outputTextIf(this.padding.left+width,abctune.metaText.author,\"composerfont\",\"meta-top\",0,0,\"end\"),this.outputTextIf(this.padding.left,abctune.metaText.partOrder,\"partsfont\",\"meta-bottom\",0,0,\"start\")},ABCJS.write.Renderer.prototype.engraveExtraText=function(width,abctune){this.lineNumber=null,this.measureNumber=null,this.voiceNumber=null;var extraText;if(abctune.metaText.unalignedWords){extraText=\"\";for(var j=0;j<abctune.metaText.unalignedWords.length;j++)if(\"string\"==typeof abctune.metaText.unalignedWords[j])extraText+=abctune.metaText.unalignedWords[j]+\"\\n\";else{for(var k=0;k<abctune.metaText.unalignedWords[j].length;k++)extraText+=\" FONT \"+abctune.metaText.unalignedWords[j][k].text;extraText+=\"\\n\"}this.outputTextIf(this.padding.left+ABCJS.write.spacing.INDENT,extraText,\"wordsfont\",\"meta-bottom\",this.spacing.words,2,\"start\")}extraText=\"\",abctune.metaText.book&&(extraText+=\"Book: \"+abctune.metaText.book+\"\\n\"),abctune.metaText.source&&(extraText+=\"Source: \"+abctune.metaText.source+\"\\n\"),abctune.metaText.discography&&(extraText+=\"Discography: \"+abctune.metaText.discography+\"\\n\"),abctune.metaText.notes&&(extraText+=\"Notes: \"+abctune.metaText.notes+\"\\n\"),abctune.metaText.transcription&&(extraText+=\"Transcription: \"+abctune.metaText.transcription+\"\\n\"),abctune.metaText.history&&(extraText+=\"History: \"+abctune.metaText.history+\"\\n\"),abctune.metaText[\"abc-copyright\"]&&(extraText+=\"Copyright: \"+abctune.metaText[\"abc-copyright\"]+\"\\n\"),abctune.metaText[\"abc-creator\"]&&(extraText+=\"Creator: \"+abctune.metaText[\"abc-creator\"]+\"\\n\"),abctune.metaText[\"abc-edited-by\"]&&(extraText+=\"Edited By: \"+abctune.metaText[\"abc-edited-by\"]+\"\\n\"),this.outputTextIf(this.padding.left,extraText,\"historyfont\",\"meta-bottom\",this.spacing.info,0,\"start\"),abctune.metaText.footer&&this.isPrint&&(this.outputTextIf(this.padding.left,abctune.metaText.footer.left,\"footerfont\",\"header meta-bottom\",0,null,\"start\"),this.outputTextIf(this.padding.left+width/2,abctune.metaText.footer.center,\"footerfont\",\"header meta-bottom\",0,null,\"middle\"),this.outputTextIf(this.padding.left+width,abctune.metaText.footer.right,\"footerfont\",\"header meta-bottom\",0,null,\"end\"))},ABCJS.write.Renderer.prototype.outputFreeText=function(text){if(\"\"===text){var hash=this.getFontAndAttr(\"textfont\",\"defined-text\");this.moveY(2*hash.attr[\"font-size\"])}else if(\"string\"==typeof text)this.outputTextIf(this.padding.left,text,\"textfont\",\"defined-text\",0,1,\"start\");else{for(var str=\"\",isCentered=!1,i=0;i<text.length;i++)text[i].font&&(str+=\"FONT(\"+text[i].font+\")\"),str+=text[i].text,text[i].center&&(isCentered=!0);var alignment=isCentered?\"middle\":\"start\",x=isCentered?this.controller.width/2:this.padding.left;this.outputTextIf(x,str,\"textfont\",\"defined-text\",0,1,alignment)}},ABCJS.write.Renderer.prototype.outputSubtitle=function(width,subtitle){this.outputTextIf(this.padding.left+width/2,subtitle,\"subtitlefont\",\"text meta-top\",this.spacing.subtitle,0,\"middle\")},ABCJS.write.Renderer.prototype.beginGroup=function(){this.path=[],this.lastM=[0,0],this.ingroup=!0},ABCJS.write.Renderer.prototype.addPath=function(path){if(path=path||[],0!==path.length){path[0][0]=\"m\",path[0][1]-=this.lastM[0],path[0][2]-=this.lastM[1],this.lastM[0]+=path[0][1],this.lastM[1]+=path[0][2],this.path.push(path[0]);for(var i=1,ii=path.length;i<ii;i++)\"m\"===path[i][0]&&(this.lastM[0]+=path[i][1],this.lastM[1]+=path[i][2]),this.path.push(path[i])}},ABCJS.write.Renderer.prototype.endGroup=function(klass){if(this.ingroup=!1,0===this.path.length)return null;var ret=this.paper.path().attr({path:this.path,stroke:\"none\",fill:\"#000000\",class:this.addClasses(klass)});return this.path=[],this.doRegression&&this.addToRegression(ret),ret},ABCJS.write.Renderer.prototype.printStaveLine=function(x1,x2,pitch,klass){var extraClass=\"staff\";void 0!==klass&&(extraClass+=\" \"+klass);var isIE=!1,dy=.35,fill=\"#000000\";isIE&&(dy=1,fill=\"#666666\");var y=this.calcY(pitch),pathString=ABCJS.write.sprintf(\"M %f %f L %f %f L %f %f L %f %f z\",x1,y-dy,x2,y-dy,x2,y+dy,x1,y+dy),ret=this.paper.path().attr({path:pathString,stroke:\"none\",fill:fill,class:this.addClasses(extraClass)}).toBack();return this.doRegression&&this.addToRegression(ret),ret},ABCJS.write.Renderer.prototype.printStem=function(x,dx,y1,y2){if(dx<0){var tmp=y2;y2=y1,y1=tmp}var isIE=!1,fill=\"#000000\";isIE&&dx<1&&(dx=1,fill=\"#666666\"),~~x===x&&(x+=.05);var pathArray=[[\"M\",x,y1],[\"L\",x,y2],[\"L\",x+dx,y2],[\"L\",x+dx,y1],[\"z\"]];if(isIE||!this.ingroup){var ret=this.paper.path().attr({path:pathArray,stroke:\"none\",fill:fill,class:this.addClasses(\"stem\")}).toBack();return this.doRegression&&this.addToRegression(ret),ret}this.addPath(pathArray)},ABCJS.write.Renderer.prototype.printSymbol=function(x,offset,symbol,scalex,scaley,klass){var el,ycorr;if(!symbol)return null;if(symbol.length>0&&symbol.indexOf(\".\")<0){for(var elemset=this.paper.set(),dx=0,i=0;i<symbol.length;i++){var s=symbol.charAt(i);ycorr=ABCJS.write.glyphs.getYCorr(s),el=ABCJS.write.glyphs.printSymbol(x+dx,this.calcY(offset+ycorr),s,this.paper,klass),el?(this.doRegression&&this.addToRegression(el),elemset.push(el),i<symbol.length-1&&(dx+=kernSymbols(s,symbol.charAt(i+1),ABCJS.write.glyphs.getSymbolWidth(s)))):this.renderText(x,this.y,\"no symbol:\"+symbol,\"debugfont\",\"debug-msg\",\"start\")}return elemset}if(ycorr=ABCJS.write.glyphs.getYCorr(symbol),this.ingroup)this.addPath(ABCJS.write.glyphs.getPathForSymbol(x,this.calcY(offset+ycorr),symbol,scalex,scaley));else{if(el=ABCJS.write.glyphs.printSymbol(x,this.calcY(offset+ycorr),symbol,this.paper,klass))return this.doRegression&&this.addToRegression(el),el;this.renderText(x,this.y,\"no symbol:\"+symbol,\"debugfont\",\"debug-msg\",\"start\")}return null},ABCJS.write.Renderer.prototype.printPath=function(attrs){var ret=this.paper.path().attr(attrs);return this.doRegression&&this.addToRegression(ret),ret},ABCJS.write.Renderer.prototype.drawBrace=function(xLeft,yTop,yBottom){var yHeight=yBottom-yTop,xCurve=[7.5,-8,21,0,18.5,-10.5,7.5],yCurve=[0,yHeight/5.5,yHeight/3.14,yHeight/2,yHeight/2.93,yHeight/4.88,0],pathString=ABCJS.write.sprintf(\"M %f %f C %f %f %f %f %f %f C %f %f %f %f %f %f z\",xLeft+xCurve[0],yTop+yCurve[0],xLeft+xCurve[1],yTop+yCurve[1],xLeft+xCurve[2],yTop+yCurve[2],xLeft+xCurve[3],yTop+yCurve[3],xLeft+xCurve[4],yTop+yCurve[4],xLeft+xCurve[5],yTop+yCurve[5],xLeft+xCurve[6],yTop+yCurve[6]),ret1=this.paper.path().attr({path:pathString,stroke:\"#000000\",fill:\"#000000\",class:this.addClasses(\"brace\")});xCurve=[0,17.5,-7.5,6.6,-5,20,0],yCurve=[yHeight/2,yHeight/1.46,yHeight/1.22,yHeight,yHeight/1.19,yHeight/1.42,yHeight/2],pathString=ABCJS.write.sprintf(\"M %f %f C %f %f %f %f %f %f C %f %f %f %f %f %f z\",xLeft+xCurve[0],yTop+yCurve[0],xLeft+xCurve[1],yTop+yCurve[1],xLeft+xCurve[2],yTop+yCurve[2],xLeft+xCurve[3],yTop+yCurve[3],xLeft+xCurve[4],yTop+yCurve[4],xLeft+xCurve[5],yTop+yCurve[5],xLeft+xCurve[6],yTop+yCurve[6]);var ret2=this.paper.path().attr({path:pathString,stroke:\"#000000\",fill:\"#000000\",class:this.addClasses(\"brace\")});return this.doRegression&&(this.addToRegression(ret1),this.addToRegression(ret2)),ret1+ret2},ABCJS.write.Renderer.prototype.drawArc=function(x1,x2,pitch1,pitch2,above,klass,isTie){var spacing=isTie?1.2:1.5;x1+=6,x2+=4,pitch1+=above?spacing:-spacing,pitch2+=above?spacing:-spacing;var y1=this.calcY(pitch1),y2=this.calcY(pitch2),dx=x2-x1,dy=y2-y1,norm=Math.sqrt(dx*dx+dy*dy),ux=dx/norm,uy=dy/norm,flatten=norm/3.5,maxFlatten=isTie?1.5:25,curve=(above?-1:1)*Math.min(maxFlatten,Math.max(4,flatten)),controlx1=x1+flatten*ux-curve*uy,controly1=y1+flatten*uy+curve*ux,controlx2=x2-flatten*ux-curve*uy,controly2=y2-flatten*uy+curve*ux,thickness=2,pathString=ABCJS.write.sprintf(\"M %f %f C %f %f %f %f %f %f C %f %f %f %f %f %f z\",x1,y1,controlx1,controly1,controlx2,controly2,x2,y2,controlx2-thickness*uy,controly2+thickness*ux,controlx1-thickness*uy,controly1+thickness*ux,x1,y1);klass?klass+=\" slur\":klass=\"slur\";var ret=this.paper.path().attr({path:pathString,stroke:\"none\",fill:\"#000000\",class:this.addClasses(klass)});return this.doRegression&&this.addToRegression(ret),ret},ABCJS.write.Renderer.prototype.calcY=function(ofs){return this.y-ofs*ABCJS.write.spacing.STEP},ABCJS.write.Renderer.prototype.printStave=function(startx,endx,numLines){var klass=\"top-line\";if(1===numLines)return void this.printStaveLine(startx,endx,6,klass);for(var i=numLines-1;i>=0;i--)this.printStaveLine(startx,endx,2*(i+1),klass),klass=void 0},ABCJS.write.Renderer.prototype.addClasses=function(c){var ret=[];return c.length>0&&ret.push(c),null!==this.lineNumber&&ret.push(\"l\"+this.lineNumber),null!==this.measureNumber&&ret.push(\"m\"+this.measureNumber),null!==this.voiceNumber&&ret.push(\"v\"+this.voiceNumber),ret.join(\" \")},ABCJS.write.Renderer.prototype.getFontAndAttr=function(type,klass){var font=this.abctune.formatting[type];font=font?{face:font.face,size:4*font.size/3,decoration:font.decoration,style:font.style,weight:font.weight,box:font.box}:{face:\"Arial\",size:16,decoration:\"underline\",style:\"normal\",weight:\"normal\"};var attr={\"font-size\":font.size,\"font-style\":font.style,\"font-family\":font.face,\"font-weight\":font.weight,\"text-decoration\":font.decoration,class:this.addClasses(klass)};return attr.font=\"\",{font:font,attr:attr}},ABCJS.write.Renderer.prototype.getTextSize=function(text,type,klass){var hash=this.getFontAndAttr(type,klass),el=this.paper.text(0,0,text).attr(hash.attr),size=el.getBBox();return isNaN(size.height)&&(size={width:0,height:0}),el.remove(),size},ABCJS.write.Renderer.prototype.renderText=function(x,y,text,type,klass,anchor,centerVertically){var hash=this.getFontAndAttr(type,klass);anchor&&(hash.attr[\"text-anchor\"]=anchor),text=text.replace(/\\n\\n/g,\"\\n \\n\");var el=this.paper.text(x,y,text).attr(hash.attr);if(!centerVertically){var size=el.getBBox();isNaN(size.height)?el.attr({y:y}):(el.attr({y:y+size.height/2}),hash.font.box&&this.paper.rect(size.x-1,size.y+size.height/2-1,size.width+2,size.height+2).attr({stroke:\"#888888\"}))}return\"debugfont\"===type&&(console.log(\"Debug msg: \"+text),el.attr({stroke:\"#ff0000\"})),this.doRegression&&this.addToRegression(el),el},ABCJS.write.Renderer.prototype.moveY=function(em,numLines){void 0===numLines&&(numLines=1),this.y+=em*numLines},ABCJS.write.Renderer.prototype.skipSpaceY=function(){this.y+=this.space},ABCJS.write.Renderer.prototype.outputTextIf=function(x,str,kind,klass,marginTop,marginBottom,alignment){if(str){marginTop&&this.moveY(marginTop);var el=this.renderText(x,this.y,str,kind,klass,alignment),bb=el.getBBox(),width=isNaN(bb.width)?0:bb.width,height=isNaN(bb.height)?0:bb.height;if(null!==marginBottom){var numLines=str.split(\"\\n\").length;isNaN(bb.height)||this.moveY(height/numLines,numLines+marginBottom)}return[width,height]}return[0,0]},ABCJS.write.Renderer.prototype.addInvisibleMarker=function(className){var dy=.35,fill=\"rgba(0,0,0,0)\",y=this.y;y=Math.round(y);var x1=0,x2=100,pathString=ABCJS.write.sprintf(\"M %f %f L %f %f L %f %f L %f %f z\",x1,y-dy,x1+x2,y-dy,x2,y+dy,x1,y+dy);this.paper.path().attr({path:pathString,stroke:\"none\",fill:fill,class:this.addClasses(className),\"data-vertical\":y}).toBack()},ABCJS.write.Renderer.prototype.printHorizontalLine=function(width,vertical,comment){var dy=.35,fill=\"rgba(0,0,255,.4)\",y=this.y;vertical&&(y=vertical),y=Math.round(y),this.paper.text(10,y,\"\"+Math.round(y)).attr({\"text-anchor\":\"start\",\"font-size\":\"18px\",fill:fill,stroke:fill});var x1=50,x2=width,pathString=ABCJS.write.sprintf(\"M %f %f L %f %f L %f %f L %f %f z\",x1,y-dy,x1+x2,y-dy,x2,y+dy,x1,y+dy);this.paper.path().attr({path:pathString,stroke:\"none\",fill:fill,class:this.addClasses(\"staff\")}).toBack();for(var i=1;i<width/100;i++)pathString=ABCJS.write.sprintf(\"M %f %f L %f %f L %f %f L %f %f z\",100*i-dy,y-5,100*i-dy,y+5,100*i+dy,y-5,100*i+dy,y+5),this.paper.path().attr({path:pathString,stroke:\"none\",fill:fill,class:this.addClasses(\"staff\")}).toBack();comment&&this.paper.text(width+70,y,comment).attr({\"text-anchor\":\"start\",\"font-size\":\"18px\",fill:fill,stroke:fill})},ABCJS.write.Renderer.prototype.printShadedBox=function(x,y,width,height,color,comment){var box=this.paper.rect(x,y,width,height).attr({fill:color,stroke:color});return comment&&this.paper.text(0,y+7,comment).attr({\"text-anchor\":\"start\",\"font-size\":\"14px\",fill:\"rgba(0,0,255,.4)\",stroke:\"rgba(0,0,255,.4)\"}),box},ABCJS.write.Renderer.prototype.printVerticalLine=function(x,y1,y2){var dy=.35,fill=\"#00aaaa\",pathString=ABCJS.write.sprintf(\"M %f %f L %f %f L %f %f L %f %f z\",x-dy,y1,x-dy,y2,x+dy,y1,x+dy,y2);this.paper.path().attr({path:pathString,stroke:\"none\",fill:fill,class:this.addClasses(\"staff\")}).toBack(),pathString=ABCJS.write.sprintf(\"M %f %f L %f %f L %f %f L %f %f z\",x-20,y1,x-20,y1+3,x,y1,x,y1+3),this.paper.path().attr({path:pathString,stroke:\"none\",fill:fill,class:this.addClasses(\"staff\")}).toBack(),pathString=ABCJS.write.sprintf(\"M %f %f L %f %f L %f %f L %f %f z\",x+20,y2,x+20,y2+3,x,y2,x,y2+3),this.paper.path().attr({path:pathString,stroke:\"none\",fill:fill,class:this.addClasses(\"staff\")}).toBack()},ABCJS.write.Renderer.prototype.addToRegression=function(el){var box=el.getBBox(),str=el.type+\" \"+box.toString()+\" \",attrs=[];for(var key in el.attrs)el.attrs.hasOwnProperty(key)&&(\"class\"===key?str=el.attrs[key]+\" \"+str:attrs.push(key+\": \"+el.attrs[key]));attrs.sort(),str+=\"{ \"+attrs.join(\" \")+\" }\",this.regressionLines.push(str)},window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.StaffGroupElement=function(){this.voices=[],this.staffs=[],this.brace=void 0},ABCJS.write.StaffGroupElement.prototype.setLimit=function(member,voice){voice.specialY[member]&&(voice.staff.specialY[member]?voice.staff.specialY[member]=Math.max(voice.staff.specialY[member],voice.specialY[member]):voice.staff.specialY[member]=voice.specialY[member])},ABCJS.write.StaffGroupElement.prototype.addVoice=function(voice,staffnumber,stafflines){var voiceNum=this.voices.length;this.voices[voiceNum]=voice,this.staffs[staffnumber]?this.staffs[staffnumber].voices.push(voiceNum):this.staffs[this.staffs.length]={top:10,bottom:2,lines:stafflines,voices:[voiceNum],specialY:{tempoHeightAbove:0,partHeightAbove:0,volumeHeightAbove:0,dynamicHeightAbove:0,endingHeightAbove:0,chordHeightAbove:0,lyricHeightAbove:0,lyricHeightBelow:0,chordHeightBelow:0,volumeHeightBelow:0,dynamicHeightBelow:0}},voice.staff=this.staffs[staffnumber]},ABCJS.write.StaffGroupElement.prototype.setStaffLimits=function(voice){voice.staff.top=Math.max(voice.staff.top,voice.top),voice.staff.bottom=Math.min(voice.staff.bottom,voice.bottom),this.setLimit(\"tempoHeightAbove\",voice),this.setLimit(\"partHeightAbove\",voice),this.setLimit(\"volumeHeightAbove\",voice),this.setLimit(\"dynamicHeightAbove\",voice),this.setLimit(\"endingHeightAbove\",voice),this.setLimit(\"chordHeightAbove\",voice),this.setLimit(\"lyricHeightAbove\",voice),this.setLimit(\"lyricHeightBelow\",voice),this.setLimit(\"chordHeightBelow\",voice),this.setLimit(\"volumeHeightBelow\",voice),this.setLimit(\"dynamicHeightBelow\",voice)};ABCJS.write.StaffGroupElement.prototype.setUpperAndLowerElements=function(renderer){for(var lastStaffBottom,i=0;i<this.staffs.length;i++){var staff=this.staffs[i],positionY={tempoHeightAbove:0,partHeightAbove:0,volumeHeightAbove:0,dynamicHeightAbove:0,endingHeightAbove:0,chordHeightAbove:0,lyricHeightAbove:0,lyricHeightBelow:0,chordHeightBelow:0,volumeHeightBelow:0,dynamicHeightBelow:0};ABCJS.write.debugPlacement&&(staff.originalTop=staff.top,staff.originalBottom=staff.bottom),staff.specialY.lyricHeightAbove&&(staff.top+=staff.specialY.lyricHeightAbove,positionY.lyricHeightAbove=staff.top),staff.specialY.chordHeightAbove&&(staff.top+=staff.specialY.chordHeightAbove,positionY.chordHeightAbove=staff.top),staff.specialY.endingHeightAbove&&(staff.specialY.chordHeightAbove?staff.top+=2:staff.top+=staff.specialY.endingHeightAbove,positionY.endingHeightAbove=staff.top),staff.specialY.dynamicHeightAbove&&staff.specialY.volumeHeightAbove?(staff.top+=Math.max(staff.specialY.dynamicHeightAbove,staff.specialY.volumeHeightAbove),positionY.dynamicHeightAbove=staff.top,positionY.volumeHeightAbove=staff.top):staff.specialY.dynamicHeightAbove?(staff.top+=staff.specialY.dynamicHeightAbove,positionY.dynamicHeightAbove=staff.top):staff.specialY.volumeHeightAbove&&(staff.top+=staff.specialY.volumeHeightAbove,positionY.volumeHeightAbove=staff.top),staff.specialY.partHeightAbove&&(staff.top+=staff.specialY.partHeightAbove,positionY.partHeightAbove=staff.top),staff.specialY.tempoHeightAbove&&(staff.top+=staff.specialY.tempoHeightAbove,positionY.tempoHeightAbove=staff.top),staff.specialY.lyricHeightBelow&&(positionY.lyricHeightBelow=staff.bottom,staff.bottom-=staff.specialY.lyricHeightBelow),staff.specialY.chordHeightBelow&&(positionY.chordHeightBelow=staff.bottom,staff.bottom-=staff.specialY.chordHeightBelow),staff.specialY.volumeHeightBelow&&staff.specialY.dynamicHeightBelow?(positionY.volumeHeightBelow=staff.bottom,positionY.dynamicHeightBelow=staff.bottom,staff.bottom-=Math.max(staff.specialY.volumeHeightBelow,staff.specialY.dynamicHeightBelow)):staff.specialY.volumeHeightBelow?(positionY.volumeHeightBelow=staff.bottom,staff.bottom-=staff.specialY.volumeHeightBelow):staff.specialY.dynamicHeightBelow&&(positionY.dynamicHeightBelow=staff.bottom,staff.bottom-=staff.specialY.dynamicHeightBelow),ABCJS.write.debugPlacement&&(staff.positionY=positionY);for(var j=0;j<staff.voices.length;j++){var voice=this.voices[staff.voices[j]];voice.setUpperAndLowerElements(positionY)}if(void 0!==lastStaffBottom){var thisStaffTop=staff.top-10,forcedSpacingBetween=lastStaffBottom+thisStaffTop,minSpacingInPitches=renderer.spacing.systemStaffSeparation/ABCJS.write.spacing.STEP,addedSpace=minSpacingInPitches-forcedSpacingBetween;addedSpace>0&&(staff.top+=addedSpace)}lastStaffBottom=2-staff.bottom}};ABCJS.write.StaffGroupElement.prototype.finished=function(){for(var i=0;i<this.voices.length;i++)if(!this.voices[i].layoutEnded())return!1;return!0},ABCJS.write.StaffGroupElement.prototype.layout=function(spacing,renderer,debug){var epsilon=1e-7;this.spacingunits=0,this.minspace=1e3;for(var x=renderer.padding.left,voiceheaderw=0,i=0;i<this.voices.length;i++)if(this.voices[i].header){var size=renderer.getTextSize(this.voices[i].header,\"voicefont\",\"\");voiceheaderw=Math.max(voiceheaderw,size.width)}x+=1.1*voiceheaderw,this.startx=x,this.brace&&(this.brace.setLocation(this.startx),x+=this.brace.getWidth(),this.startx=x);var currentduration=0;for(debug&&console.log(\"init layout\"),i=0;i<this.voices.length;i++)this.voices[i].beginLayout(x);for(var spacingunit=0;!this.finished();){for(currentduration=null,i=0;i<this.voices.length;i++)this.voices[i].layoutEnded()||currentduration&&!(this.voices[i].getDurationIndex()<currentduration)||(currentduration=this.voices[i].getDurationIndex());debug&&console.log(\"currentduration: \",currentduration);var currentvoices=[],othervoices=[];for(i=0;i<this.voices.length;i++){var durationIndex=this.voices[i].getDurationIndex();durationIndex-currentduration>epsilon?othervoices.push(this.voices[i]):(currentvoices.push(this.voices[i]),debug&&console.log(\"in: voice \",i))}spacingunit=0;var spacingduration=0;for(i=0;i<currentvoices.length;i++)currentvoices[i].getNextX()>x&&(x=currentvoices[i].getNextX(),spacingunit=currentvoices[i].getSpacingUnits(),spacingduration=currentvoices[i].spacingduration);for(this.spacingunits+=spacingunit,this.minspace=Math.min(this.minspace,spacingunit),i=0;i<currentvoices.length;i++){var voicechildx=currentvoices[i].layoutOneItem(x,spacing),dx=voicechildx-x;if(dx>0){x=voicechildx;for(var j=0;j<i;j++)currentvoices[j].shiftRight(dx)}}for(i=0;i<othervoices.length;i++)othervoices[i].spacingduration-=spacingduration,othervoices[i].updateNextX(x,spacing);for(i=0;i<currentvoices.length;i++){var voice=currentvoices[i];voice.updateIndices()}}for(i=0;i<this.voices.length;i++)this.voices[i].getNextX()>x&&(x=this.voices[i].getNextX(),spacingunit=this.voices[i].getSpacingUnits());for(this.spacingunits+=spacingunit,this.w=x,i=0;i<this.voices.length;i++)this.voices[i].w=this.w},ABCJS.write.StaffGroupElement.prototype.calcHeight=function(){for(var height=0,i=0;i<this.voices.length;i++){var staff=this.voices[i].staff;this.voices[i].duplicate||(height+=staff.top,staff.bottom<0&&(height+=-staff.bottom))}return height},ABCJS.write.StaffGroupElement.prototype.draw=function(renderer){var debugPrint,colorIndex;if(ABCJS.write.debugPlacement){var colors=[\"rgba(207,27,36,0.4)\",\"rgba(168,214,80,0.4)\",\"rgba(110,161,224,0.4)\",\"rgba(191,119,218,0.4)\",\"rgba(195,30,151,0.4)\",\"rgba(31,170,177,0.4)\",\"rgba(220,166,142,0.4)\"];debugPrint=function(staff,key){if(staff.positionY[key]){var height=staff.specialY[key]*ABCJS.write.spacing.STEP;renderer.printShadedBox(renderer.padding.left,renderer.calcY(staff.positionY[key]),renderer.controller.width,height,colors[colorIndex],key.substr(0,4)),colorIndex+=1,colorIndex>6&&(colorIndex=0)}}}renderer.addInvisibleMarker(\"abcjs-top-of-system\");for(var startY=renderer.y,j=0;j<this.staffs.length;j++){var staff1=this.staffs[j];renderer.moveY(ABCJS.write.spacing.STEP,staff1.top),staff1.absoluteY=renderer.y,ABCJS.write.debugPlacement&&(colorIndex=0,renderer.printShadedBox(renderer.padding.left,renderer.calcY(staff1.originalTop),renderer.controller.width,renderer.calcY(staff1.originalBottom)-renderer.calcY(staff1.originalTop),\"rgba(0,0,0,0.1)\"),debugPrint(staff1,\"chordHeightAbove\"),debugPrint(staff1,\"chordHeightBelow\"),debugPrint(staff1,\"dynamicHeightAbove\"),debugPrint(staff1,\"dynamicHeightBelow\"),debugPrint(staff1,\"endingHeightAbove\"),debugPrint(staff1,\"lyricHeightAbove\"),debugPrint(staff1,\"lyricHeightBelow\"),debugPrint(staff1,\"partHeightAbove\"),debugPrint(staff1,\"tempoHeightAbove\"),debugPrint(staff1,\"volumeHeightAbove\"),debugPrint(staff1,\"volumeHeightBelow\")),staff1.bottom<0&&renderer.moveY(ABCJS.write.spacing.STEP,-staff1.bottom)}var topLine,bottomLine,bartop=0;renderer.measureNumber=null;for(var i=0;i<this.voices.length;i++){var staff=this.voices[i].staff;renderer.y=staff.absoluteY,renderer.voiceNumber=i,this.voices[i].duplicate||(topLine||(topLine=renderer.calcY(10)),bottomLine=renderer.calcY(2),0!==staff.lines&&renderer.printStave(this.startx,this.w,staff.lines)),this.voices[i].draw(renderer,bartop),this.voices[i].duplicate||(bartop=renderer.calcY(2)),this.brace&&i===this.brace.length-1&&this.brace&&this.brace.draw(renderer,topLine,bottomLine)}renderer.measureNumber=null,this.staffs.length>1&&renderer.printStem(this.startx,.6,topLine,bottomLine),renderer.y=startY},window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),function(){\"use strict\";var totalHeightInPitches=5;ABCJS.write.TempoElement=function(tempo,tuneNumber){this.tempo=tempo,this.tuneNumber=tuneNumber,this.tempoHeightAbove=totalHeightInPitches,this.pitch=void 0},ABCJS.write.TempoElement.prototype.setUpperAndLowerElements=function(positionY){this.pitch=positionY.tempoHeightAbove},ABCJS.write.TempoElement.prototype.setX=function(x){this.x=x},ABCJS.write.TempoElement.prototype.draw=function(renderer){var x=this.x;void 0===this.pitch&&window.console.error(\"Tempo Element y-coordinate not set.\");var text,y=renderer.calcY(this.pitch);if(this.tempo.preString){text=renderer.renderText(x,y,this.tempo.preString,\"tempofont\",\"tempo\",\"start\");var preWidth=text.getBBox().width,charWidth=preWidth/this.tempo.preString.length;\nx+=preWidth+charWidth}if(this.tempo.duration){var dot,flag,note,temposcale=.75,tempopitch=this.pitch-totalHeightInPitches+1,duration=this.tempo.duration[0],abselem=new ABCJS.write.AbsoluteElement(this.tempo,duration,1,\"tempo\",this.tuneNumber);duration<=1/32?(note=\"noteheads.quarter\",flag=\"flags.u32nd\",dot=0):duration<=1/16?(note=\"noteheads.quarter\",flag=\"flags.u16th\",dot=0):duration<=3/32?(note=\"noteheads.quarter\",flag=\"flags.u16nd\",dot=1):duration<=1/8?(note=\"noteheads.quarter\",flag=\"flags.u8th\",dot=0):duration<=3/16?(note=\"noteheads.quarter\",flag=\"flags.u8th\",dot=1):duration<=.25?(note=\"noteheads.quarter\",dot=0):duration<=3/8?(note=\"noteheads.quarter\",dot=1):duration<=.5?(note=\"noteheads.half\",dot=0):duration<=.75?(note=\"noteheads.half\",dot=1):duration<=1?(note=\"noteheads.whole\",dot=0):duration<=1.5?(note=\"noteheads.whole\",dot=1):duration<=2?(note=\"noteheads.dbl\",dot=0):(note=\"noteheads.dbl\",dot=1);var temponote=renderer.engraver.createNoteHead(abselem,note,{verticalPos:tempopitch},\"up\",0,0,flag,dot,0,temposcale);abselem.addHead(temponote);var stem;if(\"noteheads.whole\"!==note&&\"noteheads.dbl\"!==note){var p1=tempopitch+1/3*temposcale,p2=tempopitch+7*temposcale,dx=temponote.dx+temponote.w,width=-.6;stem=new ABCJS.write.RelativeElement(null,dx,0,p1,{type:\"stem\",pitch2:p2,linewidth:width}),stem.setX(x),abselem.addExtra(stem)}abselem.setX(x);for(var i=0;i<abselem.children.length;i++)abselem.children[i].draw(renderer,x);x+=abselem.w+5;var str=\"= \"+this.tempo.bpm;text=renderer.renderText(x,y,str,\"tempofont\",\"tempo\",\"start\");var postWidth=text.getBBox().width,charWidth2=postWidth/str.length;x+=postWidth+charWidth2}this.tempo.postString&&renderer.renderText(x,y,this.tempo.postString,\"tempofont\",\"tempo\",\"start\")}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.TieElem=function(anchor1,anchor2,above,forceandshift,isTie){this.anchor1=anchor1,this.anchor2=anchor2,this.above=above,this.force=forceandshift,this.isTie=isTie},ABCJS.write.TieElem.prototype.setEndAnchor=function(anchor2){this.anchor2=anchor2,this.isTie&&(this.anchor1&&(this.anchor1.isTie=!0),this.anchor2&&(this.anchor2.isTie=!0))},ABCJS.write.TieElem.prototype.setStartX=function(startLimitElem){this.startLimitX=startLimitElem},ABCJS.write.TieElem.prototype.setEndX=function(endLimitElem){this.endLimitX=endLimitElem},ABCJS.write.TieElem.prototype.setHint=function(){this.hint=!0},ABCJS.write.TieElem.prototype.setUpperAndLowerElements=function(positionY){},ABCJS.write.TieElem.prototype.layout=function(lineStartX,lineEndX){function getPitch(anchor,isAbove,isTie){return isTie?anchor.pitch:isAbove&&void 0!==anchor.highestVert?anchor.highestVert:anchor.pitch}!this.force&&this.anchor2&&this.anchor2.pitch===this.anchor2.highestVert&&(this.above=!0),this.isTie?(this.anchor1&&(this.anchor1.tieAbove=this.above),this.anchor2&&(this.anchor2.tieAbove=this.above)):this.anchor2&&this.anchor2.isTie?this.above=this.anchor2.tieAbove:this.anchor1&&this.anchor1.isTie&&(this.above=this.anchor1.tieAbove),this.anchor1?this.startX=this.anchor1.x:this.startLimitX?this.startX=this.startLimitX.x+this.startLimitX.w:this.startX=lineStartX,this.anchor2?this.endX=this.anchor2.x:this.endLimitX?this.endX=this.endLimitX.x:this.endX=lineEndX,this.anchor1&&this.anchor2?(this.startY=getPitch(this.anchor1,this.above,this.isTie),this.endY=getPitch(this.anchor2,this.above,this.isTie)):this.anchor1?(this.startY=getPitch(this.anchor1,this.above,this.isTie),this.endY=getPitch(this.anchor1,this.above,this.isTie)):this.anchor2?(this.startY=getPitch(this.anchor2,this.above,this.isTie),this.endY=getPitch(this.anchor2,this.above,this.isTie)):(this.startY=this.above?14:0,this.endY=this.above?14:0)},ABCJS.write.TieElem.prototype.draw=function(renderer,linestartx,lineendx){this.layout(linestartx,lineendx);var klass;this.hint&&(klass=\"abcjs-hint\"),renderer.drawArc(this.startX,this.endX,this.startY,this.endY,this.above,klass,this.isTie)},window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),function(){\"use strict\";function drawLine(renderer,l,t,r,b){var pathString=ABCJS.write.sprintf(\"M %f %f L %f %f\",l,t,r,b);renderer.printPath({path:pathString,stroke:\"#000000\",class:renderer.addClasses(\"triplet\")})}function drawBracket(renderer,x1,y1,x2,y2){y1=renderer.calcY(y1),y2=renderer.calcY(y2);var bracketHeight=5;drawLine(renderer,x1,y1,x1,y1+bracketHeight),drawLine(renderer,x2,y2,x2,y2+bracketHeight);var midX=x1+(x2-x1)/2,gapWidth=8,slope=(y2-y1)/(x2-x1),leftEndX=midX-gapWidth,leftEndY=y1+(leftEndX-x1)*slope;drawLine(renderer,x1,y1,leftEndX,leftEndY);var rightStartX=midX+gapWidth,rightStartY=y1+(rightStartX-x1)*slope;drawLine(renderer,rightStartX,rightStartY,x2,y2)}ABCJS.write.TripletElem=function(number,anchor1){this.anchor1=anchor1,this.number=number},ABCJS.write.TripletElem.prototype.isClosed=function(){return this.anchor2},ABCJS.write.TripletElem.prototype.setCloseAnchor=function(anchor2){this.anchor2=anchor2,this.anchor1.parent.beam&&(this.endingHeightAbove=4)},ABCJS.write.TripletElem.prototype.setUpperAndLowerElements=function(){},ABCJS.write.TripletElem.prototype.layout=function(){if(this.anchor1&&this.anchor2)if(this.hasBeam=this.anchor1.parent.beam&&this.anchor1.parent.beam===this.anchor2.parent.beam,this.hasBeam){var beam=this.anchor1.parent.beam,left=beam.isAbove()?this.anchor1.x+this.anchor1.w:this.anchor1.x;this.yTextPos=beam.heightAtMidpoint(left,this.anchor2.x),this.yTextPos+=beam.isAbove()?4:-4,beam.isAbove()&&(this.endingHeightAbove=4)}else this.startNote=Math.max(this.anchor1.parent.top,9)+4,this.endNote=Math.max(this.anchor2.parent.top,9)+4,this.yTextPos=this.startNote+(this.endNote-this.startNote)/2},ABCJS.write.TripletElem.prototype.draw=function(renderer){var xTextPos;if(this.hasBeam){var left=this.anchor1.parent.beam.isAbove()?this.anchor1.x+this.anchor1.w:this.anchor1.x;xTextPos=this.anchor1.parent.beam.xAtMidpoint(left,this.anchor2.x)}else xTextPos=this.anchor1.x+(this.anchor2.x+this.anchor2.w-this.anchor1.x)/2,drawBracket(renderer,this.anchor1.x,this.startNote,this.anchor2.x+this.anchor2.w,this.endNote);renderer.renderText(xTextPos,renderer.calcY(this.yTextPos),\"\"+this.number,\"tripletfont\",\"triplet\",\"middle\",!0)}}(),window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.VoiceElement=function(voicenumber,voicetotal){this.children=[],this.beams=[],this.otherchildren=[],this.w=0,this.duplicate=!1,this.voicenumber=voicenumber,this.voicetotal=voicetotal,this.bottom=7,this.top=7,this.specialY={tempoHeightAbove:0,partHeightAbove:0,volumeHeightAbove:0,dynamicHeightAbove:0,endingHeightAbove:0,chordHeightAbove:0,lyricHeightAbove:0,lyricHeightBelow:0,chordHeightBelow:0,volumeHeightBelow:0,dynamicHeightBelow:0}},ABCJS.write.VoiceElement.prototype.addChild=function(child){if(\"bar\"===child.type){for(var firstItem=!0,i=0;firstItem&&i<this.children.length;i++)\"staff-extra\"!==this.children[i].type&&(firstItem=!1);firstItem||(this.beams.push(\"bar\"),this.otherchildren.push(\"bar\"))}this.children[this.children.length]=child,this.setRange(child)},ABCJS.write.VoiceElement.prototype.setLimit=function(member,child){var specialY=child.specialY;specialY||(specialY=child),specialY[member]&&(this.specialY[member]?this.specialY[member]=Math.max(this.specialY[member],specialY[member]):this.specialY[member]=specialY[member])},ABCJS.write.VoiceElement.prototype.moveDecorations=function(beam){for(var padding=1.5,ch=0;ch<beam.elems.length;ch++){var child=beam.elems[ch];if(child.top)for(var top=beam.yAtNote(child),i=0;i<child.children.length;i++){var el=child.children[i];if(\"ornament\"===el.klass&&el.bottom-padding<top){var distance=top-el.bottom+padding;el.bottom+=distance,el.top+=distance,el.pitch+=distance,top=child.top=el.top}}}},ABCJS.write.VoiceElement.prototype.adjustRange=function(child){void 0!==child.bottom&&(this.bottom=Math.min(this.bottom,child.bottom)),void 0!==child.top&&(this.top=Math.max(this.top,child.top))},ABCJS.write.VoiceElement.prototype.setRange=function(child){this.adjustRange(child),this.setLimit(\"tempoHeightAbove\",child),this.setLimit(\"partHeightAbove\",child),this.setLimit(\"volumeHeightAbove\",child),this.setLimit(\"dynamicHeightAbove\",child),this.setLimit(\"endingHeightAbove\",child),this.setLimit(\"chordHeightAbove\",child),this.setLimit(\"lyricHeightAbove\",child),this.setLimit(\"lyricHeightBelow\",child),this.setLimit(\"chordHeightBelow\",child),this.setLimit(\"volumeHeightBelow\",child),this.setLimit(\"dynamicHeightBelow\",child)},ABCJS.write.VoiceElement.prototype.setUpperAndLowerElements=function(positionY){var i;for(i=0;i<this.children.length;i++){var abselem=this.children[i];abselem.setUpperAndLowerElements(positionY)}for(i=0;i<this.otherchildren.length;i++){var abselem=this.otherchildren[i];\"string\"!=typeof abselem&&abselem.setUpperAndLowerElements(positionY)}},ABCJS.write.VoiceElement.prototype.addOther=function(child){this.otherchildren.push(child),this.setRange(child)},ABCJS.write.VoiceElement.prototype.addBeam=function(child){this.beams.push(child)},ABCJS.write.VoiceElement.prototype.updateIndices=function(){this.layoutEnded()||(this.durationindex+=this.children[this.i].duration,0===this.children[this.i].duration&&(this.durationindex=Math.round(64*this.durationindex)/64),this.i++)},ABCJS.write.VoiceElement.prototype.layoutEnded=function(){return this.i>=this.children.length},ABCJS.write.VoiceElement.prototype.getDurationIndex=function(){return this.durationindex-(this.children[this.i]&&this.children[this.i].duration>0?0:5e-7)},ABCJS.write.VoiceElement.prototype.getSpacingUnits=function(){return Math.sqrt(8*this.spacingduration)},ABCJS.write.VoiceElement.prototype.getNextX=function(){return Math.max(this.minx,this.nextx)},ABCJS.write.VoiceElement.prototype.beginLayout=function(startx){this.i=0,this.durationindex=0,this.startx=startx,this.minx=startx,this.nextx=startx,this.spacingduration=0},ABCJS.write.VoiceElement.prototype.layoutOneItem=function(x,spacing){var child=this.children[this.i];if(!child)return 0;var er=x-this.minx;return er<child.getExtraWidth()&&(x+=child.getExtraWidth()-er),child.setX(x),this.spacingduration=child.duration,this.minx=x+child.getMinWidth(),this.i!==this.children.length-1&&(this.minx+=child.minspacing),this.updateNextX(x,spacing),x},ABCJS.write.VoiceElement.prototype.updateNextX=function(x,spacing){this.nextx=x+spacing*Math.sqrt(8*this.spacingduration)},ABCJS.write.VoiceElement.prototype.shiftRight=function(dx){var child=this.children[this.i];child&&(child.setX(child.x+dx),this.minx+=dx,this.nextx+=dx)},ABCJS.write.VoiceElement.prototype.draw=function(renderer,bartop){var width=this.w-1;if(renderer.staffbottom=this.staff.bottom,renderer.measureNumber=null,this.header){var textpitch=14-(this.voicenumber+1)*(12/(this.voicetotal+1));renderer.renderText(renderer.padding.left,renderer.calcY(textpitch),this.header,\"voicefont\",\"staff-extra voice-name\",\"start\")}for(var i=0,ii=this.children.length;i<ii;i++){var child=this.children[i],justInitializedMeasureNumber=!1;\"staff-extra\"!==child.type&&null===renderer.measureNumber&&(renderer.measureNumber=0,justInitializedMeasureNumber=!0),child.draw(renderer,this.barto||i===ii-1?bartop:0),\"bar\"!==child.type||justInitializedMeasureNumber||renderer.measureNumber++}renderer.measureNumber=0,window.ABCJS.parse.each(this.beams,function(beam){\"bar\"===beam?renderer.measureNumber++:beam.draw(renderer)}),renderer.measureNumber=0;var self=this;window.ABCJS.parse.each(this.otherchildren,function(child){\"bar\"===child?renderer.measureNumber++:child.draw(renderer,self.startx+10,width)})},ABCJS.write.VoiceElement.prototype.layoutBeams=function(){for(var i=0;i<this.beams.length;i++)if(this.beams[i].layout){this.beams[i].layout(),this.moveDecorations(this.beams[i]);for(var j=0;j<this.beams[i].elems.length;j++)this.adjustRange(this.beams[i].elems[j])}for(i=0;i<this.otherchildren.length;i++){var child=this.otherchildren[i];child.layout&&child.layout()}this.staff.top=Math.max(this.staff.top,this.top),this.staff.bottom=Math.min(this.staff.bottom,this.bottom)},window.ABCJS||(window.ABCJS={}),window.ABCJS.write||(window.ABCJS.write={}),ABCJS.write.sprintf=function(){for(var a,m,p,c,x,i=0,f=arguments[i++],o=[];f;){if(m=/^[^\\x25]+/.exec(f))o.push(m[0]);else if(m=/^\\x25{2}/.exec(f))o.push(\"%\");else{if(!(m=/^\\x25(?:(\\d+)\\$)?(\\+)?(0|'[^$])?(-)?(\\d+)?(?:\\.(\\d+))?([b-fosuxX])/.exec(f)))throw\"Huh ?!\";if(null==(a=arguments[m[1]||i++])||void 0==a)throw\"Too few arguments.\";if(/[^s]/.test(m[7])&&\"number\"!=typeof a)throw\"Expecting number but found \"+typeof a;switch(m[7]){case\"b\":a=a.toString(2);break;case\"c\":a=String.fromCharCode(a);break;case\"d\":a=parseInt(a);break;case\"e\":a=m[6]?a.toExponential(m[6]):a.toExponential();break;case\"f\":a=m[6]?parseFloat(a).toFixed(m[6]):parseFloat(a);break;case\"o\":a=a.toString(8);break;case\"s\":a=(a=String(a))&&m[6]?a.substring(0,m[6]):a;break;case\"u\":a=Math.abs(a);break;case\"x\":a=a.toString(16);break;case\"X\":a=a.toString(16).toUpperCase()}a=/[def]/.test(m[7])&&m[2]&&a>0?\"+\"+a:a,c=m[3]?\"0\"==m[3]?\"0\":m[3].charAt(1):\" \",x=m[5]-String(a).length,p=m[5]?str_repeat(c,x):\"\",o.push(m[4]?a+p:p+a)}f=f.substring(m[0].length)}return o.join(\"\")};"
  },
  {
    "path": "public/vendor/codemirror-spell-checker/en_US.aff",
    "content": "SET UTF-8\nTRY esianrtolcdugmphbyfvkwzESIANRTOLCDUGMPHBYFVKWZ'\nICONV 1\nICONV ’ '\nNOSUGGEST !\n\n# ordinal numbers\nCOMPOUNDMIN 1\n# only in compounds: 1th, 2th, 3th\nONLYINCOMPOUND c\n# compound rules:\n# 1. [0-9]*1[0-9]th (10th, 11th, 12th, 56714th, etc.)\n# 2. [0-9]*[02-9](1st|2nd|3rd|[4-9]th) (21st, 22nd, 123rd, 1234th, etc.)\nCOMPOUNDRULE 2\nCOMPOUNDRULE n*1t\nCOMPOUNDRULE n*mp\nWORDCHARS 0123456789\n\nPFX A Y 1\nPFX A   0     re         .\n\nPFX I Y 1\nPFX I   0     in         .\n\nPFX U Y 1\nPFX U   0     un         .\n\nPFX C Y 1\nPFX C   0     de          .\n\nPFX E Y 1\nPFX E   0     dis         .\n\nPFX F Y 1\nPFX F   0     con         .\n\nPFX K Y 1\nPFX K   0     pro         .\n\nSFX V N 2\nSFX V   e     ive        e\nSFX V   0     ive        [^e]\n\nSFX N Y 3\nSFX N   e     ion        e\nSFX N   y     ication    y \nSFX N   0     en         [^ey] \n\nSFX X Y 3\nSFX X   e     ions       e\nSFX X   y     ications   y\nSFX X   0     ens        [^ey]\n\nSFX H N 2\nSFX H   y     ieth       y\nSFX H   0     th         [^y] \n\nSFX Y Y 1\nSFX Y   0     ly         .\n\nSFX G Y 2\nSFX G   e     ing        e\nSFX G   0     ing        [^e] \n\nSFX J Y 2\nSFX J   e     ings       e\nSFX J   0     ings       [^e]\n\nSFX D Y 4\nSFX D   0     d          e\nSFX D   y     ied        [^aeiou]y\nSFX D   0     ed         [^ey]\nSFX D   0     ed         [aeiou]y\n\nSFX T N 4\nSFX T   0     st         e\nSFX T   y     iest       [^aeiou]y\nSFX T   0     est        [aeiou]y\nSFX T   0     est        [^ey]\n\nSFX R Y 4\nSFX R   0     r          e\nSFX R   y     ier        [^aeiou]y\nSFX R   0     er         [aeiou]y\nSFX R   0     er         [^ey]\n\nSFX Z Y 4\nSFX Z   0     rs         e\nSFX Z   y     iers       [^aeiou]y\nSFX Z   0     ers        [aeiou]y\nSFX Z   0     ers        [^ey]\n\nSFX S Y 4\nSFX S   y     ies        [^aeiou]y\nSFX S   0     s          [aeiou]y\nSFX S   0     es         [sxzh]\nSFX S   0     s          [^sxzhy]\n\nSFX P Y 3\nSFX P   y     iness      [^aeiou]y\nSFX P   0     ness       [aeiou]y\nSFX P   0     ness       [^y]\n\nSFX M Y 1\nSFX M   0     's         .\n\nSFX B Y 3\nSFX B   0     able       [^aeiou]\nSFX B   0     able       ee\nSFX B   e     able       [^aeiou]e\n\nSFX L Y 1\nSFX L   0     ment       .\n\nREP 90\nREP a ei\nREP ei a\nREP a ey\nREP ey a\nREP ai ie\nREP ie ai\nREP alot a_lot\nREP are air\nREP are ear\nREP are eir\nREP air are\nREP air ere\nREP ere air\nREP ere ear\nREP ere eir\nREP ear are\nREP ear air\nREP ear ere\nREP eir are\nREP eir ere\nREP ch te\nREP te ch\nREP ch ti\nREP ti ch\nREP ch tu\nREP tu ch\nREP ch s\nREP s ch\nREP ch k\nREP k ch\nREP f ph\nREP ph f\nREP gh f\nREP f gh\nREP i igh\nREP igh i\nREP i uy\nREP uy i\nREP i ee\nREP ee i\nREP j di\nREP di j\nREP j gg\nREP gg j\nREP j ge\nREP ge j\nREP s ti\nREP ti s\nREP s ci\nREP ci s\nREP k cc\nREP cc k\nREP k qu\nREP qu k\nREP kw qu\nREP o eau\nREP eau o\nREP o ew\nREP ew o\nREP oo ew\nREP ew oo\nREP ew ui\nREP ui ew\nREP oo ui\nREP ui oo\nREP ew u\nREP u ew\nREP oo u\nREP u oo\nREP u oe\nREP oe u\nREP u ieu\nREP ieu u\nREP ue ew\nREP ew ue\nREP uff ough\nREP oo ieu\nREP ieu oo\nREP ier ear\nREP ear ier\nREP ear air\nREP air ear\nREP w qu\nREP qu w\nREP z ss\nREP ss z\nREP shun tion\nREP shun sion\nREP shun cion\nREP size cise\n"
  },
  {
    "path": "public/vendor/codemirror-spell-checker/en_US.dic",
    "content": "48914\n0/nm\n0th/pt\n1/n1\n1st/p\n1th/tc\n2/nm\n2nd/p\n2th/tc\n3/nm\n3rd/p\n3th/tc\n4/nm\n4th/pt\n5/nm\n5th/pt\n6/nm\n6th/pt\n7/nm\n7th/pt\n8/nm\n8th/pt\n9/nm\n9th/pt\nA/SM\nAA/M\nAAA\nAB/M\nABA\nABC/SM\nABM/SM\nABS\nAC/M\nACLU/M\nACT\nACTH/M\nAD/M\nADC\nADD\nADP/M\nAF\nAFAIK\nAFB\nAFC/M\nAFDC\nAFN\nAFT\nAI/SM\nAIDS/M\nAK\nAL\nAM/M\nAMA\nAMD/M\nANSI/S\nANZUS/M\nAOL/M\nAP/M\nAPB\nAPC\nAPI\nAPO\nAPR\nAR\nARC\nASAP\nASCII/SM\nASL/M\nASPCA\nATM/M\nATP/M\nATV\nAV\nAVI\nAWACS/M\nAWOL/M\nAZ/M\nAZT/M\nAachen/M\nAaliyah/M\nAaron/M\nAbbas/M\nAbbasid/M\nAbbott/M\nAbby/M\nAbdul/M\nAbe/M\nAbel/M\nAbelard/M\nAbelson/M\nAberdeen/M\nAbernathy/M\nAbidjan/M\nAbigail/M\nAbilene/M\nAbner/M\nAborigine/MS\nAbraham/M\nAbram/MS\nAbrams/M\nAbsalom/M\nAbuja/M\nAbyssinia/M\nAbyssinian/M\nAc/M\nAcadia/M\nAcapulco/M\nAccenture/M\nAccra/M\nAcevedo/M\nAchaean/M\nAchebe/M\nAchernar/M\nAcheson/M\nAchilles/M\nAconcagua/M\nAcosta/M\nAcropolis\nAcrux/M\nActaeon/M\nActon/M\nActs/M\nAcuff/M\nAda/SM\nAdam/SM\nAdams/M\nAdan/M\nAdana/M\nAdar/M\nAddams/M\nAdderley/M\nAddie/M\nAddison/M\nAdela/M\nAdelaide/M\nAdele/M\nAdeline/M\nAden/M\nAdenauer/M\nAdhara/M\nAdidas/M\nAdirondack/SM\nAdirondacks/M\nAdkins/M\nAdler/M\nAdm\nAdmiralty\nAdolf/M\nAdolfo/M\nAdolph/M\nAdonis/MS\nAdrenalin/MS\nAdrian/M\nAdriana/M\nAdriatic/M\nAdrienne/M\nAdvent/MS\nAdventist/MS\nAdvil/M\nAegean/M\nAelfric/M\nAeneas/M\nAeneid/M\nAeolus/M\nAeroflot/M\nAeschylus/M\nAesculapius/M\nAesop/M\nAfghan/SM\nAfghani/M\nAfghanistan/M\nAfr\nAfrica/M\nAfrican/SM\nAfrikaans/M\nAfrikaner/SM\nAfro/SM\nAfrocentric\nAfrocentrism/M\nAg/M\nAgamemnon/M\nAgana\nAgassi/M\nAgassiz/M\nAgatha/M\nAggie/M\nAglaia/M\nAgnes/M\nAgnew/M\nAgni/M\nAgra/M\nAgricola/M\nAgrippa/M\nAgrippina/M\nAguascalientes\nAguilar/M\nAguinaldo/M\nAguirre/M\nAgustin/M\nAhab/M\nAhmad/M\nAhmadabad/M\nAhmadinejad/M\nAhmed/M\nAhriman/M\nAida/M\nAiken/M\nAileen/M\nAimee/M\nAinu/M\nAiredale/MS\nAires/M\nAisha/M\nAjax/M\nAkbar/M\nAkhmatova/M\nAkihito/M\nAkita/M\nAkiva/M\nAkkad/M\nAkron/M\nAl/M\nAla/S\nAlabama/M\nAlabaman/MS\nAlabamian/SM\nAladdin/M\nAlamo/M\nAlamogordo/M\nAlan/M\nAlana/M\nAlar/M\nAlaric/M\nAlaska/M\nAlaskan/MS\nAlba/M\nAlbania/M\nAlbanian/MS\nAlbany/M\nAlbee/M\nAlberio/M\nAlbert/M\nAlberta/M\nAlbertan\nAlberto/M\nAlbigensian/M\nAlbion/M\nAlbireo/M\nAlbuquerque/M\nAlcatraz/M\nAlcestis/M\nAlcibiades/M\nAlcindor/M\nAlcmena/M\nAlcoa/M\nAlcott/M\nAlcuin/M\nAlcyone/M\nAldan/M\nAldebaran/M\nAlden/M\nAlderamin/M\nAldo/M\nAldrin/M\nAlec/M\nAleichem/M\nAlejandra/M\nAlejandro/M\nAlembert/M\nAleppo/M\nAleut/MS\nAleutian/SM\nAlex/M\nAlexander/MS\nAlexandra/M\nAlexandria/M\nAlexandrian\nAlexei/M\nAlexis/M\nAlfonso/M\nAlfonzo/M\nAlford/M\nAlfred/M\nAlfreda/M\nAlfredo/M\nAlgenib/M\nAlger/M\nAlgeria/M\nAlgerian/SM\nAlgieba/M\nAlgiers/M\nAlgol/M\nAlgonquian/SM\nAlgonquin/MS\nAlhambra/M\nAlhena/M\nAli/M\nAlice/M\nAlicia/M\nAlighieri/M\nAline/M\nAlioth/M\nAlisa/M\nAlisha/M\nAlison/M\nAlissa/M\nAlistair/M\nAlkaid/M\nAllah/M\nAllahabad/M\nAllan/M\nAlleghenies/M\nAllegheny/SM\nAllegra/M\nAllen/M\nAllende/M\nAllentown/M\nAllhallows/M\nAllie/MS\nAllison/M\nAllstate/M\nAllyson/M\nAlma/M\nAlmach/M\nAlmaty/M\nAlmighty/M\nAlmohad/M\nAlmoravid/M\nAlnilam/M\nAlnitak/M\nAlonzo/M\nAlpert/M\nAlphard/M\nAlphecca/M\nAlpheratz/M\nAlphonse/M\nAlphonso/M\nAlpine/M\nAlpo/M\nAlps/M\nAlsace/M\nAlsatian/SM\nAlsop/M\nAlston/M\nAlta/M\nAltai/M\nAltaic/M\nAltair/M\nAltamira/M\nAlthea/M\nAltiplano/M\nAltman/M\nAltoids/M\nAlton/M\nAludra/M\nAlva/M\nAlvarado/M\nAlvarez/M\nAlvaro/M\nAlvin/M\nAlyce/M\nAlyson/M\nAlyssa/M\nAlzheimer/M\nAm/MNR\nAmadeus/M\nAmado/M\nAmalia/M\nAmanda/M\nAmarillo/M\nAmaru/M\nAmaterasu/M\nAmati/M\nAmazon/SM\nAmazonian\nAmber/M\nAmelia/M\nAmen/M\nAmenhotep/M\nAmerasian/M\nAmerica/SM\nAmerican/MS\nAmericana/M\nAmericanism/MS\nAmericanization/MS\nAmericanize/GDS\nAmerind/SM\nAmerindian/MS\nAmeslan/M\nAmharic/M\nAmherst/M\nAmie/M\nAmiga/M\nAmish/M\nAmman/M\nAmoco/M\nAmos/M\nAmparo/M\nAmpere/M\nAmritsar/M\nAmsterdam/M\nAmtrak/M\nAmundsen/M\nAmur/M\nAmway/M\nAmy/M\nAna/M\nAnabaptist/M\nAnabel/M\nAnacin/M\nAnacreon/M\nAnaheim/M\nAnalects/M\nAnanias/M\nAnasazi/M\nAnastasia/M\nAnatole/M\nAnatolia/M\nAnatolian/M\nAnaxagoras/M\nAnchorage/M\nAndalusia/M\nAndalusian/M\nAndaman/M\nAndean/M\nAndersen/M\nAnderson/M\nAndes/M\nAndorra/M\nAndorran/SM\nAndre/MS\nAndrea/M\nAndrei/M\nAndres/M\nAndretti/M\nAndrew/SM\nAndrews/M\nAndrianampoinimerina/M\nAndroid/M\nAndromache/M\nAndromeda/M\nAndropov/M\nAndy/M\nAngara/M\nAngel/M\nAngela/M\nAngeles/M\nAngelia/M\nAngelica/M\nAngelico/M\nAngelina/M\nAngeline/M\nAngelique/M\nAngelita/M\nAngelo/M\nAngelou/M\nAngevin/M\nAngie/M\nAngkor/M\nAngle/MS\nAnglia/M\nAnglican/SM\nAnglicanism/MS\nAnglicism/MS\nAnglicization\nAnglicize\nAnglo/M\nAnglophile/M\nAnglophobe\nAngola/M\nAngolan/MS\nAngora/SM\nAngstrom/M\nAnguilla/M\nAngus/M\nAniakchak/M\nAnibal/M\nAnita/M\nAnkara/M\nAnn/M\nAnna/M\nAnnabel/M\nAnnabelle/M\nAnnam/M\nAnnapolis/M\nAnnapurna/M\nAnne/M\nAnnette/M\nAnnie/M\nAnnmarie/M\nAnnunciation/SM\nAnouilh/M\nAnselm/M\nAnselmo/M\nAnshan/M\nAntaeus/M\nAntananarivo/M\nAntarctic/M\nAntarctica/M\nAntares/M\nAnthony/M\nAnthropocene\nAntichrist/SM\nAntietam/M\nAntigone/M\nAntigua/M\nAntillean\nAntilles/M\nAntioch/M\nAntipas/M\nAntipodes\nAntofagasta/M\nAntoine/M\nAntoinette/M\nAnton/M\nAntone/M\nAntonia/M\nAntoninus/M\nAntonio/M\nAntonius/M\nAntony/M\nAntwan/M\nAntwerp/M\nAnubis/M\nAnzac/M\nApache/SM\nApalachicola/M\nApatosaurus\nApennines/M\nAphrodite/M\nApia/M\nApocalypse/M\nApocrypha/M\nApollinaire/M\nApollo/SM\nApollonian/M\nAppalachia/M\nAppalachian/SM\nAppalachians/M\nAppaloosa/SM\nApple/M\nAppleseed/M\nAppleton/M\nAppomattox/M\nApr/M\nApril/MS\nApuleius/M\nAquafresh/M\nAquarian\nAquarius/MS\nAquila/M\nAquinas/M\nAquino/M\nAquitaine/M\nAr/M\nAra/M\nArab/SM\nArabia/M\nArabian/MS\nArabic/M\nArabist/MS\nAraby/M\nAraceli/M\nArafat/M\nAragon\nAraguaya/M\nAral/M\nAramaic/M\nAramco/M\nArapaho/MS\nArapahoes\nArarat/M\nAraucanian/M\nArawak/M\nArawakan/M\nArbitron/M\nArcadia/M\nArcadian/M\nArchean/M\nArchibald/M\nArchie/M\nArchimedes/M\nArctic/M\nArcturus/M\nArdabil\nArden/M\nArequipa/M\nAres/M\nArgentina/M\nArgentine/M\nArgentinean\nArgentinian/MS\nArgo/SM\nArgonaut/MS\nArgonne/M\nArgos/M\nArgus/M\nAriadne/M\nArianism/M\nAriel/M\nAries/MS\nAriosto/M\nAristarchus/M\nAristides/M\nAristophanes/M\nAristotelian/M\nAristotle/M\nArius/M\nAriz\nArizona/M\nArizonan/SM\nArizonian/MS\nArjuna/M\nArk/M\nArkansan/MS\nArkansas/M\nArkhangelsk/M\nArkwright/M\nArlene/M\nArline/M\nArlington/M\nArmageddon/SM\nArmagnac/M\nArmand/M\nArmando/M\nArmani/M\nArmenia/M\nArmenian/SM\nArminius/M\nArmonk/M\nArmour/M\nArmstrong/M\nArneb/M\nArnhem/M\nArno/M\nArnold/M\nArnulfo/M\nAron/M\nArrhenius/M\nArron/M\nArt/M\nArtaxerxes/M\nArtemis/M\nArthur/M\nArthurian/M\nArtie/M\nArturo/M\nAruba/M\nAryan/MS\nAs/M\nAsama/M\nAscella/M\nAscension/M\nAsgard/M\nAshanti/M\nAshcroft/M\nAshe/M\nAshgabat\nAshikaga/M\nAshkenazim/M\nAshkhabad/M\nAshlee/M\nAshley/M\nAshmolean/M\nAshurbanipal/M\nAsia/M\nAsiago\nAsian/MS\nAsiatic/SM\nAsimov/M\nAsmara/M\nAsoka/M\nAspell/M\nAspen/M\nAsperger/M\nAspidiske/M\nAsquith/M\nAssad/M\nAssam/M\nAssamese/M\nAssembly\nAssisi/M\nAssyria/M\nAssyrian/SM\nAstaire/M\nAstana/M\nAstarte/M\nAston/M\nAstor/M\nAstoria/M\nAstrakhan/M\nAstroTurf/M\nAsturias/M\nAsuncion/M\nAswan/M\nAt/SM\nAtacama/M\nAtahualpa/M\nAtalanta/M\nAtari/M\nAtaturk/M\nAthabasca/M\nAthabaskan/SM\nAthanasius\nAthena/M\nAthene/M\nAthenian/SM\nAthens/M\nAtkins/M\nAtkinson/M\nAtlanta/M\nAtlantes\nAtlantic/M\nAtlantis/M\nAtlas/MS\nAtman/M\nAtreus/M\nAtria/M\nAtropos/M\nAttic/M\nAttica/M\nAttila/M\nAttlee/M\nAttn\nAttucks/M\nAtwood/M\nAu/M\nAubrey/M\nAuckland/M\nAuden/M\nAudi/M\nAudion/M\nAudra/M\nAudrey/M\nAudubon/M\nAug/M\nAugean/M\nAugsburg/M\nAugust/MS\nAugusta/M\nAugustan/M\nAugustine/M\nAugustinian/MS\nAugustus/M\nAurangzeb/M\nAurelia/M\nAurelio/M\nAurelius/M\nAureomycin/M\nAuriga/M\nAurora/M\nAuschwitz/M\nAussie/MS\nAusten/M\nAusterlitz/M\nAustin/MS\nAustralasia/M\nAustralasian\nAustralia/M\nAustralian/SM\nAustraloid/M\nAustralopithecus/M\nAustria/M\nAustrian/SM\nAustronesian/M\nAutumn/M\nAv/M\nAva/M\nAvalon/M\nAve/M\nAventine/M\nAvernus/M\nAverroes/M\nAvery/M\nAvesta/M\nAvicenna/M\nAvignon/M\nAvila/M\nAvior/M\nAvis/M\nAvogadro/M\nAvon/M\nAxis\nAxum/M\nAyala/M\nAyers/M\nAymara/M\nAyrshire/M\nAyurveda/M\nAyyubid/M\nAzana/M\nAzania/M\nAzazel/M\nAzerbaijan/M\nAzerbaijani/MS\nAzores/M\nAzov/M\nAztec/SM\nAztecan/M\nAztlan/M\nB/MNT\nBA/M\nBASIC/SM\nBB/M\nBBB/M\nBBC/M\nBBQ\nBBS\nBBSes\nBC/M\nBFF\nBIA\nBIOS\nBITNET\nBLT/SM\nBM/M\nBMW/M\nBO\nBP/M\nBPOE\nBR\nBS/M\nBSA\nBSD/SM\nBTU\nBTW\nBYOB\nBa/M\nBaal/SM\nBaath/M\nBaathist/M\nBabbage/M\nBabbitt/M\nBabel/MS\nBabylon/MS\nBabylonia/M\nBabylonian/SM\nBacall/M\nBacardi/M\nBacchanalia/M\nBacchic\nBacchus/M\nBach/M\nBackus/M\nBacon/M\nBactria/M\nBaden/M\nBadlands/M\nBaedeker/MS\nBaez/M\nBaffin/M\nBaggies/M\nBaghdad/M\nBaguio/M\nBaha'i/M\nBaha'ullah/M\nBahama/SM\nBahamanian\nBahamas/M\nBahamian/MS\nBahia/M\nBahrain/M\nBaikal/M\nBailey/M\nBaird/M\nBakelite/M\nBaker/M\nBakersfield/M\nBaku/M\nBakunin/M\nBalanchine/M\nBalaton/M\nBalboa/M\nBalder/M\nBaldwin/SM\nBalearic/M\nBalfour/M\nBali/M\nBalinese/M\nBalkan/MS\nBalkans/M\nBalkhash/M\nBall/M\nBallard/M\nBalthazar/M\nBaltic/M\nBaltimore/M\nBaluchistan/M\nBalzac/M\nBamako/M\nBambi/M\nBanach/M\nBancroft/M\nBandung/M\nBangalore/M\nBangkok/M\nBangladesh/M\nBangladeshi/SM\nBangor/M\nBangui/M\nBanjarmasin/M\nBanjul/M\nBanks/M\nBanneker/M\nBannister/M\nBanting/M\nBantu/MS\nBaotou/M\nBaptist/SM\nBaptiste/M\nBarabbas/M\nBarack/M\nBarbadian/SM\nBarbados/M\nBarbara/M\nBarbarella/M\nBarbarossa/M\nBarbary/M\nBarber/M\nBarbie/M\nBarbour/M\nBarbra/M\nBarbuda/M\nBarcelona/M\nBarclay/SM\nBarclays/M\nBardeen/M\nBarents/M\nBarker/M\nBarkley/M\nBarlow/M\nBarnabas/M\nBarnaby/M\nBarnard/M\nBarnaul/M\nBarnes/M\nBarnett/M\nBarney/M\nBarnum/M\nBaroda/M\nBarquisimeto/M\nBarr/M\nBarranquilla/M\nBarrera/M\nBarrett/M\nBarrie/M\nBarron/M\nBarry/M\nBarrymore/M\nBart/M\nBarth/MS\nBartholdi/M\nBartholomew/M\nBartlett/M\nBartok/M\nBarton/M\nBaruch/M\nBaryshnikov/M\nBasel/M\nBasho/M\nBasie/M\nBasil/M\nBasque/MS\nBasra/M\nBass/M\nBasseterre/M\nBastille/M\nBasutoland/M\nBataan/M\nBates/M\nBathsheba/M\nBatista/M\nBatman/M\nBattle/M\nBatu/M\nBaudelaire/M\nBaudouin/M\nBaudrillard/M\nBauer/M\nBauhaus/M\nBaum/M\nBavaria/M\nBavarian/M\nBaxter/M\nBayamon\nBayer/M\nBayes/M\nBayesian/M\nBayeux/M\nBaylor/M\nBayonne/M\nBayreuth/M\nBaywatch/M\nBe/MH\nBeach/M\nBeadle/M\nBean/M\nBeard/M\nBeardmore/M\nBeardsley/M\nBearnaise/M\nBeasley/M\nBeatlemania/M\nBeatles/M\nBeatrice/M\nBeatrix/M\nBeatriz/M\nBeatty/M\nBeau/M\nBeaufort/M\nBeaujolais/M\nBeaumarchais/M\nBeaumont/M\nBeauregard/M\nBeauvoir/M\nBechtel/M\nBeck/MR\nBecker/M\nBecket/M\nBeckett/M\nBecky/M\nBecquerel/M\nBede/M\nBedouin/SM\nBeebe/M\nBeecher/M\nBeefaroni/M\nBeelzebub/M\nBeerbohm/M\nBeethoven/M\nBeeton/M\nBegin/M\nBehan/M\nBehring/M\nBeiderbecke/M\nBeijing/M\nBeirut/M\nBekesy/M\nBela/M\nBelarus/M\nBelau/M\nBelem/M\nBelfast/M\nBelg\nBelgian/SM\nBelgium/M\nBelgrade/M\nBelinda/M\nBelize/M\nBell/M\nBella/M\nBellamy/M\nBellatrix/M\nBelleek/M\nBellini/M\nBellow/M\nBelmont/M\nBelmopan/M\nBelorussian/MS\nBelshazzar/M\nBeltane/M\nBelushi/M\nBen/M\nBenacerraf/M\nBenchley/M\nBender/M\nBendix/M\nBenedict/M\nBenedictine/MS\nBenelux/M\nBenet/M\nBenetton/M\nBengal/SM\nBengali/M\nBenghazi/M\nBenin/M\nBeninese/M\nBenita/M\nBenito/M\nBenjamin/M\nBennett/M\nBennie/M\nBenny/M\nBenson/M\nBentham/M\nBentley/M\nBenton/M\nBenz/M\nBenzedrine/M\nBeowulf/M\nBerber/SM\nBerenice/M\nBeretta/M\nBerg/MNR\nBergen/M\nBerger/M\nBergerac/M\nBergman/M\nBergson/M\nBeria/M\nBering/M\nBerkeley/M\nBerkshire/SM\nBerkshires/M\nBerle/M\nBerlin/SZMR\nBerliner/M\nBerlioz/M\nBerlitz/M\nBermuda/SM\nBermudan/SM\nBermudian/SM\nBern/M\nBernadette/M\nBernadine/M\nBernanke/M\nBernard/M\nBernardo/M\nBernays/M\nBernbach/M\nBernese\nBernhardt/M\nBernice/M\nBernie/M\nBernini/M\nBernoulli/M\nBernstein/M\nBerra/M\nBerry/M\nBert/M\nBerta/M\nBertelsmann/M\nBertha/M\nBertie/M\nBertillon/M\nBertram/M\nBertrand/M\nBeryl/M\nBerzelius/M\nBess/M\nBessel/M\nBessemer/M\nBessie/M\nBest/M\nBetelgeuse/M\nBeth/M\nBethany/M\nBethe/M\nBethesda/M\nBethlehem/M\nBethune/M\nBetsy/M\nBette/M\nBettie/M\nBetty/M\nBettye/M\nBeulah/M\nBeveridge\nBeverley/M\nBeverly/M\nBeyer/M\nBharat/M\nBhopal/M\nBhutan/M\nBhutanese/M\nBhutto/M\nBi/M\nBialystok/M\nBianca/M\nBib\nBible/MS\nBic/M\nBiddle/M\nBiden/M\nBierce/M\nBigfoot/M\nBiggles/M\nBiko/M\nBilbao/M\nBilbo/M\nBill/MJ\nBillie/M\nBillings/M\nBilly/M\nBimini/M\nBioko/M\nBird/M\nBirdseye/M\nBirkenstock/M\nBirmingham/M\nBiro/M\nBiscay/M\nBiscayne/M\nBishkek/M\nBishop/M\nBismarck/M\nBismark/M\nBisquick/M\nBissau/M\nBitTorrent/M\nBizet/M\nBjerknes/M\nBjork/M\nBk/M\nBlackBerry/M\nBlackbeard/M\nBlackburn/M\nBlackfeet/M\nBlackfoot/M\nBlackpool/M\nBlackshirt/M\nBlackstone/M\nBlackwell/M\nBlaine/M\nBlair/M\nBlake/M\nBlanca/M\nBlanchard/M\nBlanche/M\nBlankenship/M\nBlantyre/M\nBlatz/M\nBlavatsky/M\nBlenheim/M\nBlevins/M\nBligh/M\nBloch/M\nBlockbuster/M\nBloemfontein/M\nBlondel/M\nBlondie/M\nBloom/MR\nBloomer/M\nBloomfield/M\nBloomingdale/M\nBloomsbury/M\nBlu\nBlucher/M\nBluebeard/M\nBluetooth/M\nBlvd\nBlythe/M\nBoadicea\nBoas/M\nBob/M\nBobbi/M\nBobbie/M\nBobbitt/M\nBobby/M\nBoccaccio/M\nBodhidharma/M\nBodhisattva/M\nBodleian\nBoeing/M\nBoeotia/M\nBoeotian/M\nBoer/SM\nBoethius/M\nBogart/M\nBogota/M\nBohemia/M\nBohemian/SM\nBohr/M\nBoise/M\nBojangles/M\nBoleyn/M\nBolivar/M\nBolivia/M\nBolivian/MS\nBollywood/M\nBologna/M\nBolshevik/SM\nBolshevism/M\nBolshevist/M\nBolshoi/M\nBolton/M\nBoltzmann/M\nBombay/M\nBonaparte/M\nBonaventure/M\nBond/M\nBonhoeffer/M\nBoniface/M\nBonita/M\nBonn/MR\nBonner/M\nBonneville/M\nBonnie/M\nBono/M\nBooker/M\nBoole/M\nBoolean/M\nBoone/M\nBootes/M\nBooth/M\nBordeaux/M\nBorden/M\nBordon/M\nBoreas/M\nBorg/SM\nBorges/M\nBorgia/M\nBorglum/M\nBoris/M\nBork/M\nBorlaug/M\nBorn/M\nBorneo/M\nBorobudur/M\nBorodin/M\nBoru/M\nBosch/M\nBose/M\nBosnia/M\nBosnian\nBosporus/M\nBoston/MS\nBostonian/M\nBoswell/M\nBotox\nBotswana/M\nBotticelli/M\nBoulder/M\nBoulez/M\nBourbaki/M\nBourbon/SM\nBournemouth/M\nBovary/M\nBowditch/M\nBowell/M\nBowen/M\nBowers/M\nBowery/M\nBowie/M\nBowman/M\nBoyd/M\nBoyer/M\nBoyle/M\nBr/MT\nBrad/MY\nBradbury/M\nBraddock/M\nBradford/M\nBradley/M\nBradly/M\nBradshaw/M\nBradstreet/M\nBrady/M\nBragg/M\nBrahe/M\nBrahma/MS\nBrahmagupta/M\nBrahman/MS\nBrahmani\nBrahmanism/SM\nBrahmaputra/M\nBrahms/M\nBraille/MS\nBrain/M\nBrampton/M\nBran/M\nBranch/M\nBrandeis/M\nBranden/M\nBrandenburg/M\nBrandi/M\nBrandie/M\nBrando/M\nBrandon/M\nBrandt/M\nBrandy/M\nBrant/M\nBraque/M\nBrasilia/M\nBratislava/M\nBrattain/M\nBray/M\nBrazil/M\nBrazilian/MS\nBrazos/M\nBrazzaville/M\nBreakspear/M\nBreathalyzer\nBrecht/M\nBreckenridge/M\nBremen/M\nBrenda/M\nBrendan/M\nBrennan/M\nBrenner/M\nBrent/M\nBrenton/M\nBrest/M\nBret/M\nBreton/M\nBrett/M\nBrewer/M\nBrewster/M\nBrezhnev/M\nBrian/M\nBriana/M\nBrianna/M\nBrice/M\nBridalveil/M\nBridgeport/M\nBridger/M\nBridges/M\nBridget/M\nBridgetown/M\nBridgett/M\nBridgette/M\nBridgman/M\nBrie/SM\nBrigadoon/M\nBriggs/M\nBrigham/M\nBright/M\nBrighton/M\nBrigid/M\nBrigitte/M\nBrillo/M\nBrinkley/M\nBrisbane/M\nBristol/M\nBrit/SM\nBritain/M\nBritannia/M\nBritannic/M\nBritannica/M\nBriticism/SM\nBritish/MRZ\nBritisher/M\nBritney/M\nBriton/MS\nBritt/MN\nBrittany/SM\nBritten/M\nBrittney/M\nBrno/M\nBroadway/SM\nBrobdingnag/M\nBrobdingnagian/M\nBrock/M\nBrokaw/M\nBronson/M\nBronte/M\nBrontosaurus\nBronx/M\nBrooke/MS\nBrooklyn/M\nBrooks/M\nBros\nBrown/MG\nBrowne/M\nBrownian/M\nBrownie/S\nBrowning/M\nBrownshirt/M\nBrownsville/M\nBrubeck/M\nBruce/M\nBruckner/M\nBruegel\nBrummel/M\nBrunei/M\nBruneian/MS\nBrunelleschi/M\nBrunhilde/M\nBruno/M\nBrunswick/M\nBrussels/M\nBrut/M\nBrutus/M\nBryan/M\nBryant/M\nBryce/M\nBrynner/M\nBryon/M\nBrzezinski/M\nBtu/M\nBuber/M\nBuchanan/M\nBucharest/M\nBuchenwald/M\nBuchwald/M\nBuck/M\nBuckingham/M\nBuckley/M\nBuckner/M\nBud/M\nBudapest/M\nBuddha/SM\nBuddhism/SM\nBuddhist/SM\nBuddy/M\nBudweiser/M\nBuffalo/M\nBuffy/M\nBuford/M\nBugatti/M\nBugzilla/M\nBuick/M\nBujumbura/M\nBukhara/M\nBukharin/M\nBulawayo/M\nBulfinch/M\nBulganin/M\nBulgar/M\nBulgari/M\nBulgaria/M\nBulgarian/SM\nBullock/M\nBullwinkle/M\nBultmann/M\nBumppo/M\nBunche/M\nBundesbank/M\nBundestag/M\nBunin/M\nBunker/M\nBunsen/M\nBunuel/M\nBunyan/M\nBurbank/M\nBurberry/M\nBurch/M\nBurger/M\nBurgess/M\nBurgoyne/M\nBurgundian/M\nBurgundy/SM\nBurke/M\nBurks/M\nBurl/M\nBurlington/M\nBurma/M\nBurmese/M\nBurnett/M\nBurns/M\nBurnside/M\nBurr/M\nBurris/M\nBurroughs/M\nBursa/M\nBurt/M\nBurton/M\nBurundi/M\nBurundian/MS\nBusch/M\nBush/M\nBushido/M\nBushnell/M\nButler/M\nButterfingers/M\nBuxtehude/M\nByblos/M\nByers/M\nByrd/M\nByron/M\nByronic/M\nByzantine/MS\nByzantium/M\nC/SM\nCA\nCAD/M\nCAI\nCAM\nCAP\nCARE\nCATV\nCB\nCBC/M\nCBS/M\nCCTV\nCCU\nCD/M\nCDC\nCDT\nCEO/M\nCF\nCFC/M\nCFO\nCGI\nCIA/M\nCID\nCNN/M\nCNS/M\nCO/M\nCOBOL/SM\nCOD\nCOL\nCOLA\nCPA/M\nCPI/M\nCPO\nCPR/M\nCPU/M\nCRT/SM\nCST/M\nCT/M\nCV\nCVS/M\nCZ\nCa/M\nCabernet/M\nCabot/M\nCabral/M\nCabrera/M\nCabrini/M\nCadette\nCadillac/M\nCadiz/M\nCaedmon/M\nCaerphilly/M\nCaesar/SM\nCage/M\nCagney/M\nCahokia/M\nCaiaphas/M\nCain/SM\nCairo/M\nCaitlin/M\nCajun/MS\nCal/M\nCalais/M\nCalcutta/M\nCalder/M\nCalderon/M\nCaldwell/M\nCaleb/M\nCaledonia/M\nCalgary/M\nCalhoun/M\nCali/M\nCaliban/M\nCalif\nCalifornia/M\nCalifornian/SM\nCaligula/M\nCallaghan/M\nCallahan/M\nCallao/M\nCallas/M\nCallie/M\nCalliope/M\nCallisto/M\nCaloocan/M\nCalvary/M\nCalvert/M\nCalvin/M\nCalvinism/MS\nCalvinist/MS\nCalvinistic\nCamacho/M\nCambodia/M\nCambodian/SM\nCambrian/SM\nCambridge/M\nCamden/M\nCamel/M\nCamelopardalis/M\nCamelot/MS\nCamembert/MS\nCameron/M\nCameroon/SM\nCameroonian/MS\nCamilla/M\nCamille/M\nCamoens/M\nCampanella/M\nCampbell/M\nCampinas/M\nCampos/M\nCamry/M\nCamus/M\nCan/M\nCanaan/M\nCanaanite/MS\nCanad\nCanada/M\nCanadian/SM\nCanadianism\nCanaletto/M\nCanaries/M\nCanaveral/M\nCanberra/M\nCancer/SM\nCancun/M\nCandace/M\nCandice/M\nCandide/M\nCandy/M\nCannes/M\nCannon/M\nCanon/M\nCanopus/M\nCantabrigian/M\nCanterbury/M\nCanton/M\nCantonese/M\nCantor/M\nCantrell/M\nCantu/M\nCanute/M\nCapablanca/M\nCapek/M\nCapella/M\nCapet/M\nCapetian/M\nCapetown/M\nCaph/M\nCapistrano/M\nCapitol/SM\nCapitoline/M\nCapone/M\nCapote/M\nCapra/M\nCapri/M\nCapricorn/MS\nCapt\nCapuchin/M\nCapulet/M\nCara/M\nCaracalla/M\nCaracas/M\nCaravaggio/M\nCarboloy/M\nCarboniferous/M\nCarborundum/M\nCardenas/M\nCardiff/M\nCardin/M\nCardozo/M\nCarey/M\nCarib/MS\nCaribbean/MS\nCarina/M\nCarissa/M\nCarl/M\nCarla/M\nCarlene/M\nCarlin/M\nCarlo/MS\nCarlos/M\nCarlsbad/M\nCarlson/M\nCarlton/M\nCarly/M\nCarlyle/M\nCarmela/M\nCarmella/M\nCarmelo/M\nCarmen/M\nCarmichael/M\nCarmine/M\nCarnap/M\nCarnation/M\nCarnegie/M\nCarney/M\nCarnot/M\nCarol/M\nCarole/M\nCarolina/M\nCaroline/M\nCarolingian/M\nCarolinian/M\nCarolyn/M\nCarpathian/SM\nCarpathians/M\nCarpenter/M\nCarr/M\nCarranza/M\nCarrie/RM\nCarrier/M\nCarrillo/M\nCarroll/M\nCarson/M\nCarter/M\nCartesian/M\nCarthage/M\nCarthaginian/MS\nCartier/M\nCartwright/M\nCaruso/M\nCarver/M\nCary/M\nCasablanca/M\nCasals/M\nCasandra/M\nCasanova/SM\nCascades/M\nCase/M\nCasey/M\nCash/M\nCasio/M\nCaspar/M\nCaspian/M\nCassandra/SM\nCassatt/M\nCassidy/M\nCassie/M\nCassiopeia/M\nCassius/M\nCastaneda/M\nCastilian\nCastillo/M\nCastlereagh/M\nCastor/M\nCastries/M\nCastro/M\nCatalan/SM\nCatalina/M\nCatalonia/M\nCatawba/M\nCaterpillar/M\nCathay/M\nCather/M\nCatherine/M\nCathleen/M\nCatholic/MS\nCatholicism/MS\nCathryn/M\nCathy/M\nCatiline/M\nCato/M\nCatskill/SM\nCatskills/M\nCatt/M\nCatullus/M\nCaucasian/MS\nCaucasoid\nCaucasus/M\nCauchy/M\nCavendish/M\nCavour/M\nCaxton/M\nCayenne/M\nCayman/M\nCayuga/SM\nCayuse\nCb\nCd/M\nCe/M\nCeausescu/M\nCebu/M\nCebuano/M\nCecelia/M\nCecil/M\nCecile/M\nCecilia/M\nCecily/M\nCedric/M\nCeleste/M\nCelia/M\nCelina/M\nCellini/M\nCelsius/M\nCelt/SM\nCeltic/SM\nCenozoic/M\nCentaurus/M\nCentigrade\nCentral\nCepheid/M\nCepheus/M\nCerberus/M\nCerenkov/M\nCeres/M\nCerf/M\nCervantes/M\nCesar/M\nCesarean/M\nCessna/M\nCetus/M\nCeylon/M\nCeylonese\nCezanne/M\nCf/M\nCh'in/M\nCh/N\nChablis/M\nChad/M\nChadian/MS\nChadwick/M\nChagall/M\nChaitanya/M\nChaitin/M\nChaldea\nChaldean/M\nChallenger/M\nChalmers\nChamberlain/M\nChambers/M\nChamplain/M\nChampollion/M\nChan/M\nChance/M\nChancellorsville/M\nChandigarh/M\nChandler/M\nChandon/M\nChandra/M\nChandragupta/M\nChandrasekhar/M\nChanel/M\nChaney/M\nChang/M\nChangchun/M\nChangsha/M\nChantilly/M\nChaplin/M\nChaplinesque\nChapman/M\nChappaquiddick/M\nChapultepec/M\nCharbray/M\nChardonnay/M\nCharity/M\nCharlemagne/M\nCharlene/M\nCharles/M\nCharleston/MS\nCharley/M\nCharlie/M\nCharlotte/M\nCharlottetown/M\nCharmaine/M\nCharmin/M\nCharolais/M\nCharon/M\nChartism/M\nChartres/M\nCharybdis/M\nChase/M\nChasity/M\nChateaubriand/M\nChattahoochee/M\nChattanooga/M\nChatterley/M\nChatterton/M\nChaucer/M\nChauncey/M\nChautauqua/M\nChavez/M\nChayefsky/M\nChe/M\nChechen/M\nChechnya/M\nCheddar/M\nCheer/M\nCheerios/M\nCheetos/M\nCheever/M\nChekhov/M\nChekhovian\nChelsea/M\nChelyabinsk/M\nChen/M\nCheney/M\nChengdu/M\nChennai/M\nCheops/M\nCheri/M\nCherie/M\nChernenko/M\nChernobyl/M\nChernomyrdin/M\nCherokee/MS\nCherry/M\nCheryl/M\nChesapeake/M\nCheshire/M\nChester/M\nChesterfield/M\nChesterton/M\nChevalier/M\nCheviot/M\nChevrolet/M\nChevron/M\nChevy/M\nCheyenne/SM\nChi/M\nChianti/MS\nChiba/M\nChibcha/M\nChicago/M\nChicagoan/M\nChicana/M\nChicano/M\nChickasaw/MS\nChiclets/M\nChihuahua/MS\nChile/M\nChilean/MS\nChimborazo/M\nChimera/MS\nChimu/M\nChin/M\nChina/M\nChinatown/M\nChinese/M\nChinook/MS\nChipewyan/M\nChippendale/M\nChippewa/SM\nChiquita/M\nChirico/M\nChisholm/M\nChisinau/M\nChittagong/M\nChivas/M\nChloe/M\nChoctaw/SM\nChomsky/M\nChongqing/M\nChopin/M\nChopra/M\nChou/M\nChretien/M\nChris/M\nChrist/MS\nChrista/M\nChristchurch/M\nChristendom/MS\nChristensen/M\nChristi/M\nChristian/SM\nChristianity/SM\nChristianize\nChristie/M\nChristina/M\nChristine/M\nChristlike\nChristmas/MS\nChristmastide/MS\nChristmastime/MS\nChristoper/M\nChristopher/M\nChronicles\nChrysler/M\nChrysostom/M\nChrystal/M\nChuck/M\nChukchi/M\nChumash/M\nChung/M\nChurch/M\nChurchill/M\nChurriguera/M\nChuvash/M\nCi/M\nCicero/M\nCid/M\nCimabue/M\nCincinnati/M\nCinderella/MS\nCindy/M\nCinemaScope/M\nCinerama/M\nCipro/M\nCirce/M\nCisco/M\nCitibank/M\nCitigroup/M\nCitroen/M\nCl/MV\nClaiborne/M\nClair/M\nClaire/M\nClairol/M\nClancy/M\nClapeyron/M\nClapton/M\nClara/M\nClare/M\nClarence/M\nClarendon/M\nClarice/M\nClarissa/M\nClark/M\nClarke/M\nClaude/M\nClaudette/M\nClaudia/M\nClaudine/M\nClaudio/M\nClaudius/M\nClaus/M\nClausewitz/M\nClausius/M\nClay/M\nClayton/M\nClearasil/M\nClem/XM\nClemenceau/M\nClemens/M\nClement/MS\nClementine/M\nClements/M\nClemons/M\nClemson/M\nCleo/M\nCleopatra/M\nCleveland/M\nCliburn/M\nCliff/M\nClifford/M\nClifton/M\nCline/M\nClint/M\nClinton/M\nClio/M\nClive/M\nClorets/M\nClorox/M\nClosure/M\nClotho/M\nClouseau/M\nClovis/M\nClyde/M\nClydesdale/M\nClytemnestra/M\nCm/M\nCmdr\nCo/M\nCobain/M\nCobb/M\nCochabamba/M\nCochin/M\nCochise/M\nCochran/M\nCockney/M\nCocteau/M\nCod\nCody/M\nCoffey/M\nCognac/M\nCohan/M\nCohen/M\nCoimbatore/M\nCointreau/M\nCoke/SM\nCol/M\nColbert/M\nColby/M\nCole/M\nColeen/M\nColeman/M\nColeridge/M\nColette/M\nColfax/M\nColgate/M\nColin/M\nColleen/M\nCollier/M\nCollin/SM\nCollins/M\nColo\nCologne/M\nColombia/M\nColombian/MS\nColombo/M\nColon/M\nColoradan/SM\nColorado/M\nColoradoan\nColosseum/M\nColt/M\nColtrane/M\nColumbia/M\nColumbine/M\nColumbus/M\nCom\nComanche/MS\nCombs/M\nComdr\nComintern/M\nCommons/M\nCommonwealth\nCommunion/SM\nCommunism\nCommunist/SM\nComo/M\nComoran\nComoros/M\nCompaq/M\nCompton/M\nCompuServe/M\nComte/M\nConakry/M\nConan/M\nConcepcion/M\nConcetta/M\nConcord/SM\nConcorde/M\nCondillac/M\nCondorcet/M\nConestoga/M\nConfederacy/M\nConfederate/MS\nConfucian/SM\nConfucianism/MS\nConfucius/M\nCong/M\nCongo/M\nCongolese/M\nCongregational\nCongregationalist/MS\nCongress/MS\nCongressional\nCongreve/M\nConley/M\nConn/MR\nConnecticut/M\nConnemara/M\nConner/M\nConnery/M\nConnie/M\nConnolly/M\nConnors/M\nConrad/M\nConrail/M\nConservative\nConstable/M\nConstance/M\nConstantine/M\nConstantinople/M\nConstitution\nConsuelo/M\nContinent/M\nContinental/M\nContreras/M\nConway/M\nCook/M\nCooke/M\nCooley/M\nCoolidge/M\nCooper/M\nCooperstown/M\nCoors/M\nCopacabana/M\nCopeland/M\nCopenhagen/M\nCopernican/M\nCopernicus/M\nCopland/M\nCopley/M\nCopperfield/M\nCoppertone/M\nCoppola/M\nCoptic/M\nCora/M\nCordelia/M\nCordilleras/M\nCordoba/M\nCorey/M\nCorfu/M\nCorina/M\nCorine/M\nCorinne/M\nCorinth/M\nCorinthian/MS\nCorinthians/M\nCoriolanus/M\nCoriolis/M\nCork\nCorleone/M\nCormack/M\nCorneille/M\nCornelia/M\nCornelius/M\nCornell/M\nCorning/M\nCornish/MS\nCornwall/M\nCornwallis/M\nCoronado/M\nCorot/M\nCorp\nCorreggio/M\nCorrine/M\nCorsica/M\nCorsican/M\nCortes/MS\nCortland/M\nCorvallis/M\nCorvette/M\nCorvus/M\nCory/M\nCosby/M\nCossack/M\nCostco/M\nCostello/M\nCostner/M\nCote/M\nCotonou/M\nCotopaxi/M\nCotswold/M\nCotton/M\nCoulomb/M\nCoulter/M\nCouperin/M\nCourbet/M\nCourtney/M\nCousteau/M\nCoventry/SM\nCoward/M\nCowell/M\nCowley/M\nCowper/M\nCox/M\nCoy/M\nCozumel/M\nCpl\nCr/MT\nCrabbe/M\nCraft/M\nCraig/M\nCranach/M\nCrane/M\nCranmer/M\nCrater/M\nCrawford/M\nCray/M\nCrayola/M\nCreation/M\nCreator/M\nCrecy/M\nCree/DSM\nCreek/SM\nCreighton/M\nCreole/SM\nCreon/M\nCressida/M\nCrest/M\nCretaceous/M\nCretan/SM\nCrete/M\nCrichton/M\nCrick/M\nCrimea/M\nCrimean/M\nCriollo/M\nCrisco/M\nCristina/M\nCroat/SM\nCroatia/M\nCroatian/MS\nCroce/M\nCrockett/M\nCroesus/M\nCromwell/M\nCromwellian/M\nCronin/M\nCronkite/M\nCronus/M\nCrookes/M\nCrosby/M\nCross/M\nCrow/SM\nCrowley/M\nCrucifixion/MS\nCruikshank/M\nCruise/M\nCrusades's\nCrusoe/M\nCrux/M\nCruz/M\nCryptozoic/M\nCrystal/M\nCsonka/M\nCt\nCtesiphon/M\nCthulhu/M\nCu/M\nCuba/M\nCuban/SM\nCuchulain/M\nCuisinart/M\nCulbertson/M\nCullen/M\nCumberland/M\nCummings/M\nCunard/M\nCunningham/M\nCupid/M\nCuracao/M\nCurie/M\nCuritiba/M\nCurrier/M\nCurry/RM\nCurt/M\nCurtis/M\nCuster/M\nCuvier/M\nCuzco/M\nCybele/M\nCyclades/M\nCyclopes/M\nCyclops/M\nCygnus/M\nCymbeline/M\nCynthia/M\nCyprian/M\nCypriot/MS\nCyprus/M\nCyrano/M\nCyril/M\nCyrillic/M\nCyrus/M\nCzech/M\nCzechoslovak\nCzechoslovakia/M\nCzechoslovakian/SM\nCzechs\nCzerny/M\nD/M\nDA/M\nDAR\nDAT/M\nDBMS/M\nDC/M\nDD/M\nDDS/M\nDDT/S\nDE\nDEA\nDEC/SD\nDH\nDHS\nDI\nDJ\nDMCA\nDMD/M\nDMZ\nDNA/M\nDOA\nDOB\nDOD\nDOE\nDOS/M\nDOT\nDP/SM\nDPT\nDST\nDTP\nDUI\nDVD\nDVR/SM\nDWI\nDachau/M\nDacron/SM\nDada/M\nDadaism/M\nDaedalus/M\nDaguerre/M\nDagwood/M\nDahomey/M\nDaimler/M\nDaisy/M\nDakar/M\nDakota/SM\nDakotan/M\nDalai\nDale/M\nDaley/M\nDali/M\nDalian/M\nDallas/M\nDalmatia/M\nDalmatian/SM\nDalton/M\nDamascus/M\nDame/MN\nDamian/M\nDamien/M\nDamion/M\nDamocles/M\nDamon/M\nDan/M\nDana/M\nDanae/M\nDane/SM\nDanelaw/M\nDangerfield/M\nDanial/M\nDaniel/SM\nDanielle/M\nDaniels/M\nDanish/M\nDannie/M\nDanny/M\nDanone/M\nDante/M\nDanton/M\nDanube/M\nDanubian/M\nDaphne/M\nDarby/M\nDarcy/M\nDardanelles/M\nDare/M\nDaren/M\nDarfur/M\nDarin/M\nDario/M\nDarius/M\nDarjeeling/M\nDarla/M\nDarlene/M\nDarling/M\nDarnell/M\nDarrel/M\nDarrell/M\nDarren/M\nDarrin/M\nDarrow/M\nDarryl/M\nDarth/M\nDartmoor/M\nDartmouth/M\nDarvon/M\nDarwin/M\nDarwinian/M\nDarwinism/SM\nDarwinist\nDaryl/M\nDatamation\nDaugherty/M\nDaumier/M\nDavao/M\nDave/M\nDavenport/M\nDavid/MS\nDavidson/M\nDavies/M\nDavis/M\nDavy/SM\nDawes/M\nDawkins\nDawn/M\nDawson/M\nDay/M\nDayan\nDayton/M\nDeGeneres/M\nDeadhead/M\nDean/M\nDeana/M\nDeandre/M\nDeann/M\nDeanna/M\nDeanne/M\nDebbie/M\nDebby/M\nDebian/M\nDebora/M\nDeborah/M\nDebouillet/M\nDebra/M\nDebs/M\nDebussy/M\nDec/M\nDecalogue/M\nDecatur/M\nDecca/M\nDeccan/M\nDecember/SM\nDecker/M\nDedekind/M\nDee/M\nDeena/M\nDeere/M\nDefoe/M\nDegas/M\nDeidre/M\nDeimos/M\nDeirdre/M\nDeity\nDejesus/M\nDel/M\nDelacroix/M\nDelacruz/M\nDelaney/M\nDelano/M\nDelaware/MS\nDelawarean/SM\nDelbert/M\nDeleon/M\nDelgado/M\nDelhi/M\nDelia/M\nDelibes/M\nDelicious/M\nDelilah/M\nDelilahs\nDelius/M\nDell/M\nDella/M\nDelmar/M\nDelmarva/M\nDelmer/M\nDelmonico/M\nDelores/M\nDeloris/M\nDelphi/M\nDelphic/M\nDelphinus/M\nDelta/M\nDem/G\nDemavend/M\nDemerol/M\nDemeter/M\nDemetrius/M\nDeming/M\nDemocrat/SM\nDemocratic\nDemocritus/M\nDemosthenes/M\nDempsey/M\nDena/M\nDenali\nDeneb/M\nDenebola/M\nDeng/M\nDenis/M\nDenise/M\nDenmark/M\nDennis/M\nDenny/M\nDenver/M\nDeon/M\nDepp/M\nDerby/M\nDerek/M\nDerick/M\nDermot/M\nDerrick/M\nDerrida/M\nDescartes/M\nDesdemona/M\nDesiree/M\nDesmond/M\nDetroit/M\nDeuteronomy/M\nDevanagari/M\nDevi/M\nDevin/M\nDevon/M\nDevonian/M\nDewar/M\nDewayne/M\nDewey/M\nDewitt/M\nDexedrine/M\nDexter/M\nDhaka/M\nDhaulagiri/M\nDi/SM\nDiCaprio/M\nDiMaggio/M\nDiaghilev/M\nDial/M\nDiana/M\nDiane/M\nDiann/M\nDianna/M\nDianne/M\nDias\nDiaspora/MS\nDick/XM\nDickens/M\nDickensian\nDickerson/M\nDickinson/M\nDickson/M\nDictaphone/SM\nDiderot/M\nDido/M\nDidrikson/M\nDiefenbaker/M\nDiego/M\nDiem/M\nDietrich/M\nDijkstra/M\nDijon/M\nDilbert/MS\nDillard/M\nDillinger/M\nDillon/M\nDina/M\nDinah/M\nDino/M\nDiocletian/M\nDiogenes/M\nDion/M\nDionne/M\nDionysian/M\nDionysus/M\nDiophantine/M\nDior/M\nDipper/M\nDir\nDirac/M\nDirichlet/M\nDirk/M\nDis/M\nDisney/M\nDisneyland/M\nDisraeli/M\nDivine/M\nDiwali/M\nDix/M\nDixie/M\nDixiecrat/M\nDixieland/SM\nDixon/M\nDjibouti/M\nDmitri/M\nDnepropetrovsk/M\nDniester/M\nDobbin/M\nDoberman/M\nDobro/M\nDoctor\nDoctorow/M\nDodge/M\nDodgson/M\nDodoma/M\nDodson/M\nDoe/M\nDoha/M\nDolby/M\nDole/M\nDollie/M\nDolly/M\nDolores/M\nDomesday/M\nDomingo/M\nDominguez/M\nDominic/M\nDominica/M\nDominican/MS\nDominick/M\nDominion\nDominique/M\nDomitian/M\nDon/SM\nDona/M\nDonahue/M\nDonald/M\nDonaldson/M\nDonatello/M\nDonetsk/M\nDonizetti/M\nDonn/MR\nDonna/M\nDonne/M\nDonnell/M\nDonner/M\nDonnie/M\nDonny/M\nDonovan/M\nDooley/M\nDoolittle/M\nDoonesbury/M\nDoppler/M\nDora/M\nDorcas/M\nDoreen/M\nDorian/M\nDoric/M\nDoris/M\nDoritos/M\nDorothea/M\nDorothy/M\nDorset/M\nDorsey/M\nDorthy/M\nDortmund/M\nDostoevsky/M\nDot/M\nDotson/M\nDouala/M\nDouay/M\nDoubleday/M\nDoug/M\nDouglas/M\nDouglass/M\nDouro/M\nDover/M\nDow/M\nDowns/M\nDowny/M\nDoyle/M\nDr\nDraco/M\nDraconian/M\nDracula/M\nDrake/M\nDramamine/SM\nDrambuie/M\nDrano/M\nDravidian/M\nDreiser/M\nDresden/M\nDrew/M\nDreyfus/M\nDristan/M\nDropbox/M\nDrudge/M\nDryden/M\nDschubba/M\nDu\nDuPont/M\nDuane/M\nDubai/M\nDubcek/M\nDubhe/M\nDublin/M\nDubrovnik/M\nDuchamp/M\nDudley/M\nDuffy/M\nDuisburg/M\nDuke/M\nDulles/M\nDuluth/M\nDumas/M\nDumbledore/M\nDumbo/M\nDumpster/M\nDunant/M\nDunbar/M\nDuncan/M\nDundee\nDunedin/M\nDunkirk/M\nDunlap/M\nDunn/M\nDunne/M\nDuracell/M\nDuran/M\nDurant/M\nDurante/M\nDurban/M\nDurer/M\nDurex/M\nDurham/MS\nDurkheim/M\nDuroc/M\nDurocher/M\nDuse/M\nDushanbe/M\nDusseldorf/M\nDustbuster/M\nDustin/M\nDusty/M\nDutch/M\nDutchman/M\nDutchmen/M\nDutchwoman\nDuvalier/M\nDvina/M\nDvorak/M\nDwayne/M\nDwight/M\nDy/M\nDyer/M\nDylan/M\nDyson/M\nDzerzhinsky/M\nDzungaria/M\nE/SM\nEC\nECG/M\nECMAScript/M\nEDP/M\nEDT\nEEC/M\nEEG/M\nEEO\nEEOC\nEFL\nEFT\nEKG/M\nELF/M\nEM\nEMT\nENE/M\nEOE\nEPA/M\nER\nERA\nESE/M\nESL\nESP/M\nESPN/M\nESR\nEST/M\nET\nETA\nETD\nEU\nEULA/S\nEakins/M\nEarhart/M\nEarl/M\nEarle/M\nEarlene/M\nEarline/M\nEarnest/M\nEarnestine/M\nEarnhardt/M\nEarp/M\nEast/SZMR\nEaster/M\nEastern/R\nEastman/M\nEastwood/M\nEaton/M\nEben/M\nEbeneezer/M\nEbert/M\nEbola/M\nEbonics/M\nEbony/M\nEbro/M\nEcclesiastes/M\nEco/M\nEcstasy\nEcuador/M\nEcuadoran/SM\nEcuadorean\nEcuadorian/SM\nEd/MNX\nEdam/SM\nEdda/M\nEddie/M\nEddington/M\nEddy/M\nEden/M\nEdgar/M\nEdgardo/M\nEdinburgh/M\nEdison/M\nEdith/M\nEdmond/M\nEdmonton/M\nEdmund/M\nEdna/M\nEdsel/M\nEduardo/M\nEdward/SM\nEdwardian/M\nEdwardo/M\nEdwards/M\nEdwin/M\nEdwina/M\nEeyore/M\nEffie/M\nEfrain/M\nEfren/M\nEggo/M\nEgypt/M\nEgyptian/MS\nEgyptology/M\nEhrenberg/M\nEhrlich/M\nEichmann/M\nEiffel/M\nEileen/M\nEinstein/MS\nEire/M\nEisenhower/M\nEisenstein/M\nEisner/M\nElaine/M\nElam/M\nElanor/M\nElastoplast/M\nElba/M\nElbe/M\nElbert/M\nElbrus/M\nEldon/M\nEleanor/M\nEleazar/M\nElectra/M\nElena/M\nElgar/M\nEli/M\nElias/M\nElijah/M\nElinor/M\nEliot/M\nElisa/M\nElisabeth/M\nElise/M\nEliseo/M\nElisha/M\nEliza/M\nElizabeth/M\nElizabethan/SM\nElla/M\nEllen/M\nEllesmere/M\nEllie/M\nEllington/M\nElliot/M\nElliott/M\nEllis/M\nEllison/M\nElma/M\nElmer/M\nElmo/M\nElnath/M\nElnora/M\nElohim/M\nEloise/M\nEloy/M\nElroy/M\nElsa/M\nElsie/M\nElsinore/M\nEltanin/M\nElton/M\nElul/M\nElva/M\nElvia/M\nElvin/M\nElvira/M\nElvis/M\nElway/M\nElwood/M\nElysee/M\nElysian/M\nElysium/SM\nEmacs/M\nEmanuel/M\nEmerson/M\nEmery/M\nEmil/M\nEmile/M\nEmilia/M\nEmilio/M\nEmily/M\nEminem/M\nEminence\nEmma/M\nEmmanuel/M\nEmmett/M\nEmmy/M\nEmory/M\nEncarta/M\nEndymion/M\nEng/M\nEngels/M\nEngland/M\nEnglish/MRS\nEnglishman/M\nEnglishmen/M\nEnglishwoman/M\nEnglishwomen/M\nEnid/M\nEnif/M\nEniwetok/M\nEnkidu/M\nEnoch/M\nEnos/M\nEnrico/M\nEnrique/M\nEnron/M\nEnterprise/M\nEocene/M\nEpcot/M\nEphesian/MS\nEphesus/M\nEphraim/M\nEpictetus/M\nEpicurean/M\nEpicurus/M\nEpimethius/M\nEpiphany/SM\nEpiscopal\nEpiscopalian/MS\nEpistle\nEpsom/M\nEpson/M\nEpstein/M\nEquuleus/M\nEr/M\nErasmus/M\nErato/M\nEratosthenes/M\nErebus/M\nErector/M\nErewhon/M\nErhard/M\nEric/M\nErica/M\nErich/M\nErick/M\nEricka/M\nErickson/M\nEridanus/M\nErie/M\nErik/M\nErika/M\nErin/M\nEris/MS\nEritrea/M\nEritrean/SM\nErlenmeyer/M\nErma/M\nErna/M\nErnest/M\nErnestine/M\nErnesto/M\nErnie/M\nErnst/M\nEros/MS\nErrol/M\nErse/M\nErvIn/M\nErwin/M\nEsau/M\nEscher/M\nEscherichia/M\nEscondido\nEskimo/MS\nEsmeralda/M\nEsperanto/M\nEsperanza/M\nEspinoza/M\nEsq/M\nEsquire/MS\nEssen/M\nEssene/M\nEssequibo/M\nEssex/M\nEssie/M\nEstablishment\nEsteban/M\nEstela/M\nEstella/M\nEstelle/M\nEster/M\nEsterhazy/M\nEstes/M\nEsther/M\nEstonia/M\nEstonian/SM\nEstrada/M\nEthan/M\nEthel/M\nEthelred/M\nEthernet/M\nEthiopia/M\nEthiopian/SM\nEtna/M\nEton/M\nEtruria/M\nEtruscan/M\nEtta/M\nEu/M\nEucharist/MS\nEucharistic\nEuclid/M\nEugene/M\nEugenia/M\nEugenie/M\nEugenio/M\nEula/M\nEuler/M\nEumenides/M\nEunice/M\nEuphrates/M\nEur\nEurasia/M\nEurasian/MS\nEuripides/M\nEurodollar/SM\nEuropa/M\nEurope/M\nEuropean/MS\nEurydice/M\nEustachian/M\nEuterpe/M\nEva/M\nEvan/SM\nEvangelical\nEvangelina/M\nEvangeline/M\nEvangelist/M\nEvans/M\nEvansville/M\nEve/M\nEvelyn/M\nEvenki/M\nEverReady/M\nEverest/M\nEverett/M\nEverette/M\nEverglades/M\nEvert/M\nEvian/M\nEvita/M\nEwing/M\nExcalibur/M\nExcedrin/M\nExcellency/SM\nExchequer\nExercycle/M\nExocet/M\nExodus/M\nExxon/M\nEyck/M\nEyre/M\nEysenck/M\nEzekiel/M\nEzra/M\nF/MD\nFAA\nFAQ/SM\nFBI/M\nFCC\nFD\nFDA\nFDIC/M\nFDR/M\nFHA/M\nFICA/M\nFIFO\nFL\nFM/SM\nFNMA/M\nFOFL\nFORTRAN/M\nFPO\nFSF/M\nFSLIC\nFTC\nFUD/S\nFWD\nFWIW\nFY\nFYI\nFaberge/M\nFabian/MS\nFacebook/M\nFaeroe/M\nFafnir/M\nFagin/M\nFahd/M\nFahrenheit/M\nFairbanks/M\nFaisal/M\nFaisalabad/M\nFaith/M\nFalasha/M\nFalkland/SM\nFalklands/M\nFallopian/M\nFalstaff/M\nFalwell/M\nFannie/M\nFanny/M\nFaraday/M\nFargo/M\nFarley/M\nFarmer/M\nFarragut/M\nFarrakhan/M\nFarrell/M\nFarrow/M\nFarsi/M\nFassbinder/M\nFatah/M\nFates/M\nFather/SM\nFatima/M\nFatimid/M\nFaulkner/M\nFaulknerian/M\nFauntleroy/M\nFaust/M\nFaustian/M\nFaustino/M\nFaustus/M\nFawkes/M\nFay/M\nFaye/M\nFe/M\nFeb/M\nFebruary/SM\nFed/SM\nFedEx/M\nFederal/MS\nFederalist/M\nFederico/M\nFeds/M\nFelecia/M\nFelice/M\nFelicia/M\nFelicity/M\nFelipe/M\nFelix/M\nFellini/M\nFenian/M\nFerber/M\nFerdinand/M\nFergus/M\nFerguson/M\nFerlinghetti/M\nFermat/M\nFermi/M\nFern/M\nFernandez/M\nFernando/M\nFerrari/M\nFerraro/M\nFerrell/M\nFerris/M\nFeynman/M\nFez/M\nFiat/M\nFiberglas/M\nFibonacci/M\nFichte/M\nFidel/M\nFido/M\nFielding/M\nFields/M\nFigaro/M\nFigueroa/M\nFiji/M\nFijian/MS\nFilipino/MS\nFillmore/M\nFilofax/M\nFinch/M\nFinland/M\nFinley/M\nFinn/SM\nFinnbogadottir/M\nFinnegan/M\nFinnish/M\nFiona/M\nFirefox/M\nFirestone/M\nFischer/M\nFisher/M\nFisk/M\nFitch/M\nFitzgerald/M\nFitzpatrick/M\nFitzroy/M\nFizeau/M\nFla\nFlanagan/M\nFlanders/M\nFlathead\nFlatt/M\nFlaubert/M\nFleischer/M\nFleming/M\nFlemish/M\nFletcher/M\nFlint/M\nFlintstones/M\nFlo/M\nFlora/M\nFlorence/M\nFlorentine/M\nFlores/M\nFlorida/M\nFloridan/M\nFloridian/SM\nFlorine/M\nFlorsheim/M\nFlory/M\nFlossie/M\nFlowers/M\nFloyd/M\nFlynn/M\nFm/M\nFoch/M\nFokker/M\nFoley/M\nFolgers/M\nFolsom/M\nFomalhaut/M\nFonda/M\nFoosball/M\nForbes/M\nFord/M\nForeman/M\nForest/MR\nForester/M\nFormica/MS\nFormosa/M\nFormosan/M\nForrest/M\nForster/M\nFortaleza/M\nFosse/M\nFoster/M\nFotomat/M\nFoucault/M\nFourier/M\nFourneyron/M\nFourth\nFowler/M\nFox/MS\nFr/MD\nFragonard/M\nFran/M\nFrance/SM\nFrances/M\nFrancesca/M\nFrancine/M\nFrancis/M\nFrancisca/M\nFranciscan/MS\nFrancisco/M\nFranck/M\nFranco/M\nFrancois/M\nFrancoise/M\nFrancophile\nFranglais/M\nFrank/SM\nFrankel/M\nFrankenstein/M\nFrankfort/M\nFrankfurt/MR\nFrankfurter/M\nFrankie/M\nFrankish\nFranklin/M\nFranks/M\nFranny/M\nFranz/M\nFraser/M\nFrau/MN\nFraulein\nFrazier/M\nFred/M\nFreda/M\nFreddie/M\nFreddy/M\nFrederic/M\nFrederick/M\nFredericton/M\nFredric/M\nFredrick/M\nFreeman/M\nFreemason/SM\nFreemasonry/SM\nFreetown/M\nFreida/M\nFremont/M\nFrench/MS\nFrenchman/M\nFrenchmen/M\nFrenchwoman/M\nFrenchwomen/M\nFreon/M\nFresnel/M\nFresno/M\nFreud/M\nFreudian/M\nFrey/M\nFreya/M\nFri/M\nFriday/SM\nFrieda/M\nFriedan/M\nFriedman/M\nFriend/SM\nFrigga/M\nFrigidaire/M\nFrisbee/M\nFrisco/M\nFrisian/MS\nFrito/M\nFritz/M\nFrobisher/M\nFrodo/M\nFroissart/M\nFromm/M\nFronde/M\nFrontenac/M\nFrost/M\nFrostbelt/M\nFrunze/M\nFry/M\nFrye/M\nFuchs/M\nFuentes/M\nFugger/M\nFuji/M\nFujitsu/M\nFujiwara/M\nFujiyama/M\nFukuoka/M\nFukuyama/M\nFulani/M\nFulbright/M\nFuller/M\nFullerton/M\nFulton/M\nFunafuti/M\nFundy/M\nFuries/M\nFurtwangler/M\nFushun/M\nFuzhou/M\nFuzzbuster/M\nG/MNRB\nGA\nGAO\nGATT/M\nGB/M\nGCC/M\nGDP/M\nGE/M\nGED\nGHQ/M\nGHz\nGI\nGIF\nGIGO\nGM/M\nGMAT\nGMT/M\nGNP/M\nGNU/M\nGOP/M\nGP/M\nGPA\nGPO\nGPS\nGPU\nGSA\nGTE/M\nGU\nGUI/M\nGa/M\nGable/M\nGabon/M\nGabonese/M\nGaborone/M\nGabriel/M\nGabriela/M\nGabrielle/M\nGacrux/M\nGadsden/M\nGaea/M\nGael/SM\nGaelic/M\nGagarin/M\nGage/M\nGaia/M\nGail/M\nGaiman/M\nGaines/M\nGainsborough/M\nGalahad/SM\nGalapagos/M\nGalatea/M\nGalatia/M\nGalatians/M\nGalaxy\nGalbraith/M\nGale/M\nGalen/M\nGalibi/M\nGalilean/SM\nGalilee/M\nGalileo/M\nGall/M\nGallagher/M\nGallegos/M\nGallic/M\nGallicism/SM\nGallo/M\nGalloway/M\nGallup/M\nGalois/M\nGalsworthy/M\nGalvani/M\nGalveston/M\nGama\nGamay/M\nGambia/M\nGambian/SM\nGamble/M\nGamow/M\nGandalf/M\nGandhi/M\nGandhian/M\nGanesha/M\nGanges/M\nGangtok/M\nGantry/M\nGanymede/M\nGap/M\nGarbo/M\nGarcia/M\nGardner/M\nGareth/M\nGarfield/M\nGarfunkel/M\nGargantua/M\nGaribaldi/M\nGarland/M\nGarner/M\nGarrett/M\nGarrick/M\nGarrison/M\nGarry/M\nGarth/M\nGarvey/M\nGary/M\nGarza/M\nGascony/M\nGasser/M\nGastroenterology\nGates/M\nGatling/M\nGatorade/M\nGatsby/M\nGatun/M\nGauguin/M\nGaul/SM\nGaulish\nGauss/M\nGaussian/M\nGautama/M\nGautier/M\nGavin/M\nGawain/M\nGay/M\nGayle/M\nGaza/M\nGaziantep/M\nGd/M\nGdansk/M\nGe/M\nGeffen/M\nGehenna/M\nGehrig/M\nGeiger/M\nGelbvieh/M\nGeller/M\nGemini/MS\nGen/M\nGena/M\nGenaro/M\nGene/M\nGenesis/M\nGenet/M\nGeneva/M\nGenevieve/M\nGenghis/M\nGenoa/SM\nGentoo/M\nGentry/M\nGeo/M\nGeoffrey/M\nGeorge/MS\nGeorgetown/M\nGeorgette/M\nGeorgia/M\nGeorgian/MS\nGeorgina/M\nGer/M\nGerald/M\nGeraldine/M\nGerard/M\nGerardo/M\nGerber/M\nGere/M\nGeritol/M\nGerman/MS\nGermanic/M\nGermany/M\nGeronimo/M\nGerry/M\nGershwin/M\nGertrude/M\nGestapo/SM\nGethsemane/M\nGetty/M\nGettysburg/M\nGewurztraminer/M\nGhana/M\nGhanaian\nGhats/M\nGhazvanid/M\nGhent/M\nGhibelline/M\nGiacometti/M\nGiannini/M\nGiauque/M\nGibbon/M\nGibbs/M\nGibraltar/MS\nGibson/M\nGide/M\nGideon/M\nGielgud/M\nGienah/M\nGil/M\nGila/M\nGilbert/M\nGilberto/M\nGilchrist/M\nGilda/M\nGilead/M\nGiles/M\nGilgamesh/M\nGill/M\nGillespie/M\nGillette/M\nGilliam/M\nGillian/M\nGilligan/M\nGilman\nGilmore/M\nGina/M\nGinger/M\nGingrich/M\nGinny/M\nGino/M\nGinsberg/M\nGinsburg/M\nGinsu/M\nGiorgione/M\nGiotto/M\nGiovanni/M\nGiraudoux/M\nGiselle/M\nGish/M\nGitHub/M\nGiuliani/M\nGiuseppe/M\nGiza/M\nGk\nGladstone/MS\nGladys/M\nGlaser/M\nGlasgow/M\nGlass/M\nGlastonbury/M\nGlaswegian/SM\nGlaxo/M\nGleason/M\nGlen/M\nGlenda/M\nGlendale\nGlenlivet/M\nGlenn/M\nGlenna/M\nGloria/M\nGloucester/M\nGlover/M\nGnostic/M\nGnosticism/M\nGnuPG\nGoa/M\nGobi/M\nGod/M\nGodard/M\nGoddard/M\nGodel/M\nGodhead/M\nGodiva/M\nGodot/M\nGodspeed/SM\nGodthaab/M\nGodunov/M\nGodzilla/M\nGoebbels/M\nGoering/M\nGoethals/M\nGoethe/M\nGoff/M\nGog/M\nGogol/M\nGoiania/M\nGolan/M\nGolconda/M\nGolda/M\nGoldberg/M\nGolden/M\nGoldie/M\nGoldilocks/M\nGolding/M\nGoldman/M\nGoldsmith/M\nGoldwater/M\nGoldwyn/M\nGolgi/M\nGolgotha/M\nGoliath/M\nGomez/M\nGomorrah/M\nGompers/M\nGomulka/M\nGondwanaland/M\nGonzales/M\nGonzalez/M\nGonzalo/M\nGood/M\nGoodall/M\nGoodman/M\nGoodrich/M\nGoodwill/M\nGoodwin/M\nGoodyear/M\nGoogle/M\nGoolagong/M\nGopher\nGorbachev/M\nGordian/M\nGordimer/M\nGordon/M\nGore/M\nGoren/M\nGorey/M\nGorgas/M\nGorgon/M\nGorgonzola/M\nGorky/M\nGospel/MS\nGoteborg/M\nGoth/M\nGotham/M\nGothic/MS\nGoths\nGouda/SM\nGould/M\nGounod/M\nGovernor\nGoya/M\nGr/B\nGrable/M\nGracchus/M\nGrace/M\nGraceland/M\nGracie/M\nGraciela/M\nGrady/M\nGraffias/M\nGrafton/M\nGraham/M\nGrahame/M\nGrail/M\nGrammy/M\nGrampians/M\nGranada/M\nGrant/M\nGrass/M\nGraves/M\nGray/M\nGrecian/M\nGreece/M\nGreek/SM\nGreeley/M\nGreen/SM\nGreene/M\nGreenland/M\nGreenlandic\nGreenpeace/M\nGreensboro/M\nGreensleeves/M\nGreenspan/M\nGreenwich/M\nGreer/M\nGreg/M\nGregg/M\nGregorian/M\nGregorio/M\nGregory/M\nGrenada/M\nGrenadian/MS\nGrenadines/M\nGrendel/M\nGrenoble/M\nGresham/M\nGreta/M\nGretchen/M\nGretel/M\nGretzky/M\nGrey/M\nGrieg/M\nGriffin/M\nGriffith/M\nGrimes/M\nGrimm/M\nGrinch/M\nGris/M\nGromyko/M\nGropius/M\nGross/M\nGrosz/M\nGrotius/M\nGrover/M\nGrozny\nGrumman/M\nGrundy/M\nGrunewald/M\nGrus/M\nGruyere/SM\nGuadalajara/M\nGuadalcanal/M\nGuadalquivir/M\nGuadalupe/M\nGuadeloupe/M\nGuallatiri/M\nGuam/M\nGuamanian\nGuangzhou/M\nGuantanamo/M\nGuarani/M\nGuarnieri/M\nGuatemala/M\nGuatemalan/MS\nGuayaquil/M\nGucci/M\nGuelph/M\nGuernsey/MS\nGuerra/M\nGuerrero/M\nGuevara/M\nGuggenheim/M\nGuiana/M\nGuido\nGuillermo/M\nGuinea/M\nGuinean/MS\nGuinevere/M\nGuinness/M\nGuiyang/M\nGuizot/M\nGujarat/M\nGujarati/M\nGujranwala/M\nGullah/M\nGulliver/M\nGumbel/M\nGunther/M\nGuofeng/M\nGupta/M\nGurkha/M\nGus/M\nGustav/M\nGustavo/M\nGustavus/M\nGutenberg/M\nGuthrie/M\nGutierrez/M\nGuy/M\nGuyana/M\nGuyanese/M\nGuzman/M\nGwalior/M\nGwen/M\nGwendoline/M\nGwendolyn/M\nGwyn/M\nGypsy/SM\nH/M\nHBO/M\nHDD\nHDMI\nHDTV\nHF/M\nHHS\nHI\nHIV/M\nHM\nHMO/M\nHMS\nHOV\nHP/M\nHPV\nHQ/M\nHR\nHRH\nHS\nHSBC/M\nHST\nHT\nHTML/M\nHTTP\nHUD/M\nHa/M\nHaas/M\nHabakkuk/M\nHaber/M\nHadar/M\nHades/M\nHadrian/M\nHafiz/M\nHagar/M\nHaggai/M\nHagiographa/M\nHague/M\nHahn/M\nHaida/SM\nHaifa/M\nHaiphong/M\nHaiti/M\nHaitian/MS\nHakka/M\nHakluyt/M\nHal/SM\nHaldane/M\nHale/M\nHaleakala/M\nHaley/M\nHalifax/M\nHall/M\nHalley/M\nHalliburton/M\nHallie/M\nHallmark/M\nHalloween/MS\nHallstatt/M\nHalon/M\nHals/M\nHalsey/M\nHam/M\nHaman/M\nHamburg/MS\nHamhung/M\nHamilcar/M\nHamill/M\nHamilton/M\nHamiltonian/M\nHamitic/M\nHamlet/M\nHamlin/M\nHammarskjold/M\nHammerstein/M\nHammett/M\nHammond/M\nHammurabi/M\nHampshire/M\nHampton/M\nHamsun/M\nHan/SM\nHancock/M\nHandel/M\nHandy/M\nHaney/M\nHangul/M\nHangzhou/M\nHank/M\nHanna/M\nHannah/M\nHannibal/M\nHanoi/M\nHanover/M\nHanoverian/M\nHans/MN\nHansel/M\nHansen/M\nHanson/M\nHanuka\nHanukkah/M\nHanukkahs\nHapsburg/M\nHarare/M\nHarbin/M\nHardin/M\nHarding/M\nHardy/M\nHargreaves/M\nHarlan/M\nHarlem/M\nHarlequin/M\nHarley/M\nHarlow/M\nHarmon/M\nHarold/M\nHarper/M\nHarpy/SM\nHarrell/M\nHarriet/M\nHarriett/M\nHarrington/M\nHarris/M\nHarrisburg/M\nHarrison/M\nHarrods/M\nHarry/M\nHart/M\nHarte/M\nHartford/M\nHartline/M\nHartman/M\nHarvard/M\nHarvey/M\nHasbro/M\nHasidim/M\nHaskell/M\nHastings/M\nHatfield/M\nHathaway/M\nHatsheput/M\nHatteras/M\nHattie/M\nHauptmann/M\nHausa/M\nHausdorff/M\nHavana/MS\nHavarti/M\nHavel/M\nHavoline/M\nHaw\nHawaii/M\nHawaiian/SM\nHawking/M\nHawkins/M\nHawks\nHawthorne/M\nHay/SM\nHayden/M\nHaydn/M\nHayek/M\nHayes/M\nHaynes/M\nHays/M\nHayward/M\nHaywood/M\nHayworth/M\nHazel/M\nHazlitt/M\nHe/M\nHead/M\nHearst/M\nHeath/MR\nHeather/M\nHeaviside/M\nHeb\nHebe/M\nHebert/M\nHebraic/M\nHebraism/SM\nHebrew/MS\nHebrews/M\nHebrides/M\nHecate/M\nHector/M\nHecuba/M\nHeep/M\nHefner/M\nHegel/M\nHegelian/M\nHegira/M\nHeidegger/M\nHeidelberg/M\nHeidi/M\nHeifetz/M\nHeimlich/M\nHeine/M\nHeineken/M\nHeinlein/M\nHeinrich/M\nHeinz/M\nHeisenberg/M\nHeisman/M\nHelen/M\nHelena/M\nHelene/M\nHelga/M\nHelicon/M\nHeliopolis/M\nHelios/M\nHellene/SM\nHellenic/M\nHellenism/MS\nHellenist\nHellenistic/M\nHellenization/M\nHellenize/M\nHeller/M\nHellespont/M\nHellman/M\nHelmholtz/M\nHeloise/M\nHelsinki/M\nHelvetian\nHelvetius/M\nHemingway/M\nHench/M\nHenderson/M\nHendrick/MS\nHendricks/M\nHendrix/M\nHenley/M\nHennessy/M\nHenri/M\nHenrietta/M\nHenrik/M\nHenry/M\nHensley/M\nHenson/M\nHepburn/M\nHephaestus/M\nHepplewhite/M\nHera/M\nHeracles/M\nHeraclitus/M\nHerakles/M\nHerbart/M\nHerbert/M\nHerculaneum/M\nHerculean\nHercules/M\nHerder/M\nHereford/SM\nHerero/M\nHeriberto/M\nHerman/M\nHermaphroditus/M\nHermes/M\nHerminia/M\nHermitage/M\nHermite/M\nHermosillo/M\nHernandez/M\nHerod/M\nHerodotus/M\nHerr/MG\nHerrera/M\nHerrick/M\nHerring/M\nHerschel/M\nHersey/M\nHershel/M\nHershey/M\nHertz/M\nHertzsprung/M\nHerzegovina/M\nHerzl/M\nHeshvan/M\nHesiod/M\nHesperus/M\nHess/M\nHesse/M\nHessian/M\nHester/M\nHeston/M\nHettie/M\nHewitt/M\nHewlett/M\nHeyerdahl/M\nHeywood/M\nHezbollah/M\nHezekiah/M\nHf/M\nHg/M\nHialeah/M\nHiawatha/M\nHibernia/M\nHibernian\nHickman/M\nHickok/M\nHicks/M\nHieronymus/M\nHigashiosaka\nHiggins/M\nHighlander/SM\nHighlands\nHighness/M\nHilario/M\nHilary/M\nHilbert/M\nHilda/M\nHildebrand/M\nHilfiger/M\nHill/M\nHillary/M\nHillel/M\nHilton/M\nHimalaya/SM\nHimalayan\nHimalayas/M\nHimmler/M\nHinayana/M\nHindemith/M\nHindenburg/M\nHindi/M\nHindu/SM\nHinduism/SM\nHindustan/M\nHindustani/SM\nHines/M\nHinton/M\nHipparchus/M\nHippocrates/M\nHippocratic/M\nHiram/M\nHirobumi/M\nHirohito/M\nHiroshima/M\nHispanic/SM\nHispaniola/M\nHiss/M\nHitachi/M\nHitchcock/M\nHitler/MS\nHittite/SM\nHmong/M\nHo/M\nHobart/M\nHobbes/M\nHobbs/M\nHockney/M\nHodge/SM\nHodges/M\nHodgkin/M\nHoff/M\nHoffa/M\nHoffman/M\nHofstadter/M\nHogan/M\nHogarth/M\nHogwarts/M\nHohenlohe/M\nHohenstaufen/M\nHohenzollern/M\nHohhot/M\nHohokam/M\nHokkaido/M\nHokusai/M\nHolbein/M\nHolcomb/M\nHolden/M\nHolder/M\nHoliday/M\nHoliness\nHolland/ZSMR\nHollander/M\nHollerith/M\nHolley/M\nHollie/M\nHollis/M\nHolloway/M\nHolly/M\nHollywood/M\nHolman/M\nHolmes/M\nHolocaust/M\nHolocene/M\nHolst/M\nHolstein/SM\nHolt/M\nHomer/M\nHomeric/M\nHon\nHonda/M\nHonduran/MS\nHonduras/M\nHonecker/M\nHoneywell/M\nHong\nHoniara/M\nHonolulu/M\nHonorable\nHonshu/M\nHood/M\nHooke/RM\nHooker/M\nHooper/M\nHoosier/MS\nHooters/M\nHoover/MS\nHope/M\nHopewell/M\nHopi/SM\nHopkins/M\nHopper/M\nHorace/M\nHoracio/M\nHoratio/M\nHormel/M\nHormuz/M\nHorn/M\nHornblower/M\nHorne/M\nHorowitz/M\nHorthy/M\nHorton/M\nHorus/M\nHosea/M\nHost/SM\nHotpoint/M\nHottentot/SM\nHoudini/M\nHouse/M\nHousman/M\nHouston/M\nHouyhnhnm/M\nHovhaness/M\nHoward/M\nHowe/M\nHowell/MS\nHowells/M\nHowrah\nHoyle/M\nHrothgar/M\nHts\nHuang/M\nHubbard/M\nHubble/M\nHuber/M\nHubert/M\nHuck/M\nHuddersfield\nHudson/M\nHuerta/M\nHuey/M\nHuff/M\nHuffman/M\nHuggins/M\nHugh/MS\nHughes/M\nHugo/M\nHuguenot/MS\nHui/M\nHuitzilopotchli/M\nHull/M\nHumberto/M\nHumboldt/M\nHume/M\nHummer/M\nHumphrey/SM\nHumvee/M\nHun/SM\nHung/M\nHungarian/SM\nHungary/M\nHunspell/M\nHunt/MR\nHunter/M\nHuntington/M\nHuntley/M\nHuntsville/M\nHurley/M\nHuron/M\nHurst/M\nHus/M\nHussein/M\nHusserl/M\nHussite/M\nHuston/M\nHutchinson/M\nHutton/M\nHutu/M\nHuxley/M\nHuygens/M\nHyades/M\nHyde/M\nHyderabad/M\nHydra/M\nHymen/M\nHyperion/M\nHyundai/M\nHz/M\nI'd\nI'll\nI'm\nI've\nI/M\nIA\nIBM/M\nICBM/SM\nICC\nICU\nID/SM\nIDE\nIE\nIED\nIEEE\nIKEA/M\nIL\nIMF/M\nIMHO\nIMNSHO\nIMO\nIN\nING/M\nINRI\nINS\nIOU/M\nIP\nIPA\nIPO\nIQ/M\nIRA/SM\nIRC\nIRS/M\nISBN\nISO/M\nISP\nISS\nIT\nIUD\nIV/SM\nIVF\nIa\nIaccoca/M\nIago/M\nIan/M\nIapetus/M\nIbadan/M\nIberia/M\nIberian/M\nIbiza/M\nIblis/M\nIbo/M\nIbsen/M\nIcahn/M\nIcarus/M\nIce\nIceland/MRZ\nIcelander/M\nIcelandic/M\nIda/M\nIdaho/SM\nIdahoan/MS\nIdahoes\nIeyasu/M\nIgnacio/M\nIgnatius/M\nIgor/M\nIguassu/M\nIjsselmeer/M\nIke/M\nIkhnaton/M\nIla/M\nIlene/M\nIliad/SM\nIll\nIllinois/M\nIllinoisan/MS\nIlluminati/M\nIlyushin/M\nImelda/M\nImhotep/M\nImodium/M\nImogene/M\nImus/M\nIn/M\nIna/M\nInc\nInca/SM\nInchon/M\nIncorporated\nInd\nIndependence/M\nIndia/M\nIndian/MS\nIndiana/M\nIndianan/SM\nIndianapolis/M\nIndianian\nIndies/M\nIndira/M\nIndochina/M\nIndochinese/M\nIndonesia/M\nIndonesian/SM\nIndore/M\nIndra/M\nIndus/M\nIndy/SM\nInes/M\nInez/M\nInge/M\nInglewood\nIngram/M\nIngres/M\nIngrid/M\nInnocent/M\nInnsbruck\nInonu/M\nInquisition/M\nInst\nInstagram/M\nInstamatic/M\nIntel/M\nIntelsat/M\nInternationale/M\nInternet/SM\nInterpol/M\nInuit/MS\nInuktitut/M\nInvar/M\nIo/M\nIonesco/M\nIonian/MS\nIonic/SM\nIowa/SM\nIowan/MS\nIphigenia/M\nIpswich\nIqaluit/M\nIqbal/M\nIquitos/M\nIr/M\nIra/M\nIran/M\nIranian/SM\nIraq/M\nIraqi/MS\nIreland/M\nIrene/M\nIris/M\nIrish/MR\nIrishman/M\nIrishmen/M\nIrishwoman/M\nIrishwomen/M\nIrkutsk/M\nIrma/M\nIroquoian/SM\nIroquois/M\nIrrawaddy/M\nIrtish/M\nIrvin/M\nIrvine/M\nIrving/M\nIrwin/M\nIsaac/M\nIsabel/M\nIsabella/M\nIsabelle/M\nIsaiah/M\nIscariot/M\nIsfahan/M\nIsherwood/M\nIshim/M\nIshmael/M\nIshtar/M\nIsiah/M\nIsidro/M\nIsis/M\nIslam/MS\nIslamabad/M\nIslamic/M\nIslamism/M\nIslamist/M\nIslamophobia\nIslamophobic\nIsmael/M\nIsmail/M\nIsolde/M\nIspell/M\nIsrael/SM\nIsraeli/SM\nIsraelite/M\nIssac/M\nIssachar/M\nIstanbul/M\nIsuzu/M\nIt\nItaipu/M\nItal\nItalian/SM\nItalianate\nItaly/M\nItasca/M\nIthaca/M\nIthacan/M\nIto/M\nIva/M\nIvan/M\nIvanhoe/M\nIves/M\nIvorian\nIvory/M\nIvy/M\nIyar/M\nIzaak/M\nIzanagi/M\nIzanami/M\nIzhevsk/M\nIzmir/M\nIzod/M\nIzvestia/M\nJ/MD\nJCS\nJD\nJFK/M\nJP\nJPEG\nJV\nJack/M\nJackie/M\nJacklyn/M\nJackson/M\nJacksonian/M\nJacksonville/M\nJacky/M\nJaclyn/M\nJacob/SM\nJacobean/M\nJacobi/M\nJacobin/M\nJacobite/M\nJacobs/M\nJacobson/M\nJacquard/M\nJacqueline/M\nJacquelyn/M\nJacques/M\nJacuzzi/M\nJagger/M\nJagiellon/M\nJaguar/M\nJahangir/M\nJaime/M\nJain/M\nJainism/M\nJaipur/M\nJakarta/M\nJake/M\nJamaal/M\nJamaica/M\nJamaican/SM\nJamal/M\nJamar/M\nJame/SM\nJamel/M\nJames/M\nJamestown/M\nJami/M\nJamie/M\nJan/M\nJana/M\nJanacek/M\nJane/M\nJanell/M\nJanelle/M\nJanet/M\nJanette/M\nJanice/M\nJanie/M\nJanine/M\nJanis/M\nJanissary/M\nJanjaweed/M\nJanna/M\nJannie/M\nJansen/M\nJansenist/M\nJanuary/SM\nJanus/M\nJap/SM\nJapan/M\nJapanese/MS\nJapura/M\nJared/M\nJarlsberg/M\nJarred/M\nJarrett/M\nJarrod/M\nJarvis/M\nJasmine/M\nJason/M\nJasper/M\nJataka/M\nJava/SM\nJavaScript/M\nJavanese/M\nJavier/M\nJaxartes/M\nJay/M\nJayapura/M\nJayawardene/M\nJaycee/MS\nJaycees/M\nJayne/M\nJayson/M\nJean/M\nJeanette/M\nJeanie/M\nJeanine/M\nJeanne/M\nJeannette/M\nJeannie/M\nJeannine/M\nJed/M\nJedi/M\nJeep/M\nJeeves/M\nJeff/M\nJefferey/M\nJefferson/M\nJeffersonian/M\nJeffery/M\nJeffrey/M\nJeffry/M\nJehoshaphat/M\nJehovah/M\nJekyll/M\nJenifer/M\nJenkins/M\nJenna/M\nJenner/M\nJennie/M\nJennifer/M\nJennings/M\nJenny/M\nJensen/M\nJephthah/M\nJerald/M\nJeremiah/M\nJeremiahs\nJeremy/M\nJeri/M\nJericho/M\nJermaine/M\nJeroboam/M\nJerold/M\nJerome/M\nJerri/M\nJerrod/M\nJerrold/M\nJerry/M\nJersey/MS\nJerusalem/M\nJess/M\nJesse/M\nJessica/M\nJessie/M\nJesuit/MS\nJesus/M\nJetway/M\nJew/SM\nJewel/M\nJewell/M\nJewess/MS\nJewish/PM\nJewry/M\nJezebel/SM\nJidda/M\nJilin/M\nJill/M\nJillian/M\nJim/M\nJimenez/M\nJimmie/M\nJimmy/M\nJinan/M\nJinnah/M\nJinny/M\nJivaro/M\nJo/M\nJoan/M\nJoann/M\nJoanna/M\nJoanne/M\nJoaquin/M\nJob/SM\nJobs/M\nJocasta/M\nJocelyn/M\nJock/M\nJockey/M\nJodi/M\nJodie/M\nJody/M\nJoe/M\nJoel/M\nJoey/M\nJogjakarta/M\nJohann/M\nJohanna/M\nJohannes/M\nJohannesburg/M\nJohn/SM\nJohnathan/M\nJohnathon/M\nJohnie/M\nJohnnie/M\nJohnny/M\nJohns/M\nJohnson/M\nJohnston/M\nJolene/M\nJolson/M\nJon/M\nJonah/M\nJonahs\nJonas/M\nJonathan/M\nJonathon/M\nJones/M\nJoni/M\nJonson/M\nJoplin/M\nJordan/M\nJordanian/MS\nJorge/M\nJose/M\nJosef/M\nJosefa/M\nJosefina/M\nJoseph/M\nJosephine/M\nJosephs\nJosephson/M\nJosephus/M\nJosh/M\nJoshua/M\nJosiah/M\nJosie/M\nJosue/M\nJoule/M\nJove/M\nJovian/M\nJoy/M\nJoyce/M\nJoycean/M\nJoyner/M\nJpn\nJr/M\nJuan/M\nJuana/M\nJuanita/M\nJuarez/M\nJubal/M\nJudaeo\nJudah/M\nJudaic\nJudaical\nJudaism/MS\nJudas/MS\nJudd/M\nJude/M\nJudea/M\nJudges\nJudith/M\nJudson/M\nJudy/M\nJuggernaut/M\nJul\nJules/M\nJulia/M\nJulian/M\nJuliana/M\nJulianne/M\nJulie/M\nJuliet/M\nJuliette/M\nJulio/M\nJulius/M\nJulliard/M\nJuly/SM\nJun/M\nJune/SM\nJuneau/M\nJung/M\nJungfrau/M\nJungian/M\nJunior/SM\nJunker/SM\nJuno/M\nJupiter/M\nJurassic/M\nJurua/M\nJustice/M\nJustin/M\nJustine/M\nJustinian/M\nJutland/M\nJuvenal/M\nK/SMNGJ\nKB/M\nKC\nKFC/M\nKGB/M\nKIA\nKKK/M\nKO/M\nKP\nKS\nKY\nKaaba/M\nKabul/M\nKafka/M\nKafkaesque/M\nKagoshima/M\nKahlua/M\nKaifeng/M\nKaiser/MS\nKaitlin/M\nKalahari/M\nKalamazoo/M\nKalashnikov/M\nKalb/M\nKalevala/M\nKalgoorlie/M\nKali/M\nKalmyk/M\nKama/M\nKamchatka/M\nKamehameha/M\nKampala/M\nKampuchea/M\nKan/SM\nKanchenjunga/M\nKandahar/M\nKandinsky/M\nKane/M\nKannada/M\nKano/M\nKanpur/M\nKansan/MS\nKansas/M\nKant/M\nKantian/M\nKaohsiung/M\nKaposi/M\nKara/M\nKarachi/M\nKaraganda/M\nKarakorum/M\nKaramazov/M\nKareem/M\nKaren/M\nKarenina/M\nKari/M\nKarin/M\nKarina/M\nKarl/M\nKarla/M\nKarloff/M\nKaro/M\nKarol/M\nKarroo/M\nKaryn/M\nKasai/M\nKasey/M\nKashmir/SM\nKasparov/M\nKate/M\nKatelyn/M\nKatharine/M\nKatherine/M\nKatheryn/M\nKathiawar/M\nKathie/M\nKathleen/M\nKathmandu/M\nKathrine/M\nKathryn/M\nKathy/M\nKatie/M\nKatina/M\nKatmai/M\nKatowice/M\nKatrina/M\nKaty/M\nKauai/M\nKaufman/M\nKaunas/M\nKaunda/M\nKawabata/M\nKawasaki/M\nKay/M\nKaye/M\nKayla/M\nKazakh/M\nKazakhs\nKazakhstan/M\nKazan/M\nKazantzakis/M\nKb/M\nKeaton/M\nKeats/M\nKeck/M\nKeenan/M\nKeewatin/M\nKeillor/M\nKeisha/M\nKeith/M\nKeller/M\nKelley/M\nKelli/M\nKellie/M\nKellogg/M\nKelly/M\nKelsey/M\nKelvin/M\nKemerovo/M\nKemp/M\nKempis/M\nKen/M\nKendall/M\nKendra/M\nKendrick/M\nKenmore/M\nKennan/M\nKennedy/M\nKenneth/M\nKennith/M\nKenny/M\nKent/M\nKenton/M\nKentuckian/MS\nKentucky/M\nKenya/M\nKenyan/SM\nKenyatta/M\nKenyon/M\nKeogh/M\nKeokuk/M\nKepler/M\nKerensky/M\nKeri/M\nKermit/M\nKern/M\nKerouac/M\nKerr/M\nKerri/M\nKerry/M\nKettering/M\nKeven/M\nKevin/M\nKevlar/M\nKevorkian/M\nKewpie/M\nKey/M\nKeynes/M\nKeynesian/M\nKhabarovsk/M\nKhachaturian/M\nKhalid/M\nKhan/M\nKharkov/M\nKhartoum/M\nKhayyam/M\nKhazar/M\nKhmer/M\nKhoikhoi/M\nKhoisan/M\nKhomeini/M\nKhorana/M\nKhrushchev/M\nKhufu/M\nKhulna/M\nKhwarizmi/M\nKhyber/M\nKickapoo/M\nKidd/M\nKiel/M\nKierkegaard/M\nKieth/M\nKiev/M\nKigali/M\nKikuyu/M\nKilauea/M\nKilimanjaro/M\nKilroy/M\nKim/M\nKimberley/M\nKimberly/M\nKing/M\nKingston/M\nKingstown/M\nKinko's\nKinney/M\nKinsey/M\nKinshasa/M\nKiowa/MS\nKip/M\nKipling/M\nKirby/M\nKirchhoff/M\nKirchner/M\nKirghistan/M\nKirghiz/M\nKirghizia/M\nKiribati/M\nKirinyaga/M\nKirk/M\nKirkland/M\nKirkpatrick/M\nKirov/M\nKirsten/M\nKisangani/M\nKishinev/M\nKislev/M\nKissinger/M\nKit/M\nKitakyushu/M\nKitchener/M\nKitty/M\nKiwanis/M\nKlan/M\nKlansman/M\nKlaus/M\nKlee/M\nKleenex/MS\nKlein/M\nKlimt/M\nKline/M\nKlingon/M\nKlondike/MS\nKmart/M\nKnapp/M\nKnesset/M\nKngwarreye/M\nKnickerbocker/M\nKnievel/M\nKnight/M\nKnopf/M\nKnossos/M\nKnowles/M\nKnox/M\nKnoxville/M\nKnudsen/M\nKnuth/M\nKnuths\nKobe/M\nKoch/M\nKochab/M\nKodachrome/M\nKodak/M\nKodaly/M\nKodiak/M\nKoestler/M\nKohinoor/M\nKohl/M\nKoizumi/M\nKojak/M\nKolyma/M\nKommunizma/M\nKong/M\nKongo/M\nKonrad/M\nKoontz/M\nKoppel/M\nKoran/MS\nKoranic\nKorea/M\nKorean/SM\nKornberg/M\nKory/M\nKorzybski/M\nKosciusko/M\nKossuth/M\nKosygin/M\nKoufax/M\nKowloon/M\nKr/M\nKraft/M\nKrakatoa/M\nKrakow/M\nKramer/M\nKrasnodar/M\nKrasnoyarsk/M\nKrebs/M\nKremlin/M\nKremlinologist\nKremlinology\nKresge/M\nKringle/M\nKris/M\nKrishna/M\nKrishnamurti/M\nKrista/M\nKristen/M\nKristi/M\nKristie/M\nKristin/M\nKristina/M\nKristine/M\nKristopher/M\nKristy/M\nKroc/M\nKroger/M\nKronecker/M\nKropotkin/M\nKruger/M\nKrugerrand/M\nKrupp/M\nKrystal/M\nKshatriya/M\nKublai/M\nKubrick/M\nKuhn/M\nKuibyshev/M\nKulthumm/M\nKunming/M\nKuomintang/M\nKurd/M\nKurdish/M\nKurdistan/M\nKurosawa/M\nKurt/M\nKurtis/M\nKusch/M\nKutuzov/M\nKuwait/M\nKuwaiti/SM\nKuznets/M\nKuznetsk/M\nKwakiutl/M\nKwan/M\nKwangju/M\nKwanzaa/MS\nKy/MH\nKyle/M\nKyoto/M\nKyrgyzstan/M\nKyushu/M\nL'Amour/M\nL'Enfant\nL'Oreal/M\nL'Ouverture/M\nL/MN\nLA\nLAN/M\nLBJ/M\nLC\nLCD/M\nLCM\nLDC\nLED/M\nLG/M\nLGBT\nLIFO\nLL\nLLB/M\nLLD/M\nLNG\nLOGO\nLP/M\nLPG\nLPN/SM\nLSAT\nLSD/M\nLVN\nLa/SM\nLab\nLaban/M\nLabrador/SM\nLabradorean\nLacey/M\nLachesis/M\nLacy/M\nLadoga/M\nLadonna/M\nLady/M\nLadyship/MS\nLafayette/M\nLafitte/M\nLagos/M\nLagrange/M\nLagrangian/M\nLahore/M\nLaius/M\nLajos/M\nLakeisha/M\nLakewood\nLakisha/M\nLakota/M\nLakshmi/M\nLamaism/SM\nLamar/M\nLamarck/M\nLamaze/M\nLamb/M\nLambert/M\nLamborghini/M\nLambrusco/M\nLamentations\nLamont/M\nLana/M\nLanai/M\nLancashire/M\nLancaster/M\nLance/M\nLancelot/M\nLand/M\nLandon/M\nLandry/M\nLandsat/M\nLandsteiner/M\nLane/M\nLang/M\nLangerhans/M\nLangland/M\nLangley/M\nLangmuir/M\nLanka/M\nLankan/M\nLanny/M\nLansing/M\nLanzhou/M\nLao/SM\nLaocoon/M\nLaos/M\nLaotian/SM\nLaplace/M\nLapland/MR\nLapp/SM\nLara/M\nLaramie/M\nLardner/M\nLaredo/M\nLarousse/M\nLarry/M\nLars/MN\nLarsen/M\nLarson/M\nLascaux/M\nLassa/M\nLassen/M\nLassie/M\nLat/M\nLatasha/M\nLateran/M\nLatham/M\nLatin/MRS\nLatina\nLatino/SM\nLatisha/M\nLatonya/M\nLatoya/M\nLatrobe/M\nLatvia/M\nLatvian/MS\nLaud/MR\nLauder/M\nLaue/M\nLaundromat/M\nLaura/M\nLaurasia/M\nLaurel/M\nLauren/M\nLaurence/M\nLaurent/M\nLauri/M\nLaurie/M\nLaval/M\nLavern/M\nLaverne/M\nLavoisier/M\nLavonne/M\nLawanda/M\nLawrence/M\nLawson/M\nLayamon/M\nLayla/M\nLazaro/M\nLazarus/M\nLe/SM\nLea/M\nLeach/M\nLeadbelly/M\nLeah/M\nLeakey/M\nLean/M\nLeander/M\nLeann/M\nLeanna/M\nLeanne/M\nLear/M\nLearjet/M\nLeary/M\nLeavenworth/M\nLebanese/M\nLebanon/M\nLebesgue/M\nLeblanc/M\nLeda/M\nLederberg/M\nLee/M\nLeeds/M\nLeeuwenhoek/M\nLeeward/M\nLeft\nLegendre/M\nLeger/M\nLeghorn/M\nLego/M\nLegree/M\nLehman/M\nLeibniz/M\nLeicester/SM\nLeiden/M\nLeif/M\nLeigh/M\nLeila/M\nLeipzig/M\nLela/M\nLeland/M\nLelia/M\nLemaitre/M\nLemuel/M\nLemuria/M\nLen/M\nLena/M\nLenard/M\nLenin/M\nLeningrad/M\nLeninism/M\nLeninist/M\nLennon/M\nLenny/M\nLeno/M\nLenoir/M\nLenora/M\nLenore/M\nLent/SMN\nLenten/M\nLeo/SM\nLeola/M\nLeon/M\nLeona/M\nLeonard/M\nLeonardo/M\nLeoncavallo/M\nLeonel/M\nLeonid/M\nLeonidas/M\nLeonor/M\nLeopold/M\nLeopoldo/M\nLepidus/M\nLepke/M\nLepus/M\nLerner/M\nLeroy/M\nLes/M\nLesa/M\nLesley/M\nLeslie/M\nLesotho/M\nLesseps/M\nLessie/M\nLester/M\nLestrade/M\nLeta/M\nLetha/M\nLethe/M\nLeticia/M\nLetitia/M\nLetterman/M\nLevant/M\nLevesque/M\nLevi/SM\nLeviathan/M\nLevine/M\nLeviticus/M\nLevitt/M\nLevy/M\nLew/M\nLewinsky/M\nLewis/M\nLexington/M\nLexus/M\nLhasa/MS\nLhotse/M\nLi/MY\nLibby/M\nLiberace/M\nLiberia/M\nLiberian/SM\nLibra/MS\nLibreOffice/M\nLibreville/M\nLibrium/M\nLibya/M\nLibyan/SM\nLichtenstein/M\nLidia/M\nLie/M\nLieberman/M\nLiebfraumilch/M\nLiechtenstein/ZMR\nLiechtensteiner/M\nLiege/M\nLieut\nLila/M\nLilia/M\nLilian/M\nLiliana/M\nLilith/M\nLiliuokalani/M\nLille/M\nLillian/M\nLillie/M\nLilliput/M\nLilliputian/MS\nLilly/M\nLilongwe/M\nLily/M\nLima/M\nLimbaugh/M\nLimbo\nLimburger/M\nLimoges/M\nLimousin/M\nLimpopo/M\nLin/M\nLina/M\nLincoln/MS\nLind/M\nLinda/M\nLindbergh/M\nLindsay/M\nLindsey/M\nLindy/M\nLinnaeus/M\nLinotype/M\nLinton/M\nLinus/M\nLinux/MS\nLinwood/M\nLionel/M\nLipizzaner/M\nLippi/M\nLippmann/M\nLipscomb/M\nLipton/M\nLisa/M\nLisbon/M\nLissajous/M\nLister/M\nListerine/M\nListon/M\nLiszt/M\nLithuania/M\nLithuanian/MS\nLittle/M\nLitton/M\nLiverpool/M\nLiverpudlian/SM\nLivia/M\nLivingston/M\nLivingstone/M\nLivonia/M\nLivy/M\nLiz/M\nLiza/M\nLizzie/M\nLizzy/M\nLjubljana/M\nLlewellyn/M\nLloyd/M\nLn\nLoafer/SM\nLobachevsky/M\nLochinvar/M\nLocke/M\nLockean/M\nLockheed/M\nLockwood/M\nLodge/M\nLodz/M\nLoewe/M\nLoewi/M\nLoews/M\nLogan/M\nLohengrin/M\nLoire/M\nLois/M\nLoki/M\nLola/M\nLolita/M\nLollard/M\nLollobrigida/M\nLombard/M\nLombardi/M\nLombardy/M\nLome/M\nLon/M\nLondon/MRZ\nLondoner/M\nLong/M\nLongfellow/M\nLongstreet/M\nLongueuil\nLonnie/M\nLopez/M\nLora/M\nLoraine/M\nLord/SM\nLordship/SM\nLorelei/M\nLoren/M\nLorena/M\nLorene/M\nLorentz/M\nLorenz/M\nLorenzo/M\nLoretta/M\nLori/M\nLorie/M\nLorna/M\nLorraine/M\nLorre/M\nLorrie/M\nLos\nLot/M\nLothario/SM\nLott/M\nLottie/M\nLou/M\nLouella/M\nLouie/M\nLouis/M\nLouisa/M\nLouise/M\nLouisiana/M\nLouisianan/MS\nLouisianian/MS\nLouisville/M\nLourdes/M\nLouvre/M\nLove/M\nLovecraft/M\nLovelace/M\nLowe/M\nLowell/M\nLowenbrau/M\nLowery/M\nLowlands\nLoyang/M\nLoyd/M\nLoyola/M\nLr\nLt\nLtd\nLu/M\nLuanda/M\nLuann/M\nLubavitcher/M\nLubbock/M\nLubumbashi/M\nLucas/M\nLuce/M\nLucia/M\nLucian/M\nLuciano/M\nLucien/M\nLucifer/M\nLucile/M\nLucille/M\nLucinda/M\nLucio/M\nLucite/SM\nLucius/M\nLucknow/M\nLucretia/M\nLucretius/M\nLucy/M\nLuddite/MS\nLudhiana/M\nLudwig/M\nLuella/M\nLufthansa/M\nLuftwaffe/M\nLuger/M\nLugosi/M\nLuigi/M\nLuis/M\nLuisa/M\nLuke/M\nLula/M\nLully/M\nLulu/M\nLumiere/M\nLuna/M\nLupe/M\nLupercalia/M\nLupus/M\nLuria/M\nLusaka/M\nLusitania/M\nLuther/M\nLutheran/SM\nLutheranism/MS\nLuvs/M\nLuxembourg/ZMR\nLuxembourger/M\nLuxembourgian\nLuz/M\nLuzon/M\nLvov/M\nLyX/M\nLyallpur\nLycra/M\nLycurgus/M\nLydia/M\nLydian/SM\nLyell/M\nLyle/M\nLyly/M\nLyman/M\nLyme/M\nLynch/M\nLynda/M\nLyndon/M\nLynette/M\nLynn/M\nLynne/M\nLynnette/M\nLyon/SM\nLyons/M\nLyra/M\nLysenko/M\nLysistrata/M\nLysol/M\nM/SMGB\nMA/M\nMASH\nMB/M\nMBA/M\nMC\nMCI/M\nMD/M\nMDT\nME\nMEGO/S\nMFA/M\nMGM/M\nMHz\nMI/M\nMIA\nMIDI/M\nMIPS\nMIRV\nMIT/M\nMM\nMN\nMO\nMOOC\nMP/M\nMPEG\nMRI/M\nMS/M\nMSG/M\nMST/M\nMSW\nMT/M\nMTV/M\nMVP/M\nMW\nMaalox/M\nMabel/M\nMable/M\nMac/M\nMacArthur/M\nMacBride/M\nMacDonald/M\nMacLeish/M\nMacao/M\nMacaulay/M\nMacbeth/M\nMaccabees\nMaccabeus/M\nMace/M\nMacedon/M\nMacedonia/M\nMacedonian/SM\nMach/M\nMachiavelli/M\nMachiavellian/M\nMacias/M\nMacintosh/M\nMack/M\nMackenzie/M\nMackinac/M\nMackinaw/M\nMacmillan/M\nMacon/M\nMacumba/M\nMacy/M\nMadagascan/SM\nMadagascar/M\nMadden/M\nMaddox/M\nMadeira/SM\nMadeleine/M\nMadeline/M\nMadelyn/M\nMadge/M\nMadison/M\nMadonna/SM\nMadras/M\nMadrid/M\nMadurai/M\nMae/M\nMaeterlinck/M\nMafia/MS\nMafioso/M\nMagdalena/M\nMagdalene/M\nMagellan/M\nMagellanic/M\nMaggie/M\nMaghreb/M\nMagi\nMaginot/M\nMagnitogorsk/M\nMagog/M\nMagoo/M\nMagritte/M\nMagsaysay/M\nMagus\nMagyar/SM\nMahabharata/M\nMaharashtra/M\nMahavira/M\nMahayana/M\nMahayanist/M\nMahdi/M\nMahfouz/M\nMahican/SM\nMahler/M\nMai/M\nMaidenform/M\nMaigret/M\nMailer/M\nMaillol/M\nMaiman/M\nMaimonides/M\nMaine/MZR\nMainer/M\nMaisie/M\nMaitreya/M\nMaj\nMajesty\nMajor/M\nMajorca/M\nMajuro/M\nMakarios/M\nMaker/M\nMalabar/M\nMalabo/M\nMalacca/M\nMalachi/M\nMalagasy/M\nMalamud/M\nMalaprop/M\nMalawi/M\nMalawian/SM\nMalay/MS\nMalaya/M\nMalayalam/M\nMalayan/MS\nMalaysia/M\nMalaysian/MS\nMalcolm/M\nMaldive/MS\nMaldives/M\nMaldivian/MS\nMaldonado/M\nMale/M\nMali/M\nMalian/SM\nMalibu/M\nMalinda/M\nMalinowski/M\nMallarme/M\nMallomars/M\nMallory/M\nMalone/M\nMalory/M\nMalplaquet/M\nMalraux/M\nMalta/M\nMaltese/M\nMalthus/M\nMalthusian/SM\nMameluke/M\nMamet/M\nMamie/M\nMamore/M\nMan/M\nManagua/M\nManama/M\nManasseh/M\nManchester/M\nManchu/SM\nManchuria/M\nManchurian/M\nMancini/M\nMancunian/MS\nMandalay/M\nMandarin/M\nMandela/M\nMandelbrot/M\nMandingo/M\nMandrell/M\nMandy/M\nManet/M\nManfred/M\nManhattan/SM\nMani/M\nManichean/M\nManila/SM\nManitoba/M\nManitoulin/M\nManley/M\nMann/GM\nMannheim/M\nManning/M\nMansfield/M\nManson/M\nMantegna/M\nMantle/M\nManuel/M\nManuela/M\nManx/M\nMao/M\nMaoism/SM\nMaoist/SM\nMaori/MS\nMapplethorpe/M\nMaputo/M\nMar/SM\nMara/M\nMaracaibo/M\nMarat/M\nMaratha/M\nMarathi/M\nMarathon/M\nMarc/M\nMarceau/M\nMarcel/M\nMarcelino/M\nMarcella/M\nMarcelo/M\nMarch/MS\nMarci/M\nMarcia/M\nMarciano/M\nMarcie/M\nMarco/MS\nMarconi/M\nMarcos/M\nMarcus/M\nMarcuse\nMarcy/M\nMarduk/M\nMargaret/M\nMargarita/M\nMargarito/M\nMarge/M\nMargery/M\nMargie/M\nMargo/M\nMargot\nMargret/M\nMargrethe/M\nMarguerite/M\nMari/SM\nMaria/M\nMarian/M\nMariana/SM\nMarianas/M\nMarianne/M\nMariano/M\nMaribel/M\nMaricela/M\nMarie/M\nMarietta/M\nMarilyn/M\nMarin/M\nMarina/M\nMarine/SM\nMario/M\nMarion/M\nMaris/M\nMarisa/M\nMarisol/M\nMarissa/M\nMaritain/M\nMaritza/M\nMariupol\nMarius/M\nMarjorie/M\nMarjory/M\nMark/SM\nMarkab/M\nMarkham/M\nMarkov/M\nMarks/M\nMarla/M\nMarlboro/M\nMarlborough/M\nMarlene/M\nMarley/M\nMarlin/M\nMarlon/M\nMarlowe/M\nMarmara/M\nMarne/M\nMaronite/M\nMarple/M\nMarquesas/M\nMarquette/M\nMarquez/M\nMarquis/M\nMarquita/M\nMarrakesh/M\nMarriott/M\nMars/MS\nMarsala/M\nMarseillaise/MS\nMarseilles/M\nMarsh/M\nMarsha/M\nMarshall/M\nMarta/M\nMartel/M\nMartha/M\nMartial/M\nMartian/SM\nMartin/M\nMartina/M\nMartinez/M\nMartinique/M\nMarty/M\nMarva/M\nMarvell/M\nMarvin/M\nMarx/M\nMarxian\nMarxism/SM\nMarxist/SM\nMary/M\nMaryann/M\nMaryanne/M\nMaryellen/M\nMaryland/MR\nMarylander/M\nMarylou/M\nMasada/M\nMasai/M\nMasaryk/M\nMascagni/M\nMasefield/M\nMaserati/M\nMaseru/M\nMashhad/M\nMason/MS\nMasonic/M\nMasonite/M\nMass/MS\nMassachusetts/M\nMassasoit/M\nMassenet/M\nMassey/M\nMaster/S\nMasterCard/M\nMasters/M\nMather/M\nMathew/SM\nMathews/M\nMathewson/M\nMathias/M\nMathis/M\nMatilda/M\nMatisse/M\nMatt/M\nMattel/M\nMatterhorn/M\nMatthew/SM\nMatthews/M\nMatthias/M\nMattie/M\nMaud/M\nMaude/M\nMaugham/M\nMaui/M\nMaupassant/M\nMaura/M\nMaureen/M\nMauriac/M\nMaurice/M\nMauricio/M\nMaurine/M\nMauritania/M\nMauritanian/SM\nMauritian/SM\nMauritius/M\nMauro/M\nMaurois/M\nMauryan/M\nMauser/M\nMavis/M\nMax/M\nMaximilian/M\nMaxine/M\nMaxwell/M\nMay/SMR\nMaya/SM\nMayan/MS\nMayer/M\nMayfair/M\nMayflower/M\nMaynard/M\nMayo/M\nMaypole\nMayra/M\nMays/M\nMaytag/M\nMazama/M\nMazarin/M\nMazatlan/M\nMazda/M\nMazola/M\nMazzini/M\nMb/M\nMbabane/M\nMbini/M\nMcAdam/M\nMcBride/M\nMcCain/M\nMcCall/M\nMcCarthy/M\nMcCarthyism/M\nMcCartney/M\nMcCarty/M\nMcClain/M\nMcClellan/M\nMcClure/M\nMcConnell/M\nMcCormick/M\nMcCoy/M\nMcCray/M\nMcCullough/M\nMcDaniel/M\nMcDonald/M\nMcDonnell/M\nMcDowell/M\nMcEnroe/M\nMcFadden/M\nMcFarland/M\nMcGee/M\nMcGovern/M\nMcGowan/M\nMcGuffey/M\nMcGuire/M\nMcIntosh/M\nMcIntyre/M\nMcKay/M\nMcKee/M\nMcKenzie/M\nMcKinley/M\nMcKinney/M\nMcKnight/M\nMcLaughlin/M\nMcLean/M\nMcLeod/M\nMcLuhan/M\nMcMahon/M\nMcMillan/M\nMcNamara/M\nMcNaughton/M\nMcNeil/M\nMcPherson/M\nMcQueen/M\nMcVeigh/M\nMd/M\nMe\nMead/M\nMeade/M\nMeadows/M\nMeagan/M\nMeany/M\nMecca/MS\nMedan/M\nMedea/M\nMedellin/M\nMedia/M\nMedicaid/SM\nMedicare/SM\nMedici/M\nMedina/M\nMediterranean/MS\nMedusa/M\nMeg/M\nMegan/M\nMeghan/M\nMeier/M\nMeighen/M\nMeiji/M\nMeir/M\nMejia/M\nMekong/M\nMel/M\nMelanesia/M\nMelanesian/M\nMelanie/M\nMelba/M\nMelbourne/M\nMelchior/M\nMelchizedek/M\nMelendez/M\nMelinda/M\nMelisa/M\nMelisande/M\nMelissa/M\nMellon/M\nMelody/M\nMelpomene/M\nMelton/M\nMelva/M\nMelville/M\nMelvin/M\nMemling/M\nMemphis/M\nMenander/M\nMencius/M\nMencken/M\nMendel/M\nMendeleev/M\nMendelian/M\nMendelssohn/M\nMendez/M\nMendocino/M\nMendoza/M\nMenelaus/M\nMenelik/M\nMenes/M\nMengzi\nMenkalinan/M\nMenkar/M\nMenkent/M\nMennen/M\nMennonite/MS\nMenominee/M\nMenotti/M\nMensa/M\nMentholatum/M\nMenuhin/M\nMenzies/M\nMephisto\nMephistopheles/M\nMerak/M\nMercado/M\nMercator/M\nMercedes/M\nMercer/M\nMercia/M\nMerck/M\nMercurochrome/M\nMercury/SM\nMeredith/M\nMerino/M\nMerle/M\nMerlin/M\nMerlot/M\nMerovingian/M\nMerriam/M\nMerrick/M\nMerrill/M\nMerrimack/M\nMerritt/M\nMerthiolate/M\nMerton/M\nMervin/M\nMesa/M\nMesabi/M\nMesmer/M\nMesolithic/M\nMesopotamia/M\nMesopotamian\nMesozoic/M\nMesserschmidt/M\nMessiaen/M\nMessiah/M\nMessiahs\nMessianic\nMetallica/M\nMetamucil/M\nMethodism/SM\nMethodist/SM\nMethuselah/M\nMetternich/M\nMeuse/M\nMex\nMexicali/M\nMexican/MS\nMexico/M\nMeyer/MS\nMeyerbeer/M\nMeyers/M\nMfume/M\nMg/M\nMgr\nMiG/M\nMia/M\nMiami/MS\nMiaplacidus/M\nMicah/M\nMicawber/M\nMich/M\nMichael/M\nMichaelmas/MS\nMicheal/M\nMichel/M\nMichelangelo/M\nMichele/M\nMichelin/M\nMichelle/M\nMichelob/M\nMichelson/M\nMichigan/M\nMichigander/MS\nMichiganite\nMick/M\nMickey/M\nMickie/M\nMicky/M\nMicmac/SM\nMicronesia/M\nMicronesian/M\nMicrosoft/M\nMidas/M\nMiddleton/M\nMideast\nMideastern\nMidland/MS\nMidway/M\nMidwest/M\nMidwestern/MR\nMiguel/M\nMike/M\nMikhail/M\nMikoyan/M\nMilagros/M\nMilan/M\nMilanese\nMildred/M\nMiles/M\nMilford/M\nMilken/M\nMill/SMR\nMillard/M\nMillay/M\nMiller/M\nMillet/M\nMillicent/M\nMillie/M\nMillikan/M\nMills/M\nMilne/M\nMilo/M\nMilosevic/M\nMilquetoast/M\nMiltiades/M\nMilton/M\nMiltonic/M\nMiltown/M\nMilwaukee/M\nMimi/M\nMimosa/M\nMin/M\nMinamoto/M\nMindanao/M\nMindoro/M\nMindy/M\nMinerva/M\nMing/M\nMingus/M\nMinn\nMinneapolis/M\nMinnelli/M\nMinnesota/M\nMinnesotan/SM\nMinnie/M\nMinoan/MS\nMinolta/M\nMinos/M\nMinot/M\nMinotaur/M\nMinsk/M\nMinsky/M\nMintaka/M\nMinuit/M\nMinuteman/M\nMiocene/M\nMir/M\nMira/M\nMirabeau/M\nMirach/M\nMiranda/M\nMirfak/M\nMiriam/M\nMiro/M\nMirzam/M\nMiskito/M\nMiss\nMississauga/M\nMississippi/M\nMississippian/SM\nMissouri/M\nMissourian/MS\nMissy/M\nMistassini/M\nMister\nMistress\nMisty/M\nMitch/M\nMitchel/M\nMitchell/M\nMitford/M\nMithra/M\nMithridates/M\nMitsubishi/M\nMitterrand/M\nMitty/M\nMitzi/M\nMixtec/M\nMizar/M\nMk\nMlle\nMme/S\nMn/M\nMnemosyne/M\nMo/M\nMobil/M\nMobile/M\nMobutu/M\nModesto/M\nModigliani/M\nMoe/M\nMoet/M\nMogadishu/M\nMogul/MS\nMohacs/M\nMohamed/M\nMohammad/M\nMohammedan/SM\nMohammedanism/SM\nMohave/SM\nMohawk/SM\nMohegan\nMoho/M\nMohorovicic/M\nMoira/M\nMoises/M\nMoiseyev/M\nMojave/SM\nMoldavia/M\nMoldavian\nMoldova/M\nMoldovan\nMoliere/M\nMolina/M\nMoll/M\nMollie/M\nMolly/M\nMolnar/M\nMoloch/M\nMolokai/M\nMolotov/M\nMoluccas/M\nMombasa/M\nMon/SM\nMona/M\nMonacan\nMonaco/M\nMondale/M\nMonday/SM\nMondrian/M\nMonegasque/SM\nMonera/M\nMonet/M\nMongol/SM\nMongolia/M\nMongolian/SM\nMongolic/M\nMongoloid\nMonica/M\nMonique/M\nMonk/M\nMonmouth/M\nMonongahela/M\nMonroe/M\nMonrovia/M\nMonsanto/M\nMonsignor/SM\nMont/M\nMontague/M\nMontaigne/M\nMontana/M\nMontanan/SM\nMontcalm/M\nMonte/M\nMontenegrin/M\nMontenegro/M\nMonterrey/M\nMontesquieu/M\nMontessori/M\nMonteverdi/M\nMontevideo/M\nMontezuma/M\nMontgolfier/M\nMontgomery/M\nMonticello/M\nMontoya/M\nMontpelier/M\nMontrachet/M\nMontreal/M\nMontserrat/M\nMonty/M\nMoody/M\nMoog/M\nMoon/M\nMooney/M\nMoor/SM\nMoore/M\nMoorish/M\nMorales/M\nMoran/M\nMoravia/M\nMoravian/M\nMordred/M\nMore/M\nMoreno/M\nMorgan/SM\nMoriarty/M\nMorin/M\nMorison/M\nMorita/M\nMorley/M\nMormon/SM\nMormonism/SM\nMoro/M\nMoroccan/SM\nMorocco/M\nMoroni/M\nMorpheus/M\nMorphy/M\nMorris/M\nMorrison/M\nMorrow/M\nMorse/M\nMort/M\nMortimer/M\nMorton/M\nMosaic/M\nMoscow/M\nMoseley/M\nMoselle/M\nMoses/M\nMosley/M\nMoss/M\nMosul/M\nMotorola/M\nMotown/M\nMotrin/M\nMott/M\nMoulton/M\nMount/M\nMountbatten/M\nMountie/MS\nMoussorgsky/M\nMouthe/M\nMouton/M\nMowgli/M\nMozambican/SM\nMozambique/M\nMozart/M\nMozilla/M\nMr/SM\nMs/S\nMsgr\nMt\nMuawiya/M\nMubarak/M\nMueller/M\nMuenster/MS\nMugabe/M\nMuhammad/M\nMuhammadan/MS\nMuhammadanism/SM\nMuir/M\nMujib/M\nMulder/M\nMullen/M\nMuller/M\nMulligan/M\nMullikan/M\nMullins/M\nMulroney/M\nMultan/M\nMultics\nMumbai/M\nMumford/M\nMunch/M\nMunchhausen/M\nMunich/M\nMunoz/M\nMunro/M\nMunster/M\nMuppet/M\nMurasaki/M\nMurat/M\nMurchison/M\nMurcia\nMurdoch/M\nMuriel/M\nMurillo/M\nMurine/M\nMurmansk/M\nMurphy/M\nMurray/M\nMurrow/M\nMurrumbidgee/M\nMuscat/M\nMuscovite/M\nMuscovy/M\nMuse/M\nMusharraf/M\nMusial/M\nMuskogee/M\nMuslim/MS\nMussolini/M\nMussorgsky/M\nMutsuhito/M\nMuzak/M\nMySpace/M\nMyanmar/M\nMycenae/M\nMycenaean/M\nMyers/M\nMylar/MS\nMyles/M\nMyra/M\nMyrdal/M\nMyrna/M\nMyron/M\nMyrtle/M\nMysore/M\nMyst/M\nN'Djamena\nN/MD\nNAACP/M\nNAFTA/M\nNASA/M\nNASCAR/M\nNASDAQ/M\nNATO/M\nNB\nNBA/M\nNBC/M\nNBS\nNC\nNCAA/M\nNCO\nND\nNE/M\nNEH\nNF\nNFC\nNFL/M\nNH\nNHL/M\nNIH\nNIMBY\nNJ\nNLRB\nNM\nNORAD/M\nNOW\nNP\nNPR/M\nNR\nNRA\nNRC\nNS\nNSA/M\nNSC\nNSF\nNT\nNV\nNW/M\nNWT\nNY\nNYC\nNYSE\nNZ\nNa/M\nNabisco/M\nNabokov/M\nNader/M\nNadia/M\nNadine/M\nNagasaki/M\nNagoya/M\nNagpur/M\nNagy/M\nNahuatl/MS\nNahum/M\nNaipaul/M\nNair/M\nNairobi/M\nNaismith/M\nNam/M\nNamath/M\nNamibia/M\nNamibian/MS\nNan/M\nNanak/M\nNanchang/M\nNancy/M\nNanette/M\nNanjing/M\nNannie/M\nNanook/M\nNansen/M\nNantes/M\nNantucket/M\nNaomi/M\nNaphtali/M\nNapier/M\nNaples/M\nNapoleon/MS\nNapoleonic/M\nNapster/M\nNarcissus/M\nNarmada/M\nNarnia/M\nNarraganset\nNarragansett/M\nNash/M\nNashua/M\nNashville/M\nNassau/M\nNasser/M\nNat/M\nNatalia/M\nNatalie/M\nNatasha/M\nNatchez/M\nNate/MN\nNathan/SM\nNathaniel/M\nNathans/M\nNation/M\nNationwide/M\nNativity/M\nNaugahyde/M\nNauru/M\nNautilus/M\nNavajo/SM\nNavajoes\nNavarre/M\nNavarro/M\nNavratilova/M\nNavy\nNazarene/M\nNazareth/M\nNazca/M\nNazi/SM\nNazism/MS\nNb/M\nNd/M\nNdjamena/M\nNe/M\nNeWS\nNeWSes\nNeal/M\nNeanderthal/SM\nNeapolitan/M\nNeb\nNebr\nNebraska/M\nNebraskan/MS\nNebuchadnezzar/M\nNed/M\nNefertiti/M\nNegev/M\nNegress/MS\nNegritude\nNegro/MS\nNegroes\nNegroid/SM\nNegros/M\nNehemiah/M\nNehru/M\nNeil/M\nNelda/M\nNell/M\nNellie/M\nNelly/M\nNelsen/M\nNelson/M\nNembutal/M\nNemesis/M\nNeogene/M\nNeolithic\nNepal/M\nNepalese/M\nNepali/MS\nNeptune/M\nNereid/M\nNerf/M\nNero/M\nNeruda/M\nNescafe/M\nNesselrode/M\nNestle/M\nNestor/M\nNestorius/M\nNetflix/M\nNetherlander/SM\nNetherlands/M\nNetscape/M\nNettie/M\nNetzahualcoyotl/M\nNev/M\nNeva/M\nNevada/M\nNevadan/SM\nNevadian\nNevis/M\nNevsky/M\nNewark/M\nNewcastle/M\nNewfoundland/MRS\nNewman/M\nNewport/M\nNewsweek/M\nNewton/M\nNewtonian/M\nNexis/M\nNgaliema/M\nNguyen/M\nNi/M\nNiagara/M\nNiamey/M\nNibelung/M\nNicaea/M\nNicaragua/M\nNicaraguan/SM\nNiccolo/M\nNice/M\nNicene/M\nNichiren/M\nNicholas/M\nNichole/M\nNichols/M\nNicholson/M\nNick/M\nNickelodeon/M\nNicklaus/M\nNickolas/M\nNicobar/M\nNicodemus/M\nNicola/SM\nNicolas/M\nNicole/M\nNicosia/M\nNiebuhr/M\nNielsen/M\nNietzsche/M\nNieves/M\nNigel/M\nNiger/M\nNigeria/M\nNigerian/MS\nNigerien/M\nNightingale/M\nNijinsky/M\nNike/M\nNikita/M\nNikkei/M\nNikki/M\nNikolai/M\nNikon/M\nNile/M\nNimitz/M\nNimrod/M\nNina/M\nNineveh/M\nNintendo/M\nNiobe/M\nNippon/M\nNipponese/M\nNirenberg/M\nNirvana/M\nNisan/M\nNisei/M\nNissan/M\nNita/M\nNivea/M\nNixon/M\nNkrumah/M\nNo/M\nNoDoz/M\nNoah/M\nNobel/M\nNobelist/MS\nNoble/M\nNoe/M\nNoel/SM\nNoelle/M\nNoemi/M\nNokia/M\nNola/M\nNolan/M\nNome/M\nNona/M\nNootka/M\nNora/M\nNorbert/M\nNorberto/M\nNordic/MS\nNoreen/M\nNorfolk/M\nNoriega/M\nNorma/M\nNorman/MS\nNormand/M\nNormandy/M\nNorplant/M\nNorris/M\nNorse/M\nNorseman/M\nNorsemen/M\nNorth/M\nNorthampton/M\nNortheast/MS\nNortherner/M\nNorthrop/M\nNorthrup/M\nNorths\nNorthwest/SM\nNorton/M\nNorw\nNorway/M\nNorwegian/SM\nNorwich/M\nNosferatu/M\nNostradamus/M\nNottingham/M\nNouakchott/M\nNoumea/M\nNov/M\nNova/M\nNovartis/M\nNovember/MS\nNovgorod/M\nNovocain/MS\nNovocaine\nNovokuznetsk/M\nNovosibirsk/M\nNoxzema/M\nNoyce/M\nNoyes/M\nNp/M\nNubia/M\nNubian/M\nNukualofa/M\nNumbers/M\nNunavut/M\nNunez/M\nNunki/M\nNuremberg/M\nNureyev/M\nNutraSweet/M\nNyQuil/M\nNyasa/M\nNyerere/M\nO'Brien/M\nO'Casey/M\nO'Connell/M\nO'Connor/M\nO'Donnell/M\nO'Hara/M\nO'Higgins/M\nO'Keeffe/M\nO'Neil/M\nO'Neill/M\nO'Rourke/M\nO'Toole/M\nO/SM\nOAS/M\nOB\nOCR\nOD/SM\nOE\nOED\nOH\nOHSA/M\nOJ\nOK/SMDG\nOMB/M\nON\nOPEC/M\nOR\nOS/M\nOSHA/M\nOSes\nOT\nOTB\nOTC\nOTOH\nOahu/M\nOakland/M\nOakley/M\nOates/M\nOaxaca/M\nOb/M\nObadiah/M\nObama/M\nObamacare\nOberlin/M\nOberon/M\nOccam/M\nOccident\nOccidental/MS\nOceania/M\nOceanside\nOceanus/M\nOchoa/M\nOct/M\nOctavia/M\nOctavian/M\nOctavio/M\nOctober/SM\nOdell/M\nOder/M\nOdessa/M\nOdets/M\nOdin/M\nOdis/M\nOdom/M\nOdysseus/M\nOdyssey/M\nOedipal/M\nOedipus/M\nOersted/M\nOfelia/M\nOffenbach/M\nOfficeMax/M\nOgbomosho/M\nOgden/M\nOgilvy/M\nOglethorpe/M\nOhio/M\nOhioan/SM\nOise/M\nOjibwa/SM\nOkayama\nOkeechobee/M\nOkefenokee/M\nOkhotsk/M\nOkinawa/M\nOkinawan\nOkla\nOklahoma/M\nOklahoman/M\nOktoberfest/M\nOla/M\nOlaf/M\nOlajuwon/M\nOlav/M\nOldenburg/M\nOldfield/M\nOldsmobile/M\nOlduvai/M\nOlen/M\nOlenek/M\nOlga/M\nOligocene/M\nOlin/M\nOlive/MR\nOliver/M\nOlivetti/M\nOlivia/M\nOlivier/M\nOllie/M\nOlmec/M\nOlmsted/M\nOlsen/M\nOlson/M\nOlympia/SM\nOlympiad/MS\nOlympian/MS\nOlympic/SM\nOlympics/M\nOlympus/M\nOmaha/MS\nOman/M\nOmani/MS\nOmar/M\nOmayyad/M\nOmdurman/M\nOmnipotent\nOmsk/M\nOnassis/M\nOneal/M\nOnega/M\nOnegin/M\nOneida/MS\nOnion/M\nOno/M\nOnondaga/MS\nOnsager/M\nOnt\nOntarian\nOntario/M\nOort/M\nOpal/M\nOpel/M\nOpenOffice/M\nOphelia/M\nOphiuchus/M\nOppenheimer/M\nOprah/M\nOra/M\nOracle/M\nOran/M\nOrange/M\nOranjestad/M\nOrbison/M\nOrdovician/M\nOre/N\nOreg\nOregon/M\nOregonian/SM\nOreo/M\nOrestes/M\nOrient/M\nOriental/MS\nOrin/M\nOrinoco/M\nOrion/M\nOriya/M\nOrizaba/M\nOrkney/M\nOrlando/M\nOrleans/M\nOrlon/MS\nOrly/M\nOrpheus/M\nOrphic/M\nOrr/M\nOrtega/M\nOrthodox\nOrtiz/M\nOrval/M\nOrville/M\nOrwell/M\nOrwellian/M\nOs/M\nOsage/MS\nOsaka/M\nOsbert/M\nOsborn/M\nOsborne/M\nOscar/MS\nOsceola/M\nOsgood/M\nOshawa/M\nOshkosh/M\nOsiris/M\nOslo/M\nOsman/M\nOstrogoth/M\nOstwald/M\nOsvaldo/M\nOswald/M\nOthello/M\nOtis/M\nOttawa/SM\nOtto/M\nOttoman/M\nOuagadougou/M\nOuija/MS\nOvid/M\nOwen/SM\nOwens/M\nOxford/SM\nOxnard/M\nOxonian/M\nOxus/M\nOxycontin/M\nOz/M\nOzark/MS\nOzarks/M\nOzymandias/M\nOzzie/M\nP/MN\nPA/M\nPAC/M\nPARC/S\nPASCAL\nPBS/M\nPBX\nPC/SM\nPCB\nPCMCIA\nPCP/M\nPD\nPDF\nPDQ\nPDT\nPE\nPET/M\nPFC\nPG\nPGP\nPIN\nPJ's\nPLO/M\nPM/SMDG\nPMS/M\nPO\nPOW/M\nPP\nPPS\nPR\nPRC/M\nPRO\nPS/M\nPST/M\nPT\nPTA/M\nPTO\nPVC/M\nPW\nPX\nPa/M\nPaar/M\nPablo/M\nPablum/M\nPabst/M\nPace/M\nPacheco/M\nPacific/M\nPacino/M\nPackard/M\nPadang\nPaderewski/M\nPadilla/M\nPaganini/M\nPage/M\nPaglia/M\nPahlavi/M\nPaige/M\nPaine/M\nPaiute/SM\nPakistan/M\nPakistani/SM\nPalembang/M\nPaleocene/M\nPaleogene/M\nPaleolithic/M\nPaleozoic/M\nPalermo/M\nPalestine/M\nPalestinian/SM\nPalestrina/M\nPaley/M\nPalikir/M\nPalisades/M\nPalladio/M\nPalmer/M\nPalmerston/M\nPalmolive/M\nPalmyra/M\nPalomar/M\nPam/M\nPamela/M\nPamirs/M\nPampers/M\nPan/M\nPanama/SM\nPanamanian/MS\nPanasonic/M\nPandora/M\nPangaea/M\nPankhurst/M\nPanmunjom/M\nPansy/M\nPantagruel/M\nPantaloon/M\nPantheon/M\nPanza/M\nParacelsus/M\nParaclete/M\nParadise\nParaguay/M\nParaguayan/MS\nParalympic/S\nParamaribo/M\nParamount/M\nParana/M\nParcheesi/M\nPareto/M\nParis/M\nParisian/MS\nPark/SMR\nParker/M\nParkinson/M\nParkman/M\nParks/M\nParliament/M\nParmenides\nParmesan/MS\nParnassus/MS\nParnell/M\nParr/M\nParrish/M\nParsifal/M\nParsons/M\nParthenon/M\nParthia/M\nPasadena/M\nPascal/SM\nPasquale/M\nPassion/SM\nPassover/MS\nPasternak/M\nPasteur/M\nPat/M\nPatagonia/M\nPatagonian/M\nPate/M\nPatel/M\nPaterson/M\nPatna/M\nPatrica/M\nPatrice/M\nPatricia/M\nPatrick/M\nPatsy/M\nPatterson/M\nPatti/M\nPatton/M\nPatty/M\nPaul/GM\nPaula/M\nPaulette/M\nPauli/M\nPauline/M\nPauling/M\nPavarotti/M\nPavlov/M\nPavlova/M\nPavlovian/M\nPawnee/SM\nPayPal/M\nPayne/M\nPb/M\nPd/M\nPeabody/M\nPeace/M\nPeale/M\nPearl/M\nPearlie/M\nPearson/M\nPeary/M\nPechora/M\nPeck/M\nPeckinpah/M\nPecos/M\nPedro/M\nPeel/M\nPeg/M\nPegasus/MS\nPeggy/M\nPei/M\nPeiping/M\nPeking/SM\nPekingese/SM\nPele/M\nPelee/M\nPeloponnese/M\nPembroke/M\nPen/M\nPena/M\nPenderecki/M\nPenelope/M\nPenn/M\nPenna\nPenney/M\nPennington/M\nPennsylvania/M\nPennsylvanian/MS\nPenny/M\nPennzoil/M\nPensacola/M\nPentagon/M\nPentateuch/M\nPentax/M\nPentecost/SM\nPentecostal/MS\nPentecostalism\nPentium/SM\nPeoria/M\nPepin/M\nPepsi/M\nPepys/M\nPequot/M\nPercheron/M\nPercival/M\nPercy/M\nPerelman/M\nPerez/M\nPericlean/M\nPericles/M\nPerkins/M\nPerl/SM\nPerm/M\nPermalloy/M\nPermian/M\nPernod/M\nPeron/M\nPerot/M\nPerrier/M\nPerry/RM\nPerseid/M\nPersephone/M\nPersepolis/M\nPerseus/M\nPershing/M\nPersia/M\nPersian/SM\nPerth/M\nPeru/M\nPeruvian/MS\nPeshawar/M\nPetain/M\nPete/RMZ\nPeter/M\nPeters/MN\nPetersen/M\nPeterson/M\nPetra/M\nPetrarch/M\nPetty/M\nPeugeot/M\nPfc\nPfizer/M\nPhD/M\nPhaedra/M\nPhaethon/M\nPhanerozoic/M\nPharaoh/M\nPharaohs\nPharisaic\nPharisaical\nPharisee/MS\nPhekda/M\nPhelps/M\nPhidias/M\nPhil/MY\nPhiladelphia/M\nPhilby/M\nPhilemon/M\nPhilip/MS\nPhilippe/M\nPhilippians/M\nPhilippine/SM\nPhilippines/M\nPhilips/M\nPhilistine/M\nPhillip/SM\nPhillipa/M\nPhillips/M\nPhilly/M\nPhipps/M\nPhobos/M\nPhoebe/M\nPhoenicia/M\nPhoenician/SM\nPhoenix/M\nPhotostat/MS\nPhotostatted\nPhotostatting\nPhrygia/M\nPhyllis/M\nPiaf/M\nPiaget/M\nPianola/M\nPicasso/M\nPiccadilly/M\nPickering/M\nPickett/M\nPickford/M\nPickwick/M\nPict/M\nPiedmont/M\nPierce/M\nPierre/M\nPierrot/M\nPike/M\nPilate/MS\nPilates/M\nPilcomayo/M\nPilgrim/SM\nPillsbury/M\nPinatubo/M\nPincus/M\nPindar/M\nPinkerton/M\nPinocchio/M\nPinochet/M\nPinter/M\nPinyin\nPippin/M\nPiraeus/M\nPirandello/M\nPisa/M\nPisces/M\nPisistratus/M\nPissaro/M\nPitcairn/M\nPitt/SM\nPittman/M\nPitts/M\nPittsburgh/M\nPius/M\nPizarro/M\nPkwy\nPl\nPlanck/M\nPlano\nPlantagenet/M\nPlasticine/M\nPlataea/M\nPlath/M\nPlato/M\nPlatonic\nPlatonism/M\nPlatonist/M\nPlatte/M\nPlautus/M\nPlayStation/M\nPlayboy/M\nPlaytex/M\nPleiades/M\nPleistocene/M\nPlexiglas/MS\nPliny/M\nPliocene/SM\nPlutarch/M\nPluto/M\nPlymouth/M\nPm/M\nPo/M\nPocahontas/M\nPocono/SM\nPoconos/M\nPodgorica/M\nPodhoretz/M\nPodunk/M\nPoe/M\nPogo/M\nPoincare/M\nPoiret/M\nPoirot/M\nPoisson/M\nPoitier/M\nPokemon/M\nPol/MY\nPoland/M\nPolanski/M\nPolaris/M\nPolaroid/MS\nPole/SM\nPolish/M\nPolitburo/M\nPolk/M\nPollard/M\nPollock/M\nPollux/M\nPolly/M\nPollyanna/M\nPolo/M\nPoltava/M\nPolyhymnia/M\nPolynesia/M\nPolynesian/MS\nPolyphemus/M\nPomerania/M\nPomeranian/M\nPomona/M\nPompadour/M\nPompeian\nPompeii/M\nPompey/M\nPonce/M\nPontchartrain/M\nPontiac/M\nPontianak/M\nPooh/M\nPoole/M\nPoona/M\nPope/M\nPopeye/M\nPopocatepetl/M\nPopper/M\nPoppins/M\nPopsicle/M\nPorfirio/M\nPorrima/M\nPorsche/M\nPort/MR\nPorter/M\nPortia/M\nPortland/M\nPorto/M\nPortsmouth/M\nPortugal/M\nPortuguese/M\nPoseidon/M\nPost/M\nPotemkin/M\nPotomac/M\nPotsdam/M\nPottawatomie/M\nPotter/M\nPotts/M\nPound/M\nPoussin/M\nPowell/M\nPowerPC/M\nPowerPoint/M\nPowers/M\nPowhatan/M\nPoznan/M\nPr/M\nPrada/M\nPrado/M\nPraetorian/M\nPrague/M\nPraia/M\nPrakrit/M\nPratchett/M\nPratt/M\nPravda/M\nPraxiteles/M\nPreakness/M\nPrecambrian/M\nPreminger/M\nPremyslid/M\nPrensa/M\nPrentice/M\nPres\nPresbyterian/SM\nPresbyterianism/MS\nPrescott/M\nPresley/M\nPreston/M\nPretoria/M\nPriam/M\nPribilof/M\nPrice/M\nPriestley/M\nPrince/M\nPrinceton/M\nPrincipe/M\nPriscilla/M\nPrius/M\nPrivate\nProcrustean/M\nProcrustes/M\nProcter/M\nProcyon/M\nProf\nProhibition\nProkofiev/M\nPromethean/M\nPrometheus/M\nProphets\nProserpina/M\nProserpine/M\nProtagoras/M\nProterozoic/M\nProtestant/MS\nProtestantism/SM\nProteus/M\nProudhon/M\nProust/M\nProvencal/MS\nProvence/M\nProverbs\nProvidence/SM\nProvo/M\nProzac/MS\nPrudence/M\nPrudential/M\nPruitt/M\nPrussia/M\nPrussian/MS\nPrut/M\nPryor/M\nPsalms/M\nPsalter/MS\nPsyche/M\nPt/M\nPtah/M\nPtolemaic/M\nPtolemy/SM\nPu/M\nPuccini/M\nPuck/M\nPuckett/M\nPuebla/M\nPueblo/M\nPuerto\nPuget/M\nPugh/M\nPulaski/M\nPulitzer/M\nPullman/MS\nPunch/M\nPunic/M\nPunjab/M\nPunjabi/M\nPurana/M\nPurcell/M\nPurdue/M\nPurim/MS\nPurina/M\nPuritan/M\nPuritanism/MS\nPurus/M\nPusan/M\nPusey/M\nPushkin/M\nPushtu/M\nPutin/M\nPutnam/M\nPuzo/M\nPvt\nPygmalion/M\nPygmy/SM\nPyle/M\nPym/M\nPynchon/M\nPyongyang/M\nPyotr/M\nPyrenees/M\nPyrex/MS\nPyrrhic/M\nPythagoras/M\nPythagorean/M\nPythias/M\nPython/M\nQ\nQA\nQB\nQC\nQED\nQM\nQWERTY\nQaddafi/M\nQantas/M\nQatar/M\nQatari/MS\nQingdao/M\nQiqihar/M\nQom/M\nQuaalude/M\nQuaker/MS\nQuakerism/SM\nQuaoar/M\nQuasimodo/M\nQuaternary/M\nQuayle/M\nQue\nQuebec/M\nQuebecois/M\nQuechua/M\nQueen/MS\nQueens/M\nQueensland/M\nQuentin/M\nQuetzalcoatl/M\nQuezon/M\nQuincy/M\nQuinn/M\nQuintilian/M\nQuinton/M\nQuirinal/M\nQuisling/M\nQuito/M\nQuixote/M\nQuixotism/M\nQumran/M\nQuonset/M\nR/M\nRAF/M\nRAM/SM\nRBI\nRC\nRCA/M\nRCMP\nRD\nRDA\nREIT\nREM/SM\nRF\nRFC/S\nRFD\nRI\nRIF\nRIP\nRISC\nRN/M\nRNA/M\nROFL\nROM/M\nROTC/M\nRP\nRR\nRSFSR\nRSI\nRSV\nRSVP\nRTFM\nRV/SM\nRa/M\nRabat/M\nRabelais/M\nRabelaisian/M\nRabin/M\nRachael/M\nRachel/M\nRachelle/M\nRachmaninoff/M\nRacine/M\nRadcliffe/M\nRae/M\nRafael/M\nRaffles/M\nRagnarok/M\nRainier/M\nRaleigh/M\nRalph/M\nRama/M\nRamada/M\nRamadan/MS\nRamakrishna/M\nRamanujan/M\nRamayana/M\nRambo/M\nRamirez/M\nRamiro/M\nRamon/M\nRamona/M\nRamos/M\nRamsay/M\nRamses/M\nRamsey/M\nRand/M\nRandal/M\nRandall/M\nRandell/M\nRandi/M\nRandolph/M\nRandy/M\nRangoon/M\nRankin/M\nRankine/M\nRaoul/M\nRaphael/M\nRappaport/M\nRapunzel/M\nRaquel/M\nRasalgethi/M\nRasalhague/M\nRasmussen/M\nRasputin/M\nRasta\nRastaban/M\nRastafarian/MS\nRastafarianism\nRather/M\nRatliff/M\nRaul/M\nRavel/M\nRawalpindi/M\nRay/M\nRayBan/M\nRayburn/M\nRayleigh/M\nRaymond/M\nRaymundo/M\nRb/M\nRd\nRe/M\nReading/M\nReagan/M\nReaganomics/M\nRealtor/M\nReasoner/M\nReba/M\nRebekah/M\nRecife/M\nReconstruction/M\nRedeemer/M\nRedford/M\nRedgrave/M\nRedmond/M\nReebok/M\nReed/M\nReese/M\nReeves/M\nReformation/MS\nRefugio/M\nReggie/M\nRegina/M\nReginae/M\nReginald/M\nRegor/M\nRegulus/M\nRehnquist/M\nReich/M\nReichstag's\nReid/M\nReilly/M\nReinaldo/M\nReinhardt/M\nReinhold/M\nRemarque/M\nRembrandt/M\nRemington/M\nRemus/M\nRena/M\nRenaissance/SM\nRenascence\nRenault/M\nRene/M\nRenee/M\nReno/M\nRenoir/M\nRep\nRepresentative\nRepublican/SM\nRepublicanism\nRequiem/MS\nResistance\nRestoration/M\nResurrection\nReuben/M\nReunion/M\nReuters/M\nReuther/M\nRev\nReva/M\nRevelation/SM\nRevelations/M\nRevere/M\nReverend/M\nRevlon/M\nRex/M\nReyes/M\nReykjavik/M\nReyna/M\nReynaldo/M\nReynolds/M\nRf/M\nRh/M\nRhea/M\nRhee/M\nRheingau/M\nRhenish/M\nRhiannon/M\nRhine/M\nRhineland/M\nRhoda/M\nRhode/S\nRhodes/M\nRhodesia/M\nRhodesian\nRhonda/M\nRhone/M\nRibbentrop/M\nRicardo/M\nRice/M\nRich/M\nRichard/MS\nRichards/M\nRichardson/M\nRichelieu/M\nRichie/M\nRichmond/M\nRichter/M\nRichthofen/M\nRick/M\nRickenbacker/M\nRickey/M\nRickie/M\nRickover/M\nRicky/M\nRico/M\nRiddle/M\nRide/M\nRiefenstahl/M\nRiel/M\nRiemann/M\nRiesling/MS\nRiga/M\nRigel/M\nRiggs/M\nRight\nRigoberto/M\nRigoletto/M\nRiley/M\nRilke/M\nRimbaud/M\nRingling/M\nRingo/M\nRio/SM\nRios/M\nRipley/M\nRisorgimento/M\nRita/M\nRitalin/M\nRitz/M\nRivas/M\nRivera/M\nRivers/M\nRiverside\nRiviera/MS\nRiyadh/M\nRizal/M\nRn/M\nRoach/M\nRoanoke/M\nRob/M\nRobbie/M\nRobbin/MS\nRobbins/M\nRobby/M\nRoberson/M\nRobert/MS\nRoberta/M\nRoberto/M\nRoberts/M\nRobertson/M\nRobeson/M\nRobespierre/M\nRobin/M\nRobinson/M\nRobitussin/M\nRobles/M\nRobson/M\nRobt/M\nRobyn/M\nRocco/M\nRocha/M\nRochambeau/M\nRoche/M\nRochelle/M\nRochester/M\nRock/M\nRockefeller/M\nRockford/M\nRockies/M\nRockne/M\nRockwell/M\nRocky/SM\nRod/M\nRoddenberry/M\nRoderick/M\nRodger/MS\nRodgers/M\nRodin/M\nRodney/M\nRodolfo/M\nRodrick/M\nRodrigo/M\nRodriguez/M\nRodriquez/M\nRoeg/M\nRoentgen\nRogelio/M\nRoger/MS\nRogers/M\nRoget/M\nRojas/M\nRoku/M\nRolaids/M\nRoland/M\nRolando/M\nRolex/M\nRolland/M\nRollerblade/M\nRollins/M\nRolodex/M\nRolvaag/M\nRom\nRoman/MS\nRomanesque/MS\nRomania/M\nRomanian/MS\nRomano/M\nRomanov/M\nRomans/M\nRomansh/M\nRomanticism\nRomany/SM\nRome/SM\nRomeo/M\nRomero/M\nRommel/M\nRomney/M\nRomulus/M\nRon/M\nRonald/M\nRonda/M\nRonnie/M\nRonny/M\nRonstadt/M\nRontgen\nRooney/M\nRoosevelt/M\nRoot/M\nRoquefort/SM\nRorschach/M\nRory/M\nRosa/M\nRosales/M\nRosalie/M\nRosalind/M\nRosalinda/M\nRosalyn/M\nRosanna/M\nRosanne/M\nRosario/M\nRoscoe/M\nRose/M\nRoseann/M\nRoseau/M\nRosecrans/M\nRosella/M\nRosemarie/M\nRosemary/M\nRosenberg/M\nRosendo/M\nRosenzweig/M\nRosetta/M\nRosicrucian/M\nRosie/M\nRoslyn/M\nRoss/M\nRossetti/M\nRossini/M\nRostand/M\nRostov/M\nRostropovich/M\nRoswell/M\nRotarian/M\nRoth/M\nRothko/M\nRothschild/M\nRotterdam/M\nRottweiler/M\nRouault/M\nRourke/M\nRousseau/M\nRove/RM\nRover/M\nRowe/M\nRowena/M\nRowland/M\nRowling/M\nRoxanne/M\nRoxie/M\nRoxy/M\nRoy/M\nRoyal/M\nRoyce/M\nRozelle/M\nRte\nRu/MH\nRubaiyat/M\nRubbermaid/M\nRuben/SM\nRubens/M\nRubicon/MS\nRubik/M\nRubin/M\nRubinstein/M\nRuby/M\nRuchbah/M\nRudolf/M\nRudolph/M\nRudy/M\nRudyard/M\nRufus/M\nRuhr/M\nRuiz/M\nRukeyser/M\nRumpelstiltskin/M\nRumsfeld/M\nRunnymede/M\nRunyon/M\nRupert/M\nRush/M\nRushdie/M\nRushmore/M\nRuskin/M\nRuss/M\nRussel/M\nRussell/M\nRussia/M\nRussian/SM\nRusso/M\nRustbelt/M\nRusty/M\nRutan/M\nRutgers/M\nRuth/M\nRutherford/M\nRuthie/M\nRutledge/M\nRwanda/MS\nRwandan/SM\nRwy\nRx\nRy\nRyan/M\nRydberg/M\nRyder/M\nRyukyu/M\nS/MN\nSA\nSAC\nSALT/M\nSAM/M\nSAP/M\nSARS/M\nSASE\nSAT\nSBA\nSC/M\nSCSI/M\nSD\nSDI\nSE/M\nSEATO\nSEC/M\nSF\nSGML/M\nSIDS/M\nSJ\nSK\nSLR\nSO/S\nSOB/M\nSOP/M\nSOS/M\nSOSes\nSPCA\nSPF\nSQL\nSRO\nSS\nSSA\nSSE/M\nSSS\nSST\nSSW/M\nST\nSTD\nSTOL\nSUSE/M\nSUV\nSVN/M\nSW/M\nSWAK\nSWAT\nSaab/M\nSaar/M\nSaarinen/M\nSaatchi/M\nSabbath/M\nSabbaths\nSabik/M\nSabin/M\nSabina/M\nSabine/M\nSabre/M\nSabrina/M\nSacajawea/M\nSacco/M\nSachs/M\nSacramento/M\nSadat/M\nSaddam/M\nSadducee/M\nSade/M\nSadie/M\nSadr/M\nSafavid/M\nSafeway/M\nSagan/M\nSaginaw/M\nSagittarius/MS\nSahara/M\nSaharan/M\nSahel/M\nSaigon/M\nSaiph/M\nSakai/M\nSakha/M\nSakhalin/M\nSakharov/M\nSaki/M\nSaks/M\nSal/MY\nSaladin/M\nSalado/M\nSalamis/M\nSalas/M\nSalazar/M\nSalem/M\nSalerno/M\nSalinas/M\nSalinger/M\nSalisbury/M\nSalish/M\nSalk/M\nSallie/M\nSallust/M\nSally/M\nSalome/M\nSalonika/M\nSalton/M\nSalvador/M\nSalvadoran/SM\nSalvadorean/MS\nSalvadorian/MS\nSalvatore/M\nSalween/M\nSalyut/M\nSam/M\nSamantha/M\nSamar/M\nSamara/M\nSamaritan/MS\nSamarkand/M\nSammie/M\nSammy/M\nSamoa/M\nSamoan/SM\nSamoset/M\nSamoyed/M\nSampson/M\nSamson/M\nSamsonite/M\nSamsung/M\nSamuel/M\nSamuelson/M\nSan'a\nSan/M\nSana/M\nSanchez/M\nSancho/M\nSand/ZM\nSandburg/M\nSanders/M\nSandinista/M\nSandoval/M\nSandra/M\nSandy/M\nSanford/M\nSanforized/M\nSang/MR\nSanger/M\nSanhedrin/M\nSanka/M\nSankara/M\nSanskrit/M\nSanta/M\nSantana/M\nSantayana/M\nSanteria/M\nSantiago/M\nSantos/M\nSappho/M\nSapporo/M\nSara/M\nSaracen/MS\nSaragossa/M\nSarah/M\nSarajevo/M\nSaran/M\nSarasota/M\nSaratov/M\nSarawak/M\nSardinia/M\nSargasso/M\nSargent/M\nSargon/M\nSarnoff/M\nSaroyan/M\nSarto/M\nSartre/M\nSasha/M\nSask\nSaskatchewan/M\nSaskatoon/M\nSasquatch/MS\nSassanian/M\nSassoon/M\nSat/M\nSatan/M\nSatanism/M\nSatanist/M\nSaturday/MS\nSaturn/M\nSaturnalia/M\nSaudi/MS\nSaul/M\nSaunders/M\nSaundra/M\nSaussure/M\nSauternes\nSavage/M\nSavannah/M\nSavior/M\nSavonarola/M\nSavoy/M\nSavoyard/M\nSawyer/M\nSaxon/MS\nSaxony/M\nSayers/M\nSb/M\nSc/M\nScala/M\nScan\nScandinavia/M\nScandinavian/MS\nScaramouch/M\nScarborough/M\nScarlatti/M\nScheat/M\nSchedar/M\nScheherazade/M\nSchelling/M\nSchenectady/M\nSchiaparelli/M\nSchick/M\nSchiller/M\nSchindler/M\nSchlesinger/M\nSchliemann/M\nSchlitz/M\nSchmidt/M\nSchnabel/M\nSchnauzer/M\nSchneider/M\nSchoenberg/M\nSchopenhauer/M\nSchrieffer/M\nSchrodinger/M\nSchroeder/M\nSchubert/M\nSchultz/M\nSchulz/M\nSchumann/M\nSchumpeter/M\nSchuyler/M\nSchuylkill/M\nSchwartz/M\nSchwarzenegger/M\nSchwarzkopf/M\nSchweitzer/M\nSchweppes/M\nSchwinger/M\nSchwinn/M\nScientologist/SM\nScientology/M\nScipio/M\nScopes/M\nScorpio/SM\nScorpius/M\nScorsese/M\nScot/SM\nScotch/MS\nScotchman/M\nScotchmen/M\nScotchwoman/M\nScotchwomen/M\nScotia/M\nScotland/M\nScotsman/M\nScotsmen/M\nScotswoman/M\nScotswomen/M\nScott/M\nScottie/SM\nScottish/M\nScottsdale/M\nScrabble/MS\nScranton/M\nScriabin/M\nScribner/M\nScripture/SM\nScrooge/M\nScruggs/M\nScud/M\nSculley/M\nScylla/M\nScythia/M\nScythian/M\nSe/MH\nSeaborg/M\nSeagram/M\nSean/M\nSears/M\nSeattle/M\nSebastian/M\nSec\nSeconal/M\nSecretariat/M\nSecretary\nSeder/MS\nSedna/M\nSeebeck/M\nSeeger/M\nSega/M\nSegovia/M\nSegre/M\nSegundo/M\nSeiko/M\nSeine/M\nSeinfeld/M\nSejong/M\nSelassie/M\nSelectric/M\nSelena/M\nSeleucid/M\nSeleucus/M\nSelim/M\nSeljuk/M\nSelkirk/M\nSellers/M\nSelma/M\nSelznick/M\nSemarang/M\nSeminole/MS\nSemiramis/M\nSemite/MS\nSemitic/SM\nSemtex/M\nSenate/MS\nSendai/M\nSeneca/MS\nSenegal/M\nSenegalese/M\nSenghor/M\nSenior/M\nSennacherib/M\nSennett/M\nSensurround/M\nSeoul/M\nSep\nSephardi/M\nSepoy/M\nSept/M\nSeptember/MS\nSeptuagint/MS\nSequoya/M\nSerb/SM\nSerbia/M\nSerbian/MS\nSerena/M\nSerengeti/M\nSergei/M\nSergio/M\nSerpens/M\nSerra/M\nSerrano/M\nSet/M\nSeth/M\nSeton/M\nSeurat/M\nSeuss/M\nSevastopol/M\nSevern/M\nSeverus/M\nSeville/M\nSevres/M\nSeward/M\nSextans/M\nSexton/M\nSeychelles/M\nSeyfert/M\nSeymour/M\nSgt\nShackleton/M\nShaffer/M\nShaka/M\nShaker\nShakespeare/M\nShakespearean/M\nShana/M\nShane/M\nShanghai/M\nShankara/M\nShanna/M\nShannon/M\nShantung/M\nShapiro/M\nShari'a/M\nShari/M\nSharif/M\nSharlene/M\nSharon/M\nSharp/M\nSharpe/M\nSharron/M\nShasta/M\nShaula/M\nShaun/M\nShauna/M\nShavian/M\nShavuot/M\nShaw/M\nShawn/M\nShawna/M\nShawnee/SM\nShcharansky/M\nShea/M\nSheba/M\nShebeli/M\nSheena/M\nSheetrock/M\nSheffield/M\nSheila/M\nShelby/M\nSheldon/M\nShelia/M\nShell/M\nShelley/M\nShelly/M\nShelton/M\nShenandoah/M\nShenyang/M\nSheol/M\nShepard/M\nShepherd/M\nSheppard/M\nSheratan/M\nSheraton/M\nSheree/M\nSheri/M\nSheridan/M\nSherlock/M\nSherman/M\nSherpa/M\nSherri/M\nSherrie/M\nSherry/M\nSherwood/M\nSheryl/M\nShetland/SM\nShetlands/M\nShevardnadze/M\nShevat/M\nShi'ite/M\nShields/M\nShiite/MS\nShijiazhuang/M\nShikoku/M\nShillong/M\nShiloh/M\nShinto/MS\nShintoism/MS\nShintoist/MS\nShiraz/M\nShirley/M\nShiva/M\nShockley/M\nShort/M\nShorthorn/M\nShoshone/SM\nShostakovitch/M\nShrek/M\nShreveport/M\nShriner/M\nShropshire/M\nShula/M\nShylock/M\nShylockian/M\nSi/M\nSiam/M\nSiamese/M\nSibelius/M\nSiberia/M\nSiberian/MS\nSibyl/M\nSicilian/SM\nSicily/M\nSid/M\nSiddhartha/M\nSidney/M\nSiegfried/M\nSiemens/M\nSierpinski/M\nSierras\nSigismund/M\nSigmund/M\nSigurd/M\nSihanouk/M\nSikh/M\nSikhism\nSikhs\nSikkim/M\nSikkimese/M\nSikorsky/M\nSilas/M\nSilesia/M\nSilurian/SM\nSilva/M\nSilvia/M\nSimenon/M\nSimmental/M\nSimmons/M\nSimon/M\nSimone/M\nSimpson/SM\nSimpsons/M\nSims/M\nSinai/M\nSinatra/M\nSinbad/M\nSinclair/M\nSindbad/M\nSindhi/M\nSingapore/M\nSingaporean/SM\nSinger/M\nSingh/M\nSingleton/M\nSinhalese/M\nSinkiang/M\nSioux/M\nSir/SM\nSirius/M\nSistine/M\nSisyphean/M\nSisyphus/M\nSiva/M\nSivan/M\nSjaelland/M\nSkinner/M\nSkippy/M\nSkopje/M\nSkye/M\nSkylab/M\nSkype/M\nSlackware/M\nSlashdot/M\nSlater/M\nSlav/SM\nSlavic/M\nSlavonic/M\nSlinky/M\nSloan/M\nSloane/M\nSlocum/M\nSlovak/SM\nSlovakia/M\nSlovakian\nSlovene/SM\nSlovenia/M\nSlovenian/MS\nSlurpee/M\nSm/M\nSmall/M\nSmetana/M\nSmirnoff/M\nSmith/M\nSmithson/M\nSmithsonian/M\nSmokey/M\nSmolensk/M\nSmollett/M\nSmuts/M\nSmyrna\nSn/M\nSnake/M\nSnapple/M\nSnead/M\nSnell/M\nSnickers/M\nSnider/M\nSnoopy/M\nSnow/M\nSnowbelt/M\nSnyder/M\nSoave/M\nSoc\nSocorro/M\nSocrates/M\nSocratic/M\nSoddy/M\nSodom/M\nSofia/M\nSoho/M\nSol/M\nSolis/M\nSolomon/M\nSolon/M\nSolzhenitsyn/M\nSomali/SM\nSomalia/M\nSomalian/MS\nSomme/M\nSomoza/M\nSon/M\nSondheim/M\nSondra/M\nSonghai/M\nSonghua/M\nSonia/M\nSonja/M\nSonny/M\nSonora/M\nSontag/M\nSony/M\nSonya/M\nSophia/M\nSophie/M\nSophoclean/M\nSophocles/M\nSopwith/M\nSorbonne/M\nSosa/M\nSoto/M\nSouphanouvong/M\nSourceforge/M\nSousa/M\nSouth/M\nSouthampton/M\nSoutheast/MS\nSoutherner/SM\nSouthey/M\nSouths\nSouthwest/MS\nSoviet/M\nSoweto/M\nSoyinka/M\nSoyuz/M\nSp\nSpaatz/M\nSpackle/M\nSpahn/M\nSpain/M\nSpam/M\nSpan\nSpanglish\nSpaniard/SM\nSpanish/M\nSparks/M\nSparta/M\nSpartacus/M\nSpartan/MS\nSpears/M\nSpeer/M\nSpence/RM\nSpencer/M\nSpencerian/M\nSpengler/M\nSpenglerian/M\nSpenser/M\nSpenserian/M\nSperry/M\nSphinx/M\nSpica/M\nSpielberg/M\nSpillane/M\nSpinoza/M\nSpinx/M\nSpiro/M\nSpirograph/M\nSpitsbergen/M\nSpitz/M\nSpock/M\nSpokane/M\nSpringfield/M\nSpringsteen/M\nSprint/M\nSprite/M\nSputnik/M\nSq\nSquanto/M\nSquibb/M\nSr/M\nSrinagar/M\nSrivijaya/M\nSt\nSta\nStacey/M\nStaci/M\nStacie/M\nStacy/M\nStael/M\nStafford/M\nStairMaster/M\nStalin/M\nStalingrad/M\nStalinist/M\nStallone/M\nStamford/M\nStan/M\nStandish/M\nStanford/M\nStanislavsky/M\nStanley/M\nStanton/M\nStaples/M\nStarbucks/M\nStark/M\nStarkey/M\nStarr/M\nStaten/M\nStates\nStaubach/M\nSte\nSteadicam/M\nSteele/M\nStefan/M\nStefanie/M\nStein/MR\nSteinbeck/M\nSteinem/M\nSteiner/M\nSteinmetz/M\nSteinway/M\nStella/M\nStendhal/M\nStengel/M\nStephan/M\nStephanie/M\nStephen/MS\nStephens/M\nStephenson/M\nSterling/M\nStern/M\nSterne/M\nSterno/M\nStetson/M\nSteuben/M\nSteve/M\nSteven/MS\nStevens/M\nStevenson/M\nStevie/M\nStewart/M\nStieglitz/M\nStilton/SM\nStimson/M\nStine/M\nStirling/M\nStockhausen/M\nStockholm/M\nStockton/M\nStoic/SM\nStoicism/MS\nStokes/M\nStolichnaya/M\nStolypin/M\nStone/M\nStonehenge/M\nStoppard/M\nStout/M\nStowe/M\nStrabo/M\nStradivari\nStradivarius/M\nStrasbourg/M\nStrauss/M\nStravinsky/M\nStreisand/M\nStrickland/M\nStrindberg/M\nStromboli/M\nStrong/M\nStu/M\nStuart/MS\nStudebaker/M\nStuttgart/M\nStuyvesant/M\nStygian/M\nStyrofoam/SM\nStyron/M\nStyx/M\nSuarez/M\nSubaru/M\nSucre/M\nSucrets/M\nSudan/M\nSudanese/M\nSudetenland/M\nSudoku/M\nSudra/M\nSue/M\nSuetonius/M\nSuez/M\nSuffolk/M\nSufi/M\nSufism/M\nSuharto/M\nSui/M\nSukarno/M\nSukkot\nSulawesi/M\nSuleiman/M\nSulla/M\nSullivan/M\nSumatra/M\nSumatran/SM\nSumeria/M\nSumerian/SM\nSummer/MS\nSummers/M\nSumner/M\nSumter/M\nSun/SM\nSunbeam/M\nSunbelt/M\nSundanese/M\nSundas/M\nSunday/MS\nSung/M\nSunkist/M\nSunni/SM\nSunnite/MS\nSunnyvale/M\nSuperbowl/M\nSuperfund/M\nSuperglue/M\nSuperior/M\nSuperman/M\nSupt\nSurabaya/M\nSurat/M\nSuriname/M\nSurinamese\nSurya/M\nSusan/M\nSusana/M\nSusanna/M\nSusanne/M\nSusie/M\nSusquehanna/M\nSussex/M\nSutherland/M\nSutton/M\nSuva/M\nSuwanee/M\nSuzanne/M\nSuzette/M\nSuzhou/M\nSuzuki/M\nSuzy/M\nSvalbard/M\nSven/M\nSvengali/M\nSverdlovsk\nSwahili/SM\nSwammerdam/M\nSwanee/M\nSwansea/M\nSwanson/M\nSwazi/SM\nSwaziland/M\nSwed/N\nSwede/SM\nSweden/M\nSwedenborg/M\nSwedish/M\nSweeney/M\nSweet/M\nSwift/M\nSwinburne/M\nSwiss/MS\nSwissair/M\nSwitz\nSwitzerland/M\nSybil/M\nSydney/M\nSykes/M\nSylvester/M\nSylvia/M\nSylvie/M\nSynge/M\nSyracuse/M\nSyria/M\nSyriac/M\nSyrian/MS\nSzilard/M\nSzymborska/M\nT'ang/M\nT/MDG\nTA\nTARP\nTB/M\nTBA\nTD\nTDD\nTEFL\nTELNET/S\nTELNETTed\nTELNETTing\nTESL\nTESOL\nTGIF\nTHC\nTKO/M\nTLC/M\nTM\nTN\nTNT/M\nTOEFL\nTQM\nTV/SM\nTVA\nTWA/M\nTWX\nTX\nTa/M\nTabasco/SM\nTabatha/M\nTabernacle/MS\nTabitha/M\nTabriz/MS\nTacitus/M\nTacoma/M\nTad/M\nTadzhik/M\nTaegu/M\nTaejon/M\nTaft/M\nTagalog/SM\nTagore/M\nTagus/M\nTahiti/M\nTahitian/MS\nTahoe/M\nTaichung/M\nTainan\nTaine/M\nTaipei/M\nTaiping/M\nTaiwan/M\nTaiwanese/M\nTaiyuan/M\nTajikistan/M\nTaklamakan/M\nTalbot/M\nTaliban/M\nTaliesin/M\nTallahassee/M\nTallchief/M\nTalley/M\nTalleyrand/M\nTallinn/M\nTalmud/MS\nTalmudic\nTalmudist\nTamara/M\nTameka/M\nTamera/M\nTamerlane/M\nTami/M\nTamika/M\nTamil/MS\nTammany/M\nTammi/M\nTammie/M\nTammuz/M\nTammy/M\nTampa/M\nTampax/M\nTamra/M\nTamworth/M\nTancred/M\nTaney/M\nTanganyika/M\nTangier/MS\nTangshan/M\nTania/M\nTanisha/M\nTanner/M\nTannhauser/M\nTantalus/M\nTanya/M\nTanzania/M\nTanzanian/SM\nTao/M\nTaoism/MS\nTaoist/MS\nTara/M\nTarantino/M\nTarawa/M\nTarazed/M\nTarbell/M\nTarget/M\nTarim/M\nTarkenton/M\nTarkington/M\nTartary/M\nTartuffe/M\nTarzan/M\nTasha/M\nTashkent/M\nTasman/M\nTasmania/M\nTasmanian/M\nTass/M\nTatar/MS\nTate/M\nTatum/M\nTaurus/MS\nTawney/M\nTaylor/M\nTb/M\nTbilisi/M\nTc/M\nTchaikovsky/M\nTe/M\nTeX\nTeXes\nTeasdale/M\nTechnicolor/M\nTecumseh/M\nTed/M\nTeddy/M\nTeflon/MS\nTegucigalpa/M\nTehran\nTelePrompTer\nTelePrompter/M\nTelemachus/M\nTelemann/M\nTeletype\nTell/MR\nTeller/M\nTelugu/M\nTempe\nTemplar/M\nTenn/M\nTennessean/SM\nTennessee/M\nTennyson/M\nTenochtitlan/M\nTeotihuacan/M\nTerence/M\nTeresa/M\nTereshkova/M\nTeri/M\nTerkel/M\nTerpsichore/M\nTerr/M\nTerra/M\nTerran/M\nTerrance/M\nTerrell/M\nTerrence/M\nTerri/M\nTerrie/M\nTerry/M\nTertiary/M\nTesla/M\nTess/M\nTessa/M\nTessie/M\nTet/M\nTethys/M\nTetons/M\nTeuton/MS\nTeutonic/M\nTevet/M\nTex/M\nTexaco/M\nTexan/MS\nTexas/M\nTh/M\nThackeray/M\nThad/M\nThaddeus/M\nThai/SM\nThailand/M\nThales/M\nThalia/M\nThames/M\nThanh/M\nThanksgiving/MS\nThant/M\nThar/M\nTharp/M\nThatcher/M\nThea/M\nThebes/M\nTheiler/M\nThelma/M\nThemistocles/M\nTheocritus/M\nTheodora/M\nTheodore/M\nTheodoric/M\nTheodosius/M\nTheosophy/M\nTheravada/M\nTheresa/M\nTherese/M\nThermopylae/M\nThermos\nTheron/M\nTheseus/M\nThespian/M\nThespis/M\nThessalonian/SM\nThessaloniki/M\nThessaly/M\nThieu/M\nThimbu/M\nThimphu\nThomas/M\nThomism/M\nThomistic/M\nThompson/M\nThomson/M\nThor/M\nThorazine/M\nThoreau/M\nThornton/M\nThoroughbred/M\nThorpe/M\nThoth/M\nThrace/M\nThracian/M\nThu\nThucydides/M\nThule/M\nThunderbird/M\nThur/S\nThurber/M\nThurman/M\nThurmond/M\nThursday/SM\nThutmose/M\nTi/M\nTia/M\nTianjin/M\nTiber/M\nTiberius/M\nTibet/M\nTibetan/MS\nTicketmaster/M\nTiconderoga/M\nTide/M\nTienanmen/M\nTiffany/M\nTigris/M\nTijuana/M\nTillich/M\nTillman/M\nTilsit/M\nTim/M\nTimbuktu/M\nTimex/M\nTimmy/M\nTimon/M\nTimor/M\nTimothy/M\nTimur/M\nTimurid/M\nTina/M\nTing/M\nTinkerbell/M\nTinkertoy/M\nTinseltown/M\nTintoretto/M\nTippecanoe/M\nTipperary/M\nTirane\nTiresias/M\nTirol/M\nTirolean\nTisha/M\nTishri/M\nTitan/SM\nTitania/M\nTitanic/M\nTitian/M\nTiticaca/M\nTito/M\nTitus/M\nTl/M\nTlaloc/M\nTlingit/M\nTm/M\nTobago/M\nTobit/M\nToby/M\nTocantins/M\nTocqueville/M\nTod/M\nTodd/M\nTogo/M\nTogolese/M\nTojo/M\nTokay/M\nTokugawa/M\nTokyo/M\nTokyoite\nToledo/MS\nTolkien/M\nTolstoy/M\nToltec/M\nTolyatti/M\nTom/M\nTomas/M\nTombaugh/M\nTomlin/M\nTommie/M\nTommy/M\nTompkins/M\nTomsk/M\nTonga/M\nTongan/MS\nToni/M\nTonia/M\nTonto/M\nTony/M\nTonya/M\nTopeka/M\nTopsy/M\nTorah/M\nTorahs\nToronto/M\nTorquemada/M\nTorrance/M\nTorrens/M\nTorres/M\nTorricelli/M\nTortola/M\nTortuga/M\nTorvalds/M\nTory/SM\nTosca/M\nToscanini/M\nToshiba/M\nToto/M\nToulouse/M\nTownes/M\nTownsend/M\nToynbee/M\nToyoda/M\nToyota/M\nTracey/M\nTraci/M\nTracie/M\nTracy/M\nTrafalgar/M\nTrailways/M\nTrajan/M\nTran/M\nTranscaucasia/M\nTransvaal/M\nTransylvania/M\nTransylvanian/M\nTrappist/SM\nTravis/M\nTravolta/M\nTreasury/SM\nTreblinka/M\nTrekkie/M\nTrent/M\nTrenton/M\nTrevelyan/M\nTrevino/M\nTrevor/M\nTrey/M\nTriangulum/M\nTriassic/M\nTricia/M\nTrident/M\nTrieste/M\nTrimurti/M\nTrina/M\nTrinidad/M\nTrinidadian/MS\nTrinity/SM\nTripitaka/M\nTripoli/M\nTrippe/M\nTrisha/M\nTristan/M\nTriton/M\nTrobriand/M\nTroilus/M\nTrojan/MS\nTrollope/M\nTrondheim/M\nTropicana/M\nTrotsky/M\nTroy/M\nTroyes\nTruckee/M\nTrudeau/M\nTrudy/M\nTruffaut/M\nTrujillo/M\nTruman/M\nTrumbull/M\nTrump/M\nTruth/M\nTsimshian/M\nTsiolkovsky/M\nTsitsihar/M\nTsongkhapa/M\nTswana/M\nTu/M\nTuamotu/M\nTuareg/M\nTubman/M\nTucker/M\nTucson/M\nTucuman/M\nTudor/SM\nTue/S\nTues/M\nTuesday/MS\nTulane/M\nTull/M\nTulsa/M\nTulsidas/M\nTums/M\nTungus/M\nTunguska/M\nTunis/M\nTunisia/M\nTunisian/MS\nTunney/M\nTupi/M\nTupperware/M\nTupungato/M\nTurgenev/M\nTurin/M\nTuring/M\nTurk/SM\nTurkestan/M\nTurkey/M\nTurkic/MS\nTurkish/M\nTurkmenistan/M\nTurner/M\nTurpin/M\nTuscaloosa/M\nTuscan/M\nTuscany/M\nTuscarora/MS\nTuscon/M\nTuskegee/M\nTussaud/M\nTut/M\nTutankhamen/M\nTutsi/M\nTutu/M\nTuvalu/M\nTuvaluan\nTwain/M\nTweed/M\nTweedledee/M\nTweedledum/M\nTwila/M\nTwinkies/M\nTwitter/M\nTwizzlers/M\nTwp\nTy/M\nTycho/M\nTylenol/M\nTyler/M\nTyndale/M\nTyndall/M\nTyre/M\nTyree/M\nTyrolean\nTyrone/M\nTyson/M\nU/M\nUAR\nUAW\nUBS/M\nUCLA/M\nUFO/SM\nUHF/M\nUK/M\nUL\nUN/M\nUNESCO/M\nUNICEF/M\nUNIX/M\nUPC\nUPI/M\nUPS/M\nURL/S\nUS/M\nUSA/M\nUSAF\nUSB\nUSCG\nUSDA/M\nUSIA\nUSMC\nUSN\nUSO\nUSP\nUSPS\nUSS\nUSSR/M\nUT/M\nUTC\nUV/M\nUbangi/M\nUbuntu/M\nUcayali/M\nUccello/M\nUdall/M\nUfa/M\nUganda/M\nUgandan/MS\nUighur/M\nUjungpandang/M\nUkraine/M\nUkrainian/SM\nUlster/M\nUltrasuede/M\nUlyanovsk/M\nUlysses/M\nUmbriel/M\nUnderwood/M\nUngava/M\nUnicode/M\nUnilever/M\nUnion/SM\nUnionist\nUniroyal/M\nUnitarian/MS\nUnitarianism/MS\nUnitas/M\nUnix/S\nUnukalhai/M\nUpanishads/M\nUpdike/M\nUpjohn/M\nUpton/M\nUr/M\nUral/SM\nUrals/M\nUrania/M\nUranus/M\nUrban/M\nUrdu/M\nUrey/M\nUriah/M\nUriel/M\nUris/M\nUrquhart/M\nUrsa/M\nUrsula/M\nUrsuline/M\nUruguay/M\nUruguayan/MS\nUrumqi/M\nUsenet/MS\nUstinov/M\nUtah/M\nUtahan/MS\nUte/SM\nUtopia/SM\nUtopian/SM\nUtrecht/M\nUtrillo/M\nUzbek/M\nUzbekistan/M\nUzi/SM\nV/M\nVA\nVAT/M\nVAX\nVAXes\nVCR/M\nVD/M\nVDT\nVDU\nVF\nVFW/M\nVG\nVGA\nVHF/M\nVHS\nVI/M\nVIP/SM\nVISTA\nVJ\nVLF/M\nVOA\nVP\nVT\nVTOL\nVa/M\nVader/M\nVaduz/M\nVal/M\nValarie/M\nValdez/M\nValencia/SM\nValenti/M\nValentin/M\nValentine/M\nValentino/M\nValenzuela/M\nValeria/M\nValerian/M\nValerie/M\nValery/M\nValhalla/M\nValium/MS\nValkyrie/SM\nVallejo\nValletta/M\nValois/M\nValparaiso/M\nValvoline/M\nVan/M\nVance/M\nVancouver/M\nVandal/MS\nVanderbilt/M\nVandyke/M\nVanessa/M\nVang/M\nVanuatu/M\nVanzetti/M\nVaranasi/M\nVarese/M\nVargas/M\nVaseline/SM\nVasquez/M\nVassar/M\nVatican/M\nVauban/M\nVaughan/M\nVaughn/M\nVazquez/M\nVeblen/M\nVeda/SM\nVedanta/M\nVega/SM\nVegas/M\nVegemite/M\nVela/M\nVelasquez/M\nVelazquez/M\nVelcro/MS\nVelez/M\nVelma/M\nVelveeta/M\nVenetian/SM\nVenezuela/M\nVenezuelan/SM\nVenice/M\nVenn/M\nVentolin/M\nVenus/MS\nVenusian/M\nVera/M\nVeracruz/M\nVerde/M\nVerdi/M\nVerdun/M\nVerizon/M\nVerlaine/M\nVermeer/M\nVermont/ZMR\nVermonter/M\nVern/M\nVerna/M\nVerne/M\nVernon/M\nVerona/M\nVeronese/M\nVeronica/M\nVersailles/M\nVesalius/M\nVespasian/M\nVespucci/M\nVesta/M\nVesuvius/M\nViacom/M\nViagra/M\nVic/M\nVicente/M\nVichy/M\nVicki/M\nVickie/M\nVicksburg/M\nVicky/M\nVictor/M\nVictoria/M\nVictorian/MS\nVictorianism\nVictrola/M\nVidal/M\nVienna/M\nViennese/M\nVientiane/M\nVietcong/M\nVietminh/M\nVietnam/M\nVietnamese/M\nVijayanagar/M\nVijayawada/M\nViking/MS\nVila/M\nVilla/M\nVillarreal/M\nVillon/M\nVilma/M\nVilnius/M\nVilyui/M\nVince/M\nVincent/M\nVindemiatrix/M\nVinson/M\nViola/M\nViolet/M\nVirgie/M\nVirgil/M\nVirginia/M\nVirginian/SM\nVirgo/SM\nVisa/M\nVisayans/M\nVishnu/M\nVisigoth/M\nVisigoths\nVistula/M\nVitim/M\nVito/M\nVitus/M\nVivaldi/M\nVivekananda/M\nVivian/M\nVivienne/M\nVlad/M\nVladimir/M\nVladivostok/M\nVlaminck/M\nVlasic/M\nVogue/M\nVolcker/M\nVoldemort/M\nVolga/M\nVolgograd/M\nVolkswagen/M\nVolstead/M\nVolta/M\nVoltaire/M\nVolvo/M\nVonda/M\nVonnegut/M\nVoronezh/M\nVorster/M\nVoyager/M\nVt\nVuitton/M\nVulcan/M\nVulg\nVulgate/SM\nW/MDT\nWA\nWAC\nWASP/M\nWATS/M\nWC\nWHO/M\nWI\nWMD\nWNW/M\nWP\nWSW/M\nWTO\nWV\nWW\nWWI\nWWII\nWWW/M\nWY\nWYSIWYG\nWabash/M\nWac\nWaco/M\nWade/M\nWagner/M\nWagnerian/M\nWahhabi/M\nWaikiki/M\nWaite/M\nWake/M\nWaksman/M\nWald/MN\nWaldemar/M\nWalden/M\nWaldensian/M\nWaldheim/M\nWaldo/M\nWaldorf/M\nWales/M\nWalesa/M\nWalgreen/M\nWalker/M\nWalkman/M\nWall/SMR\nWallace/M\nWallenstein/M\nWaller/M\nWallis/M\nWalloon/M\nWalls/M\nWalmart/M\nWalpole/M\nWalpurgisnacht/M\nWalsh/M\nWalt/MRZ\nWalter/M\nWalters/M\nWalton/M\nWanamaker/M\nWanda/M\nWang/M\nWankel/M\nWard/M\nWare/MG\nWarhol/M\nWaring/M\nWarner/M\nWarren/M\nWarsaw/M\nWarwick/M\nWasatch/M\nWash/M\nWashington/M\nWashingtonian/MS\nWassermann/M\nWaterbury/M\nWaterford/M\nWatergate/M\nWaterloo/MS\nWaters/M\nWatkins/M\nWatson/M\nWatt/SM\nWatteau/M\nWatts/M\nWatusi/M\nWaugh/M\nWave\nWayne/M\nWeaver/M\nWeb/MR\nWebb/M\nWeber/M\nWebern/M\nWebster/MS\nWed/M\nWeddell/M\nWedgwood/M\nWednesday/MS\nWeeks/M\nWehrmacht/M\nWei/M\nWeierstrass/M\nWeill/M\nWeinberg/M\nWeiss/M\nWeissmuller/M\nWeizmann/M\nWeldon/M\nWelland/M\nWeller/M\nWelles/M\nWellington/SM\nWells/M\nWelsh/M\nWelshman/M\nWelshmen/M\nWelshwoman\nWendell/M\nWendi/M\nWendy/M\nWesak/M\nWesley/M\nWesleyan/M\nWessex/M\nWesson/M\nWest/SM\nWestern/MRS\nWestinghouse/M\nWestminster/M\nWeston/M\nWestphalia/M\nWeyden/M\nWezen/M\nWharton/M\nWheaties/M\nWheatstone/M\nWheeler/M\nWheeling/M\nWhig/SM\nWhipple/M\nWhirlpool/M\nWhistler/M\nWhitaker/M\nWhite/SM\nWhitefield/M\nWhitehall/M\nWhitehead/M\nWhitehorse/M\nWhiteley/M\nWhitfield/M\nWhitley/M\nWhitman/M\nWhitney/M\nWhitsunday/MS\nWhittier/M\nWiFi\nWicca/M\nWichita/M\nWiemar/M\nWiesel/M\nWiesenthal/M\nWiggins/M\nWigner/M\nWii/M\nWikileaks\nWikipedia/M\nWilberforce/M\nWilbert/M\nWilbur/M\nWilburn/M\nWilcox/M\nWilda/M\nWilde/MR\nWilder/M\nWiles/M\nWiley/M\nWilford/M\nWilfred/M\nWilfredo/M\nWilhelm/M\nWilhelmina/M\nWilkerson/M\nWilkes/M\nWilkins/M\nWilkinson/M\nWill/M\nWilla/M\nWillamette/M\nWillard/M\nWillemstad/M\nWilliam/SM\nWilliams/M\nWilliamson/M\nWillie/M\nWillis/M\nWilly/M\nWilma/M\nWilmer/M\nWilmington/M\nWilson/M\nWilsonian/M\nWilton/M\nWimbledon/M\nWimsey/M\nWinchell/M\nWinchester/MS\nWindbreaker/M\nWindex/M\nWindhoek/M\nWindows/M\nWindsor/SM\nWindward/M\nWinesap/M\nWinfred/M\nWinfrey/M\nWinifred/M\nWinkle/M\nWinnebago/M\nWinnie/M\nWinnipeg/M\nWinston/M\nWinters/M\nWinthrop/M\nWis\nWisc\nWisconsin/M\nWisconsinite/MS\nWise/M\nWitt/M\nWittgenstein/M\nWitwatersrand/M\nWm/M\nWobegon/M\nWodehouse/M\nWolf/M\nWolfe/M\nWolff/M\nWolfgang/M\nWollongong/M\nWollstonecraft/M\nWolsey/M\nWolverhampton\nWonder/M\nWonderbra/M\nWong/M\nWood/SM\nWoodard/M\nWoodhull/M\nWoodrow/M\nWoods/M\nWoodstock/M\nWoodward/M\nWoolf/M\nWoolite/M\nWoolongong/M\nWoolworth/M\nWooster/M\nWooten/M\nWorcester/SM\nWorcestershire/M\nWordsworth/M\nWorkman/M\nWorms/M\nWotan/M\nWovoka/M\nWozniak/M\nWozzeck/M\nWrangell/M\nWren/M\nWright/M\nWrigley/M\nWroclaw/M\nWu/M\nWuhan/M\nWurlitzer/M\nWyatt/M\nWycherley/M\nWycliffe/M\nWyeth/M\nWylie/M\nWynn/M\nWyo\nWyoming/M\nWyomingite/SM\nX/M\nXEmacs/M\nXL/M\nXML\nXS\nXXL\nXanadu/M\nXanthippe/M\nXavier/M\nXe/SM\nXenakis/M\nXenia/M\nXenophon/M\nXerox/MS\nXerxes/M\nXhosa/M\nXi'an/M\nXian/SM\nXiaoping/M\nXimenes/M\nXingu/M\nXiongnu/M\nXmas/MS\nXochipilli/M\nXuzhou/M\nY/M\nYMCA/M\nYMHA\nYMMV\nYT\nYWCA/M\nYWHA\nYacc/M\nYahoo/M\nYahtzee/M\nYahweh/M\nYakima/M\nYakut/M\nYakutsk/M\nYale/M\nYalow/M\nYalta/M\nYalu/M\nYamagata/M\nYamaha/M\nYamoussoukro/M\nYang/M\nYangon/M\nYangtze/M\nYank/SM\nYankee/SM\nYaobang/M\nYaounde/M\nYaqui/M\nYaren\nYaroslavl/M\nYataro/M\nYates/M\nYb/M\nYeager/M\nYeats/M\nYekaterinburg/M\nYellowknife/M\nYellowstone/M\nYeltsin/M\nYemen/M\nYemeni/SM\nYemenite\nYenisei/M\nYerevan/M\nYerkes/M\nYesenia/M\nYevtushenko/M\nYggdrasil/M\nYiddish/M\nYmir/M\nYoda/M\nYoknapatawpha/M\nYoko/M\nYokohama/M\nYolanda/M\nYong/M\nYonkers/M\nYork/M\nYorkie/M\nYorkshire/MS\nYorktown/M\nYoruba/M\nYosemite/M\nYossarian/M\nYouTube/M\nYoung/M\nYoungstown/M\nYpres/M\nYpsilanti/M\nYuan/M\nYucatan/M\nYugo/M\nYugoslav/MS\nYugoslavia/M\nYugoslavian/SM\nYukon/M\nYule/SM\nYuletide/MS\nYuma/SM\nYunnan/M\nYuri/M\nYves/M\nYvette/M\nYvonne/M\nZ/SMNXT\nZachariah/M\nZachary/M\nZachery/M\nZagreb/M\nZaire/M\nZairian\nZambezi/M\nZambia/M\nZambian/SM\nZamboni/M\nZamenhof/M\nZamora/M\nZane/M\nZanuck/M\nZanzibar/M\nZapata/M\nZaporozhye/M\nZapotec/M\nZappa/M\nZara/M\nZarathustra/M\nZealand/M\nZebedee/M\nZechariah/M\nZedekiah/M\nZedong/M\nZeffirelli/M\nZeke/M\nZelig/M\nZelma/M\nZen/M\nZenger/M\nZeno/M\nZephaniah/M\nZephyrus/M\nZest/M\nZeus/M\nZhdanov\nZhengzhou/M\nZhivago/M\nZhukov/M\nZibo/M\nZiegfeld/M\nZiegler/M\nZiggy/M\nZimbabwe/M\nZimbabwean/SM\nZimmerman/M\nZinfandel/M\nZion/SM\nZionism/SM\nZionist/SM\nZiploc/M\nZn/M\nZoe/M\nZola/M\nZollverein/M\nZoloft/M\nZomba/M\nZorn/M\nZoroaster/M\nZoroastrian/MS\nZoroastrianism/SM\nZorro/M\nZosma/M\nZr/M\nZsigmondy/M\nZubenelgenubi/M\nZubeneschamali/M\nZukor/M\nZulu/SM\nZululand\nZuni/M\nZurich/M\nZwingli/M\nZworykin/M\nZyrtec/M\nZyuganov/M\nZzz\na/S\naah\naardvark/SM\nab/SDY\naback\nabacus/MS\nabaft\nabalone/SM\nabandon/LSDG\nabandonment/M\nabase/LGDS\nabasement/M\nabash/GLDS\nabashed/UY\nabashment/M\nabate/LGDS\nabated/U\nabatement/M\nabattoir/MS\nabbe/SM\nabbess/MS\nabbey/MS\nabbot/MS\nabbr\nabbrev/S\nabbreviate/DSGNX\nabbreviation/M\nabdicate/GNDSX\nabdication/M\nabdomen/SM\nabdominal\nabduct/DSG\nabductee/MS\nabduction/SM\nabductor/MS\nabeam\naberrant\naberration/MS\naberrational\nabet/S\nabetted\nabetting\nabettor/SM\nabeyance/M\nabhor/S\nabhorred\nabhorrence/M\nabhorrent/Y\nabhorring\nabidance/M\nabide/GS\nabiding/Y\nability/IEMS\nabject/YP\nabjection/M\nabjectness/M\nabjuration/SM\nabjuratory\nabjure/ZGDRS\nabjurer/M\nablate/XGNVDS\nablation/M\nablative/MS\nablaze\nable/UT\nabler\nabloom\nablution/SM\nabnegate/GNDS\nabnegation/M\nabnormal/Y\nabnormality/SM\naboard\nabode/MS\nabolish/GDS\nabolition/M\nabolitionism/M\nabolitionist/SM\nabominable\nabominably\nabominate/DSGNX\nabomination/M\naboriginal/MS\naborigine/SM\naborning\nabort/GVDS\nabortion/MS\nabortionist/MS\nabortive/Y\nabound/DSG\nabout\nabove/M\naboveboard\nabracadabra/M\nabrade/GDS\nabrasion/MS\nabrasive/MYPS\nabrasiveness/M\nabreast\nabridge/DSG\nabridgment/MS\nabroad\nabrogate/XGNDS\nabrogation/M\nabrogator/MS\nabrupt/TPRY\nabruptness/M\nabs/M\nabscess/MDSG\nabscissa/SM\nabscission/M\nabscond/ZGSDR\nabsconder/M\nabseil/MDSG\nabsence/SM\nabsent/DYSG\nabsentee/MS\nabsenteeism/M\nabsentminded/YP\nabsentmindedness/M\nabsinthe/M\nabsolute/PMYTNS\nabsoluteness/M\nabsolution/M\nabsolutism/M\nabsolutist/MS\nabsolve/DSG\nabsorb/AGDS\nabsorbance\nabsorbency/M\nabsorbent/SM\nabsorbing/Y\nabsorption/M\nabsorptive\nabstain/DRZGS\nabstainer/M\nabstemious/PY\nabstemiousness/M\nabstention/MS\nabstinence/M\nabstinent\nabstract/GSPMDY\nabstracted/YP\nabstractedness/M\nabstraction/SM\nabstractness/MS\nabstruse/YP\nabstruseness/M\nabsurd/TPRY\nabsurdist/MS\nabsurdity/SM\nabsurdness/M\nabundance/SM\nabundant/Y\nabuse's\nabuse/EGVDS\nabuser/MS\nabusive/YP\nabusiveness/M\nabut/SL\nabutment/MS\nabutted\nabutting\nabuzz\nabysmal/Y\nabyss/MS\nabyssal\nac\nacacia/MS\nacademe/M\nacademia/M\nacademic/SM\nacademical/Y\nacademician/MS\nacademy/SM\nacanthus/MS\naccede/GDS\naccelerate/GNXDS\nacceleration/M\naccelerator/SM\naccent/MDSG\naccented/U\naccentual\naccentuate/GNDS\naccentuation/M\naccept/DSBG\nacceptability/M\nacceptableness/M\nacceptably/U\nacceptance/SM\nacceptation/MS\naccepted/U\naccess/MDSG\naccessibility/IM\naccessible/I\naccessibly/I\naccession/MDGS\naccessorize/DSG\naccessory/SM\naccident/MS\naccidental/SMY\nacclaim/MDGS\nacclamation/M\nacclimate/DSGN\nacclimation/M\nacclimatization/M\nacclimatize/DSG\nacclivity/SM\naccolade/SM\naccommodate/XGNDS\naccommodating/Y\naccommodation/M\naccompanied/U\naccompaniment/MS\naccompanist/SM\naccompany/DSG\naccomplice/SM\naccomplish/DSLG\naccomplished/U\naccomplishment/MS\naccord/GMDS\naccordance/M\naccordant\naccording/Y\naccordion/MS\naccordionist/MS\naccost/GMDS\naccount/MDSBG\naccountability/M\naccountable/U\naccountancy/M\naccountant/MS\naccounted/U\naccounting/M\naccouter/SGD\naccouterments/M\naccredit/SGD\naccreditation/M\naccredited/U\naccretion/MS\naccrual/MS\naccrue/GDS\nacct\nacculturate/DSGN\nacculturation/M\naccumulate/XGNVDS\naccumulation/M\naccumulator/MS\naccuracy/IM\naccurate/IY\naccurateness/M\naccursed/P\naccursedness/M\naccusation/MS\naccusative/MS\naccusatory\naccuse/ZGDRS\naccuser/M\naccusing/Y\naccustom/DSG\naccustomed/U\nace/DSMG\nacerbate/DSG\nacerbic\nacerbically\nacerbity/M\nacetaminophen/M\nacetate/MS\nacetic\nacetone/M\nacetonic\nacetyl\nacetylene/M\nache/DSMG\nachene/MS\nachieve/BLZGDRS\nachievement/SM\nachiever/M\naching/Y\nachoo/M\nachromatic\nachy/TR\nacid/SMY\nacidic\nacidify/GDS\nacidity/M\nacidosis/M\nacidulous\nacknowledge/DSG\nacknowledged/U\nacknowledgment/SM\nacme/SM\nacne/M\nacolyte/MS\naconite/MS\nacorn/MS\nacoustic/S\nacoustical/Y\nacoustics/M\nacquaint/AGSD\nacquaintance/SM\nacquaintanceship/M\nacquainted/U\nacquiesce/DSG\nacquiescence/M\nacquiescent/Y\nacquire/ZGBDRSL\nacquirement/M\nacquisition/MS\nacquisitive/YP\nacquisitiveness/M\nacquit/S\nacquittal/MS\nacquitted\nacquitting\nacre/SM\nacreage/MS\nacrid/PTRY\nacridity/M\nacridness/M\nacrimonious/YP\nacrimoniousness/M\nacrimony/M\nacrobat/MS\nacrobatic/S\nacrobatically\nacrobatics/M\nacronym/MS\nacrophobia/M\nacropolis/MS\nacross\nacrostic/SM\nacrylamide\nacrylic/MS\nact's\nact/ASDGV\nacting/M\nactinium/M\naction/ASM\nactionable\nactivate/ICANGSD\nactivation/ICAM\nactivator/MS\nactive's\nactive/IKY\nactiveness/M\nactives\nactivism/M\nactivist/MS\nactivities\nactivity/IM\nactor/AMS\nactress/MS\nactual/Y\nactuality/SM\nactualization/M\nactualize/GDS\nactuarial\nactuary/SM\nactuate/GNDS\nactuation/M\nactuator/SM\nacuity/M\nacumen/M\nacupressure/M\nacupuncture/M\nacupuncturist/SM\nacute/PMYTRS\nacuteness/M\nacyclovir/M\nacyl\nad/SM\nadage/MS\nadagio/MS\nadamant/MY\nadapt/BZGVDRS\nadaptability/M\nadaptation/MS\nadapter/M\nadaption/S\nadd/SDRBZG\naddend/MS\naddenda\naddendum/M\nadder/M\naddict/GVMDS\naddiction/SM\naddition/SM\nadditional/Y\nadditive/SM\naddle/GDS\naddress's\naddress/AGDS\naddressable\naddressed/U\naddressee/SM\nadduce/GDS\nadenine/M\nadenoid/SM\nadenoidal\nadept/MYPS\nadeptness/M\nadequacy/IM\nadequate/IY\nadequateness/M\nadhere/GDS\nadherence/M\nadherent/SM\nadhesion/M\nadhesive/PSM\nadhesiveness/M\nadiabatic\nadieu/MS\nadios\nadipose\nadj\nadjacency/M\nadjacent/Y\nadjectival/Y\nadjective/MS\nadjoin/GDS\nadjourn/DGLS\nadjournment/SM\nadjudge/GDS\nadjudicate/GNVXDS\nadjudication/M\nadjudicator/SM\nadjudicatory\nadjunct/MS\nadjuration/MS\nadjure/GDS\nadjust/AGDSL\nadjustable\nadjuster/SM\nadjustment/AMS\nadjutant/SM\nadman/M\nadmen\nadmin/S\nadminister/DGS\nadministrate/XDSGNV\nadministration/M\nadministrative/Y\nadministrator/MS\nadmirably\nadmiral/MS\nadmiralty/M\nadmiration/M\nadmire/BZGDRS\nadmirer/M\nadmiring/Y\nadmissibility/IM\nadmissible/I\nadmissibly\nadmission/AM\nadmissions\nadmit/AS\nadmittance/M\nadmitted/Y\nadmitting/A\nadmix/GDS\nadmixture/SM\nadmonish/LDSG\nadmonishment/MS\nadmonition/MS\nadmonitory\nado/M\nadobe/MS\nadolescence/SM\nadolescent/SM\nadopt/AGVDS\nadoptable\nadopter/MS\nadoption/SM\nadorableness/M\nadorably\nadoration/M\nadore/BZGDRS\nadorer/M\nadoring/Y\nadorn/LGDS\nadorned/U\nadornment/MS\nadrenal/MS\nadrenalin's\nadrenaline/M\nadrenergic\nadrift\nadroit/PY\nadroitness/M\nadsorb/SDG\nadsorbent/MS\nadsorption/SM\nadulate/DSGN\nadulation/M\nadulator/MS\nadulatory\nadult/MS\nadulterant/MS\nadulterate/GNDS\nadulterated/U\nadulteration/M\nadulterer/SM\nadulteress/MS\nadulterous\nadultery/SM\nadulthood/M\nadumbrate/GNDS\nadumbration/M\nadv\nadvance/LDSMG\nadvancement/SM\nadvantage/EDSMG\nadvantageous/EY\nadvent/SM\nadventitious/Y\nadventure/DRSMZG\nadventurer/M\nadventuresome\nadventuress/MS\nadventurism\nadventurist/S\nadventurous/YP\nadventurousness/M\nadverb/SM\nadverbial/SMY\nadversarial\nadversary/SM\nadverse/PRYT\nadverseness/M\nadversity/SM\nadvert/SMDG\nadvertise/LZGDRS\nadvertised/U\nadvertisement/MS\nadvertiser/M\nadvertising/M\nadvertorial/SM\nadvice/M\nadvisability/IM\nadvisable/I\nadvisably\nadvise/LDRSZGB\nadvised/UY\nadvisement/M\nadviser/M\nadvisory/SM\nadvocacy/M\nadvocate/MGDS\nadvt\nadware\nadze/SM\naegis/M\naerate/DSGN\naeration/M\naerator/SM\naerial/SMY\naerialist/MS\naerie/MS\naerobatic/S\naerobatics/M\naerobic/S\naerobically\naerobics/M\naerodrome/MS\naerodynamic/S\naerodynamically\naerodynamics/M\naerogram/S\naeronautic/S\naeronautical\naeronautics/M\naerosol/MS\naerospace/M\naesthete/MS\naesthetic/S\naesthetically\naestheticism/M\naesthetics/M\nafar\naffability/M\naffable\naffably\naffair/MS\naffect's\naffect/EGDS\naffectation/SM\naffected/UY\naffecting/Y\naffection/EM\naffectionate/Y\naffections\nafferent\naffiance/GDS\naffidavit/SM\naffiliate's\naffiliate/EGNDS\naffiliated/U\naffiliation/EM\naffiliations\naffinity/SM\naffirm/AGDS\naffirmation/AMS\naffirmative/MYS\naffix/GMDS\nafflatus/M\nafflict/GDS\naffliction/SM\naffluence/M\naffluent/Y\nafford/GDSB\naffordability\naffordably\nafforest/EGSD\nafforestation/M\naffray/MS\naffront/GMDS\nafghan/MS\naficionado/MS\nafield\nafire\naflame\nafloat\naflutter\nafoot\naforementioned\naforesaid\naforethought\nafoul\nafraid/U\nafresh\naft/RZ\nafterbirth/M\nafterbirths\nafterburner/MS\naftercare/M\naftereffect/MS\nafterglow/SM\nafterimage/MS\nafterlife/M\nafterlives\naftermarket/MS\naftermath/M\naftermaths\nafternoon/MS\naftershave/SM\naftershock/SM\naftertaste/SM\nafterthought/SM\nafterward/S\nafterword/MS\nagain\nagainst\nagape/M\nagar/M\nagate/MS\nagave/M\nage/DSMGJ\nageism/M\nageist/SM\nageless/YP\nagelessness/M\nagency/SM\nagenda/SM\nagent/AMS\nageratum/M\nagglomerate/DSMGNX\nagglomeration/M\nagglutinate/DSXGN\nagglutination/M\naggrandize/GLDS\naggrandizement/M\naggravate/GNXDS\naggravating/Y\naggravation/M\naggregate/MGNDSX\naggregation/M\naggression/M\naggressive/PY\naggressiveness/M\naggressor/SM\naggrieve/DSG\naggro\naghast\nagile/Y\nagility/M\naging/M\nagitate/XGNDS\nagitation/M\nagitator/MS\nagitprop/M\nagleam\naglitter\naglow\nagnostic/MS\nagnosticism/M\nago\nagog\nagonist/S\nagonize/GDS\nagonizing/Y\nagony/SM\nagoraphobia/M\nagoraphobic/MS\nagrarian/MS\nagrarianism/M\nagree/EBLDS\nagreeableness/EM\nagreeably/E\nagreeing/E\nagreement/ESM\nagribusiness/MS\nagricultural/Y\nagriculturalist/MS\nagriculture/M\nagriculturist/MS\nagronomic\nagronomist/MS\nagronomy/M\naground\nague/M\nah\naha\nahchoo\nahead\nahem\nahoy\naid/SMDG\naide/SM\naided/U\naigrette/MS\nail/SDLG\naileron/SM\nailment/SM\naim/SMDG\naimless/YP\naimlessness/M\nain't\nair/SMDJG\nairbag/MS\nairbase/SM\nairbed/S\nairborne\nairbrush/MDSG\nairbus/MS\naircraft/M\naircraftman\naircraftmen\naircrew/S\nairdrome/S\nairdrop/SM\nairdropped\nairdropping\nairfare/SM\nairfield/SM\nairflow/M\nairfoil/SM\nairfreight/M\nairguns\nairhead/SM\nairily\nairiness/M\nairing/M\nairless/P\nairlessness/M\nairletters\nairlift/SGMD\nairline/RSMZ\nairliner/M\nairlock/SM\nairmail/GSMD\nairman/M\nairmen\nairplane/MS\nairplay/M\nairport/SM\nairship/SM\nairshow/S\nairsick/P\nairsickness/M\nairspace/M\nairspeed\nairstrike/MS\nairstrip/SM\nairtight\nairtime/M\nairwaves/M\nairway/MS\nairwoman\nairwomen\nairworthiness/M\nairworthy/P\nairy/PTR\naisle/MS\naitch/MS\najar\naka\nakimbo\nakin\nalabaster/M\nalack\nalacrity/M\nalarm/GMDS\nalarming/Y\nalarmist/SM\nalas\nalb/SM\nalbacore/SM\nalbatross/MS\nalbeit\nalbinism/M\nalbino/MS\nalbum/MNS\nalbumen/M\nalbumin/M\nalbuminous\nalchemist/SM\nalchemy/M\nalcohol/SM\nalcoholic/MS\nalcoholically\nalcoholism/M\nalcove/MS\nalder/MS\nalderman/M\naldermen\nalderwoman/M\nalderwomen\nale/SMV\naleatory\nalehouse/SM\nalembic/SM\nalert/GMDYPS\nalertness/M\nalewife/M\nalewives\nalfalfa/M\nalfresco\nalga/M\nalgae\nalgal\nalgebra/SM\nalgebraic\nalgebraically\nalgorithm/SM\nalgorithmic\nalias/GMDS\nalibi/GMDS\nalien/BGMDS\nalienable/IU\nalienate/DSGN\nalienation/M\nalienist/SM\nalight/GDS\nalign/ALGDS\naligned/U\naligner/MS\nalignment/AMS\nalike/U\naliment/MDSG\nalimentary\nalimony/M\naliveness/M\naliyah/M\naliyahs\nalkali/M\nalkalies\nalkaline\nalkalinity/M\nalkalize/DSG\nalkaloid/SM\nalkyd/MS\nall/M\nallay/GDS\nallegation/MS\nallege/GDS\nalleged/Y\nallegiance/MS\nallegoric\nallegorical/Y\nallegorist/MS\nallegory/SM\nallegretto/MS\nallegro/MS\nallele/MS\nalleluia/SM\nallergen/SM\nallergenic\nallergic\nallergically\nallergist/SM\nallergy/SM\nalleviate/DSGN\nalleviation/M\nalley/MS\nalleyway/SM\nalliance/SM\nalligator/MS\nalliterate/DSXGNV\nalliteration/M\nalliterative/Y\nallocate/ADSGN\nallocation/AM\nallocations\nallot/LS\nallotment/SM\nallotted\nallotting\nallover\nallow/EGDS\nallowable/U\nallowably\nallowance/SM\nalloy/GMDS\nalloyed/U\nallspice/M\nallude/GDS\nallure/MGLDS\nallurement/MS\nalluring/Y\nallusion/SM\nallusive/PY\nallusiveness/M\nalluvial/M\nalluvium/SM\nally/GDSM\nalmanac/SM\nalmighty\nalmond/MS\nalmoner/SM\nalmost\nalms/M\nalmshouse/MS\naloe/SM\naloft\naloha/MS\nalone\nalong\nalongshore\nalongside\naloof/PY\naloofness/M\naloud\nalp/SM\nalpaca/MS\nalpha/MS\nalphabet/SM\nalphabetic\nalphabetical/Y\nalphabetization/SM\nalphabetize/ZGDRS\nalphabetizer/M\nalphanumeric\nalphanumerical/Y\nalpine/S\nalready\nalright\nalso\nalt/S\naltar/MS\naltarpiece/SM\nalter/GDBS\nalterable/U\nalteration/MS\naltercation/SM\naltered/U\nalternate/DSMYGNVX\nalternation/M\nalternative/MYS\nalternator/SM\nalthough\naltimeter/MS\naltitude/MS\nalto/SM\naltogether\naltruism/M\naltruist/SM\naltruistic\naltruistically\nalum/SM\nalumina/M\naluminum/M\nalumna/M\nalumnae\nalumni\nalumnus/M\nalveolar/S\nalways\nam/N\namalgam/SM\namalgamate/XGNDS\namalgamation/M\namanuenses\namanuensis/M\namaranth/M\namaranths\namaretto/M\namaryllis/MS\namass/GDS\namateur/SM\namateurish/YP\namateurishness/M\namateurism/M\namatory\namaze/LMGDS\namazement/M\namazing/Y\namazon/MS\namazonian\nambassador/SM\nambassadorial\nambassadorship/MS\nambassadress/MS\namber/M\nambergris/M\nambiance/MS\nambidexterity/M\nambidextrous/Y\nambient\nambiguity/SM\nambiguous/UY\nambit\nambition/MS\nambitious/YP\nambitiousness/M\nambivalence/M\nambivalent/Y\namble/MZGDRS\nambler/M\nambrosia/M\nambrosial\nambulance/MS\nambulanceman\nambulancemen\nambulancewoman\nambulancewomen\nambulant\nambulate/DSXGN\nambulation/M\nambulatory/SM\nambuscade/MGDS\nambush/GMDS\nameliorate/GNVDS\namelioration/M\namen/B\namenability/M\namenably\namend/BLGDS\namendment/SM\namenity/SM\namerce/GLDS\namercement/SM\namericium/M\namethyst/SM\namiability/M\namiable\namiably\namicability/M\namicable\namicably\namid\namide/MS\namidships\namigo/MS\namino\namiss\namity/M\nammeter/SM\nammo/M\nammonia/M\nammonium\nammunition/M\namnesia/M\namnesiac/MS\namnesic/SM\namnesty/GDSM\namniocenteses\namniocentesis/M\namnion/MS\namniotic\namoeba/MS\namoebae\namoebic\namok\namong\namontillado/SM\namoral/Y\namorality/M\namorous/YP\namorousness/M\namorphous/PY\namorphousness/M\namortization/SM\namortize/DSGB\namount/GMDS\namour/MS\namoxicillin\namp/SMY\namperage/M\nampere/MS\nampersand/MS\namphetamine/SM\namphibian/MS\namphibious/Y\namphitheater/SM\namphora/M\namphorae\nampicillin\nample/TR\namplification/M\namplifier/M\namplify/NDRSXZG\namplitude/SM\nampule/MS\namputate/GNDSX\namputation/M\namputee/MS\namt\namulet/MS\namuse/LGDS\namusement/MS\namusing/Y\namylase/M\nan/CS\nanabolism/M\nanachronism/SM\nanachronistic\nanachronistically\nanaconda/SM\nanaerobe/SM\nanaerobic\nanaerobically\nanagram/MS\nanal/Y\nanalgesia/M\nanalgesic/SM\nanalog/MS\nanalogical/Y\nanalogize/GDS\nanalogous/YP\nanalogousness/M\nanalogue/SM\nanalogy/SM\nanalysand/MS\nanalyses/A\nanalysis/AM\nanalyst/SM\nanalytic\nanalytical/Y\nanalyzable\nanalyze/ADSG\nanalyzer/SM\nanapest/SM\nanapestic/MS\nanarchic\nanarchically\nanarchism/M\nanarchist/MS\nanarchistic\nanarchy/M\nanathema/SM\nanathematize/DSG\nanatomic\nanatomical/Y\nanatomist/SM\nanatomize/DSG\nanatomy/SM\nancestor/SM\nancestral/Y\nancestress/MS\nancestry/SM\nanchor/MDGS\nanchorage/MS\nanchorite/MS\nanchorman/M\nanchormen\nanchorpeople\nanchorperson/SM\nanchorwoman/M\nanchorwomen\nanchovy/SM\nancient/SPMRYT\nancientness/M\nancillary/SM\nand\nandante/SM\nandiron/SM\nandrogen/M\nandrogenic\nandrogynous\nandrogyny/M\nandroid/SM\nanecdotal/Y\nanecdote/MS\nanemia/M\nanemic\nanemically\nanemometer/SM\nanemone/SM\nanent\nanesthesia/M\nanesthesiologist/SM\nanesthesiology/M\nanesthetic/SM\nanesthetist/MS\nanesthetization/M\nanesthetize/GDS\naneurysm/SM\nanew\nangel/MS\nangelfish/MS\nangelic\nangelica/M\nangelical/Y\nanger/GMDS\nangina/M\nangioplasty/SM\nangiosperm/SM\nangle/MZGDRS\nangler/M\nangleworm/MS\nanglicism/S\nanglicize/GDS\nangling/M\nanglophile/S\nanglophone/S\nangora/MS\nangostura\nangrily\nangry/TR\nangst/M\nangstrom/MS\nanguish/GMDS\nangular\nangularity/SM\nangulation\nanhydrous\naniline/M\nanimadversion/MS\nanimadvert/GSD\nanimal/MS\nanimalcule/SM\nanimate/ADSGN\nanimated/Y\nanimation/AM\nanimations\nanimator/MS\nanime/M\nanimism/M\nanimist/SM\nanimistic\nanimosity/SM\nanimus/M\nanion/MS\nanionic\nanise/M\naniseed/M\nanisette/M\nankh/M\nankhs\nankle/MS\nanklebone/MS\nanklet/MS\nannalist/SM\nannals/M\nanneal/GDS\nannelid/MS\nannex/GMDS\nannexation/MS\nannihilate/DSGN\nannihilation/M\nannihilator/SM\nanniversary/SM\nannotate/DSXGNV\nannotation/M\nannotator/MS\nannounce/DRSLZG\nannounced/U\nannouncement/MS\nannouncer/M\nannoy/GDS\nannoyance/MS\nannoying/Y\nannual/MYS\nannualized\nannuitant/SM\nannuity/SM\nannul/LS\nannular\nannulled\nannulling\nannulment/SM\nannunciation/SM\nanode/MS\nanodize/GDS\nanodyne/MS\nanoint/GDLS\nanointment/M\nanomalous/Y\nanomaly/SM\nanon/S\nanonymity/M\nanonymous/Y\nanopheles/M\nanorak/MS\nanorectic/SM\nanorexia/M\nanorexic/MS\nanother\nanswer/BMDGS\nanswerable/U\nanswered/U\nanswerphone/S\nant/SMD\nantacid/SM\nantagonism/SM\nantagonist/SM\nantagonistic\nantagonistically\nantagonize/DSG\nantarctic\nante/SM\nanteater/MS\nantebellum\nantecedence/M\nantecedent/SM\nantechamber/SM\nantedate/GDS\nantediluvian\nanteing\nantelope/MS\nantenatal\nantenna/SM\nantennae\nanterior\nanteroom/MS\nanthem/MS\nanther/MS\nanthill/SM\nanthologist/SM\nanthologize/DSG\nanthology/SM\nanthracite/M\nanthrax/M\nanthropocentric\nanthropoid/MS\nanthropological/Y\nanthropologist/SM\nanthropology/M\nanthropomorphic\nanthropomorphically\nanthropomorphism/M\nanthropomorphize\nanthropomorphous\nanti/SM\nantiabortion\nantiabortionist/MS\nantiaircraft\nantibacterial/MS\nantibiotic/MS\nantibody/SM\nantic/MS\nanticancer\nanticipate/GNXDS\nanticipated/U\nanticipation/M\nanticipatory\nanticked\nanticking\nanticlerical\nanticlimactic\nanticlimactically\nanticlimax/MS\nanticline/SM\nanticlockwise\nanticoagulant/MS\nanticommunism/M\nanticommunist/SM\nanticyclone/SM\nanticyclonic\nantidemocratic\nantidepressant/MS\nantidote/MS\nantifascist/MS\nantifreeze/M\nantigen/SM\nantigenic\nantigenicity/M\nantihero/M\nantiheroes\nantihistamine/SM\nantiknock/M\nantilabor\nantilogarithm/SM\nantimacassar/MS\nantimalarial\nantimatter/M\nantimicrobial\nantimissile\nantimony/M\nantinuclear\nantioxidant/MS\nantiparticle/SM\nantipasti\nantipasto/MS\nantipathetic\nantipathy/SM\nantipersonnel\nantiperspirant/SM\nantiphon/SM\nantiphonal/MYS\nantipodal/S\nantipodean/MS\nantipodes/M\nantipollution\nantipoverty\nantiquarian/SM\nantiquarianism/M\nantiquary/SM\nantiquate/GDS\nantique/DSMG\nantiquity/SM\nantirrhinum/S\nantiscience\nantisemitic\nantisemitism/M\nantisepsis/M\nantiseptic/SM\nantiseptically\nantiserum/MS\nantislavery\nantisocial/Y\nantispasmodic/MS\nantisubmarine\nantitank\nantitheses\nantithesis/M\nantithetic\nantithetical/Y\nantitoxin/MS\nantitrust\nantivenin/MS\nantivenom\nantiviral/MS\nantivirus\nantivivisectionist/MS\nantiwar\nantler/MDS\nantonym/SM\nantonymous\nantrum\nantsy/TR\nanus/MS\nanvil/MS\nanxiety/SM\nanxious/YP\nanxiousness/M\nany\nanybody/SM\nanyhow\nanymore\nanyone/M\nanyplace\nanything/SM\nanytime\nanyway/S\nanywhere\nanywise\naorta/MS\naortic\napace\napart\napartheid/M\napartment/MS\napathetic\napathetically\napathy/M\napatite/M\nape/DSMG\napelike\naperitif/MS\naperture/SM\napex/MS\naphasia/M\naphasic/MS\naphelia\naphelion/SM\naphid/MS\naphorism/MS\naphoristic\naphoristically\naphrodisiac/SM\napiarist/SM\napiary/SM\napical/Y\napiece\napish/Y\naplenty\naplomb/M\napocalypse/SM\napocalyptic\napocrypha/M\napocryphal/Y\napogee/MS\napolitical/Y\napologetic/U\napologetically\napologia/SM\napologist/MS\napologize/GDS\napology/SM\napoplectic\napoplexy/SM\napoptosis\napoptotic\napostasy/SM\napostate/SM\napostatize/GDS\napostle/MS\napostleship/M\napostolic\napostrophe/MS\napothecary/SM\napothegm/SM\napotheoses\napotheosis/M\napp/SM\nappall/GDS\nappalling/Y\nappaloosa/MS\napparatchik/S\napparatus/MS\napparel/MDGS\napparent/Y\napparition/SM\nappeal/GMDS\nappealing/UY\nappear/AESDG\nappearance/EAMS\nappease/LZGDRS\nappeasement/SM\nappeaser/M\nappellant/SM\nappellate/XN\nappellation/M\nappend/GDS\nappendage/SM\nappendectomy/SM\nappendices\nappendicitis/M\nappendix/MS\nappertain/GDS\nappetite/SM\nappetizer/MS\nappetizing/Y\napplaud/ZGDRS\napplauder/M\napplause/M\napple/MS\napplejack/M\napplesauce/M\napplet/MS\nappliance/SM\napplicability/M\napplicable/I\napplicably\napplicant/SM\napplication/AM\napplicator/SM\napplier/MS\napplique/DSM\nappliqueing\napply/ANXGDS\nappoint/AELSVGD\nappointee/SM\nappointment's/A\nappointment/ESM\napportion/AGDLS\napportionment/AM\nappose/GDS\napposite/YNVP\nappositeness/M\napposition/M\nappositive/SM\nappraisal/AMS\nappraise/ADSG\nappraiser/MS\nappreciable/I\nappreciably/I\nappreciate/DSXGNV\nappreciated/U\nappreciation/M\nappreciative/Y\nappreciator/MS\nappreciatory\napprehend/GDS\napprehension/MS\napprehensive/YP\napprehensiveness/M\napprentice/DSMG\napprenticeship/MS\napprise/GDS\napproach/GBMDS\napproachable/UI\napprobation/EM\napprobations\nappropriate/PYGNXDS\nappropriated/U\nappropriateness/IM\nappropriation/M\nappropriator/SM\napproval/EM\napprovals\napprove/EGDS\napproved/U\napproving/EY\napprox\napproximate/DSXYGN\napproximation/M\nappurtenance/SM\nappurtenant\napricot/MS\napron/MS\napropos\napse/SM\napt/IYPT\napter\naptitude/SM\naptness/IM\naqua/SM\naquaculture/M\naqualung/MS\naquamarine/SM\naquanaut/MS\naquaplane/MGDS\naquarium/MS\naquatic/SM\naquatically\naquatics/M\naquatint/S\naquavit/M\naqueduct/MS\naqueous\naquifer/SM\naquiline\narabesque/MS\narability/M\narachnid/MS\narachnophobia\narbiter/SM\narbitrage/MZGDRS\narbitrager/M\narbitrageur/SM\narbitrament/SM\narbitrarily\narbitrariness/M\narbitrary/P\narbitrate/GNDS\narbitration/M\narbitrator/MS\narbor/MS\narboreal\narboretum/SM\narborvitae/SM\narbutus/MS\narc/SMDG\narcade/MS\narcane\narch/PZTGVMDRSY\narchaeological/Y\narchaeologist/SM\narchaeology/M\narchaic\narchaically\narchaism/MS\narchaist/MS\narchangel/MS\narchbishop/SM\narchbishopric/SM\narchdeacon/SM\narchdiocesan\narchdiocese/MS\narchduchess/MS\narchduke/MS\narchenemy/SM\narcher/M\narchery/M\narchetypal\narchetype/MS\narchfiend/MS\narchiepiscopal\narchipelago/MS\narchitect/SM\narchitectonic/S\narchitectonics/M\narchitectural/Y\narchitecture/MS\narchitrave/SM\narchival\narchive/DSMG\narchivist/MS\narchness/M\narchway/SM\narctic/MS\nardent/Y\nardor/MS\narduous/YP\narduousness/M\nare/SMB\narea/SM\nareal\naren't\narena/MS\nargent/M\nargon/M\nargosy/SM\nargot/MS\narguable/IU\narguably/U\nargue/ZGDRS\narguer/M\nargument/MS\nargumentation/M\nargumentative/PY\nargumentativeness/M\nargyle/MS\naria/SM\narid/Y\naridity/M\naright\narise/GS\narisen\naristocracy/SM\naristocrat/SM\naristocratic\naristocratically\narithmetic/M\narithmetical/Y\narithmetician/MS\nark/SM\narm's\narm/EAGDS\narmada/MS\narmadillo/SM\narmament/AEM\narmaments\narmature/MS\narmband/MS\narmchair/MS\narmed/U\narmful/MS\narmhole/SM\narmistice/SM\narmlet/MS\narmload/S\narmor/ZGMDRS\narmored/U\narmorer/M\narmorial\narmory/SM\narmpit/MS\narmrest/SM\narmy/SM\naroma/MS\naromatherapist/MS\naromatherapy/M\naromatic/MS\naromatically\narose\naround\narousal/M\narouse/GDS\narpeggio/MS\narr\narraign/DGSL\narraignment/SM\narrange/AESDLG\narrangement's/E\narrangement/ASM\narranger/SM\narrant\narras/MS\narray/EGMDS\narrears/M\narrest/AGMDS\narrhythmia/M\narrhythmic\narrhythmical\narrival/MS\narrive/GDS\narrogance/M\narrogant/Y\narrogate/GNDS\narrogation/M\narrow/MS\narrowhead/MS\narrowroot/M\narroyo/MS\narsed\narsenal/MS\narsenic/M\narsing\narson/M\narsonist/SM\nart/SM\narterial\narteriole/MS\narteriosclerosis/M\nartery/SM\nartful/PY\nartfulness/M\narthritic/MS\narthritis/M\narthropod/MS\narthroscope/SM\narthroscopic\narthroscopy\nartichoke/SM\narticle/MDS\narticulacy/I\narticular\narticulate/YGNPDSX\narticulateness/IM\narticulation/M\nartifact/SM\nartifice/RSMZ\nartificer/M\nartificial/Y\nartificiality/M\nartillery/M\nartilleryman/M\nartillerymen\nartiness/M\nartisan/MS\nartist/MS\nartiste/MS\nartistic/I\nartistically\nartistry/M\nartless/PY\nartlessness/M\nartsy/TR\nartwork/MS\narty/PTR\narugula\narum/SM\nasap\nasbestos/M\nascend/AGDS\nascendance/M\nascendancy/M\nascendant/SM\nascension/MS\nascent/MS\nascertain/GDSBL\nascertainment/M\nascetic/MS\nascetically\nasceticism/M\nascot/MS\nascribe/GBDS\nascription/M\naseptic\naseptically\nasexual/Y\nasexuality/M\nash/MDNSG\nashamed/UY\nashcan/MS\nashlar/MS\nashore\nashram/MS\nashtray/SM\nashy/TR\naside/MS\nasinine/Y\nasininity/SM\nask/SDG\naskance\nasked/U\naskew\naslant\nasleep\nasocial\nasp/SMNX\nasparagus/M\naspartame/M\naspect/MS\naspen/M\nasperity/SM\naspersion/MS\nasphalt/MDGS\nasphodel/SM\nasphyxia/M\nasphyxiate/DSXGN\nasphyxiation/M\naspic/MS\naspidistra/MS\naspirant/MS\naspirate/MGNDSX\naspiration/M\naspirator/SM\naspire/GDS\naspirin/MS\nass/MS\nassail/GBDS\nassailable/U\nassailant/SM\nassassin/SM\nassassinate/GNXDS\nassassination/M\nassault/MDRGS\nassay/ZGMDRS\nassayer/M\nassemblage/SM\nassemble/AEGSD\nassembler/MS\nassemblies\nassembly/AM\nassemblyman/M\nassemblymen\nassemblywoman/M\nassemblywomen\nassent/GMDS\nassert/AGVDS\nassertion/AM\nassertions\nassertive/YP\nassertiveness/M\nassess/ALGDS\nassessment/ASM\nassessor/MS\nasset/MS\nasseverate/DSGN\nasseveration/M\nasshole/MS!\nassiduity/M\nassiduous/PY\nassiduousness/M\nassign's\nassign/ALGDS\nassignable\nassignation/MS\nassigned/U\nassignee/M\nassigner/MS\nassignment/AMS\nassignor/MS\nassimilate/DSGN\nassimilation/M\nassist/GMDS\nassistance/M\nassistant/SM\nassisted/U\nassize/MS\nassn\nassoc\nassociate's\nassociate/EDSGNV\nassociation/EM\nassociations\nassonance/M\nassonant/MS\nassort/GLDS\nassortment/MS\nasst\nassuage/GDS\nassume/BGDS\nassumption/SM\nassumptive\nassurance/ASM\nassure/AGDS\nassured/MYS\nastatine/M\naster/EMS\nasterisk/GMDS\nastern\nasteroid/MS\nasthma/M\nasthmatic/SM\nasthmatically\nastigmatic\nastigmatism/SM\nastir\nastonish/DSLG\nastonishing/Y\nastonishment/M\nastound/GDS\nastounding/Y\nastraddle\nastrakhan/M\nastral\nastray\nastride\nastringency/M\nastringent/SMY\nastrolabe/SM\nastrologer/SM\nastrological/Y\nastrologist/MS\nastrology/M\nastronaut/MS\nastronautic/S\nastronautical\nastronautics/M\nastronomer/SM\nastronomic\nastronomical/Y\nastronomy/M\nastrophysical\nastrophysicist/MS\nastrophysics/M\nastute/PYTR\nastuteness/M\nasunder\nasylum/SM\nasymmetric\nasymmetrical/Y\nasymmetry/SM\nasymptomatic\nasymptotic\nasymptotically\nasynchronous/Y\nat\natavism/M\natavist/SM\natavistic\nataxia/M\nataxic/MS\nate\natelier/SM\natheism/M\natheist/MS\natheistic\natherosclerosis/M\natherosclerotic\nathirst\nathlete/MS\nathletic/S\nathletically\nathleticism\nathletics/M\nathwart\natilt\natishoo\natlas/MS\natmosphere/MS\natmospheric/S\natmospherically\natmospherics/M\natoll/MS\natom/SM\natomic\natomically\natomize/ZGDRS\natomizer/M\natonal/Y\natonality/M\natone/LGDS\natonement/M\natop\natria\natrial\natrioventricular\natrium/M\natrocious/PY\natrociousness/M\natrocity/SM\natrophy/DSMG\natropine/M\nattach/ALGDS\nattache/BM\nattached/U\nattachment/AM\nattachments\nattack/ZGMDRS\nattacker/M\nattain/AGDS\nattainability/M\nattainable/U\nattainder/M\nattainment/SM\nattar/M\nattempt's\nattempt/ASDG\nattend/SDRZG\nattendance/SM\nattendant/SM\nattended/U\nattendee/SM\nattention/IM\nattentions\nattentive/IPY\nattentiveness/IM\nattenuate/DSGN\nattenuation/M\nattest/SDG\nattestation/SM\nattested/U\nattic/SM\nattire/DSMG\nattitude/SM\nattitudinal\nattitudinize/GDS\nattn\nattorney/MS\nattract/SGVDB\nattractant/MS\nattraction/MS\nattractive/UY\nattractiveness/M\nattribute/DSMGNVBX\nattributed/U\nattribution/M\nattributive/MYS\nattrition/M\nattune/DSG\natty\natwitter\natypical/Y\naubergine/S\nauburn/M\nauction/MDGS\nauctioneer/SM\naudacious/YP\naudaciousness/M\naudacity/M\naudibility/IM\naudible/MS\naudibly/I\naudience/MS\naudio/MS\naudiological\naudiologist/SM\naudiology/M\naudiometer/SM\naudiophile/SM\naudiotape/SM\naudiovisual/S\naudiovisuals/M\naudit/GMDS\naudition/SMDG\nauditor/MS\nauditorium/SM\nauditory\nauger/MS\naught/MS\naugment/DRZGS\naugmentation/MS\naugmentative\naugmenter/M\naugur/GMDS\naugury/SM\naugust/PTRY\naugustness/M\nauk/SM\naunt/SM\nauntie/SM\naura/MS\naural/Y\naureole/SM\naureus\nauricle/SM\nauricular\naurora/SM\nauscultate/GNDSX\nauscultation/M\nauspice/SM\nauspicious/IY\nauspiciousness/M\naustere/RYT\nausterity/SM\naustral\nauthentic/IU\nauthentically\nauthenticate/XGNDS\nauthenticated/U\nauthentication/M\nauthenticity/M\nauthor/SMDG\nauthoress/MS\nauthorial\nauthoritarian/MS\nauthoritarianism/M\nauthoritative/YP\nauthoritativeness/M\nauthority/SM\nauthorization/MS\nauthorize/AGDS\nauthorized/U\nauthorship/M\nautism/M\nautistic\nauto/MS\nautobahn/SM\nautobiographer/SM\nautobiographic\nautobiographical/Y\nautobiography/SM\nautoclave/MS\nautocracy/SM\nautocrat/SM\nautocratic\nautocratically\nautocross\nautodidact/SM\nautograph/MDG\nautographs\nautoimmune\nautoimmunity/M\nautomaker/SM\nautomate/GNDS\nautomatic/SM\nautomatically\nautomation/M\nautomatism/M\nautomatize/GDS\nautomaton/SM\nautomobile/DSMG\nautomotive\nautonomic\nautonomous/Y\nautonomy/M\nautopilot/SM\nautopsy/GDSM\nautosuggestion\nautoworker/MS\nautumn/SM\nautumnal\naux\nauxiliary/SM\nauxin/M\nav/RZ\navail/BGMDS\navailability/UM\navailable/U\navalanche/SM\navarice/M\navaricious/Y\navast\navatar/MS\navaunt\navdp\nave\navenge/ZGDRS\navenger/M\navenue/MS\naverage/MYGDS\naverred\naverring\naverse/XN\naversion/M\navert/GDS\navg\navian\naviary/SM\naviation/M\naviator/MS\naviatrices\naviatrix/MS\navid/Y\navidity/M\navionic/S\navionics/M\navitaminosis/M\navocado/SM\navocation/MS\navocational\navoid/SDGB\navoidable/U\navoidably/U\navoidance/M\navoirdupois/M\navouch/DSG\navow/EDGS\navowal/ESM\navowed/Y\navuncular/Y\naw\nawait/GDS\nawake/GS\nawaken/AGDS\nawakening/SM\naward/GMDS\nawardee/S\naware/UP\nawareness/UM\nawash\naway\nawe/DSMG\naweigh\nawesome/YP\nawesomeness/M\nawestruck\nawful/YP\nawfuller\nawfullest\nawfulness/M\nawhile\nawkward/RYPT\nawkwardness/M\nawl/SM\nawn/GJSM\nawning/M\nawoke\nawoken\nawry\nax/MDSG\naxial/Y\naxiom/SM\naxiomatic\naxiomatically\naxis/M\naxle/MS\naxletree/SM\naxolotl/SM\naxon/MS\nayah/M\nayahs\nayatollah/M\nayatollahs\naye/SM\nazalea/SM\nazimuth/M\nazimuths\nazure/SM\nb/KDT\nbaa/SMDG\nbabble/MZGDRS\nbabbler/M\nbabe/SM\nbabel/MS\nbaboon/MS\nbabushka/SM\nbaby/TGDRSM\nbabyhood/M\nbabyish\nbabysat\nbabysit/S\nbabysitter/MS\nbabysitting/M\nbaccalaureate/SM\nbaccarat/M\nbacchanal/MS\nbacchanalia/M\nbacchanalian/MS\nbaccy\nbachelor/SM\nbachelorhood/M\nbacillary\nbacilli\nbacillus/M\nback/SJZGMDR\nbackache/MS\nbackbench/S\nbackbit\nbackbite/ZGRS\nbackbiter/M\nbackbitten\nbackboard/SM\nbackbone/MS\nbackbreaking\nbackchat\nbackcloth\nbackcloths\nbackcomb/DSG\nbackdate/GDS\nbackdoor\nbackdrop/MS\nbacker/M\nbackfield/SM\nbackfire/MGDS\nbackgammon/M\nbackground/MRZS\nbackgrounder/M\nbackhand/MDRSZG\nbackhanded/Y\nbackhander/M\nbackhoe/MS\nbacking/M\nbacklash/MS\nbackless\nbacklog/MS\nbacklogged\nbacklogging\nbackpack/ZGMDRS\nbackpacker/M\nbackpacking/M\nbackpedal/SDG\nbackrest/SM\nbackroom/S\nbackscratching/M\nbackseat/SM\nbackside/SM\nbackslapper/SM\nbackslapping/M\nbackslash/MS\nbackslid\nbackslide/RSZG\nbackslider/M\nbackspace/DSMG\nbackspin/M\nbackstabber/MS\nbackstabbing\nbackstage/M\nbackstair/S\nbackstop/SM\nbackstopped\nbackstopping\nbackstory/S\nbackstreet/S\nbackstretch/MS\nbackstroke/MGDS\nbacktalk/M\nbacktrack/SDG\nbackup/MS\nbackward/PSY\nbackwardness/M\nbackwash/M\nbackwater/SM\nbackwoods/M\nbackwoodsman/M\nbackwoodsmen\nbackyard/SM\nbacon/M\nbacteria/M\nbacterial\nbactericidal\nbactericide/SM\nbacteriologic\nbacteriological\nbacteriologist/SM\nbacteriology/M\nbacterium/M\nbad/MYP\nbadder\nbaddest\nbaddie/MS\nbade\nbadge/MZRS\nbadger/GMD\nbadinage/M\nbadlands/M\nbadman/M\nbadmen\nbadminton/M\nbadmouth/GD\nbadmouths\nbadness/M\nbaffle/MZGDRSL\nbafflement/M\nbaffler/M\nbag/SM\nbagatelle/SM\nbagel/MS\nbagful/MS\nbaggage/M\nbagged\nbaggie/M\nbaggily\nbagginess/M\nbagging\nbaggy/PTRS\nbagpipe/MZRS\nbagpiper/M\nbaguette/MS\nbah\nbaht/SM\nbail/SBGMD\nbailey/S\nbailiff/S\nbailiwick/MS\nbailout/SM\nbailsman/M\nbailsmen\nbairn/MS\nbait/SGMD\nbaize/M\nbake/DRSMZG\nbaked/U\nbaker/M\nbakery/SM\nbakeshop/MS\nbaklava/M\nbaksheesh/M\nbalaclava/MS\nbalalaika/MS\nbalance's\nbalance/UDSG\nbalboa/SM\nbalcony/SM\nbald/STGPDRY\nbalderdash/M\nbaldfaced\nbaldness/M\nbaldric/SM\nbaldy/S\nbale/DRSMZG\nbaleen/M\nbaleful/PY\nbalefulness/M\nbaler/M\nbalk/SGMD\nbalky/RT\nball/SGMD\nballad/SM\nballadeer/MS\nballadry/M\nballast/GSMD\nballcock/MS\nballerina/SM\nballet/SM\nballetic\nballgame/MS\nballgirl/S\nballgown/S\nballistic/S\nballistics/M\nballoon/SGMD\nballoonist/MS\nballot/SMDG\nballpark/MS\nballplayer/MS\nballpoint/MS\nballroom/MS\nballs/DSG\nballsy/RT\nbally\nballyhoo/SMDG\nbalm/SM\nbalminess/M\nbalmy/RTP\nbaloney/M\nbalsa/MS\nbalsam/SM\nbalsamic\nbaluster/SM\nbalustrade/MS\nbamboo/SM\nbamboozle/DSG\nban/SM\nbanal/Y\nbanality/SM\nbanana/SM\nband's\nband/ESGD\nbandage/DSMG\nbandanna/MS\nbandbox/MS\nbandeau/M\nbandeaux\nbandit/SM\nbanditry/M\nbandleader/S\nbandmaster/SM\nbandoleer/SM\nbandsman/M\nbandsmen\nbandstand/SM\nbandwagon/SM\nbandwidth\nbandwidths\nbandy/DRSTG\nbane/SM\nbaneful\nbang/SGMDR\nbangle/SM\nbani\nbanish/GLDS\nbanishment/M\nbanister/SM\nbanjo/MS\nbanjoist/SM\nbank/SZGBMDR\nbankbook/SM\nbankcard/SM\nbanker/M\nbanking/M\nbanknote/SM\nbankroll/SGMD\nbankrupt/SGMD\nbankruptcy/SM\nbanned\nbanner/SM\nbanning\nbannock/MS\nbanns/M\nbanquet/ZGMDRS\nbanqueter/M\nbanquette/SM\nbanshee/MS\nbantam/SM\nbantamweight/SM\nbanter/GSMD\nbantering/Y\nbanyan/SM\nbanzai/SM\nbaobab/SM\nbap/S\nbaptism/MS\nbaptismal\nbaptist/S\nbaptistery/SM\nbaptize/ZGDRS\nbaptized/U\nbaptizer/M\nbar's\nbar/ECUTS\nbarb/SZGMDR\nbarbarian/SM\nbarbarianism/MS\nbarbaric\nbarbarically\nbarbarism/SM\nbarbarity/SM\nbarbarize/DSG\nbarbarous/Y\nbarbecue/DSMG\nbarbel/SM\nbarbell/MS\nbarber/GMD\nbarberry/SM\nbarbershop/MS\nbarbie/S\nbarbiturate/SM\nbarbwire/M\nbarcarole/SM\nbard/SM\nbardic\nbare/DRSPYG\nbareback/D\nbarefaced/Y\nbarefoot/D\nbarehanded\nbareheaded\nbarelegged\nbareness/M\nbarf/SGMDY\nbarfly/SM\nbargain/MDRZGS\nbargainer/M\nbarge/MGDS\nbargeman/M\nbargemen\nbarhop/S\nbarhopped\nbarhopping\nbarista/MS\nbaritone/MS\nbarium/M\nbark's\nbark/CSGD\nbarkeep/ZMRS\nbarkeeper/M\nbarker/SM\nbarley/M\nbarmaid/MS\nbarman/M\nbarmen\nbarmy/RT\nbarn/SM\nbarnacle/MDS\nbarney/S\nbarnstorm/SDRZG\nbarnstormer/M\nbarnyard/SM\nbarometer/MS\nbarometric\nbarometrically\nbaron/MS\nbaronage/MS\nbaroness/MS\nbaronet/MS\nbaronetcy/SM\nbaronial\nbarony/SM\nbaroque/M\nbarque/SM\nbarrack/MDGS\nbarracuda/SM\nbarrage/MGDS\nbarre/MGJDS\nbarred/UEC\nbarrel/GSMD\nbarren/TPSMR\nbarrenness/M\nbarrette/SM\nbarricade/MGDS\nbarrier/MS\nbarring/ECU\nbarrio/SM\nbarrister/MS\nbarroom/MS\nbarrow/SM\nbartender/SM\nbarter/ZGSMDR\nbarterer/M\nbaryon/SM\nbasal/Y\nbasalt/M\nbasaltic\nbase's\nbase/CDSLTG\nbaseball/SM\nbaseboard/MS\nbaseless\nbaseline/MS\nbasely\nbaseman/M\nbasemen\nbasement/CMS\nbaseness/M\nbaser\nbash/GMDS\nbashful/PY\nbashfulness/M\nbashing/M\nbasic/MS\nbasically\nbasil/M\nbasilica/MS\nbasilisk/MS\nbasin/MS\nbasinful/MS\nbasis/M\nbask/SGD\nbasket/SM\nbasketball/MS\nbasketry/M\nbasketwork/M\nbasque/S\nbass/MS\nbasset/SM\nbassinet/MS\nbassist/MS\nbasso/MS\nbassoon/MS\nbassoonist/SM\nbasswood/MS\nbast/M\nbastard/MS\nbastardization/MS\nbastardize/GDS\nbastardy/M\nbaste/ZGNXDRS\nbaster/M\nbastion/M\nbat/SM\nbatch/MDSG\nbate/KACGSD\nbath/ZGMDRS\nbathe/M\nbather/M\nbathetic\nbathhouse/MS\nbathing/M\nbathmat/MS\nbathos/M\nbathrobe/SM\nbathroom/SM\nbaths\nbathtub/MS\nbathwater\nbathyscaphe/SM\nbathysphere/MS\nbatik/MS\nbatiste/M\nbatman/M\nbatmen\nbaton/MS\nbatsman/M\nbatsmen\nbattalion/SM\nbatted\nbatten/GSMD\nbatter/JZGSMDR\nbatterer/M\nbattery/SM\nbatting/M\nbattle/LDRSMZG\nbattleaxe/MS\nbattledore/SM\nbattledress\nbattlefield/MS\nbattlefront/MS\nbattleground/MS\nbattlement/SM\nbattler/M\nbattleship/SM\nbatty/RT\nbauble/SM\nbaud/SM\nbauxite/M\nbawd/SM\nbawdily\nbawdiness/M\nbawdy/PRT\nbawl/SGMD\nbay/SMDG\nbayberry/SM\nbayonet/SMDG\nbayou/MS\nbazaar/SM\nbazillion/S\nbazooka/SM\nbbl\nbdrm\nbe\nbeach/MDSG\nbeachcomber/SM\nbeachfront\nbeachhead/MS\nbeachwear/M\nbeacon/SM\nbead/SGMD\nbeading/M\nbeadle/SM\nbeady/RT\nbeagle/SM\nbeak/SZMDR\nbeaker/M\nbeam/SGMD\nbean/SGMD\nbeanbag/MS\nbeanfeast/S\nbeanie/SM\nbeanpole/MS\nbeansprout/S\nbeanstalk/MS\nbear/SZGBJMR\nbearable/U\nbearably/U\nbeard/MDGS\nbeardless\nbearer/M\nbearing/M\nbearish/PY\nbearishness/M\nbearlike\nbearskin/MS\nbeast/MS\nbeastliness/M\nbeastly/TPRM\nbeat/SZGBMNRJ\nbeatable/U\nbeaten/U\nbeater/M\nbeatific\nbeatifically\nbeatification/M\nbeatify/GXNDS\nbeating/M\nbeatitude/SM\nbeatnik/MS\nbeau/SM\nbeaut/MS\nbeauteous/Y\nbeautician/SM\nbeautification/M\nbeautifier/M\nbeautiful/Y\nbeautify/NDRSZG\nbeauty/SM\nbeaver/SGMD\nbebop/MS\nbecalm/GSD\nbecame\nbecause\nbeck/SM\nbeckon/SGD\nbecloud/GDS\nbecome/S\nbecoming/UY\nbecquerel/S\nbed/SM\nbedaub/GSD\nbedazzle/GDSL\nbedazzlement/M\nbedbug/SM\nbedchamber/S\nbedclothes/M\nbedded\nbedder\nbedding/M\nbedeck/GSD\nbedevil/LGDS\nbedevilment/M\nbedfellow/SM\nbedhead/S\nbedim/S\nbedimmed\nbedimming\nbedizen/GDS\nbedlam/SM\nbedpan/SM\nbedpost/SM\nbedraggle/GDS\nbedridden\nbedrock/SM\nbedroll/SM\nbedroom/SM\nbedside/SM\nbedsit/S\nbedsitter/S\nbedsore/SM\nbedspread/SM\nbedstead/SM\nbedtime/SM\nbee/RSMZGJ\nbeebread/M\nbeech/MS\nbeechnut/MS\nbeef/SGMD\nbeefburger/SM\nbeefcake/MS\nbeefiness/M\nbeefsteak/MS\nbeefy/RPT\nbeehive/MS\nbeekeeper/MS\nbeekeeping/M\nbeeline/MS\nbeen\nbeep/SZGMDR\nbeeper/M\nbeer/M\nbeery/TR\nbeeswax/M\nbeet/SM\nbeetle/MGDS\nbeetroot/S\nbeeves\nbefall/SGN\nbefell\nbefit/S\nbefitted\nbefitting/Y\nbefog/S\nbefogged\nbefogging\nbefore\nbeforehand\nbefoul/DGS\nbefriend/SGD\nbefuddle/GLDS\nbefuddlement/M\nbeg/S\nbegan\nbegat\nbeget/S\nbegetter/S\nbegetting\nbeggar/MDYGS\nbeggary/M\nbegged\nbegging\nbegin/S\nbeginner/SM\nbeginning/MS\nbegone\nbegonia/SM\nbegot\nbegotten\nbegrime/DSG\nbegrudge/DSG\nbegrudging/Y\nbeguile/DRSZGL\nbeguilement/M\nbeguiler/M\nbeguiling/Y\nbeguine/SM\nbegum/MS\nbegun\nbehalf/M\nbehalves\nbehave/GDS\nbehavior/SM\nbehavioral/Y\nbehaviorism/M\nbehaviorist/MS\nbehead/DGS\nbeheld\nbehemoth/M\nbehemoths\nbehest/MS\nbehind/MS\nbehindhand\nbehold/NRZGS\nbeholder/M\nbehoove/DSG\nbeige/M\nbeing/M\nbejewel/SDG\nbelabor/SDG\nbelated/Y\nbelay/GDS\nbelch/GMDS\nbeleaguer/GSD\nbelfry/SM\nbelie/DS\nbelief/EUM\nbeliefs\nbelievable/U\nbelievably/U\nbelieve/EDRSZG\nbeliever/EUMS\nbelieving/U\nbelittle/LDSG\nbelittlement/M\nbell/SGMD\nbelladonna/M\nbellboy/SM\nbelle/MS\nbelled/A\nbelletrist/MS\nbelletristic\nbellhop/SM\nbellicose\nbellicosity/M\nbelligerence/M\nbelligerency/M\nbelligerent/MYS\nbelling/A\nbellman/M\nbellmen\nbellow/MDGS\nbellwether/MS\nbelly/GDSM\nbellyache/MGDS\nbellybutton/SM\nbellyful/MS\nbelong/JDGS\nbelonging/M\nbeloved/SM\nbelow\nbelt/SGMD\nbeltway/SM\nbeluga/MS\nbelying\nbemire/GDS\nbemoan/DGS\nbemuse/LGDS\nbemused/Y\nbemusement/M\nbench/GMDS\nbenchmark/MS\nbend/BSZGMR\nbender/M\nbendy/TR\nbeneath\nbenedictine\nbenediction/SM\nbenedictory\nbenefaction/SM\nbenefactor/MS\nbenefactress/MS\nbenefice/SM\nbeneficence/M\nbeneficent/Y\nbeneficial/Y\nbeneficiary/SM\nbenefit/SMDG\nbenevolence/SM\nbenevolent/Y\nbenighted/Y\nbenign/Y\nbenignant\nbenignity/M\nbent/SM\nbentwood/M\nbenumb/DSG\nbenzene/M\nbenzine/M\nbenzyl\nbequeath/DG\nbequeaths\nbequest/MS\nberate/GDS\nbereave/DSLG\nbereavement/MS\nbereft\nberet/MS\nberg/SM\nberiberi/M\nberk/S\nberkelium/M\nberm/SM\nberry/GDSM\nberrylike\nberserk\nberth/GMD\nberths\nberyl/MS\nberyllium/M\nbeseech/ZGRS\nbeseecher/M\nbeseeching/Y\nbeseem/DSG\nbeset/S\nbesetting\nbeside/S\nbesiege/ZGDRS\nbesieger/M\nbesmear/DSG\nbesmirch/GDS\nbesom/MS\nbesot/S\nbesotted\nbesotting\nbesought\nbespangle/DSG\nbespatter/GSD\nbespeak/SG\nbespectacled\nbespoke\nbespoken\nbest/SGMD\nbestial/Y\nbestiality/M\nbestiary/SM\nbestir/S\nbestirred\nbestirring\nbestow/DGS\nbestowal/SM\nbestrew/SDG\nbestrewn\nbestridden\nbestride/SG\nbestrode\nbestseller/MS\nbestselling\nbet/SM\nbeta/SM\nbetake/GS\nbetaken\nbetcha\nbetel/M\nbethink/SG\nbethought\nbetide/GDS\nbetimes\nbetoken/GDS\nbetook\nbetray/DRZGS\nbetrayal/SM\nbetrayer/M\nbetroth/DG\nbetrothal/SM\nbetrothed/M\nbetroths\nbetter/MDGLS\nbetterment/M\nbetting\nbettor/MS\nbetween\nbetwixt\nbevel/GMDS\nbeverage/SM\nbevvy/S\nbevy/SM\nbewail/DGS\nbeware/GDS\nbewhiskered\nbewigged\nbewilder/LSGD\nbewildering/Y\nbewilderment/M\nbewitch/GLDS\nbewitching/Y\nbewitchment/M\nbey/SM\nbeyond\nbezel/MS\nbf\nbhaji\nbi/SMRZ\nbiannual/Y\nbias/GMDS\nbiased/U\nbiathlon/SM\nbib/SM\nbible/MS\nbiblical\nbibliographer/MS\nbibliographic\nbibliographical/Y\nbibliography/SM\nbibliophile/SM\nbibulous\nbicameral\nbicameralism/M\nbicarb/MS\nbicarbonate/MS\nbicentenary/SM\nbicentennial/SM\nbicep/MS\nbiceps/M\nbicker/MDRZGS\nbickerer/M\nbiconcave\nbiconvex\nbicuspid/MS\nbicycle/DRSMZG\nbicycler/M\nbicyclist/SM\nbid/SMG\nbiddable\nbidden/U\nbidder/MS\nbidding/M\nbiddy/SM\nbide/S\nbidet/MS\nbidirectional/Y\nbiennial/MYS\nbiennium/MS\nbier/M\nbiff/SGD\nbifocal/S\nbifocals/M\nbifurcate/XDSGN\nbifurcation/M\nbig/P\nbigamist/SM\nbigamous\nbigamy/M\nbigger\nbiggest\nbiggie/MS\nbiggish\nbighead/SM\nbighearted/P\nbigheartedness/M\nbighorn/SM\nbight/MS\nbigmouth/M\nbigmouths\nbigness/M\nbigot/MDS\nbigotry/SM\nbigwig/MS\nbijou/M\nbijoux\nbike/DRSMZG\nbiker/M\nbikini/MS\nbilabial/MS\nbilateral/Y\nbilberry/S\nbile/M\nbilge/MS\nbilingual/SMY\nbilingualism/M\nbilious/P\nbiliousness/M\nbilirubin\nbilk/SZGDR\nbilker/M\nbill/SBJGMD\nbillboard/MS\nbillet/GMDS\nbillfold/SM\nbillhook/S\nbilliard/S\nbilliards/M\nbilling/M\nbillingsgate/M\nbillion/MHS\nbillionaire/SM\nbillionth/M\nbillionths\nbillow/GMDS\nbillowy\nbilly/SM\nbillycan/S\nbimbo/MS\nbimetallic/SM\nbimetallism/M\nbimonthly/SM\nbin/SM\nbinary/SM\nbind's\nbind/AUGS\nbinder/MS\nbindery/SM\nbinding/MS\nbindweed/M\nbinge/MDS\nbingo/M\nbinman\nbinmen\nbinnacle/SM\nbinned\nbinning\nbinocular/MS\nbinomial/SM\nbio/SM\nbiochemical/SMY\nbiochemist/MS\nbiochemistry/M\nbiodegradability/M\nbiodegrade/DSGB\nbiodiversity/M\nbioethics/M\nbiofeedback/M\nbiog\nbiographer/SM\nbiographic\nbiographical/Y\nbiography/SM\nbiol\nbiologic\nbiological/Y\nbiologist/MS\nbiology/M\nbiomass/M\nbiomedical\nbionic/S\nbionically\nbionics/M\nbiophysical\nbiophysicist/MS\nbiophysics/M\nbiopic/MS\nbiopsy/GDSM\nbioreactor/S\nbiorhythm/MS\nbiosensor/S\nbiosphere/SM\nbiosynthesis\nbiotech\nbiotechnological\nbiotechnology/M\nbiotin/M\nbipartisan\nbipartisanship/M\nbipartite\nbiped/MS\nbipedal\nbiplane/MS\nbipolar\nbipolarity/M\nbiracial\nbirch/GMDS\nbird/SZGMDR\nbirdbath/M\nbirdbaths\nbirdbrain/SMD\nbirdcage/S\nbirder/M\nbirdhouse/MS\nbirdie/MDS\nbirdieing\nbirdlike\nbirdlime/M\nbirdseed/M\nbirdsong\nbirdwatcher/SM\nbirdying\nbiretta/SM\nbirth/ZGMDR\nbirthday/MS\nbirther/M\nbirthmark/MS\nbirthplace/MS\nbirthrate/MS\nbirthright/MS\nbirths/A\nbirthstone/SM\nbiscuit/SM\nbisect/DGS\nbisection/MS\nbisector/SM\nbisexual/MYS\nbisexuality/M\nbishop/MS\nbishopric/SM\nbismuth/M\nbison/M\nbisque/M\nbistro/MS\nbit/CSMG\nbitch/GMDS\nbitchily\nbitchiness/M\nbitchy/PRT\nbitcoin/SM\nbite/RSMZ\nbiter/M\nbiting/Y\nbitmap/S\nbitten\nbitter/PMRYTS\nbittern/SM\nbitterness/M\nbitters/M\nbittersweet/MS\nbitty/TR\nbitumen/M\nbituminous\nbivalent\nbivalve/SM\nbivouac/MS\nbivouacked\nbivouacking\nbiweekly/SM\nbiyearly\nbiz/M\nbizarre/Y\nbk\nbl/DG\nblab/SM\nblabbed\nblabber/DGS\nblabbermouth/M\nblabbermouths\nblabbing\nblack/PXTGMDNRYS\nblackamoor/MS\nblackball/SGMD\nblackberry/GSM\nblackbird/SM\nblackboard/MS\nblackcurrant/S\nblacken/DG\nblackface\nblackguard/SM\nblackhead/MS\nblacking/M\nblackish\nblackjack/MDGS\nblackleg/S\nblacklist/MDSG\nblackmail/MDRSZG\nblackmailer/M\nblackness/M\nblackout/SM\nblacksmith/M\nblacksmiths\nblacksnake/SM\nblackthorn/SM\nblacktop/SM\nblacktopped\nblacktopping\nbladder/MS\nblade/MDS\nblag/S\nblagged\nblagging\nblah/M\nblahs/M\nblame/BMGDRS\nblameless/YP\nblamelessness/M\nblameworthiness/M\nblameworthy/P\nblammo\nblanch/GDS\nblancmange/MS\nbland/PTRY\nblandish/DSLG\nblandishment/SM\nblandness/M\nblank/TGPMDRYS\nblanket/GMDS\nblankness/M\nblare/MGDS\nblarney/SMDG\nblase\nblaspheme/ZGDRS\nblasphemer/M\nblasphemous/Y\nblasphemy/SM\nblast/ZGMDRS\nblaster/M\nblastoff/MS\nblat/S\nblatancy/SM\nblatant/Y\nblather/SMDG\nblaze/MZGDRS\nblazer/M\nblazon/MDGS\nbldg\nbleach/MDRSZG\nbleached/U\nbleacher/M\nbleak/TPRY\nbleakness/M\nblear\nblearily\nbleariness/M\nbleary/PRT\nbleat/GMDS\nbleed/ZGRS\nbleeder/M\nbleeding/M\nbleep/ZGMDRS\nbleeper/M\nblemish/GMDS\nblemished/U\nblench/DSG\nblend/ZGMDRS\nblender/M\nbless/GDSJ\nblessed/YP\nblessedness/M\nblessing/M\nbletch\nblew\nblight/ZGMDRS\nblimey\nblimp/MS\nblimpish\nblind/PZTGMDRYS\nblinder/M\nblindfold/SMDG\nblinding/Y\nblindness/M\nblindside/DSG\nblini/MS\nblink/ZGMDRS\nblinker/MDG\nblintz/MS\nblintze/M\nblip/SM\nbliss/M\nblissful/YP\nblissfulness/M\nblister/GMDS\nblistering/Y\nblistery\nblithe/PYTR\nblitheness/M\nblither/G\nblithesome\nblitz/GMDS\nblitzkrieg/MS\nblivet/S\nblizzard/SM\nbloat/ZGDRS\nbloatware\nblob/SM\nblobbed\nblobbing\nbloc/SM\nblock's\nblock/UGDS\nblockade/MZGDRS\nblockader/M\nblockage/MS\nblockbuster/SM\nblockbusting/M\nblocker/MS\nblockhead/SM\nblockhouse/MS\nblog/SM\nblogged\nblogger/MS\nblogging\nbloke/MS\nblokish\nblond/PTMRS\nblonde/MS\nblondish\nblondness/M\nblood/GMDS\nbloodbath/M\nbloodbaths\nbloodcurdling\nbloodhound/SM\nbloodily\nbloodiness/M\nbloodless/YP\nbloodlessness/M\nbloodletting/M\nbloodline/SM\nbloodmobile/MS\nbloodshed/M\nbloodshot\nbloodstain/SMD\nbloodstock/M\nbloodstream/SM\nbloodsucker/SM\nbloodsucking\nbloodthirstily\nbloodthirstiness/M\nbloodthirsty/RPT\nbloody/PTGDRS\nbloom/ZGMDRS\nbloomer/M\nbloop/ZGMDRS\nblooper/M\nblossom/GMDS\nblossomy\nblot/SM\nblotch/GMDS\nblotchy/TR\nblotted\nblotter/MS\nblotting\nblotto\nblouse/MGDS\nblow/SZGMR\nblower/M\nblowfly/SM\nblowgun/MS\nblowhard/MS\nblowhole/S\nblowjob\nblowlamp/S\nblown\nblowout/SM\nblowpipe/SM\nblowtorch/MS\nblowup/MS\nblowy/TR\nblowzy/RT\nblubber/GSMD\nblubbery\nbludgeon/MDGS\nblue/DRSPMTG\nbluebell/MS\nblueberry/SM\nbluebird/MS\nbluebonnet/SM\nbluebottle/SM\nbluefish/MS\nbluegill/MS\nbluegrass/M\nblueish\nbluejacket/SM\nbluejeans/M\nblueness/M\nbluenose/MS\nbluepoint/MS\nblueprint/MDGS\nbluestocking/SM\nbluesy/RT\nbluet/MS\nbluff/ZTGPMDRYS\nbluffer/M\nbluffness/M\nbluing/M\nbluish\nblunder/MDRZGS\nblunderbuss/MS\nblunderer/M\nblunt/PTGDRYS\nbluntness/M\nblur/SM\nblurb/MS\nblurred\nblurriness/M\nblurring\nblurry/TRP\nblurt/GDS\nblush/ZGMDRS\nblusher/M\nbluster/MDRSZG\nblusterer/M\nblusterous\nblustery\nblvd\nboa/SM\nboar/SM\nboard/ZGMDRS\nboarder/M\nboarding/M\nboardinghouse/MS\nboardroom/MS\nboardwalk/MS\nboast/ZGMDRS\nboaster/M\nboastful/PY\nboastfulness/M\nboat/SZGMDR\nboater/M\nboathouse/MS\nboating/M\nboatload/S\nboatman/M\nboatmen\nboatswain/SM\nboatyard/S\nbob/SM\nbobbed\nbobbin/MS\nbobbing\nbobble/MGDS\nbobby/SM\nbobbysoxer/SM\nbobcat/MS\nbobolink/SM\nbobsled/SM\nbobsledded\nbobsledder/MS\nbobsledding\nbobsleigh/M\nbobsleighs\nbobtail/SM\nbobwhite/MS\nboccie/M\nbock/M\nbod/SMDG\nbodacious\nbode/S\nbodega/MS\nbodge/GDS\nbodice/MS\nbodily\nbodkin/MS\nbody/DSM\nbodybuilder/SM\nbodybuilding/M\nbodyguard/MS\nbodysuit/SM\nbodywork/M\nboffin/S\nboffo\nbog/SM\nboga\nbogey/GMDS\nbogeyman/M\nbogeymen\nbogged\nbogging\nboggle/GDS\nboggy/TR\nbogie/MS\nbogon\nbogosity\nbogus\nbogyman/M\nbogymen\nbohemian/SM\nbohemianism/M\nboil/SJZGMDR\nboiler/M\nboilermaker/SM\nboilerplate/M\nboink/GDS\nboisterous/YP\nboisterousness/M\nbola/SM\nbold/PTRY\nboldface/DM\nboldness/M\nbole/SM\nbolero/MS\nbolivar/MS\nbolivares\nboll/SM\nbollard/S\nbollix/GMDS\nbollocking/S\nbollocks\nbologna/M\nbolshie\nbolster/GMDS\nbolt's\nbolt/USGD\nbolthole/S\nbolus/MS\nbomb/SJZGMDR\nbombard/GDLS\nbombardier/MS\nbombardment/SM\nbombast/M\nbombastic\nbombastically\nbomber/M\nbombproof\nbombshell/SM\nbombsite/S\nbonanza/MS\nbonbon/MS\nbonce/S\nbond/SGMD\nbondage/M\nbondholder/MS\nbonding/M\nbondman/M\nbondmen\nbondsman/M\nbondsmen\nbondwoman/M\nbondwomen\nbone/DRSMZG\nbonehead/SMD\nboneless\nboner/M\nboneshaker/S\nboneyard\nbonfire/MS\nbong/SGMD\nbongo/MS\nbonhomie/M\nboniness/M\nbonito/MS\nbonk/SZGD\nbonnet/MS\nbonny/TR\nbonobo/MS\nbonsai/M\nbonus/MS\nbony/PTR\nboo/SMDHG\nboob/SGMD\nbooby/SM\nboodle/MS\nbooger/S\nboogeyman/M\nboogeymen\nboogie/MDS\nboogieing\nboogieman/M\nboohoo/GMDS\nbook/SBJGMD\nbookbinder/SM\nbookbindery/SM\nbookbinding/M\nbookcase/MS\nbookend/MS\nbookie/MS\nbooking/M\nbookish\nbookkeeper/MS\nbookkeeping/M\nbooklet/MS\nbookmaker/SM\nbookmaking/M\nbookmark/SMDG\nbookmobile/SM\nbookplate/MS\nbookseller/MS\nbookshelf/M\nbookshelves\nbookshop/SM\nbookstall/S\nbookstore/MS\nbookworm/SM\nboom/SZGMDR\nboombox/MS\nboomerang/MDGS\nboon/SM\nboondocks/M\nboondoggle/MZGDRS\nboondoggler/M\nboonies/M\nboor/SM\nboorish/PY\nboorishness/MS\nboost/ZGMDRS\nbooster/M\nboot's\nboot/ASGD\nbootblack/SM\nbootee/MS\nbooth/M\nbooths\nbootlace/S\nbootleg/MS\nbootlegged\nbootlegger/MS\nbootlegging/M\nbootless\nbootstrap/MS\nbootstrapped\nbootstrapping\nbooty/SM\nbooze/MZGDRS\nboozer/M\nboozy/TR\nbop/SM\nbopped\nbopping\nborax/M\nbordello/MS\nborder/GMDS\nborderland/MS\nborderline/MS\nbore/DRSMZG\nboredom/M\nborehole/S\nborer/M\nboring/Y\nborn/IAU\nborne\nboron/M\nborough/M\nboroughs\nborrow/SDRZGJ\nborrower/M\nborrowing/M\nborscht/M\nborstal/S\nborzoi/SM\nbosh/M\nbosom's\nbosom/US\nbosomy\nboss/DSGM\nbossily\nbossiness/M\nbossism/M\nbossy/RTP\nbot/S\nbotanic\nbotanical/Y\nbotanist/SM\nbotany/M\nbotch/DRSZGM\nbotcher/M\nboth\nbother/SMDG\nbotheration\nbothersome\nbotnet/SM\nbottle/DRSMZG\nbottleneck/MS\nbottler/M\nbottom/SMDG\nbottomless\nbotulinum\nbotulism/M\nboudoir/SM\nbouffant/SM\nbougainvillea/MS\nbough/M\nboughs\nbought\nbouillabaisse/SM\nbouillon/MS\nboulder/SM\nboules\nboulevard/SM\nbounce/DRSMZG\nbouncer/M\nbouncily\nbounciness/M\nbouncy/RTP\nbound/ASMGD\nboundary/SM\nbounden\nbounder/SM\nboundless/PY\nboundlessness/M\nbounteous/YP\nbounteousness/M\nbountiful/YP\nbountifulness/M\nbounty/SM\nbouquet/SM\nbourbon/SM\nbourgeois/M\nbourgeoisie/M\nboustrophedon\nbout/MS\nboutique/SM\nboutonniere/MS\nbouzouki/MS\nbovine/SM\nbovver\nbow/ZGSMDR\nbowdlerization/MS\nbowdlerize/DSG\nbowed/U\nbowel/SM\nbower/M\nbowl/MDRZGS\nbowleg/SM\nbowlegged\nbowler/M\nbowlful/SM\nbowline/SM\nbowling/M\nbowman/M\nbowmen\nbowsprit/SM\nbowstring/SM\nbowwow/SM\nbox/ZGMDNRS\nboxcar/SM\nboxer/M\nboxing/M\nboxlike\nboxroom/S\nboxwood/M\nboxy/RT\nboy/SM\nboycott/SGMD\nboyfriend/MS\nboyhood/SM\nboyish/YP\nboyishness/M\nboysenberry/SM\nbozo/MS\nbpm\nbps\nbra/SM\nbrace/MZGDRS\nbracelet/MS\nbracer/M\nbracero/MS\nbracken/M\nbracket/GMDS\nbrackish/P\nbrackishness/M\nbract/MS\nbrad/SM\nbradawl/S\nbradycardia\nbrae/SM\nbrag/SM\nbraggadocio/SM\nbraggart/SM\nbragged\nbragger/MS\nbragging\nbraid/GMDS\nbraiding/M\nbraille/M\nbrain/GMDS\nbrainchild/M\nbrainchildren/M\nbraininess/M\nbrainless/Y\nbrainpower\nbrainstorm/SMDG\nbrainstorming/M\nbrainteaser/SM\nbrainwash/DSG\nbrainwashing/M\nbrainwave/S\nbrainy/PTR\nbraise/GDS\nbrake/MGDS\nbrakeman/M\nbrakemen\nbramble/MS\nbrambly\nbran/M\nbranch/GMDS\nbranchlike\nbrand/ZGMDRS\nbranded/U\nbrander/M\nbrandish/DSG\nbrandy/GDSM\nbrash/PTRY\nbrashness/M\nbrass/MS\nbrasserie/MS\nbrassiere/MS\nbrassily\nbrassiness/M\nbrassy/PTR\nbrat/SM\nbratty/RT\nbratwurst/SM\nbravado/M\nbrave/GPMYDTRS\nbraveness/M\nbravery/M\nbravo/SM\nbravura/SM\nbrawl/SDRZGM\nbrawler/M\nbrawn/M\nbrawniness/M\nbrawny/RTP\nbray/DGSM\nbraze/DRSZG\nbrazen/SDYGP\nbrazenness/M\nbrazer/M\nbrazier/SM\nbreach/GMDS\nbread/GMDHS\nbreadbasket/SM\nbreadboard/SM\nbreadbox/MS\nbreadcrumb/MS\nbreadfruit/SM\nbreadline/MS\nbreadth/M\nbreadths\nbreadwinner/SM\nbreak/BMZGRS\nbreakable/MS\nbreakage/MS\nbreakaway/MS\nbreakdown/MS\nbreaker/M\nbreakfast/MDGS\nbreakfront/MS\nbreakneck\nbreakout/MS\nbreakpoints\nbreakthrough/M\nbreakthroughs\nbreakup/SM\nbreakwater/SM\nbream/MS\nbreast/SMDG\nbreastbone/MS\nbreastfed\nbreastfeed/GS\nbreastplate/SM\nbreaststroke/SM\nbreastwork/MS\nbreath/MDRSZGB\nbreathalyze/ZGDRS\nbreathe\nbreather/M\nbreathing/M\nbreathless/PY\nbreathlessness/M\nbreaths\nbreathtaking/Y\nbreathy/RT\nbred/I\nbreech/MS\nbreed/SRZGM\nbreeder/M\nbreeding/IM\nbreeze/DSMG\nbreezeway/SM\nbreezily\nbreeziness/M\nbreezy/RTP\nbrethren\nbreve/SM\nbrevet/SM\nbrevetted\nbrevetting\nbreviary/SM\nbrevity/M\nbrew/MDRZGS\nbrewer/M\nbrewery/SM\nbrewpub/SM\nbribe/DRSMZG\nbriber/M\nbribery/M\nbrick/SMDG\nbrickbat/SM\nbrickie/S\nbricklayer/MS\nbricklaying/M\nbrickwork/M\nbrickyard/S\nbridal/SM\nbride/SM\nbridegroom/SM\nbridesmaid/MS\nbridge/DSMG\nbridgeable/U\nbridgehead/SM\nbridgework/M\nbridle/DSMG\nbridled/U\nbridleway/S\nbrie/MZR\nbrief's\nbrief/CSDTGJ\nbriefcase/SM\nbriefer\nbriefing/CM\nbriefly\nbriefness/M\nbrier/M\nbrig/MS\nbrigade/SM\nbrigadier/MS\nbrigand/SM\nbrigandage/M\nbrigantine/MS\nbright/SPNRYXT\nbrighten/DRZG\nbrightener/M\nbrightness/M\nbrights/M\nbrill\nbrilliance/M\nbrilliancy/M\nbrilliant/MYS\nbrilliantine/M\nbrim/MS\nbrimful\nbrimless\nbrimmed\nbrimming\nbrimstone/M\nbrindle/DM\nbrine/M\nbring/SRZG\nbringer/M\nbrininess/M\nbrink/SM\nbrinkmanship/M\nbriny/RTP\nbrioche/SM\nbriquette/MS\nbrisk/SDRYTGP\nbrisket/SM\nbriskness/M\nbristle/DSMG\nbristly/TR\nbritches/M\nbrittle/PRMT\nbrittleness/M\nbro/SMH\nbroach/MDSG\nbroad/SMNRYXTP\nbroadband/M\nbroadcast/AMGS\nbroadcaster/MS\nbroadcasting/M\nbroadcloth/M\nbroaden/DG\nbroadloom/M\nbroadminded\nbroadness/M\nbroadsheet/SM\nbroadside/MGDS\nbroadsword/SM\nbrocade/DSMG\nbroccoli/M\nbrochette/SM\nbrochure/MS\nbrogan/SM\nbrogue/SM\nbroil/SMDRZG\nbroiler/M\nbroke\nbroken/YP\nbrokenhearted/Y\nbrokenness/M\nbroker/SMDG\nbrokerage/MS\nbrolly/S\nbromide/SM\nbromidic\nbromine/M\nbronc/SM\nbronchi\nbronchial\nbronchitic\nbronchitis/M\nbronchus/M\nbronco/SM\nbroncobuster/SM\nbrontosaur/MS\nbrontosaurus/MS\nbronze/DSMG\nbrooch/MS\nbrood/SMDRZG\nbrooder/M\nbroodily\nbrooding/MY\nbroodmare/MS\nbroody/RMPT\nbrook/SMDG\nbrooklet/SM\nbroom/SM\nbroomstick/MS\nbroth/MRZ\nbrothel/MS\nbrother/MY\nbrotherhood/MS\nbrotherliness/M\nbroths\nbrougham/SM\nbrought\nbrouhaha/SM\nbrow/MS\nbrowbeat/SNG\nbrown/SMDRPTG\nbrownfield\nbrownie/MS\nbrownish\nbrownness/M\nbrownout/SM\nbrownstone/MS\nbrowse/DRSMZG\nbrowser/M\nbrr\nbruin/SM\nbruise/DRSMZG\nbruiser/M\nbruising/M\nbruit/SDG\nbrunch/MDSG\nbrunet/SM\nbrunette/MS\nbrunt/M\nbrush/MDSG\nbrushoff/SM\nbrushstroke/S\nbrushwood/M\nbrushwork/M\nbrusque/RPYT\nbrusqueness/M\nbrutal/Y\nbrutality/SM\nbrutalization/M\nbrutalize/GDS\nbrute/SM\nbrutish/PY\nbrutishness/M\nbu\nbub/SM\nbubble/DSMG\nbubblegum/M\nbubbly/RMT\nbubo/M\nbuboes\nbuccaneer/SGMD\nbuck/MDGS\nbuckaroo/SM\nbuckboard/MS\nbucket/SGMD\nbucketful/MS\nbuckeye/MS\nbuckle's\nbuckle/UDSG\nbuckler/MS\nbuckram/M\nbucksaw/MS\nbuckshot/M\nbuckskin/MS\nbuckteeth\nbucktooth/MD\nbuckwheat/M\nbuckyball/SM\nbucolic/MS\nbucolically\nbud/SM\nbudded\nbudding/S\nbuddy/SM\nbudge/DSG\nbudgerigar/MS\nbudget/SGMD\nbudgetary\nbudgie/SM\nbuff/AMDGS\nbuffalo/MDG\nbuffaloes\nbuffer/SMDG\nbuffet/SMDGJ\nbuffoon/SM\nbuffoonery/M\nbuffoonish\nbug's\nbug/CS\nbugaboo/SM\nbugbear/SM\nbugged/C\nbugger/SMDG\nbuggery\nbugging/C\nbuggy/RSMT\nbugle/DRSMZG\nbugler/M\nbuild/SMRZGJ\nbuilder/M\nbuilding/M\nbuildup/SM\nbuilt/AI\nbuiltin\nbulb/MS\nbulbous\nbulge/DSMG\nbulgy/RT\nbulimarexia/M\nbulimia/M\nbulimic/SM\nbulk/MDGS\nbulkhead/MS\nbulkiness/M\nbulky/RTP\nbull/MDGS\nbulldog/SM\nbulldogged\nbulldogging\nbulldoze/ZGDRS\nbulldozer/M\nbullet/SM\nbulletin/MDGS\nbulletproof/SDG\nbullfight/SMRZG\nbullfighter/M\nbullfighting/M\nbullfinch/MS\nbullfrog/MS\nbullhead/MDS\nbullheaded/PY\nbullheadedness/M\nbullhorn/MS\nbullion/M\nbullish/YP\nbullishness/M\nbullock/SM\nbullpen/SM\nbullring/MS\nbullshit/MS!\nbullshitted/!\nbullshitter/SM!\nbullshitting/!\nbullwhip/S\nbully/DSMG\nbulrush/MS\nbulwark/MS\nbum/SM\nbumbag/S\nbumble/DRSZG\nbumblebee/SM\nbumbler/M\nbumf\nbummed\nbummer/SM\nbummest\nbumming\nbump/MDRZGS\nbumper/M\nbumph\nbumpiness/M\nbumpkin/MS\nbumptious/PY\nbumptiousness/M\nbumpy/PRT\nbun/SM\nbunch/MDSG\nbunchy/RT\nbunco/SMDG\nbundle/DSMG\nbung/MDGS\nbungalow/MS\nbungee/SM\nbunghole/MS\nbungle/DRSMZG\nbungler/M\nbunion/SM\nbunk's\nbunk/CDGS\nbunker/SM\nbunkhouse/SM\nbunkum/M\nbunny/SM\nbunt/MDGSJ\nbunting/M\nbuoy/MDGS\nbuoyancy/M\nbuoyant/Y\nbur/SMY\nburble/DSMG\nburbs/M\nburden's\nburden/USGD\nburdensome\nburdock/M\nbureau/SM\nbureaucracy/SM\nbureaucrat/MS\nbureaucratic\nbureaucratically\nbureaucratization/M\nbureaucratize/GDS\nburg/MRZS\nburgeon/DSG\nburger/M\nburgh/MRZ\nburgher/M\nburghs\nburglar/MS\nburglarize/GDS\nburglarproof\nburglary/SM\nburgle/DSG\nburgomaster/SM\nburgundy/SM\nburial/ASM\nburka/S\nburl/MDS\nburlap/M\nburlesque/MGDS\nburliness/M\nburly/RPT\nburn/MDRZGSB\nburnable/SM\nburner/M\nburnish/ZGMDRS\nburnisher/M\nburnoose/MS\nburnout/MS\nburnt\nburp/MDGS\nburqa/S\nburr/MDGS\nburrito/MS\nburro/SM\nburrow/SMDRZG\nburrower/M\nbursa/M\nbursae\nbursar/SM\nbursary/SM\nbursitis/M\nburst/SMG\nbury/ADSG\nbus/AMS\nbusboy/SM\nbusby/SM\nbused\nbusgirl/MS\nbush/MDSGJ\nbushel/SGMD\nbushiness/M\nbushing/M\nbushman/M\nbushmaster/SM\nbushmen\nbushwhack/DRSZG\nbushwhacker/M\nbushy/RPT\nbusily\nbusiness/MS\nbusinesslike\nbusinessman/M\nbusinessmen\nbusinessperson/SM\nbusinesswoman/M\nbusinesswomen\nbusing/M\nbusk/DRZGS\nbuskin/SM\nbusload/S\nbuss/M\nbust/MDRZGS\nbuster/M\nbustle/DSMG\nbusty/RZT\nbusy/DRSTGP\nbusybody/SM\nbusyness/M\nbusywork/M\nbut/ACS\nbutane/M\nbutch/MRSZ\nbutcher/MDG\nbutchery/SM\nbutler/SM\nbutt/MDRZGS\nbutte/SM\nbutted/A\nbutter/MDG\nbutterball/MS\nbuttercream\nbuttercup/SM\nbutterfat/M\nbutterfingered\nbutterfingers/M\nbutterfly/GDSM\nbuttermilk/M\nbutternut/SM\nbutterscotch/M\nbuttery/TRSM\nbutting/A\nbuttock/SM\nbutton's\nbutton/USDG\nbuttonhole/DSMG\nbuttonwood/MS\nbuttress/MDSG\nbutty/S\nbuxom\nbuy/ZGSMR\nbuyback/SM\nbuyer/M\nbuyout/SM\nbuzz/MDRSZG\nbuzzard/MS\nbuzzer/M\nbuzzkill/SM\nbuzzword/SM\nbx\nbxs\nby/M\nbye/SM\nbygone/SM\nbylaw/SM\nbyline/SM\nbypass/GMDS\nbypath/M\nbypaths\nbyplay/M\nbyproduct/MS\nbyre/S\nbyroad/SM\nbystander/MS\nbyte/MS\nbyway/SM\nbyword/SM\nbyzantine\nc/IES\nca\ncab/SMRZ\ncabal/MS\ncabala's\ncaballero/MS\ncabana/SM\ncabaret/SM\ncabbage/MS\ncabbed\ncabbing\ncabby/SM\ncabdriver/SM\ncabin/MS\ncabinet/SM\ncabinetmaker/MS\ncabinetmaking/M\ncabinetry/M\ncabinetwork/M\ncable/MGDS\ncablecast/GMS\ncablegram/MS\ncabochon/SM\ncaboodle/M\ncaboose/SM\ncabriolet/SM\ncabstand/SM\ncacao/MS\ncache/MGDS\ncachepot/SM\ncachet/MS\ncackle/MZGDRS\ncackler/M\ncacophonous\ncacophony/SM\ncacti\ncactus/M\ncad/SM\ncadaver/SM\ncadaverous\ncaddie/MDS\ncaddish/YP\ncaddishness/M\ncaddying\ncadence/DSM\ncadenza/SM\ncadet/MS\ncadge/ZGDRS\ncadger/M\ncadmium/M\ncadre/MS\ncaducei\ncaduceus/M\ncaesura/SM\ncafe/SM\ncafeteria/MS\ncafetiere/S\ncaff/CS\ncaffeinated\ncaffeine/M\ncaftan/MS\ncage/DSMG\ncagey\ncagier\ncagiest\ncagily\ncaginess/M\ncagoule/S\ncahoot/MS\ncaiman/MS\ncairn/MS\ncaisson/SM\ncaitiff/SM\ncajole/ZGLDRS\ncajolement/M\ncajoler/M\ncajolery/M\ncake/DSMG\ncakewalk/SM\ncal\ncalabash/MS\ncalaboose/SM\ncalamari/SM\ncalamine/M\ncalamitous/Y\ncalamity/SM\ncalcareous\ncalciferous\ncalcification/M\ncalcify/GNDS\ncalcimine/DSMG\ncalcine/DSG\ncalcite/M\ncalcium/M\ncalculable/I\ncalculate/AGNVDSX\ncalculated/Y\ncalculating/Y\ncalculation/AM\ncalculator/SM\ncalculi\ncalculus/M\ncaldera/SM\ncalendar/MDGS\ncalender's\ncalf/M\ncalfskin/M\ncaliber/SM\ncalibrate/GNDSX\ncalibration/M\ncalibrator/SM\ncalico/M\ncalicoes\ncalifornium/M\ncaliper/SGMD\ncaliph/M\ncaliphate/MS\ncaliphs\ncalisthenic/S\ncalisthenics/M\ncalk/SGMD\ncall/ASGMD\ncalla/MS\ncallable\ncallback/MS\ncalled/U\ncaller/MS\ncalligrapher/SM\ncalligraphic\ncalligraphist/MS\ncalligraphy/M\ncalling/SM\ncalliope/MS\ncallosity/SM\ncallous/PGDSY\ncallousness/M\ncallow/RPT\ncallowness/M\ncallus/MDSG\ncalm/PSTGMDRY\ncalmness/M\ncaloric\ncalorie/MS\ncalorific\ncalumet/MS\ncalumniate/GNDS\ncalumniation/M\ncalumniator/MS\ncalumnious\ncalumny/SM\ncalve/GDS\ncalypso/MS\ncalyx/MS\ncam/SM\ncamaraderie/M\ncamber/MDSG\ncambial\ncambium/SM\ncambric/M\ncamcorder/SM\ncame\ncamel/MS\ncamelhair\ncamellia/MS\ncameo/MS\ncamera/MS\ncameraman/M\ncameramen\ncamerawoman/M\ncamerawomen\ncamerawork\ncamiknickers\ncamisole/SM\ncamouflage/MZGDRS\ncamouflager/M\ncamp's\ncamp/CSGD\ncampaign/SMDRZG\ncampaigner/M\ncampanile/SM\ncampanologist/MS\ncampanology/M\ncamper/MS\ncampfire/SM\ncampground/SM\ncamphor/M\ncamping/M\ncampsite/SM\ncampus/MS\ncampy/TR\ncamshaft/SM\ncan't\ncan/SMDRZG\ncanal/MS\ncanalization/M\ncanalize/GDS\ncanape/MS\ncanard/MS\ncanary/SM\ncanasta/M\ncancan/MS\ncancel/DRSZG\ncanceler/M\ncancellation/SM\ncancer/MS\ncancerous\ncandelabra/SM\ncandelabrum/M\ncandid/YP\ncandida\ncandidacy/SM\ncandidate/MS\ncandidature/SM\ncandidness/M\ncandle/MZGDRS\ncandlelight/M\ncandlelit\ncandlepower/M\ncandler/M\ncandlestick/MS\ncandlewick/SM\ncandor/M\ncandy/GDSM\ncandyfloss\ncane/SM\ncanebrake/MS\ncaner/M\ncanine/MS\ncanister/SM\ncanker/GMDS\ncankerous\ncannabis/MS\ncanned\ncannelloni/M\ncannery/SM\ncannibal/SM\ncannibalism/M\ncannibalistic\ncannibalization/M\ncannibalize/GDS\ncannily/U\ncanniness/M\ncanning\ncannon/GMDS\ncannonade/MGDS\ncannonball/SM\ncannot\ncanny/UTR\ncanoe/MDS\ncanoeing\ncanoeist/SM\ncanola/M\ncanon/MS\ncanonical/Y\ncanonization/SM\ncanonize/DSG\ncanoodle/DSG\ncanopy/GDSM\ncanst\ncant's\ncant/CZRDGS\ncantabile\ncantaloupe/SM\ncantankerous/PY\ncantankerousness/M\ncantata/MS\ncanteen/MS\ncanter/CM\ncantered\ncantering\ncanticle/MS\ncantilever/MDGS\ncanto/MS\ncanton/MLS\ncantonal\ncantonment/MS\ncantor/MS\ncanvas/MGDS\ncanvasback/SM\ncanvass/MDRSZG\ncanvasser/M\ncanyon/MGS\ncap/SMDRBZ\ncapabilities\ncapability/IM\ncapable/I\ncapably/I\ncapacious/PY\ncapaciousness/M\ncapacitance/M\ncapacities\ncapacitor/SM\ncapacity/IM\ncaparison/MDGS\ncape/SM\ncaper/GMD\ncapeskin/M\ncapillarity/M\ncapillary/SM\ncapital/MSY\ncapitalism/M\ncapitalist/SM\ncapitalistic\ncapitalistically\ncapitalization/M\ncapitalize/ADSG\ncapitation/CSM\ncapitol/SM\ncapitulate/ADSXGN\ncapitulation/AM\ncaplet/MS\ncapo/SM\ncapon/MS\ncapped/UA\ncapping/UA\ncappuccino/SM\ncaprice/SM\ncapricious/PY\ncapriciousness/M\ncapsicum/SM\ncapsize/DSG\ncapstan/SM\ncapstone/MS\ncapsular\ncapsule/DSMG\ncapsulize/DSG\ncapt\ncaptain/SMDG\ncaptaincy/SM\ncaption/SMDG\ncaptious/YP\ncaptiousness/M\ncaptivate/DSGN\ncaptivation/M\ncaptivator/SM\ncaptive/SM\ncaptivity/SM\ncaptor/MS\ncapture/ADSMG\ncar/SMDRZG\ncarafe/MS\ncaramel/SM\ncaramelize/DSG\ncarapace/SM\ncarat/MS\ncaravan/SM\ncaravansary/SM\ncaravel/SM\ncaraway/SM\ncarbide/SM\ncarbine/SM\ncarbohydrate/SM\ncarbolic\ncarbon/MS\ncarbonaceous\ncarbonate/MGNDS\ncarbonation/M\ncarboniferous\ncarbonize/GDS\ncarborundum/M\ncarboy/MS\ncarbs\ncarbuncle/SM\ncarbuncular\ncarburetor/SM\ncarcass/MS\ncarcinogen/SM\ncarcinogenic/MS\ncarcinogenicity/M\ncarcinoma/MS\ncard/ESGMD\ncardamom/SM\ncardamon/S\ncardboard/M\ncarder/MS\ncardholder/S\ncardiac\ncardie/S\ncardigan/SM\ncardinal/SMY\ncardio\ncardiogram/SM\ncardiograph/M\ncardiographs\ncardiologist/MS\ncardiology/M\ncardiomyopathy\ncardiopulmonary\ncardiovascular\ncardsharp/MRZS\ncardsharper/M\ncare/SM\ncareen/DGS\ncareer/MDGS\ncareerism\ncareerist/SM\ncarefree\ncareful/YP\ncarefuller\ncarefullest\ncarefulness/M\ncaregiver/SM\ncareless/PY\ncarelessness/M\ncarer/M\ncaress/MDSG\ncaret/MS\ncaretaker/MS\ncareworn\ncarfare/M\ncargo/M\ncargoes\ncarhop/MS\ncaribou/SM\ncaricature/MGDS\ncaricaturist/SM\ncaries/M\ncarillon/SM\ncaring/M\ncarious\ncarjack/JSDRZG\ncarjacker/M\ncarjacking/M\ncarload/SM\ncarmine/SM\ncarnage/M\ncarnal/Y\ncarnality/M\ncarnation/IMS\ncarnelian/MS\ncarnival/MS\ncarnivora\ncarnivore/SM\ncarnivorous/PY\ncarnivorousness/M\ncarny/SM\ncarob/MS\ncarol/ZGMDRS\ncaroler/M\ncarom/GMDS\ncarotene/M\ncarotid/SM\ncarousal/SM\ncarouse/DRSMZG\ncarousel/SM\ncarouser/M\ncarp/SZGMDR\ncarpal/MS\ncarpel/MS\ncarpenter/MDGS\ncarpentry/M\ncarper/M\ncarpet/MDGS\ncarpetbag/MS\ncarpetbagged\ncarpetbagger/MS\ncarpetbagging\ncarpeting/M\ncarpi\ncarpool/SMDG\ncarport/SM\ncarpus/M\ncarrel/MS\ncarriage/SM\ncarriageway/S\ncarrier/M\ncarrion/M\ncarrot/MS\ncarroty\ncarry/ZGDRSM\ncarryall/SM\ncarrycot/S\ncarryout\ncarryover/MS\ncarsick/P\ncarsickness/M\ncart/SZGMDR\ncartage/M\ncartel/MS\ncarter/M\ncarthorse/SM\ncartilage/SM\ncartilaginous\ncartload/SM\ncartographer/SM\ncartographic\ncartography/M\ncarton/MS\ncartoon/SMDG\ncartoonist/MS\ncartridge/MS\ncartwheel/GMDS\ncarve/JZGDRS\ncarver/M\ncarvery/S\ncarving/M\ncaryatid/MS\ncasaba/MS\ncascade/DSMG\ncascara/SM\ncase/LDSJMG\ncasebook/S\ncased/U\ncaseharden/DGS\ncasein/M\ncaseload/MS\ncasement/MS\ncasework/ZMR\ncaseworker/M\ncash/GMDS\ncashback/M\ncashbook/MS\ncashew/MS\ncashier/GSMD\ncashless\ncashmere/M\ncasing/M\ncasino/MS\ncask/SM\ncasket/MS\ncassava/SM\ncasserole/DSMG\ncassette/MS\ncassia/MS\ncassock/SM\ncassowary/SM\ncast/ASGM\ncastanet/MS\ncastaway/MS\ncaste/JMZRS\ncastellated\ncaster/M\ncastigate/DSGN\ncastigation/M\ncastigator/SM\ncasting/AM\ncastle/MGDS\ncastoff/SM\ncastor/MS\ncastrate/GNXDS\ncastration/M\ncasual/PMYS\ncasualness/M\ncasualty/SM\ncasuist/SM\ncasuistic\ncasuistry/M\ncat/SM\ncataclysm/MS\ncataclysmal\ncataclysmic\ncatacomb/SM\ncatafalque/MS\ncatalepsy/M\ncataleptic/MS\ncatalog/ZGSMDR\ncataloger/M\ncatalpa/SM\ncatalyses\ncatalysis/M\ncatalyst/MS\ncatalytic/M\ncatalyze/GDS\ncatamaran/SM\ncatapult/GMDS\ncataract/MS\ncatarrh/M\ncatastrophe/MS\ncatastrophic\ncatastrophically\ncatatonia/M\ncatatonic/SM\ncatbird/SM\ncatboat/SM\ncatcall/GSMD\ncatch/ZGJLMRS\ncatchall/MS\ncatcher/M\ncatchment/MS\ncatchpenny\ncatchphrase/SM\ncatchword/MS\ncatchy/RT\ncatechism/SM\ncatechist/SM\ncatechize/DSG\ncategorical/Y\ncategorization/MS\ncategorize/GDS\ncategory/SM\ncater/ZGJDRS\ncatercorner\ncaterer/M\ncaterpillar/MS\ncaterwaul/SMDG\ncatfish/MS\ncatgut/M\ncatharses\ncatharsis/M\ncathartic/SM\ncathedral/SM\ncatheter/SM\ncatheterize/DSG\ncathode/SM\ncathodic\ncatholic\ncatholicity/M\ncation/MS\ncatkin/MS\ncatlike\ncatnap/MS\ncatnapped\ncatnapping\ncatnip/M\ncatsuit/S\ncattail/SM\ncatted\ncattery/S\ncattily\ncattiness/M\ncatting\ncattle/M\ncattleman/M\ncattlemen\ncatty/TPR\ncatwalk/SM\ncaucus/MDSG\ncaudal/Y\ncaught/U\ncauldron/MS\ncauliflower/SM\ncaulk/ZGMDRS\ncaulker/M\ncausal/Y\ncausality/SM\ncausation/M\ncausative\ncause/MZGDRS\ncauseless\ncauser/M\ncauserie/SM\ncauseway/SM\ncaustic/SM\ncaustically\ncausticity/M\ncauterization/M\ncauterize/GDS\ncaution/SMDG\ncautionary\ncautious/IY\ncautiousness/M\ncavalcade/MS\ncavalier/SMY\ncavalry/SM\ncavalryman/M\ncavalrymen\ncave/DRSMZG\ncaveat/MS\ncaveman/M\ncavemen\ncavern/MS\ncavernous/Y\ncaviar/M\ncavil/ZGJMDRS\ncaviler/M\ncaving/M\ncavity/FSM\ncavort/DGS\ncaw/SMDG\ncay/CSM\ncayenne/M\ncayuse/MS\ncc\ncease/CMGDS\nceasefire/MS\nceaseless/YP\nceaselessness/M\nceca\ncecal\ncecum/M\ncedar/MS\ncede/FAGSD\nceder/MS\ncedilla/SM\nceilidh\nceilidhs\nceiling/MS\ncelandine/M\nceleb/S\ncelebrant/SM\ncelebrate/DSGNX\ncelebration/M\ncelebrator/SM\ncelebratory\ncelebrity/SM\nceleriac\ncelerity/M\ncelery/M\ncelesta/MS\ncelestial/Y\ncelibacy/M\ncelibate/MS\ncell/SMD\ncellar/MS\ncellist/SM\ncellmate/SM\ncello/MS\ncellophane/M\ncellphone/MS\ncellular/SM\ncellulite/M\ncellulitis\ncelluloid/M\ncellulose/M\ncement/MDRZGS\ncementer/M\ncementum/M\ncemetery/SM\ncenobite/MS\ncenobitic\ncenotaph/M\ncenotaphs\ncenser/MS\ncensor/MDGS\ncensored/U\ncensorial\ncensorious/PY\ncensoriousness/M\ncensorship/M\ncensure/BDRSMZG\ncensurer/M\ncensus/MDSG\ncent/SZMR\ncentaur/SM\ncentavo/SM\ncentenarian/MS\ncentenary/SM\ncentennial/MYS\ncenter/MDG\ncenterboard/SM\ncenterfold/MS\ncenterpiece/MS\ncentigrade\ncentigram/SM\ncentiliter/MS\ncentime/SM\ncentimeter/MS\ncentipede/SM\ncentral/SMY\ncentralism\ncentralist\ncentrality/M\ncentralization/CM\ncentralize/CGDS\ncentralizer/MS\ncentrifugal/Y\ncentrifuge/DSMG\ncentripetal/Y\ncentrism/M\ncentrist/MS\ncenturion/SM\ncentury/SM\ncephalic\nceramic/SM\nceramicist/SM\nceramics/M\nceramist/MS\ncereal/MS\ncerebellar\ncerebellum/SM\ncerebra\ncerebral\ncerebrate/GNDS\ncerebration/M\ncerebrovascular\ncerebrum/MS\ncerement/MS\nceremonial/SMY\nceremonious/UY\nceremoniousness/M\nceremony/SM\ncerise/M\ncerium/M\ncermet/M\ncert/S\ncertain/UY\ncertainty/USM\ncertifiable\ncertifiably\ncertificate/MGNXDS\ncertification/M\ncertify/DSG\ncertitude/IM\ncertitudes\ncerulean/M\ncervical\ncervices\ncervix/M\ncesarean/MS\ncesium/M\ncessation/MS\ncession/KAFSM\ncesspit/S\ncesspool/MS\ncetacean/MS\ncf\ncg\nch/IFVT\nchad/S\nchafe/GDS\nchaff/GMDS\nchaffinch/MS\nchagrin/GSMD\nchain's\nchain/UGDS\nchainsaw/MDGS\nchair/GMDS\nchairlift/MS\nchairman/M\nchairmanship/SM\nchairmen\nchairperson/SM\nchairwoman/M\nchairwomen\nchaise/MS\nchalcedony/M\nchalet/MS\nchalice/SM\nchalk/GMDS\nchalkboard/SM\nchalkiness/M\nchalky/PRT\nchallenge/DRSMZG\nchallenged/U\nchallenger/M\nchallis/M\nchamber/SMD\nchamberlain/MS\nchambermaid/MS\nchambray/M\nchameleon/SM\nchamois/M\nchamomile/MS\nchamp/ZGMDS\nchampagne/MS\nchampion/GMDS\nchampionship/MS\nchance/MGDS\nchancel/SM\nchancellery/SM\nchancellor/MS\nchancellorship/M\nchancery/SM\nchanciness/M\nchancre/SM\nchancy/PRT\nchandelier/SM\nchandler/MS\nchange/MZGDRS\nchangeability/M\nchangeable/P\nchangeableness/M\nchangeably\nchanged/U\nchangeless/Y\nchangeling/SM\nchangeover/SM\nchanger/M\nchanging/U\nchannel/GSMD\nchannelization/M\nchannelize/DSG\nchanson/SM\nchant/ZGMDRS\nchanter/M\nchanteuse/MS\nchantey/SM\nchanticleer/MS\nchaos/M\nchaotic\nchaotically\nchap/SM\nchaparral/SM\nchapati/S\nchapatti/S\nchapbook/MS\nchapeau/SM\nchapel/MS\nchaperon/MDGS\nchaperonage/M\nchaperoned/U\nchaplain/MS\nchaplaincy/SM\nchaplet/SM\nchapped\nchapping\nchappy/S\nchapter/SM\nchar/SM\ncharabanc/MS\ncharacter/MS\ncharacterful\ncharacteristic/SM\ncharacteristically/U\ncharacterization/MS\ncharacterize/DSG\ncharacterless\ncharade/SM\ncharbroil/GDS\ncharcoal/MS\nchard/M\nchardonnay/SM\ncharge/AESDGM\nchargeable/A\ncharged/U\ncharger/SM\ncharily\nchariness/M\nchariot/SM\ncharioteer/MS\ncharisma/M\ncharismatic/MS\ncharitable/P\ncharitableness/M\ncharitably/U\ncharity/SM\ncharlady/S\ncharlatan/SM\ncharlatanism/M\ncharlatanry/M\ncharlie/S\ncharm/ZGMDRS\ncharmer/M\ncharming/Y\ncharmless\ncharred\ncharring\nchart/GMDS\ncharted/U\ncharter's\ncharter/ASGD\ncharterer/MS\nchartreuse/M\ncharwoman/M\ncharwomen\nchary/TRP\nchase/MZGDRS\nchaser/M\nchasm/MS\nchassis/M\nchaste/PYTR\nchasten/DGS\nchasteness/M\nchastise/DRSZGL\nchastisement/SM\nchastiser/M\nchastity/M\nchasuble/SM\nchat/SM\nchateau/SM\nchateaux\nchatelaine/SM\nchatline/S\nchatted\nchattel/MS\nchatter/MDRZGS\nchatterbox/MS\nchatterer/M\nchattily\nchattiness/M\nchatting\nchatty/TPR\nchauffeur/GMDS\nchauvinism/M\nchauvinist/SM\nchauvinistic\nchauvinistically\ncheap/PXTNRY\ncheapen/DG\ncheapness/M\ncheapo\ncheapskate/MS\ncheat/ZGMDRS\ncheater/M\ncheck/AGMDS\ncheckbook/SM\ncheckbox\nchecked/U\nchecker/MDGS\ncheckerboard/SM\ncheckers/M\nchecklist/MS\ncheckmate/MGDS\ncheckoff/SM\ncheckout/SM\ncheckpoint/SM\ncheckroom/MS\nchecksum\ncheckup/MS\ncheddar/M\ncheek/GMDS\ncheekbone/SM\ncheekily\ncheekiness/M\ncheeky/TPR\ncheep/GMDS\ncheer/ZGMDRS\ncheerer/M\ncheerful/YP\ncheerfuller\ncheerfullest\ncheerfulness/M\ncheerily\ncheeriness/M\ncheerio/MS\ncheerleader/SM\ncheerless/PY\ncheerlessness/M\ncheery/TPR\ncheese/MGDS\ncheeseboard/S\ncheeseburger/SM\ncheesecake/SM\ncheesecloth/M\ncheeseparing/M\ncheesiness/M\ncheesy/TPR\ncheetah/M\ncheetahs\nchef/SM\nchem\nchemical/SMY\nchemise/MS\nchemist/MS\nchemistry/M\nchemo/M\nchemotherapeutic\nchemotherapy/M\nchemurgy/M\nchenille/M\ncherish/DSG\ncheroot/MS\ncherry/SM\nchert/M\ncherub/MS\ncherubic\ncherubim\nchervil/M\nchess/M\nchessboard/MS\nchessman/M\nchessmen\nchest/MDS\nchesterfield/SM\nchestful/SM\nchestnut/SM\nchesty/TR\nchevalier/SM\ncheviot/M\nchevron/MS\nchew/SZGMDR\nchewer/M\nchewiness/M\nchewy/PTR\nchg\nchge\nchi/SM\nchiaroscuro/M\nchic/PTMR\nchicane/MS\nchicanery/SM\nchichi/MS\nchick/XMNS\nchickadee/SM\nchicken/MDG\nchickenfeed/M\nchickenhearted\nchickenpox/M\nchickenshit/S!\nchickpea/SM\nchickweed/M\nchicle/M\nchicness/M\nchicory/SM\nchide/GDS\nchiding/Y\nchief/TMRYS\nchiefdom/M\nchieftain/MS\nchieftainship/SM\nchiffon/M\nchiffonier/MS\nchigger/MS\nchignon/MS\nchihuahua/SM\nchilblain/SM\nchild/M\nchildbearing/M\nchildbirth/M\nchildbirths\nchildcare/M\nchildhood/SM\nchildish/YP\nchildishness/M\nchildless/P\nchildlessness/M\nchildlike\nchildminder/S\nchildminding\nchildproof/GSD\nchildren/M\nchili/M\nchilies\nchill/JPZTGMDRS\nchiller/M\nchilliness/M\nchilling/Y\nchillness/M\nchilly/TPR\nchime/MZGDRS\nchimer/M\nchimera/MS\nchimeric\nchimerical\nchimney/MS\nchimp/MS\nchimpanzee/SM\nchin/SM\nchina/M\nchinaware/M\nchinchilla/MS\nchine/MS\nchink/GMDS\nchinless\nchinned\nchinning\nchino/MS\nchinstrap/MS\nchintz/M\nchintzy/RT\nchinwag/S\nchip/SM\nchipboard\nchipmunk/SM\nchipolata/S\nchipped\nchipper/MS\nchippie\nchipping/S\nchippy/S\nchirography/M\nchiropodist/MS\nchiropody/M\nchiropractic/SM\nchiropractor/SM\nchirp/GMDS\nchirpily\nchirpy/PTR\nchirrup/GMDS\nchisel/ZGMDRS\nchiseler/M\nchit/SM\nchitchat/SM\nchitchatted\nchitchatting\nchitin/M\nchitinous\nchitosan\nchitterlings/M\nchivalrous/PY\nchivalrousness/M\nchivalry/M\nchive/MS\nchivy/GDS\nchlamydia/MS\nchlamydiae\nchloral/M\nchlordane/M\nchloride/MS\nchlorinate/GNDS\nchlorination/M\nchlorine/M\nchlorofluorocarbon/SM\nchloroform/SGMD\nchlorophyll/M\nchloroplast/MS\nchm\nchoc/S\nchock/GMDS\nchockablock\nchocoholic/SM\nchocolate/MS\nchocolaty\nchoice/MTRS\nchoir/MS\nchoirboy/MS\nchoirmaster/SM\nchoke/MZGDRS\nchokecherry/SM\nchoker/M\ncholecystectomy\ncholecystitis\ncholer/M\ncholera/M\ncholeric\ncholesterol/M\nchomp/ZGMDRS\nchoose/ZGRS\nchooser/M\nchoosiness/M\nchoosy/TPR\nchop/SM\nchophouse/SM\nchopped\nchopper/MDGS\nchoppily\nchoppiness/M\nchopping\nchoppy/TPR\nchopstick/SM\nchoral/MYS\nchorale/MS\nchord/MS\nchordal\nchordate/SM\nchore/MS\nchorea/M\nchoreograph/DRZG\nchoreographer/M\nchoreographic\nchoreographically\nchoreographs\nchoreography/M\nchorister/SM\nchoroid/MS\nchortle/MZGDRS\nchortler/M\nchorus/GMDS\nchose\nchosen\nchow/SGMD\nchowder/MS\nchrism/M\nchristen/ASGD\nchristening/MS\nchristian/U\nchristology\nchromatic\nchromatically\nchromatin/M\nchromatography\nchrome/MGDS\nchromium/M\nchromosomal\nchromosome/MS\nchronic\nchronically\nchronicle/DRSMZG\nchronicler/M\nchronograph/M\nchronographs\nchronological/Y\nchronologist/MS\nchronology/SM\nchronometer/SM\nchrysalis/MS\nchrysanthemum/MS\nchub/SM\nchubbiness/M\nchubby/TPR\nchuck/GMDS\nchuckhole/SM\nchuckle/MGDS\nchuffed\nchug/SM\nchugged\nchugging\nchukka/MS\nchum/SM\nchummed\nchummily\nchumminess/M\nchumming\nchummy/PTR\nchump/MS\nchunder/GDS\nchunk/GMDS\nchunkiness/M\nchunky/PTR\nchunter/DGS\nchurch/MS\nchurchgoer/SM\nchurchgoing/M\nchurchman/M\nchurchmen\nchurchwarden/MS\nchurchwoman\nchurchwomen\nchurchyard/SM\nchurl/MS\nchurlish/PY\nchurlishness/M\nchurn/ZGMDRS\nchurner/M\nchute/MS\nchutney/MS\nchutzpah/M\nchyme/M\nciabatta/SM\nciao/S\ncicada/MS\ncicatrices\ncicatrix/M\ncicerone/SM\nciceroni\ncider's\ncider/S\ncigar/MS\ncigarette/MS\ncigarillo/MS\ncilantro/M\ncilia\ncilium/M\ncinch/GMDS\ncinchona/SM\ncincture/SM\ncinder/GMDS\ncine\ncinema/MS\ncinematic\ncinematographer/MS\ncinematographic\ncinematography/M\ncinnabar/M\ncinnamon/M\ncipher's\ncipher/CGDS\ncir\ncirca\ncircadian\ncircle/MGDS\ncirclet/MS\ncircuit/MDGS\ncircuital\ncircuitous/YP\ncircuitousness/M\ncircuitry/M\ncircuity/M\ncircular/SMY\ncircularity/M\ncircularize/DSG\ncirculate/ADSG\ncirculation/SM\ncirculatory\ncircumcise/XDSGN\ncircumcised/U\ncircumcision/M\ncircumference/MS\ncircumferential\ncircumflex/MS\ncircumlocution/MS\ncircumlocutory\ncircumnavigate/XGNDS\ncircumnavigation/M\ncircumpolar\ncircumscribe/GDS\ncircumscription/MS\ncircumspect/Y\ncircumspection/M\ncircumstance/MGDS\ncircumstantial/Y\ncircumvent/DSG\ncircumvention/M\ncircus/MS\ncirque/MS\ncirrhosis/M\ncirrhotic/SM\ncirri\ncirrus/M\ncistern/MS\ncit\ncitadel/MS\ncitation/AMS\ncite's\ncite/IAGSD\ncitified\ncitizen/MS\ncitizenry/M\ncitizenship/M\ncitric\ncitron/MS\ncitronella/M\ncitrus/MS\ncity/SM\ncitywide\ncivet/MS\ncivic/S\ncivics/M\ncivil/UY\ncivilian/MS\ncivility/ISM\ncivilization/MS\ncivilize/GDS\ncivilized/U\ncivvies/M\nck\ncl\nclack/GMDS\nclad/U\ncladding/M\nclaim's\nclaim/CKEAGDS\nclaimable/A\nclaimant/MS\nclaimed/U\nclaimer/ECSM\nclairvoyance/M\nclairvoyant/MS\nclam/SM\nclambake/MS\nclamber/ZGMDRS\nclamberer/M\nclammed\nclammily\nclamminess/M\nclamming\nclammy/PTR\nclamor/GMDS\nclamorous\nclamp/GMDS\nclampdown/MS\nclan/SM\nclandestine/Y\nclang/ZGMDRS\nclangor/M\nclangorous/Y\nclank/GMDS\nclannish/P\nclannishness/M\nclansman/M\nclansmen\nclanswoman\nclanswomen\nclap/SM\nclapboard/MDGS\nclapped\nclapper/MS\nclapperboard/S\nclapping/M\nclaptrap/M\nclaque/MS\nclaret/MS\nclarification/M\nclarify/XDSNG\nclarinet/SM\nclarinetist/SM\nclarion/MDGS\nclarity/M\nclash/GMDS\nclasp's\nclasp/UGDS\nclass/GMDS\nclassic/MS\nclassical/MY\nclassicism/M\nclassicist/MS\nclassifiable\nclassification/CAM\nclassifications\nclassified's\nclassified/U\nclassifieds\nclassifier/MS\nclassify/ACSDGN\nclassiness/M\nclassless/P\nclassmate/MS\nclassroom/MS\nclasswork/M\nclassy/TRP\nclatter/GMDS\nclausal\nclause/MS\nclaustrophobia/M\nclaustrophobic\nclavichord/SM\nclavicle/MS\nclavier/MS\nclaw's\nclaw/CSGD\nclay/M\nclayey\nclayier\nclayiest\nclean/BJPZTGDRYS\ncleaner/M\ncleaning/M\ncleanliness/UM\ncleanly/UTPR\ncleanness/UM\ncleanse/ZGDRS\ncleanser/M\ncleanup/MS\nclear/JPTGMDRYS\nclearance/SM\nclearheaded\nclearing/M\nclearinghouse/SM\nclearness/M\nclearway/S\ncleat/MS\ncleavage/MS\ncleave/ZGDRS\ncleaver/M\nclef/SM\ncleft/MS\nclematis/MS\nclemency/IM\nclement/Y\nclementine/S\nclench/GMDS\nclerestory/SM\nclergy/SM\nclergyman/M\nclergymen\nclergywoman/M\nclergywomen\ncleric/MS\nclerical/Y\nclericalism/M\nclerk/GMDS\nclerkship/M\nclever/PTRY\ncleverness/M\nclevis/MS\nclew/SGMD\ncliche/MDS\nclick/BZGMDRS\nclicker/M\nclient/MS\nclientele/MS\ncliff/MS\ncliffhanger/SM\ncliffhanging\nclifftop/S\nclii\nclimacteric/M\nclimactic\nclimate/SM\nclimatic\nclimatically\nclimatologist/SM\nclimatology/M\nclimax/MDSG\nclimb/SMDRZGB\nclimber/M\nclimbing/M\nclime/SM\nclinch/MDRSZG\nclincher/M\ncling/SMRZG\nclinger/M\nclingfilm\nclingy/RT\nclinic/SM\nclinical/Y\nclinician/SM\nclink/SMDRZG\nclinker/M\ncliometric/S\ncliometrician/MS\ncliometrics/M\nclip/SM\nclipboard/MS\nclipped\nclipper/SM\nclipping/SM\nclique/SM\ncliquey\ncliquish/YP\ncliquishness/M\nclit/SM\nclitoral\nclitorides\nclitoris/MS\nclix\ncloaca/M\ncloacae\ncloak's\ncloak/USDG\ncloakroom/MS\nclobber/SMDG\ncloche/SM\nclock/SMDG\nclockwise\nclockwork/SM\nclod/MS\ncloddish\nclodhopper/MS\nclog's\nclog/US\nclogged/U\nclogging/U\ncloisonne/M\ncloister/SMDG\ncloistral\nclomp/SDG\nclonal\nclone/DSMG\nclonk/SMDG\nclop/MS\nclopped\nclopping\nclose/DRSMYTGJP\nclosefisted\nclosemouthed\ncloseness/M\ncloseout/MS\ncloset/SMDG\ncloseup/SM\nclosing/M\nclosure/ESM\nclot/MS\ncloth/M\nclothe/UDSG\nclotheshorse/MS\nclothesline/SM\nclothespin/SM\nclothier/MS\nclothing/M\ncloths\nclotted\nclotting\ncloture/SM\ncloud/SMDG\ncloudburst/SM\nclouded/U\ncloudiness/M\ncloudless\ncloudy/RPT\nclout/SMDG\nclove/RSMZ\ncloven\nclover/M\ncloverleaf/SM\ncloverleaves\nclown/SMDG\nclownish/YP\nclownishness/M\ncloy/DGS\ncloying/Y\nclub/MS\nclubbable\nclubbed\nclubber/S\nclubbing\nclubfeet\nclubfoot/MD\nclubhouse/SM\nclubland\ncluck/SMDG\nclue/MGDS\nclueless\nclump/SMDG\nclumpy/TR\nclumsily\nclumsiness/M\nclumsy/TRP\nclung\nclunk/SMDRZG\nclunker/M\nclunky/TR\ncluster/MDSG\nclutch/GMDS\nclutter/MDSG\ncluttered/U\nclvi\nclvii\nclxi\nclxii\nclxiv\nclxix\nclxvi\nclxvii\ncm\ncnidarian/MS\nco/ESD\ncoach/MDSG\ncoachload/S\ncoachman/M\ncoachmen\ncoachwork\ncoadjutor/MS\ncoagulant/MS\ncoagulate/GNDS\ncoagulation/M\ncoagulator/MS\ncoal/MDGS\ncoalesce/GDS\ncoalescence/M\ncoalescent\ncoalface/MS\ncoalfield/S\ncoalition/MS\ncoalitionist/MS\ncoalmine/S\ncoarse/RYTP\ncoarsen/SDG\ncoarseness/M\ncoast/SMDRZG\ncoastal\ncoaster/M\ncoastguard/S\ncoastline/MS\ncoat/MDGJS\ncoating/M\ncoatroom/S\ncoattail/SM\ncoauthor/MDGS\ncoax/DRSZG\ncoaxer/M\ncoaxial\ncoaxing/Y\ncob/SM\ncobalt/M\ncobber/S\ncobble/DRSMZG\ncobbler/M\ncobblestone/SM\ncobnut/S\ncobra/SM\ncobweb/SM\ncobwebbed\ncobwebby/RT\ncoca/M\ncocaine/M\ncocci/S\ncoccus/M\ncoccyges\ncoccyx/M\ncochineal/M\ncochlea/SM\ncochleae\ncochlear\ncock/MDGS\ncockade/SM\ncockamamie\ncockatoo/SM\ncockatrice/SM\ncockchafer/S\ncockcrow/SM\ncockerel/SM\ncockeyed\ncockfight/MGS\ncockfighting/M\ncockily\ncockiness/M\ncockle/SM\ncockleshell/SM\ncockney/SM\ncockpit/SM\ncockroach/MS\ncockscomb/SM\ncocksucker/MS!\ncocksure\ncocktail/MS\ncocky/RTP\ncoco/MS\ncocoa/SM\ncoconut/SM\ncocoon/SMDG\ncod/SM\ncoda/MS\ncodded\ncodding\ncoddle/DSG\ncode's\ncode/CZGDRS\ncodeine/M\ncodependency/M\ncodependent/SM\ncoder/CM\ncodex/M\ncodfish/MS\ncodger/SM\ncodices\ncodicil/SM\ncodification/M\ncodifier/M\ncodify/XDRSNZG\ncodon/S\ncodpiece/MS\ncodswallop\ncoed/MS\ncoeducation/M\ncoeducational\ncoefficient/MS\ncoelenterate/MS\ncoequal/MYS\ncoerce/DRSZGNV\ncoercer/M\ncoercion/M\ncoeval/SMY\ncoexist/DSG\ncoexistence/M\ncoexistent\ncoextensive\ncoffee/SM\ncoffeecake/SM\ncoffeehouse/MS\ncoffeemaker/SM\ncoffeepot/MS\ncoffer/SM\ncofferdam/MS\ncoffin/SMDG\ncog/SM\ncogency/M\ncogent/Y\ncogitate/DSXGNV\ncogitation/M\ncogitator/MS\ncognac/SM\ncognate/MS\ncognition/AM\ncognitional\ncognitive/Y\ncognizable\ncognizance/AM\ncognizant\ncognomen/SM\ncognoscente/M\ncognoscenti\ncogwheel/SM\ncohabit/SGD\ncohabitant/MS\ncohabitation/M\ncoheir/SM\ncohere/DSG\ncoherence/IM\ncoherency/M\ncoherent/IY\ncohesion/M\ncohesive/YP\ncohesiveness/M\ncoho/MS\ncohort/SM\ncoif/MS\ncoiffed\ncoiffing\ncoiffure/DSMG\ncoil's/A\ncoil/UADGS\ncoin/MDRZGS\ncoinage/SM\ncoincide/DSG\ncoincidence/MS\ncoincident\ncoincidental/Y\ncoiner/M\ncoinsurance/M\ncoir\ncoital\ncoitus/M\ncoke/MGDS\ncol/S\ncola/MS\ncolander/SM\ncold/MRYTPS\ncoldblooded\ncoldness/M\ncoleslaw/M\ncoleus/MS\ncoley/S\ncolic/M\ncolicky\ncoliseum/MS\ncolitis/M\ncoll\ncollaborate/DSXGNV\ncollaboration/M\ncollaborationist\ncollaborative/Y\ncollaborator/MS\ncollage/SM\ncollagen\ncollapse/MGDS\ncollapsible\ncollar/SMDG\ncollarbone/SM\ncollard/SM\ncollarless\ncollate/DSXGN\ncollateral/MY\ncollateralize\ncollation/M\ncollator/MS\ncolleague/MS\ncollect's\ncollect/ASGVD\ncollected/U\ncollectedly\ncollectible/SM\ncollection/AMS\ncollective/MYS\ncollectivism/M\ncollectivist/SM\ncollectivization/M\ncollectivize/DSG\ncollector/MS\ncolleen/SM\ncollege/SM\ncollegiality/M\ncollegian/MS\ncollegiate\ncollide/DSG\ncollie/RSMZ\ncollier/M\ncolliery/SM\ncollision/SM\ncollocate/MGNDSX\ncollocation/M\ncolloid/SM\ncolloidal\ncolloq\ncolloquial/Y\ncolloquialism/SM\ncolloquies\ncolloquium/MS\ncolloquy/M\ncollude/DSG\ncollusion/M\ncollusive\ncologne/SM\ncolon/SM\ncolonel/SM\ncolonelcy/M\ncolones\ncolonial/SMY\ncolonialism/M\ncolonialist/MS\ncolonist/SM\ncolonization/ACM\ncolonize/CAGSD\ncolonizer/MS\ncolonnade/MDS\ncolonoscopy/SM\ncolony/SM\ncolophon/SM\ncolor's\ncolor/AEGDS\ncolorant/SM\ncoloration/EM\ncoloratura/MS\ncolorblind/P\ncolorblindness/M\ncolored's\ncolored/U\ncoloreds\ncolorfast/P\ncolorfastness/M\ncolorful/PY\ncolorfulness/M\ncoloring's\ncolorist/S\ncolorization/M\ncolorize/DSG\ncolorless/PY\ncolorlessness/M\ncolorway/S\ncolossal/Y\ncolossi\ncolossus/M\ncolostomy/SM\ncolostrum/M\ncolt/MS\ncoltish\ncolumbine/SM\ncolumn/SMD\ncolumnar\ncolumnist/SM\ncom/JL\ncoma/MS\ncomaker/SM\ncomatose\ncomb/MDRZGJS\ncombat/SMDGV\ncombatant/SM\ncombativeness/M\ncombed/U\ncomber/M\ncombination/SM\ncombine's\ncombine/ADSG\ncombined/U\ncombiner/MS\ncombings/M\ncombo/SM\ncombustibility/M\ncombustible/MS\ncombustion/M\ncombustive\ncome/IMZGRS\ncomeback/MS\ncomedian/MS\ncomedic\ncomedienne/MS\ncomedown/MS\ncomedy/SM\ncomeliness/M\ncomely/RPT\ncomer's\ncomestible/SM\ncomet/SM\ncomeuppance/SM\ncomfit's\ncomfit/ES\ncomfort/ESMDG\ncomfortable/P\ncomfortableness/M\ncomfortably/U\ncomforter/MS\ncomforting/Y\ncomfortless\ncomfy/RT\ncomic/SM\ncomical/Y\ncomicality/M\ncoming/M\ncomity/M\ncomm\ncomma/SM\ncommand/SMDRLZG\ncommandant/MS\ncommandeer/GDS\ncommander/M\ncommandment/MS\ncommando/SM\ncommemorate/XGNVDS\ncommemoration/M\ncommemorator/MS\ncommence/ADSLG\ncommencement/AM\ncommencements\ncommend/ASDBG\ncommendably\ncommendation/AMS\ncommendatory\ncommensurable\ncommensurate/IY\ncomment/GSMD\ncommentary/SM\ncommentate/DSG\ncommentator/SM\ncommerce/M\ncommercial/SMY\ncommercialism/M\ncommercialization/M\ncommercialize/GDS\ncommie/SM\ncommingle/DSG\ncommiserate/GNVDSX\ncommiseration/M\ncommissar/SM\ncommissariat/SM\ncommissary/SM\ncommission's\ncommission/ACSGD\ncommissionaire/S\ncommissioner/SM\ncommit/AS\ncommitment/MS\ncommittal/SM\ncommitted/AU\ncommittee/SM\ncommitteeman/M\ncommitteemen\ncommitteewoman/M\ncommitteewomen\ncommitter/S\ncommitting/A\ncommode's\ncommode/EIS\ncommodification\ncommodious/Y\ncommodity/SM\ncommodore/SM\ncommon's\ncommon/UPRYT\ncommonality/S\ncommonalty/M\ncommoner/MS\ncommonness/UM\ncommonplace/MS\ncommons\ncommonsense\ncommonweal/MH\ncommonwealth/M\ncommonwealths\ncommotion/SM\ncommunal/Y\ncommune/XDSMGN\ncommunicability/M\ncommunicable/I\ncommunicably\ncommunicant/MS\ncommunicate/GNVDSX\ncommunication/M\ncommunicative/U\ncommunicator/SM\ncommunion/M\ncommunique/SM\ncommunism/M\ncommunist/SM\ncommunistic\ncommunity/SM\ncommutation/MS\ncommutative\ncommutator/SM\ncommute/BDRSMZG\ncommuter/M\ncomp/MDYGS\ncompact/TGSMDRYP\ncompaction\ncompactness/M\ncompactor/SM\ncompanion/SBM\ncompanionably\ncompanionship/M\ncompanionway/MS\ncompany/SM\ncomparability/M\ncomparable/I\ncomparably/I\ncomparative/MYS\ncompare/BDSMG\ncomparison/MS\ncompartment/SM\ncompartmental\ncompartmentalization/M\ncompartmentalize/DSG\ncompass/GMDS\ncompassion/M\ncompassionate/Y\ncompatibility/IM\ncompatible/IMS\ncompatibly/I\ncompatriot/MS\ncompeer/SM\ncompel/S\ncompelled\ncompelling/Y\ncompendious\ncompendium/SM\ncompensate/DSXGN\ncompensated/U\ncompensation/M\ncompensatory\ncompere/DSG\ncompete/DSG\ncompetence/IM\ncompetences\ncompetencies\ncompetency/IM\ncompetent/IY\ncompetition/SM\ncompetitive/PY\ncompetitiveness/M\ncompetitor/SM\ncompilation/SM\ncompile/DRSZG\ncompiler/M\ncomplacence/M\ncomplacency/M\ncomplacent/Y\ncomplain/DRZGS\ncomplainant/MS\ncomplainer/M\ncomplaint/SM\ncomplaisance/M\ncomplaisant/Y\ncomplected\ncomplement/SGMD\ncomplementary\ncomplete/PYTGNXDRS\ncompleted/U\ncompleteness/IM\ncompletion/M\ncomplex/MSY\ncomplexion/MDS\ncomplexional\ncomplexity/SM\ncompliance/M\ncompliant/Y\ncomplicate/GDS\ncomplicated/Y\ncomplication/M\ncomplicit\ncomplicity/M\ncompliment/MDGS\ncomplimentary/U\ncomply/NDSXG\ncompo/S\ncomponent/SM\ncomport/LSGD\ncomportment/M\ncompose/AECGSD\ncomposedly\ncomposer/MS\ncomposite/MYGNXDS\ncomposition/CM\ncompositor/SM\ncompost/SGMD\ncomposure/EM\ncompote/SM\ncompound/GMDBS\ncompounded/U\ncomprehend/SDG\ncomprehensibility/IM\ncomprehensible/I\ncomprehensibly/I\ncomprehension/IM\ncomprehensions\ncomprehensive/PMYS\ncomprehensiveness/M\ncompress's\ncompress/CGDS\ncompressed/U\ncompressible\ncompression/CM\ncompressor/SM\ncomprise/GDS\ncompromise/MGDS\ncomptroller/MS\ncompulsion/MS\ncompulsive/YP\ncompulsiveness/M\ncompulsorily\ncompulsory/SM\ncompunction/SM\ncomputation/SM\ncomputational/Y\ncompute/ADSG\ncomputer/MS\ncomputerate\ncomputerization/M\ncomputerize/GDS\ncomputing/M\ncomrade/SMY\ncomradeship/M\ncon/GSM\nconcatenate/XDSGN\nconcatenation/M\nconcave/YP\nconcaveness/M\nconceal/SDRZGBL\nconcealed/U\nconcealer/M\nconcealment/M\nconceit/SMD\nconceited/PY\nconceitedness/M\nconceivable/I\nconceivably/I\nconceive/DSGB\nconcentrate/DSMGNX\nconcentration/M\nconcentric\nconcentrically\nconcept/SM\nconception/SM\nconceptional\nconceptual/Y\nconceptualization/MS\nconceptualize/DSG\nconcern/UMD\nconcerned/UY\nconcerning\nconcerns\nconcert's\nconcert/ESDG\nconcerted/Y\nconcertgoer/S\nconcertina/SGMD\nconcertize/DSG\nconcertmaster/MS\nconcerto/SM\nconcessionaire/MS\nconcessional\nconcessionary\nconch/M\nconchie/S\nconchs\nconcierge/MS\nconciliate/DSGN\nconciliation/AM\nconciliator/SM\nconciliatory\nconcise/RPYTN\nconciseness/M\nconcision/M\nconclave/SM\nconclude/DSG\nconclusion/MS\nconclusive/IYP\nconclusiveness/IM\nconcoct/SDG\nconcoction/MS\nconcomitant/MYS\nconcord/M\nconcordance/SM\nconcordant\nconcordat/SM\nconcourse/SM\nconcrete/DSPMYGNX\nconcreteness/M\nconcretion/M\nconcubinage/M\nconcubine/MS\nconcupiscence/M\nconcupiscent\nconcur/S\nconcurred\nconcurrence/SM\nconcurrency\nconcurring\nconcuss/V\nconcussion/SM\ncondemn/SDRZG\ncondemnation/MS\ncondemnatory\ncondemner/M\ncondensate/MNXS\ncondensation/M\ncondense/DRSZG\ncondenser/M\ncondescending/Y\ncondescension/M\ncondign\ncondiment/MS\ncondition's\ncondition/AGSD\nconditional/SMY\nconditioned/U\nconditioner/SM\nconditioning/M\ncondo/SM\ncondolence/SM\ncondom/SM\ncondominium/MS\ncondone/DSG\ncondor/SM\nconduce/DSGV\nconduct/MDGV\nconductance/M\nconductibility/M\nconductible\nconduction/M\nconductivity/M\nconductor/MS\nconductress/MS\nconduit/SM\ncone/M\nconeys\nconfab/SM\nconfabbed\nconfabbing\nconfabulate/XDSGN\nconfabulation/M\nconfection/SZMR\nconfectioner/M\nconfectionery/SM\nconfederacy/SM\nconfederate/M\nconfer/S\nconferee/SM\nconference/MGS\nconferrable\nconferral/M\nconferred\nconferrer/MS\nconferring\nconfessed/Y\nconfession/SM\nconfessional/SM\nconfessor/MS\nconfetti/M\nconfidant/MS\nconfidante/SM\nconfide/DRSZG\nconfidence/SM\nconfident/Y\nconfidential/Y\nconfidentiality/M\nconfider/M\nconfiding/Y\nconfiguration/S\nconfigure/B\nconfined/U\nconfinement/MS\nconfirm/ASDG\nconfirmation/ASM\nconfirmatory\nconfirmed/U\nconfiscate/DSGNX\nconfiscation/M\nconfiscator/SM\nconfiscatory\nconflagration/MS\nconflate/XDSGN\nconflation/M\nconflict/SGMD\nconfluence/MS\nconfluent\nconform/ZB\nconformable/U\nconformance/M\nconformism/M\nconformist/SM\nconformity/M\nconfrere/MS\nconfrontation/SM\nconfrontational\nconfuse/RZ\nconfused/Y\nconfusing/Y\nconfutation/M\nconfute/DSG\nconga/SMDG\ncongeal/SLDG\ncongealment/M\nconger/SM\ncongeries/M\ncongest/SDGV\ncongestion/M\nconglomerate/DSXMGN\nconglomeration/M\ncongrats/M\ncongratulate/XGNDS\ncongratulation/M\ncongratulatory\ncongregant/MS\ncongregate/GNDSX\ncongregation/M\ncongregational\ncongregationalism/M\ncongregationalist/MS\ncongress/MS\ncongressional\ncongressman/M\ncongressmen\ncongresspeople\ncongressperson/MS\ncongresswoman/M\ncongresswomen\ncongruence/M\ncongruent/Y\ncongruity/ISM\ncongruous\nconic/SM\nconical/Y\nconifer/SM\nconiferous\nconjectural\nconjecture/MGDS\nconjoint\nconjugal/Y\nconjugate/DSXGN\nconjugation/M\nconjunct/VMS\nconjunctiva/SM\nconjunctive/SM\nconjunctivitis/M\nconjuration/MS\nconjure/DRSZG\nconjurer/M\nconk/MDRZ\nconman\nconnect/AEDVGS\nconnectable\nconnected/U\nconnection/EMS\nconnective/MS\nconnectivity/M\nconnector/MS\nconned\nconning\nconniption/MS\nconnivance/M\nconnive/DRSZG\nconniver/M\nconnoisseur/SM\nconnotative\nconnubial\nconquer/ASDG\nconquerable/U\nconquered/U\nconqueror/MS\nconquest/AM\nconquistador/SM\ncons/DSG\nconsanguineous\nconsanguinity/M\nconscienceless\nconscientious/PY\nconscientiousness/M\nconscious/UYP\nconsciousness/UM\nconsciousnesses\nconscription/M\nconsecrate/ADSGN\nconsecrated/U\nconsecration/AM\nconsecrations\nconsecutive/Y\nconsensual\nconsensus/MS\nconsent/SMDG\nconsequence/SM\nconsequent/Y\nconsequential/IY\nconservancy/SM\nconservation/M\nconservationism/M\nconservationist/SM\nconservatism/M\nconservative/MYS\nconservatoire/S\nconservator/SM\nconservatory/SM\nconsider/AGSD\nconsiderable/I\nconsiderably\nconsiderate/IPYN\nconsiderateness/IM\nconsideration/AIM\nconsiderations\nconsidered/U\nconsign/ASDG\nconsignee/MS\nconsignment/MS\nconsist/SDG\nconsistence/MS\nconsistency/ISM\nconsistent/IY\nconsistory/SM\nconsolable/I\nconsolation/MS\nconsolatory\nconsolidate/XDSGN\nconsolidated/U\nconsolidation/M\nconsolidator/MS\nconsoling/Y\nconsomme/M\nconsonance/SM\nconsonant/SMY\nconsortia\nconsortium/M\nconspectus/MS\nconspicuous/IPY\nconspicuousness/IM\nconspiracy/SM\nconspirator/MS\nconspiratorial/Y\nconspire/GD\nconstable/SM\nconstabulary/SM\nconstancy/IM\nconstant/MYS\nconstellation/SM\nconsternation/M\nconstipate/GNDS\nconstipation/M\nconstituency/SM\nconstituent/SM\nconstitute/ADSGNV\nconstitution/AM\nconstitutional/MYS\nconstitutionalism\nconstitutionality/UM\nconstitutions\nconstrained/U\nconstraint/SM\nconstrict/GVSD\nconstriction/SM\nconstrictor/SM\nconstruable\nconstruct's\nconstruct/CADVGS\nconstruction/CAMS\nconstructional\nconstructionist's\nconstructionist/CS\nconstructive/YP\nconstructiveness/M\nconstructor/MS\nconstrue/GDS\nconsul/KSM\nconsular/K\nconsulate/SM\nconsulship/M\nconsult/GSD\nconsultancy/SM\nconsultant/MS\nconsultation/MS\nconsultative\nconsumable/SM\nconsume/BDRSZG\nconsumed/U\nconsumer/M\nconsumerism/M\nconsumerist/MS\nconsummate/YGNXDS\nconsummated/U\nconsumption/M\nconsumptive/SM\ncont\ncontact/ASDG\ncontactable\ncontagion/MS\ncontagious/PY\ncontagiousness/M\ncontain/SBLDRZG\ncontainer/M\ncontainerization/M\ncontainerize/DSG\ncontainment/M\ncontaminant/SM\ncontaminate/ACDSG\ncontaminated/U\ncontamination/CM\ncontaminator/SM\ncontd\ncontemn/SDG\ncontemplate/DSGNV\ncontemplation/M\ncontemplative/SMY\ncontemporaneity/M\ncontemporaneous/Y\ncontempt/M\ncontemptible\ncontemptibly\ncontemptuous/YP\ncontemptuousness/M\ncontender/MS\ncontent/ESLMDG\ncontented/EY\ncontentedness/M\ncontention/SM\ncontentious/YP\ncontentiousness/M\ncontently\ncontentment/EM\nconterminous/Y\ncontestable/I\ncontestant/MS\ncontested/U\ncontextualization\ncontextualize/DSG\ncontiguity/M\ncontiguous/Y\ncontinence/IM\ncontinent/SM\ncontinental/SM\ncontingency/SM\ncontingent/SMY\ncontinua\ncontinual/Y\ncontinuance/EMS\ncontinuation/EMS\ncontinue/EGDS\ncontinuity/ESM\ncontinuous/EY\ncontinuum/M\ncontort/GD\ncontortion/MS\ncontortionist/SM\ncontraband/M\ncontrabassoon/S\ncontraception/M\ncontraceptive/SM\ncontract/MDG\ncontractible\ncontractile\ncontraction/S\ncontractual/Y\ncontradict/SDG\ncontradiction/SM\ncontradictory\ncontradistinction/MS\ncontraflow/S\ncontrail/MS\ncontraindicate/GNXDS\ncontraindication/M\ncontralto/SM\ncontraption/SM\ncontrapuntal/Y\ncontrarian/SM\ncontrarianism\ncontrariety/M\ncontrarily\ncontrariness/M\ncontrariwise\ncontrary/PSM\ncontrast/MDGS\ncontravene/GDS\ncontravention/SM\ncontretemps/M\ncontribute/XGND\ncontribution/M\ncontributor/MS\ncontributory\ncontrition/M\ncontrivance/MS\ncontrive/ZGDRS\ncontriver/M\ncontrol's\ncontrol/CS\ncontrollable/U\ncontrolled/UC\ncontroller/MS\ncontrolling/C\ncontroversial/Y\ncontroversy/SM\ncontrovert/DSG\ncontrovertible/I\ncontumacious/Y\ncontumacy/M\ncontumelious\ncontumely/SM\ncontuse/XDSGN\ncontusion/M\nconundrum/SM\nconurbation/MS\nconvalesce/DSG\nconvalescence/MS\nconvalescent/SM\nconvection/M\nconvectional\nconvective\nconvector/S\nconvene/ADSG\nconvener/MS\nconvenience/IMS\nconvenient/IY\nconvent/SM\nconventicle/MS\nconvention/SM\nconventional/UY\nconventionality/UM\nconventionalize/GDS\nconventioneer/S\nconvergence/MS\nconvergent\nconversant\nconversation/MS\nconversational/Y\nconversationalist/SM\nconverse/Y\nconvert's\nconvert/AGSD\nconverted/U\nconverter/SM\nconvertibility/M\nconvertible/SM\nconvex/Y\nconvexity/M\nconvey/SBDG\nconveyance/MGS\nconveyor/MS\nconvict/GSMD\nconviction/MS\nconvince/GDS\nconvinced/U\nconvincing/UY\nconvivial/Y\nconviviality/M\nconvoke/DSG\nconvoluted\nconvolution/MS\nconvoy/SMDG\nconvulse/GNVXDS\nconvulsion/M\nconvulsive/Y\ncony/M\ncoo/GSMD\ncook's\ncook/ADGS\ncookbook/MS\ncooked/U\ncooker/SM\ncookery/SM\ncookhouse/S\ncookie/SM\ncooking/M\ncookout/SM\ncookware/SM\ncool/MDRYZTGPS\ncoolant/SM\ncooler/M\ncoolie/SM\ncoolness/M\ncoon/MS!\ncoonskin/MS\ncoop/MDRZGS\ncooper/MDG\ncooperage/M\ncooperate/DSGNV\ncooperation/M\ncooperative/PMYS\ncooperativeness/M\ncooperator/SM\ncoordinate/DSMYGN\ncoordinated/U\ncoordination/M\ncoordinator/MS\ncoot/MS\ncootie/SM\ncop/GJSMD\ncopacetic\ncopay/M\ncope/MS\ncopier/SM\ncopilot/SM\ncoping/M\ncopious/PY\ncopiousness/M\ncopped\ncopper/SM\ncopperhead/SM\ncopperplate/M\ncoppery\ncopping\ncopra/M\ncopse/SM\ncopter/SM\ncopula/SM\ncopulate/GNVDS\ncopulation/M\ncopulative/SM\ncopy's\ncopy/ADSG\ncopybook/SM\ncopycat/MS\ncopycatted\ncopycatting\ncopyist/MS\ncopyleft\ncopyright/GSMD\ncopywriter/MS\ncoquetry/SM\ncoquette/DSMG\ncoquettish/Y\ncor\ncoracle/SM\ncoral/SM\ncorbel/SM\ncord/EASGDM\ncordage/M\ncordial/SMY\ncordiality/M\ncordillera/MS\ncordite/M\ncordless\ncordon/SMDG\ncordovan/M\ncorduroy/MS\ncorduroys/M\ncore/MZGDRS\ncoreligionist/S\ncorer/M\ncorespondent/MS\ncorgi/SM\ncoriander/M\ncork's\ncork/UDGS\ncorkage\ncorker/SM\ncorkscrew/SMDG\ncorm/MS\ncormorant/SM\ncorn/MDRZGS\ncornball/MS\ncornbread/M\ncorncob/MS\ncorncrake/S\ncornea/SM\ncorneal\ncorner/GMD\ncornerstone/SM\ncornet/SM\ncornfield/S\ncornflakes/M\ncornflour\ncornflower/SM\ncornice/MS\ncornily\ncorniness/M\ncornmeal/M\ncornrow/MDGS\ncornstalk/SM\ncornstarch/M\ncornucopia/MS\ncorny/PRT\ncorolla/MS\ncorollary/SM\ncorona/SM\ncoronal/MS\ncoronary/SM\ncoronation/SM\ncoroner/MS\ncoronet/MS\ncorp\ncorpora\ncorporal/SM\ncorporate/XYN\ncorporation/IM\ncorporatism\ncorporeal/Y\ncorporeality/M\ncorps/MS\ncorpse/M\ncorpsman/M\ncorpsmen\ncorpulence/M\ncorpulent\ncorpus/M\ncorpuscle/MS\ncorpuscular\ncorr\ncorral/SM\ncorralled\ncorralling\ncorrect/DRYTGVSBP\ncorrected/U\ncorrection/SM\ncorrectional\ncorrective/SM\ncorrectness/IM\ncorrector\ncorrelate/XDSMGNV\ncorrelated/U\ncorrelation/M\ncorrelative/MS\ncorrespond/SDG\ncorrespondence/SM\ncorrespondent/SM\ncorresponding/Y\ncorridor/SM\ncorrie/S\ncorroborate/GNVDSX\ncorroborated/U\ncorroboration/M\ncorroborator/SM\ncorroboratory\ncorrode/GDS\ncorrosion/M\ncorrosive/SMY\ncorrugate/GNXDS\ncorrugation/M\ncorrupt/DRYPSTG\ncorruptibility/IM\ncorruptible/I\ncorruption/MS\ncorruptness/M\ncorsage/MS\ncorsair/MS\ncorset/SGMD\ncortege/MS\ncortex/M\ncortical\ncortices\ncortisone/M\ncorundum/M\ncoruscate/GNDS\ncoruscation/M\ncorvette/SM\ncos/M\ncosh/DSG\ncosign/ZGSDR\ncosignatory/SM\ncosigner/M\ncosine/SM\ncosmetic/SM\ncosmetically\ncosmetician/MS\ncosmetologist/MS\ncosmetology/M\ncosmic\ncosmically\ncosmogonist/SM\ncosmogony/SM\ncosmological\ncosmologist/SM\ncosmology/SM\ncosmonaut/SM\ncosmopolitan/MS\ncosmopolitanism/M\ncosmos/MS\ncosplay\ncosponsor/GSMD\ncosset/SGD\ncossetted\ncossetting\ncost/MDYGSJ\ncostar/SM\ncostarred\ncostarring\ncostliness/M\ncostly/PTR\ncostume/MZGDRS\ncostumer/M\ncostumier/S\ncot/SM\ncotangent/MS\ncote/MS\ncoterie/MS\ncoterminous\ncotillion/SM\ncottage/MZGRS\ncottager/M\ncottar/SM\ncotter/SM\ncotton/SGMD\ncottonmouth/M\ncottonmouths\ncottonseed/MS\ncottontail/MS\ncottonwood/SM\ncottony\ncotyledon/MS\ncouch/MDSG\ncouchette/S\ncougar/SM\ncough/MDG\ncoughs\ncould\ncould've\ncouldn't\ncoulee/SM\ncoulis\ncoulomb/MS\ncouncil/MS\ncouncilman/M\ncouncilmen\ncouncilor/MS\ncouncilperson/SM\ncouncilwoman/M\ncouncilwomen\ncounsel/JMDGS\ncounselor/MS\ncount/EASMDG\ncountable/U\ncountably\ncountdown/MS\ncounted/U\ncountenance's\ncountenance/EGDS\ncounter/EMS\ncounteract/SGVD\ncounteraction/MS\ncounterargument/S\ncounterattack/GMDS\ncounterbalance/MGDS\ncounterblast/S\ncounterclaim/GSMD\ncounterclockwise\ncounterculture/SM\ncountered\ncounterespionage/M\ncounterexample/S\ncounterfactual\ncounterfeit/ZGMDRS\ncounterfeiter/M\ncounterfoil/MS\ncountering\ncounterinsurgency/SM\ncounterintelligence/M\ncounterman/M\ncountermand/GMDS\ncountermeasure/SM\ncountermen\ncounteroffensive/SM\ncounteroffer/SM\ncounterpane/SM\ncounterpart/SM\ncounterpetition\ncounterpoint/MDGS\ncounterpoise/MGDS\ncounterproductive\ncounterrevolution/SM\ncounterrevolutionary/SM\ncountersign/GSMD\ncountersignature/MS\ncountersink/GSM\ncounterspy/SM\ncountersunk\ncountertenor/MS\ncountervail/GSD\ncounterweight/MS\ncountess/MS\ncountless\ncountrified\ncountry/SM\ncountryman/M\ncountrymen\ncountryside/MS\ncountrywide\ncountrywoman/M\ncountrywomen\ncounty/SM\ncountywide\ncoup's\ncoup/AS\ncoupe/SM\ncouple's\ncouple/UCGSD\ncouplet/MS\ncoupling/SM\ncoupon/SM\ncourage/M\ncourageous/YP\ncourageousness/M\ncourgette/S\ncourier/MDSG\ncourse/EDGMS\ncoursebook/S\ncourser/MS\ncoursework\ncourt/SMDYG\ncourteous/EY\ncourteousness/M\ncourtesan/SM\ncourtesy/ESM\ncourthouse/MS\ncourtier/SM\ncourtliness/M\ncourtly/PRT\ncourtroom/MS\ncourtship/MS\ncourtyard/MS\ncouscous/M\ncousin/SM\ncouture/M\ncouturier/MS\ncove/MS\ncoven/SM\ncovenant/MDSG\ncover's\ncover/AEUGDS\ncoverage/M\ncoverall/MS\ncovering's\ncoverings\ncoverlet/MS\ncovert/SPMY\ncovertness/M\ncovet/SDG\ncovetous/YP\ncovetousness/M\ncovey/SM\ncow/ZGSMDR\ncoward/SMY\ncowardice/M\ncowardliness/M\ncowbell/MS\ncowbird/MS\ncowboy/SM\ncowcatcher/MS\ncower/DG\ncowgirl/MS\ncowhand/MS\ncowherd/MS\ncowhide/MS\ncowl/MGSJ\ncowlick/MS\ncowling/M\ncowman/M\ncowmen\ncoworker/MS\ncowpat/S\ncowpoke/MS\ncowpox/M\ncowpuncher/SM\ncowrie/SM\ncowshed/S\ncowslip/SM\ncox/GDS\ncoxcomb/MS\ncoxswain/MS\ncoy/TPRY\ncoyness/M\ncoyote/SM\ncoypu/SM\ncozen/SDG\ncozenage/M\ncozily\ncoziness/M\ncozy/RSMTP\ncpd\ncpl\ncps\ncrab/MS\ncrabbed\ncrabber/SM\ncrabbily\ncrabbiness/M\ncrabbing\ncrabby/PRT\ncrabgrass/M\ncrablike\ncrabwise\ncrack/SMDRYZGJ\ncrackdown/MS\ncracker/M\ncrackerjack/MS\ncrackhead/MS\ncrackle/DSJMG\ncrackling/M\ncrackpot/MS\ncrackup/SM\ncradle/DSMG\ncraft/SMDG\ncraftily\ncraftiness/M\ncraftsman/M\ncraftsmanship/M\ncraftsmen\ncraftspeople\ncraftswoman/M\ncraftswomen\ncrafty/RTP\ncrag/MS\ncragginess/M\ncraggy/RPT\ncram/S\ncrammed\ncrammer/S\ncramming\ncramp/SMDG\ncramping/M\ncrampon/SM\ncranberry/SM\ncrane/DSMG\ncranial\ncranium/SM\ncrank/SMDG\ncrankcase/SM\ncrankily\ncrankiness/M\ncrankshaft/MS\ncranky/PRT\ncranny/DSM\ncrap/MS\ncrape/SM\ncrapped\ncrapper/S\ncrappie/RSMT\ncrapping\ncrappy\ncraps/M\ncrapshooter/MS\ncrash/MDSG\ncrass/RYTP\ncrassness/M\ncrate/DRSMZG\ncrater/MDG\ncravat/SM\ncrave/DSGJ\ncraven/SMYP\ncravenness/M\ncraving/M\ncraw/MS\ncrawdad/SM\ncrawl/SMDRZG\ncrawler/M\ncrawlspace/SM\ncrawly/TRSM\ncray/S\ncrayfish/MS\ncrayola/S\ncrayon/GSMD\ncraze/DSMG\ncrazily\ncraziness/M\ncrazy/PRSMT\ncreak/SMDG\ncreakily\ncreakiness/M\ncreaky/RPT\ncream/SMDRZG\ncreamer/M\ncreamery/SM\ncreamily\ncreaminess/M\ncreamy/RPT\ncrease/ICGMSD\ncreate/KADSGNV\ncreation's/K\ncreation/ASM\ncreationism/SM\ncreationist/SM\ncreative/SMYP\ncreativeness/M\ncreativity/M\ncreator/MS\ncreature/SM\ncreche/SM\ncred\ncredence/M\ncredential/SGMD\ncredenza/SM\ncredibility/IM\ncredible/I\ncredibly/I\ncredit/EGSBMD\ncreditably/E\ncreditor/SM\ncreditworthy/P\ncredo/SM\ncredulity/IM\ncredulous/IY\ncredulousness/M\ncreed/SM\ncreek/SM\ncreel/SM\ncreep/SMRZG\ncreeper/M\ncreepily\ncreepiness/M\ncreepy/TPR\ncremains/M\ncremate/GNDSX\ncremation/M\ncrematoria\ncrematorium/MS\ncrematory/SM\ncreme/SM\ncrenelate/XGNDS\ncrenelation/M\ncreole/SM\ncreosote/MGDS\ncrepe/SM\ncrept\ncrepuscular\ncrescendo/CSM\ncrescent/MS\ncress/M\ncrest/SMDG\ncrestfallen\ncrestless\ncretaceous\ncretin/SM\ncretinism/M\ncretinous\ncretonne/M\ncrevasse/SM\ncrevice/MS\ncrew/MDGS\ncrewel/M\ncrewelwork/M\ncrewman/M\ncrewmen\ncrib/MS\ncribbage/M\ncribbed\ncribber/MS\ncribbing\ncrick/SMDG\ncricket/MRSZG\ncricketer/M\ncrier/M\ncrikey\ncrime/SM\ncriminal/MYS\ncriminality/M\ncriminalize/CGDS\ncriminologist/MS\ncriminology/M\ncrimp/SMDG\ncrimson/SMDG\ncringe/DSMG\ncrinkle/DSMG\ncrinkly/RT\ncrinoline/SM\ncripes\ncripple/DRSMZG\ncrippler/M\ncrippleware\ncrippling/Y\ncrises\ncrisis/M\ncrisp/SMDRYTGP\ncrispbread/S\ncrispiness/M\ncrispness/M\ncrispy/PRT\ncrisscross/GMDS\ncriteria\ncriterion/M\ncritic/SM\ncritical/UY\ncriticism/MS\ncriticize/ZGDRS\ncriticizer/M\ncritique/MGDS\ncritter/SM\ncroak/SMDG\ncroaky/RT\ncrochet/SMDRZG\ncrocheter/M\ncrocheting/M\ncrock/SMD\ncrockery/M\ncrocodile/SM\ncrocus/MS\ncroft/SRZG\ncroissant/MS\ncrone/SM\ncrony/SM\ncronyism/M\ncrook/SMDG\ncrooked/PTRY\ncrookedness/M\ncrookneck/SM\ncroon/SMDRZG\ncrooner/M\ncrop/MS\ncropland/SM\ncropped\ncropper/MS\ncropping\ncroquet/M\ncroquette/SM\ncrosier/MS\ncross's\ncross/AUGTSD\ncrossbar/SM\ncrossbeam/MS\ncrossbones/M\ncrossbow/SM\ncrossbowman/M\ncrossbowmen\ncrossbred\ncrossbreed/SGM\ncrosscheck/SMDG\ncrosscurrent/MS\ncrosscut/SM\ncrosscutting\ncrosser\ncrossfire/MS\ncrosshatch/GDS\ncrossing/SM\ncrossly\ncrossness/M\ncrossover/MS\ncrosspatch/MS\ncrosspiece/SM\ncrossroad/MS\ncrossroads/M\ncrosstown\ncrosswalk/MS\ncrosswind/MS\ncrosswise\ncrossword/MS\ncrotch/MS\ncrotchet/SM\ncrotchety\ncrouch/GMDS\ncroup/M\ncroupier/M\ncroupy/ZTR\ncrouton/MS\ncrow/MDGS\ncrowbar/MS\ncrowd/SMDG\ncrowded/U\ncrowdfund/SDG\ncrowfeet\ncrowfoot/SM\ncrown/SMDG\ncrowned/U\ncrucial/Y\ncrucible/SM\ncrucifix/MS\ncrucifixion/SM\ncruciform/SM\ncrucify/DSG\ncrud/M\ncruddy/TR\ncrude/RMYTP\ncrudeness/M\ncrudites/M\ncrudity/SM\ncruel/RYPT\ncruelness/M\ncruelty/SM\ncruet/SM\ncruft/SD\ncrufty\ncruise/DRSMZG\ncruiser/M\ncruller/MS\ncrumb/SMDYG\ncrumble/MGDS\ncrumbliness/M\ncrumbly/TPR\ncrumby/TR\ncrumminess/M\ncrummy/PTR\ncrumpet/MS\ncrumple/MGDS\ncrunch/GMDRS\ncrunchiness/M\ncrunchy/TRP\ncrupper/MS\ncrusade/MZGDRS\ncrusader/M\ncruse/SM\ncrush/MDRSZG\ncrusher/M\ncrushing/Y\ncrust/SMDG\ncrustacean/SM\ncrustal\ncrustily\ncrustiness/M\ncrusty/TRP\ncrutch/MS\ncrux/MS\ncry/ZGJDRSM\ncrybaby/SM\ncryogenic/S\ncryogenics/M\ncryonics\ncryosurgery/M\ncrypt/SM\ncryptic\ncryptically\ncryptogram/SM\ncryptographer/SM\ncryptography/M\ncrystal/SM\ncrystalline\ncrystallization/M\ncrystallize/ADSG\ncrystallographic\ncrystallography\nct\nctn\nctr\ncu\ncub/ZGSMDR\ncubbyhole/MS\ncube/MS\ncuber/M\ncubic\ncubical\ncubicle/MS\ncubism/M\ncubist/SM\ncubit/SM\ncuboid/S\ncuckold/MDSG\ncuckoldry/M\ncuckoo/SM\ncucumber/SM\ncud/SM\ncuddle/DSMG\ncuddly/TR\ncudgel/SGMDJ\ncue/DSMG\ncuff/MDGS\ncuisine/SM\nculinary\ncull/MDGS\nculminate/XDSGN\nculmination/M\nculotte/SM\nculpability/M\nculpable/I\nculpably\nculprit/SM\ncult/MS\ncultism/M\ncultist/MS\ncultivable\ncultivar/S\ncultivate/BDSGN\ncultivated/U\ncultivation/M\ncultivator/MS\ncultural/Y\nculture/MGDS\ncultured/U\nculvert/MS\ncum/SM\ncumber/SDG\ncumbersome/P\ncumbersomeness/M\ncumbrous\ncumin/M\ncummerbund/MS\ncumming\ncumulative/Y\ncumuli\ncumulonimbi\ncumulonimbus/M\ncumulus/M\ncuneiform/M\ncunnilingus/M\ncunning/MRYT\ncunt/MS!\ncup/SM\ncupboard/SM\ncupcake/MS\ncupful/SM\ncupid/SM\ncupidity/M\ncupola/SMD\ncuppa/S\ncupped\ncupping\ncupric\ncur/SMY\ncurability/M\ncuracao\ncuracy/SM\ncurare/M\ncurate/DSMGV\ncurative/MS\ncurator/KMS\ncuratorial\ncurb/MDGS\ncurbing/M\ncurbside\ncurbstone/SM\ncurd/MS\ncurdle/DSG\ncure's\ncure/KZGBDRS\ncured/U\ncurer/KM\ncurettage/M\ncurfew/SM\ncuria/M\ncuriae\ncurie/SM\ncurio/SM\ncuriosity/SM\ncurious/YP\ncuriousness/M\ncurium/M\ncurl's\ncurl/UDGS\ncurler/SM\ncurlew/SM\ncurlicue/DSMG\ncurliness/M\ncurling/M\ncurly/RPT\ncurmudgeon/MYS\ncurrant/MS\ncurrency/SM\ncurrent's\ncurrent/FAY\ncurrents\ncurricula\ncurricular\ncurriculum/M\ncurry/DSMG\ncurrycomb/SGMD\ncurse/DSMGV\ncursed/Y\ncursive's\ncursive/EAY\ncursor/SM\ncursorily\ncursoriness/M\ncursory/P\ncurt/RYTP\ncurtail/GDSL\ncurtailment/SM\ncurtain/GMDS\ncurtness/M\ncurtsy/GDSM\ncurvaceous/P\ncurvaceousness/M\ncurvature/SM\ncurve/DSMG\ncurvy/RT\ncushion/MDSG\ncushy/RT\ncusp/MS\ncuspid/SM\ncuspidor/SM\ncuss's\ncuss/FEGSD\ncussed/PY\ncustard/MS\ncustodial\ncustodian/MS\ncustodianship/M\ncustody/M\ncustom/SZMR\ncustomarily\ncustomary/U\ncustomer/M\ncustomhouse/SM\ncustomization/M\ncustomize/DSG\ncut/TSMR\ncutaneous\ncutaway/MS\ncutback/MS\ncute/YP\ncuteness/M\ncutesy/TR\ncutey/S\ncuticle/MS\ncutie/SM\ncutlass/MS\ncutler/SM\ncutlery/M\ncutlet/SM\ncutoff/SM\ncutout/SM\ncutter/SM\ncutthroat/SM\ncutting/MYS\ncuttlefish/MS\ncutup/SM\ncutworm/MS\ncw\ncwt\ncyan/M\ncyanide/M\ncyberbully/S\ncybercafe/S\ncybernetic/S\ncybernetics/M\ncyberpunk/SM\ncybersex\ncyberspace/MS\ncyborg/SM\ncyclamen/MS\ncycle/ADSMG\ncyclic\ncyclical/Y\ncyclist/MS\ncyclometer/MS\ncyclone/MS\ncyclonic\ncyclopedia/MS\ncyclopes\ncyclops/M\ncyclotron/MS\ncygnet/MS\ncylinder/MS\ncylindrical\ncymbal/MS\ncymbalist/MS\ncynic/SM\ncynical/Y\ncynicism/M\ncynosure/MS\ncypress/MS\ncyst/MS\ncystic\ncystitis\ncytologist/SM\ncytology/M\ncytoplasm/M\ncytoplasmic\ncytosine/M\nczar/MS\nczarina/SM\nczarism\nczarist/SM\nd'Arezzo/M\nd'Estaing/M\nd/NXGJ\ndB\ndab/SM\ndabbed\ndabber/MS\ndabbing\ndabble/ZGDRS\ndabbler/M\ndace/SM\ndacha/MS\ndachshund/MS\ndactyl/MS\ndactylic/MS\ndad/SM\ndadaism/M\ndadaist/MS\ndaddy/SM\ndado/M\ndadoes\ndaemon/MS\ndaemonic\ndaffiness/M\ndaffodil/SM\ndaffy/PTR\ndaft/PTRY\ndaftness/M\ndag/S\ndagger/MS\ndago/S\ndagoes\ndaguerreotype/DSMG\ndahlia/MS\ndailiness/M\ndaily/PSM\ndaintily\ndaintiness/M\ndainty/RSMTP\ndaiquiri/MS\ndairy/GSM\ndairying/M\ndairymaid/MS\ndairyman/M\ndairymen\ndairywoman/M\ndairywomen\ndais/MS\ndaisy/SM\ndale/SM\ndalliance/MS\ndallier/M\ndally/ZGDRS\ndalmatian/MS\ndam/SM\ndamage/MGDS\ndamageable\ndamaged/U\ndamages/M\ndamask/MDGS\ndame/SM\ndammed\ndamming\ndammit\ndamn/SBGMD\ndamnably\ndamnation/M\ndamned/T\ndamp/SPXZTGMDNRY\ndampen/ZGDR\ndampener/M\ndamper/M\ndampness/M\ndamsel/MS\ndamselfly/SM\ndamson/MS\ndance/MZGDRS\ndancer/M\ndancing/M\ndandelion/SM\ndander/M\ndandify/GDS\ndandle/GDS\ndandruff/M\ndandy/TRSM\ndang/SZGDR\ndanger/M\ndangerous/Y\ndangle/ZGDRS\ndangler/M\ndanish/MS\ndank/PTRY\ndankness/M\ndanseuse/MS\ndapper/TR\ndapple/MGDS\ndare/DRSMZG\ndaredevil/MS\ndaredevilry/M\ndarer/M\ndaresay\ndaring/MY\ndark/PXTMNRY\ndarken/ZGDR\ndarkener/M\ndarkie/S\ndarkness/M\ndarkroom/MS\ndarling/MS\ndarn/SZGMDR\ndarned/TR\ndarner/M\ndart/SZGMDR\ndartboard/MS\ndarter/M\ndash/ZGMDRS\ndashboard/SM\ndasher/M\ndashiki/MS\ndashing/Y\ndastard/MYS\ndastardliness/M\ndata\ndatabase/SM\ndatatype\ndate/DRSMZGV\ndatebook/S\ndated/U\ndateless\ndateline/MGDS\ndater/M\ndative/MS\ndatum/M\ndaub/SZGMDR\ndauber/M\ndaughter/SMY\ndaunt/GDS\ndaunting/Y\ndauntless/YP\ndauntlessness/M\ndauphin/MS\ndavenport/MS\ndavit/MS\ndawdle/ZGDRS\ndawdler/M\ndawn/SGMD\nday/SM\ndaybed/MS\ndaybreak/M\ndaycare/M\ndaydream/MDRZGS\ndaydreamer/M\ndaylight/MS\ndaylights/M\ndaylong\ndaytime/M\ndaze/DSMG\ndazed/Y\ndazzle/MZGDRS\ndazzler/M\ndazzling/Y\ndb\ndbl\ndc\ndd/SDG\ndded/K\ndding/K\ndeacon/MS\ndeaconess/MS\ndead/XTMNRY\ndeadbeat/MS\ndeadbolt/SM\ndeaden/GD\ndeadhead/SDG\ndeadline/SM\ndeadliness/M\ndeadlock/GSMD\ndeadly/TPR\ndeadpan/MS\ndeadpanned\ndeadpanning\ndeadwood/M\ndeaf/PXTNR\ndeafen/GD\ndeafening/Y\ndeafness/M\ndeal/SJZGMR\ndealer/M\ndealership/SM\ndealing/M\ndealt\ndean/M\ndeanery/SM\ndeanship/M\ndear/SPTMRYH\ndearest/S\ndearness/M\ndearth/M\ndearths\ndeary/SM\ndeath/MY\ndeathbed/SM\ndeathblow/MS\ndeathless/Y\ndeathlike\ndeaths\ndeathtrap/MS\ndeathwatch/MS\ndeaves\ndeb/SM\ndebacle/MS\ndebarkation/M\ndebarment/M\ndebate/BMZR\ndebater/M\ndebating/M\ndebauch/MDSG\ndebauchee/MS\ndebauchery/SM\ndebenture/MS\ndebilitate/DSGN\ndebilitation/M\ndebility/SM\ndebit/D\ndebonair/PY\ndebonairness/M\ndebouch/GDS\ndebridement\ndebris/M\ndebt/SM\ndebtor/MS\ndebugger/S\ndebut/GMD\ndebutante/SM\ndecade/MS\ndecadence/M\ndecadency/M\ndecadent/MYS\ndecaf/MS\ndecaffeinate/DSG\ndecagon/MS\ndecal/MS\ndecampment/M\ndecapitate/XGNDS\ndecapitator/MS\ndecathlete/S\ndecathlon/SM\ndecay/GD\ndeceased/M\ndecedent/MS\ndeceit/MS\ndeceitful/YP\ndeceitfulness/M\ndeceive/UGDS\ndeceiver/MS\ndeceiving/Y\ndecelerate/GNDS\ndeceleration/M\ndecelerator/SM\ndecency/ISM\ndecennial/SM\ndecent/IY\ndeception/MS\ndeceptive/YP\ndeceptiveness/M\ndecibel/MS\ndecidable/U\ndecide/BZGDRS\ndecided/Y\ndeciduous\ndeciliter/MS\ndecimal/SM\ndecimalization\ndecimate/DSGN\ndecimation/M\ndecimeter/MS\ndecipherable/UI\ndecision/IM\ndecisions\ndecisive/IPY\ndecisiveness/IM\ndeck/SGMD\ndeckchair/S\ndeckhand/SM\ndeckle/S\ndeclamation/MS\ndeclamatory\ndeclaration/MS\ndeclarative\ndeclaratory\ndeclare/DRSZGB\ndeclared/U\ndeclarer/M\ndeclension/SM\ndeclination/M\ndecline/DRSMZG\ndecliner/M\ndeclivity/SM\ndecolletage/SM\ndecollete\ndecongestant/MS\ndeconstructionism\ndecor/MS\ndecorate/AGNVDS\ndecorating/M\ndecoration/AM\ndecorations\ndecorative/Y\ndecorator/MS\ndecorous/IY\ndecorousness/M\ndecorum/M\ndecoupage/DSMG\ndecoy/GMDS\ndecreasing/Y\ndecree/MDS\ndecreeing\ndecremented\ndecrements\ndecrepit\ndecrepitude/M\ndecriminalization/M\ndecry/GDS\ndecryption\ndedicate/AGDS\ndedication/SM\ndedicator/SM\ndedicatory\ndeduce/GDS\ndeducible\ndeduct/GVD\ndeductible/SM\ndeduction/SM\ndeductive/Y\ndeed/GD\ndeejay/MS\ndeem/ASGD\ndeep/SPXTMNRY\ndeepen/GD\ndeepness/M\ndeer/M\ndeerskin/M\ndeerstalker/S\ndef/Z\ndefacement/M\ndefacer/SM\ndefalcate/DSXGN\ndefalcation/M\ndefamation/M\ndefamatory\ndefame/ZGDRS\ndefamer/M\ndefaulter/SM\ndefeat/MDRZGS\ndefeated/U\ndefeater/M\ndefeatism/M\ndefeatist/MS\ndefecate/GNDS\ndefecation/M\ndefect/MDGVS\ndefection/MS\ndefective/MPYS\ndefectiveness/M\ndefector/MS\ndefendant/SM\ndefended/U\ndefenestration/S\ndefense/DSMGV\ndefenseless/YP\ndefenselessness/M\ndefensible/I\ndefensibly/I\ndefensive/MYP\ndefensiveness/M\ndeference/M\ndeferential/Y\ndeferral/MS\ndeferred\ndeferring\ndeffer\ndeffest\ndefiant/Y\ndefibrillation\ndefibrillator/S\ndeficiency/SM\ndeficient\ndeficit/SM\ndefilement/M\ndefinable/IU\ndefine/AGDS\ndefined/U\ndefiner/MS\ndefinite/IYVP\ndefiniteness/IM\ndefinition/AM\ndefinitions\ndefinitive/Y\ndeflate/GNDS\ndeflation/M\ndeflationary\ndeflect/DGVS\ndeflection/MS\ndeflector/SM\ndefogger/SM\ndefoliant/SM\ndefoliate/DSGN\ndefoliation/M\ndefoliator/MS\ndeformity/SM\ndefraud/DRZGS\ndefrauder/M\ndefrayal/M\ndefrock/DG\ndefroster/MS\ndeft/PTRY\ndeftness/M\ndefunct\ndefy/GDS\ndeg\ndegeneracy/M\ndegenerate/MV\ndegrade/B\ndegree/MS\ndehydrator/SM\ndehydrogenase\ndeicer/MS\ndeification/M\ndeify/NGDS\ndeign/GDS\ndeist/MS\ndeistic\ndeity/SM\ndeject/GDS\ndejected/Y\ndejection/M\ndelay/ZDR\ndelectable\ndelectably\ndelectation/M\ndelegate/GD\ndelete/XGNDS\ndeleterious\ndeletion/M\ndelft/M\ndelftware/M\ndeli/SM\ndeliberate/XYVP\ndeliberateness/M\ndelicacy/ISM\ndelicate/IY\ndelicateness/M\ndelicatessen/SM\ndelicious/PY\ndeliciousness/M\ndelighted/Y\ndelightful/Y\ndeliminator\ndelineate/GNXDS\ndelineation/M\ndelinquency/SM\ndelinquent/SMY\ndeliquesce/DSG\ndeliquescent\ndelirious/YP\ndeliriousness/M\ndelirium/SM\ndeliver/ADGS\ndeliverable\ndeliverance/M\ndelivered/U\ndeliverer/SM\ndell/SM\ndelphinium/MS\ndelta/MS\ndelude/GDS\ndeluge/MGDS\ndelusion/MS\ndelusional\ndelusive/Y\ndeluxe\ndelve/ZGDRS\ndelver/M\ndemagogic\ndemagogically\ndemagogue/SM\ndemagoguery/M\ndemagogy/M\ndemand/GMDS\ndemanding/U\ndemarcate/DSGNX\ndemarcation/M\ndemean/GDS\ndemeanor/M\ndemented/Y\ndementia/M\ndemesne/MS\ndemigod/MS\ndemigoddess/MS\ndemijohn/SM\ndemimondaine/SM\ndemimonde/M\ndemise/MGDS\ndemitasse/MS\ndemo/GMD\ndemocracy/SM\ndemocrat/MS\ndemocratic/U\ndemocratically\ndemocratization/M\ndemocratize/GDS\ndemode\ndemographer/SM\ndemographic/SM\ndemographically\ndemographics/M\ndemography/M\ndemolish/DSG\ndemolition/MS\ndemon/MS\ndemonetization/M\ndemoniac\ndemoniacal/Y\ndemonic\ndemonically\ndemonize/GDS\ndemonology/SM\ndemonstrability\ndemonstrable/I\ndemonstrably\ndemonstrate/XGNVDS\ndemonstration/M\ndemonstrative/MYSP\ndemonstrativeness/M\ndemonstrator/MS\ndemote/GD\ndemotic\ndemount\ndemulcent/SM\ndemur/TMRS\ndemure/PY\ndemureness/M\ndemurral/SM\ndemurred\ndemurrer/SM\ndemurring\nden/M\ndenationalization\ndenaturation\ndenature/DG\ndendrite/SM\ndengue/M\ndeniability\ndeniable/U\ndenial/MS\ndenier/M\ndenigrate/DSGN\ndenigration/M\ndenim/MS\ndenitrification\ndenizen/MS\ndenominational\ndenotative\ndenouement/MS\ndenounce/LDSG\ndenouncement/SM\ndense/PYTR\ndenseness/M\ndensity/SM\ndent/ISGMD\ndental/Y\ndentifrice/SM\ndentin/M\ndentist/MS\ndentistry/M\ndentition/M\ndenture/IMS\ndenuclearize/GDS\ndenudation/M\ndenude/GDS\ndenunciation/SM\ndeny/ZGDRS\ndeodorant/SM\ndeodorization/M\ndeodorize/DRSZG\ndeodorizer/M\ndeparted/M\ndepartment/MS\ndepartmental/Y\ndepartmentalization/M\ndepartmentalize/GDS\ndeparture/SM\ndependability/M\ndependable/U\ndependably\ndependence/IM\ndependency/SM\ndependent/IMYS\ndepict/GDS\ndepiction/MS\ndepilatory/SM\ndeplete/GNDS\ndepletion/M\ndeplorably\ndeplore/BGDS\ndeploy/ALGDS\ndeployment/AM\ndeployments\ndeponent/MS\ndeportation/MS\ndeportee/MS\ndeportment/M\ndeposit/AGMDS\ndepositor/MS\ndepository/SM\ndeprave/GDS\ndepravity/SM\ndeprecate/GNDS\ndeprecating/Y\ndeprecation/M\ndeprecatory\ndepreciate/DSGN\ndepreciation/M\ndepredation/SM\ndepressant/SM\ndepressing/Y\ndepression/SM\ndepressive/SM\ndepressor/MS\ndepressurization\ndeprive/GDS\ndeprogramming\ndepth/M\ndepths\ndeputation/MS\ndepute/DSG\ndeputize/DSG\ndeputy/SM\nderailleur/SM\nderailment/SM\nderangement/M\nderby/SM\nderelict/MS\ndereliction/M\nderide/GDS\nderision/M\nderisive/PY\nderisiveness/M\nderisory\nderivation/MS\nderivative/MS\nderive/B\ndermal\ndermatitis/M\ndermatological\ndermatologist/SM\ndermatology/M\ndermis/M\nderogate/DSGN\nderogation/M\nderogatorily\nderogatory\nderrick/SM\nderriere/SM\nderringer/SM\nderv\ndervish/MS\ndesalinate/GNDS\ndesalination/M\ndesalinization/M\ndesalinize/GDS\ndescant/M\ndescend/FGDS\ndescendant/MS\ndescender\ndescribable/I\ndescribe/BZGDR\ndescriber/M\ndescription/SM\ndescriptive/PY\ndescriptiveness/M\ndescriptor/S\ndescry/GDS\ndesecrate/DSGN\ndesecration/M\ndeselection\ndesert/SDRZGM\ndeserter/M\ndesertification\ndesertion/SM\ndeserved/UY\ndeserving/U\ndesiccant/SM\ndesiccate/DSGN\ndesiccation/M\ndesiccator/SM\ndesiderata\ndesideratum/M\ndesign/ASDG\ndesignate/DSGNX\ndesignation/M\ndesirability/UM\ndesirableness/M\ndesirably/U\ndesire/B\ndesired/U\ndesirous\ndesist/SDG\ndesk/SM\ndeskill/G\ndesktop/SM\ndesolate/PDSYGN\ndesolateness/M\ndesolation/M\ndespair/SMDG\ndespairing/Y\ndesperado/M\ndesperadoes\ndesperate/YNP\ndesperateness/M\ndesperation/M\ndespicable\ndespicably\ndespise/DSG\ndespite\ndespoilment/M\ndespondence/M\ndespondency/M\ndespondent/Y\ndespotic\ndespotically\ndespotism/M\ndessert/SM\ndessertspoon/S\ndessertspoonful/S\ndestination/SM\ndestine/DSG\ndestiny/SM\ndestitute/N\ndestitution/M\ndestroy/SZGDR\ndestroyer/M\ndestruct/GVMDS\ndestructibility/IM\ndestructible/I\ndestruction/M\ndestructive/PY\ndestructiveness/M\ndesuetude/M\ndesultorily\ndesultory\ndetach/BLGDS\ndetachment/MS\ndetain/LGDS\ndetainee/MS\ndetainment/M\ndetect/SDGVB\ndetectable/U\ndetected/U\ndetection/M\ndetective/SM\ndetector/SM\ndetente/SMNX\ndetention/M\ndeter/SL\ndetergent/SM\ndeteriorate/DSGN\ndeterioration/M\ndeterment/M\ndeterminable/I\ndeterminant/SM\ndeterminate\ndetermine/AGDS\ndetermined/U\ndeterminedly\ndeterminer/SM\ndeterminism/M\ndeterministic\ndeterred/U\ndeterrence/M\ndeterrent/MS\ndeterring\ndetestably\ndetestation/M\ndethrone/DSLG\ndethronement/M\ndetonate/GNDSX\ndetonation/M\ndetonator/SM\ndetox/MDSG\ndetoxification/M\ndetoxify/DSGN\ndetract/GD\ndetriment/SM\ndetrimental/Y\ndetritus/M\ndeuce/SM\ndeuterium/M\ndevastate/GNDS\ndevastating/Y\ndevastation/M\ndevastator/MS\ndevelop/ASGDL\ndeveloped/U\ndeveloper/SM\ndevelopment/ASM\ndevelopmental/Y\ndeviance/M\ndeviancy/M\ndeviant/SM\ndeviate/DSMGNX\ndeviating/U\ndeviation/M\ndevil/SMDGL\ndevilish/YP\ndevilishness/M\ndevilment/M\ndevilry/SM\ndeviltry/SM\ndevious/YP\ndeviousness/M\ndevoid\ndevolution/M\ndevolve/DSG\ndevoted/Y\ndevotee/SM\ndevotion/MS\ndevotional/SM\ndevour/SDG\ndevout/PRYT\ndevoutness/M\ndew/M\ndewberry/SM\ndewclaw/SM\ndewdrop/SM\ndewiness/M\ndewlap/SM\ndewy/RTP\ndexterity/M\ndexterous/YP\ndexterousness/M\ndextrose/M\ndharma\ndhoti/SM\ndhow/MS\ndiabetes/M\ndiabetic/SM\ndiabolic\ndiabolical/Y\ndiacritic/MS\ndiacritical\ndiadem/SM\ndiaereses\ndiaeresis/M\ndiagnose/DSG\ndiagnosis/M\ndiagnostic/S\ndiagnostically\ndiagnostician/SM\ndiagnostics/M\ndiagonal/SMY\ndiagram/SM\ndiagrammatic\ndiagrammatically\ndiagrammed\ndiagramming\ndial/AMDGS\ndialect/SM\ndialectal\ndialectic/SM\ndialectical\ndialectics/M\ndialing/S\ndialog\ndialogue/SM\ndialyses\ndialysis/M\ndialyzes\ndiam\ndiamante\ndiameter/SM\ndiametric\ndiametrical/Y\ndiamond/SM\ndiamondback/MS\ndiapason/SM\ndiaper/SMDG\ndiaphanous\ndiaphragm/SM\ndiaphragmatic\ndiarist/SM\ndiarrhea/M\ndiary/SM\ndiaspora\ndiastase/M\ndiastole/M\ndiastolic\ndiathermy/M\ndiatom/SM\ndiatomic\ndiatonic\ndiatribe/SM\ndibble/DSMG\ndibs/M\ndice/GDS\ndices/I\ndicey\ndichotomous\ndichotomy/SM\ndicier\ndiciest\ndick/MRXZS\ndicker/DG\ndickey/SM\ndickhead/S\ndickybird/S\ndicotyledon/MS\ndicotyledonous\ndict\ndicta\ndictate/DSMGNX\ndictation/M\ndictator/SM\ndictatorial/Y\ndictatorship/SM\ndiction/M\ndictionary/SM\ndictum/M\ndid/AU\ndidactic\ndidactically\ndiddle/DRSZG\ndiddler/M\ndiddly\ndiddlysquat\ndiddums\ndidgeridoo/S\ndidn't\ndido/M\ndidoes\ndidst\ndie/DSM\ndielectric/MS\ndiereses\ndieresis/M\ndiesel/SMDG\ndiet/MDRZGS\ndietary/SM\ndieter/M\ndietetic/S\ndietetics/M\ndietitian/MS\ndiff/DRZGS\ndiffer/DG\ndifference/IM\ndifferences\ndifferent/IY\ndifferential/SM\ndifferentiate/DSGN\ndifferentiated/U\ndifferentiation/M\ndifficult/Y\ndifficulty/SM\ndiffidence/M\ndiffident/Y\ndiffract/GSD\ndiffraction/M\ndiffuse/DSYGNVP\ndiffuseness/M\ndiffusion/M\ndig/SM\ndigerati/M\ndigest/SMDGV\ndigested/U\ndigestibility/M\ndigestible/I\ndigestion/IM\ndigestions\ndigestive/S\ndigger/SM\ndigging/S\ndiggings/M\ndigicam/S\ndigit/SM\ndigital/Y\ndigitalis/M\ndigitization\ndigitize/GDS\ndignified/U\ndignify/DSG\ndignitary/SM\ndignity/ISM\ndigraph/M\ndigraphs\ndigress/GVDS\ndigression/MS\ndike/MGDS\ndiktat/S\ndilapidated\ndilapidation/M\ndilatation/M\ndilate/DSGN\ndilation/M\ndilator/SM\ndilatory\ndildo/S\ndilemma/MS\ndilettante/SM\ndilettantish\ndilettantism/M\ndiligence/M\ndiligent/Y\ndill/MS\ndilly/SM\ndillydally/DSG\ndilute/DSGNX\ndiluted/U\ndilution/M\ndim/PSRY\ndime/MS\ndimension/SM\ndimensional\ndimensionless\ndiminish/GDS\ndiminished/U\ndiminuendo/SM\ndiminution/SM\ndiminutive/SM\ndimity/M\ndimmed/U\ndimmer/SM\ndimmest\ndimming\ndimness/M\ndimple/DSMG\ndimply\ndimwit/SM\ndimwitted\ndin/ZGSMDR\ndinar/SM\ndine/S\ndiner/M\ndinette/MS\nding/MDG\ndingbat/MS\ndinghy/SM\ndingily\ndinginess/M\ndingle/SM\ndingo/M\ndingoes\ndingus/MS\ndingy/RPT\ndink/R\ndinky/RSMT\ndinned\ndinner/SMDG\ndinnertime/M\ndinnerware/M\ndinning\ndinosaur/SM\ndint/M\ndiocesan/MS\ndiocese/MS\ndiode/SM\ndiorama/SM\ndioxide/SM\ndioxin/SM\ndip/SM\ndiphtheria/M\ndiphthong/SM\ndiploid/SM\ndiploma/SM\ndiplomacy/M\ndiplomat/MS\ndiplomata\ndiplomatic/U\ndiplomatically\ndiplomatist/MS\ndiplopia\ndipole/SM\ndipped\ndipper/SM\ndipping\ndippy/RT\ndipso/S\ndipsomania/M\ndipsomaniac/MS\ndipstick/SM\ndipterous\ndiptych/M\ndiptychs\ndire/YTR\ndirect/ASDGVT\ndirecter\ndirection/IM\ndirectional\ndirectionless\ndirections\ndirective/SM\ndirectly\ndirectness/IM\ndirector/MS\ndirectorate/SM\ndirectorial\ndirectorship/SM\ndirectory/SM\ndireful\ndirge/SM\ndirigible/MS\ndirk/MS\ndirndl/SM\ndirt/M\ndirtball/S\ndirtily\ndirtiness/M\ndirty/DRSTGP\ndis/M\ndisable/DSGL\ndisablement/M\ndisambiguate/N\ndisappointing/Y\ndisarming/Y\ndisassembly\ndisastrous/Y\ndisbandment/M\ndisbarment/M\ndisbelieving/Y\ndisbursal/M\ndisburse/DSGL\ndisbursement/MS\ndisc/M\ndiscern/LSDG\ndiscernible/I\ndiscernibly\ndiscerning/Y\ndiscernment/M\ndischarged/U\ndisciple/SM\ndiscipleship/M\ndisciplinarian/SM\ndisciplinary\ndiscipline/DSMG\ndisciplined/U\ndisclose/DSG\ndisclosed/U\ndisco/MG\ndiscography/SM\ndiscoloration/S\ndiscombobulate/DSGN\ndiscombobulation/M\ndiscomfit/DG\ndiscomfiture/M\ndiscommode/DG\ndisconcerting/Y\ndisconnected/PY\ndisconnectedness/M\ndisconsolate/Y\ndiscordance/M\ndiscordant/Y\ndiscotheque/SM\ndiscourage/LGDS\ndiscouragement/SM\ndiscouraging/Y\ndiscover/ASDG\ndiscovered/U\ndiscoverer/MS\ndiscovery/ASM\ndiscreet/PRYT\ndiscreetness/M\ndiscrepancy/SM\ndiscrepant\ndiscrete/PYN\ndiscreteness/M\ndiscretion/IM\ndiscretionary\ndiscriminant\ndiscriminate/GNDS\ndiscriminating/U\ndiscrimination/M\ndiscriminator/MS\ndiscriminatory\ndiscursiveness/M\ndiscus/MS\ndiscussant/SM\ndiscussion/SM\ndisdain/SMDG\ndisdainful/Y\ndisembowel/SDLG\ndisembowelment/M\ndisfigurement/SM\ndisfranchisement/M\ndisgorgement/M\ndisgruntle/LGDS\ndisgruntlement/M\ndisguise/GD\ndisguised/U\ndisgusted/Y\ndisgusting/Y\ndish/MDSG\ndishabille/M\ndisharmonious\ndishcloth/M\ndishcloths\ndisheartening/Y\ndishevel/DGLS\ndishevelment/M\ndishpan/SM\ndishrag/SM\ndishtowel/MS\ndishware/M\ndishwasher/MS\ndishwater/M\ndishy\ndisillusion/GLD\ndisillusionment/M\ndisinfectant/MS\ndisinfection/M\ndisinterested/PY\ndisinterestedness/M\ndisjointed/YP\ndisjointedness/M\ndisjunctive\ndisjuncture\ndisk/MS\ndiskette/MS\ndislodge/GDS\ndismal/Y\ndismantlement/M\ndismay/SMDG\ndismayed/U\ndismember/LGD\ndismemberment/M\ndismissive/Y\ndisorder/Y\ndisorganization/M\ndisparage/DSGL\ndisparagement/M\ndisparaging/Y\ndisparate/Y\ndispatcher/MS\ndispel/S\ndispelled\ndispelling\ndispensary/SM\ndispensation/MS\ndispense/BZGDRS\ndispenser/M\ndispersal/M\ndisperse/GNDS\ndispersion/M\ndispirit/GDS\ndispleasure/M\ndisposable/SM\ndisposal/SM\ndisposed/I\ndisposition/ISM\ndispossession/M\ndisproof/SM\ndisproportional\ndisprove/B\ndisputable/I\ndisputably/I\ndisputant/MS\ndisputation/SM\ndisputatious/Y\ndispute/DRSMZGB\ndisputed/U\ndisputer/M\ndisquiet/GSMD\ndisquisition/MS\ndisregardful\ndisrepair/M\ndisrepute/MB\ndisrupt/GVSD\ndisruption/SM\ndisruptive/Y\ndissect/SDG\ndissed\ndissemblance/M\ndissemble/ZGDRS\ndissembler/M\ndisseminate/GNDS\ndissemination/M\ndissension/SM\ndissent/SMDRZG\ndissenter/M\ndissertation/SM\ndissidence/M\ndissident/MS\ndissimilar\ndissimilitude/S\ndissing\ndissipate/GNDS\ndissipation/M\ndissociate/GNDS\ndissociation/M\ndissoluble/I\ndissolute/YNP\ndissoluteness/M\ndissolve/AGDS\ndissolved/U\ndissonance/SM\ndissonant\ndissuade/GDS\ndissuasive\ndist\ndistaff/SM\ndistal/Y\ndistance/DSMG\ndistant/Y\ndistaste/SM\ndistemper/M\ndistention/SM\ndistillate/SMNX\ndistillation/M\ndistillery/SM\ndistinct/IYTVP\ndistincter\ndistinction/SM\ndistinctive/YP\ndistinctiveness/M\ndistinctness/IM\ndistinguish/GDSB\ndistinguishable/I\ndistinguished/U\ndistort/GDR\ndistortion/MS\ndistract/DG\ndistracted/Y\ndistraction/S\ndistrait\ndistraught\ndistress/DG\ndistressful\ndistressing/Y\ndistribute/AGNVDS\ndistributed/U\ndistribution/AM\ndistributional\ndistributions\ndistributive/Y\ndistributor's\ndistributor/AS\ndistributorship/S\ndistrict's\ndistrict/AS\ndisturb/ZGSDR\ndisturbance/SM\ndisturbed/U\ndisturber/M\ndisturbing/Y\ndisunion/M\ndisyllabic\nditch/MDSG\ndither/SMDRZG\nditherer/M\nditransitive\nditsy\nditto/SMDG\nditty/SM\nditz/MS\ndiuretic/MS\ndiurnal/Y\ndiv\ndiva/MS\ndivalent\ndivan/SM\ndive/MZTGDRS\ndiver/M\ndiverge/DSG\ndivergence/MS\ndivergent\ndiverse/XYNP\ndiverseness/M\ndiversification/M\ndiversify/GNDS\ndiversion/M\ndiversionary\ndiversity/SM\ndivert/SDG\ndiverticulitis/M\ndivest/SLDG\ndivestiture/MS\ndivestment/M\ndivide/DRSMZGB\ndivided/U\ndividend/MS\ndivider/M\ndivination/M\ndivine/DRSMYZTG\ndiviner/M\ndiving/M\ndivinity/SM\ndivisibility/IM\ndivisible/I\ndivision/MS\ndivisional\ndivisive/PY\ndivisiveness/M\ndivisor/SM\ndivorce/DSLMG\ndivorcee/MS\ndivorcement/MS\ndivot/SM\ndivulge/GDS\ndivvy/DSMG\ndixieland/M\ndizzily\ndizziness/M\ndizzy/DRSPTG\ndjellaba/MS\ndo/SJMRHZG\ndoable\ndob/S\ndobbed\ndobbin/SM\ndobbing\ndoberman/MS\ndobro\ndoc/SM\ndocent/SM\ndocile/Y\ndocility/M\ndock/MDRZGS\ndocket/SMDG\ndockland/S\ndockside\ndockworker/MS\ndockyard/MS\ndoctor/SMDG\ndoctoral\ndoctorate/MS\ndoctrinaire/MS\ndoctrinal\ndoctrine/MS\ndocudrama/SM\ndocument/GMDS\ndocumentary/SM\ndocumentation/SM\ndocumented/U\ndodder/SMDG\ndoddery\ndoddle\ndodge/DRSMZG\ndodgem/S\ndodger/M\ndodgy/RT\ndodo/MS\ndoe/SM\ndoer/M\ndoes/AU\ndoeskin/MS\ndoesn't\ndoff/DGS\ndog/SM\ndogcart/SM\ndogcatcher/SM\ndoge/MS\ndogeared\ndogfight/SM\ndogfish/MS\ndogged/PY\ndoggedness/M\ndoggerel/M\ndogging\ndoggone/TGRS\ndoggy/RSMT\ndoghouse/SM\ndogie/SM\ndogleg/SM\ndoglegged\ndoglegging\ndoglike\ndogma/SM\ndogmatic\ndogmatically\ndogmatism/M\ndogmatist/SM\ndognapper\ndogsbody/S\ndogsled/S\ndogtrot/MS\ndogtrotted\ndogtrotting\ndogwood/MS\ndoily/SM\ndoing/USM\ndoldrums/M\ndole's\ndole/FGDS\ndoleful/YP\ndolefulness/M\ndoll/MDGS\ndollar/SM\ndollhouse/SM\ndollop/SGMD\ndolly/SM\ndolmen/SM\ndolomite/M\ndolor/M\ndolorous/Y\ndolphin/MS\ndolt/MS\ndoltish/YP\ndoltishness/M\ndomain/SM\ndome/MGDS\ndomestic/SM\ndomestically\ndomesticate/DSGN\ndomesticated/U\ndomestication/M\ndomesticity/M\ndomicile/DSMG\ndomiciliary\ndominance/M\ndominant/SMY\ndominate/DSGN\ndomination/M\ndominatrices\ndominatrix/M\ndomineer/SGD\ndomineering/Y\ndominion/SM\ndomino/M\ndominoes\ndon't\ndon/SM\ndona/MS\ndonate/DSXGN\ndonation/M\ndone/FAU\ndong/MDGS\ndongle/SM\ndonkey/SM\ndonned\ndonning\ndonnish\ndonnybrook/MS\ndonor/SM\ndonuts\ndoodad/SM\ndoodah\ndoodahs\ndoodle/DRSMZG\ndoodlebug/SM\ndoodler/M\ndoohickey/SM\ndoolally\ndoom/MDGS\ndoomsayer/MS\ndoomsday/M\ndoomster/S\ndoor's\ndoor/IS\ndoorbell/MS\ndoorjamb/S\ndoorkeeper/MS\ndoorknob/MS\ndoorknocker/S\ndoorman/M\ndoormat/SM\ndoormen\ndoorplate/SM\ndoorpost/S\ndoorstep/MS\ndoorstepped\ndoorstepping\ndoorstop/MS\ndoorway/SM\ndooryard/MS\ndopa/M\ndopamine\ndope/MZGDRS\ndoper/M\ndopey\ndopier\ndopiest\ndopiness/M\ndoping/M\ndoppelganger/S\ndork/MS\ndorky/RT\ndorm/MRZS\ndormancy/M\ndormant\ndormer/M\ndormice\ndormitory/SM\ndormouse/M\ndorsal/Y\ndory/SM\ndosage/SM\ndose/MGDS\ndosh\ndosimeter/SM\ndoss/DRSZG\ndosshouse/S\ndossier/MS\ndost\ndot/ZGSMDR\ndotage/M\ndotard/SM\ndotcom/SM\ndote/S\ndoter/M\ndoting/Y\ndotted\ndotting\ndotty/RT\ndouble's\ndouble/ADSG\ndoubleheader/MS\ndoublespeak/M\ndoublet/MS\ndoubloon/SM\ndoubly\ndoubt/SMDRZG\ndoubter/M\ndoubtful/PY\ndoubtfulness/M\ndoubting/Y\ndoubtless/Y\ndouche/DSMG\ndough/M\ndoughnut/SM\ndoughty/RT\ndoughy/TR\ndour/RYTP\ndourness/M\ndouse/DSG\ndove/MS\ndovecot/S\ndovecote/SM\ndovetail/MDSG\ndovish\ndowager/MS\ndowdily\ndowdiness/M\ndowdy/RSPT\ndowel/SMDG\ndower/SMDG\ndown/MDRZGS\ndownbeat/SM\ndowncast\ndowndraft/MS\ndowner/M\ndownfall/SMN\ndownfield\ndowngrade/DSMG\ndownhearted/PY\ndownheartedness/M\ndownhill/MS\ndownload/MDBSG\ndownmarket\ndownplay/DSG\ndownpour/MS\ndownrange\ndownright\ndownriver\ndownscale\ndownshift/SGD\ndownside/MS\ndownsize/GDS\ndownsizing/M\ndownspout/MS\ndownstage\ndownstairs/M\ndownstate/M\ndownstream\ndownswing/MS\ndowntime/M\ndowntown/M\ndowntrend/MS\ndowntrodden\ndownturn/MS\ndownward/S\ndownwind\ndowny/RT\ndowry/SM\ndowse/DRSZG\ndowser/M\ndoxology/SM\ndoyen/SM\ndoyenne/MS\ndoz/XGDNS\ndoze/M\ndozen/MH\ndozily\ndozy/RTP\ndpi\ndpt\ndrab/MYSP\ndrabber\ndrabbest\ndrabness/M\ndrachma/MS\ndraconian\ndraft's\ndraft/ASDG\ndraftee/SM\ndrafter/SM\ndraftily\ndraftiness/M\ndrafting/M\ndraftsman/M\ndraftsmanship/M\ndraftsmen\ndraftswoman/M\ndraftswomen\ndrafty/RTP\ndrag/MS\ndragged\ndragging\ndraggy/TR\ndragnet/SM\ndragon/SM\ndragonfly/SM\ndragoon/SMDG\ndragster/S\ndrain/SMDRZG\ndrainage/M\ndrainboard/SM\ndrainer/M\ndrainpipe/MS\ndrake/SM\ndram/MS\ndrama/SM\ndramatic/S\ndramatically\ndramatics/M\ndramatist/SM\ndramatization/SM\ndramatize/DSG\ndrank\ndrape/DRSMZG\ndraper/M\ndrapery/SM\ndrastic\ndrastically\ndrat\ndratted\ndraughtboard/S\ndraw/MRZGSJ\ndrawback/MS\ndrawbridge/MS\ndrawer/M\ndrawing/M\ndrawl/SMDG\ndrawn/A\ndrawstring/MS\ndray/MS\ndread/SMDG\ndreadful/PY\ndreadfulness/M\ndreadlocks/M\ndreadnought/MS\ndream/SMDRZG\ndreamboat/MS\ndreamed/U\ndreamer/M\ndreamily\ndreaminess/M\ndreamland/M\ndreamless\ndreamlike\ndreamworld/SM\ndreamy/RPT\ndrear\ndrearily\ndreariness/M\ndreary/RPT\ndredge/DRSMZG\ndredger/M\ndregs/M\ndrench/GDS\ndress/AUGSDM\ndressage/M\ndresser/MS\ndressiness/M\ndressing/SM\ndressmaker/SM\ndressmaking/M\ndressy/TPR\ndrew/A\ndribble/MZGDRS\ndribbler/M\ndriblet/MS\ndrier/M\ndrift/SMDRZG\ndrifter/M\ndriftnet/S\ndriftwood/M\ndrill/SMDRZG\ndriller/M\ndrillmaster/SM\ndrink/SMRBJZG\ndrinkable/U\ndrinker/M\ndrip/MS\ndripped\ndripping/SM\ndrippy/TR\ndrive/RSMZGJ\ndrivel/SZGMDR\ndriveler/M\ndriven\ndriver/M\ndriveshaft/SM\ndriveway/MS\ndrizzle/MGDS\ndrizzly\ndrogue/SM\ndroid/S\ndroll/RPT\ndrollery/SM\ndrollness/M\ndrolly\ndromedary/SM\ndrone/DSMG\ndrool/SMDG\ndroop/GSMD\ndroopiness/M\ndroopy/TPR\ndrop/MS\ndropkick/MS\ndroplet/SM\ndropout/SM\ndropped\ndropper/SM\ndropping/S\ndroppings/M\ndropsical\ndropsy/M\ndross/M\ndrought/SM\ndrove/RSMZ\ndrover/M\ndrown/GSJD\ndrowning/M\ndrowse/MGDS\ndrowsily\ndrowsiness/M\ndrowsy/RTP\ndrub/S\ndrubbed\ndrubber/SM\ndrubbing/MS\ndrudge/MGDS\ndrudgery/M\ndrug/MS\ndrugged\ndruggie/SM\ndrugging\ndruggist/SM\ndruggy\ndrugstore/MS\ndruid/SM\ndruidism/M\ndrum/MS\ndrumbeat/SM\ndrumlin/SM\ndrummed\ndrummer/SM\ndrumming\ndrumstick/SM\ndrunk/STMNR\ndrunkard/MS\ndrunken/PY\ndrunkenness/M\ndrupe/SM\ndruthers/M\ndry/ZTGDRSMY\ndryad/SM\ndryer/SM\ndryness/M\ndrys\ndrywall/M\ndual\ndualism/M\nduality/M\ndub/SM\ndubbed\ndubber/SM\ndubbin/M\ndubbing\ndubiety/M\ndubious/YP\ndubiousness/M\nducal\nducat/SM\nduchess/MS\nduchy/SM\nduck/MDGS\nduckbill/SM\nduckboards\nduckling/SM\nduckpins/M\nduckweed/M\nducky/TRSM\nduct's/K\nduct/CKIFS\nductile\nductility/M\nducting\nductless\ndud/GSMD\ndude/MS\ndudgeon/M\ndue/SM\nduel/MDRJZGS\ndueler/M\nduelist/SM\nduenna/MS\nduet/MS\nduff/MDRZGS\nduffer/M\ndug\ndugout/MS\nduh\nduke/MS\ndukedom/SM\ndulcet\ndulcimer/MS\ndull/DRPTGS\ndullard/SM\ndullness/M\ndully\nduly/U\ndumb/RYPT\ndumbbell/SM\ndumbfound/SDG\ndumbness/M\ndumbo/S\ndumbstruck\ndumbwaiter/SM\ndumdum/MS\ndummy/SM\ndump/MDRZGS\ndumpiness/M\ndumpling/SM\ndumpsite/S\ndumpster/SM\ndumpy/PTR\ndun/SM\ndunce/SM\ndunderhead/MS\ndune/MS\ndung/MDGS\ndungaree/MS\ndungeon/SM\ndunghill/MS\ndunk/MDGS\ndunned\ndunner\ndunnest\ndunning\ndunno\nduo/SM\nduodecimal\nduodena\nduodenal\nduodenum/M\nduopoly/S\ndupe/MZGDRS\nduper/M\nduple\nduplex/MS\nduplicate's\nduplicate/AGNDS\nduplication/AM\nduplicator/MS\nduplicitous\nduplicity/M\ndurability/M\ndurable\ndurably\ndurance/M\nduration/M\nduress/M\nduring\ndurst\ndurum/M\ndusk/M\nduskiness/M\ndusky/RTP\ndust/MDRZGS\ndustbin/SM\ndustcart/S\nduster/M\ndustiness/M\ndustless\ndustman\ndustmen\ndustpan/SM\ndustsheet/S\ndusty/RTP\ndutch\nduteous/Y\ndutiable\ndutiful/YP\ndutifulness/M\nduty/SM\nduvet/SM\ndwarf/SGMD\ndwarfish\ndwarfism/M\ndweeb/SM\ndwell/SJZGR\ndweller/M\ndwelling/M\ndwelt/I\ndwindle/DSG\ndyadic\ndybbuk/SM\ndybbukim\ndye/DRSMZG\ndyeing/A\ndyer/M\ndyestuff/M\ndying/M\ndyke/MS\ndynamic/MS\ndynamical/Y\ndynamics/M\ndynamism/M\ndynamite/MZGDRS\ndynamiter/M\ndynamo/SM\ndynastic\ndynasty/SM\ndysentery/M\ndysfunction/MS\ndysfunctional\ndyslectic/SM\ndyslexia/M\ndyslexic/SM\ndyspepsia/M\ndyspeptic/MS\ndysphagia\ndysprosium/M\ndystonia\ndz\ne'en\ne'er\ne/FDST\neBay/M\neMusic/M\nea\neach\neager/PTRY\neagerness/M\neagle/MS\neaglet/MS\near/SMDY\nearache/SM\nearbud/SM\neardrum/SM\nearful/SM\nearl/MS\nearldom/SM\nearliness/M\nearlobe/SM\nearly/RTP\nearmark/SMDG\nearmuff/SM\nearn/DRZTGJS\nearned/U\nearner/M\nearnest/SMYP\nearnestness/M\nearnings/M\nearphone/MS\nearpiece/S\nearplug/SM\nearring/SM\nearshot/M\nearsplitting\nearth's\nearth/UDYG\nearthbound\nearthen\nearthenware/M\nearthiness/M\nearthling/MS\nearthly/RT\nearthquake/SM\nearths/U\nearthshaking\nearthward/S\nearthwork/MS\nearthworm/MS\nearthy/RTP\nearwax/M\nearwig/SM\nease/EDSM\neasel/SM\neasement/SM\neasily/U\neasiness/UM\neasing\neast/M\neastbound\neasterly/SM\neastern/ZR\neasterner/M\neasternmost\neastward/S\neasy/URTP\neasygoing\neat/ZGBSNR\neatable/SM\neaten/U\neater/M\neatery/SM\neave/MS\neavesdrop/S\neavesdropped\neavesdropper/SM\neavesdropping\nebb/SMDG\nebony/SM\nebullience/M\nebullient/Y\nebullition/M\neccentric/SM\neccentrically\neccentricity/SM\neccl\necclesial\necclesiastic/SM\necclesiastical/Y\nechelon/SM\nechinoderm/SM\necho's\necho/ADG\nechoes/A\nechoic\necholocation/M\nechos\neclair/SM\neclat/M\neclectic/SM\neclectically\neclecticism/M\neclipse/DSMG\necliptic/M\neclogue/SM\necocide/M\necol\necologic\necological/Y\necologist/MS\necology/M\necon\neconometric\neconomic/S\neconomical/UY\neconomics/M\neconomist/SM\neconomize/DRSZG\neconomizer/M\neconomy/SM\necosystem/MS\necotourism/M\necotourist/MS\necru/M\necstasy/SM\necstatic\necstatically\necu/S\necumenical/Y\necumenicism/M\necumenism/M\neczema/M\ned/ACSM\nedamame\neddy/DSMG\nedelweiss/M\nedema/SM\nedge/MZGJDRS\nedger/M\nedgewise\nedgily\nedginess/M\nedging/M\nedgy/RTP\nedibility/M\nedible/SMP\nedibleness/M\nedict/SM\nedification/M\nedifice/SM\nedifier/M\nedify/DRSZGN\nedifying/U\nedit's\nedit/ADGS\neditable\nedited/U\nedition/MS\neditor/SM\neditorial/SMY\neditorialize/DSG\neditorship/M\neduc\neducability/M\neducable/I\neducate/ADSGNV\neducated/U\neducation/AM\neducational/Y\neducationalist/S\neducationist/S\neducations\neducator/MS\neduce/DSGB\nedutainment/M\neek\neel/SM\neerie/RT\neerily\neeriness/M\neff/GSD\nefface/DSLG\neffacement/M\neffect/SMDGV\neffective/IPY\neffectiveness/IM\neffectual/IY\neffectuate/DSG\neffeminacy/M\neffeminate/Y\neffendi/SM\nefferent\neffervesce/GDS\neffervescence/M\neffervescent/Y\neffete/YP\neffeteness/M\nefficacious/Y\nefficacy/IM\nefficiency/IM\nefficient/IY\neffigy/SM\nefflorescence/M\nefflorescent\neffluence/M\neffluent/MS\neffluvia\neffluvium/M\neffort/SM\neffortless/YP\neffortlessness/M\neffrontery/M\neffulgence/M\neffulgent\neffuse/DSGNVX\neffusion/M\neffusive/YP\neffusiveness/M\negad\negalitarian/SM\negalitarianism/M\negg/GSMD\neggbeater/MS\neggcup/SM\negghead/SM\neggnog/M\neggplant/MS\neggshell/SM\neglantine/SM\nego/SM\negocentric/MS\negocentrically\negocentricity/M\negoism/M\negoist/SM\negoistic\negoistical/Y\negomania/M\negomaniac/MS\negotism/M\negotist/SM\negotistic\negotistical/Y\negregious/PY\negregiousness/M\negress/MS\negret/SM\neh\neider/SM\neiderdown/MS\neigenvalue/S\neight/SM\neighteen/MHS\neighteenth/M\neighteenths\neighth/M\neighths\neightieth/M\neightieths\neighty/SMH\neinsteinium/M\neisteddfod/S\neither\nejaculate/GNXDS\nejaculation/M\nejaculatory\neject/SDG\nejection/MS\nejector/SM\neke/DSG\nelaborate/YGNDSPX\nelaborateness/M\nelaboration/M\nelan/M\neland/SM\nelapse/DSG\nelastic/MS\nelastically\nelasticated\nelasticity/M\nelasticize/DSG\nelate/DSGN\nelated/Y\nelation/M\nelbow/SMDG\nelbowroom/M\nelder/SMY\nelderberry/SM\neldercare/M\neldest\neldritch\nelect's\nelect/ASDGV\nelectable\nelection/AMS\nelectioneer/DGS\nelective/MS\nelector/MS\nelectoral/Y\nelectorate/MS\nelectric/S\nelectrical/Y\nelectrician/MS\nelectricity/M\nelectrification/M\nelectrifier/M\nelectrify/ZGNDRS\nelectrocardiogram/MS\nelectrocardiograph/M\nelectrocardiographs\nelectrocardiography/M\nelectrocute/DSXGN\nelectrocution/M\nelectrode/SM\nelectrodynamics\nelectroencephalogram/MS\nelectroencephalograph/M\nelectroencephalographic\nelectroencephalographs\nelectroencephalography/M\nelectrologist/SM\nelectrolysis/M\nelectrolyte/MS\nelectrolytic\nelectromagnet/MS\nelectromagnetic\nelectromagnetically\nelectromagnetism/M\nelectromotive\nelectron/MS\nelectronic/S\nelectronica/M\nelectronically\nelectronics/M\nelectroplate/DSG\nelectroscope/SM\nelectroscopic\nelectroshock/M\nelectrostatic/S\nelectrostatics/M\nelectrotype/MS\neleemosynary\nelegance/IM\nelegant/IY\nelegiac/MS\nelegiacal\nelegy/SM\nelem\nelement/MS\nelemental/Y\nelementary\nelephant/SM\nelephantiasis/M\nelephantine\nelev\nelevate/XDSGN\nelevation/M\nelevator/MS\neleven/SMH\nelevens/S\neleventh/M\nelevenths\nelf/M\nelfin\nelfish\nelicit/SDG\nelicitation/M\nelide/DSG\neligibility/IM\neligible\neliminate/XDSGN\nelimination/M\neliminator/S\nelision/MS\nelite/SM\nelitism/M\nelitist/MS\nelixir/SM\nelk/SM\nell/SM\nellipse/MS\nellipsis/M\nellipsoid/SM\nellipsoidal\nelliptic\nelliptical/Y\nelm/SM\nelocution/M\nelocutionary\nelocutionist/SM\nelodea/SM\nelongate/DSGNX\nelongation/M\nelope/DSGL\nelopement/MS\neloquence/M\neloquent/Y\nelse\nelsewhere\nelucidate/DSGNX\nelucidation/M\nelude/DSG\nelusive/YP\nelusiveness/M\nelver/SM\nelves\nelvish\nem's\nem/S\nemaciate/GNDS\nemaciation/M\nemail/SMDG\nemanate/XDSGN\nemanation/M\nemancipate/DSGN\nemancipation/M\nemancipator/MS\nemasculate/GNDS\nemasculation/M\nembalm/SZGDR\nembalmer/M\nembank/SLGD\nembankment/SM\nembargo/MDG\nembargoes\nembark/AEGDS\nembarkation/EM\nembarkations\nembarrass/GLDS\nembarrassed/U\nembarrassing/Y\nembarrassment/SM\nembassy/SM\nembattled\nembed/S\nembedded\nembedding\nembellish/LGDS\nembellishment/SM\nember/SM\nembezzle/ZGLDRS\nembezzlement/M\nembezzler/M\nembitter/GLDS\nembitterment/M\nemblazon/GDLS\nemblazonment/M\nemblem/SM\nemblematic\nemblematically\nembodiment/EM\nembody/AEGSD\nembolden/DGS\nembolism/MS\nembolization\nemboss/DRSZG\nembosser/M\nembouchure/M\nembower/SGD\nembrace/DSMG\nembraceable\nembrasure/MS\nembrocation/MS\nembroider/SDRZG\nembroiderer/M\nembroidery/SM\nembroil/DGLS\nembroilment/M\nembryo/SM\nembryological\nembryologist/MS\nembryology/M\nembryonic\nemcee/DSM\nemceeing\nemend/SDG\nemendation/MS\nemerald/MS\nemerge/ADSG\nemergence/AM\nemergency/SM\nemergent\nemerita\nemeritus\nemery/M\nemetic/SM\nemf/S\nemigrant/SM\nemigrate/DSXGN\nemigration/M\nemigre/SM\neminence/MS\neminent/Y\nemir/MS\nemirate/MS\nemissary/SM\nemission/SM\nemit/S\nemitted\nemitter/MS\nemitting\nemo/SM\nemoji\nemollient/MS\nemolument/MS\nemote/XDSGNV\nemoticon/SM\nemotion/M\nemotional/UY\nemotionalism/M\nemotionalize/GDS\nemotionless\nemotive/Y\nempathetic\nempathize/DSG\nempathy/M\nemperor/MS\nemphases\nemphasis/M\nemphasize/AGDS\nemphatic/U\nemphatically\nemphysema/M\nempire/SM\nempiric\nempirical/Y\nempiricism/M\nempiricist/SM\nemplacement/SM\nemploy's\nemploy/ADGLS\nemployable/U\nemployee/SM\nemployer/SM\nemployment/UAM\nemployments\nemporium/SM\nempower/SDGL\nempowerment/M\nempress/MS\nemptily\nemptiness/M\nempty/TGPDRSM\nempyrean/M\nemu/SM\nemulate/DSGNVX\nemulation/M\nemulator/SM\nemulsification/M\nemulsifier/M\nemulsify/NDRSZG\nemulsion/MS\nen/SM\nenable/DRSZG\nenabler/M\nenact/ASLDG\nenactment/ASM\nenamel/JSZGMDR\nenameler/M\nenamelware/M\nenamor/SGD\nenc\nencamp/LSGD\nencampment/MS\nencapsulate/XGNDS\nencapsulation/M\nencase/LDSG\nencasement/M\nencephalitic\nencephalitis/M\nenchain/DGS\nenchant/ELDGS\nenchanter/MS\nenchanting/Y\nenchantment/EM\nenchantments\nenchantress/MS\nenchilada/SM\nencipher/SGD\nencircle/DSGL\nencirclement/M\nencl\nenclave/MS\nenclose/GDS\nenclosed/U\nenclosure/SM\nencode/DRSZG\nencoder/M\nencomium/MS\nencompass/GDS\nencore/DSMG\nencounter/GSMD\nencourage/DSLG\nencouragement/SM\nencouraging/Y\nencroach/GLDS\nencroachment/SM\nencrust/DGS\nencrustation/SM\nencrypt/DGS\nencryption\nencumber/EGSD\nencumbered/U\nencumbrance/MS\nency\nencyclical/SM\nencyclopedia/MS\nencyclopedic\nencyst/LSGD\nencystment/M\nend/GVSJMD\nendanger/SGDL\nendangerment/M\nendear/SGLD\nendearing/Y\nendearment/SM\nendeavor/GSMD\nendemic/MS\nendemically\nendgame/S\nending/M\nendive/SM\nendless/PY\nendlessness/M\nendmost\nendocarditis\nendocrine/MS\nendocrinologist/MS\nendocrinology/M\nendogenous/Y\nendometrial\nendometriosis\nendometrium\nendorphin/M\nendorse/LZGDRS\nendorsement/MS\nendorser/M\nendoscope/MS\nendoscopic\nendoscopy/M\nendothelial\nendothermic\nendow/SDLG\nendowment/MS\nendpoint/SM\nendue/DSG\nendurable/U\nendurance/M\nendure/DSBG\nendways\nenema/SM\nenemy/SM\nenergetic\nenergetically\nenergize/ZGDRS\nenergizer/M\nenergy/SM\nenervate/GNDS\nenervation/M\nenfeeble/GDSL\nenfeeblement/M\nenfilade/DSMG\nenfold/SGD\nenforce/LZGDRS\nenforceable/U\nenforced/U\nenforcement/M\nenforcer/M\nenfranchise/EGDSL\nenfranchisement/EM\nengage/EADSG\nengagement/EMS\nengagingly\nengender/SGD\nengine/SM\nengineer/MDGS\nengineering/M\nengorge/LGDS\nengorgement/M\nengram/SM\nengrave/ZGJDRS\nengraver/M\nengraving/M\nengross/GLDS\nengrossment/M\nengulf/SLGD\nengulfment/M\nenhance/LZGDRS\nenhancement/SM\nenigma/SM\nenigmatic\nenigmatically\nenjambment/SM\nenjoin/SGD\nenjoy/GBLSD\nenjoyably\nenjoyment/SM\nenlarge/LZGDRS\nenlargeable\nenlargement/MS\nenlarger/M\nenlighten/SGLD\nenlightened/U\nenlightenment/M\nenlist/ADGSL\nenlistee/SM\nenlistment/AM\nenlistments\nenliven/SLDG\nenlivenment/M\nenmesh/DSGL\nenmeshment/M\nenmity/SM\nennoble/DSGL\nennoblement/M\nennui/M\nenormity/SM\nenormous/PY\nenormousness/M\nenough/M\nenplane/DSG\nenquirer/S\nenquiringly\nenrage/GDS\nenrapture/DSG\nenrich/DSLG\nenrichment/M\nenroll/DLSG\nenrollment/MS\nensconce/DSG\nensemble/SM\nenshrine/GLDS\nenshrinement/M\nenshroud/DGS\nensign/MS\nensilage/M\nenslave/DSGL\nenslavement/M\nensnare/DSLG\nensnarement/M\nensue/DSG\nensure/ZGDRS\nensurer/M\nentail/DSGL\nentailment/M\nentangle/EDSLG\nentanglement/EM\nentanglements\nentente/SM\nenter/ASGD\nenteric\nenteritis/M\nenterprise/MGS\nenterprising/Y\nentertain/ZGDRSL\nentertainer/M\nentertaining/MY\nentertainment/MS\nenthrall/GDSL\nenthrallment/M\nenthrone/GDSL\nenthronement/SM\nenthuse/DSG\nenthusiasm/MS\nenthusiast/MS\nenthusiastic/U\nenthusiastically\nentice/GDSL\nenticement/MS\nenticing/Y\nentire/Y\nentirety/M\nentitle/DSGL\nentitlement/SM\nentity/SM\nentomb/DSGL\nentombment/M\nentomological\nentomologist/MS\nentomology/M\nentourage/SM\nentr'acte\nentrails/M\nentrance/LDSMG\nentrancement/M\nentrancing/Y\nentrant/SM\nentrap/LS\nentrapment/M\nentrapped\nentrapping\nentreat/GSD\nentreating/Y\nentreaty/SM\nentree/MS\nentrench/DSGL\nentrenchment/MS\nentrepreneur/SM\nentrepreneurial\nentrepreneurship\nentropy/M\nentrust/SGD\nentry/ASM\nentryphone/S\nentryway/MS\nentwine/DSG\nenumerable\nenumerate/DSGNX\nenumeration/M\nenumerator/SM\nenunciate/DSGN\nenunciation/M\nenuresis/M\nenvelop/SLDRZG\nenvelope/SM\nenveloper/M\nenvelopment/M\nenvenom/SDG\nenviable/U\nenviably\nenvious/PY\nenviousness/M\nenvironment/MS\nenvironmental/Y\nenvironmentalism/M\nenvironmentalist/SM\nenvirons/M\nenvisage/GDS\nenvision/DGS\nenvoy/SM\nenvy/DSMG\nenvying/Y\nenzymatic\nenzyme/SM\neolian\neon/SM\neosinophil/S\neosinophilic\nepaulet/SM\nepee/MS\nephedrine/M\nephemera/M\nephemeral/Y\nepic/MS\nepicenter/MS\nepicure/SM\nepicurean/MS\nepidemic/SM\nepidemically\nepidemiological\nepidemiologist/SM\nepidemiology/M\nepidermal\nepidermic\nepidermis/MS\nepidural/S\nepiglottis/MS\nepigram/SM\nepigrammatic\nepigraph/M\nepigraphs\nepigraphy/M\nepilepsy/M\nepileptic/SM\nepilogue/MS\nepinephrine/M\nepiphany/SM\nepiscopacy/M\nepiscopal\nepiscopate/M\nepisode/SM\nepisodic\nepisodically\nepistemic\nepistemological\nepistemology\nepistle/SM\nepistolary\nepitaph/M\nepitaphs\nepithelial\nepithelium/M\nepithet/SM\nepitome/SM\nepitomize/GDS\nepoch/M\nepochal\nepochs\neponymous\nepoxy/DSMG\nepsilon/SM\nequability/M\nequable\nequably\nequal/SMDYG\nequality/IM\nequalization/M\nequalize/ZGDRS\nequalizer/M\nequanimity/M\nequate/DSGNBX\nequation/M\nequator/SM\nequatorial\nequerry/SM\nequestrian/SM\nequestrianism/M\nequestrienne/SM\nequidistant/Y\nequilateral/SM\nequilibrium/EM\nequine/SM\nequinoctial\nequinox/MS\nequip/AS\nequipage/MS\nequipment/M\nequipoise/M\nequipped/UA\nequipping/A\nequitable/I\nequitably/I\nequitation/M\nequity/ISM\nequiv\nequivalence/MS\nequivalency/SM\nequivalent/MYS\nequivocal/UY\nequivocalness/M\nequivocate/GNXDS\nequivocation/M\nequivocator/SM\ner/C\nera/SM\neradicable/I\neradicate/DSGN\neradication/M\neradicator/MS\nerase/DRSBZG\neraser/M\nerasure/SM\nerbium/M\nere\nerect/PSGDY\nerectile\nerection/SM\nerectness/M\nerector/MS\nerelong\neremite/MS\nerg/SM\nergo\nergonomic/S\nergonomically\nergonomics/M\nergosterol/M\nergot/M\nermine/SM\nerode/DSG\nerodible\nerogenous\nerosion/M\nerosive\nerotic/S\nerotica/M\nerotically\neroticism/M\nerr/GSD\nerrand/SM\nerrant/I\nerrata/SM\nerratic\nerratically\nerratum/M\nerroneous/Y\nerror/SM\nersatz/MS\nerst\nerstwhile\neruct/SDG\neructation/SM\nerudite/YN\nerudition/M\nerupt/SDGV\neruption/MS\nerysipelas/M\nerythrocyte/SM\nerythromycin\nescalate/CDSGN\nescalation/CM\nescalations\nescalator/MS\nescallop/SGMD\nescalope/S\nescapade/MS\nescape/LMGDS\nescapee/MS\nescapement/SM\nescapism/M\nescapist/MS\nescapologist/S\nescapology\nescargot/MS\nescarole/MS\nescarpment/MS\neschatological\neschatology\neschew/SDG\nescort/SMDG\nescritoire/MS\nescrow/SM\nescudo/SM\nescutcheon/SM\nesophageal\nesophagi\nesophagus/M\nesoteric\nesoterically\nesp\nespadrille/MS\nespalier/MDSG\nespecial/Y\nespionage/M\nesplanade/MS\nespousal/M\nespouse/GDS\nespresso/MS\nesprit/M\nespy/DSG\nesquire/SM\nessay/SMDRZG\nessayer/M\nessayist/SM\nessence/SM\nessential/IMS\nessentially\nestablish/AESDGL\nestablishment/AEM\nestablishments\nestate/SM\nesteem/ESMDG\nester/SM\nestimable/I\nestimate/MGNDSX\nestimation/M\nestimator/SM\nestoppel\nestrange/LDSG\nestrangement/MS\nestrogen/M\nestrous\nestrus/MS\nestuary/SM\neta/SM\netc\netch/DRSZGJ\netcher/M\netching/M\neternal/YP\neternalness/M\neternity/SM\nethane/M\nethanol/M\nether/M\nethereal/Y\nethic/SM\nethical/UY\nethics/M\nethnic/SM\nethnically\nethnicity/M\nethnocentric\nethnocentrism/M\nethnographer/S\nethnographic\nethnographically\nethnography\nethnological/Y\nethnologist/SM\nethnology/M\nethological\nethologist/MS\nethology/M\nethos/M\nethyl/M\nethylene/M\netiolated\netiologic\netiological\netiology/SM\netiquette/M\netude/SM\netymological/Y\netymologist/SM\netymology/SM\neucalypti\neucalyptus/MS\neuchre/DSMG\neuclidean\neugenic/S\neugenically\neugenicist/MS\neugenics/M\neulogist/MS\neulogistic\neulogize/ZGDRS\neulogizer/M\neulogy/SM\neunuch/M\neunuchs\neuphemism/SM\neuphemistic\neuphemistically\neuphonious/Y\neuphony/M\neuphoria/M\neuphoric\neuphorically\neureka\neuro/MS\neuropium/M\neutectic\neuthanasia/M\neuthanize/DSG\neuthenics/M\nevacuate/XDSGN\nevacuation/M\nevacuee/MS\nevade/DRSZG\nevader/M\nevaluate/AGNVDSX\nevaluation/AM\nevanescence/M\nevanescent\nevangelic\nevangelical/SMY\nevangelicalism/M\nevangelism/M\nevangelist/MS\nevangelistic\nevangelize/GDS\nevaporate/GNDS\nevaporation/M\nevaporator/SM\nevasion/SM\nevasive/YP\nevasiveness/M\neve/ASM\neven/MDRYTGSJP\nevenhanded/Y\nevening/M\nevenness/UM\nevensong/M\nevent/SM\neventful/UY\neventfulness/M\neventide/M\neventual/Y\neventuality/SM\neventuate/GDS\never\neverglade/SM\nevergreen/SM\neverlasting/MYS\nevermore\nevery\neverybody/M\neveryday\neveryone/M\neveryplace\neverything/M\neverywhere\nevict/SDG\neviction/MS\nevidence/MGDS\nevident/Y\nevil/MRYTSP\nevildoer/SM\nevildoing/M\neviller\nevillest\nevilness/M\nevince/DSG\neviscerate/DSGN\nevisceration/M\nevocation/MS\nevocative/Y\nevoke/DSG\nevolution/M\nevolutionary\nevolutionist/SM\nevolve/DSG\newe/RSMZ\newer/M\nex/MS\nexabyte/MS\nexacerbate/GNDS\nexacerbation/M\nexact/SPDRYTG\nexacting/Y\nexaction/M\nexactitude/M\nexactness/IM\nexaggerate/XDSGN\nexaggerated/Y\nexaggeration/M\nexaggerator/MS\nexalt/SDG\nexaltation/M\nexam/MS\nexamination/AMS\nexamine/AGDS\nexaminer/MS\nexample/MGDS\nexampled/U\nexasperate/DSGN\nexasperated/Y\nexasperating/Y\nexasperation/M\nexcavate/GNDSX\nexcavation/M\nexcavator/SM\nexceed/GSD\nexceeding/Y\nexcel/S\nexcelled\nexcellence/M\nexcellency/SM\nexcellent/Y\nexcelling\nexcelsior/M\nexcept/GSD\nexception/BSM\nexceptionable/U\nexceptional/UY\nexceptionalism\nexcerpt/MDGS\nexcess/VMS\nexcessive/Y\nexchange/DSMG\nexchangeable\nexchequer/SM\nexcise/XDSMGN\nexcision/M\nexcitability/M\nexcitably\nexcitation/M\nexcite/BDRSLZG\nexcited/Y\nexcitement/SM\nexciter/M\nexciting/Y\nexcl\nexclaim/DGS\nexclamation/SM\nexclamatory\nexclude/GDS\nexclusion/MS\nexclusionary\nexclusive/PMYS\nexclusiveness/M\nexclusivity/M\nexcommunicate/GNDSX\nexcommunication/M\nexcoriate/DSGNX\nexcoriation/M\nexcrement/M\nexcremental\nexcrescence/MS\nexcrescent\nexcreta/M\nexcrete/XGNDS\nexcretion/M\nexcretory\nexcruciating/Y\nexculpate/DSGN\nexculpation/M\nexculpatory\nexcursion/MS\nexcursionist/MS\nexcursive/YP\nexcursiveness/M\nexcusable/I\nexcusably/I\nexcuse/DSBMG\nexcused/U\nexec/MS\nexecrable\nexecrably\nexecrate/DSGN\nexecration/M\nexecute/BXGNVDS\nexecution/ZMR\nexecutioner/M\nexecutive/SM\nexecutor/MS\nexecutrices\nexecutrix/M\nexegeses\nexegesis/M\nexegetic\nexegetical\nexemplar/SM\nexemplary\nexemplification/M\nexemplify/GDSXN\nexempt/SGD\nexemption/SM\nexercise/DRSMZG\nexerciser/M\nexert/SDG\nexertion/MS\nexeunt\nexfoliate/GNDS\nexhalation/MS\nexhale/DSG\nexhaust/GVMDS\nexhaustible/I\nexhaustion/M\nexhaustive/YP\nexhaustiveness/M\nexhibit/GMDS\nexhibition/MS\nexhibitionism/M\nexhibitionist/MS\nexhibitor/SM\nexhilarate/DSGN\nexhilaration/M\nexhort/SDG\nexhortation/MS\nexhumation/MS\nexhume/DSG\nexigence/MS\nexigency/SM\nexigent\nexiguity/M\nexiguous\nexile/DSMG\nexist/SDG\nexistence/MS\nexistent\nexistential/Y\nexistentialism/M\nexistentialist/MS\nexit/MDGS\nexobiology/M\nexodus/MS\nexogenous\nexon\nexonerate/GNDS\nexoneration/M\nexoplanet/MS\nexorbitance/M\nexorbitant/Y\nexorcise/DSG\nexorcism/SM\nexorcist/SM\nexoskeleton/SM\nexosphere/SM\nexothermic\nexotic/SM\nexotica\nexotically\nexoticism/M\nexp\nexpand/BGSD\nexpanse/XMNVS\nexpansible\nexpansion/M\nexpansionary\nexpansionism/M\nexpansionist/MS\nexpansive/YP\nexpansiveness/M\nexpat/S\nexpatiate/GNDS\nexpatiation/M\nexpatriate/DSMGN\nexpatriation/M\nexpect/GSD\nexpectancy/M\nexpectant/Y\nexpectation/SM\nexpectorant/SM\nexpectorate/DSGN\nexpectoration/M\nexpedience/IM\nexpediences\nexpediencies\nexpediency/IM\nexpedient/SMY\nexpedite/DRSZGNX\nexpediter/M\nexpedition/M\nexpeditionary\nexpeditious/PY\nexpeditiousness/M\nexpel/S\nexpelled\nexpelling\nexpend/GSBD\nexpendable/SM\nexpenditure/SM\nexpense/MS\nexpensive/IYP\nexpensiveness/IM\nexperience/IMD\nexperiences\nexperiencing\nexperiential\nexperiment/MDRSZG\nexperimental/Y\nexperimentation/M\nexperimenter/M\nexpert/SPMY\nexpertise/M\nexpertness/M\nexpiate/GNDS\nexpiation/M\nexpiatory\nexpiration/M\nexpire/DSG\nexpired/U\nexpiry/M\nexplain/ADGS\nexplainable\nexplained/U\nexplanation/MS\nexplanatory\nexpletive/MS\nexplicable/I\nexplicate/XGNDS\nexplication/M\nexplicit/PY\nexplicitness/M\nexplode/GDS\nexploit/ZGBMDRS\nexploitation/M\nexploitative\nexploited/U\nexploiter/M\nexploration/MS\nexploratory\nexplore/ZGDRS\nexplored/U\nexplorer/M\nexplosion/SM\nexplosive/SPMY\nexplosiveness/M\nexpo/MS\nexponent/MS\nexponential/Y\nexponentiation\nexport/BSZGMDR\nexportation/M\nexporter/M\nexpose/DSMG\nexposed/U\nexposition/SM\nexpositor/SM\nexpository\nexpostulate/GNXDS\nexpostulation/M\nexposure/MS\nexpound/ZGDRS\nexpounder/M\nexpress/GVMDSY\nexpressed/U\nexpressible/I\nexpression/SM\nexpressionism/M\nexpressionist/SM\nexpressionistic\nexpressionless/Y\nexpressive/PY\nexpressiveness/M\nexpressway/SM\nexpropriate/GNXDS\nexpropriation/M\nexpropriator/SM\nexpulsion/MS\nexpunge/GDS\nexpurgate/DSGNX\nexpurgated/U\nexpurgation/M\nexquisite/YP\nexquisiteness/M\next\nextant\nextemporaneous/PY\nextemporaneousness/M\nextempore\nextemporization/M\nextemporize/GDS\nextend/SZGDRB\nextender/M\nextensible\nextension/SM\nextensional\nextensive/YP\nextensiveness/M\nextent/SM\nextenuate/DSGN\nextenuation/M\nexterior/MS\nexterminate/DSXGN\nextermination/M\nexterminator/MS\nexternal/MYS\nexternalization/SM\nexternalize/DSG\nextinct/GDS\nextinction/MS\nextinguish/ZGBDRS\nextinguishable/I\nextinguisher/M\nextirpate/GNDS\nextirpation/M\nextol/S\nextolled\nextolling\nextort/SGD\nextortion/MRZ\nextortionate/Y\nextortioner/M\nextortionist/MS\nextra/SM\nextracellular\nextract/MDGS\nextraction/SM\nextractor/MS\nextracurricular\nextradite/GNBXDS\nextradition/M\nextrajudicial\nextralegal\nextramarital\nextramural\nextraneous/Y\nextraordinaire\nextraordinarily\nextraordinary\nextrapolate/XGNDS\nextrapolation/M\nextrasensory\nextraterrestrial/MS\nextraterritorial\nextraterritoriality/M\nextravagance/MS\nextravagant/Y\nextravaganza/MS\nextravehicular\nextreme/PMYTRS\nextremeness/M\nextremism/M\nextremist/MS\nextremity/SM\nextricable/I\nextricate/GNDS\nextrication/M\nextrinsic\nextrinsically\nextroversion/M\nextrovert/SMD\nextrude/GDS\nextrusion/SM\nextrusive\nexuberance/M\nexuberant/Y\nexudation/M\nexude/DSG\nexult/SDG\nexultant/Y\nexultation/M\nexurb/SM\nexurban\nexurbanite/SM\nexurbia/M\neye/DSM\neyeball/GMDS\neyebrow/SM\neyedropper/SM\neyeful/SM\neyeglass/MS\neyeing\neyelash/MS\neyeless\neyelet/SM\neyelid/SM\neyeliner/MS\neyeopener/MS\neyeopening\neyepiece/MS\neyesight/M\neyesore/MS\neyestrain/M\neyeteeth\neyetooth/M\neyewash/M\neyewitness/MS\nf/CIAVTR\nfa/M\nfab\nfable/DSM\nfabric/SM\nfabricate/DSGNX\nfabrication/M\nfabricator/SM\nfabulous/Y\nfacade/SM\nface's\nface/ACSDG\nfacecloth/M\nfacecloths\nfaceless\nfacet/SMDG\nfacetious/YP\nfacetiousness/M\nfacial/SMY\nfacile/Y\nfacilitate/GNDS\nfacilitation/M\nfacilitator/MS\nfacility/SM\nfacing/SM\nfacsimile/DSM\nfacsimileing\nfact/MS\nfaction/SM\nfactional\nfactionalism/M\nfactious\nfactitious\nfactoid/SM\nfactor's\nfactor/ASDG\nfactorial/MS\nfactorization\nfactorize/GDS\nfactory/SM\nfactotum/SM\nfactual/Y\nfaculty/SM\nfad/GSMD\nfaddish/P\nfaddist/MS\nfaddy/P\nfade/MS\nfading/U\nfaerie/SM\nfaff/DGS\nfag/SM\nfagged\nfagging\nfaggot/SM\nfagot/SMG\nfaience/M\nfail/MDGJS\nfailing/M\nfaille/M\nfailure/SM\nfain/RT\nfaint/SMDRYTGP\nfainthearted\nfaintness/M\nfair/MRYTGJPS\nfairground/MS\nfairing/M\nfairness/UM\nfairway/SM\nfairy/SM\nfairyland/SM\nfaith/M\nfaithful's\nfaithful/UPY\nfaithfulness/UM\nfaithfuls\nfaithless/PY\nfaithlessness/M\nfaiths\nfajita/SM\nfajitas/M\nfake/MZGDRS\nfaker/M\nfakir/SM\nfalcon/SMRZ\nfalconer/M\nfalconry/M\nfall/MNGS\nfallacious/Y\nfallacy/SM\nfallback\nfallibility/IM\nfallible/P\nfallibleness/M\nfallibly/I\nfalloff/SM\nfallout/M\nfallow/SMDG\nfalse/PRYT\nfalsehood/SM\nfalseness/M\nfalsetto/SM\nfalsie/SM\nfalsifiable\nfalsification/M\nfalsifier/M\nfalsify/DRSZGNX\nfalsity/SM\nfalter/GSJMD\nfaltering/Y\nfame's\nfame/D\nfamilial\nfamiliar/MYS\nfamiliarity/UM\nfamiliarization/M\nfamiliarize/GDS\nfamily/SM\nfamine/SM\nfamish/DSG\nfamous/IY\nfan/SM\nfanatic/SM\nfanatical/Y\nfanaticism/M\nfanboy/SM\nfanciable\nfancier/M\nfanciful/YP\nfancifulness/M\nfancily\nfanciness/M\nfancy/DRSMZTGP\nfancywork/M\nfandango/MS\nfandom\nfanfare/SM\nfang/MDS\nfanlight/SM\nfanned\nfanning\nfanny/SM\nfantail/MS\nfantasia/SM\nfantasist/S\nfantasize/GDS\nfantastic\nfantastical/Y\nfantasy/DSMG\nfanzine/MS\nfar\nfarad/SM\nfaradize/DG\nfaraway\nfarce/SM\nfarcical/Y\nfare/MGDS\nfarewell/SM\nfarina/M\nfarinaceous\nfarm/MDRZGSJ\nfarmer/M\nfarmhand/SM\nfarmhouse/SM\nfarming/M\nfarmland/MS\nfarmstead/MS\nfarmyard/MS\nfaro/M\nfarrago/M\nfarragoes\nfarrier/MS\nfarrow/SMDG\nfarseeing\nfarsighted/P\nfarsightedness/M\nfart/MDGS\nfarther\nfarthermost\nfarthest\nfarthing/SM\nfascia/SM\nfascicle/SM\nfascinate/GNDSX\nfascinating/Y\nfascination/M\nfascism/M\nfascist/MS\nfascistic\nfashion/ZGBMDRS\nfashionable/U\nfashionably/U\nfashioner/M\nfashionista/MS\nfast/MDRTGSP\nfastback/SM\nfastball/SM\nfasten/UAGDS\nfastener/SM\nfastening/MS\nfastidious/PY\nfastidiousness/M\nfastness/MS\nfat/GSPMD\nfatal/Y\nfatalism/M\nfatalist/SM\nfatalistic\nfatalistically\nfatality/SM\nfatback/M\nfate/MS\nfateful/YP\nfatefulness/M\nfathead/MDS\nfather/SGMDY\nfatherhood/M\nfatherland/MS\nfatherless\nfathom/SMDGB\nfathomable/U\nfathomless\nfatigue/MDSG\nfatigues/M\nfatness/M\nfatso/S\nfatten/SDG\nfatter\nfattest\nfattiness/M\nfatty/RSMTP\nfatuity/M\nfatuous/YP\nfatuousness/M\nfatwa/SM\nfaucet/SM\nfault/CSMDG\nfaultfinder/SM\nfaultfinding/M\nfaultily\nfaultiness/M\nfaultless/PY\nfaultlessness/M\nfaulty/PRT\nfaun/MS\nfauna/SM\nfauvism/M\nfauvist/SM\nfaux\nfave/S\nfavor/ESMDG\nfavorable/U\nfavorably/U\nfavorite/SM\nfavoritism/M\nfawn/MDRZGS\nfawner/M\nfax/GMDS\nfay/TSMR\nfaze/GDS\nfazed/U\nfealty/M\nfear/MDGS\nfearful/YP\nfearfulness/M\nfearless/PY\nfearlessness/M\nfearsome\nfeasibility/M\nfeasible/IU\nfeasibly\nfeast/SMDG\nfeat/MS\nfeather/SGMD\nfeatherbedding/M\nfeatherbrained\nfeatherless\nfeatherweight/MS\nfeathery/TR\nfeature/DSMG\nfeatureless\nfebrile\nfecal\nfeces/M\nfeckless/PY\nfecund\nfecundate/GNDS\nfecundation/M\nfecundity/M\nfed/SM\nfederal/SMY\nfederalism/M\nfederalist/MS\nfederalization/M\nfederalize/GDS\nfederate/FXDSGN\nfederation/FM\nfedora/SM\nfee/SM\nfeeble/RTP\nfeebleness/M\nfeebly\nfeed/MRZGSJ\nfeedback/M\nfeedbag/SM\nfeeder/M\nfeeding/M\nfeedlot/SM\nfeel/MRZGSJ\nfeeler/M\nfeelgood\nfeeling/MY\nfeet\nfeign/SDG\nfeigned/U\nfeint/SMDG\nfeisty/TR\nfeldspar/M\nfelicitate/GNXDS\nfelicitation/M\nfelicitous/Y\nfelicity/ISM\nfeline/SM\nfell/MDRZTGS\nfella/S\nfellatio/M\nfellow/SM\nfellowman/M\nfellowmen\nfellowship/MS\nfelon/SM\nfelonious\nfelony/SM\nfelt/MDGS\nfem\nfemale/PSM\nfemaleness/M\nfeminine/SMY\nfemininity/M\nfeminism/M\nfeminist/SM\nfeminize/DSG\nfemoral\nfemur/SM\nfen/SM\nfence/DRSMZG\nfencer/M\nfencing/M\nfend/CDRZGS\nfender/CM\nfenestration/M\nfennel/M\nferal\nferment/FCMS\nfermentation/M\nfermented\nfermenting\nfermium/M\nfern/MS\nferny/RT\nferocious/PY\nferociousness/M\nferocity/M\nferret/GSMD\nferric\nferromagnetic\nferrous\nferrule/MS\nferry/DSMG\nferryboat/SM\nferryman/M\nferrymen\nfertile/I\nfertility/IM\nfertilization/M\nfertilize/DRSZG\nfertilized/U\nfertilizer/M\nferule/SM\nfervency/M\nfervent/Y\nfervid/Y\nfervor/M\nfess/FKGSD\nfest/MRZVS\nfestal\nfester/GMD\nfestival/SM\nfestive/YP\nfestiveness/M\nfestivity/SM\nfestoon/GMDS\nfeta/M\nfetal\nfetch/DRSZG\nfetcher/M\nfetching/Y\nfete/MGDS\nfetid/P\nfetidness/M\nfetish/MS\nfetishism/M\nfetishist/SM\nfetishistic\nfetlock/MS\nfetter's\nfetter/USGD\nfettle/M\nfettuccine/M\nfetus/MS\nfeud/MDGS\nfeudal\nfeudalism/M\nfeudalistic\nfever/SMD\nfeverish/YP\nfeverishness/M\nfew/TPMR\nfewness/M\nfey\nfez/M\nfezzes\nff\nfiance/CM\nfiancee/MS\nfiances\nfiasco/M\nfiascoes\nfiat/MS\nfib/ZSMR\nfibbed\nfibber/SM\nfibbing\nfiber/M\nfiberboard/M\nfiberfill/M\nfiberglass/M\nfibril/SM\nfibrillate/GNDS\nfibrillation/M\nfibrin/M\nfibroid\nfibrosis/M\nfibrous\nfibula/M\nfibulae\nfibular\nfiche/SM\nfichu/SM\nfickle/RPT\nfickleness/M\nfiction/MS\nfictional/Y\nfictionalization/SM\nfictionalize/DSG\nfictitious/Y\nfictive\nficus/M\nfiddle/DRSMZG\nfiddler/M\nfiddlesticks\nfiddly/TR\nfidelity/IM\nfidget/SGMD\nfidgety\nfiduciary/SM\nfie\nfief/MS\nfiefdom/MS\nfield/ISMRZ\nfielded\nfielder/IM\nfielding\nfieldsman\nfieldsmen\nfieldwork/MRZ\nfieldworker/M\nfiend/SM\nfiendish/Y\nfierce/PRYT\nfierceness/M\nfieriness/M\nfiery/RPT\nfiesta/SM\nfife/MZRS\nfifer/M\nfifteen/MHS\nfifteenth/M\nfifteenths\nfifth/MY\nfifths\nfiftieth/M\nfiftieths\nfifty/SMH\nfig/SLM\nfight/SMRZG\nfightback\nfighter/IMS\nfighting/IM\nfigment/MS\nfiguration/FM\nfigurative/Y\nfigure's\nfigure/FEGSD\nfigurehead/SM\nfigurine/MS\nfilament/MS\nfilamentous\nfilbert/MS\nfilch/DSG\nfile's/KC\nfile/CAKGDS\nfilename/S\nfiler/CSM\nfilet\nfilial\nfilibuster/MDRSZG\nfilibusterer/M\nfiligree/DSM\nfiligreeing\nfiling's\nfilings\nfill's\nfill/AIDGS\nfilled/U\nfiller/MS\nfillet/MDGS\nfilling/SM\nfillip/MDGS\nfilly/SM\nfilm/MDGS\nfilminess/M\nfilmmaker/SM\nfilmstrip/MS\nfilmy/TPR\nfilo\nfilter/MDRBSZG\nfiltered/U\nfilterer/M\nfilth/M\nfilthily\nfilthiness/M\nfilthy/RPT\nfiltrate's\nfiltrate/IGNDS\nfiltration/IM\nfin/SMR\nfinagle/DRSZG\nfinagler/M\nfinal/SMY\nfinale/MS\nfinalist/SM\nfinality/M\nfinalization/M\nfinalize/DSG\nfinance's\nfinance/ADSG\nfinancial/Y\nfinancier/MS\nfinancing/M\nfinch/MS\nfind/JMRZGS\nfinder/M\nfinding/M\nfindings/M\nfine's/F\nfine/CAFTGDS\nfinely\nfineness/M\nfinery/AM\nfinespun\nfinesse/DSMG\nfinger/MDGSJ\nfingerboard/SM\nfingering/M\nfingerling/SM\nfingermark/S\nfingernail/SM\nfingerprint/SGMD\nfingertip/MS\nfinial/MS\nfinical\nfinickiness/M\nfinicky/RPT\nfinis/MS\nfinish's\nfinish/ADSG\nfinished/U\nfinisher/MS\nfinite/IY\nfink/MDGS\nfinned\nfinny\nfir/ZGSJMDRH\nfire/MS\nfirearm/SM\nfireball/MS\nfirebomb/MDSJG\nfirebox/MS\nfirebrand/SM\nfirebreak/SM\nfirebrick/SM\nfirebug/SM\nfirecracker/SM\nfiredamp/M\nfirefight/MRSZG\nfirefighter/M\nfirefighting/M\nfirefly/SM\nfireguard/S\nfirehouse/SM\nfirelight/ZMR\nfireman/M\nfiremen\nfireplace/SM\nfireplug/MS\nfirepower/M\nfireproof/DSG\nfirer/M\nfirescreen/S\nfireside/MS\nfirestorm/MS\nfiretrap/MS\nfiretruck/MS\nfirewall/MS\nfirewater/M\nfirewood/M\nfirework/SM\nfirm/MDRYPTGS\nfirmament/SM\nfirmness/M\nfirmware/M\nfirst/SMY\nfirstborn/SM\nfirsthand\nfirth/M\nfirths\nfiscal/MYS\nfish/MDRSZG\nfishbowl/SM\nfishcake/SM\nfisher/M\nfisherman/M\nfishermen\nfishery/SM\nfishhook/SM\nfishily\nfishiness/M\nfishing/M\nfishmonger/MS\nfishnet/SM\nfishpond/MS\nfishtail/DGS\nfishwife/M\nfishwives\nfishy/TRP\nfissile\nfission/BM\nfissure/SM\nfist/MS\nfistfight/MS\nfistful/SM\nfisticuffs/M\nfistula/SM\nfistulous/M\nfit/KAMS\nfitful/YP\nfitfulness/M\nfitly\nfitment/S\nfitness/UM\nfitted/UA\nfitter/MS\nfittest\nfitting/SMY\nfive/MZRS\nfix/ZGBJMDRS\nfixate/GNVDSX\nfixation/M\nfixative/MS\nfixed/Y\nfixer/M\nfixings/M\nfixity/M\nfixture/MS\nfizz/MDSG\nfizzle/DSMG\nfizzy/RT\nfjord/SM\nfl/JDG\nflab/M\nflabbergast/SGD\nflabbily\nflabbiness/M\nflabby/RPT\nflaccid/Y\nflaccidity/M\nflack/SM\nflag/MS\nflagella\nflagellant/S\nflagellate/GNDS\nflagellation/M\nflagellum/M\nflagged\nflagging/U\nflagman/M\nflagmen\nflagon/MS\nflagpole/SM\nflagrance/M\nflagrancy/M\nflagrant/Y\nflagship/SM\nflagstaff/MS\nflagstone/MS\nflail/SGMD\nflair/SM\nflak/M\nflake/DSMG\nflakiness/M\nflaky/TRP\nflamage\nflambe/MS\nflambeed\nflambeing\nflamboyance/M\nflamboyancy/M\nflamboyant/Y\nflame/DRSJMZG\nflamenco/MS\nflameproof/DGS\nflamethrower/SM\nflamingo/MS\nflammability/IM\nflammable/SM\nflan/MS\nflange/MS\nflank/SZGMDR\nflanker/M\nflannel/SGMD\nflannelette/M\nflap/MS\nflapjack/MS\nflapped\nflapper/SM\nflapping\nflare/DSMG\nflareup/SM\nflash/ZTGMDRS\nflashback/SM\nflashbulb/SM\nflashcard/SM\nflashcube/SM\nflasher/M\nflashgun/SM\nflashily\nflashiness/M\nflashing/M\nflashlight/MS\nflashy/RTP\nflask/SM\nflat/MYPS\nflatbed/SM\nflatboat/SM\nflatbread\nflatcar/SM\nflatfeet\nflatfish/MS\nflatfoot/SMD\nflatiron/SM\nflatland/M\nflatlet/S\nflatmate/S\nflatness/M\nflatted\nflatten/SDG\nflatter/SDRZG\nflatterer/M\nflattering/Y\nflattery/M\nflattest\nflatting\nflattish\nflattop/SM\nflatulence/M\nflatulent\nflatus/M\nflatware/M\nflatworm/SM\nflaunt/MDSG\nflaunting/Y\nflavor/MDSGJ\nflavored/U\nflavorful\nflavoring/M\nflavorless\nflavorsome\nflaw/MDGS\nflawless/PY\nflawlessness/M\nflax/MN\nflay/DGS\nflea/MS\nfleabag/SM\nfleabite/S\nfleapit/S\nfleck/SGMD\nfledged/U\nfledgling/MS\nflee/S\nfleece/MZGDRS\nfleecer/M\nfleeciness/M\nfleecy/RTP\nfleeing\nfleet/STGMDRYP\nfleetingly/M\nfleetingness/M\nfleetness/M\nflesh/GMDSY\nfleshly/TR\nfleshpot/MS\nfleshy/RT\nflew\nflex/AMS\nflexed\nflexibility/IM\nflexible/I\nflexibly/I\nflexing\nflexion\nflextime/M\nflibbertigibbet/SM\nflick/SZGMDR\nflicker/GMD\nflier/M\nflight/MS\nflightiness/M\nflightless\nflighty/PTR\nflimflam/SM\nflimflammed\nflimflamming\nflimsily\nflimsiness/M\nflimsy/TRP\nflinch/GMDS\nfling/GM\nflint/SM\nflintlock/SM\nflinty/TR\nflip/MS\nflipflop/S\nflipflopped\nflipflopping\nflippancy/M\nflippant/Y\nflipped\nflipper/MS\nflippest\nflipping\nflippy/S\nflirt/SGMD\nflirtation/MS\nflirtatious/YP\nflirtatiousness/M\nflirty\nflit/MS\nflitted\nflitting\nfloat/SMDRZG\nfloater/M\nflock/SMDG\nflocking/M\nfloe/MS\nflog/S\nflogged\nflogger/SM\nflogging/MS\nflood/SMDRG\nfloodgate/MS\nfloodlight/MDSG\nfloodlit\nfloodplain/MS\nfloodwater/MS\nfloor/SMDG\nfloorboard/MS\nflooring/M\nfloorwalker/SM\nfloozy/SM\nflop/MS\nflophouse/MS\nflopped\nfloppily\nfloppiness/M\nflopping\nfloppy/PRSMT\nflora/SM\nfloral\nflorescence/IM\nflorescent/I\nfloret/SM\nflorid/PY\nfloridness/M\nflorin/SM\nflorist/SM\nfloss/MDSG\nflossy/RT\nflotation/SM\nflotilla/MS\nflotsam/M\nflounce/DSMG\nflouncy\nflounder/MDSG\nflour/SMDG\nflourish/GMDS\nfloury\nflout/SMDRZG\nflouter/M\nflow/MDGS\nflowchart/SM\nflower's\nflower/CSDG\nflowerbed/MS\nfloweriness/M\nflowering/S\nflowerless\nflowerpot/MS\nflowery/PTR\nflown\nflt\nflu/M\nflub/MS\nflubbed\nflubbing\nfluctuate/GNDSX\nfluctuation/M\nflue/MS\nfluency/M\nfluent/Y\nfluff/SMDG\nfluffiness/M\nfluffy/RPT\nfluid/SMY\nfluidity/M\nfluke/SM\nfluky/RT\nflume/SM\nflummox/DSG\nflung\nflunk/SMDG\nflunky/SM\nfluoresce/DSG\nfluorescence/M\nfluorescent\nfluoridate/GNDS\nfluoridation/M\nfluoride/SM\nfluorine/M\nfluorite/M\nfluorocarbon/MS\nfluoroscope/SM\nfluoroscopic\nflurry/GDSM\nflush/MDRSTG\nfluster/MDSG\nflute/DSMG\nfluting/M\nflutist/MS\nflutter/MDSG\nfluttery\nfluvial\nflux/IMS\nfluxed\nfluxing\nfly/ZTGBDRSM\nflyaway\nflyblown\nflyby/M\nflybys\nflycatcher/MS\nflying/M\nflyleaf/M\nflyleaves\nflyover/MS\nflypaper/SM\nflypast/S\nflysheet/S\nflyspeck/GMDS\nflyswatter/MS\nflytrap/S\nflyway/SM\nflyweight/SM\nflywheel/MS\nfoal/MDGS\nfoam/MDGS\nfoaminess/M\nfoamy/RTP\nfob/SM\nfobbed\nfobbing\nfocal/Y\nfocus's\nfocus/ADSG\nfocused/U\nfodder/SM\nfoe/SM\nfog's\nfog/CS\nfogbound\nfogged/C\nfoggily\nfogginess/M\nfogging/C\nfoggy/RTP\nfoghorn/MS\nfogy/SM\nfogyish\nfoible/SM\nfoil/MDGS\nfoist/SDG\nfol\nfold's\nfold/AUSGD\nfoldaway\nfolder/SM\nfoldout/MS\nfoliage/M\nfolic\nfolio/SM\nfolk/MS\nfolklore/M\nfolkloric\nfolklorist/MS\nfolksiness/M\nfolksinger/SM\nfolksinging/M\nfolksy/PTR\nfolktale/MS\nfolkway/MS\nfoll\nfollicle/MS\nfollow/SDRZGJ\nfollower/M\nfollowing/M\nfollowup/S\nfolly/SM\nfoment/SGD\nfomentation/M\nfond/RYTP\nfondant/MS\nfondle/DSG\nfondness/M\nfondue/SM\nfont/MS\nfontanel/MS\nfoo\nfoobar\nfood/MS\nfoodie/SM\nfoodstuff/SM\nfool/MDGS\nfoolery/SM\nfoolhardily\nfoolhardiness/M\nfoolhardy/TPR\nfoolish/YP\nfoolishness/M\nfoolproof\nfoolscap/M\nfoot/MDRZGSJ\nfootage/M\nfootball/MRZGS\nfootballer/M\nfootbridge/SM\nfootfall/MS\nfoothill/MS\nfoothold/MS\nfootie\nfooting/M\nfootless\nfootlights/M\nfootling/MS\nfootlocker/SM\nfootloose\nfootman/M\nfootmen\nfootnote/MGDS\nfootpath/M\nfootpaths\nfootplate/S\nfootprint/SM\nfootrace/MS\nfootrest/MS\nfootsie/SM\nfootslogging\nfootsore\nfootstep/MS\nfootstool/SM\nfootwear/M\nfootwork/M\nfooty\nfop/SM\nfoppery/M\nfoppish/P\nfoppishness/M\nfor/H\nfora\nforage/DRSMZG\nforager/M\nforay/SMDG\nforbade\nforbear/SMG\nforbearance/M\nforbid/S\nforbidden\nforbidding/YS\nforbore\nforborne\nforce/DSMG\nforced/U\nforceful/PY\nforcefulness/M\nforceps/M\nforcible\nforcibly\nford/MDGSB\nfore/MS\nforearm/GSMD\nforebear/MS\nforebode/GJDS\nforeboding/M\nforecast/MRZGS\nforecaster/M\nforecastle/MS\nforeclose/DSG\nforeclosure/MS\nforecourt/SM\nforedoom/DGS\nforefather/MS\nforefeet\nforefinger/SM\nforefoot/M\nforefront/SM\nforego/G\nforegoes\nforegone\nforeground/GMDS\nforehand/MS\nforehead/MS\nforeign/ZRP\nforeigner/M\nforeignness/M\nforeknew\nforeknow/GS\nforeknowledge/M\nforeknown\nforeleg/SM\nforelimb/MS\nforelock/MS\nforeman/M\nforemast/MS\nforemen\nforemost\nforename/MDS\nforenoon/MS\nforensic/MS\nforensically\nforensics/M\nforeordain/GSD\nforepart/MS\nforeperson/SM\nforeplay/M\nforequarter/MS\nforerunner/MS\nforesail/MS\nforesaw\nforesee/RSBZ\nforeseeable/U\nforeseeing\nforeseen/U\nforeseer/M\nforeshadow/GDS\nforeshore/S\nforeshorten/DSG\nforesight/MD\nforesightedness/M\nforeskin/MS\nforest's\nforest/ACGDS\nforestall/SGD\nforestation/ACM\nforester/MS\nforestland/M\nforestry/M\nforetaste/DSMG\nforetell/GS\nforethought/M\nforetold\nforever/M\nforevermore\nforewarn/DSG\nforewent\nforewoman/M\nforewomen\nforeword/MS\nforfeit/GSMD\nforfeiture/SM\nforgather/SDG\nforgave\nforge/DRSMZGVJ\nforger/M\nforgery/SM\nforget/S\nforgetful/YP\nforgetfulness/M\nforgettable/U\nforgetting\nforging/M\nforgivable/U\nforgive/BRSZGP\nforgiven\nforgiveness/M\nforgiver/M\nforgiving/U\nforgo/RZG\nforgoer/M\nforgoes\nforgone\nforgot\nforgotten/U\nfork/MDGS\nforkful/SM\nforklift/MS\nforlorn/Y\nform's\nform/CAIFDGS\nformal/SMY\nformaldehyde/M\nformalin\nformalism/M\nformalist/MS\nformalities\nformality/IM\nformalization/M\nformalize/GDS\nformat/SMV\nformation/CFASM\nformatted/A\nformatting/M\nformed/U\nformer/FIAM\nformerly\nformfitting\nformic\nformidable\nformidably\nformless/PY\nformlessness/M\nformula/MS\nformulaic\nformulate/ADSGNX\nformulated/U\nformulation/AM\nformulator/SM\nfornicate/GNDS\nfornication/M\nfornicator/MS\nforsake/GS\nforsaken\nforsook\nforsooth\nforswear/SG\nforswore\nforsworn\nforsythia/SM\nfort/MS\nforte/SM\nforthcoming/M\nforthright/YP\nforthrightness/M\nforthwith\nfortieth/M\nfortieths\nfortification/M\nfortified/U\nfortifier/M\nfortify/DRSNZGX\nfortissimo\nfortitude/M\nfortnight/MYS\nfortress/MS\nfortuitous/YP\nfortuitousness/M\nfortuity/M\nfortunate/UY\nfortune/MS\nfortuneteller/SM\nfortunetelling/M\nforty/SMH\nforum/SM\nforward/MDRYZTGSP\nforwarder/M\nforwardness/M\nforwent\nfossa\nfossil/SM\nfossilization/M\nfossilize/GDS\nfoster/GSD\nfought\nfoul/MDRYTGSP\nfoulard/M\nfoulmouthed\nfoulness/M\nfound/FSDG\nfoundation/SM\nfounded/U\nfounder/GMDS\nfoundling/SM\nfoundry/SM\nfount/SM\nfountain/SM\nfountainhead/MS\nfour/MHS\nfourfold\nfourposter/SM\nfourscore/M\nfoursome/SM\nfoursquare\nfourteen/SMH\nfourteenth/M\nfourteenths\nfourth/MY\nfourths\nfowl/MDGS\nfox/GMDS\nfoxfire/M\nfoxglove/SM\nfoxhole/MS\nfoxhound/SM\nfoxhunt/GS\nfoxily\nfoxiness/M\nfoxtrot/MS\nfoxtrotted\nfoxtrotting\nfoxy/RTP\nfoyer/SM\nfps\nfr\nfracas/MS\nfrack/SDG\nfractal/SM\nfraction/ISM\nfractional/Y\nfractious/YP\nfractiousness/M\nfracture/MGDS\nfrag/S\nfragile/RT\nfragility/M\nfragment/GMDS\nfragmentary/M\nfragmentation/M\nfragrance/MS\nfragrant/Y\nfrail/RYTP\nfrailness/M\nfrailty/SM\nframe/DRSMZG\nframed/U\nframer/M\nframework/SM\nfranc/SM\nfranchise's\nfranchise/EDSG\nfranchisee/SM\nfranchiser/SM\nfrancium/M\nfrancophone\nfrangibility/M\nfrangible\nfrank/SMDRYTGP\nfrankfurter/MS\nfrankincense/M\nfrankness/M\nfrantic\nfrantically\nfrappe/SM\nfrat/MS\nfraternal/Y\nfraternity/FSM\nfraternization/M\nfraternize/ZGDRS\nfraternizer/M\nfratricidal\nfratricide/MS\nfraud's\nfraud/S\nfraudster/S\nfraudulence/M\nfraudulent/Y\nfraught\nfray's\nfray/CDGS\nfrazzle/MGDS\nfreak/SMDG\nfreakish/YP\nfreakishness/M\nfreaky/RT\nfreckle/DSMG\nfreckly\nfree/YTDRS\nfreebase/MGDS\nfreebie/SM\nfreebooter/SM\nfreeborn\nfreedman/M\nfreedmen\nfreedom/SM\nfreehand\nfreehold/ZMRS\nfreeholder/M\nfreeing\nfreelance/DRSMZG\nfreelancer/M\nfreeload/SDRZG\nfreeloader/M\nfreeman/M\nfreemasonry\nfreemen\nfreephone\nfreesia/S\nfreestanding\nfreestone/SM\nfreestyle/SM\nfreethinker/SM\nfreethinking/M\nfreeware/M\nfreeway/MS\nfreewheel/DGS\nfreewill\nfreezable\nfreeze's\nfreeze/UAGS\nfreezer/MS\nfreezing's\nfreight/MDRZGS\nfreighter/M\nfrench\nfrenetic\nfrenetically\nfrenzied/Y\nfrenzy/DSM\nfreq\nfrequencies\nfrequency/IM\nfrequent/DRYSZTG\nfrequented/U\nfrequenter/M\nfresco/M\nfrescoes\nfresh/PNRYXZT\nfreshen/ZGDR\nfreshener/M\nfreshet/MS\nfreshman/M\nfreshmen\nfreshness/M\nfreshwater/M\nfret/MS\nfretful/YP\nfretfulness/M\nfretsaw/MS\nfretted\nfretting\nfretwork/M\nfriable\nfriar/SM\nfriary/SM\nfricassee/DSM\nfricasseeing\nfricative/SM\nfriction/SM\nfrictional\nfridge/SM\nfriedcake/MS\nfriend's\nfriend/US\nfriendless\nfriendlies\nfriendliness/UM\nfriendly's\nfriendly/UPTR\nfriendship/MS\nfrieze/SM\nfrig/S\nfrigate/MS\nfrigged\nfrigging\nfright/SXGMDN\nfrighten/DG\nfrightening/Y\nfrightful/PY\nfrightfulness/M\nfrigid/YP\nfrigidity/M\nfrigidness/M\nfrill/SMD\nfrilly/TR\nfringe's\nfringe/IDSG\nfrippery/SM\nfrisk/SDG\nfriskily\nfriskiness/M\nfrisky/TRP\nfrisson/S\nfritter/MDSG\nfritz/M\nfrivolity/SM\nfrivolous/PY\nfrivolousness/M\nfrizz/MDSYG\nfrizzle/MGDS\nfrizzy/TR\nfro\nfrock's\nfrock/CUS\nfrog/MS\nfrogging/S\nfrogman/M\nfrogmarch/GDS\nfrogmen\nfrogspawn\nfrolic/SM\nfrolicked\nfrolicker/SM\nfrolicking\nfrolicsome\nfrom\nfrond/SM\nfront's\nfront/FSDG\nfrontage/MS\nfrontal/Y\nfrontbench/ZRS\nfrontier/MS\nfrontiersman/M\nfrontiersmen\nfrontierswoman\nfrontierswomen\nfrontispiece/MS\nfrontward/S\nfrosh/M\nfrost's\nfrost/CSDG\nfrostbit\nfrostbite/MGS\nfrostbitten\nfrostily\nfrostiness/M\nfrosting/M\nfrosty/TPR\nfroth/MDG\nfrothiness/M\nfroths\nfrothy/TPR\nfroufrou/M\nfroward/P\nfrowardness/M\nfrown/SMDG\nfrowzily\nfrowziness/M\nfrowzy/TPR\nfroze/AU\nfrozen/UA\nfructify/DSG\nfructose/M\nfrugal/Y\nfrugality/M\nfruit/SMDG\nfruitcake/MS\nfruiterer/S\nfruitful/YP\nfruitfulness/M\nfruitiness/M\nfruition/M\nfruitless/PY\nfruitlessness/M\nfruity/TPR\nfrump/SM\nfrumpish\nfrumpy/TR\nfrustrate/GNXDS\nfrustrating/Y\nfrustration/M\nfrustum/MS\nfry/GDSM\nfryer/SM\nft\nftp/ZGS\nfuchsia/MS\nfuck/SMGDRZ!\nfucker/M!\nfuckhead/S!\nfuddle/DSMG\nfudge/DSMG\nfuehrer/MS\nfuel's\nfuel/ADGS\nfug\nfugal\nfuggy\nfugitive/MS\nfugue/SM\nfuhrer/SM\nfulcrum/MS\nfulfill/LDGS\nfulfilled/U\nfulfilling/U\nfulfillment/M\nfull/MDRZTGSP\nfullback/MS\nfuller/M\nfullness/M\nfully\nfulminate/DSXGN\nfulmination/M\nfulsome/PY\nfulsomeness/M\nfum/S\nfumble/DRSMZG\nfumbler/M\nfumbling/Y\nfume/MGDS\nfumigant/MS\nfumigate/GNDS\nfumigation/M\nfumigator/SM\nfumy/RT\nfun/M\nfunction/MDGS\nfunctional/Y\nfunctionalism\nfunctionalist/S\nfunctionality/S\nfunctionary/SM\nfund/AMDGS\nfundamental/SMY\nfundamentalism/M\nfundamentalist/SM\nfunded/U\nfunding/M\nfundraiser/MS\nfundraising\nfuneral/MS\nfunerary\nfunereal/Y\nfunfair/S\nfungal\nfungi\nfungible/MS\nfungicidal\nfungicide/MS\nfungoid\nfungous\nfungus/M\nfunicular/SM\nfunk/MDGS\nfunkiness/M\nfunky/PRT\nfunnel/MDGS\nfunner\nfunnest\nfunnily\nfunniness/M\nfunny/TPRSM\nfunnyman/M\nfunnymen\nfur/SM\nfurbelow/M\nfurbish/ADSG\nfurious/Y\nfurl's\nfurl/UDGS\nfurlong/SM\nfurlough/GMD\nfurloughs\nfurn\nfurnace/SM\nfurnish/ADSG\nfurnished/U\nfurnishings/M\nfurniture/M\nfuror/SM\nfurred\nfurrier/M\nfurriness/M\nfurring/M\nfurrow/MDSG\nfurry/ZTRP\nfurther/SGD\nfurtherance/M\nfurthermore\nfurthermost\nfurthest\nfurtive/YP\nfurtiveness/M\nfury/SM\nfurze/M\nfuse's/A\nfuse/CAIFGDS\nfusee/SM\nfuselage/SM\nfusibility/M\nfusible\nfusilier/SM\nfusillade/MS\nfusion/IFKSM\nfuss/MDSG\nfussbudget/MS\nfussily\nfussiness/M\nfusspot/SM\nfussy/TRP\nfustian/M\nfustiness/M\nfusty/TRP\nfut\nfutile/Y\nfutility/M\nfuton/SM\nfuture/MS\nfuturism/M\nfuturist/MS\nfuturistic\nfuturity/SM\nfuturologist/MS\nfuturology/M\nfutz/DSG\nfuzz/MDSG\nfuzzball/S\nfuzzily\nfuzziness/M\nfuzzy/PTR\nfwd\nfwy\ng/SNXVB\ngab/SM\ngabardine/SM\ngabbed\ngabbiness/M\ngabbing\ngabble/DSMG\ngabby/RTP\ngaberdine/SM\ngabfest/MS\ngable/DSM\ngad/S\ngadabout/SM\ngadded\ngadder/SM\ngadding\ngadfly/SM\ngadget/SM\ngadgetry/M\ngadolinium/M\ngaff/MDRZGS\ngaffe/SM\ngaffer/M\ngag/SM\ngaga\ngagged\ngagging\ngaggle/SM\ngaiety/M\ngaily\ngain's\ngain/ADGS\ngainer/SM\ngainful/Y\ngainsaid\ngainsay/ZGRS\ngainsayer/M\ngait/MRZS\ngaiter/M\ngal/SM\ngala/MS\ngalactic\ngalaxy/SM\ngale's\ngale/AS\ngalena/M\ngall/MDGS\ngallant/SMY\ngallantry/M\ngallbladder/MS\ngalleon/SM\ngalleria/MS\ngallery/SM\ngalley/SM\ngallimaufry/SM\ngallium/M\ngallivant/GSD\ngallon/SM\ngallop/SMDG\ngallows/M\ngallstone/MS\ngaloot/SM\ngalore\ngalosh/MS\ngalumph/DG\ngalumphs\ngalvanic\ngalvanism/M\ngalvanization/M\ngalvanize/DSG\ngalvanometer/MS\ngambit/SM\ngamble/DRSMZG\ngambler/M\ngambling/M\ngambol/SMDG\ngame/MYTGDRSP\ngamecock/MS\ngamekeeper/MS\ngameness/M\ngamesmanship/M\ngamester/MS\ngamete/SM\ngametic\ngamin/SM\ngamine/SM\ngaminess/M\ngaming/M\ngamma/SM\ngammon/M\ngammy\ngamut/SM\ngamy/RTP\ngander/SM\ngang/MDGS\ngangbusters/M\ngangland/M\nganglia\ngangling\nganglion/M\nganglionic\ngangplank/SM\ngangrene/DSMG\ngangrenous\ngangsta/S\ngangster/SM\ngangway/MS\nganja\ngannet/SM\ngantlet/MS\ngantry/SM\ngap/GSMD\ngape/MS\ngar/SLM\ngarage/DSMG\ngarb/MDGS\ngarbage/M\ngarbageman\ngarbanzo/SM\ngarble/DSG\ngarcon/SM\ngarden/SZGMDR\ngardener/M\ngardenia/MS\ngardening/M\ngarfish/MS\ngargantuan\ngargle/DSMG\ngargoyle/SM\ngarish/PY\ngarishness/M\ngarland/MDGS\ngarlic/M\ngarlicky\ngarment/MS\ngarner/SGD\ngarnet/SM\ngarnish/GLMDS\ngarnishee/DSM\ngarnisheeing\ngarnishment/SM\ngarret/SM\ngarrison/MDSG\ngarrote/MZGDRS\ngarroter/M\ngarrulity/M\ngarrulous/PY\ngarrulousness/M\ngarter/SM\ngas's\ngas/CS\ngasbag/SM\ngaseous\ngash/MDSG\ngasholder/S\ngasket/SM\ngaslight/MS\ngasman\ngasmen\ngasohol/M\ngasoline/M\ngasometer/S\ngasp/MDGS\ngassed/C\ngasses\ngassing/C\ngassy/RT\ngastric\ngastritis/M\ngastroenteritis/M\ngastrointestinal\ngastronome/S\ngastronomic\ngastronomical/Y\ngastronomy/M\ngastropod/SM\ngasworks/M\ngate/MGDS\ngateau\ngateaux\ngatecrash/DRSZG\ngatecrasher/M\ngatehouse/SM\ngatekeeper/MS\ngatepost/MS\ngateway/MS\ngather/SJZGMDR\ngatherer/M\ngathering/M\ngator/SM\ngauche/RPYT\ngaucheness/M\ngaucherie/M\ngaucho/SM\ngaudily\ngaudiness/M\ngaudy/RPT\ngauge/DSMG\ngaunt/RPT\ngauntlet/MS\ngauntness/M\ngauze/M\ngauziness/M\ngauzy/RPT\ngave\ngavel/SM\ngavotte/MS\ngawd\ngawk/DGS\ngawkily\ngawkiness/M\ngawky/RPT\ngawp/DGS\ngay/TSPMR\ngayness/M\ngaze/MZGDRS\ngazebo/SM\ngazelle/MS\ngazer/M\ngazette/MGDS\ngazetteer/MS\ngazillion/S\ngazpacho/M\ngazump/DGS\ngear/MDGS\ngearbox/MS\ngearing/M\ngearshift/MS\ngearwheel/SM\ngecko/SM\ngeddit\ngee/DS\ngeeing\ngeek/MS\ngeeky/RT\ngeese\ngeezer/MS\ngeisha/M\ngel/SM\ngelatin/M\ngelatinous\ngelcap/M\ngeld/DJGS\ngelding/M\ngelid\ngelignite/M\ngelled\ngelling\ngem/SM\ngemological\ngemologist/MS\ngemology/M\ngemstone/MS\ngendarme/MS\ngender/MDS\ngene/MS\ngenealogical/Y\ngenealogist/MS\ngenealogy/SM\ngenera\ngeneral/SMY\ngeneralissimo/MS\ngeneralist/MS\ngenerality/SM\ngeneralization/MS\ngeneralize/GDS\ngeneralship/M\ngenerate/CAVNGSD\ngeneration/ACM\ngenerational\ngenerations\ngenerator/SM\ngeneric/SM\ngenerically\ngenerosity/SM\ngenerous/PY\ngenerousness/M\ngenes/S\ngenesis/M\ngenetic/S\ngenetically\ngeneticist/MS\ngenetics/M\ngenial/FY\ngeniality/FM\ngeniculate\ngenie/SM\ngenii\ngenital/FY\ngenitalia/M\ngenitals/M\ngenitive/MS\ngenitourinary\ngenius/MS\ngenned\ngenning\ngenocidal\ngenocide/MS\ngenome/MS\ngenomics\ngenre/SM\ngent/AMS\ngenteel/YP\ngenteelness/M\ngentian/SM\ngentile/SM\ngentility/M\ngentle/TGDRSP\ngentlefolk/MS\ngentlefolks/M\ngentleman/MY\ngentlemanly/U\ngentlemen\ngentleness/M\ngentlewoman/M\ngentlewomen\ngently\ngentrification/M\ngentrify/DSGN\ngentry/SM\ngenuflect/DGS\ngenuflection/MS\ngenuine/PY\ngenuineness/M\ngenus/M\ngeocache/DSG\ngeocentric\ngeocentrically\ngeochemistry/M\ngeode/SM\ngeodesic/SM\ngeodesy/M\ngeodetic\ngeoengineering\ngeog\ngeographer/SM\ngeographic\ngeographical/Y\ngeography/SM\ngeologic\ngeological/Y\ngeologist/MS\ngeology/SM\ngeom\ngeomagnetic\ngeomagnetism/M\ngeometer\ngeometric\ngeometrical/Y\ngeometry/SM\ngeophysical\ngeophysicist/SM\ngeophysics/M\ngeopolitical\ngeopolitics/M\ngeostationary\ngeosynchronous\ngeosyncline/MS\ngeothermal\ngeothermic\ngeranium/MS\ngerbil/MS\ngeriatric/S\ngeriatrician/S\ngeriatrics/M\ngerm/MS\ngermane\ngermanium/M\ngermicidal\ngermicide/MS\ngerminal/M\ngerminate/GNDS\ngermination/M\ngerontological\ngerontologist/MS\ngerontology/M\ngerrymander/GMDS\ngerrymandering/M\ngerund/MS\ngestalt/S\ngestapo/MS\ngestate/GNDS\ngestation/M\ngestational\ngesticulate/DSGNX\ngesticulation/M\ngestural\ngesture/MGDS\ngesundheit\nget/S\ngetaway/SM\ngetting\ngetup/M\ngewgaw/SM\ngeyser/SM\nghastliness/M\nghastly/TPR\nghat/MS\nghee\ngherkin/MS\nghetto/SM\nghettoize/GDS\nghost/SMDYG\nghostliness/M\nghostly/RTP\nghostwrite/ZGRS\nghostwriter/M\nghostwritten\nghostwrote\nghoul/SM\nghoulish/YP\nghoulishness/M\ngiant/SM\ngiantess/MS\ngibber/GDS\ngibberish/M\ngibbet/GMDS\ngibbon/MS\ngibbous\ngibe/MGDS\ngiblet/SM\ngiddily\ngiddiness/M\ngiddy/RTP\ngift/MDGS\ngig/SM\ngigabit/SM\ngigabyte/MS\ngigahertz/M\ngigantic\ngigantically\ngigapixel/MS\ngigawatt/SM\ngigged\ngigging\ngiggle/DRSMZG\ngiggler/M\ngiggly/RT\ngigolo/SM\ngild/MDRZGS\ngilder/M\ngilding/M\ngill/MS\ngillie/S\ngillion/S\ngilt/MS\ngimbals/M\ngimcrack/SM\ngimcrackery/M\ngimlet/GSMD\ngimme/SM\ngimmick/MS\ngimmickry/M\ngimmicky\ngimp/MDGS\ngimpy\ngin/SM\nginger/GSMDY\ngingerbread/M\ngingersnap/SM\ngingery\ngingham/M\ngingivitis/M\nginkgo/M\nginkgoes\nginned\nginning\nginormous\nginseng/M\ngiraffe/MS\ngird/DRZGS\ngirder/M\ngirdle/DSMG\ngirl/MS\ngirlfriend/MS\ngirlhood/SM\ngirlish/YP\ngirlishness/M\ngirly\ngiro/S\ngirt/MDGS\ngirth/M\ngirths\ngist/M\ngit/S\ngite/S\ngive/ZGJRS\ngiveaway/MS\ngiveback/MS\ngiven/SM\ngiver/M\ngizmo/SM\ngizzard/MS\nglace/S\nglaceed\nglaceing\nglacial/Y\nglaciate/XGNDS\nglaciation/M\nglacier/MS\nglad/MYSP\ngladden/GDS\ngladder\ngladdest\nglade/SM\ngladiator/SM\ngladiatorial\ngladiola/SM\ngladioli\ngladiolus/M\ngladness/M\ngladsome\nglam\nglamorization/M\nglamorize/DSG\nglamorous/Y\nglamour/GMDS\nglance/DSMG\ngland/SM\nglandes\nglandular\nglans/M\nglare/DSMG\nglaring/Y\nglasnost/M\nglass/MDSG\nglassblower/MS\nglassblowing/M\nglassful/SM\nglasshouse/S\nglassily\nglassiness/M\nglassware/M\nglassy/RTP\nglaucoma/M\nglaze/DSMG\nglazier/SM\nglazing/M\ngleam/SMDGJ\nglean/SDRZGJ\ngleaner/M\ngleanings/M\nglee/M\ngleeful/YP\ngleefulness/M\nglen/MS\nglenohumeral\nglenoid\nglib/YP\nglibber\nglibbest\nglibness/M\nglide/DRSMZG\nglider/M\ngliding/M\nglimmer/MDGJS\nglimmering/M\nglimpse/MGDS\nglint/SMDG\nglissandi\nglissando/M\nglisten/MDSG\nglister/DSG\nglitch/GMDS\nglitter/MDSG\nglitterati\nglittery\nglitz/M\nglitzy/TR\ngloaming/SM\ngloat/SMDG\ngloating/Y\nglob/MDGS\nglobal/Y\nglobalism/M\nglobalist/MS\nglobalization/M\nglobalize/GDS\nglobe/SM\nglobetrotter/MS\nglobetrotting\nglobular\nglobule/MS\nglobulin/M\nglockenspiel/SM\ngloom/M\ngloomily\ngloominess/M\ngloomy/TRP\nglop/M\ngloppy\nglorification/M\nglorify/GDSN\nglorious/IY\nglory/DSMG\ngloss/MDSG\nglossary/SM\nglossily\nglossiness/M\nglossolalia/M\nglossy/PTRSM\nglottal\nglottis/MS\nglove/DSMG\nglow/MDRZGS\nglower/GMD\nglowing/Y\nglowworm/MS\nglucagon\nglucose/M\nglue/MGDS\nglued/U\ngluey\ngluier\ngluiest\nglum/YP\nglummer\nglummest\nglumness/M\nglut/MNS\ngluten/M\nglutenous\nglutinous/Y\nglutted\nglutting\nglutton/MS\ngluttonous/Y\ngluttony/M\nglycerin/M\nglycerol/M\nglycogen/M\nglyph\ngm\ngnarl/SMDG\ngnarly/TR\ngnash/MDSG\ngnat/MS\ngnaw/DGS\ngneiss/M\ngnocchi\ngnome/SM\ngnomic\ngnomish\ngnu/SM\ngo/JMRHZG\ngoad/MDGS\ngoal/MS\ngoalie/SM\ngoalkeeper/MS\ngoalkeeping/M\ngoalless\ngoalmouth\ngoalmouths\ngoalpost/MS\ngoalscorer/S\ngoaltender/MS\ngoat/MS\ngoatee/SM\ngoatherd/MS\ngoatskin/MS\ngob/SM\ngobbed\ngobbet/SM\ngobbing\ngobble/DRSMZG\ngobbledygook/M\ngobbler/M\ngoblet/SM\ngoblin/SM\ngobsmacked\ngobstopper/S\ngod/SM\ngodawful\ngodchild/M\ngodchildren/M\ngoddammit\ngoddamn/D\ngoddaughter/MS\ngoddess/MS\ngodfather/SM\ngodforsaken\ngodhead/M\ngodhood/M\ngodless/PY\ngodlessness/M\ngodlike\ngodliness/UM\ngodly/URTP\ngodmother/SM\ngodparent/SM\ngodsend/SM\ngodson/SM\ngodspeed\ngoer/M\ngoes\ngofer/SM\ngoggle/DSMG\ngoggles/M\ngoing/M\ngoiter/SM\ngold/MNS\ngoldbrick/ZGSMDR\ngoldbricker/M\ngolden/TR\ngoldenrod/M\ngoldfield/S\ngoldfinch/MS\ngoldfish/MS\ngoldmine/SM\ngoldsmith/M\ngoldsmiths\ngolf/MDRZGS\ngolfer/M\ngolliwog/S\ngolly/SM\ngonad/SM\ngonadal\ngondola/MS\ngondolier/SM\ngone/ZR\ngoner/M\ngong/MDGS\ngonk/S\ngonna\ngonorrhea/M\ngonorrheal\ngonzo\ngoo/M\ngoober/SM\ngood/MYSP\ngoodbye/MS\ngoodhearted\ngoodish\ngoodly/TR\ngoodness/M\ngoodnight\ngoods/M\ngoodwill/M\ngoody/SM\ngooey\ngoof/MDGS\ngoofball/SM\ngoofiness/M\ngoofy/RPT\ngoogle/DSMG\ngoogly/S\ngooier\ngooiest\ngook/MS\ngoon/MS\ngoop/M\ngoose/DSMG\ngooseberry/SM\ngoosebumps/M\ngoosestep/S\ngoosestepped\ngoosestepping\ngopher/SM\ngore/MGDS\ngorge's\ngorge/EDSG\ngorgeous/YP\ngorgeousness/M\ngorgon/SM\ngorilla/MS\ngorily\ngoriness/M\ngormandize/DRSZG\ngormandizer/M\ngormless\ngorp/MS\ngorse/M\ngory/RTP\ngosh\ngoshawk/MS\ngosling/SM\ngospel/MS\ngossamer/M\ngossip/MDRZGS\ngossiper/M\ngossipy\ngot\ngotcha/S\ngoths\ngotta\ngotten\ngouache/S\ngouge/DRSMZG\ngouger/M\ngoulash/MS\ngourd/SM\ngourde/MS\ngourmand/SM\ngourmet/SM\ngout/M\ngouty/TR\ngov\ngovern/DGSBL\ngovernable/U\ngovernance/M\ngoverned/U\ngoverness/MS\ngovernment/MS\ngovernmental\ngovernor/SM\ngovernorship/M\ngovt\ngown/MDGS\ngr\ngrab/MS\ngrabbed\ngrabber/MS\ngrabbing\ngrabby/TR\ngrace/EDSMG\ngraceful/EPY\ngracefulness/EM\ngraceless/PY\ngracelessness/M\ngracious/UY\ngraciousness/M\ngrackle/MS\ngrad/MRZSB\ngradate/XGNDS\ngradation/CM\ngrade's\ngrade/CADSG\ngraded/U\ngrader/M\ngradient/MS\ngradual/PY\ngradualism/M\ngradualness/M\ngraduate/XMGNDS\ngraduation/M\ngraffiti\ngraffito/M\ngraft/SMDRZG\ngrafter/M\ngraham/S\ngrail\ngrain/ISMD\ngraininess/M\ngrainy/PTR\ngram/KMS\ngrammar/MS\ngrammarian/SM\ngrammatical/UY\ngramophone/MS\ngrampus/MS\ngran/S\ngranary/SM\ngrand/SMRYPT\ngrandam/MS\ngrandaunt/MS\ngrandchild/M\ngrandchildren/M\ngranddad/SM\ngranddaddy/SM\ngranddaughter/SM\ngrandee/MS\ngrandeur/M\ngrandfather/GMDYS\ngrandiloquence/M\ngrandiloquent\ngrandiose/Y\ngrandiosity/M\ngrandma/MS\ngrandmother/MYS\ngrandnephew/MS\ngrandness/M\ngrandniece/MS\ngrandpa/MS\ngrandparent/MS\ngrandson/MS\ngrandstand/SGMD\ngranduncle/SM\ngrange/SM\ngranite/M\ngranitic\ngranny/SM\ngranola/M\ngrant/SMDRZG\ngrantee/MS\ngranter/M\ngrantsmanship/M\ngranular\ngranularity/M\ngranulate/GNDS\ngranulation/M\ngranule/MS\ngrape/SM\ngrapefruit/MS\ngrapeshot/M\ngrapevine/SM\ngraph/MDG\ngraphic/MS\ngraphical/Y\ngraphite/M\ngraphologist/MS\ngraphology/M\ngraphs\ngrapnel/MS\ngrapple/MGDS\ngrasp/SMDBG\ngrass/MDSG\ngrasshopper/MS\ngrassland/MS\ngrassroots\ngrassy/TR\ngrate/DRSMZGJ\ngrateful/UYP\ngratefulness/UM\ngrater/M\ngratification/M\ngratify/GNXDS\ngratifying/Y\ngratin/S\ngrating/MY\ngratis\ngratitude/IM\ngratuitous/YP\ngratuitousness/M\ngratuity/SM\ngravamen/MS\ngrave/DRSMYTGP\ngravedigger/SM\ngravel/SGMDY\ngraven\ngraveness/M\ngraveside/MS\ngravestone/SM\ngraveyard/MS\ngravid\ngravimeter/MS\ngravitas\ngravitate/GNDS\ngravitation/M\ngravitational\ngravity/M\ngravy/SM\ngray/MDRTGSP\ngraybeard/SM\ngrayish\ngrayness/M\ngraze/DRSMZG\ngrazer/M\ngrease/DRSMZG\ngreasepaint/M\ngreasily\ngreasiness/M\ngreasy/PTR\ngreat/SMRYPT\ngreatcoat/SM\ngreathearted\ngreatness/M\ngrebe/SM\ngreed/M\ngreedily\ngreediness/M\ngreedy/PTR\ngreen/GPSMDRYT\ngreenback/MS\ngreenbelt/MS\ngreenery/M\ngreenfield\ngreenfly/S\ngreengage/MS\ngreengrocer/SM\ngreenhorn/SM\ngreenhouse/SM\ngreenish\ngreenmail/M\ngreenness/M\ngreenroom/SM\ngreensward/M\ngreenwood/M\ngreet/ZGJSDR\ngreeter/M\ngreeting/M\ngregarious/PY\ngregariousness/M\ngremlin/SM\ngrenade/SM\ngrenadier/MS\ngrenadine/M\ngrep/S\ngrepped\ngrepping\ngrew/A\ngreyhound/SM\ngribble/S\ngrid/MS\ngriddle/SM\ngriddlecake/SM\ngridiron/SM\ngridlock/SMD\ngrief/SM\ngrievance/MS\ngrieve/ZGDRS\ngriever/M\ngrievous/PY\ngrievousness/M\ngriffin/SM\ngriffon/SM\ngrill/SGMDJ\ngrille/MS\ngrim/DYPG\ngrimace/DSMG\ngrime/SM\ngriminess/M\ngrimmer\ngrimmest\ngrimness/M\ngrimy/TRP\ngrin/MS\ngrind/SZGMRJ\ngrinder/M\ngrindstone/MS\ngringo/MS\ngrinned\ngrinning\ngrip/MDRSZG\ngripe/SM\ngriper/M\ngrippe/MZGDR\ngripper/M\ngrisliness/M\ngrisly/RTP\ngrist/MY\ngristle/M\ngristmill/MS\ngrit/MS\ngrits/M\ngritted\ngritter/SM\ngrittiness/M\ngritting\ngritty/RTP\ngrizzle/DSG\ngrizzly/TRSM\ngroan/SGMD\ngroat/SM\ngrocer/MS\ngrocery/SM\ngrog/M\ngroggily\ngrogginess/M\ngroggy/PRT\ngroin/SM\ngrok/S\ngrokked\ngrokking\ngrommet/SM\ngroom/SZGMDR\ngroomer/M\ngrooming/M\ngroomsman/M\ngroomsmen\ngroove/MGDS\ngroovy/RT\ngrope/DRSMZG\ngroper/M\ngrosbeak/MS\ngrosgrain/M\ngross/PTGMDRSY\ngrossness/M\ngrotesque/SPMY\ngrotesqueness/M\ngrotto/M\ngrottoes\ngrotty/TR\ngrouch/GMDS\ngrouchily\ngrouchiness/M\ngrouchy/RTP\nground/ZGMDRJS\ngroundbreaking/MS\ngroundcloth\ngroundcloths\ngrounder/M\ngroundhog/MS\ngrounding/M\ngroundless/Y\ngroundnut/MS\ngroundsheet/S\ngroundskeeper/S\ngroundsman\ngroundsmen\ngroundswell/SM\ngroundwater/M\ngroundwork/M\ngroup/JSZGMDR\ngrouper/M\ngroupie/MS\ngrouping/M\ngroupware/M\ngrouse/MZGDRS\ngrouser/M\ngrout/SGMD\ngrove/SM\ngrovel/ZGDRS\ngroveler/M\ngrovelled\ngrovelling\ngrow/AHSG\ngrower/MS\ngrowing/I\ngrowl/SZGMDR\ngrowler/M\ngrown/AI\ngrownup/MS\ngrowth/AM\ngrowths\ngrub/MS\ngrubbed\ngrubber/MS\ngrubbily\ngrubbiness/M\ngrubbing\ngrubby/TRP\ngrubstake/M\ngrudge/MGDS\ngrudging/Y\ngrue/S\ngruel/GJM\ngrueling/Y\ngruesome/RYTP\ngruesomeness/M\ngruff/TPRY\ngruffness/M\ngrumble/DRSMZGJ\ngrumbler/M\ngrump/SM\ngrumpily\ngrumpiness/M\ngrumpy/PRT\ngrunge/MS\ngrungy/RT\ngrunion/SM\ngrunt/SGMD\ngt\nguacamole/M\nguanine/M\nguano/M\nguarani/MS\nguarantee/MDS\nguaranteeing\nguarantor/MS\nguaranty/GDSM\nguard/SZGMDR\nguarded/Y\nguarder/M\nguardhouse/SM\nguardian/SM\nguardianship/M\nguardrail/SM\nguardroom/SM\nguardsman/M\nguardsmen\nguava/SM\ngubernatorial\nguerrilla/SM\nguess/ZGBMDRS\nguesser/M\nguesstimate/DSMG\nguesswork/M\nguest/SGMD\nguestbook\nguesthouse/S\nguestroom/S\nguff/M\nguffaw/MDGS\nguidance/M\nguide/DRSMZG\nguidebook/SM\nguided/U\nguideline/SM\nguidepost/SM\nguider/M\nguild/SZMR\nguilder/M\nguildhall/MS\nguile/M\nguileful\nguileless/YP\nguilelessness/M\nguillemot/S\nguillotine/DSMG\nguilt/M\nguiltily\nguiltiness/M\nguiltless\nguilty/PRT\nguinea/MS\nguise/ESM\nguitar/MS\nguitarist/SM\ngulag/SM\ngulch/MS\ngulden/MS\ngulf/MS\ngull/MDSG\ngullet/MS\ngullibility/M\ngullible\ngully/SM\ngulp/MDRSZG\ngulper/M\ngum/SM\ngumball/S\ngumbo/SM\ngumboil/SM\ngumboot/S\ngumdrop/SM\ngummed\ngumming\ngummy/TR\ngumption/M\ngumshoe/MDS\ngumshoeing\ngun/SM\ngunboat/SM\ngunfight/MRZS\ngunfighter/M\ngunfire/M\ngunge\ngungy\ngunk/M\ngunky\ngunman/M\ngunmen\ngunmetal/M\ngunned\ngunnel/MS\ngunner/MS\ngunnery/M\ngunning\ngunny/M\ngunnysack/MS\ngunpoint/M\ngunpowder/M\ngunrunner/MS\ngunrunning/M\ngunship/MS\ngunshot/MS\ngunslinger/SM\ngunsmith/M\ngunsmiths\ngunwale/MS\nguppy/SM\ngurgle/MGDS\ngurney/MS\nguru/MS\ngush/MDRSZG\ngusher/M\ngushing/Y\ngushy/TR\ngusset/MSDG\ngussy/DSG\ngust/EMDSG\ngustatory\ngustily\ngusto/M\ngusty/RT\ngut/SM\ngutless/P\ngutlessness/M\ngutsy/RT\ngutted\ngutter/SMDG\nguttersnipe/MS\ngutting\nguttural/MS\ngutty/RT\nguv/S\nguvnor/S\nguy/SGMD\nguzzle/DRSZG\nguzzler/M\ngym/SM\ngymkhana/MS\ngymnasium/MS\ngymnast/MS\ngymnastic/S\ngymnastically\ngymnastics/M\ngymnosperm/SM\ngymslip/S\ngynecologic\ngynecological\ngynecologist/SM\ngynecology/M\ngyp/SM\ngypped\ngypper/SM\ngypping\ngypster/SM\ngypsum/M\ngypsy/SM\ngyrate/DSGNX\ngyration/M\ngyrator/SM\ngyrfalcon/MS\ngyro/MS\ngyroscope/MS\ngyroscopic\ngyve/MGDS\nh'm\nh/NRSXZGVJ\nha/SH\nhaberdasher/SM\nhaberdashery/SM\nhabiliment/SM\nhabit's\nhabit/ISB\nhabitability/M\nhabitat/SM\nhabitation/MS\nhabitual/YP\nhabitualness/M\nhabituate/GNDS\nhabituation/M\nhabitue/SM\nhacienda/SM\nhack/MDRZGS\nhacker/M\nhacking/M\nhackish\nhackle/MS\nhackney/SMDG\nhacksaw/SM\nhacktivist/S\nhackwork/M\nhad\nhaddock/SM\nhadn't\nhadst\nhafnium/M\nhaft/MS\nhag/SM\nhaggard/YP\nhaggardness/M\nhaggis/MS\nhaggish\nhaggle/MZGDRS\nhaggler/M\nhagiographer/SM\nhagiography/SM\nhahnium/M\nhaiku/M\nhail/MDGS\nhailstone/MS\nhailstorm/MS\nhair/MDS\nhairball/MS\nhairband/S\nhairbreadth/M\nhairbreadths\nhairbrush/MS\nhaircloth/M\nhaircut/SM\nhairdo/MS\nhairdresser/SM\nhairdressing/M\nhairdryer/MS\nhairgrip/S\nhairiness/M\nhairless\nhairlike\nhairline/SM\nhairnet/SM\nhairpiece/MS\nhairpin/SM\nhairsbreadth/M\nhairsbreadths\nhairsplitter/SM\nhairsplitting/M\nhairspray/S\nhairspring/MS\nhairstyle/MS\nhairstylist/SM\nhairy/TRP\nhaj\nhajj/M\nhajjes\nhajji/SM\nhake/MS\nhalal/M\nhalberd/SM\nhalcyon\nhale/ITGDRS\nhalf/M\nhalfback/SM\nhalfhearted/PY\nhalfheartedness/M\nhalfpence\nhalfpenny/SM\nhalftime/MS\nhalftone/MS\nhalfway\nhalfwit/SM\nhalibut/SM\nhalite/M\nhalitosis/M\nhall/MS\nhallelujah/M\nhallelujahs\nhallmark/GMDS\nhalloo/MSG\nhallow/DSG\nhallowed/U\nhallucinate/GNXDS\nhallucination/M\nhallucinatory\nhallucinogen/SM\nhallucinogenic/SM\nhallway/SM\nhalo/MDGS\nhalogen/SM\nhalon\nhalt/MDRZGS\nhalter/GMD\nhalterneck/S\nhalting/Y\nhalve/DSG\nhalyard/MS\nham/SM\nhamburg/SZMR\nhamburger/M\nhamlet/MS\nhammed\nhammer/MDRSJZG\nhammerer/M\nhammerhead/SM\nhammerlock/SM\nhammertoe/MS\nhamming\nhammock/SM\nhammy/TR\nhamper/GMDS\nhampered/U\nhamster/MS\nhamstring/GSM\nhamstrung\nhand's\nhand/UDGS\nhandbag/SM\nhandball/MS\nhandbarrow/SM\nhandbill/MS\nhandbook/MS\nhandbrake/S\nhandcar/SM\nhandcart/MS\nhandclasp/MS\nhandcraft/SMDG\nhandcuff/MDGS\nhanded/P\nhandful/SM\nhandgun/SM\nhandheld/MS\nhandhold/MS\nhandicap/MS\nhandicapped\nhandicapper/MS\nhandicapping\nhandicraft/MS\nhandily\nhandiness/M\nhandiwork/M\nhandkerchief/MS\nhandle/MZGDRS\nhandlebar/MS\nhandler/M\nhandmade\nhandmaid/XMNS\nhandmaiden/M\nhandout/SM\nhandover/S\nhandpick/GDS\nhandrail/MS\nhandsaw/SM\nhandset/SM\nhandshake/JMGS\nhandsome/PYTR\nhandsomeness/M\nhandspring/MS\nhandstand/SM\nhandwork/M\nhandwoven\nhandwriting/M\nhandwritten\nhandy/UTR\nhandyman/M\nhandymen\nhang/MDRJZGS\nhangar/MS\nhangdog\nhanger/M\nhanging/M\nhangman/M\nhangmen\nhangnail/MS\nhangout/SM\nhangover/MS\nhangup/MS\nhank/MRZS\nhanker/GJD\nhankering/M\nhankie/MS\nhansom/MS\nhap/MY\nhaphazard/YP\nhaphazardness/M\nhapless/YP\nhaplessness/M\nhaploid/MS\nhappen/SDGJ\nhappening/M\nhappenstance/SM\nhappily/U\nhappiness/UM\nhappy/URTP\nharangue/MGDS\nharass/LZGDRS\nharasser/M\nharassment/M\nharbinger/SM\nharbor/GMDS\nharbormaster/S\nhard/NRYXTP\nhardback/MS\nhardball/M\nhardboard/M\nhardbound\nhardcore\nhardcover/SM\nharden/ZGDR\nhardened/U\nhardener/M\nhardhat/MS\nhardheaded/PY\nhardheadedness/M\nhardhearted/PY\nhardheartedness/M\nhardihood/M\nhardily\nhardiness/M\nhardliner/MS\nhardness/M\nhardscrabble\nhardship/SM\nhardstand/SM\nhardtack/M\nhardtop/SM\nhardware/M\nhardwired\nhardwood/SM\nhardworking\nhardy/PTR\nhare/MGDS\nharebell/MS\nharebrained\nharelip/SM\nharelipped\nharem/SM\nharicot/S\nhark/DGS\nharlequin/SM\nharlot/SM\nharlotry/M\nharm/MDGS\nharmed/U\nharmful/YP\nharmfulness/M\nharmless/PY\nharmlessness/M\nharmonic/SM\nharmonica/MS\nharmonically\nharmonies\nharmonious/PY\nharmoniousness/M\nharmonium/MS\nharmonization/M\nharmonize/ZGDRS\nharmonizer/M\nharmony/EM\nharness's\nharness/UDSG\nharp/MDGS\nharpist/SM\nharpoon/ZGSMDR\nharpooner/M\nharpsichord/MS\nharpsichordist/SM\nharpy/SM\nharridan/MS\nharrier/M\nharrow/SMDG\nharrumph/GD\nharrumphs\nharry/DRSZG\nharsh/RYTP\nharshness/M\nhart/MS\nharvest/SMDRZG\nharvested/U\nharvester/M\nhash/AMDSG\nhashish/M\nhashtag/SM\nhasn't\nhasp/MS\nhassle/DSMG\nhassock/SM\nhast/DNXG\nhaste/SM\nhasten/DG\nhastily\nhastiness/M\nhasty/RTP\nhat/ZGSMDR\nhatband/S\nhatbox/MS\nhatch/MDSG\nhatchback/MS\nhatcheck/SM\nhatched/U\nhatchery/SM\nhatchet/SM\nhatching/M\nhatchway/SM\nhate/MS\nhateful/PY\nhatefulness/M\nhatemonger/MS\nhater/M\nhatpin/S\nhatred/SM\nhatstand/S\nhatted\nhatter/SM\nhatting\nhauberk/SM\nhaughtily\nhaughtiness/M\nhaughty/PRT\nhaul/MDRZGS\nhaulage/M\nhauler/M\nhaulier/S\nhaunch/MS\nhaunt/SMDRZG\nhaunter/M\nhaunting/Y\nhauteur/M\nhave/MGS\nhaven't\nhaven/SM\nhaversack/SM\nhavoc/M\nhaw/GSMD\nhawk/MDRZGS\nhawker/M\nhawkish/P\nhawkishness/M\nhawser/SM\nhawthorn/MS\nhay/GSMD\nhaycock/SM\nhayloft/SM\nhaymaking\nhaymow/SM\nhayrick/MS\nhayride/MS\nhayseed/MS\nhaystack/SM\nhaywire\nhazard/SMDG\nhazardous/Y\nhaze/MZGJDRS\nhazel/SM\nhazelnut/MS\nhazer/M\nhazily\nhaziness/M\nhazing/M\nhazmat\nhazy/RTP\nhdqrs\nhe'd\nhe'll\nhe/M\nhead/MDRZGJS\nheadache/MS\nheadband/MS\nheadbanger/S\nheadbanging\nheadboard/SM\nheadbutt/DSG\nheadcase/S\nheadcheese\nheadcount/S\nheaddress/MS\nheader/M\nheadfirst\nheadgear/M\nheadhunt/DRSZG\nheadhunter/M\nheadhunting/M\nheadily\nheadiness/M\nheading/M\nheadlamp/MS\nheadland/MS\nheadless\nheadlight/MS\nheadline/MZGDRS\nheadliner/M\nheadlock/MS\nheadlong\nheadman/M\nheadmaster/SM\nheadmen\nheadmistress/MS\nheadphone/MS\nheadpiece/MS\nheadpin/SM\nheadquarter/SDG\nheadquarters/M\nheadrest/MS\nheadroom/M\nheadscarf\nheadscarves\nheadset/SM\nheadship/SM\nheadshrinker/SM\nheadsman/M\nheadsmen\nheadstall/SM\nheadstand/SM\nheadstone/SM\nheadstrong\nheadteacher/S\nheadwaiter/SM\nheadwaters/M\nheadway/M\nheadwind/SM\nheadword/SM\nheady/RTP\nheal/DRHZGS\nhealed/U\nhealer/M\nhealth/M\nhealthcare\nhealthful/PY\nhealthfulness/M\nhealthily/U\nhealthiness/UM\nhealthy/UTRP\nheap/MDGS\nhear/AHGJS\nheard/AU\nhearer/SM\nhearing/AM\nhearken/SGD\nhearsay/M\nhearse's\nhearse/AS\nheart/SM\nheartache/MS\nheartbeat/MS\nheartbreak/SMG\nheartbroken\nheartburn/M\nhearten/ESGD\nheartfelt\nhearth/M\nhearthrug/S\nhearths\nhearthstone/SM\nheartily\nheartiness/M\nheartland/MS\nheartless/PY\nheartlessness/M\nheartrending/Y\nheartsick/P\nheartsickness/M\nheartstrings/M\nheartthrob/MS\nheartwarming\nheartwood/M\nhearty/RSMPT\nheat's\nheat/ADGS\nheated/U\nheatedly\nheater/SM\nheath/MNRX\nheathen/M\nheathendom/M\nheathenish\nheathenism/M\nheather/M\nheaths\nheating/M\nheatproof\nheatstroke/M\nheatwave/S\nheave/DRSMZG\nheaven/SMY\nheavenly/TR\nheavens/M\nheavenward/S\nheaver/M\nheavily\nheaviness/M\nheavy/RSMTP\nheavyhearted\nheavyset\nheavyweight/MS\nheck/M\nheckle/DRSMZG\nheckler/M\nheckling/M\nhectare/SM\nhectic\nhectically\nhectogram/SM\nhectometer/MS\nhector/SMDG\nhedge/DRSMZG\nhedgehog/MS\nhedgehop/S\nhedgehopped\nhedgehopping\nhedger/M\nhedgerow/SM\nhedonism/M\nhedonist/MS\nhedonistic\nheed/MDGS\nheeded/U\nheedful/Y\nheedless/PY\nheedlessness/M\nheehaw/SMDG\nheel/MDGS\nheelless\nheft/MDGS\nheftily\nheftiness/M\nhefty/PRT\nhegemonic\nhegemony/M\nhegira/SM\nheifer/SM\nheight/XSMN\nheighten/DG\nheinous/YP\nheinousness/M\nheir/MS\nheiress/MS\nheirloom/SM\nheist/SMDG\nheld\nhelical\nhelices\nhelicopter/SGMD\nheliocentric\nheliotrope/SM\nhelipad/S\nheliport/MS\nhelium/M\nhelix/M\nhell/M\nhellbent\nhellcat/MS\nhellebore/M\nhellhole/MS\nhellion/MS\nhellish/YP\nhellishness/M\nhello/SM\nhelluva\nhelm/MS\nhelmet/SMD\nhelmsman/M\nhelmsmen\nhelot/SM\nhelp/MDRZGSJ\nhelper/M\nhelpful/UY\nhelpfulness/M\nhelping/M\nhelpless/PY\nhelplessness/M\nhelpline/SM\nhelpmate/SM\nhelve/SM\nhem/SM\nhematite/M\nhematologic\nhematological\nhematologist/MS\nhematology/M\nheme/M\nhemisphere/SM\nhemispheric\nhemispherical\nhemline/SM\nhemlock/SM\nhemmed\nhemmer/SM\nhemming\nhemoglobin/M\nhemophilia/M\nhemophiliac/MS\nhemorrhage/MGDS\nhemorrhagic\nhemorrhoid/MS\nhemostat/MS\nhemp/MN\nhemstitch/MDSG\nhen/M\nhence\nhenceforth\nhenceforward\nhenchman/M\nhenchmen\nhenna/SMDG\nhenpeck/GSD\nhep\nheparin/M\nhepatic\nhepatitis/M\nhepatocyte/S\nhepper\nheppest\nheptagon/MS\nheptagonal\nheptathlon/SM\nherald/SMDG\nheralded/U\nheraldic\nheraldry/M\nherb/MS\nherbaceous\nherbage/M\nherbal/S\nherbalist/MS\nherbicidal\nherbicide/MS\nherbivore/SM\nherbivorous\nherculean\nherd/MDRZGS\nherder/M\nherdsman/M\nherdsmen\nhere/M\nhereabout/S\nhereafter/SM\nhereby\nhereditary\nheredity/M\nherein\nhereinafter\nhereof\nhereon\nheresy/SM\nheretic/SM\nheretical\nhereto\nheretofore\nhereunto\nhereupon\nherewith\nheritable/I\nheritage/MS\nhermaphrodite/SM\nhermaphroditic\nhermetic\nhermetical/Y\nhermit/SM\nhermitage/MS\nhernia/SM\nhernial\nherniate/GNDS\nherniation/M\nhero/M\nheroes\nheroic/S\nheroically\nheroics/M\nheroin/SM\nheroine/SM\nheroism/M\nheron/SM\nherpes/M\nherpetologist/SM\nherpetology/M\nherring/MS\nherringbone/M\nherself\nhertz/M\nhesitance/M\nhesitancy/M\nhesitant/Y\nhesitate/DSGNX\nhesitating/UY\nhesitation/M\nhessian\nhetero/SM\nheterodox\nheterodoxy/M\nheterogeneity/M\nheterogeneous/Y\nheterosexual/MYS\nheterosexuality/M\nheuristic/MS\nheuristically\nheuristics/M\nhew/ZGSDR\nhewer/M\nhex/GMDS\nhexadecimal/S\nhexagon/MS\nhexagonal\nhexagram/SM\nhexameter/SM\nhey\nheyday/SM\nhf\nhgt\nhgwy\nhi/SD\nhiatus/MS\nhibachi/MS\nhibernate/GNDS\nhibernation/M\nhibernator/MS\nhibiscus/MS\nhiccough/DG\nhiccoughs\nhiccup/GSMD\nhick/MS\nhickey/SM\nhickory/SM\nhid\nhidden\nhide/MZGJDRS\nhideaway/SM\nhidebound\nhideous/YP\nhideousness/M\nhideout/MS\nhider/M\nhiding/M\nhie/S\nhieing\nhierarchic\nhierarchical/Y\nhierarchy/SM\nhieroglyph/M\nhieroglyphic/MS\nhieroglyphs\nhigh/MRYZTP\nhighball/SM\nhighborn\nhighboy/MS\nhighbrow/SM\nhighchair/MS\nhighfalutin\nhighhanded/PY\nhighhandedness/M\nhighland/MRZS\nhighlander/M\nhighlight/SMDRZG\nhighlighter/M\nhighness/M\nhighroad/MS\nhighs\nhightail/DSG\nhighway/MS\nhighwayman/M\nhighwaymen\nhijab\nhijack/SJZGMDR\nhijacker/M\nhijacking/M\nhike/MZGDRS\nhiker/M\nhiking/M\nhilarious/PY\nhilariousness/M\nhilarity/M\nhill/MS\nhillbilly/SM\nhilliness/M\nhillock/MS\nhillside/SM\nhilltop/MS\nhilly/PRT\nhilt/MS\nhim/S\nhimself\nhind/MRZS\nhinder/GD\nhindered/U\nhindmost\nhindquarter/MS\nhindrance/SM\nhindsight/M\nhinge's\nhinge/UDSG\nhint/MDRZGS\nhinter/M\nhinterland/SM\nhip/SPM\nhipbath\nhipbaths\nhipbone/MS\nhiphuggers\nhipness/M\nhipped\nhipper\nhippest\nhippie/SM\nhipping\nhippo/SM\nhippodrome/SM\nhippopotamus/MS\nhippy\nhipster/MS\nhiragana\nhire's\nhire/AGDS\nhireling/MS\nhirsute/P\nhirsuteness/M\nhiss/MDSG\nhist\nhistamine/MS\nhistogram/MS\nhistologist/SM\nhistology/M\nhistorian/MS\nhistoric\nhistorical/Y\nhistoricity/M\nhistoriographer/MS\nhistoriography/M\nhistory/SM\nhistrionic/S\nhistrionically\nhistrionics/M\nhit/SM\nhitch's\nhitch/UDSG\nhitcher/MS\nhitchhike/DRSMZG\nhitchhiker/M\nhither\nhitherto\nhitter/SM\nhitting\nhive/MGDS\nhiya\nhmm\nho/SMDRYZ\nhoagie/MS\nhoard/SZGMDRJ\nhoarder/M\nhoarding/M\nhoarfrost/M\nhoariness/M\nhoarse/YTRP\nhoarseness/M\nhoary/TRP\nhoax/MDRSZG\nhoaxer/M\nhob/SM\nhobbit/S\nhobble/MZGDRS\nhobbler/M\nhobby/SM\nhobbyhorse/MS\nhobbyist/SM\nhobgoblin/MS\nhobnail/SGMD\nhobnob/S\nhobnobbed\nhobnobbing\nhobo/MS\nhock/MDSG\nhockey/M\nhockshop/MS\nhod/SM\nhodgepodge/SM\nhoe/SM\nhoecake/SM\nhoedown/SM\nhoeing\nhoer/M\nhog/SM\nhogan/SM\nhogback/SM\nhogged\nhogging\nhoggish/Y\nhogshead/SM\nhogtie/DS\nhogtying\nhogwash/M\nhoick/SGD\nhoist/SGMD\nhoke/GDS\nhokey\nhokier\nhokiest\nhokum/M\nhold/MRJSZG\nholdall/S\nholder/M\nholding/M\nholdout/SM\nholdover/SM\nholdup/MS\nhole/MGDS\nholey\nholiday/SMDG\nholidaymaker/S\nholiness/UM\nholism\nholistic\nholistically\nholler/MDGS\nhollow/MDRYPSTG\nhollowness/M\nholly/SM\nhollyhock/MS\nholmium/M\nholocaust/SM\nhologram/MS\nholograph/M\nholographic\nholographs\nholography/M\nhols\nholster/SMDG\nholy/URPT\nhomage/MS\nhombre/MS\nhomburg/SM\nhome/MYZGDRS\nhomebody/SM\nhomeboy/SM\nhomecoming/SM\nhomegrown\nhomeland/MS\nhomeless/MP\nhomelessness/M\nhomelike\nhomeliness/M\nhomely/PRT\nhomemade\nhomemaker/SM\nhomemaking/M\nhomeopath/M\nhomeopathic\nhomeopaths\nhomeopathy/M\nhomeostasis/M\nhomeostatic\nhomeowner/MS\nhomepage/MS\nhomer/GMD\nhomeroom/MS\nhomeschooling/M\nhomesick/P\nhomesickness/M\nhomespun/M\nhomestead/SMDRZG\nhomesteader/M\nhomestretch/MS\nhometown/MS\nhomeward/S\nhomework/MRZG\nhomewrecker/SM\nhomey/SMP\nhomeyness/M\nhomicidal\nhomicide/MS\nhomier\nhomiest\nhomiletic\nhomily/SM\nhominid/SM\nhominoid/S\nhominy/M\nhomo/MS\nhomoerotic\nhomogeneity/M\nhomogeneous/Y\nhomogenization/M\nhomogenize/DSG\nhomograph/M\nhomographs\nhomologous\nhomonym/SM\nhomophobia/M\nhomophobic\nhomophone/MS\nhomosexual/SM\nhomosexuality/M\nhon/SZTGMDR\nhoncho/MS\nhone/MS\nhoner/M\nhonest/EYT\nhonester\nhonesty/EM\nhoney/SGMD\nhoneybee/SM\nhoneycomb/MDSG\nhoneydew/SM\nhoneylocust/M\nhoneymoon/ZGMDRS\nhoneymooner/M\nhoneypot/S\nhoneysuckle/SM\nhonk/MDRSZG\nhonker/M\nhonky/SM\nhonor/ESGMDB\nhonorableness/M\nhonorably/E\nhonorarily\nhonorarium/MS\nhonorary\nhonoree/SM\nhonorer/SM\nhonorific/MS\nhooch/M\nhood/MDSG\nhoodie/MS\nhoodlum/SM\nhoodoo/MDSG\nhoodwink/DGS\nhooey/M\nhoof/MDRSZG\nhook's\nhook/UDSG\nhookah/M\nhookahs\nhooker/MS\nhookup/MS\nhookworm/MS\nhooky/M\nhooligan/MS\nhooliganism/M\nhoop/MDSG\nhoopla/M\nhooray\nhoosegow/SM\nhoot/MDRSZG\nhootenanny/SM\nhooter/M\nhoover/DSG\nhooves\nhop/SGMD\nhope/MS\nhopeful/PSMY\nhopefulness/M\nhopeless/YP\nhopelessness/M\nhopped\nhopper/MS\nhopping\nhopscotch/MDSG\nhora/MS\nhorde/DSMG\nhorehound/SM\nhorizon/SM\nhorizontal/SMY\nhormonal\nhormone/SM\nhorn/MDS\nhornblende/M\nhornet/MS\nhornless\nhornlike\nhornpipe/MS\nhorny/TR\nhorologic\nhorological\nhorologist/MS\nhorology/M\nhoroscope/SM\nhorrendous/Y\nhorrible/P\nhorribleness/M\nhorribly\nhorrid/Y\nhorrific\nhorrifically\nhorrify/DSG\nhorrifying/Y\nhorror/MS\nhorse's\nhorse/UDSG\nhorseback/M\nhorsebox/S\nhorseflesh/M\nhorsefly/SM\nhorsehair/M\nhorsehide/M\nhorselaugh/M\nhorselaughs\nhorseless\nhorseman/M\nhorsemanship/M\nhorsemen\nhorseplay/M\nhorsepower/M\nhorseradish/MS\nhorseshit/!\nhorseshoe/DSM\nhorseshoeing\nhorsetail/SM\nhorsetrading\nhorsewhip/SM\nhorsewhipped\nhorsewhipping\nhorsewoman/M\nhorsewomen\nhorsey\nhorsier\nhorsiest\nhortatory\nhorticultural\nhorticulturalist/S\nhorticulture/M\nhorticulturist/MS\nhosanna/SM\nhose/MGDS\nhosepipe/S\nhosier/MS\nhosiery/M\nhosp\nhospholipase\nhospice/MS\nhospitable/I\nhospitably/I\nhospital/SM\nhospitality/M\nhospitalization/SM\nhospitalize/DSG\nhost/MDSG\nhostage/MS\nhostel/ZGMDRS\nhosteler/M\nhostelry/SM\nhostess/MDSG\nhostile/MYS\nhostilities/M\nhostility/SM\nhostler/MS\nhot/SYP\nhotbed/MS\nhotblooded\nhotbox/MS\nhotcake/SM\nhotel/SM\nhotelier/MS\nhotfoot/MDGS\nhothead/DSM\nhotheaded/YP\nhotheadedness/M\nhothouse/SM\nhotkey/S\nhotlink/S\nhotness/M\nhotplate/SM\nhotpot/S\nhots/M\nhotshot/MS\nhotted\nhotter\nhottest\nhottie/S\nhotting\nhound/SGMD\nhour/MYS\nhourglass/MS\nhouri/SM\nhouse's\nhouse/ADSG\nhouseboat/SM\nhousebound\nhouseboy/SM\nhousebreak/RSZG\nhousebreaker/M\nhousebreaking/M\nhousebroke\nhousebroken\nhouseclean/DSG\nhousecleaning/M\nhousecoat/SM\nhousefly/SM\nhouseful/SM\nhousehold/SMRZ\nhouseholder/M\nhousehusband/SM\nhousekeeper/MS\nhousekeeping/M\nhouselights/M\nhousemaid/SM\nhouseman/M\nhousemaster/S\nhousemate/S\nhousemen\nhousemistress/S\nhousemother/SM\nhouseparent/SM\nhouseplant/MS\nhouseproud\nhouseroom\nhousetop/SM\nhousewares/M\nhousewarming/SM\nhousewife/MY\nhousewives\nhousework/M\nhousing/MS\nhove\nhovel/SM\nhover/SGD\nhovercraft/M\nhow'd\nhow're\nhow/SM\nhowbeit\nhowdah/M\nhowdahs\nhowdy\nhowever\nhowitzer/SM\nhowl/MDRSZG\nhowler/M\nhowsoever\nhoyden/MS\nhoydenish\nhp\nhr/S\nht\nhuarache/SM\nhub/SM\nhubbub/SM\nhubby/SM\nhubcap/SM\nhubris/M\nhuckleberry/SM\nhuckster/SGMD\nhucksterism/M\nhuddle/DSMG\nhue/DSM\nhuff/MDSG\nhuffily\nhuffiness/M\nhuffy/PRT\nhug/STMR\nhuge/YP\nhugeness/M\nhugged\nhugging\nhuh\nhula/MS\nhulk/MSG\nhull/MDRSZG\nhullabaloo/SM\nhuller/M\nhum/SM\nhuman/SMRYTP\nhumane/PY\nhumaneness/M\nhumanism/M\nhumanist/SM\nhumanistic\nhumanitarian/MS\nhumanitarianism/M\nhumanities/M\nhumanity/ISM\nhumanization/CM\nhumanize/CDSG\nhumanizer/SM\nhumankind/M\nhumanness/M\nhumanoid/SM\nhumble/DRSZTGJP\nhumbleness/M\nhumbler/M\nhumbly\nhumbug/SM\nhumbugged\nhumbugging\nhumdinger/MS\nhumdrum/M\nhumeral\nhumeri\nhumerus/M\nhumid/Y\nhumidification/M\nhumidifier/CM\nhumidify/CZGDRS\nhumidity/M\nhumidor/SM\nhumiliate/DSGNX\nhumiliating/Y\nhumiliation/M\nhumility/M\nhummed\nhummer/SM\nhumming\nhummingbird/SM\nhummock/SM\nhummocky\nhummus/M\nhumongous\nhumor/SMDG\nhumoresque\nhumorist/MS\nhumorless/YP\nhumorlessness/M\nhumorous/PY\nhumorousness/M\nhump/MDSG\nhumpback/MDS\nhumph/DG\nhumphs\nhumus/M\nhunch/MDSG\nhunchback/SMD\nhundred/SMH\nhundredfold\nhundredth/M\nhundredths\nhundredweight/SM\nhung\nhunger/SMDG\nhungover\nhungrily\nhungriness/M\nhungry/PRT\nhunk/MRSZ\nhunker/DG\nhunky/RT\nhunt/MDRSZG\nhunter/M\nhunting/M\nhuntress/MS\nhuntsman/M\nhuntsmen\nhurdle/DRSMZG\nhurdler/M\nhurdling/M\nhurl/MDRSZG\nhurler/M\nhurling/M\nhurrah/GMD\nhurrahs\nhurricane/MS\nhurried/UY\nhurry/DSMG\nhurt/MSG\nhurtful/YP\nhurtfulness/M\nhurtle/DSG\nhusband/GMDS\nhusbandman/M\nhusbandmen\nhusbandry/M\nhush/MDSG\nhusk/MDRSZG\nhusker/M\nhuskily\nhuskiness/M\nhusky/PRSMT\nhussar/SM\nhussy/SM\nhustings/M\nhustle/DRSMZG\nhustler/M\nhut/SM\nhutch/MS\nhuzzah/MDG\nhuzzahs\nhwy\nhyacinth/M\nhyacinths\nhybrid/SM\nhybridism/M\nhybridization/M\nhybridize/DSG\nhydra/SM\nhydrangea/SM\nhydrant/MS\nhydrate's\nhydrate/CGNDS\nhydration/CM\nhydraulic/S\nhydraulically\nhydraulics/M\nhydro/M\nhydrocarbon/MS\nhydrocephalus/M\nhydrodynamic/S\nhydrodynamics/M\nhydroelectric\nhydroelectrically\nhydroelectricity/M\nhydrofoil/MS\nhydrogen/M\nhydrogenate/CGDS\nhydrogenation/M\nhydrogenous\nhydrologist/MS\nhydrology/M\nhydrolyses\nhydrolysis/M\nhydrolyze/DSG\nhydrometer/SM\nhydrometry/M\nhydrophobia/M\nhydrophobic\nhydrophone/SM\nhydroplane/GDSM\nhydroponic/S\nhydroponically\nhydroponics/M\nhydrosphere/M\nhydrotherapy/M\nhydrous\nhydroxide/SM\nhyena/SM\nhygiene/M\nhygienic/U\nhygienically\nhygienist/MS\nhygrometer/SM\nhying\nhymen/SM\nhymeneal\nhymn/MDSG\nhymnal/MS\nhymnbook/SM\nhype/MGDRS\nhyperactive\nhyperactivity/M\nhyperbola/SM\nhyperbole/M\nhyperbolic\nhypercritical/Y\nhyperglycemia/M\nhyperinflation\nhyperlink/GSMD\nhypermarket/S\nhypermedia/M\nhyperparathyroidism\nhypersensitive/P\nhypersensitiveness/M\nhypersensitivity/SM\nhyperspace/S\nhypertension/M\nhypertensive/SM\nhypertext/M\nhyperthyroid/M\nhyperthyroidism/M\nhypertrophy/DSMG\nhyperventilate/GNDS\nhyperventilation/M\nhyphen/MDSG\nhyphenate/XDSMGN\nhyphenation/M\nhypnoses\nhypnosis/M\nhypnotherapist/S\nhypnotherapy/M\nhypnotic/SM\nhypnotically\nhypnotism/M\nhypnotist/MS\nhypnotize/GDS\nhypo/MS\nhypoallergenic\nhypochondria/M\nhypochondriac/SM\nhypocrisy/SM\nhypocrite/MS\nhypocritical/Y\nhypodermic/MS\nhypoglycemia/M\nhypoglycemic/SM\nhypotenuse/MS\nhypothalami\nhypothalamus/M\nhypothermia/M\nhypotheses\nhypothesis/M\nhypothesize/DSG\nhypothetical/Y\nhypothyroid/M\nhypothyroidism/M\nhyssop/M\nhysterectomy/SM\nhysteresis\nhysteria/M\nhysteric/SM\nhysterical/Y\nhysterics/M\ni/US\niPad/M\niPhone/M\niPod/M\niTunes/M\niamb/MS\niambi\niambic/SM\niambus/MS\nibex/MS\nibid\nibidem\nibis/MS\nibuprofen/M\nice's\nice/CDSG\niceberg/SM\niceboat/SM\nicebound\nicebox/MS\nicebreaker/SM\nicecap/SM\niceman/M\nicemen\nichthyologist/MS\nichthyology/M\nicicle/SM\nicily\niciness/M\nicing/SM\nicky/RT\nicon/MS\niconic\niconoclasm/M\niconoclast/SM\niconoclastic\niconography/M\nictus/M\nicy/TPR\nid/SMY\nidea/MS\nideal/SMY\nidealism/M\nidealist/SM\nidealistic\nidealistically\nidealization/MS\nidealize/DSG\nidem\nidempotent\nidentical/Y\nidentifiable/U\nidentification/M\nidentified/U\nidentify/ZGNDRSX\nidentikit/S\nidentity/SM\nideogram/SM\nideograph/M\nideographs\nideological/Y\nideologist/SM\nideologue/MS\nideology/SM\nides/M\nidiocy/SM\nidiom/SM\nidiomatic/U\nidiomatically\nidiopathic\nidiosyncrasy/SM\nidiosyncratic\nidiosyncratically\nidiot/SM\nidiotic\nidiotically\nidle/MZTGDRSP\nidleness/M\nidler/M\nidol/MS\nidolater/SM\nidolatress/MS\nidolatrous\nidolatry/M\nidolization/M\nidolize/GDS\nidyll/SM\nidyllic\nidyllically\nif/SM\niffiness/M\niffy/RTP\nigloo/SM\nigneous\nignitable\nignite/AGDS\nignition/MS\nignoble\nignobly\nignominious/Y\nignominy/SM\nignoramus/MS\nignorance/M\nignorant/Y\nignore/GDS\niguana/MS\nii\niii\nilea\nileitis/M\nileum/M\nilia\nilium/M\nilk/SM\nill/SMP\nillegal/MYS\nillegality/SM\nillegibility/M\nillegible\nillegibly\nillegitimacy/M\nillegitimate/Y\nilliberal/Y\nilliberality/M\nillicit/YP\nillicitness/M\nillimitable\nilliteracy/M\nilliterate/MYS\nillness/MS\nillogical/Y\nillogicality/M\nilluminate/GNXDS\nilluminating/Y\nillumination/M\nillumine/DSBG\nillus/V\nillusion/EMS\nillusionist/SM\nillusory\nillustrate/GNVXDS\nillustration/M\nillustrative/Y\nillustrator/SM\nillustrious/PY\nillustriousness/M\nimage/DSMG\nimagery/M\nimaginable/U\nimaginably/U\nimaginal\nimaginary\nimagination/MS\nimaginative/UY\nimagine/DSBJG\nimago/M\nimagoes\nimam/MS\nimbalance/DSM\nimbecile/MS\nimbecilic\nimbecility/SM\nimbibe/ZGDRS\nimbiber/M\nimbrication/M\nimbroglio/SM\nimbue/DSG\nimitable/I\nimitate/DSGNVX\nimitation/M\nimitative/PY\nimitativeness/M\nimitator/SM\nimmaculate/PY\nimmaculateness/M\nimmanence/M\nimmanency/M\nimmanent/Y\nimmaterial/YP\nimmateriality/M\nimmaterialness/M\nimmature/Y\nimmaturity/M\nimmeasurable\nimmeasurably\nimmediacies/M\nimmediacy/SM\nimmediate/PY\nimmediateness/M\nimmemorial/Y\nimmense/Y\nimmensity/SM\nimmerse/XDSGNV\nimmersible\nimmersion/M\nimmigrant/SM\nimmigrate/DSGN\nimmigration/M\nimminence/M\nimminent/Y\nimmobile\nimmobility/M\nimmobilization/M\nimmobilize/ZGDRS\nimmoderate/Y\nimmodest/Y\nimmodesty/M\nimmolate/DSGN\nimmolation/M\nimmoral/Y\nimmorality/SM\nimmortal/MYS\nimmortality/M\nimmortalize/DSG\nimmovability/M\nimmovable\nimmovably\nimmune\nimmunity/M\nimmunization/SM\nimmunize/GDS\nimmunodeficiency/M\nimmunodeficient\nimmunoglobulin/S\nimmunologic\nimmunological\nimmunologist/MS\nimmunology/M\nimmure/DSG\nimmutability/M\nimmutable\nimmutably\nimp/SMR\nimpact/SMDG\nimpair/SDGL\nimpaired/U\nimpairment/MS\nimpala/SM\nimpale/DSGL\nimpalement/M\nimpalpable\nimpalpably\nimpanel/SDG\nimpart/SDG\nimpartial/Y\nimpartiality/M\nimpassably\nimpasse/BSMV\nimpassibility/M\nimpassible\nimpassibly\nimpassioned\nimpassive/YP\nimpassiveness/M\nimpassivity/M\nimpasto/M\nimpatience/MS\nimpatiens/M\nimpatient/Y\nimpeach/ZGBLDRS\nimpeachable/U\nimpeacher/M\nimpeachment/SM\nimpeccability/M\nimpeccable\nimpeccably\nimpecunious/PY\nimpecuniousness/M\nimpedance/M\nimpede/DSG\nimpeded/U\nimpediment/SM\nimpedimenta/M\nimpel/S\nimpelled\nimpeller/MS\nimpelling\nimpend/SDG\nimpenetrability/M\nimpenetrable\nimpenetrably\nimpenitence/M\nimpenitent/Y\nimperative/SMY\nimperceptibility/M\nimperceptible\nimperceptibly\nimperceptive\nimperf\nimperfect/SMYP\nimperfection/MS\nimperfectness/M\nimperial/MYS\nimperialism/M\nimperialist/SM\nimperialistic\nimperialistically\nimperil/GSLD\nimperilment/M\nimperious/PY\nimperiousness/M\nimperishable\nimperishably\nimpermanence/M\nimpermanent/Y\nimpermeability/M\nimpermeable\nimpermeably\nimpermissible\nimpersonal/Y\nimpersonate/GNXDS\nimpersonation/M\nimpersonator/SM\nimpertinence/MS\nimpertinent/Y\nimperturbability/M\nimperturbable\nimperturbably\nimpervious/Y\nimpetigo/M\nimpetuosity/M\nimpetuous/YP\nimpetuousness/M\nimpetus/MS\nimpiety/SM\nimpinge/LDSG\nimpingement/M\nimpious/PY\nimpiousness/M\nimpish/YP\nimpishness/M\nimplacability/M\nimplacable\nimplacably\nimplant/BSGMD\nimplantation/M\nimplausibility/SM\nimplausible\nimplausibly\nimplement/GBMDRS\nimplementable/U\nimplementation/SM\nimplemented/U\nimplicate/DSG\nimplication/M\nimplicit/PY\nimplicitness/M\nimplode/DSG\nimplore/DSG\nimploring/Y\nimplosion/MS\nimplosive\nimply/XDSGN\nimpolite/YP\nimpoliteness/MS\nimpolitic\nimponderable/MS\nimport/ZGBSMDR\nimportance/M\nimportant/Y\nimportation/MS\nimporter/M\nimportunate/Y\nimportune/GDS\nimportunity/M\nimpose/ADSG\nimposer/MS\nimposing/U\nimposingly\nimposition/MS\nimpossibility/SM\nimpossible/S\nimpossibly\nimpost/SM\nimpostor/SM\nimposture/MS\nimpotence/M\nimpotency/M\nimpotent/Y\nimpound/DGS\nimpoverish/DSLG\nimpoverishment/M\nimpracticability\nimpracticable\nimpracticably\nimpractical/Y\nimpracticality/M\nimprecate/DSXGN\nimprecation/M\nimprecise/PYN\nimpreciseness/M\nimprecision/M\nimpregnability/M\nimpregnable\nimpregnably\nimpregnate/GNDS\nimpregnation/M\nimpresario/SM\nimpress/MDSGV\nimpressed/U\nimpressibility/M\nimpressible\nimpression/BSM\nimpressionability/M\nimpressionism/M\nimpressionist/SM\nimpressionistic\nimpressive/PY\nimpressiveness/M\nimprimatur/SM\nimprint/MDRZGS\nimprinter/M\nimprison/SDLG\nimprisonment/SM\nimprobability/SM\nimprobable\nimprobably\nimpromptu/SM\nimproper/Y\nimpropriety/SM\nimprove/GBDSL\nimproved/U\nimprovement/MS\nimprovidence/M\nimprovident/Y\nimprovisation/SM\nimprovisational\nimprovise/ZGDRS\nimproviser/M\nimprudence/M\nimprudent/Y\nimpudence/M\nimpudent/Y\nimpugn/ZGSDR\nimpugner/M\nimpulse/MGNVDS\nimpulsion/M\nimpulsive/PY\nimpulsiveness/M\nimpunity/M\nimpure/RYT\nimpurity/SM\nimputation/SM\nimpute/BDSG\nin/ASM\ninaccuracy/S\ninaction/M\ninadequacy/S\ninadvertence/M\ninadvertent/Y\ninalienability/M\ninalienably\ninamorata/SM\ninane/RYT\ninanimate/PY\ninanimateness/M\ninanity/SM\ninappropriate/Y\ninarticulate/Y\ninasmuch\ninaudible\ninaugural/SM\ninaugurate/XGNDS\ninauguration/M\ninboard/MS\ninbound\ninbox/MS\ninbreed/S\ninc/TGD\nincalculably\nincandescence/M\nincandescent/Y\nincantation/SM\nincapacitate/GDS\nincarcerate/XDSGN\nincarceration/M\nincarnadine/DSG\nincarnate/AXGNDS\nincarnation/AM\nincendiary/SM\nincense/MGDS\nincentive's\nincentive/ES\ninception/SM\nincessant/Y\nincest/M\nincestuous/PY\nincestuousness/M\ninch/MDSG\ninchoate\ninchworm/SM\nincidence/SM\nincident/SM\nincidental/MYS\nincinerate/DSGN\nincineration/M\nincinerator/MS\nincipience/M\nincipient/Y\nincise/XGNVDS\nincision/M\nincisive/PY\nincisiveness/M\nincisor/MS\nincitement/MS\ninciter/MS\nincl\ninclement\ninclination/EM\ninclinations\nincline's\nincline/EGDS\ninclude/GDS\ninclusion/MS\ninclusive/YP\ninclusiveness/M\nincognito/MS\nincombustible\nincommode/GD\nincommodious\nincommunicado\nincompatibility/S\nincompetent/MS\nincomplete/Y\ninconceivability/M\nincongruous/PY\nincongruousness/M\ninconsolably\ninconstant/Y\nincontestability/M\nincontestably\nincontinent\nincontrovertibly\ninconvenience/GD\nincorporate/ADSGN\nincorporated/U\nincorporation/AM\nincorporeal\nincorrect/Y\nincorrigibility/M\nincorrigible\nincorrigibly\nincorruptibly\nincreasing/Y\nincrement/SMD\nincremental/Y\nincrementalism\nincrementalist/SM\nincriminate/GNDS\nincrimination/M\nincriminatory\nincrustation/SM\nincubate/GNDS\nincubation/M\nincubator/SM\nincubus/MS\ninculcate/DSGN\ninculcation/M\ninculpate/DSG\nincumbency/SM\nincumbent/SM\nincunabula\nincunabulum/M\nincur/SB\nincurable/MS\nincurably\nincurious\nincurred\nincurring\nincursion/MS\nind\nindebted/P\nindebtedness/M\nindeed\nindefatigable\nindefatigably\nindefeasible\nindefeasibly\nindefinably\nindelible\nindelibly\nindemnification/M\nindemnify/GDSXN\nindemnity/SM\nindentation/MS\nindention/M\nindenture/DG\nindescribably\nindestructibly\nindeterminably\nindeterminacy/M\nindeterminate/Y\nindex/ZGMDRS\nindexation/SM\nindexer/M\nindicate/XDSGNV\nindication/M\nindicative/SMY\nindicator/MS\nindict/GDSBL\nindictment/SM\nindie/S\nindigence/M\nindigenous\nindigent/SMY\nindignant/Y\nindignation/M\nindigo/M\nindirect/Y\nindiscipline\nindiscreet/Y\nindiscretion/S\nindiscriminate/Y\nindispensability/M\nindispensable/MS\nindispensably\nindissolubility\nindissolubly\nindistinguishably\nindite/GDS\nindium/M\nindividual/MYS\nindividualism/M\nindividualist/MS\nindividualistic\nindividualistically\nindividuality/M\nindividualization/M\nindividualize/GDS\nindividuate/DSGN\nindividuation/M\nindivisibly\nindoctrinate/GNDS\nindoctrination/M\nindolence/M\nindolent/Y\nindomitable\nindomitably\nindubitable\nindubitably\ninduce/DRSZGL\ninducement/SM\ninducer/M\ninduct/DGV\ninductance/M\ninductee/SM\ninduction/MS\ninductive/Y\nindulge/DSG\nindulgence/SM\nindulgent/Y\nindustrial/Y\nindustrialism/M\nindustrialist/SM\nindustrialization/M\nindustrialize/DSG\nindustrious/YP\nindustriousness/M\nindustry/SM\nindwell/SG\ninebriate/MGNDS\ninebriation/M\ninedible\nineffability/M\nineffable\nineffably\ninefficiency/S\ninelastic\nineligible/MS\nineligibly\nineluctable\nineluctably\ninept/YP\nineptitude/M\nineptness/M\ninequality/S\ninert/YP\ninertia/M\ninertial\ninertness/M\ninescapable\ninescapably\ninestimably\ninevitability/M\ninevitable/M\ninevitably\ninexact/Y\ninexhaustibly\ninexorability\ninexorable\ninexorably\ninexpedient\ninexpert/Y\ninexpiable\ninexplicably\ninexpressibly\ninexpressive\ninextricably\ninf/ZT\ninfallible\ninfamy/SM\ninfancy/M\ninfant/MS\ninfanticide/MS\ninfantile\ninfantry/SM\ninfantryman/M\ninfantrymen\ninfarct/MS\ninfarction/M\ninfatuate/DSXGN\ninfatuation/M\ninfect/AESDG\ninfected/U\ninfection/ASM\ninfectious/PY\ninfectiousness/M\ninfelicitous\ninference/SM\ninferential\ninferior/MS\ninferiority/M\ninfernal/Y\ninferno/MS\ninferred\ninferring\ninfest/GDS\ninfestation/MS\ninfidel/MS\ninfidelity/S\ninfiltrator/SM\ninfinite/MV\ninfinitesimal/SMY\ninfinitival\ninfinitive/MS\ninfinitude/M\ninfinity/SM\ninfirm\ninfirmary/SM\ninfirmity/SM\ninfix\ninflame/DSG\ninflammable\ninflammation/SM\ninflammatory\ninflatable/SM\ninflate/DSGNB\ninflation/EM\ninflationary\ninflect/SDG\ninflection/MS\ninflectional\ninflict/SDGV\ninfliction/M\ninflow/SM\ninfluence/MGDS\ninfluenced/U\ninfluential/Y\ninfluenza/M\ninfo/M\ninfomercial/SM\ninform/Z\ninformal/Y\ninformant/SM\ninformation/EM\ninformational\ninformative/PY\ninformativeness/M\ninformed/U\ninfotainment/M\ninfra\ninfrared/M\ninfrasonic\ninfrastructural\ninfrastructure/SM\ninfrequence/M\ninfrequent/Y\ninfringement/MS\ninfuriate/GDS\ninfuriating/Y\ninfuser/SM\ningenious/PY\ningeniousness/M\ningenue/SM\ningenuity/M\ningenuous/EY\ningenuousness/M\ningest/SDG\ningestion/M\ninglenook/SM\ningot/SM\ningrain/G\ningrate/SM\ningratiate/GNDS\ningratiating/Y\ningratiation/M\ningredient/MS\ningress/MS\ninguinal\ninhabit/DG\ninhabitable/U\ninhabitant/SM\ninhabited/U\ninhalant/SM\ninhalation/MS\ninhalator/MS\ninhaler/SM\ninharmonious\ninhere/DSG\ninherent/Y\ninherit/EGSD\ninheritance/EM\ninheritances\ninheritor/SM\ninhibit/GSD\ninhibition/SM\ninhibitor/SM\ninhibitory\ninhuman/Y\ninhumane/Y\ninimical/Y\ninimitably\niniquitous/Y\niniquity/SM\ninitial/SGMDY\ninitialism\ninitialization\ninitialize/DSG\ninitialized/AU\ninitiate/XMGNVDS\ninitiated/U\ninitiation/M\ninitiative/SM\ninitiator/MS\ninitiatory\ninject/SDG\ninjection/SM\ninjector/SM\ninjure/DRSZG\ninjured/U\ninjurer/M\ninjurious\nink/MD\ninkblot/SM\ninkiness/M\ninkling/SM\ninkstand/SM\ninkwell/MS\ninky/RTP\ninland/M\ninline\ninmate/SM\ninmost\ninn/SGMRJ\ninnards/M\ninnate/PY\ninnateness/M\ninnermost\ninnersole/SM\ninnerspring\ninnervate/GNDS\ninnervation/M\ninning/M\ninnit\ninnkeeper/MS\ninnocence/M\ninnocent/MYS\ninnocuous/PY\ninnocuousness/M\ninnovate/XDSGNV\ninnovation/M\ninnovator/MS\ninnovatory\ninnuendo/SM\ninnumerably\ninnumerate\ninoculate/AGDS\ninoculation/MS\ninoperative\ninordinate/Y\ninorganic\ninquire/ZGDR\ninquirer/M\ninquiring/Y\ninquiry/SM\ninquisition/MS\ninquisitional\ninquisitive/YP\ninquisitiveness/M\ninquisitor/SM\ninquisitorial\ninrush/MS\ninsane/T\ninsatiability/M\ninsatiably\ninscribe/ZGDR\ninscriber/M\ninscription/MS\ninscrutability/M\ninscrutable/P\ninscrutableness/M\ninscrutably\ninseam/SM\ninsecticidal\ninsecticide/MS\ninsectivore/MS\ninsectivorous\ninsecure/Y\ninseminate/DSGN\ninsemination/M\ninsensate\ninsensible\ninsensitive/Y\ninseparable/MS\ninsert's\ninsert/AGSD\ninsertion/AM\ninsertions\ninsetting\ninshore\ninside/RSMZ\ninsider/M\ninsidious/YP\ninsidiousness/M\ninsight/MS\ninsightful\ninsignia/M\ninsinuate/GNVDSX\ninsinuation/M\ninsinuator/SM\ninsipid/PY\ninsipidity/M\ninsist/SGD\ninsistence/M\ninsistent/Y\ninsisting/Y\ninsofar\ninsole/SM\ninsolence/M\ninsolent/Y\ninsoluble\ninsolubly\ninsolvency/S\ninsomnia/M\ninsomniac/SM\ninsomuch\ninsouciance/M\ninsouciant\ninspect/AGDS\ninspection/SM\ninspector/MS\ninspectorate/MS\ninspiration/MS\ninspirational\ninspired/U\ninspiring/U\ninst\ninstability/S\ninstallation/MS\ninstaller/UMS\ninstallment/SM\ninstance/GD\ninstant/MRYS\ninstantaneous/Y\ninstantiate/DSG\ninstar\ninstate/AGDS\ninstead\ninstigate/DSGN\ninstigation/M\ninstigator/MS\ninstillation/M\ninstinct/VMS\ninstinctive/Y\ninstinctual\ninstitute/XMZGNDRS\ninstituter/M\ninstitution/M\ninstitutional/Y\ninstitutionalization/M\ninstitutionalize/DSG\ninstr\ninstruct/SDGV\ninstructed/U\ninstruction/MS\ninstructional\ninstructive/Y\ninstructor/MS\ninstrument/MDSG\ninstrumental/MYS\ninstrumentalist/SM\ninstrumentality/M\ninstrumentation/M\ninsubordinate\ninsufferable\ninsufferably\ninsular\ninsularity/M\ninsulate/GNDS\ninsulation/M\ninsulator/MS\ninsulin/M\ninsult/SMDG\ninsulting/Y\ninsuperable\ninsuperably\ninsurance/SM\ninsure/DRSZGB\ninsured/SM\ninsurer/M\ninsurgence/SM\ninsurgency/SM\ninsurgent/MS\ninsurmountably\ninsurrection/SM\ninsurrectionist/SM\nint\nintact\nintaglio/MS\ninteger/MS\nintegral/SMY\nintegrate/AEVNGSD\nintegration/EAM\nintegrator\nintegrity/M\nintegument/SM\nintellect/MS\nintellectual/MYS\nintellectualism/M\nintellectualize/GDS\nintelligence/M\nintelligent/Y\nintelligentsia/M\nintelligibility/M\nintelligible/U\nintelligibly/U\nintended/SM\nintense/YTVR\nintensification/M\nintensifier/M\nintensify/DRSZGN\nintensity/S\nintensive/MYPS\nintensiveness/M\nintent/SMYP\nintention/MS\nintentional/UY\nintentness/M\ninter/ESL\ninteract/SGVD\ninteraction/SM\ninteractive/Y\ninteractivity\ninterbred\ninterbreed/GS\nintercede/GDS\nintercept/GMDS\ninterception/MS\ninterceptor/SM\nintercession/SM\nintercessor/MS\nintercessory\ninterchange/DSMG\ninterchangeability\ninterchangeable\ninterchangeably\nintercity\nintercollegiate\nintercom/SM\nintercommunicate/DSGN\nintercommunication/M\ninterconnect/GDS\ninterconnection/SM\nintercontinental\nintercourse/M\nintercultural\ninterdenominational\ninterdepartmental\ninterdependence/M\ninterdependent/Y\ninterdict/GMDS\ninterdiction/M\ninterdisciplinary\ninterest/ESMD\ninterested/U\ninteresting/Y\ninterface/MGDS\ninterfaith\ninterfere/GDS\ninterference/M\ninterferon/M\ninterfile/GDS\nintergalactic\nintergovernmental\ninterim/M\ninterior/SM\ninterj\ninterject/GDS\ninterjection/SM\ninterlace/GDS\ninterlard/DGS\ninterleave/DSG\ninterleukin/M\ninterline/GDSJ\ninterlinear\ninterlining/M\ninterlink/DSG\ninterlock/GMDS\ninterlocutor/SM\ninterlocutory\ninterlope/ZGDRS\ninterloper/M\ninterlude/MGDS\nintermarriage/SM\nintermarry/GDS\nintermediary/SM\nintermediate/MYS\ninterment/EM\ninterments\nintermezzi\nintermezzo/MS\ninterminably\nintermingle/DSG\nintermission/SM\nintermittent/Y\nintermix/GDS\nintern/GDL\ninternal/SY\ninternalization/M\ninternalize/GDS\ninternational/SMY\ninternationalism/M\ninternationalist/SM\ninternationalization\ninternationalize/DSG\ninternecine\ninternee/SM\ninternet\ninternist/MS\ninternment/M\ninternship/MS\ninteroffice\ninterpenetrate/DSGN\ninterpersonal\ninterplanetary\ninterplay/M\ninterpolate/XDSGN\ninterpolation/M\ninterpose/GDS\ninterposition/M\ninterpret/AGVDS\ninterpretation/AMS\ninterpretative\ninterpreted/U\ninterpreter/MS\ninterracial\ninterred/E\ninterregnum/SM\ninterrelate/XDSGN\ninterrelation/M\ninterrelationship/MS\ninterring/E\ninterrogate/DSGNVX\ninterrogation/M\ninterrogative/MYS\ninterrogator/SM\ninterrogatory/SM\ninterrupt/ZGMDRS\ninterrupter/M\ninterruption/MS\ninterscholastic\nintersect/GDS\nintersection/SM\nintersession/SM\nintersex\nintersperse/GNDS\ninterspersion/M\ninterstate/MS\ninterstellar\ninterstice/MS\ninterstitial\nintertwine/GDS\ninterurban\ninterval/SM\nintervene/GDS\nintervention/SM\ninterventionism/M\ninterventionist/SM\ninterview/ZGMDRS\ninterviewee/MS\ninterviewer/M\nintervocalic\ninterwar\ninterweave/GS\ninterwove\ninterwoven\nintestacy/M\nintestate\nintestinal\nintestine/MS\nintimacy/SM\nintimate/MYGNDSX\nintimation/M\nintimidate/GNDS\nintimidating/Y\nintimidation/M\nintonation/SM\nintoxicant/SM\nintoxicate/DSGN\nintoxication/M\nintracranial\nintramural\nintramuscular\nintranet/MS\nintransigence/M\nintransigent/MYS\nintrastate\nintrauterine\nintravenous/MSY\nintrepid/Y\nintrepidity/M\nintricacy/SM\nintricate/Y\nintrigue/DRSMZG\nintriguer/M\nintriguing/Y\nintrinsic\nintrinsically\nintro/SM\nintroduce/AGDS\nintroduction/AM\nintroductions\nintroductory\nintroit/SM\nintrospect/GVDS\nintrospection/M\nintrospective/Y\nintroversion/M\nintrovert/MDS\nintrude/DRSZG\nintruder/M\nintrusion/SM\nintrusive/YP\nintrusiveness/M\nintuit/SDGV\nintuition/S\nintuitive/PY\nintuitiveness/M\ninundate/XDSGN\ninundation/M\ninure/DSG\ninvade/DRSZG\ninvader/M\ninvalid/GMDYS\ninvalidism/M\ninvaluable\ninvaluably\ninvariant\ninvasion/MS\ninvasive\ninvective/M\ninveigh/GD\ninveighs\ninveigle/ZGDRS\ninveigler/M\ninvent/ASGVD\ninvention/AMS\ninventive/PY\ninventiveness/M\ninventor/MS\ninventory/DSMG\ninverse/SMY\ninvert/SMDG\ninvest/ASDGL\ninvestigate/GNVDSX\ninvestigation/M\ninvestigator/SM\ninvestigatory\ninvestiture/MS\ninvestment/AEM\ninvestor/SM\ninveteracy/M\ninveterate\ninvidious/YP\ninvidiousness/M\ninvigilate/GNDS\ninvigilator/S\ninvigorate/ADSG\ninvigorating/Y\ninvigoration/M\ninvincibility/M\ninvincibly\ninviolability/M\ninviolably\ninviolate\ninvitation/SM\ninvitational/SM\ninvite/DSMG\ninvited/U\ninvitee/SM\ninviting/Y\ninvoke/DSG\ninvoluntariness/M\ninvoluntary/P\ninvolution/M\ninvolve/LDSG\ninvolvement/SM\ninward/SY\nioctl\niodide/SM\niodine/M\niodize/DSG\nion/USM\nionic\nionization/UM\nionize/UDSG\nionizer/MS\nionosphere/MS\nionospheric\niota/MS\nipecac/SM\nirascibility/M\nirascible\nirascibly\nirate/YP\nirateness/M\nire/M\nireful\nirenic\nirides\niridescence/M\niridescent/Y\niridium/M\niris/MS\nirk/SGD\nirksome/YP\nirksomeness/M\niron/MDSG\nironclad/MS\nironic\nironical/Y\nironing/M\nironmonger/S\nironmongery\nironstone/M\nironware/M\nironwood/MS\nironwork/M\nirony/SM\nirradiate/DSGN\nirradiation/M\nirrational/SMY\nirrationality/M\nirreclaimable\nirreconcilability/M\nirreconcilable\nirreconcilably\nirrecoverable\nirrecoverably\nirredeemable\nirredeemably\nirreducible\nirreducibly\nirrefutable\nirrefutably\nirregardless\nirregular/MYS\nirregularity/SM\nirrelevance/MS\nirrelevancy/MS\nirrelevant/Y\nirreligion\nirreligious\nirremediable\nirremediably\nirremovable\nirreparable\nirreparably\nirreplaceable\nirrepressible\nirrepressibly\nirreproachable\nirreproachably\nirresistible\nirresistibly\nirresolute/PYN\nirresoluteness/M\nirresolution/M\nirrespective\nirresponsibility/M\nirresponsible\nirresponsibly\nirretrievable\nirretrievably\nirreverence/M\nirreverent/Y\nirreversible\nirreversibly\nirrevocable\nirrevocably\nirrigable\nirrigate/DSGN\nirrigation/M\nirritability/M\nirritable\nirritably\nirritant/SM\nirritate/DSXGN\nirritating/Y\nirritation/M\nirrupt/DGVS\nirruption/SM\nischemia\nischemic\nisinglass/M\nisl\nisland/SZMR\nislander/M\nisle/MS\nislet/SM\nism/CM\nisms\nisn't\nisobar/MS\nisobaric\nisolate/DSMGN\nisolation/M\nisolationism/M\nisolationist/SM\nisomer/MS\nisomeric\nisomerism/M\nisometric/S\nisometrically\nisometrics/M\nisomorphic\nisosceles\nisotherm/SM\nisotope/SM\nisotopic\nisotropic\nissuance/M\nissue/ADSMG\nissuer/MS\nisthmian\nisthmus/MS\nit'd\nit'll\nit/USM\nital\nitalic/SM\nitalicization/M\nitalicize/GDS\nitalics/M\nitch/MDSG\nitchiness/M\nitchy/RPT\nitem/MS\nitemization/M\nitemize/GDS\niterate/AXGNVDS\niteration/AM\niterator/S\nitinerant/SM\nitinerary/SM\nitself\niv/U\nivory/SM\nivy/DSM\nix\nj/F\njab/SM\njabbed\njabber/SMDRZG\njabberer/M\njabbing\njabot/SM\njacaranda/MS\njack/MDGS\njackal/SM\njackass/MS\njackboot/SMD\njackdaw/MS\njacket/SMD\njackhammer/MS\njackknife/MGDS\njackknives\njackpot/MS\njackrabbit/MS\njackstraw/MS\njacquard/M\njade/MGDS\njaded/PY\njadedness/M\njadeite/M\njag/SM\njagged/TPRY\njaggedness/M\njaggies\njaguar/SM\njail/MDRZGS\njailbird/SM\njailbreak/SM\njailer/M\njailhouse/S\njalapeno/MS\njalopy/SM\njalousie/MS\njam/SM\njamb/MS\njambalaya/M\njamboree/MS\njammed\njamming\njammy/RT\njangle/DRSMZG\njangler/M\njanitor/SM\njanitorial\njapan/SM\njapanned\njapanning\njape/MGDS\njar/SM\njardiniere/SM\njarful/MS\njargon/M\njarred\njarring/Y\njasmine/SM\njasper/M\njato/MS\njaundice/DSMG\njaunt/SGMD\njauntily\njauntiness/M\njaunty/RPT\njava/M\njavelin/SM\njaw/SGMD\njawbone/DSMG\njawbreaker/MS\njawline/S\njay/SM\njaybird/SM\njaywalk/DRSZG\njaywalker/M\njaywalking/M\njazz/MDSG\njazzy/TR\njct\njealous/Y\njealousy/SM\njean/MS\njeans/M\njeep/MS\njeer/MDSG\njeering/MY\njeez\njejuna\njejune\njejunum/M\njell/DSG\njello/S\njelly/GDSM\njellybean/MS\njellyfish/MS\njellylike\njellyroll/SM\njemmy/GDS\njennet/MS\njenny/SM\njeopardize/GDS\njeopardy/M\njeremiad/MS\njerk/MDSG\njerkily\njerkin/MS\njerkiness/M\njerkwater\njerky/TRMP\njeroboam/S\njerrybuilt\njerrycan/S\njersey/MS\njest/MDRSZG\njester/M\njesting/Y\njet/SM\njetliner/SM\njetport/MS\njetsam/M\njetted\njetting\njettison/MDSG\njetty/SM\njewel/SZGMDR\njeweler/M\njewelry/SM\njg\njib/SGMD\njibbed\njibbing\njibe/MS\njiff/MS\njiffy/SM\njig's\njig/AS\njigged/A\njigger's\njigger/ASDG\njigging/A\njiggle/DSMG\njiggly\njigsaw/SMDG\njihad/SM\njihadist/SM\njilt/MDSG\njimmy/DSMG\njimsonweed/M\njingle/DSMG\njingly\njingoism/M\njingoist/SM\njingoistic\njink/DSG\njinn\njinni/M\njinrikisha/SM\njinx/MDSG\njitney/SM\njitterbug/MS\njitterbugged\njitterbugger/M\njitterbugging\njitters/M\njittery/RT\njive/MGDS\njob/SM\njobbed\njobber/SM\njobbing\njobholder/MS\njobless/P\njoblessness/M\njobshare/S\njobsworth\njobsworths\njock/MS\njockey/SGMD\njockstrap/MS\njocose/PY\njocoseness/M\njocosity/M\njocular/Y\njocularity/M\njocund/Y\njocundity/M\njodhpurs/M\njoey/S\njog/SM\njogged\njogger/SM\njogging/M\njoggle/DSMG\njohn/MS\njohnny/SM\njohnnycake/MS\njoin's\njoin/AFDSG\njoiner/FMS\njoinery/M\njoint's\njoint/EGSD\njointly/F\njoist/SM\njojoba\njoke/MZGDRS\njoker/M\njokey\njokier\njokiest\njoking/Y\njollification/SM\njollily\njolliness/M\njollity/M\njolly/TGPDRSM\njolt/MDRSZG\njolter/M\njonquil/SM\njosh/MDRSZG\njosher/M\njostle/MGDS\njot/SM\njotted\njotter/MS\njotting/MS\njoule/SM\njounce/MGDS\njouncy\njournal/MS\njournalese/M\njournalism/M\njournalist/SM\njournalistic\njourney/ZGMDRS\njourneyer/M\njourneyman/M\njourneymen\njourno/S\njoust/SZGMDR\njouster/M\njousting/M\njovial/Y\njoviality/M\njowl/MS\njowly/TR\njoy/SGMD\njoyful/YP\njoyfuller\njoyfullest\njoyfulness/M\njoyless/PY\njoylessness/M\njoyous/YP\njoyousness/M\njoyridden\njoyride/RSMZG\njoyrider/M\njoyriding/M\njoyrode\njoystick/SM\njubilant/Y\njubilation/M\njubilee/SM\njudder/GDS\njudge's\njudge/ADSG\njudgeship/M\njudgment/SM\njudgmental/Y\njudicatory/SM\njudicature/M\njudicial/Y\njudiciary/SM\njudicious/IYP\njudiciousness/IM\njudo/M\njug/SM\njugful/MS\njugged\njuggernaut/SM\njugging\njuggle/MZGDRS\njuggler/M\njugglery/M\njugular/SM\njuice/DRSMZG\njuicer/M\njuicily\njuiciness/M\njuicy/PTR\njujitsu/M\njujube/MS\njukebox/MS\njulep/SM\njulienne\njumble/MGDS\njumbo/SM\njump/MDRSZG\njumper/M\njumpily\njumpiness/M\njumpsuit/MS\njumpy/TRP\njun\njunco/SM\njunction/FISM\njuncture/FMS\njungle/MS\njunior/MS\njuniper/SM\njunk/MDRSZG\njunker/M\njunket/MDSG\njunketeer/MS\njunkie/MTRS\njunkyard/MS\njunta/SM\njuridic\njuridical/Y\njurisdiction/SM\njurisdictional\njurisprudence/M\njurist/MS\njuristic\njuror/SM\njury/ISM\njuryman/M\njurymen\njurywoman/M\njurywomen\njust/RYPT\njustice/IMS\njustifiable/U\njustifiably/U\njustification/M\njustified/U\njustify/XGDSN\njustness/M\njut/SM\njute/M\njutted\njutting\njuvenile/SM\njuxtapose/DSG\njuxtaposition/SM\nk/IFGS\nkHz\nkW\nkWh\nkabbalah\nkaboom\nkabuki/M\nkaddish/MS\nkaffeeklatch/MS\nkaffeeklatsch/MS\nkahuna/S\nkaiser/MS\nkale/M\nkaleidoscope/MS\nkaleidoscopic\nkaleidoscopically\nkamikaze/MS\nkana\nkangaroo/MS\nkanji\nkaolin/M\nkapok/M\nkappa/SM\nkaput\nkarakul/M\nkaraoke/MS\nkarat/SM\nkarate/M\nkarma/M\nkarmic\nkart/MS\nkatakana\nkatydid/SM\nkayak/SMDG\nkayaking/M\nkayo/MDSG\nkazoo/SM\nkc\nkebab/SM\nkedgeree\nkeel/MDSG\nkeelhaul/DGS\nkeen/MDRYSTGP\nkeenness/M\nkeep/MRSZG\nkeeper/M\nkeeping/M\nkeepsake/MS\nkeg/SM\nkelp/M\nkelvin/SM\nken/SM\nkenned\nkennel/SGMD\nkenning\nkeno/M\nkepi/MS\nkept\nkeratin/M\nkeratitis\nkerbside\nkerchief/SM\nkerfuffle/S\nkernel/SM\nkerosene/M\nkestrel/MS\nketch/MS\nketchup/M\nkettle/SM\nkettledrum/SM\nkey/SGMD\nkeybinding/S\nkeyboard/ZGSMDR\nkeyboarder/M\nkeyboardist/SM\nkeyhole/MS\nkeynote/MZGDRS\nkeynoter/M\nkeypad/SM\nkeypunch/ZGMDRS\nkeypuncher/M\nkeystone/MS\nkeystroke/SM\nkeyword/MS\nkg\nkhaki/SM\nkhan/MS\nkibble/DSMG\nkibbutz/MS\nkibbutzim\nkibitz/ZGDRS\nkibitzer/M\nkibosh/M\nkick/MDRSZG\nkickback/SM\nkickball/M\nkickboxing\nkicker/M\nkickoff/MS\nkickstand/MS\nkicky/RT\nkid/SM\nkidded\nkidder/SM\nkiddie/SM\nkidding\nkiddish\nkiddo/SM\nkidnap/S\nkidnapped\nkidnapper/MS\nkidnapping/MS\nkidney/SM\nkidskin/M\nkielbasa/MS\nkielbasi\nkike/S\nkill/JMDRSZG\nkilldeer/SM\nkiller/M\nkilling/M\nkilljoy/SM\nkiln/MDSG\nkilo/MS\nkilobyte/SM\nkilocycle/SM\nkilogram/SM\nkilohertz/M\nkiloliter/MS\nkilometer/MS\nkiloton/SM\nkilowatt/SM\nkilt/MDRS\nkilter/M\nkimono/MS\nkin/M\nkinase\nkind's\nkind/UPRYT\nkinda\nkindergarten/MS\nkindergartner/SM\nkindhearted/PY\nkindheartedness/M\nkindle/AGDS\nkindliness/M\nkindling/M\nkindly/URT\nkindness/UM\nkindnesses\nkindred/M\nkinds\nkine/S\nkinematic/S\nkinematics/M\nkinetic/S\nkinetically\nkinetics/M\nkinfolk/SM\nkinfolks/M\nking/MYS\nkingdom/SM\nkingfisher/SM\nkingly/RT\nkingmaker/S\nkingpin/SM\nkingship/M\nkink/MDSG\nkinkily\nkinkiness/M\nkinky/TPR\nkinsfolk/M\nkinship/M\nkinsman/M\nkinsmen\nkinswoman/M\nkinswomen\nkiosk/SM\nkip/SM\nkipped\nkipper/MDGS\nkipping\nkirsch/MS\nkismet/M\nkiss/MDRSBZG\nkisser/M\nkissoff/SM\nkissogram/S\nkit/SGMD\nkitchen/SM\nkitchenette/MS\nkitchenware/M\nkite/MS\nkith/M\nkitsch/M\nkitschy\nkitted\nkitten/MS\nkittenish\nkitting\nkitty/SM\nkiwi/MS\nkiwifruit/MS\nkl\nklaxon/S\nkleptocracy\nkleptomania/M\nkleptomaniac/SM\nkludge/GDS\nkluge/DS\nklutz/MS\nklutziness/M\nklutzy/TRP\nkm\nkn\nknack/SZMR\nknacker/GD\nknapsack/MS\nknave/SM\nknavery/M\nknavish/Y\nknead/SZGDR\nkneader/M\nknee/MDS\nkneecap/SM\nkneecapped\nkneecapping\nkneeing\nkneel/SG\nknell/SGMD\nknelt\nknew\nknicker/S\nknickerbockers/M\nknickers/M\nknickknack/MS\nknife/DSMG\nknight/MDYSG\nknighthood/MS\nknightliness/M\nknish/MS\nknit/MS\nknitted\nknitter/SM\nknitting/M\nknitwear/M\nknives\nknob/MS\nknobbly\nknobby/TR\nknock/SZGMDR\nknockabout\nknockdown/SM\nknocker/M\nknockoff/SM\nknockout/SM\nknockwurst/SM\nknoll/SM\nknot/MS\nknothole/SM\nknotted\nknotting\nknotty/TR\nknow/SB\nknowing/UYS\nknowledge/M\nknowledgeable\nknowledgeably\nknown\nknuckle/DSMG\nknuckleduster/S\nknucklehead/MS\nknurl/SGMD\nkoala/SM\nkoan/S\nkohl\nkohlrabi/M\nkohlrabies\nkola/MS\nkook/MS\nkookaburra/SM\nkookiness/M\nkooky/TPR\nkopeck/MS\nkorma\nkosher/DSG\nkowtow/GMDS\nkph\nkraal/SM\nkraut/SM!\nkrill/M\nkrona/M\nkrone/RM\nkronor\nkronur\nkrypton/M\nkt\nkuchen/SM\nkudos/M\nkudzu/SM\nkumquat/MS\nkvetch/GMDS\nkw\nl/SDXTGJ\nla/M\nlab/SM\nlabel's\nlabel/ASDG\nlabeled/U\nlabia\nlabial/SM\nlabile\nlabium/M\nlabor/SMDRZG\nlaboratory/SM\nlaborer/M\nlaborious/PY\nlaboriousness/M\nlaborsaving\nlaburnum/MS\nlabyrinth/M\nlabyrinthine\nlabyrinths\nlac/M\nlace's\nlace/UGDS\nlacerate/DSGNX\nlaceration/M\nlacewing/SM\nlacework/M\nlachrymal\nlachrymose\nlack/MDSG\nlackadaisical/Y\nlackey/SM\nlackluster\nlaconic\nlaconically\nlacquer/GMDS\nlacrosse/M\nlactate/GNDS\nlactation/M\nlacteal\nlactic\nlactose/M\nlacuna/M\nlacunae\nlacy/RT\nlad/SGMDNJ\nladder/GSMD\nladdie/SM\nladdish/P\nlade/S\nladen/U\nlading/M\nladle/DSMG\nlady/SM\nladybird/SM\nladybug/MS\nladyfinger/MS\nladylike/U\nladylove/MS\nladyship/MS\nlaetrile/M\nlag/SZMR\nlager/M\nlaggard/MYS\nlagged\nlagging/M\nlagniappe/SM\nlagoon/SM\nlaid/IA\nlain\nlair/MS\nlaird/SM\nlaity/M\nlake/MS\nlakefront/S\nlakeside\nlam/SM\nlama/MS\nlamasery/SM\nlamb/MDSG\nlambada/MS\nlambaste/GDS\nlambda/SM\nlambency/M\nlambent/Y\nlambkin/SM\nlambskin/SM\nlambswool\nlame/MYZTGDRSP\nlamebrain/MS\nlameness/M\nlament/BSMDG\nlamentably\nlamentation/MS\nlamina/M\nlaminae\nlaminar\nlaminate/MGNDS\nlamination/M\nlammed\nlamming\nlamp/MS\nlampblack/M\nlamplight/MRZ\nlamplighter/M\nlampoon/SGMD\nlamppost/SM\nlamprey/MS\nlampshade/SM\nlanai/SM\nlance/DRSMZG\nlancer/M\nlancet/SM\nland/MDRSGJ\nlandau/SM\nlandfall/MS\nlandfill/MS\nlandholder/SM\nlandholding/MS\nlanding/M\nlandlady/SM\nlandless/M\nlandline/MS\nlandlocked\nlandlord/MS\nlandlubber/MS\nlandmark/MS\nlandmass/MS\nlandmine/S\nlandowner/MS\nlandownership\nlandowning/SM\nlandscape/MZGDRS\nlandscaper/M\nlandslid\nlandslide/MGS\nlandslip/S\nlandsman/M\nlandsmen\nlandward/S\nlane/MS\nlanguage/MS\nlanguid/PY\nlanguidness/M\nlanguish/DSG\nlanguor/SM\nlanguorous/Y\nlank/RYTP\nlankiness/M\nlankness/M\nlanky/RTP\nlanolin/M\nlantern/MS\nlanthanum/M\nlanyard/MS\nlap/SM\nlaparoscopic\nlaparoscopy\nlaparotomy\nlapboard/SM\nlapdog/SM\nlapel/SM\nlapidary/SM\nlapin/SM\nlapped\nlappet/SM\nlapping\nlapse/AKGMSD\nlaptop/SM\nlapwing/MS\nlarboard/SM\nlarcenist/SM\nlarcenous\nlarceny/SM\nlarch/MS\nlard/MDRSZG\nlarder/M\nlardy/RT\nlarge/RSPMYT\nlargehearted\nlargeness/M\nlargess/M\nlargish\nlargo/SM\nlariat/SM\nlark/MDSG\nlarkspur/SM\nlarva/M\nlarvae\nlarval\nlaryngeal\nlarynges\nlaryngitis/M\nlarynx/M\nlasagna/MS\nlascivious/YP\nlasciviousness/M\nlase/ZGDRS\nlaser/M\nlash/MDSGJ\nlashing/M\nlass/MS\nlassie/SM\nlassitude/M\nlasso/SMDG\nlast/MDYSG\nlasting/Y\nlat/S\nlatch's\nlatch/UDSG\nlatchkey/SM\nlate/YTRP\nlatecomer/MS\nlatency/M\nlateness/M\nlatent\nlateral/MDYSG\nlatest/M\nlatex/M\nlath/MDRSZG\nlathe/M\nlather/GMD\nlathery\nlaths\nlatices\nlatish\nlatitude/MS\nlatitudinal\nlatitudinarian/MS\nlatrine/MS\nlatte/RSM\nlatter/MY\nlattice/MDS\nlatticework/SM\nlaud/MDSGB\nlaudably\nlaudanum/M\nlaudatory\nlaugh/BMDG\nlaughably\nlaughing/MY\nlaughingstock/SM\nlaughs\nlaughter/M\nlaunch/AGMDS\nlauncher/SM\nlaunchpad/SM\nlaunder/DRZGS\nlaunderer/M\nlaunderette/SM\nlaundress/MS\nlaundromat/MS\nlaundry/SM\nlaundryman/M\nlaundrymen\nlaundrywoman/M\nlaundrywomen\nlaureate/MS\nlaureateship/M\nlaurel/SM\nlav/SGD\nlava/M\nlavage/M\nlavaliere/SM\nlavatorial\nlavatory/SM\nlave/S\nlavender/SM\nlavish/PTGDRSY\nlavishness/M\nlaw/SM\nlawbreaker/SM\nlawbreaking/M\nlawful/UPY\nlawfulness/UM\nlawgiver/MS\nlawless/PY\nlawlessness/M\nlawmaker/MS\nlawmaking/M\nlawman/M\nlawmen\nlawn/MS\nlawnmower/SM\nlawrencium/M\nlawsuit/MS\nlawyer/SM\nlax/TRYP\nlaxative/MS\nlaxity/M\nlaxness/M\nlay/AICSGM\nlayabout/S\nlayaway/M\nlayer/CSM\nlayered\nlayering/M\nlayette/MS\nlayman/M\nlaymen\nlayoff/SM\nlayout/SM\nlayover/MS\nlaypeople\nlayperson/MS\nlayup/SM\nlaywoman/M\nlaywomen\nlaze/MGDS\nlazily\nlaziness/M\nlazy/DRSTGP\nlazybones/M\nlb/S\nlbw\nlea/SM\nleach/DSG\nlead/MDNRSZG\nleader/M\nleaderless\nleadership/SM\nleading/M\nleaf/MDSG\nleafage/M\nleafless\nleaflet/GMDS\nleafstalk/MS\nleafy/RT\nleague/DSMG\nleak/MDSG\nleakage/MS\nleakiness/M\nleaky/PRT\nlean/MDRSTGJP\nleaning/M\nleanness/M\nleap/MDRSZG\nleaper/M\nleapfrog/MS\nleapfrogged\nleapfrogging\nlearn/AUGDS\nlearnedly\nlearner/MS\nlearning's\nlease/ADSMG\nleaseback/SM\nleasehold/MRSZ\nleaseholder/M\nleaser/SM\nleash's\nleash/UDSG\nleast/M\nleastwise\nleather/MS\nleatherette/M\nleatherneck/MS\nleathery\nleave/DRSMZGJ\nleaven/SGMD\nleavened/U\nleavening/M\nleaver/M\nleavings/M\nlech/MDRSZG\nlecher/M\nlecherous/PY\nlecherousness/M\nlechery/M\nlecithin/M\nlectern/MS\nlecture/MZGDRS\nlecturer/M\nlectureship/SM\nledge/RSMZ\nledger/M\nlee/RSMZ\nleech/MDSG\nleek/MS\nleer/MDG\nleeriness/M\nleery/RPT\nleeward/SM\nleeway/M\nleft/MRST\nleftism/M\nleftist/SM\nleftmost\nleftover/SM\nleftward/S\nlefty/SM\nleg/SM\nlegacy/SM\nlegal/SMY\nlegalese/M\nlegalism/MS\nlegalistic\nlegalistically\nlegality/SM\nlegalization/M\nlegalize/GDS\nlegate/CXMNS\nlegatee/MS\nlegation's/AC\nlegato/SM\nlegend/SM\nlegendarily\nlegendary\nlegerdemain/M\nlegged\nlegginess/M\nlegging/MS\nleggy/RPT\nleghorn/MS\nlegibility/M\nlegible\nlegibly\nlegion/SM\nlegionary/SM\nlegionnaire/SM\nlegislate/DSGNV\nlegislation/M\nlegislative/Y\nlegislator/MS\nlegislature/SM\nlegit\nlegitimacy/M\nlegitimate/DSYG\nlegitimatize/GDS\nlegitimization/M\nlegitimize/DSG\nlegless\nlegman/M\nlegmen\nlegroom/SM\nlegume/MS\nleguminous\nlegwarmer/S\nlegwork/M\nlei/SM\nleisure/DMY\nleisureliness/M\nleisurewear/M\nleitmotif/MS\nleitmotiv/MS\nlemma/S\nlemme/JG\nlemming/M\nlemon/SM\nlemonade/SM\nlemongrass\nlemony\nlemur/SM\nlend/RSZG\nlender/M\nlength/MNX\nlengthen/GD\nlengthily\nlengthiness/M\nlengths\nlengthwise\nlengthy/PRT\nlenience/M\nleniency/M\nlenient/Y\nlenitive\nlens/MS\nlent\nlentil/MS\nlento\nleonine\nleopard/SM\nleopardess/MS\nleotard/SM\nleper/SM\nleprechaun/MS\nleprosy/M\nleprous\nlepta\nlepton/MS\nlesbian/SM\nlesbianism/M\nlesion/MS\nless/MNRX\nlessee/MS\nlessen/GD\nlesson/MS\nlessor/MS\nlet/ISM\nletdown/SM\nlethal/Y\nlethargic\nlethargically\nlethargy/M\nletter/ZGMDRS\nletterbomb/S\nletterbox/S\nlettered/U\nletterer/M\nletterhead/MS\nlettering/M\nletterpress/M\nletting/S\nlettuce/MS\nletup/SM\nleucotomy/S\nleukemia/M\nleukemic/SM\nleukocyte/MS\nlevee/SM\nlevel/PSZGMDRY\nleveler/M\nlevelheaded/P\nlevelheadedness/M\nlevelness/M\nlever/SGMD\nleverage's\nleverage/CDSG\nleviathan/MS\nlevier/M\nlevitate/DSGN\nlevitation/M\nlevity/M\nlevy/DRSMZG\nlewd/RYPT\nlewdness/M\nlexer/S\nlexical\nlexicographer/MS\nlexicographic\nlexicographical\nlexicography/M\nlexicon/SM\nlexis\nlg\nliabilities\nliability/AM\nliable/A\nliaise/GDS\nliaison/MS\nliar/MS\nlib/M\nlibation/SM\nlibber/MS\nlibel/SZGMDR\nlibeler/M\nlibelous\nliberal/MYPS\nliberalism/M\nliberality/M\nliberalization/SM\nliberalize/GDS\nliberalness/M\nliberate/CDSGN\nliberation/CM\nliberator/MS\nlibertarian/SM\nlibertine/MS\nliberty/SM\nlibidinal\nlibidinous\nlibido/MS\nlibrarian/MS\nlibrarianship\nlibrary/SM\nlibrettist/MS\nlibretto/SM\nlice\nlicense/MGDS\nlicensed/U\nlicensee/MS\nlicentiate/SM\nlicentious/YP\nlicentiousness/M\nlichen/MS\nlicit/Y\nlick/MDJSG\nlicking/M\nlicorice/SM\nlid/SM\nlidded\nlidless\nlido/MS\nlie/DSM\nlied/MR\nlief/RT\nliege/SM\nlien/MS\nlieu/M\nlieutenancy/M\nlieutenant/MS\nlife/MZR\nlifebelt/S\nlifeblood/M\nlifeboat/MS\nlifebuoy/MS\nlifeforms\nlifeguard/SM\nlifeless/YP\nlifelessness/M\nlifelike\nlifeline/MS\nlifelong\nlifer/M\nlifesaver/SM\nlifesaving/M\nlifespan/S\nlifestyle/SM\nlifetime/MS\nlifework/MS\nlift/MDRSZG\nlifter/M\nliftoff/SM\nligament/MS\nligate/GNDS\nligation/M\nligature/MGDS\nlight's/C\nlight/CASTGD\nlighted/U\nlighten/SDRZG\nlightener/M\nlighter/SM\nlightface/MD\nlightheaded\nlighthearted/YP\nlightheartedness/M\nlighthouse/MS\nlighting's\nlightly\nlightness/M\nlightning/MDS\nlightproof\nlightship/MS\nlightweight/SM\nligneous\nlignite/M\nlii\nlikability/M\nlikable/P\nlikableness/M\nlike/EMGDST\nlikelihood/UM\nlikelihoods\nlikeliness/UM\nlikely/UPRT\nliken/SGD\nlikeness/UM\nlikenesses\nliker\nlikewise\nliking/M\nlilac/SM\nlilliputian\nlilo/S\nlilt/MDSG\nlily/SM\nlimb/MS\nlimber/UDSG\nlimberness/M\nlimbless\nlimbo/SM\nlime/MGDS\nlimeade/SM\nlimelight/M\nlimerick/SM\nlimescale\nlimestone/M\nlimey/S\nlimit's\nlimit/CSZGDR\nlimitation/CM\nlimitations\nlimited/U\nlimiter's\nlimiting/S\nlimitless/P\nlimitlessness/M\nlimn/DSG\nlimo/MS\nlimousine/MS\nlimp/MDRYSPTG\nlimpet/MS\nlimpid/YP\nlimpidity/M\nlimpidness/M\nlimpness/M\nlimy/RT\nlinage/M\nlinchpin/SM\nlinden/MS\nline/MZGDRSJ\nlineage/MS\nlineal/Y\nlineament/SM\nlinear/Y\nlinearity/M\nlinebacker/MS\nlined/U\nlinefeed\nlineman/M\nlinemen\nlinen/SM\nlinens/M\nliner/M\nlinesman/M\nlinesmen\nlineup/MS\nling/M\nlinger/ZGJDRS\nlingerer/M\nlingerie/M\nlingering/Y\nlingo/M\nlingoes\nlingual\nlinguine/M\nlinguist/SM\nlinguistic/S\nlinguistically\nlinguistics/M\nliniment/SM\nlining/M\nlink/MDRSG\nlinkage/MS\nlinkman\nlinkmen\nlinkup/MS\nlinnet/MS\nlino\nlinoleum/M\nlinseed/M\nlint's\nlint/CDG\nlintel/MS\nlints\nlinty/TR\nlion/MS\nlioness/MS\nlionhearted\nlionization/M\nlionize/GDS\nlip/SM\nlipid/SM\nliposuction/M\nlipped\nlippy\nlipread/GRS\nlipreader/M\nlipreading/M\nlipstick/MDSG\nliq\nliquefaction/M\nliquefy/DSG\nliqueur/SM\nliquid/MS\nliquidate/XGNDS\nliquidation/M\nliquidator/MS\nliquidity/M\nliquidize/ZGDRS\nliquidizer/M\nliquor/MDGS\nlira/M\nlire\nlisle/M\nlisp/MDRSZG\nlisper/M\nlissome\nlist/MDNSJXG\nlisted/U\nlisten/BMDRZG\nlistener/M\nlisteria\nlisting/M\nlistless/YP\nlistlessness/M\nlit/ZR\nlitany/SM\nlitchi/MS\nlite\nliter/M\nliteracy/M\nliteral/SMYP\nliteralness/M\nliterariness/M\nliterary/P\nliterate/SMY\nliterati/M\nliterature/M\nlithe/RPYT\nlitheness/M\nlithesome\nlithium/M\nlithograph/MDRZG\nlithographer/M\nlithographic\nlithographically\nlithographs\nlithography/M\nlithosphere/SM\nlitigant/SM\nlitigate/DSGN\nlitigation/M\nlitigator/MS\nlitigious/P\nlitigiousness/M\nlitmus/M\nlitotes/M\nlitter/MDRSZG\nlitterateur/MS\nlitterbug/MS\nlitterer/M\nlittle/MTRP\nlittleness/M\nlittoral/SM\nliturgical/Y\nliturgist/SM\nliturgy/SM\nlivability/M\nlivable/U\nlive/ATGDSB\nlivelihood/SM\nliveliness/M\nlivelong/S\nlively/PRT\nliven/SGD\nliver's\nliver/S\nliveried\nliverish\nliverwort/MS\nliverwurst/M\nlivery/CSM\nliveryman/CM\nliverymen/C\nlivestock/M\nliveware\nlivid/Y\nliving/MS\nlix/K\nlizard/MS\nll\nllama/SM\nllano/SM\nlo\nload's\nload/AUGSD\nloadable\nloader/MS\nloading's\nloaf/MDRSZG\nloafer/M\nloam/M\nloamy/TR\nloan/MDRSZG\nloaner/M\nloansharking/M\nloanword/MS\nloath/JZGDRS\nloathe\nloather/M\nloathing/M\nloathsome/PY\nloathsomeness/M\nloaves\nlob/SMD\nlobar\nlobbed\nlobber/MS\nlobbing\nlobby/GDSM\nlobbyist/MS\nlobe/MS\nlobotomize/DSG\nlobotomy/SM\nlobster/MS\nlocal/SMY\nlocale/MS\nlocality/SM\nlocalization/M\nlocalize/DSG\nlocate/EAGNDS\nlocation's/A\nlocation/ESM\nlocator/MS\nlocavore/SM\nloci\nlock/MDRSBZG\nlocker/M\nlocket/MS\nlockjaw/M\nlockout/MS\nlocksmith/M\nlocksmiths\nlockstep/M\nlockup/MS\nloco/S\nlocomotion/M\nlocomotive/MS\nlocoweed/SM\nlocum/S\nlocus/M\nlocust/SM\nlocution/MS\nlode/MS\nlodestar/MS\nlodestone/MS\nlodge/DRSJMZG\nlodger/M\nlodging/M\nlodgings/M\nloft/MDSG\nloftily\nloftiness/M\nlofty/PRT\nlog/SM\nloganberry/SM\nlogarithm/SM\nlogarithmic\nlogbook/SM\nloge/MS\nlogged\nlogger/SM\nloggerhead/SM\nloggia/SM\nlogging/M\nlogic/M\nlogical/Y\nlogicality/M\nlogician/MS\nlogin/S\nlogistic/S\nlogistical/Y\nlogistics/M\nlogjam/SM\nlogo/MS\nlogoff/S\nlogon/S\nlogotype/SM\nlogout/S\nlogrolling/M\nlogy/RT\nloin/MS\nloincloth/M\nloincloths\nloiter/ZGSDR\nloiterer/M\nloitering/M\nlolcat/SM\nloll/DSG\nlollipop/SM\nlollop/GSD\nlolly/S\nlollygag/S\nlollygagged\nlollygagging\nlone/YZR\nloneliness/M\nlonely/PTR\nloner/M\nlonesome/YP\nlonesomeness/M\nlong's\nlong/KDSTG\nlongboat/MS\nlongbow/MS\nlonger\nlongevity/M\nlonghair/MS\nlonghand/M\nlonghorn/MS\nlonghouse/S\nlonging/MYS\nlongish\nlongitude/MS\nlongitudinal/Y\nlongshoreman/M\nlongshoremen\nlongsighted\nlongstanding\nlongtime\nlongueur/SM\nlongways\nloo\nloofah/M\nloofahs\nlook/MDRSZG\nlookalike/MS\nlooker/M\nlookout/MS\nlookup\nloom/MDSG\nloon/MS\nloonie/M\nloony/RSMT\nloop/MDSG\nloophole/MS\nloopy/RT\nloos/NRX\nloose/UDSTG\nloosely\nloosen/UGSD\nlooseness/M\nloot/MDRSZG\nlooter/M\nlooting/M\nlop/S\nlope/MGDS\nlopped\nlopping\nlopsided/YP\nlopsidedness/M\nloquacious/PY\nloquaciousness/M\nloquacity/M\nlord/MDYSG\nlordliness/M\nlordly/TPR\nlordship/SM\nlore/M\nlorgnette/SM\nloris/MS\nlorn\nlorry/SM\nlose/ZGRSJ\nloser/M\nlosing/M\nloss/MS\nlossless\nlost\nlot/SM\nlotion/SM\nlottery/SM\nlotto/M\nlotus/MS\nlouche\nloud/RYTP\nloudhailer/SM\nloudmouth/MD\nloudmouths\nloudness/M\nloudspeaker/MS\nlough\nloughs\nlounge/MZGDRS\nlounger/M\nlour/DSG\nlouse's\nlouse/CDSG\nlousily\nlousiness/M\nlousy/TPR\nlout/MS\nloutish/PY\nlouver/MDS\nlovableness/M\nlovably\nlove/MYZGDRSB\nlovebird/SM\nlovechild/M\nloved/U\nloveless\nloveliness/M\nlovelorn\nlovely/RSMTP\nlovemaking/M\nlover/M\nlovesick\nlovey/S\nloving/Y\nlow/SZTGMDRYP\nlowborn\nlowboy/MS\nlowbrow/SM\nlowdown/M\nlower/GD\nlowercase/M\nlowermost\nlowish\nlowland/SZMR\nlowlander/M\nlowlife/SM\nlowliness/M\nlowly/TPR\nlowness/M\nlox/M\nloyal/ETY\nloyaler\nloyalism/M\nloyalist/SM\nloyalties\nloyalty/EM\nlozenge/SM\nltd\nluau/MS\nlubber/MYS\nlube/MGDS\nlubricant/SM\nlubricate/DSGN\nlubrication/M\nlubricator/MS\nlubricious/Y\nlubricity/M\nlucid/PY\nlucidity/M\nlucidness/M\nluck/MDSG\nluckily/U\nluckiness/UM\nluckless\nlucky/UPTR\nlucrative/YP\nlucrativeness/M\nlucre/M\nlucubrate/GNDS\nlucubration/M\nludicrous/YP\nludicrousness/M\nludo\nluff/DSG\nlug/SM\nluge/S\nluggage/M\nlugged\nlugger/MS\nlugging\nlughole/S\nlugsail/SM\nlugubrious/YP\nlugubriousness/M\nlukewarm/YP\nlukewarmness/M\nlull/MDSG\nlullaby/SM\nlulu/S\nlumbago/M\nlumbar\nlumber/MDRZGS\nlumberer/M\nlumbering/M\nlumberjack/SM\nlumberman/M\nlumbermen\nlumberyard/SM\nluminary/SM\nluminescence/M\nluminescent\nluminosity/M\nluminous/Y\nlummox/MS\nlump/MDNSG\nlumpectomy/S\nlumpiness/M\nlumpish\nlumpy/TRP\nlunacy/SM\nlunar\nlunatic/SM\nlunch/GMDS\nlunchbox/S\nluncheon/SM\nluncheonette/SM\nlunchroom/MS\nlunchtime/MS\nlung/MDSG\nlunge/SM\nlungfish/MS\nlungful/S\nlunkhead/MS\nlupine/MS\nlupus/M\nlurch/GMDS\nlure/MGDS\nlurgy\nlurid/PY\nluridness/M\nlurk/DRSZG\nluscious/PY\nlusciousness/M\nlush/MRSYPT\nlushness/M\nlust/MDRSG\nluster/M\nlusterless\nlustful/Y\nlustily\nlustiness/M\nlustrous/Y\nlusty/PTR\nlutanist/SM\nlute/MS\nlutenist/SM\nlutetium/M\nluxuriance/M\nluxuriant/Y\nluxuriate/DSGN\nluxuriation/M\nluxurious/PY\nluxuriousness/M\nluxury/SM\nlvi\nlvii\nlxi\nlxii\nlxiv\nlxix\nlxvi\nlxvii\nlyceum/MS\nlychgate/S\nlye/MG\nlying/M\nlymph/M\nlymphatic/SM\nlymphocyte/SM\nlymphoid\nlymphoma/SM\nlynch/JZGDRS\nlyncher/M\nlynching/M\nlynx/MS\nlyre/MS\nlyrebird/MS\nlyric/SM\nlyrical/Y\nlyricism/M\nlyricist/SM\nlysosomal\nlysosomes\nm/KAS\nma'am\nma/SMH\nmac/SGMD\nmacabre\nmacadam/M\nmacadamia/SM\nmacadamize/GDS\nmacaque/MS\nmacaroni/MS\nmacaroon/MS\nmacaw/SM\nmace/MS\nmacerate/DSGN\nmaceration/M\nmach/M\nmachete/SM\nmachinate/GNDSX\nmachination/M\nmachine/DSMGB\nmachinery/M\nmachinist/MS\nmachismo/M\nmacho/M\nmackerel/SM\nmackinaw/SM\nmackintosh/MS\nmacrame/M\nmacro/SM\nmacrobiotic/S\nmacrobiotics/M\nmacrocosm/SM\nmacroeconomic/S\nmacroeconomics/M\nmacrology/S\nmacron/MS\nmacrophages\nmacroscopic\nmad/SMYP\nmadam/SM\nmadame/M\nmadcap/MS\nmadden/DGS\nmaddening/Y\nmadder/MS\nmaddest\nmadding\nmade/AU\nmademoiselle/MS\nmadhouse/SM\nmadman/M\nmadmen\nmadness/M\nmadras/MS\nmadrasa/S\nmadrassah\nmadrassahs\nmadrigal/SM\nmadwoman/M\nmadwomen\nmaelstrom/SM\nmaestro/SM\nmafia/SM\nmafiosi\nmafioso/M\nmag/SM\nmagazine/SM\nmage/MS\nmagenta/M\nmaggot/MS\nmaggoty\nmagi/M\nmagic/SM\nmagical/Y\nmagician/SM\nmagicked\nmagicking\nmagisterial/Y\nmagistracy/M\nmagistrate/SM\nmagma/M\nmagnanimity/M\nmagnanimous/Y\nmagnate/SM\nmagnesia/M\nmagnesium/M\nmagnet/MS\nmagnetic\nmagnetically\nmagnetism/M\nmagnetite/M\nmagnetizable\nmagnetization/CM\nmagnetize/CGDS\nmagneto/SM\nmagnetometer/SM\nmagnetosphere\nmagnification/M\nmagnificence/M\nmagnificent/Y\nmagnifier/M\nmagnify/ZGXDRSN\nmagniloquence/M\nmagniloquent\nmagnitude/SM\nmagnolia/MS\nmagnum/MS\nmagpie/MS\nmagus/M\nmaharajah/M\nmaharajahs\nmaharani/SM\nmaharishi/SM\nmahatma/SM\nmahogany/SM\nmahout/MS\nmaid/MNSX\nmaiden/MY\nmaidenhair/M\nmaidenhead/SM\nmaidenhood/M\nmaidservant/SM\nmail/JMDRSZG\nmailbag/SM\nmailbomb/GSD\nmailbox/MS\nmailer/M\nmailing/M\nmaillot/SM\nmailman/M\nmailmen\nmailshot/S\nmaim/DSG\nmain/MYS\nmainframe/SM\nmainland/MS\nmainline/MGDS\nmainmast/MS\nmainsail/MS\nmainspring/MS\nmainstay/MS\nmainstream/SMDG\nmaintain/ZGBDRS\nmaintainability\nmaintenance/M\nmaintop/SM\nmaisonette/MS\nmaize/SM\nmajestic\nmajestically\nmajesty/SM\nmajolica/M\nmajor/SGMDY\nmajordomo/MS\nmajorette/MS\nmajoritarian/SM\nmajoritarianism\nmajority/SM\nmake's/A\nmake/UAGS\nmakeover/MS\nmaker/SM\nmakeshift/SM\nmakeup/MS\nmakeweight/S\nmaking/MS\nmakings/M\nmalachite/M\nmaladjusted\nmaladjustment/M\nmaladministration\nmaladroit/PY\nmaladroitness/M\nmalady/SM\nmalaise/M\nmalamute/MS\nmalapropism/SM\nmalaria/M\nmalarial\nmalarkey/M\nmalathion/M\nmalcontent/MS\nmale/MPS\nmalediction/SM\nmalefaction/M\nmalefactor/SM\nmalefic\nmaleficence/M\nmaleficent\nmaleness/M\nmalevolence/M\nmalevolent/Y\nmalfeasance/M\nmalformation/SM\nmalformed\nmalfunction/MDSG\nmalice/M\nmalicious/PY\nmaliciousness/M\nmalign/DSG\nmalignancy/SM\nmalignant/Y\nmalignity/M\nmalinger/ZGSDR\nmalingerer/M\nmall/MS\nmallard/SM\nmalleability/M\nmalleable\nmallet/MS\nmallow/MS\nmalnourished\nmalnutrition/M\nmalocclusion/M\nmalodorous\nmalpractice/SM\nmalt/MDSG\nmalted/MS\nmaltose/M\nmaltreat/GLDS\nmaltreatment/M\nmalty/TR\nmalware/M\nmam/S\nmama/MS\nmamba/SM\nmambo/SGMD\nmamma/M\nmammal/MS\nmammalian/MS\nmammary\nmammogram/MS\nmammography/M\nmammon/M\nmammoth/M\nmammoths\nmammy/SM\nman's/F\nman/USY\nmanacle/DSMG\nmanage/ZGDRSL\nmanageability/M\nmanageable/U\nmanagement/MS\nmanager/M\nmanageress/S\nmanagerial\nmanana/MS\nmanatee/SM\nmandala/SM\nmandamus/MS\nmandarin/MS\nmandate/DSMG\nmandatory\nmandible/MS\nmandibular\nmandolin/MS\nmandrake/MS\nmandrel/SM\nmandrill/MS\nmane/MDS\nmanege/M\nmaneuver/MDGSBJ\nmaneuverability/M\nmanful/Y\nmanga/M\nmanganese/M\nmange/DRMZ\nmanger/M\nmangetout/S\nmanginess/M\nmangle/MZGDRS\nmango/M\nmangoes\nmangrove/MS\nmangy/TRP\nmanhandle/GDS\nmanhole/SM\nmanhood/M\nmanhunt/SM\nmania/SM\nmaniac/MS\nmaniacal/Y\nmanic/SM\nmanically\nmanicure/MGDS\nmanicurist/MS\nmanifest/MDYSG\nmanifestation/SM\nmanifesto/SM\nmanifold/GMDS\nmanikin/SM\nmanila/M\nmanioc/MS\nmanipulable\nmanipulate/XGNVDS\nmanipulation/M\nmanipulative/Y\nmanipulator/MS\nmankind/M\nmanky\nmanlike\nmanliness/M\nmanly/UTR\nmanna/M\nmanned/U\nmannequin/SM\nmanner/MDYS\nmannerism/SM\nmannerly/U\nmanning/U\nmannish/YP\nmannishness/M\nmanometer/SM\nmanor/SM\nmanorial\nmanpower/M\nmanque\nmansard/MS\nmanse/SXMN\nmanservant/M\nmansion/M\nmanslaughter/M\nmanta/SM\nmantel/MS\nmantelpiece/SM\nmantelshelf\nmantelshelves\nmantes\nmantilla/SM\nmantis/MS\nmantissa/SM\nmantle's\nmantle/EGDS\nmantra/MS\nmanual/MYS\nmanufacture/DRSMZG\nmanufacturer/M\nmanufacturing/M\nmanumission/SM\nmanumit/S\nmanumitted\nmanumitting\nmanure/MGDS\nmanuscript/MS\nmany/M\nmap's\nmap/AS\nmaple/SM\nmapmaker/SM\nmapped/A\nmapper/MS\nmapping/S\nmar/S\nmarabou/MS\nmarabout/SM\nmaraca/MS\nmaraschino/MS\nmarathon/SMRZ\nmarathoner/M\nmaraud/ZGDRS\nmarauder/M\nmarble/MGDS\nmarbleize/GDS\nmarbling/M\nmarch/ZGMDRS\nmarcher/M\nmarchioness/MS\nmare/MS\nmargarine/M\nmargarita/MS\nmarge\nmargin/MS\nmarginal/YS\nmarginalia/M\nmarginalization/M\nmarginalize/GDS\nmaria/M\nmariachi/MS\nmarigold/MS\nmarijuana/M\nmarimba/SM\nmarina/MS\nmarinade/DSMG\nmarinara/M\nmarinate/DSGN\nmarination/M\nmarine/MZRS\nmariner/M\nmarionette/MS\nmarital/Y\nmaritime\nmarjoram/M\nmark/AMDSG\nmarkdown/SM\nmarked/U\nmarkedly\nmarker/MS\nmarket/MDRZGBS\nmarketability/M\nmarketable/U\nmarketeer/SM\nmarketer/M\nmarketing/M\nmarketplace/SM\nmarking/SM\nmarkka/M\nmarkkaa\nmarksman/M\nmarksmanship/M\nmarksmen\nmarkup/MS\nmarl/M\nmarlin/MS\nmarlinespike/SM\nmarmalade/M\nmarmoreal\nmarmoset/SM\nmarmot/MS\nmaroon/MDGS\nmarque/MS\nmarquee/SM\nmarquess/MS\nmarquetry/M\nmarquis/MS\nmarquise/M\nmarquisette/M\nmarred/U\nmarriage/ASM\nmarriageability/M\nmarriageable\nmarried/SM\nmarring\nmarrow/MS\nmarry/AGDS\nmarsh/MS\nmarshal/SMDG\nmarshland/SM\nmarshmallow/SM\nmarshy/RT\nmarsupial/MS\nmart/MNSX\nmarten/M\nmartensite\nmartial/Y\nmartian/S\nmartin/MS\nmartinet/MS\nmartingale/MS\nmartini/SM\nmartyr/MDGS\nmartyrdom/M\nmarvel/MDGS\nmarvelous/Y\nmarzipan/M\nmasc\nmascara/GMDS\nmascot/MS\nmasculine/SM\nmasculinity/M\nmaser/SM\nmash/MDRSZG\nmasher/M\nmashup/MS\nmask's\nmask/UDSG\nmasker/MS\nmasochism/M\nmasochist/SM\nmasochistic\nmasochistically\nmason/SM\nmasonic\nmasonry/M\nmasque/MS\nmasquerade/DRSMZG\nmasquerader/M\nmass/MDSGV\nmassacre/MGDS\nmassage/DSMG\nmasseur/SM\nmasseuse/MS\nmassif/MS\nmassive/PY\nmassiveness/M\nmast/MDS\nmastectomy/SM\nmaster's\nmaster/ADGS\nmasterclass/S\nmasterful/Y\nmasterly\nmastermind/SGMD\nmasterpiece/MS\nmasterstroke/SM\nmasterwork/MS\nmastery/M\nmasthead/MS\nmastic/M\nmasticate/GNDS\nmastication/M\nmastiff/SM\nmastitis\nmastodon/SM\nmastoid/SM\nmasturbate/GNDS\nmasturbation/M\nmasturbatory\nmat/SZGMDR\nmatador/SM\nmatch/AMS\nmatchbook/SM\nmatchbox/MS\nmatched/U\nmatching\nmatchless\nmatchlock/SM\nmatchmaker/MS\nmatchmaking/M\nmatchstick/MS\nmatchwood/M\nmate/MS\nmaterial/SMY\nmaterialism/M\nmaterialist/SM\nmaterialistic\nmaterialistically\nmaterialization/M\nmaterialize/DSG\nmateriel/M\nmaternal/Y\nmaternity/M\nmatey/S\nmath/M\nmathematical/Y\nmathematician/SM\nmathematics/M\nmaths\nmatinee/SM\nmating/M\nmatins/M\nmatriarch/M\nmatriarchal\nmatriarchs\nmatriarchy/SM\nmatrices\nmatricidal\nmatricide/MS\nmatriculate/DSGN\nmatriculation/M\nmatrimonial\nmatrimony/M\nmatrix/M\nmatron/MYS\nmatte/DRSMZG\nmatter/MDG\nmatting/M\nmattock/SM\nmattress/MS\nmaturate/GNDS\nmaturation/M\nmature/YTGDRS\nmaturity/SM\nmatzo/SMH\nmatzoh/M\nmatzohs\nmatzot\nmaudlin\nmaul/MDRSZG\nmauler/M\nmaunder/SDG\nmausoleum/SM\nmauve/M\nmaven/SM\nmaverick/SM\nmaw/SM\nmawkish/PY\nmawkishness/M\nmax/GMDS\nmaxi/MS\nmaxilla/M\nmaxillae\nmaxillary\nmaxim/SM\nmaximal/Y\nmaximization/M\nmaximize/GDS\nmaximum/SM\nmay/M\nmaybe/SM\nmayday/MS\nmayflower/MS\nmayfly/SM\nmayhem/M\nmayn't\nmayo/M\nmayonnaise/M\nmayor/SM\nmayoral\nmayoralty/M\nmayoress/MS\nmaypole/SM\nmayst\nmaze/MS\nmazurka/MS\nmdse\nme/DSH\nmead/M\nmeadow/MS\nmeadowlark/MS\nmeager/PY\nmeagerness/M\nmeal/MS\nmealiness/M\nmealtime/SM\nmealy/TPR\nmealybug/SM\nmealymouthed\nmean/MRYJPSTG\nmeander/SMDJG\nmeanderings/M\nmeanie/M\nmeaning/M\nmeaningful/PY\nmeaningfulness/M\nmeaningless/YP\nmeaninglessness/M\nmeanness/M\nmeant/U\nmeantime/M\nmeanwhile/M\nmeany/SM\nmeas\nmeasles/M\nmeasly/RT\nmeasurable\nmeasurably\nmeasure's\nmeasure/ADSG\nmeasured/U\nmeasureless\nmeasurement/MS\nmeat/MS\nmeatball/MS\nmeathead/MS\nmeatiness/M\nmeatless\nmeatloaf/M\nmeatloaves\nmeatpacking/M\nmeaty/TPR\nmecca/SM\nmechanic/MS\nmechanical/Y\nmechanics/M\nmechanism/SM\nmechanistic\nmechanistically\nmechanization/M\nmechanize/DSG\nmedal/SM\nmedalist/MS\nmedallion/SM\nmeddle/ZGDRS\nmeddler/M\nmeddlesome\nmedia/SM\nmedial/AY\nmedian/MS\nmediate/DSGN\nmediated/U\nmediation/AM\nmediator/MS\nmedic/SM\nmedicaid/M\nmedical/SMY\nmedicament/M\nmedicare/M\nmedicate/GNXDS\nmedication/M\nmedicinal/Y\nmedicine/MS\nmedico/MS\nmedieval\nmedievalist/MS\nmediocre\nmediocrity/SM\nmeditate/DSGNVX\nmeditation/M\nmeditative/Y\nmedium/MS\nmedley/MS\nmedulla/SM\nmedusa\nmedusae\nmeed/M\nmeek/RYPT\nmeekness/M\nmeerschaum/SM\nmeet/MJSG\nmeeting/M\nmeetinghouse/SM\nmeetup\nmeg/S\nmega\nmegabit/SM\nmegabucks/M\nmegabyte/MS\nmegachurch/MS\nmegacycle/SM\nmegadeath/M\nmegadeaths\nmegahertz/M\nmegalith/M\nmegalithic\nmegaliths\nmegalomania/M\nmegalomaniac/SM\nmegalopolis/MS\nmegaphone/DSMG\nmegapixel/SM\nmegastar/S\nmegaton/SM\nmegawatt/MS\nmeh\nmeiosis/M\nmeiotic\nmelamine/M\nmelancholia/M\nmelancholic/S\nmelancholy/M\nmelange/MS\nmelanin/M\nmelanoma/SM\nmeld/MDSG\nmelee/SM\nmeliorate/GNVDS\nmelioration/M\nmellifluous/PY\nmellifluousness/M\nmellow/PTGDRYS\nmellowness/M\nmelodic\nmelodically\nmelodious/YP\nmelodiousness/M\nmelodrama/MS\nmelodramatic/S\nmelodramatically\nmelodramatics/M\nmelody/SM\nmelon/SM\nmelt's\nmelt/ADSG\nmeltdown/SM\nmember's\nmember/EAS\nmembership/SM\nmembrane/SM\nmembranous\nmeme/S\nmemento/MS\nmemo/MS\nmemoir/MS\nmemorabilia/M\nmemorability/M\nmemorable/U\nmemorably\nmemorandum/MS\nmemorial/SM\nmemorialize/DSG\nmemorization/M\nmemorize/DSG\nmemory/SM\nmemsahib/S\nmen/M\nmenace/MGDS\nmenacing/Y\nmenage/MS\nmenagerie/MS\nmend/MDRSZG\nmendacious/Y\nmendacity/M\nmendelevium/M\nmender/M\nmendicancy/M\nmendicant/SM\nmending/M\nmenfolk/MS\nmenfolks/M\nmenhaden/M\nmenial/MYS\nmeningeal\nmeninges\nmeningitis/M\nmeninx/M\nmenisci\nmeniscus/M\nmenopausal\nmenopause/M\nmenorah/M\nmenorahs\nmensch/MS\nmenservants\nmenses/M\nmenstrual\nmenstruate/GNDS\nmenstruation/M\nmensurable\nmensuration/M\nmenswear/M\nmental/Y\nmentalist/SM\nmentality/SM\nmenthol/M\nmentholated\nmention/GSMD\nmentioned/U\nmentor/MDSG\nmenu/MS\nmeow/MDSG\nmercantile\nmercantilism/M\nmercenary/SM\nmercer/MS\nmercerize/GDS\nmerchandise/MZGDRS\nmerchandiser/M\nmerchandising/M\nmerchant/MBS\nmerchantman/M\nmerchantmen\nmerciful/UY\nmerciless/PY\nmercilessness/M\nmercurial/Y\nmercuric\nmercury/M\nmercy/SM\nmere/MYTS\nmeretricious/YP\nmeretriciousness/M\nmerganser/MS\nmerge/DRSZG\nmerger/M\nmeridian/MS\nmeringue/MS\nmerino/MS\nmerit/CSM\nmerited/U\nmeriting\nmeritocracy/SM\nmeritocratic\nmeritorious/PY\nmeritoriousness/M\nmermaid/SM\nmerman/M\nmermen\nmerrily\nmerriment/M\nmerriness/M\nmerry/TRP\nmerrymaker/MS\nmerrymaking/M\nmesa/MS\nmescal/MS\nmescalin\nmescaline/M\nmesdames\nmesdemoiselles\nmesh/MDSG\nmesmeric\nmesmerism/M\nmesmerize/ZGDRS\nmesmerizer/M\nmesomorph/M\nmesomorphs\nmeson/SM\nmesosphere/SM\nmesquite/SM\nmess/MDSG\nmessage/MGDS\nmesseigneurs\nmessenger/SM\nmessiah/M\nmessiahs\nmessianic\nmessieurs\nmessily\nmessiness/M\nmessmate/SM\nmessy/PTR\nmestizo/MS\nmet\nmeta\nmetabolic\nmetabolically\nmetabolism/SM\nmetabolite/SM\nmetabolize/DSG\nmetacarpal/SM\nmetacarpi\nmetacarpus/M\nmetadata\nmetal/SMD\nmetalanguage/MS\nmetallic\nmetallurgic\nmetallurgical\nmetallurgist/MS\nmetallurgy/M\nmetalwork/MRZG\nmetalworker/M\nmetalworking/M\nmetamorphic\nmetamorphism/M\nmetamorphose/GDS\nmetamorphosis/M\nmetaphor/MS\nmetaphoric\nmetaphorical/Y\nmetaphysical/Y\nmetaphysics/M\nmetastases\nmetastasis/M\nmetastasize/DSG\nmetastatic\nmetatarsal/MS\nmetatarsi\nmetatarsus/M\nmetatheses\nmetathesis/M\nmete/MZGDRS\nmetempsychoses\nmetempsychosis/M\nmeteor/MS\nmeteoric\nmeteorically\nmeteorite/SM\nmeteoroid/SM\nmeteorologic\nmeteorological\nmeteorologist/SM\nmeteorology/M\nmeter/GMD\nmethadone/M\nmethamphetamine/M\nmethane/M\nmethanol/M\nmethinks\nmethod/MS\nmethodical/YP\nmethodicalness/M\nmethodological/Y\nmethodology/SM\nmethotrexate\nmethought\nmeths\nmethyl/M\nmeticulous/YP\nmeticulousness/M\nmetier/MS\nmetric/S\nmetrical/Y\nmetricate/GNDS\nmetrication/M\nmetricize/GDS\nmetro/SM\nmetronome/MS\nmetropolis/MS\nmetropolitan\nmettle/M\nmettlesome\nmew/SGMD\nmewl/DSG\nmews/M\nmezzanine/MS\nmezzo/SM\nmfg\nmfr/S\nmg\nmgr\nmi/MNX\nmiasma/MS\nmic/S\nmica/M\nmice\nmick/S\nmickey/MS\nmicro/SM\nmicrobe/MS\nmicrobial\nmicrobiological\nmicrobiologist/MS\nmicrobiology/M\nmicrobrewery/SM\nmicrochip/MS\nmicrocircuit/SM\nmicrocode\nmicrocomputer/MS\nmicrocosm/MS\nmicrocosmic\nmicrodot/SM\nmicroeconomics/M\nmicroelectronic/S\nmicroelectronics/M\nmicrofiber/MS\nmicrofiche/M\nmicrofilm/GMDS\nmicrofloppies\nmicrogroove/SM\nmicrolight/MS\nmicroloan/MS\nmicromanage/GDSL\nmicromanagement/M\nmicrometeorite/SM\nmicrometer/MS\nmicron/MS\nmicroorganism/MS\nmicrophone/SM\nmicroprocessor/MS\nmicroscope/SM\nmicroscopic\nmicroscopical/Y\nmicroscopy/M\nmicrosecond/MS\nmicrosurgery/M\nmicrowave/DSMGB\nmicrowaveable\nmid\nmidair/M\nmidday/M\nmidden/MS\nmiddle/MGS\nmiddlebrow/SM\nmiddleman/M\nmiddlemen\nmiddlemost\nmiddleweight/MS\nmiddy/SM\nmidfield/RZ\nmidge/SM\nmidget/MS\nmidi/MS\nmidland/MS\nmidlife/M\nmidmost\nmidnight/M\nmidpoint/MS\nmidrib/MS\nmidriff/MS\nmidsection/MS\nmidshipman/M\nmidshipmen\nmidships\nmidsize\nmidst/M\nmidstream/M\nmidsummer/M\nmidterm/MS\nmidtown/M\nmidway/MS\nmidweek/MS\nmidwife/MGDS\nmidwifery/SM\nmidwinter/M\nmidwives\nmidyear/MS\nmien/M\nmiff/DSG\nmight've\nmight/M\nmightily\nmightiness/M\nmightn't\nmighty/TRP\nmignonette/SM\nmigraine/MS\nmigrant/MS\nmigrate/AGDS\nmigration/SM\nmigratory\nmikado/MS\nmike/MGDS\nmil/SZMR\nmilady/SM\nmilch\nmild/MRYTP\nmildew/SMDG\nmildness/M\nmile/MS\nmileage/SM\nmilepost/MS\nmiler/M\nmilestone/MS\nmilf/MS\nmilieu/SM\nmilitancy/M\nmilitant/MYS\nmilitarily\nmilitarism/M\nmilitarist/SM\nmilitaristic\nmilitarization/CM\nmilitarize/CDSG\nmilitary/M\nmilitate/GDS\nmilitia/SM\nmilitiaman/M\nmilitiamen\nmilk/MDRSZG\nmilker/M\nmilkiness/M\nmilkmaid/MS\nmilkman/M\nmilkmen\nmilkshake/SM\nmilksop/MS\nmilkweed/SM\nmilky/RTP\nmill/MDRSZGJ\nmillage/M\nmillennia\nmillennial/MS\nmillennium/MS\nmiller/M\nmillet/M\nmilliard/MS\nmillibar/MS\nmilligram/MS\nmilliliter/MS\nmillimeter/MS\nmilliner/MS\nmillinery/M\nmilling/M\nmillion/HSM\nmillionaire/SM\nmillionairess/S\nmillionth/M\nmillionths\nmillipede/SM\nmillisecond/SM\nmillpond/SM\nmillrace/SM\nmillstone/SM\nmillstream/MS\nmillwright/SM\nmilometer/S\nmilquetoast/SM\nmilt/MDSG\nmime/MGDS\nmimeograph/GMD\nmimeographs\nmimetic\nmimic/SM\nmimicked\nmimicker/SM\nmimicking\nmimicry/SM\nmimosa/SM\nmin\nminaret/MS\nminatory\nmince/DRSMZG\nmincemeat/M\nmincer/M\nmind's\nmind/ADRSZG\nmindbogglingly\nminded/P\nmindful/YP\nmindfulness/M\nmindless/YP\nmindlessness/M\nmindset/MS\nmine/MZGNDRSX\nminefield/SM\nminer/M\nmineral/MS\nmineralogical\nmineralogist/MS\nmineralogy/M\nminestrone/M\nminesweeper/SM\nmingle/DSG\nmingy\nmini/MS\nminiature/MS\nminiaturist/MS\nminiaturization/M\nminiaturize/GDS\nminibar/S\nminibike/SM\nminibus/MS\nminicab/S\nminicam/MS\nminicomputer/SM\nminifloppies\nminim/SM\nminimal/Y\nminimalism/M\nminimalist/MS\nminimization\nminimize/DSG\nminimum/MS\nmining/M\nminion/M\nminiseries/M\nminiskirt/MS\nminister/SGMD\nministerial\nministrant/MS\nministration/MS\nministry/SM\nminivan/MS\nmink/MS\nminnesinger/MS\nminnow/SM\nminor/SMDG\nminority/SM\nminoxidil/M\nminster/MS\nminstrel/SM\nminstrelsy/M\nmint/MDRSZG\nmintage/M\nminter/M\nminty/RT\nminuend/MS\nminuet/SM\nminus/MS\nminuscule/MS\nminute/PDRSMYTG\nminuteman/M\nminutemen\nminuteness/M\nminutia/M\nminutiae\nminx/MS\nmiracle/MS\nmiraculous/Y\nmirage/SM\nmire/MGDS\nmirror/GSMD\nmirth/M\nmirthful/PY\nmirthfulness/M\nmirthless/Y\nmiry/RT\nmisaddress/DSG\nmisadventure/MS\nmisaligned\nmisalignment/M\nmisalliance/MS\nmisanthrope/SM\nmisanthropic\nmisanthropically\nmisanthropist/MS\nmisanthropy/M\nmisapplication/M\nmisapply/DSGNX\nmisapprehend/GSD\nmisapprehension/MS\nmisappropriate/XDSGN\nmisappropriation/M\nmisbegotten\nmisbehave/GDS\nmisbehavior/M\nmisc\nmiscalculate/DSXGN\nmiscalculation/M\nmiscall/DSG\nmiscarriage/MS\nmiscarry/GDS\nmiscast/SG\nmiscegenation/M\nmiscellaneous/Y\nmiscellany/SM\nmischance/SM\nmischief/M\nmischievous/YP\nmischievousness/M\nmiscibility/M\nmiscible\nmiscommunication\nmisconceive/GDS\nmisconception/SM\nmisconduct/MDGS\nmisconstruction/MS\nmisconstrue/GDS\nmiscount/MDSG\nmiscreant/SM\nmiscue/DSMG\nmisdeal/GMS\nmisdealt\nmisdeed/MS\nmisdemeanor/MS\nmisdiagnose/GDS\nmisdiagnosis/M\nmisdid\nmisdirect/SDG\nmisdirection/M\nmisdo/JG\nmisdoes\nmisdoing/M\nmisdone\nmiser/SBMY\nmiserableness/M\nmiserably\nmiserliness/M\nmisery/SM\nmisfeasance/M\nmisfeature/S\nmisfile/GDS\nmisfire/MGDS\nmisfit/SM\nmisfitted\nmisfitting\nmisfortune/SM\nmisgiving/MS\nmisgovern/SDGL\nmisgovernment/M\nmisguidance/M\nmisguide/DSG\nmisguided/Y\nmishandle/DSG\nmishap/SM\nmishear/GS\nmisheard\nmishit/S\nmishitting\nmishmash/MS\nmisidentify/GDS\nmisinform/DGS\nmisinformation/M\nmisinterpret/SGD\nmisinterpretation/SM\nmisjudge/DSG\nmisjudgment/SM\nmislabel/GSD\nmislaid\nmislay/GS\nmislead/GS\nmisleading/Y\nmisled\nmismanage/LGDS\nmismanagement/M\nmismatch/GMDS\nmisname/GDS\nmisnomer/MS\nmisogamist/MS\nmisogamy/M\nmisogynist/SM\nmisogynistic\nmisogynous\nmisogyny/M\nmisplace/GLDS\nmisplacement/M\nmisplay/GMDS\nmisprint/GMDS\nmisprision/M\nmispronounce/DSG\nmispronunciation/SM\nmisquotation/MS\nmisquote/MGDS\nmisread/GJS\nmisreading/M\nmisreport/MDGS\nmisrepresent/GDS\nmisrepresentation/MS\nmisrule/MGDS\nmiss's\nmiss/EDSGV\nmissal/ESM\nmissed/U\nmisshape/GDS\nmisshapen\nmissile/MS\nmissilery/M\nmission/AMS\nmissionary/SM\nmissioner/SM\nmissive/MS\nmisspeak/GS\nmisspell/GDJS\nmisspelling/M\nmisspend/GS\nmisspent\nmisspoke\nmisspoken\nmisstate/GDSL\nmisstatement/SM\nmisstep/MS\nmissus/MS\nmist's\nmist/CDRSZG\nmistakable/U\nmistake/BMGS\nmistaken/Y\nmister's\nmistily\nmistime/GDS\nmistiness/M\nmistletoe/M\nmistook\nmistral/MS\nmistranslated\nmistreat/LDGS\nmistreatment/M\nmistress/MS\nmistrial/MS\nmistrust/MDSG\nmistrustful/Y\nmisty/PRT\nmistype/GS\nmisunderstand/SGJ\nmisunderstanding/M\nmisunderstood\nmisuse/DSMG\nmite/MZRS\nmiter/MDG\nmitigate/DSGN\nmitigated/U\nmitigation/M\nmitochondria\nmitochondrial\nmitochondrion\nmitoses\nmitosis/M\nmitotic\nmitt/MNSX\nmitten/M\nmix/ZGMDRSB\nmixed/U\nmixer/M\nmixture/SM\nmizzen/MS\nmizzenmast/SM\nmks\nml\nmm\nmnemonic/MS\nmnemonically\nmo/CKHS\nmoan/MDRSZG\nmoaner/M\nmoat/MDS\nmob's\nmob/CS\nmobbed/C\nmobbing/C\nmobile/MS\nmobility/M\nmobilization/CM\nmobilizations\nmobilize/CDSG\nmobilizer/SM\nmobster/SM\nmoccasin/SM\nmocha/M\nmock/DRSZG\nmocker/M\nmockery/SM\nmocking/Y\nmockingbird/SM\nmod/STM\nmodal/SM\nmodality/S\nmodded\nmodding\nmode/MS\nmodel/ZGSJMDR\nmodeler/M\nmodeling/M\nmodem/SM\nmoderate/MYGNPDS\nmoderateness/M\nmoderation/M\nmoderator/SM\nmodern/MYPS\nmodernism/M\nmodernist/SM\nmodernistic\nmodernity/M\nmodernization/M\nmodernize/DRSZG\nmodernizer/M\nmodernness/M\nmodest/Y\nmodesty/M\nmodicum/SM\nmodifiable\nmodification/M\nmodified/U\nmodifier/M\nmodify/DRSXZGN\nmodish/YP\nmodishness/M\nmodular\nmodulate/CGNDS\nmodulation/CM\nmodulations\nmodulator/MS\nmodule/MS\nmodulo\nmodulus\nmoggy\nmogul/SM\nmohair/M\nmoi\nmoiety/SM\nmoil/MDSG\nmoire/SM\nmoist/XTPNRY\nmoisten/DRZG\nmoistener/M\nmoistness/M\nmoisture/M\nmoisturize/ZGDRS\nmoisturizer/M\nmolar/SM\nmolasses/M\nmold/MDRJSZG\nmoldboard/SM\nmolder/GMD\nmoldiness/M\nmolding/M\nmoldy/TPR\nmole/MS\nmolecular\nmolecularity/M\nmolecule/SM\nmolehill/SM\nmoleskin/M\nmolest/DRZGS\nmolestation/M\nmolested/U\nmolester/M\nmoll/MS\nmollification/M\nmollify/DSNG\nmolluscan\nmollusk/SM\nmolly/SM\nmollycoddle/DSMG\nmolt/MDNRSZG\nmolter/M\nmolybdenum/M\nmom/SM\nmoment/MS\nmomenta\nmomentarily\nmomentariness/M\nmomentary/P\nmomentous/PY\nmomentousness/M\nmomentum/M\nmommy/SM\nmonarch/M\nmonarchic\nmonarchical\nmonarchism/M\nmonarchist/MS\nmonarchistic\nmonarchs\nmonarchy/SM\nmonastery/SM\nmonastic/MS\nmonastical/Y\nmonasticism/M\nmonaural\nmonetarily\nmonetarism/M\nmonetarist/MS\nmonetary\nmonetize/CGDS\nmoney/SMD\nmoneybag/MS\nmoneybox/S\nmoneylender/SM\nmoneymaker/SM\nmoneymaking/M\nmonger/MDGS\nmongol/S\nmongolism/M\nmongoloid/MS\nmongoose/MS\nmongrel/SM\nmonies\nmoniker/SM\nmonism/M\nmonist/MS\nmonition/SM\nmonitor/SMDG\nmonitory\nmonk/MS\nmonkey/MDGS\nmonkeyshine/SM\nmonkish\nmonkshood/SM\nmono/M\nmonochromatic\nmonochrome/MS\nmonocle/DSM\nmonoclonal\nmonocotyledon/SM\nmonocotyledonous\nmonocular\nmonodic\nmonodist/SM\nmonody/SM\nmonogamist/MS\nmonogamous/Y\nmonogamy/M\nmonogram/SM\nmonogrammed\nmonogramming\nmonograph/M\nmonographs\nmonolingual/MS\nmonolith/M\nmonolithic\nmonoliths\nmonologist/SM\nmonologue/SM\nmonomania/M\nmonomaniac/MS\nmonomaniacal\nmonomer/SM\nmononucleosis/M\nmonophonic\nmonoplane/SM\nmonopolist/SM\nmonopolistic\nmonopolization/M\nmonopolize/DRSZG\nmonopolizer/M\nmonopoly/SM\nmonorail/MS\nmonosyllabic\nmonosyllable/MS\nmonotheism/M\nmonotheist/SM\nmonotheistic\nmonotone/MS\nmonotonic\nmonotonically\nmonotonous/PY\nmonotonousness/M\nmonotony/M\nmonounsaturated\nmonoxide/MS\nmonseigneur/M\nmonsieur/M\nmonsignor/SM\nmonsoon/SM\nmonsoonal\nmonster/SM\nmonstrance/ASM\nmonstrosity/SM\nmonstrous/Y\nmontage/SM\nmonth/MY\nmonthly/SM\nmonths\nmonument/MS\nmonumental/Y\nmoo/SGMD\nmooch/ZGMDRS\nmoocher/M\nmood/MS\nmoodily\nmoodiness/M\nmoody/TPR\nmoon/MDSG\nmoonbeam/MS\nmoonless\nmoonlight/SMDRZG\nmoonlighter/M\nmoonlighting/M\nmoonlit\nmoonscape/SM\nmoonshine/MZRS\nmoonshiner/M\nmoonshot/MS\nmoonstone/MS\nmoonstruck\nmoonwalk/MS\nmoor/MDJSG\nmoorhen/S\nmooring/M\nmoorland/MS\nmoose/M\nmoot/DSG\nmop/SZGMDR\nmope/MS\nmoped/SM\nmoper/M\nmopey\nmopier\nmopiest\nmopish\nmopped\nmoppet/MS\nmopping\nmoraine/SM\nmoral/SMY\nmorale/M\nmoralist/MS\nmoralistic\nmoralistically\nmoralities\nmorality/UM\nmoralization/CM\nmoralize/CGDS\nmoralizer/MS\nmorass/MS\nmoratorium/SM\nmoray/SM\nmorbid/YP\nmorbidity/M\nmorbidness/M\nmordancy/M\nmordant/SMY\nmore/MS\nmoreish\nmorel/SM\nmoreover\nmores/M\nmorgue/MS\nmoribund\nmorn/MJSG\nmorning/M\nmorocco/M\nmoron/SM\nmoronic\nmoronically\nmorose/YP\nmoroseness/M\nmorph/GD\nmorpheme/MS\nmorphemic\nmorphia/M\nmorphine/M\nmorphing/M\nmorphological\nmorphology/M\nmorphs\nmorrow/MS\nmorsel/MS\nmortal/MYS\nmortality/M\nmortar/MDSG\nmortarboard/SM\nmortgage's\nmortgage/AGDS\nmortgagee/MS\nmortgagor/MS\nmortician/MS\nmortification/M\nmortify/NGDS\nmortise/DSMG\nmortuary/SM\nmosaic/MS\nmosey/SGD\nmosh/DSG\nmosque/MS\nmosquito/M\nmosquitoes\nmoss/MS\nmossback/SM\nmossy/TR\nmost/MY\nmot/SM\nmote's\nmote/KCXSVN\nmotel/SM\nmotet/SM\nmoth/M\nmothball/GMDS\nmother/MDYSG\nmotherboard/SM\nmotherfucker/MS!\nmotherfucking/!\nmotherhood/M\nmotherland/MS\nmotherless\nmotherliness/M\nmoths\nmotif/SM\nmotile/S\nmotility/M\nmotion/KCM\nmotioned\nmotioning\nmotionless/YP\nmotionlessness/M\nmotivate/CDSG\nmotivated/U\nmotivation/SM\nmotivational\nmotivator/SM\nmotive/MS\nmotiveless\nmotley/MS\nmotlier\nmotliest\nmotocross/MS\nmotor/SGMD\nmotorbike/MGDS\nmotorboat/MS\nmotorcade/MS\nmotorcar/SM\nmotorcycle/DSMG\nmotorcyclist/MS\nmotorist/SM\nmotorization/M\nmotorize/DSG\nmotorman/M\nmotormen\nmotormouth/M\nmotormouths\nmotorway/SM\nmottle/GDS\nmotto/M\nmottoes\nmoue/MS\nmound/SGMD\nmount/EASGMD\nmountable\nmountain/SM\nmountaineer/SMDG\nmountaineering/M\nmountainous\nmountainside/SM\nmountaintop/SM\nmountebank/MS\nmounted/U\nmounter/MS\nmounting/SM\nmourn/SZGDR\nmourned/U\nmourner/M\nmournful/YP\nmournfulness/M\nmourning/M\nmouse/DRSMZG\nmouser/M\nmousetrap/SM\nmousetrapped\nmousetrapping\nmousiness/M\nmoussaka/S\nmousse/MGDS\nmousy/PTR\nmouth/GMD\nmouthful/MS\nmouthiness/M\nmouthpiece/MS\nmouths\nmouthwash/MS\nmouthwatering\nmouthy/PTR\nmouton/M\nmovable/SM\nmove/AMZGDRSB\nmoved/U\nmovement/SM\nmover/AM\nmovie/SM\nmoviegoer/SM\nmoving/Y\nmow/SZGMDR\nmower/M\nmoxie/M\nmozzarella/M\nmp\nmpg\nmph\nmt\nmtg\nmtge\nmu/SM\nmuch/M\nmucilage/M\nmucilaginous\nmuck/MDSG\nmuckrake/DRSZG\nmuckraker/M\nmucky/TR\nmucous\nmucus/M\nmud/M\nmuddily\nmuddiness/M\nmuddle/MGDS\nmuddleheaded\nmuddy/PTGDRS\nmudflap/S\nmudflat/MS\nmudguard/SM\nmudpack/S\nmudroom/MS\nmudslide/MS\nmudslinger/SM\nmudslinging/M\nmuenster/M\nmuesli\nmuezzin/MS\nmuff/MDSG\nmuffin/MS\nmuffle/ZGDRS\nmuffler/M\nmufti/SM\nmug/SM\nmugful/MS\nmugged\nmugger/MS\nmugginess/M\nmugging/MS\nmuggins\nmuggle/MS\nmuggy/PTR\nmugshot/MS\nmugwump/MS\nmujaheddin\nmukluk/MS\nmulatto/M\nmulattoes\nmulberry/SM\nmulch/GMDS\nmulct/SGMD\nmule/MS\nmuleskinner/MS\nmuleteer/MS\nmulish/PY\nmulishness/M\nmull/DSG\nmullah/M\nmullahs\nmullein/M\nmullet/MS\nmulligan/SM\nmulligatawny/M\nmullion/SMD\nmulti\nmulticolored\nmulticultural\nmulticulturalism/M\nmultidimensional\nmultidisciplinary\nmultifaceted\nmultifamily\nmultifarious/PY\nmultifariousness/M\nmultiform\nmultilateral/Y\nmultilayered\nmultilevel\nmultilingual\nmultilingualism/M\nmultimedia/M\nmultimillionaire/SM\nmultinational/SM\nmultiparty\nmultiplayer/M\nmultiple/MS\nmultiplex/ZGMDRS\nmultiplexer/M\nmultiplicand/MS\nmultiplication/M\nmultiplicative\nmultiplicity/SM\nmultiplier/M\nmultiply/NZGDRSX\nmultiprocessing\nmultiprocessor/SM\nmultipurpose\nmultiracial\nmultistage\nmultistory\nmultitask/GS\nmultitasking/M\nmultitude/SM\nmultitudinous\nmultivariate\nmultiverse/SM\nmultivitamin/MS\nmultiyear\nmum/SM\nmumble/MZGDRS\nmumbler/M\nmumbletypeg/M\nmummer/MS\nmummery/M\nmummification/M\nmummify/GNDS\nmummy/SM\nmumps/M\nmun\nmunch/GDS\nmunchies/M\nmunchkin/SM\nmundane/SY\nmung/DSG\nmunicipal/SMY\nmunicipality/SM\nmunificence/M\nmunificent/Y\nmunition/MDGS\nmural/SM\nmuralist/SM\nmurder/ZGMDRS\nmurderer/M\nmurderess/MS\nmurderous/Y\nmurk/MS\nmurkily\nmurkiness/M\nmurky/PTR\nmurmur/ZGJMDRS\nmurmurer/M\nmurmuring/M\nmurmurous\nmurrain/M\nmuscat/MS\nmuscatel/SM\nmuscle/MGDS\nmusclebound\nmuscleman\nmusclemen\nmuscly\nmuscular/Y\nmuscularity/M\nmusculature/M\nmuse/MGDSJ\nmusette/MS\nmuseum/MS\nmush/MDRSZG\nmushiness/M\nmushroom/GSMD\nmushy/PTR\nmusic/SM\nmusical/MYS\nmusicale/MS\nmusicality/M\nmusician/SMY\nmusicianship/M\nmusicological\nmusicologist/MS\nmusicology/M\nmusing/MY\nmusk/M\nmuskeg/MS\nmuskellunge/MS\nmusket/MS\nmusketeer/MS\nmusketry/M\nmuskie/M\nmuskiness/M\nmuskmelon/SM\nmuskox/MN\nmuskrat/MS\nmusky/PTRS\nmuslin/M\nmuss/MDSG\nmussel/MS\nmussy/TR\nmust've\nmust/MRSZ\nmustache/MDS\nmustachio/SMD\nmustang/MS\nmustard/M\nmuster/GMD\nmustily\nmustiness/M\nmustn't\nmusty/PTR\nmutability/M\nmutably\nmutagen/MS\nmutant/MS\nmutate/XGNVDS\nmutation/M\nmutational\nmute/MYTGDRSPB\nmuteness/M\nmutilate/DSGNX\nmutilation/M\nmutilator/SM\nmutineer/SM\nmutinous/Y\nmutiny/GDSM\nmutt/MS\nmutter/ZGJMDRS\nmutterer/M\nmuttering/M\nmutton/M\nmuttonchops/M\nmutual/Y\nmutuality/M\nmuumuu/MS\nmuzak\nmuzzily\nmuzzle/DSMG\nmuzzy/P\nmy\nmycologist/SM\nmycology/M\nmyelitis/M\nmyna/MS\nmyocardial\nmyocardium\nmyopia/M\nmyopic\nmyopically\nmyriad/SM\nmyrmidon/MS\nmyrrh/M\nmyrtle/SM\nmys\nmyself\nmysterious/PY\nmysteriousness/M\nmystery/SM\nmystic/SM\nmystical/Y\nmysticism/M\nmystification/CM\nmystify/CDSGN\nmystique/M\nmyth/M\nmythic\nmythical\nmythological\nmythologist/SM\nmythologize/DSG\nmythology/SM\nmyths\nmyxomatosis\nn/IKTH\nnaan/S\nnab/S\nnabbed\nnabbing\nnabob/SM\nnacelle/SM\nnacho/SM\nnacre/M\nnacreous\nnadir/SM\nnae\nnaff/RT\nnag/SM\nnagged\nnagger/MS\nnagging\nnagware\nnah\nnaiad/SM\nnaif/MS\nnail/MDSG\nnailbrush/MS\nnaive/RYT\nnaivete/M\nnaivety/M\nnaked/PY\nnakedness/M\nname's\nname/AGDS\nnameable/U\nnamed/U\nnamedrop\nnamedropping/M\nnameless/Y\nnamely\nnameplate/MS\nnamesake/SM\nnanny/SM\nnanobot/S\nnanosecond/SM\nnanotechnology/SM\nnap/SM\nnapalm/MDSG\nnape/MS\nnaphtha/M\nnaphthalene/M\nnapkin/MS\nnapless\nnapoleon/SM\nnapped\nnapper/MS\nnapping\nnappy/TRSM\nnarc/MS\nnarcissism/M\nnarcissist/MS\nnarcissistic\nnarcissus/M\nnarcolepsy/M\nnarcoleptic\nnarcoses\nnarcosis/M\nnarcotic/SM\nnarcotization/M\nnarcotize/GDS\nnark\nnarky\nnarrate/GNVDSX\nnarration/M\nnarrative/SM\nnarrator/SM\nnarrow/PTGMDRYS\nnarrowness/M\nnarwhal/MS\nnary\nnasal/SMY\nnasality/M\nnasalization/M\nnasalize/DSG\nnascence/AM\nnascent/A\nnastily\nnastiness/M\nnasturtium/SM\nnasty/PTR\nnatal\nnatch\nnation/MS\nnational/MYS\nnationalism/M\nnationalist/SM\nnationalistic\nnationalistically\nnationality/SM\nnationalization/MS\nnationalize/CDSG\nnationhood/M\nnationwide\nnative/MS\nnativity/SM\nnatl\nnatter/GMDS\nnattily\nnattiness/M\nnatty/PTR\nnatural's\nnatural/UPY\nnaturalism/M\nnaturalist/SM\nnaturalistic\nnaturalization/M\nnaturalize/DSG\nnaturalness/UM\nnaturals\nnature's\nnature/CS\nnaturism\nnaturist/S\nnaught/MS\nnaughtily\nnaughtiness/M\nnaughty/PTR\nnausea/M\nnauseate/GDS\nnauseating/Y\nnauseous/PY\nnauseousness/M\nnautical/Y\nnautilus/MS\nnaval\nnave/MS\nnavel/SM\nnavigability/M\nnavigable\nnavigate/DSGN\nnavigation/M\nnavigational\nnavigator/MS\nnavvy/S\nnavy/SM\nnay/SM\nnaysayer/MS\nne'er\nneanderthal/MS\nneap/MS\nnear/DRYSPTG\nnearby\nnearness/M\nnearshore\nnearside\nnearsighted/YP\nnearsightedness/M\nneat/NRYPXT\nneaten/GD\nneath\nneatness/M\nnebula/M\nnebulae\nnebular\nnebulous/PY\nnebulousness/M\nnecessarily/U\nnecessary/SM\nnecessitate/DSG\nnecessitous\nnecessity/SM\nneck/MDSG\nneckband/S\nneckerchief/MS\nnecking/M\nnecklace/MGDSJ\nneckline/MS\nnecktie/MS\nnecrology/M\nnecromancer/SM\nnecromancy/M\nnecrophilia\nnecrophiliac/S\nnecropolis/MS\nnecroses\nnecrosis/M\nnecrotic\nnectar/M\nnectarine/MS\nnee\nneed/MDSG\nneeded/U\nneedful/Y\nneediness/M\nneedle/MGDS\nneedlepoint/M\nneedless/YP\nneedlessness/M\nneedlewoman/M\nneedlewomen\nneedlework/M\nneedn't\nneedy/PTR\nnefarious/YP\nnefariousness/M\nneg\nnegate/DSGNVX\nnegation/M\nnegative/MYGPDS\nnegativeness/M\nnegativism/M\nnegativity/M\nneglect/SGMD\nneglectful/YP\nneglectfulness/M\nnegligee/MS\nnegligence/M\nnegligent/Y\nnegligible\nnegligibly\nnegotiability/M\nnegotiable/A\nnegotiate/ADSGN\nnegotiation/AM\nnegotiations\nnegotiator/MS\nnegritude/M\nnegro\nnegroid\nneigh/MDG\nneighbor/SMDYG\nneighborhood/SM\nneighborliness/M\nneighs\nneither\nnelson/SM\nnematode/SM\nnemeses\nnemesis/M\nneoclassic\nneoclassical\nneoclassicism/M\nneocolonialism/M\nneocolonialist/MS\nneocon/S\nneoconservative/SM\nneodymium/M\nneolithic\nneologism/SM\nneon/M\nneonatal\nneonate/MS\nneophilia\nneophyte/MS\nneoplasm/MS\nneoplastic\nneoprene/M\nnepenthe/M\nnephew/SM\nnephrite/M\nnephritic\nnephritis/M\nnepotism/M\nnepotist/SM\nnepotistic\nneptunium/M\nnerd/MS\nnerdy/RT\nnerve's\nnerve/UDSG\nnerveless/YP\nnervelessness/M\nnerviness/M\nnervous/YP\nnervousness/M\nnervy/TPR\nnest/MDSG\nnestle/GJDS\nnestling/M\nnet/SM\nnetball\nnetbook/MS\nnether\nnethermost\nnetherworld/M\nnetiquette/S\nnetted\nnetter/S\nnetting/M\nnettle/MGDS\nnettlesome\nnetwork/SGMD\nnetworking/M\nneural/Y\nneuralgia/M\nneuralgic\nneurasthenia/M\nneurasthenic/MS\nneuritic/MS\nneuritis/M\nneurological/Y\nneurologist/SM\nneurology/M\nneuron/MS\nneuronal\nneuroses\nneurosis/M\nneurosurgeon/MS\nneurosurgery/M\nneurosurgical\nneurotic/MS\nneurotically\nneurotransmitter/SM\nneut\nneuter/MDGS\nneutral/SMY\nneutralism/M\nneutralist/SM\nneutrality/M\nneutralization/M\nneutralize/DRSZG\nneutralizer/M\nneutrino/SM\nneutron/SM\nnever\nnevermore\nnevertheless\nnevi\nnevus/M\nnew/STMRYP\nnewbie/MS\nnewborn/SM\nnewcomer/SM\nnewel/SM\nnewfangled\nnewfound\nnewline/S\nnewlywed/SM\nnewness/M\nnews/M\nnewsagent/S\nnewsboy/SM\nnewscast/SMRZ\nnewscaster/M\nnewsdealer/SM\nnewsflash/S\nnewsgirl/SM\nnewsgroup/MS\nnewshound/S\nnewsletter/MS\nnewsman/M\nnewsmen\nnewspaper/MS\nnewspaperman/M\nnewspapermen\nnewspaperwoman/M\nnewspaperwomen\nnewspeak\nnewsprint/M\nnewsreader/S\nnewsreel/MS\nnewsroom/MS\nnewsstand/SM\nnewsweekly/SM\nnewswoman/M\nnewswomen\nnewsworthiness/M\nnewsworthy/P\nnewsy/TR\nnewt/MS\nnewton/MS\nnext/M\nnexus/MS\nniacin/M\nnib/SM\nnibble/MZGDRS\nnibbler/M\nnice/PYTR\nniceness/M\nnicety/SM\nniche/SM\nnick/MDRSZG\nnickel/MS\nnickelodeon/SM\nnicker/MDG\nnickle/S\nnickname/DSMG\nnicotine/M\nniece/SM\nniff\nniffy\nnifty/TR\nnigga/S\nniggard/SMY\nniggardliness/M\nniggaz\nnigger/SM!\nniggle/MZGDRS\nniggler/M\nnigh/RT\nnight/SMY\nnightcap/SM\nnightclothes/M\nnightclub/SM\nnightclubbed\nnightclubbing\nnightdress/MS\nnightfall/M\nnightgown/SM\nnighthawk/SM\nnightie/SM\nnightingale/SM\nnightlife/M\nnightlight/S\nnightlong\nnightmare/SM\nnightmarish\nnightshade/SM\nnightshirt/SM\nnightspot/MS\nnightstand/SM\nnightstick/SM\nnighttime/M\nnightwatchman\nnightwatchmen\nnightwear/M\nnihilism/M\nnihilist/MS\nnihilistic\nnil/M\nnimbi\nnimble/TPR\nnimbleness/M\nnimbly\nnimbus/M\nnimby\nnimrod/MS\nnincompoop/SM\nnine/MS\nninepin/MS\nninepins/M\nnineteen/SMH\nnineteenth/M\nnineteenths\nninetieth/M\nninetieths\nninety/HSM\nninja/SM\nninny/SM\nninth/M\nninths\nniobium/M\nnip/SM\nnipped\nnipper/MS\nnippiness/M\nnipping\nnipple/MS\nnippy/TPR\nnirvana/M\nnisei/M\nnit/SMR\nniter/M\nnitpick/SZGDR\nnitpicker/M\nnitpicking/M\nnitrate/DSMGN\nnitration/M\nnitrification/M\nnitrite/SM\nnitro\nnitrocellulose/M\nnitrogen/M\nnitrogenous\nnitroglycerin/M\nnitwit/MS\nnix/GMDS\nno/SM\nnob/SY\nnobble/GDS\nnobelium/M\nnobility/M\nnoble/RSPMT\nnobleman/M\nnoblemen\nnobleness/M\nnoblewoman/M\nnoblewomen\nnobody/SM\nnocturnal/Y\nnocturne/MS\nnod/SM\nnodal\nnodded\nnodding\nnoddle/MS\nnoddy\nnode/MS\nnodular\nnodule/MS\nnoel/MS\nnoes\nnoggin/MS\nnohow\nnoise/DSMG\nnoiseless/PY\nnoiselessness/M\nnoisemaker/MS\nnoisily\nnoisiness/M\nnoisome\nnoisy/PTR\nnomad/SM\nnomadic\nnomenclature/MS\nnominal/Y\nnominate/ACGNVDS\nnomination's/A\nnomination/CSM\nnominative/SM\nnominator/CSM\nnominee/MS\nnon\nnonabrasive\nnonabsorbent/SM\nnonacademic\nnonacceptance/M\nnonacid\nnonactive/MS\nnonaddictive\nnonadhesive\nnonadjacent\nnonadjustable\nnonadministrative\nnonage/MS\nnonagenarian/MS\nnonaggression/M\nnonalcoholic\nnonaligned\nnonalignment/M\nnonallergic\nnonappearance/MS\nnonassignable\nnonathletic\nnonattendance/M\nnonautomotive\nnonavailability/M\nnonbasic\nnonbeliever/MS\nnonbelligerent/MS\nnonbinding\nnonbreakable\nnonburnable\nnoncaloric\nnoncancerous\nnonce/M\nnonchalance/M\nnonchalant/Y\nnonchargeable\nnonclerical/MS\nnonclinical\nnoncollectable\nnoncom/MS\nnoncombat\nnoncombatant/MS\nnoncombustible\nnoncommercial/MS\nnoncommittal/Y\nnoncommunicable\nnoncompeting\nnoncompetitive\nnoncompliance/M\nnoncomplying\nnoncomprehending\nnonconducting\nnonconductor/MS\nnonconforming\nnonconformism\nnonconformist/MS\nnonconformity/M\nnonconsecutive\nnonconstructive\nnoncontagious\nnoncontinuous\nnoncontributing\nnoncontributory\nnoncontroversial\nnonconvertible\nnoncooperation/M\nnoncorroding\nnoncorrosive\nnoncredit\nnoncriminal/SM\nnoncritical\nnoncrystalline\nnoncumulative\nnoncustodial\nnondairy\nnondeductible/M\nnondelivery/SM\nnondemocratic\nnondenominational\nnondepartmental\nnondepreciating\nnondescript\nnondestructive\nnondetachable\nnondisciplinary\nnondisclosure/M\nnondiscrimination/M\nnondiscriminatory\nnondramatic\nnondrinker/MS\nnondrying\nnone\nnoneducational\nnoneffective\nnonelastic\nnonelectric\nnonelectrical\nnonempty\nnonenforceable\nnonentity/SM\nnonequivalent/MS\nnonessential\nnonesuch/MS\nnonetheless\nnonevent/MS\nnonexchangeable\nnonexclusive\nnonexempt/M\nnonexistence/M\nnonexistent\nnonexplosive/MS\nnonfactual\nnonfading\nnonfat\nnonfatal\nnonfattening\nnonferrous\nnonfiction/M\nnonfictional\nnonflammable\nnonflowering\nnonfluctuating\nnonflying\nnonfood/M\nnonfreezing\nnonfunctional\nnongovernmental\nnongranular\nnonhazardous\nnonhereditary\nnonhuman\nnonidentical\nnoninclusive\nnonindependent\nnonindustrial\nnoninfectious\nnoninflammatory\nnoninflationary\nnoninflected\nnonintellectual/MS\nnoninterchangeable\nnoninterference/M\nnonintervention/M\nnonintoxicating\nnoninvasive\nnonirritating\nnonissue\nnonjudgmental\nnonjudicial\nnonlegal\nnonlethal\nnonlinear\nnonliterary\nnonliving/M\nnonmagnetic\nnonmalignant\nnonmember/MS\nnonmetal/SM\nnonmetallic\nnonmigratory\nnonmilitant\nnonmilitary\nnonnarcotic/SM\nnonnative/MS\nnonnegotiable\nnonnuclear\nnonnumerical\nnonobjective\nnonobligatory\nnonobservance/M\nnonobservant\nnonoccupational\nnonoccurrence/M\nnonofficial\nnonoperational\nnonoperative\nnonparallel/MS\nnonpareil/MS\nnonparticipant/MS\nnonparticipating\nnonpartisan/SM\nnonpaying\nnonpayment/SM\nnonperformance/M\nnonperforming\nnonperishable\nnonperson/MS\nnonphysical/Y\nnonplus/S\nnonplussed\nnonplussing\nnonpoisonous\nnonpolitical\nnonpolluting\nnonporous\nnonpracticing\nnonprejudicial\nnonprescription\nnonproductive\nnonprofessional/SM\nnonprofit/SMB\nnonproliferation/M\nnonpublic\nnonpunishable\nnonracial\nnonradioactive\nnonrandom\nnonreactive\nnonreciprocal/SM\nnonreciprocating\nnonrecognition/M\nnonrecoverable\nnonrecurring\nnonredeemable\nnonrefillable\nnonrefundable\nnonreligious\nnonrenewable\nnonrepresentational\nnonresident/MS\nnonresidential\nnonresidual/M\nnonresistance/M\nnonresistant\nnonrestrictive\nnonreturnable/MS\nnonrhythmic\nnonrigid\nnonsalaried\nnonscheduled\nnonscientific\nnonscoring\nnonseasonal\nnonsectarian\nnonsecular\nnonsegregated\nnonsense/M\nnonsensical/Y\nnonsensitive\nnonsexist\nnonsexual\nnonskid\nnonslip\nnonsmoker/SM\nnonsmoking\nnonsocial\nnonspeaking\nnonspecialist/MS\nnonspecializing\nnonspecific\nnonspiritual/SM\nnonstaining\nnonstandard\nnonstarter/MS\nnonstick\nnonstop\nnonstrategic\nnonstriking\nnonstructural\nnonsuccessive\nnonsupport/GM\nnonsurgical\nnonsustaining\nnonsympathizer/M\nnontarnishable\nnontaxable\nnontechnical\nnontenured\nnontheatrical\nnonthinking\nnonthreatening\nnontoxic\nnontraditional\nnontransferable\nnontransparent\nnontrivial\nnontropical\nnonuniform\nnonunion\nnonuser/MS\nnonvenomous\nnonverbal\nnonviable\nnonviolence/M\nnonviolent/Y\nnonvirulent\nnonvocal\nnonvocational\nnonvolatile\nnonvoter/MS\nnonvoting\nnonwhite/MS\nnonworking\nnonyielding\nnonzero\nnoodle/MGDS\nnook/MS\nnookie\nnooky\nnoon/M\nnoonday/M\nnoontide/M\nnoontime/M\nnoose/SM\nnope\nnor\nnor'easter\nnorm/MS\nnormal/MY\nnormalcy/M\nnormality/M\nnormalization/M\nnormalize/DSG\nnormative\nnorth/ZMR\nnorthbound\nnortheast/MRZ\nnortheaster/MY\nnortheastern\nnortheastward/S\nnorther/MY\nnortherly/SM\nnorthern/ZR\nnortherner/M\nnorthernmost\nnorthward/S\nnorthwest/ZMR\nnorthwester/MY\nnorthwestern\nnorthwestward/S\nnose/MGDS\nnosebag/S\nnosebleed/MS\nnosecone/SM\nnosedive/DSMG\nnosegay/SM\nnosh/MDRSZG\nnosher/M\nnosily\nnosiness/M\nnostalgia/M\nnostalgic\nnostalgically\nnostril/MS\nnostrum/MS\nnosy/RPT\nnot/B\nnotability/SM\nnotable/SM\nnotably\nnotarial\nnotarization/M\nnotarize/GDS\nnotary/SM\nnotate/GDS\nnotation/FCSM\nnotch/GMDS\nnote's\nnote/FCSDG\nnotebook/MS\nnotelet/S\nnotepad/S\nnotepaper/M\nnoteworthiness/M\nnoteworthy/P\nnothing/PSM\nnothingness/M\nnotice/MGDS\nnoticeable/U\nnoticeably\nnoticeboard/S\nnoticed/U\nnotifiable\nnotification/M\nnotifier/M\nnotify/NDRSXZG\nnotion/MS\nnotional/Y\nnotoriety/M\nnotorious/Y\nnotwithstanding\nnotwork/S\nnougat/MS\nnoun/KMS\nnourish/DSLG\nnourishment/M\nnous\nnova/MS\nnovae\nnovel/SM\nnovelette/SM\nnovelist/SM\nnovelization/MS\nnovelize/DSG\nnovella/MS\nnovelty/SM\nnovena/MS\nnovene\nnovice/MS\nnovitiate/MS\nnow/M\nnowadays/M\nnoway/S\nnowhere/M\nnowise\nnowt\nnoxious\nnozzle/MS\nnu/SM\nnuance/MDS\nnub/SM\nnubbin/MS\nnubby/TR\nnubile\nnuclear/K\nnucleate/DSGN\nnucleation/M\nnuclei\nnucleic\nnucleoli\nnucleolus/M\nnucleon/SM\nnucleoside\nnucleotide\nnucleus/M\nnude/MTRS\nnudge/GDSM\nnudism/M\nnudist/SM\nnudity/M\nnugatory\nnugget/SM\nnuisance/MS\nnuke/MGDS\nnull/S\nnullification/M\nnullify/NDSG\nnullity/M\nnumb/ZTGPDRYS\nnumber's\nnumber/ASDG\nnumbered/U\nnumberless\nnumbness/M\nnumerable/I\nnumeracy/IM\nnumeral/SM\nnumerate/XGNDS\nnumeration/M\nnumerator/MS\nnumeric\nnumerical/Y\nnumerologist/MS\nnumerology/M\nnumerous/Y\nnuminous\nnumismatic/S\nnumismatics/M\nnumismatist/SM\nnumskull/MS\nnun/SM\nnuncio/SM\nnunnery/SM\nnuptial/MS\nnurse/MZGDRS\nnurselings\nnursemaid/MS\nnurser/M\nnursery/SM\nnurseryman/M\nnurserymen\nnursing/M\nnursling/SM\nnurture/DRSMZG\nnurturer/M\nnut/SM\nnutcase/S\nnutcracker/MS\nnuthatch/MS\nnuthouse/S\nnutmeat/SM\nnutmeg/SM\nnutpick/SM\nnutria/SM\nnutrient/MS\nnutriment/MS\nnutrition/M\nnutritional/Y\nnutritionist/SM\nnutritious/YP\nnutritiousness/M\nnutritive\nnutshell/MS\nnutted\nnutter/S\nnuttiness/M\nnutting\nnutty/RTP\nnuzzle/DRSMZG\nnuzzler/M\nnybble/S\nnylon/MS\nnylons/M\nnymph/M\nnymphet/MS\nnympho/S\nnymphomania/M\nnymphomaniac/SM\nnymphs\no\no'clock\no'er\noaf/SM\noafish/PY\noafishness/M\noak/SMN\noakum/M\noar/SGMD\noarlock/SM\noarsman/M\noarsmen\noarswoman/M\noarswomen\noases\noasis/M\noat/SMN\noatcake/SM\noath/M\noaths\noatmeal/M\noats/M\nob/S\nobbligato/MS\nobduracy/M\nobdurate/PY\nobdurateness/M\nobedience/EM\nobedient/EY\nobeisance/SM\nobeisant\nobelisk/MS\nobese\nobesity/M\nobey/EDSG\nobfuscate/GNXDS\nobfuscation/M\nobi/SM\nobit/MS\nobituary/SM\nobj\nobject/SGVMD\nobjectify/NGDS\nobjection/SMB\nobjectionable/U\nobjectionably\nobjective/SMYP\nobjectiveness/M\nobjectivity/M\nobjector/MS\nobjurgate/XGNDS\nobjurgation/M\noblate/NX\noblation/M\nobligate/DSXGN\nobligation/M\nobligatorily\nobligatory\noblige/EGDS\nobliging/Y\noblique/SMYP\nobliqueness/M\nobliquity/M\nobliterate/DSGN\nobliteration/M\noblivion/M\noblivious/YP\nobliviousness/M\noblong/MS\nobloquy/M\nobnoxious/YP\nobnoxiousness/M\noboe/MS\noboist/MS\nobscene/RYT\nobscenity/SM\nobscurantism/M\nobscurantist/SM\nobscure/DRSYTG\nobscurity/SM\nobsequies\nobsequious/PY\nobsequiousness/M\nobsequy/M\nobservably\nobservance/MS\nobservant/Y\nobservation/SM\nobservational\nobservatory/SM\nobserve/DRSBZG\nobserved/U\nobserver/M\nobsess/DSGV\nobsession/SM\nobsessional/Y\nobsessive/PSMY\nobsessiveness/M\nobsidian/M\nobsolesce/DSG\nobsolescence/M\nobsolescent\nobsolete/GDS\nobstacle/MS\nobstetric/S\nobstetrical\nobstetrician/SM\nobstetrics/M\nobstinacy/M\nobstinate/Y\nobstreperous/YP\nobstreperousness/M\nobstruct/DGVS\nobstructed/U\nobstruction/SM\nobstructionism/M\nobstructionist/MS\nobstructive/YP\nobstructiveness/M\nobtain/DBLGS\nobtainable/U\nobtainment/M\nobtrude/DSG\nobtrusion/M\nobtrusive/UPY\nobtrusiveness/UM\nobtuse/YTRP\nobtuseness/M\nobverse/SM\nobviate/DSGN\nobviation/M\nobvious/PY\nobviousness/M\nocarina/MS\noccasion/GMDS\noccasional/Y\noccidental/SM\nocclude/GDS\nocclusion/SM\nocclusive\noccult/M\noccultism/M\noccultist/SM\noccupancy/M\noccupant/SM\noccupation/AM\noccupational/Y\noccupations\noccupied/U\noccupier/SM\noccupy/ADSG\noccur/AS\noccurred/A\noccurrence/SM\noccurring/A\nocean/SM\noceanfront/SM\noceangoing\noceanic/M\noceanographer/SM\noceanographic\noceanography/M\noceanology/M\nocelot/MS\noch/R\nocher/M\nocker/S\noctagon/MS\noctagonal\noctal\noctane/MS\noctave/MS\noctavo/MS\noctet/SM\noctogenarian/SM\noctopus/MS\nocular/MS\noculist/SM\nodalisque/SM\nodd/STRYLP\noddball/SM\noddity/SM\noddment/SM\noddness/M\nodds/M\node/SM\nodious/YP\nodiousness/M\nodium/M\nodometer/MS\nodor/MDS\nodoriferous\nodorless\nodorous\nodyssey/MS\noedipal\noenology/M\noenophile/SM\noeuvre/MS\nof\noff/SZGDRJ\noffal/M\noffbeat/MS\noffend/ZGDRS\noffender/M\noffense/MS\noffensive's\noffensive/IPY\noffensiveness/IM\noffensives\noffer/JGMD\noffering/M\noffertory/SM\noffhand\noffhanded/PY\noffhandedness/M\noffice/MZRS\nofficeholder/SM\nofficer/M\nofficial/MYS\nofficialdom/M\nofficialese\nofficialism/M\nofficiant/SM\nofficiate/DSG\nofficiator/MS\nofficious/PY\nofficiousness/M\noffing/M\noffish\noffline\noffload/SDG\noffprint/SM\noffset/MS\noffsetting\noffshoot/MS\noffshore/G\noffside\noffsite\noffspring/M\noffstage/S\nofftrack\noft\noften/TR\noftentimes\nofttimes\nogle/MZGDRS\nogler/M\nogre/MS\nogreish\nogress/MS\noh/M\nohm/SM\nohmmeter/MS\noho\nohs\noi\noik/S\noil/SGMD\noilcan/S\noilcloth/M\noilcloths\noilfield/S\noiliness/M\noilman\noilmen\noilskin/MS\noilskins/M\noily/RPT\noink/MDSG\nointment/SM\nokapi/SM\nokay/MSG\nokra/MS\nold/TMNRP\noldie/SM\noldish\noldness/M\noldster/MS\nole/SMV\noleaginous\noleander/MS\noleo/M\noleomargarine/M\nolfactory/SM\noligarch/M\noligarchic\noligarchical\noligarchs\noligarchy/SM\noligonucleotide/S\noligopoly/SM\nolive/SM\nom/SMNX\nombudsman/M\nombudsmen\nomega/SM\nomelet/MS\nomen/M\nomicron/MS\nominous/YP\nominousness/M\nomission/MS\nomit/S\nomitted\nomitting\nomnibus/MS\nomnipotence/M\nomnipotent\nomnipresence/M\nomnipresent\nomniscience/M\nomniscient\nomnivore/MS\nomnivorous/PY\nomnivorousness/M\non/Y\nonce/M\noncogene/SM\noncologist/SM\noncology/M\noncoming\none/SXMNP\noneness/M\nonerous/PY\nonerousness/M\noneself\nonetime\nongoing\nonion/M\nonionskin/M\nonline\nonlooker/SM\nonlooking\nonomatopoeia/M\nonomatopoeic\nonomatopoetic\nonrush/MSG\nonscreen\nonset/MS\nonshore\nonside\nonsite\nonslaught/MS\nonstage\nonto\nontogeny/M\nontological\nontology/M\nonus/MS\nonward\nonyx/MS\noodles/M\nooh/GD\noohs\noomph\noops\nooze/MGDS\noozy/TR\nop/SMDG\nopacity/M\nopal/MS\nopalescence/M\nopalescent\nopaque/PYTGDRS\nopaqueness/M\nopcode/S\nope/S\nopen/ZTGJPMDRYS\nopencast\nopened/U\nopener/M\nopenhanded/P\nopenhandedness/M\nopenhearted\nopening/M\nopenness/M\nopenwork/M\nopera/MS\noperable/I\noperand/S\noperate/DSGNVX\noperatic\noperatically\noperation/M\noperational/Y\noperative/SM\noperator/SM\noperetta/SM\nophthalmic\nophthalmologist/SM\nophthalmology/M\nopiate/SM\nopine/GNXDS\nopinion/M\nopinionated\nopium/M\nopossum/MS\nopp\nopponent/SM\nopportune/IY\nopportunism/M\nopportunist/SM\nopportunistic\nopportunistically\nopportunity/SM\noppose/DSG\nopposed/U\nopposite/SMYNX\nopposition/M\noppress/DSGV\noppression/M\noppressive/YP\noppressiveness/M\noppressor/MS\nopprobrious/Y\nopprobrium/M\nopt/SGD\noptic/MS\noptical/Y\noptician/SM\noptics/M\noptima\noptimal/Y\noptimism/SM\noptimist/SM\noptimistic\noptimistically\noptimization/MS\noptimize/DRSG\noptimum/SM\noption/SMDG\noptional/Y\noptometrist/MS\noptometry/M\nopulence/M\nopulent/Y\nopus/MS\nor\noracle/SM\noracular\noral/MYS\norange/SMP\norangeade/MS\norangery/SM\norangutan/SM\norate/GNXDS\noration/M\norator/SM\noratorical/Y\noratorio/MS\noratory/SM\norb/SM\norbicular\norbit/MDRZGS\norbital/SM\norbiter/M\norc/S\norchard/SM\norchestra/MS\norchestral\norchestrate/DSXGN\norchestration/M\norchid/SM\nordain/SDLG\nordainment/M\nordeal/SM\norder/EAMDGS\norderings\norderliness/EM\norderly/PSM\nordinal/SM\nordinance/SM\nordinarily\nordinariness/M\nordinary/SMP\nordinate/MNSX\nordination/M\nordnance/M\nordure/M\nore/SM\noregano/M\norg\norgan/MS\norgandy/M\norganelle/MS\norganic/SM\norganically/I\norganism/MS\norganismic\norganist/MS\norganization/ASM\norganizational/Y\norganize/AESDG\norganized/U\norganizer/MS\norganza/M\norgasm/SM\norgasmic\norgiastic\norgy/SM\noriel/MS\norient's\norient/AEDGS\noriental/MS\norientalist/S\norientate/EDSGN\norientation/AEM\norientations\norienteering\norifice/MS\norig\norigami/M\norigin/SM\noriginal/MYS\noriginality/M\noriginate/DSGN\norigination/M\noriginator/SM\noriole/SM\norison/SM\normolu/M\nornament/SGMD\nornamental\nornamentation/M\nornate/YP\nornateness/M\norneriness/M\nornery/PRT\nornithological\nornithologist/MS\nornithology/M\norotund\norotundity/SM\norphan/SMDG\norphanage/MS\norris/MS\northodontia/M\northodontic/S\northodontics/M\northodontist/SM\northodox/U\northodoxy/SM\northogonal\northogonality\northographic\northographically\northography/SM\northopedic/S\northopedics/M\northopedist/MS\norzo/M\noscillate/GNDSX\noscillation/M\noscillator/SM\noscillatory\noscilloscope/MS\nosculate/DSXGN\nosculation/M\nosier/MS\nosmium/M\nosmosis/M\nosmotic\nosprey/SM\nossification/M\nossify/NGDS\nostensible\nostensibly\nostentation/M\nostentatious/Y\nosteoarthritis/M\nosteopath/M\nosteopathic\nosteopaths\nosteopathy/M\nosteoporosis/M\nostler/S\nostracism/M\nostracize/GDS\nostrich/MS\nother/SP\notherwise\notherworldly\notiose\notter/MS\nottoman/MS\noubliette/MS\nouch\nought\noughtn't\nounce/MS\nour/S\nourselves\noust/ZGDRS\nouster/M\nout/SJGMDR\noutage/SM\noutargue/GDS\noutback/MS\noutbalance/DSG\noutbid/S\noutbidding\noutboard/MS\noutboast/DSG\noutbound\noutbox/MS\noutbreak/MS\noutbuilding/MS\noutburst/SM\noutcast/MS\noutclass/DSG\noutcome/MS\noutcrop/MS\noutcropped\noutcropping/SM\noutcry/SM\noutdated\noutdid\noutdistance/GDS\noutdo/G\noutdoes\noutdone\noutdoor/S\noutdoors/M\noutdoorsy\noutdraw/GS\noutdrawn\noutdrew\noutermost\nouterwear/M\noutface/GDS\noutfall/S\noutfield/SMRZ\noutfielder/M\noutfight/SG\noutfit/SM\noutfitted\noutfitter/MS\noutfitting\noutflank/GSD\noutflow/MS\noutfought\noutfox/GDS\noutgo/MJG\noutgoes\noutgrew\noutgrow/HGS\noutgrown\noutgrowth/M\noutgrowths\noutguess/GDS\noutgun/S\noutgunned\noutgunning\nouthit/S\nouthitting\nouthouse/SM\nouting/M\noutlaid\noutlandish/PY\noutlandishness/M\noutlast/DSG\noutlaw/SGMD\noutlay/SGM\noutlet/SM\noutline/MGDS\noutlive/GDS\noutlook/MS\noutlying\noutmaneuver/GDS\noutmatch/GDS\noutmoded\noutnumber/DSG\noutpace/GDS\noutpatient/MS\noutperform/GSD\noutplace/L\noutplacement/M\noutplay/GDS\noutpoint/DGS\noutpost/MS\noutpouring/MS\noutproduce/DSG\noutput/SM\noutputted\noutputting\noutrace/GDS\noutrage/MGDS\noutrageous/Y\noutran\noutrank/GDS\noutre\noutreach/MDSG\noutrider/MS\noutrigger/SM\noutright\noutrun/S\noutrunning\noutscore/GDS\noutsell/GS\noutset/SM\noutshine/GS\noutshone\noutshout/GDS\noutside/MZRS\noutsider/M\noutsize/MS\noutskirt/MS\noutsmart/GDS\noutsold\noutsource/DSG\noutsourcing/M\noutspend/SG\noutspent\noutspoken/YP\noutspokenness/M\noutspread/GS\noutstanding/Y\noutstation/MS\noutstay/DGS\noutstretch/DSG\noutstrip/S\noutstripped\noutstripping\noutta\nouttake/MS\noutvote/GDS\noutward/YS\noutwear/GS\noutweigh/GD\noutweighs\noutwit/S\noutwith\noutwitted\noutwitting\noutwore\noutwork/MDRSZG\noutworn\nouzo/MS\nova\noval/MS\novarian\novary/SM\novate/NX\novation/M\noven/MS\novenbird/SM\novenproof\novenware\nover/MYS\noverabundance/M\noverabundant\noverachieve/ZGDRS\noverachiever/M\noveract/GVSD\noverage/SM\noveraggressive\noverall/SM\noveralls/M\noverambitious\noveranxious\noverarching\noverarm/GSD\noverate\noverattentive\noverawe/DSG\noverbalance/MGDS\noverbear/GS\noverbearing/Y\noverbid/SM\noverbidding\noverbite/MS\noverblown\noverboard\noverbold\noverbook/DGS\noverbore\noverborne\noverbought\noverbuild/SG\noverbuilt\noverburden/GSD\noverbuy/GS\novercame\novercapacity/M\novercapitalize/DSG\novercareful\novercast/MGS\novercautious\novercharge/DSMG\noverclock/GD\novercloud/SGD\novercoat/MS\novercome/GS\novercompensate/DSGN\novercompensation/M\noverconfidence/M\noverconfident\noverconscientious\novercook/DGS\novercritical\novercrowd/SDG\novercrowding/M\noverdecorate/DSG\noverdependent\noverdevelop/SDG\noverdid\noverdo/G\noverdoes\noverdone\noverdose/MGDS\noverdraft/SM\noverdraw/GS\noverdrawn\noverdress/GMDS\noverdrew\noverdrive/SM\noverdub/SM\noverdubbed\noverdubbing\noverdue\novereager\novereat/GSN\noveremotional\noveremphasis/M\noveremphasize/GDS\noverenthusiastic\noverestimate/MGNDS\noverestimation/M\noverexcite/DSG\noverexercise/GDS\noverexert/SDG\noverexertion/M\noverexpose/GDS\noverexposure/M\noverextend/DGS\noverfed\noverfeed/GS\noverfill/DGS\noverflew\noverflight/MS\noverflow/MDSG\noverflown\noverfly/GS\noverfond\noverfull\novergeneralize/DSG\novergenerous\novergraze/DSG\novergrew\noverground\novergrow/HSG\novergrown\novergrowth/M\noverhand/MDS\noverhang/MSG\noverhasty\noverhaul/MDSG\noverhead/MS\noverhear/SG\noverheard\noverheat/DSG\noverhung\noverindulge/GDS\noverindulgence/M\noverindulgent\noverjoy/GSD\noverkill/M\noverladen\noverlaid\noverlain\noverland\noverlap/SM\noverlapped\noverlapping\noverlarge\noverlay/GSM\noverleaf\noverlie\noverload/GMDS\noverlong\noverlook/GMDS\noverlord/MS\noverly/SG\novermanned\novermanning\novermaster/SDG\novermodest\novermuch/S\novernice\novernight/MS\noveroptimism/M\noveroptimistic\noverpaid\noverparticular\noverpass/MS\noverpay/GS\noverplay/GDS\noverpopulate/GNDS\noverpopulation/M\noverpower/SDG\noverpowering/Y\noverpraise/DSG\noverprecise\noverprice/DSG\noverprint/SMDG\noverproduce/GDS\noverproduction/M\noverprotect/SDGV\noverqualified\noverran\noverrate/GDS\noverreach/GDS\noverreact/SDG\noverreaction/SM\noverrefined\noverridden\noverride/MGS\noverripe/M\noverrode\noverrule/GDS\noverrun/SM\noverrunning\noversampling\noversaw\noversea/S\noversee/RSZ\noverseeing\noverseen\noverseer/M\noversell/GS\noversensitive/P\noversensitiveness/M\noversexed\novershadow/DSG\novershare/DSG\novershoe/MS\novershoot/GS\novershot\noversight/SM\noversimple\noversimplification/M\noversimplify/DSNGX\noversize\noversleep/GS\noverslept\noversold\noverspecialization/M\noverspecialize/GDS\noverspend/SG\noverspent\noverspread/GS\noverstaffed\noverstate/DSLG\noverstatement/MS\noverstay/DSG\noverstep/S\noverstepped\noverstepping\noverstimulate/DSG\noverstock/GSD\noverstretch/GDS\noverstrict\noverstrung\noverstuffed\noversubscribe/DSG\noversubtle\noversupply/GDS\noversuspicious\novert/Y\novertake/GS\novertaken\novertax/GDS\noverthink/SG\noverthought\noverthrew\noverthrow/SMG\noverthrown\novertime/MS\novertire/GDS\novertone/MS\novertook\noverture/MS\noverturn/DSG\noveruse/DSMG\novervaluation/S\novervalue/DSG\noverview/MS\noverweening/Y\noverweight/M\noverwhelm/SGD\noverwhelming/Y\noverwinter/SDG\noverwork/GMDS\noverwrite/GS\noverwritten\noverwrote\noverwrought\noverzealous\noviduct/SM\noviparous\novoid/MS\novular\novulate/DSGN\novulation/M\novule/MS\novum/M\now\nowe/DSG\nowl/SM\nowlet/MS\nowlish/Y\nown/ESGD\nowner/MS\nownership/M\nox/MN\noxblood/M\noxbow/MS\noxcart/SM\noxford/SM\noxidant/MS\noxidase\noxidation/M\noxide/MS\noxidization/M\noxidize/ZGDRS\noxidizer/M\noxtail/S\noxyacetylene/M\noxygen/M\noxygenate/DSGN\noxygenation/M\noxymora\noxymoron/M\noyster/SM\noz\nozone/M\np/NRXTGJ\npH\npa/SMH\npablum/M\npabulum/M\npace/MZGDRS\npacemaker/SM\npacer/M\npacesetter/SM\npacey\npachyderm/MS\npachysandra/MS\npacific\npacifically\npacification/M\npacifier/M\npacifism/M\npacifist/SM\npacifistic\npacify/ZGDRSN\npack's\npack/AUGSD\npackage's\npackage/AGDS\npackager/SM\npackaging/M\npacker/MS\npacket/MS\npacking's\npackinghouse/SM\npacksaddle/MS\npact/MS\npacy/RT\npad/SM\npadded\npadding/M\npaddle/MZGDRS\npaddler/M\npaddock/MDGS\npaddy/SM\npadlock/MDSG\npadre/SM\npaean/SM\npaella/MS\npagan/SM\npaganism/M\npage/MZGDRS\npageant/MS\npageantry/M\npageboy/SM\npager/M\npaginate/DSGN\npagination/M\npagoda/MS\npah\npaid/AU\npail/MS\npailful/SM\npain/MDSG\npainful/PY\npainfuller\npainfullest\npainfulness/M\npainkiller/MS\npainkilling\npainless/PY\npainlessness/M\npainstaking/MY\npaint/SZGJMDR\npaintball\npaintbox/MS\npaintbrush/MS\npainted/U\npainter/MY\npainting/M\npaintwork\npair/AMDSG\npaired/U\npairing/S\npairwise\npaisley/SM\npajama/S\npajamas/M\npal/SMY\npalace/MS\npaladin/SM\npalanquin/SM\npalatable/U\npalatal/SM\npalatalization/M\npalatalize/GDS\npalate/MBS\npalatial/Y\npalatinate/MS\npalatine/MS\npalaver/GSMD\npalazzi\npalazzo\npale/MYTGPDRSJ\npaleface/MS\npaleness/M\npaleographer/MS\npaleography/M\npaleolithic\npaleontologist/SM\npaleontology/M\npalette/SM\npalfrey/SM\npalimony/M\npalimpsest/MS\npalindrome/MS\npalindromic\npaling/M\npalisade/SM\npalish\npall/MDSG\npalladium/M\npallbearer/MS\npallet/MS\npalliate/DSGNV\npalliation/M\npalliative/SM\npallid/YP\npallidness/M\npallor/M\npalm/MDSG\npalmate\npalmetto/SM\npalmist/SM\npalmistry/M\npalmtop/SM\npalmy/TR\npalomino/MS\npalpable\npalpably\npalpate/DSGN\npalpation/M\npalpitate/XGNDS\npalpitation/M\npalsy/GDSM\npaltriness/M\npaltry/RPT\npampas/M\npamper/DSG\npamphlet/MS\npamphleteer/MS\npan/SM\npanacea/SM\npanache/M\npanama/MS\npanatella/S\npancake/DSMG\npanchromatic\npancreas/MS\npancreatic\npancreatitis\npanda/SM\npandemic/SM\npandemonium/M\npander/MDRZGS\npanderer/M\npane/KM\npanegyric/SM\npanel/SGJMD\npaneling/M\npanelist/MS\npanes\npang/MS\npanhandle/DRSMZG\npanhandler/M\npanic/SM\npanicked\npanicking\npanicky\npanned\npannier/SM\npanning\npanoply/SM\npanorama/SM\npanoramic\npanpipes/M\npansy/SM\npant/MDSG\npantaloons/M\npantechnicon/S\npantheism/M\npantheist/SM\npantheistic\npantheon/SM\npanther/MS\npantie/MS\npanto/S\npantomime/MGDS\npantomimic\npantomimist/SM\npantry/SM\npantsuit/SM\npantyhose/M\npantyliner/M\npantywaist/SM\npap/SM\npapa/MS\npapacy/SM\npapal\npaparazzi/M\npaparazzo\npapaya/MS\npaper/SZGMDR\npaperback/SM\npaperbark/S\npaperboard/M\npaperboy/SM\npaperclip/S\npaperer/M\npapergirl/SM\npaperhanger/SM\npaperhanging/M\npaperless\npaperweight/MS\npaperwork/M\npapery\npapilla/M\npapillae\npapillary\npapist/MS\npapoose/MS\npappy/SM\npaprika/M\npapyri\npapyrus/M\npar/SZGMDRBJ\npara/MS\nparable/MS\nparabola/SM\nparabolic\nparacetamol/S\nparachute/DSMG\nparachutist/MS\nparade/MZGDRS\nparader/M\nparadigm/SM\nparadigmatic\nparadisaical\nparadise/SM\nparadox/MS\nparadoxical/Y\nparaffin/M\nparagliding\nparagon/MS\nparagraph/GMD\nparagraphs\nparakeet/SM\nparalegal/MS\nparallax/MS\nparallel/SGMD\nparalleled/U\nparallelism/MS\nparallelogram/SM\nparalyses\nparalysis/M\nparalytic/SM\nparalyze/DSG\nparalyzing/Y\nparamecia\nparamecium/M\nparamedic/MS\nparamedical/MS\nparameter/MS\nparametric\nparamilitary/SM\nparamount\nparamountcy\nparamour/SM\nparanoia/M\nparanoiac/MS\nparanoid/SM\nparanormal\nparapet/MS\nparaphernalia/M\nparaphrase/DSMG\nparaplegia/M\nparaplegic/SM\nparaprofessional/MS\nparapsychologist/MS\nparapsychology/M\nparaquat/M\nparasailing\nparascending\nparasite/SM\nparasitic\nparasitical/Y\nparasitism/M\nparasol/MS\nparasympathetic/S\nparathion/M\nparathyroid/MS\nparatroop/RZS\nparatrooper/M\nparatroops/M\nparatyphoid/M\nparboil/DSG\nparcel/GMDS\nparch/LGDS\nparchment/SM\npardner/S\npardon/ZGMDRBS\npardonable/U\npardonably/U\npardoner/M\npare/S\nparegoric/M\nparent/GMDS\nparentage/M\nparental\nparentheses\nparenthesis/M\nparenthesize/DSG\nparenthetic\nparenthetical/Y\nparenthood/M\nparenting/M\nparer/M\npares/S\nparesis/M\nparfait/MS\npariah/M\npariahs\nparietal\nparimutuel/MS\nparing/M\nparish/MS\nparishioner/MS\nparity/ESM\npark/MDSG\nparka/SM\nparking/M\nparkland\nparkway/MS\nparky\nparlance/M\nparlay/GMDS\nparley/GMDS\nparliament/SM\nparliamentarian/SM\nparliamentary\nparlor/MS\nparlous\nparmigiana\nparochial/Y\nparochialism/M\nparodist/SM\nparody/GDSM\nparole/MGDS\nparolee/MS\nparoxysm/SM\nparoxysmal\nparquet/MDSG\nparquetry/M\nparred\nparricidal\nparricide/MS\nparring\nparrot/GMDS\nparry/GDSM\nparse/DRSG\nparsec/MS\nparsimonious/Y\nparsimony/M\nparsley/M\nparsnip/MS\nparson/MS\nparsonage/MS\npart's\npart/CDSG\npartake/ZGRS\npartaken\npartaker/M\nparterre/SM\nparthenogenesis/M\npartial/MYS\npartiality/M\nparticipant/SM\nparticipate/DSGN\nparticipation/M\nparticipator/MS\nparticipatory\nparticipial/M\nparticiple/MS\nparticle/SM\nparticleboard/M\nparticular/SMY\nparticularity/SM\nparticularization/M\nparticularize/DSG\nparticulate/SM\nparting/MS\npartisan/SM\npartisanship/M\npartition/GMDS\npartitive/MS\npartly\npartner/MDSG\npartnership/MS\npartook\npartridge/SM\nparturition/M\npartway\nparty/GDSM\nparvenu/MS\npascal/MS\npaschal\npasha/SM\npass/M\npassably\npassage/MS\npassageway/MS\npassbook/MS\npasse/DRSBXZGNV\npassel/MS\npassenger/SM\npasser/M\npasserby/M\npassersby\npassim\npassing/MY\npassion/EM\npassionate/EY\npassionflower/SM\npassionless\npassive/PMYS\npassiveness/M\npassivity/M\npassivization\npassivize/DSG\npasskey/MS\npassphrase/S\npassport/MS\npassword/MS\npast/AMS\npasta/SM\npaste/DSMG\npasteboard/M\npastel/MS\npastern/MS\npasteurization/M\npasteurize/ZGDRS\npasteurized/U\npasteurizer/M\npastiche/MS\npastie\npastille/MS\npastime/MS\npastiness/M\npastor/MS\npastoral/MS\npastorate/MS\npastrami/M\npastry/SM\npasturage/M\npasture/DSMG\npastureland/M\npasty/PTRSM\npat/SM\npatch/EGMDS\npatchily\npatchiness/M\npatchouli\npatchwork/SM\npatchy/TPR\npate/MS\npatella/MS\npatellae\npatent/GMDYS\npaterfamilias/MS\npaternal/Y\npaternalism/M\npaternalist/S\npaternalistic\npaternity/M\npaternoster/MS\npath/M\npathetic\npathetically\npathfinder/SM\npathless\npathogen/SM\npathogenic\npathological/Y\npathologist/SM\npathology/M\npathos/M\npaths\npathway/MS\npatience/M\npatient/IMST\npatienter\npatiently\npatina/MS\npatine\npatio/SM\npatisserie/S\npatois/M\npatresfamilias\npatriarch/M\npatriarchal\npatriarchate/MS\npatriarchs\npatriarchy/SM\npatrician/SM\npatricide/SM\npatrimonial\npatrimony/SM\npatriot/SM\npatriotic/U\npatriotically\npatriotism/M\npatrol/MS\npatrolled\npatrolling\npatrolman/M\npatrolmen\npatrolwoman/M\npatrolwomen\npatron/MS\npatronage/MS\npatroness/MS\npatronize/ZGDRS\npatronizer/M\npatronizing/Y\npatronymic/SM\npatronymically\npatroon/SM\npatsy/SM\npatted\npatter/MDGS\npattern/SMDG\npatting\npatty/SM\npaucity/M\npaunch/MS\npaunchy/RT\npauper/MS\npauperism/M\npauperize/DSG\npause/DSMG\npave/AGDS\npaved/U\npavement/MS\npavilion/SM\npaving/MS\npavlova/S\npaw/SGMD\npawl/MS\npawn/MDSG\npawnbroker/MS\npawnbroking/M\npawnshop/MS\npawpaw/MS\npay's\npay/ASGBL\npayback/SM\npaycheck/MS\npayday/MS\npayed\npayee/SM\npayer/SM\npayload/SM\npaymaster/SM\npayment/ASM\npayoff/MS\npayola/M\npayout/MS\npayphone/S\npayroll/SM\npayslip/SM\npaywall/SM\npayware\npct\npd\npea/SM\npeace/SM\npeaceable\npeaceably\npeaceful/PY\npeacefulness/M\npeacekeeper/SM\npeacekeeping/M\npeacemaker/MS\npeacemaking/M\npeacetime/M\npeach/MS\npeachy/TR\npeacock/MS\npeafowl/MS\npeahen/MS\npeak/MDSG\npeaky\npeal/AMDSG\npeanut/MS\npear/MYS\npearl/SGMD\npearly/RT\npeasant/SM\npeasantry/M\npeashooter/SM\npeat/M\npeaty/TR\npebble/MGDS\npebbly\npecan/SM\npeccadillo/M\npeccadilloes\npeccary/SM\npeck/MDRSZG\npeckish\npecs\npectic\npectin/M\npectoral/MS\npeculate/GNDS\npeculation/M\npeculator/SM\npeculiar/Y\npeculiarity/SM\npecuniary\npedagogic\npedagogical/Y\npedagogue/SM\npedagogy/M\npedal/SGMD\npedalo/S\npedant/MS\npedantic\npedantically\npedantry/M\npeddle/ZGDRS\npeddler/M\npederast/MS\npederasty/M\npedestal/MS\npedestrian/SM\npedestrianization\npedestrianize/GDS\npediatric/S\npediatrician/MS\npediatrics/M\npedicab/SM\npedicure/MGDS\npedicurist/MS\npedigree/MDS\npediment/MS\npedometer/MS\npedophile/S\npedophilia\npeduncle/MS\npee/DRSMZ\npeeing\npeek/MDSG\npeekaboo/M\npeel/MDRSJZG\npeeled/U\npeeler/M\npeeling/M\npeen/MS\npeep/MDRSZG\npeepbo\npeeper/M\npeephole/MS\npeepshow/MS\npeer/MDG\npeerage/SM\npeeress/MS\npeerless\npeeve/DSMG\npeevish/PY\npeevishness/M\npeewee/MS\npeewit/S\npeg/SM\npegboard/MS\npegged\npegging\npeignoir/SM\npejoration/M\npejorative/SMY\npeke/MS\npekineses\npekingese/SM\npekoe/M\npelagic\npelf/M\npelican/MS\npellagra/M\npellet/GMDS\npellucid\npelmet/S\npelt/MDSG\npelvic\npelvis/MS\npemmican/M\npen/M\npenal\npenalization/M\npenalize/DSG\npenalty/SM\npenance/MS\npence\npenchant/SM\npencil/GMDJS\npend/CDSG\npendant/MS\npendent/MS\npendulous\npendulum/MS\npenetrability/M\npenetrable\npenetrate/DSGNVX\npenetrating/Y\npenetration/M\npenfriend/S\npenguin/MS\npenicillin/M\npenile\npeninsula/SM\npeninsular\npenis/MS\npenitence/M\npenitent/SMY\npenitential\npenitentiary/SM\npenknife/M\npenknives\npenlight/SM\npenman/M\npenmanship/M\npenmen\npennant/MS\npenned\npenniless\npenning\npennon/MS\npenny/SM\npennyweight/MS\npennyworth\npenologist/MS\npenology/M\npension/BZGMDRS\npensioner/M\npensive/PY\npensiveness/M\npent\npentacle/MS\npentagon/MS\npentagonal\npentagram/SM\npentameter/SM\npentathlete/MS\npentathlon/MS\npenthouse/SM\npenuche/M\npenultimate/SM\npenumbra/MS\npenumbrae\npenurious/PY\npenuriousness/M\npenury/M\npeon/MS\npeonage/M\npeony/SM\npeople/MGDS\npep/SM\npepped\npepper/GMDS\npeppercorn/SM\npeppermint/SM\npepperoni/MS\npeppery\npeppiness/M\npepping\npeppy/TPR\npepsin/M\npeptic/MS\npeptide/S\nperadventure/M\nperambulate/XGNDS\nperambulation/M\nperambulator/MS\npercale/MS\nperceive/BGDS\nperceived/U\npercent/MS\npercentage/SM\npercentile/SM\nperceptible\nperceptibly\nperception/SM\nperceptional\nperceptive/PY\nperceptiveness/M\nperceptual/Y\nperch/GMDS\nperchance\npercipience/M\npercipient\npercolate/GNDS\npercolation/M\npercolator/SM\npercussion/AM\npercussionist/MS\npercussive\nperdition/M\nperdurable\nperegrinate/DSXGN\nperegrination/M\nperegrine/MS\nperemptorily\nperemptory\nperennial/SMY\nperestroika/M\nperfect/PTGMDRYS\nperfecta/MS\nperfectibility/M\nperfectible\nperfection/SM\nperfectionism/M\nperfectionist/SM\nperfectness/M\nperfidious/Y\nperfidy/SM\nperforate/GNXDS\nperforation/M\nperforce\nperform/SDRZG\nperformance/SM\nperformative\nperformed/U\nperformer/M\nperfume/DRSMZG\nperfumer/M\nperfumery/SM\nperfunctorily\nperfunctory\nperfusion\npergola/SM\nperhaps\npericardia\npericardial\npericarditis\npericardium/M\nperigee/SM\nperihelia\nperihelion/M\nperil/SGMD\nperilous/Y\nperimeter/SM\nperinatal\nperinea\nperineum/M\nperiod/MS\nperiodic\nperiodical/SMY\nperiodicity/M\nperiodontal\nperiodontics/M\nperiodontist/SM\nperipatetic/MS\nperipheral/MYS\nperiphery/SM\nperiphrases\nperiphrasis/M\nperiphrastic\nperiscope/SM\nperish/BDRSZG\nperishable/MS\nperistalses\nperistalsis/M\nperistaltic\nperistyle/SM\nperitoneal\nperitoneum/MS\nperitonitis/M\nperiwig/SM\nperiwinkle/SM\nperjure/DRSZG\nperjurer/M\nperjury/SM\nperk/MDSG\nperkily\nperkiness/M\nperky/TPR\nperm/MDSG\npermafrost/M\npermanence/M\npermanency/M\npermanent/SMY\npermeability/M\npermeable\npermeate/GNDS\npermeation/M\npermissible\npermissibly\npermission/MS\npermissive/PY\npermissiveness/M\npermit/MS\npermitted\npermitting\npermutation/SM\npermute/DSG\npernicious/YP\nperniciousness/M\nperoration/MS\nperoxide/MGDS\nperpendicular/SMY\nperpendicularity/M\nperpetrate/DSGN\nperpetration/M\nperpetrator/MS\nperpetual/SMY\nperpetuate/DSGN\nperpetuation/M\nperpetuity/M\nperplex/GDS\nperplexed/Y\nperplexity/SM\nperquisite/SM\npersecute/GNXDS\npersecution/M\npersecutor/SM\nperseverance/M\npersevere/DSG\npersiflage/M\npersimmon/SM\npersist/SGD\npersistence/M\npersistent/Y\npersnickety\nperson/UMS\npersona/SM\npersonable\npersonae\npersonage/MS\npersonal/MYS\npersonality/SM\npersonalize/CDSG\npersonalty/M\npersonification/M\npersonify/GDSNX\npersonnel/M\nperspective/MS\nperspex\nperspicacious/Y\nperspicacity/M\nperspicuity/M\nperspicuous\nperspiration/M\nperspire/GDS\npersuade/BZGDRS\npersuaded/U\npersuader/M\npersuasion/SM\npersuasive/PY\npersuasiveness/M\npert/RYPT\npertain/GSD\npertinacious/Y\npertinacity/M\npertinence/M\npertinent/Y\npertness/M\nperturb/DGS\nperturbation/SM\nperturbed/U\npertussis/M\nperuke/MS\nperusal/MS\nperuse/GDS\nperv/S\npervade/DSG\npervasive/PY\npervasiveness/M\nperverse/PXYN\nperverseness/M\nperversion/M\nperversity/M\npervert/SGMD\npeseta/MS\npeskily\npeskiness/M\npesky/TPR\npeso/MS\npessary/S\npessimal\npessimism/M\npessimist/SM\npessimistic\npessimistically\npest/MRSZ\npester/GD\npesticide/MS\npestiferous\npestilence/SM\npestilent\npestilential\npestle/MGDS\npesto/M\npet/SZMR\npetabyte/MS\npetal/SMD\npetard/MS\npetcock/SM\npeter/GMD\npetiole/SM\npetite/MS\npetition/ZGMDRS\npetitioner/M\npetrel/MS\npetrifaction/M\npetrify/DSG\npetrochemical/SM\npetrodollar/MS\npetrol/M\npetrolatum/M\npetroleum/M\npetrologist/SM\npetrology/M\npetted\npetticoat/MS\npettifog/S\npettifogged\npettifogger/SM\npettifoggery/M\npettifogging\npettily\npettiness/M\npetting/M\npettish/Y\npetty/PTR\npetulance/M\npetulant/Y\npetunia/MS\npew/SM\npewee/SM\npewit/SM\npewter/MS\npeyote/M\npf\npfennig/MS\npg\nphaeton/MS\nphage/S\nphagocyte/SM\nphalanger/SM\nphalanges\nphalanx/MS\nphalli\nphallic\nphallus/M\nphantasm/MS\nphantasmagoria/MS\nphantasmagorical\nphantasmal\nphantom/SM\npharaoh/M\npharaohs\npharisaic\npharisee/SM\npharmaceutic/MS\npharmaceutical/SM\npharmaceutics/M\npharmacist/MS\npharmacological\npharmacologist/SM\npharmacology/M\npharmacopoeia/MS\npharmacy/SM\npharyngeal\npharynges\npharyngitis/M\npharynx/M\nphase/DSMG\nphaseout/SM\nphat\npheasant/MS\nphenacetin/M\nphenobarbital/M\nphenol/M\nphenom/MS\nphenomena\nphenomenal/Y\nphenomenological\nphenomenology\nphenomenon/MS\nphenotype\npheromone/MS\nphew\nphi/SM\nphial/SM\nphilander/ZGDRS\nphilanderer/M\nphilandering/M\nphilanthropic\nphilanthropically\nphilanthropist/MS\nphilanthropy/SM\nphilatelic\nphilatelist/MS\nphilately/M\nphilharmonic/SM\nphilippic/MS\nphilistine/MS\nphilistinism/M\nphilodendron/SM\nphilological\nphilologist/MS\nphilology/M\nphilosopher/MS\nphilosophic\nphilosophical/Y\nphilosophize/DRSZG\nphilosophizer/M\nphilosophy/SM\nphilter/MS\nphish/ZGDR\nphisher/M\nphlebitis/M\nphlegm/M\nphlegmatic\nphlegmatically\nphloem/M\nphlox/M\nphobia/MS\nphobic/MS\nphoebe/MS\nphoenix/MS\nphone/DSMG\nphonecard/S\nphoneme/MS\nphonemic\nphonemically\nphonetic/S\nphonetically\nphonetician/SM\nphonetics/M\nphoneyed\nphoneying\nphonic/S\nphonically\nphonics/M\nphoniness/M\nphonograph/M\nphonographic\nphonographs\nphonological/Y\nphonologist/MS\nphonology/M\nphony/PTGDRSM\nphooey\nphosphate/MS\nphosphodiesterase\nphosphor/MS\nphosphorescence/M\nphosphorescent/Y\nphosphoric\nphosphorous\nphosphorus/M\nphoto/SGMD\nphotobomb/DGS\nphotocell/MS\nphotocopier/M\nphotocopy/DRSMZG\nphotoelectric\nphotoelectrically\nphotoengrave/DRSJZG\nphotoengraver/M\nphotoengraving/M\nphotofinishing/M\nphotogenic\nphotogenically\nphotograph/MDRZG\nphotographer/M\nphotographic\nphotographically\nphotographs/A\nphotography/M\nphotojournalism/M\nphotojournalist/SM\nphotometer/MS\nphoton/MS\nphotosensitive\nphotostat/SM\nphotostatic\nphotostatted\nphotostatting\nphotosynthesis/M\nphotosynthesize/GDS\nphotosynthetic\nphototropic\nphototropism\nphototypesetter\nphototypesetting\nphrasal\nphrase's\nphrase/AGDS\nphrasebook/S\nphraseology/M\nphrasing/MS\nphreaking\nphrenologist/SM\nphrenology/M\nphyla\nphylactery/SM\nphylogeny/M\nphylum/M\nphys\nphysic/SM\nphysical/MYS\nphysicality\nphysician/SM\nphysicist/SM\nphysicked\nphysicking\nphysics/M\nphysio/S\nphysiognomy/SM\nphysiography/M\nphysiologic\nphysiological/Y\nphysiologist/MS\nphysiology/M\nphysiotherapist/MS\nphysiotherapy/M\nphysique/MS\npi/SMDRHZG\npianissimo/SM\npianist/MS\npiano/SM\npianoforte/SM\npianola/S\npiaster/MS\npiazza/MS\npibroch/M\npibrochs\npic/SM\npica/M\npicador/MS\npicante\npicaresque\npicayune\npiccalilli/M\npiccolo/MS\npick/MDRSJZG\npickax/GMDS\npicker/M\npickerel/MS\npicket/ZGMDRS\npickings/M\npickle/MGDS\npickpocket/SM\npickup/MS\npicky/PTR\npicnic/MS\npicnicked\npicnicker/SM\npicnicking\npicot/SM\npictograph/M\npictographs\npictorial/MYS\npicture/MGDS\npicturesque/PY\npicturesqueness/M\npiddle/MGDS\npiddly\npidgin/MS\npie/SM\npiebald/MS\npiece/DSMG\npiecemeal\npiecework/MRZ\npieceworker/M\npiecrust/SM\npieing\npier/M\npierce/JGDS\npiercing/MY\npiety/M\npiezoelectric\npiffle/MG\npig/SML\npigeon/MS\npigeonhole/DSMG\npigged\npiggery/S\npigging\npiggish/PY\npiggishness/M\npiggy/TRSM\npiggyback/MDSG\npigheaded/PY\npigheadedness/M\npiglet/MS\npigment/MDS\npigmentation/M\npigpen/MS\npigskin/MS\npigsty/SM\npigswill\npigtail/MS\npike/MZGDRS\npiker/M\npikestaff/SM\npilaf/SM\npilaster/MS\npilchard/MS\npile/MGDSJ\npileup/MS\npilfer/ZGDRS\npilferage/M\npilferer/M\npilgrim/MS\npilgrimage/MS\npiling/M\npill/MDSG\npillage/MZGDRS\npillager/M\npillar/MDS\npillbox/MS\npillion/MS\npillock/S\npillory/GDSM\npillow/GMDS\npillowcase/MS\npillowslip/MS\npilot/DGSM\npilothouse/SM\npimento/MS\npimiento/MS\npimp/GMDYS\npimpernel/MS\npimple/DSM\npimply/RT\npin/SM\npinafore/MS\npinata/MS\npinball/M\npincer/MS\npinch/GMDS\npincushion/MS\npine's\npine/AGDS\npineapple/MS\npinewood/S\npiney\npinfeather/SM\nping/GMD\npinhead/SM\npinhole/SM\npinier\npiniest\npinion/SMDG\npink/TGPMDRS\npinkeye/M\npinkie/SM\npinkish\npinkness/M\npinko/MS\npinnacle/SM\npinnate\npinned/U\npinning/U\npinny/S\npinochle/M\npinon/MS\npinpoint/SGMD\npinprick/MS\npinsetter/SM\npinstripe/DSM\npint/MS\npinto/MS\npinup/MS\npinwheel/GSMD\npinyin/M\npinyon/SM\npioneer/SGMD\npious/YP\npiousness/M\npip/SZGMDR\npipe/MS\npipeline/SM\npiper/M\npipette/SM\npipework\npiping/M\npipit/MS\npipped\npippin/SM\npipping\npipsqueak/SM\npiquancy/M\npiquant/Y\npique/MGDS\npiracy/M\npiranha/SM\npirate/DSMG\npiratical/Y\npirogi/M\npiroshki/M\npirouette/DSMG\npiscatorial\npismire/SM\npiss/ZGMDRS\npissoir/S\npistachio/SM\npiste/S\npistil/SM\npistillate\npistol/SM\npiston/SM\npit/SM\npita/MS\npitapat/SM\npitch/MDRSZG\npitchblende/M\npitcher/M\npitchfork/MDSG\npitchman/M\npitchmen\npiteous/YP\npiteousness/M\npitfall/SM\npith/M\npithead/S\npithily\npithiness/M\npithy/RTP\npitiable\npitiably\npitiful/Y\npitiless/PY\npitilessness/M\npiton/MS\npitta/S\npittance/MS\npitted\npitting\npituitary/SM\npity/GDSM\npitying/Y\npivot/MDGS\npivotal\npix/M\npixel/MS\npixie/MS\npizza/MS\npizzazz/M\npizzeria/SM\npizzicati\npizzicato/M\npj's\npk\npkg\npkt\npkwy\npl\nplacard/SMDG\nplacate/DSGN\nplacation/M\nplacatory\nplace's\nplace/AESDLG\nplacebo/SM\nplaced/U\nplaceholder/MS\nplacekick/MDRZGS\nplacekicker/M\nplacement/EASM\nplacenta/SM\nplacental/S\nplacer/SM\nplacid/Y\nplacidity/M\nplacings\nplacket/SM\nplagiarism/SM\nplagiarist/SM\nplagiarize/DRSZG\nplagiarizer/M\nplagiary/M\nplague/DSMG\nplaice\nplaid/MS\nplain/MRYTSP\nplainchant\nplainclothes\nplainclothesman/M\nplainclothesmen\nplainness/M\nplainsman/M\nplainsmen\nplainsong/M\nplainspoken\nplaint/SMV\nplaintiff/SM\nplaintive/Y\nplait/MDGS\nplan/ZMRS\nplanar\nplane's\nplane/CGDS\nplaneload/MS\nplaner/M\nplanet/SM\nplanetarium/SM\nplanetary\nplangency/M\nplangent\nplank/MDGS\nplanking/M\nplankton/M\nplanned/U\nplanner/SM\nplanning/S\nplant/MDRZGSJ\nplantain/SM\nplantar\nplantation/MS\nplanter/M\nplanting/M\nplantlike\nplaque/SM\nplash/MDSG\nplasma/M\nplaster/SZGMDR\nplasterboard/M\nplasterer/M\nplastic/SM\nplasticity/M\nplasticize/DSG\nplastique\nplat/XGMDNS\nplate/MS\nplateau/SMDG\nplateful/SM\nplatelet/SM\nplaten/M\nplatform/SGMD\nplating/M\nplatinum/M\nplatitude/SM\nplatitudinous\nplatonic\nplatoon/SGMD\nplatted\nplatter/SM\nplatting\nplaty/M\nplatypus/MS\nplatys\nplaudit/SM\nplausibility/M\nplausible\nplausibly\nplay/AEGMDS\nplayable/EU\nplayact/SGD\nplayacting/M\nplayback/MS\nplaybill/MS\nplaybook/MS\nplayboy/SM\nplayer/SM\nplayfellow/SM\nplayful/PY\nplayfulness/M\nplaygirl/MS\nplaygoer/MS\nplayground/SM\nplaygroup/S\nplayhouse/MS\nplaylist/MS\nplaymate/MS\nplayoff/SM\nplaypen/SM\nplayroom/SM\nplayschool/S\nplaything/SM\nplaytime/M\nplaywright/SM\nplaza/MS\nplea/MS\nplead/DRZGSJ\npleader/M\npleading/MY\npleasant/UTYP\npleasanter\npleasantness/UM\npleasantry/SM\nplease/EDSG\npleasing/YS\npleasurably\npleasure/MGDSB\npleasureful\npleat/MDGS\npleb/S\nplebby\nplebe/MS\nplebeian/MS\nplebiscite/MS\nplectra\nplectrum/MS\npledge/DSMG\nplenary/SM\nplenipotentiary/SM\nplenitude/SM\nplenteous\nplentiful/Y\nplenty/M\nplenum/S\npleonasm/MS\nplethora/M\npleura/M\npleurae\npleurisy/M\nplexus/MS\npliability/M\npliable\npliancy/M\npliant/Y\npliers/M\nplight/SMDG\nplimsoll/S\nplinth/M\nplinths\nplod/S\nplodded\nplodder/MS\nplodding/S\nplonk/DRSZG\nplop/MS\nplopped\nplopping\nplosive/S\nplot/MS\nplotted\nplotter/SM\nplotting\nplover/SM\nplow/GMDS\nplowman/M\nplowmen\nplowshare/MS\nploy's\nploy/S\npluck/MDSG\npluckily\npluckiness/M\nplucky/RPT\nplug's\nplug/US\nplugged/U\nplugging/U\nplughole/S\nplugin/SM\nplum/GMDS\nplumage/M\nplumb/MDRSZGJ\nplumbed/U\nplumber/M\nplumbing/M\nplume/MS\nplummer\nplummest\nplummet/SGMD\nplummy\nplump/MDRYSTGP\nplumpness/M\nplumy/RT\nplunder/SZGMDR\nplunderer/M\nplunge/DRSMZG\nplunger/M\nplunk/MDSG\npluperfect/SM\nplural/SM\npluralism/M\npluralist/MS\npluralistic\nplurality/SM\npluralization/M\npluralize/GDS\nplus/MS\nplush/MRYTP\nplushness/M\nplushy/RT\nplutocracy/SM\nplutocrat/SM\nplutocratic\nplutonium/M\npluvial\nply/AGDSM\nplywood/M\npm\npneumatic\npneumatically\npneumococcal\npneumococci\npneumococcus\npneumonia/M\npoach/DRSZG\npoacher/M\npoaching/M\npock/GMDS\npocket/SMDG\npocketbook/SM\npocketful/SM\npocketknife/M\npocketknives\npockmark/MDGS\npod/SM\npodcast/SM\npodded\npodding\npodiatrist/SM\npodiatry/M\npodium/SM\npoem/MS\npoesy/M\npoet/MS\npoetaster/MS\npoetess/MS\npoetic/S\npoetical/Y\npoetry/M\npogrom/SM\npoi/M\npoignancy/M\npoignant/Y\npoinciana/SM\npoinsettia/SM\npoint/MDRSZG\npointblank\npointed/Y\npointer/M\npointillism/M\npointillist/SM\npointless/PY\npointlessness/M\npointy/TR\npoise/MGDS\npoison/SJZGMDR\npoisoner/M\npoisoning/M\npoisonous/Y\npoke/MZGDRS\npoker/M\npokey/MS\npoky/TR\npol/SGMD\npolar\npolarity/SM\npolarization/CM\npolarize/CDSG\npole/MS\npoleaxe/GDS\npolecat/MS\npolemic/MS\npolemical/Y\npolemicist/SM\npolemics/M\npolestar/SM\npolice/DSMG\npoliceman/M\npolicemen\npolicewoman/M\npolicewomen\npolicy/SM\npolicyholder/MS\npolicymaker/S\npolio/MS\npoliomyelitis/M\npolish/ZGMDRS\npolished/U\npolisher/M\npolitburo/MS\npolite/RYTP\npoliteness/M\npolitesse/M\npolitic/S\npolitical/Y\npolitician/SM\npoliticization/M\npoliticize/CDSG\npoliticking/M\npolitico/SM\npolitics/M\npolity/SM\npolka/MDSG\npoll/GMDNS\npollack/MS\npollard/S\npollen/M\npollinate/GNDS\npollination/M\npollinator/SM\npolling/M\npolliwog/SM\npollster/SM\npollutant/MS\npollute/ZGNDRS\npolluted/U\npolluter/M\npollution/M\npolo/M\npolonaise/SM\npolonium/M\npoltergeist/MS\npoltroon/SM\npoly\npolyacrylamide\npolyamory/S\npolyandrous\npolyandry/M\npolyclinic/SM\npolyester/MS\npolyethylene/M\npolygamist/MS\npolygamous\npolygamy/M\npolyglot/SM\npolygon/SM\npolygonal\npolygraph/GMD\npolygraphs\npolyhedral\npolyhedron/SM\npolymath/M\npolymaths\npolymer/SM\npolymeric\npolymerization/M\npolymerize/GDS\npolymorphic\npolymorphous\npolynomial/MS\npolyp/MS\npolyphonic\npolyphony/M\npolypropylene/M\npolys\npolysemous\npolystyrene/M\npolysyllabic\npolysyllable/MS\npolytechnic/MS\npolytheism/M\npolytheist/SM\npolytheistic\npolythene\npolyunsaturate/DS\npolyurethane/MS\npolyvinyl\npom/S\npomade/DSMG\npomander/SM\npomegranate/MS\npommel/SGMD\npommy/S\npomp/M\npompadour/SMD\npompano/MS\npompom/SM\npomposity/M\npompous/YP\npompousness/M\nponce/GDS\nponcho/SM\nponcy\npond/MS\nponder/SZGDR\nponderer/M\nponderous/YP\nponderousness/M\npone/MS\npong/GDS\npongee/M\nponiard/MS\npontiff/SM\npontifical/Y\npontificate/DSMG\npontoon/SM\npony/GDSM\nponytail/MS\npoo/SGD\npooch/MDSG\npoodle/SM\npoof/MS\npoofter/S\npooh/GMD\npoohs\npool/GMDS\npoolroom/MS\npoolside/S\npoop/GMDS\npoor/TRYP\npoorboy/M\npoorhouse/SM\npoorness/M\npop/SM\npopcorn/M\npope/MS\npopgun/SM\npopinjay/MS\npoplar/SM\npoplin/M\npopover/SM\npoppa/MS\npoppadom/S\npopped\npopper/SM\npoppet/S\npopping\npoppy/SM\npoppycock/M\npopulace/MS\npopular/Y\npopularity/UM\npopularization/M\npopularize/DSG\npopulate/ACGDS\npopulation/CM\npopulations\npopulism/M\npopulist/MS\npopulous/P\npopulousness/M\npopup/MS\nporcelain/SM\nporch/MS\nporcine\nporcupine/SM\npore/MGDS\nporgy/SM\npork/ZMR\nporker/M\nporky/RSMT\nporn/M\nporno/M\npornographer/MS\npornographic\npornographically\npornography/M\nporosity/M\nporous/P\nporousness/M\nporphyritic\nporphyry/M\nporpoise/MGDS\nporridge/M\nporringer/SM\nport's/A\nport/CAEGDS\nportability/M\nportable/MS\nportage/DSMG\nportal/SM\nportcullis/MS\nportend/SGD\nportent/SM\nportentous/YP\nporter/ASM\nporterhouse/SM\nportfolio/MS\nporthole/MS\nportico/M\nporticoes\nportiere/MS\nportion/KSGMD\nportliness/M\nportly/RPT\nportmanteau/MS\nportrait/MS\nportraitist/SM\nportraiture/M\nportray/SGD\nportrayal/MS\nportulaca/M\npose's/A\npose/CAKEGDS\nposer/EKSM\nposeur/SM\nposh/TR\nposit/DSGV\nposition/CKEMS\npositional/K\npositioned/K\npositioning/K\npositive/MYPS\npositiveness/M\npositivism\npositivist/S\npositron/MS\nposs\nposse/MS\npossess/AEVGSD\npossession/ASM\npossessive/SMYP\npossessiveness/M\npossessor/SM\npossibility/SM\npossible/SM\npossibly\npossum/SM\npost/ZGMDRSJ\npostage/M\npostal\npostbag/S\npostbox/S\npostcard/SM\npostcode/S\npostcolonial\npostconsonantal\npostdate/DSG\npostdoc/MS\npostdoctoral\nposter/M\nposterior/SM\nposterity/M\npostgraduate/SM\nposthaste\nposthumous/Y\nposthypnotic\npostie/S\npostilion/SM\npostindustrial\nposting/M\npostlude/SM\npostman/M\npostmark/SMDG\npostmaster/MS\npostmen\npostmenopausal\npostmeridian\npostmistress/MS\npostmodern\npostmodernism/M\npostmodernist/MS\npostmortem/SM\npostnasal\npostnatal\npostoperative\npostpaid\npostpartum\npostpone/DSGL\npostponement/SM\npostprandial\npostscript/SM\npostseason/SM\npostulate/XDSMGN\npostulation/M\npostural\nposture/MGJDS\nposturing/M\npostwar\npostwoman\npostwomen\nposy/SM\npot/CSM\npotability/M\npotable/SM\npotash/M\npotassium/M\npotato/M\npotatoes\npotbelly/DSM\npotboiler/SM\npotency/M\npotent/Y\npotentate/MS\npotential/MYS\npotentiality/SM\npotentiate/GDS\npotful/SM\npothead/SM\npother/SMDG\npotherb/SM\npotholder/MS\npothole/DRSMZG\npothook/SM\npotion/SM\npotluck/MS\npotpie/SM\npotpourri/SM\npotsherd/SM\npotshot/MS\npottage/M\npotted\npotter/GSMD\npottery/SM\npotting\npotty/PRSMT\npouch/MDSG\npouf/S\npouffe/S\npoulterer/MS\npoultice/DSMG\npoultry/M\npounce/DSMG\npound's\npound/KDSG\npoundage/M\npounding/SM\npour/GDSJ\npout/ZGMDRS\npouter/M\npoverty/M\npow\npowder/GSMD\npowdery\npower/MDSG\npowerboat/MS\npowerful/Y\npowerhouse/SM\npowerless/PY\npowerlessness/M\npowwow/SGMD\npox/MS\npp\nppm\nppr\npr\npracticability/M\npracticably\npractical/SMY\npracticality/SM\npractice/DSMGB\npracticed/U\npracticum/SM\npractitioner/SM\npraetor/SM\npraetorian\npragmatic/MS\npragmatical/Y\npragmatism/M\npragmatist/MS\nprairie/SM\npraise/EDSMG\npraiseworthiness/M\npraiseworthy/P\npraline/SM\npram/MS\nprance/DRSMZG\nprancer/M\nprancing/Y\nprang/DSG\nprank/MS\nprankster/SM\npraseodymium/M\nprat/S\nprate/MZGDRS\nprater/M\npratfall/SM\nprattle/DRSMZG\nprattler/M\nprawn/MDSG\npray/ZGDRS\nprayer/M\nprayerful/Y\npreach/DRSZGL\npreacher/M\npreachment/M\npreachy/RT\npreadolescence/SM\npreamble/MGDS\nprearrange/LGDS\nprearrangement/M\npreassigned\nprecancel/SMDG\nprecancerous\nprecarious/PY\nprecariousness/M\nprecast\nprecaution/MS\nprecautionary\nprecede/DSG\nprecedence/M\nprecedent/SM\nprecept/SM\npreceptor/SM\nprecinct/MS\npreciosity/M\nprecious/YP\npreciousness/M\nprecipice/SM\nprecipitant/MS\nprecipitate/XMYGNDS\nprecipitation/M\nprecipitous/Y\nprecis/M\nprecise/DRSYTGNP\npreciseness/M\nprecision/M\npreclude/GDS\npreclusion/M\nprecocious/YP\nprecociousness/M\nprecocity/M\nprecognition/M\nprecognitive\nprecolonial\npreconceive/GDS\npreconception/SM\nprecondition/MDGS\nprecook/GSD\nprecursor/SM\nprecursory\npredate/DSG\npredator/MS\npredatory\npredawn\npredecease/GDS\npredecessor/SM\npredefined\npredesignate/GDS\npredestination/M\npredestine/DSG\npredetermination/M\npredetermine/ZGDRS\npredeterminer/M\npredicable\npredicament/MS\npredicate/MGNVDS\npredication/M\npredicative/Y\npredict/BGVSD\npredictability/UM\npredictable/U\npredictably/U\nprediction/SM\npredictor/MS\npredigest/GDS\npredilection/SM\npredispose/GDS\npredisposition/MS\npredominance/M\npredominant/Y\npredominate/YGDS\npreemie/SM\npreeminence/M\npreeminent/Y\npreempt/GVSD\npreemption/M\npreemptive/Y\npreen/DSG\npreexist/DGS\npreexistence/M\npref\nprefab/SM\nprefabbed\nprefabbing\nprefabricate/DSGN\nprefabrication/M\npreface/DSMG\nprefatory\nprefect/SM\nprefecture/MS\nprefer/SBL\npreferably\npreference/MS\npreferential/Y\npreferment/M\npreferred\npreferring\nprefigure/GDS\nprefix/MDSG\npreform/GSD\npregame/SM\npregnancy/SM\npregnant\npreheat/GSD\nprehensile\nprehistorian/S\nprehistoric\nprehistorical/Y\nprehistory/M\nprehuman\nprejudge/GDS\nprejudgment/SM\nprejudice/MGDS\nprejudiced/U\nprejudicial\nprekindergarten/SM\nprelacy/M\nprelate/SM\nprelim/SM\npreliminary/SM\npreliterate\nprelude/MS\npremarital\npremature/Y\npremed/SM\npremedical\npremeditate/DSGN\npremeditated/U\npremeditation/M\npremenstrual\npremier/SGMD\npremiere/MS\npremiership/MS\npremise/DSMG\npremium/SM\npremix/GDS\npremolar/SM\npremonition/MS\npremonitory\nprenatal/Y\nprenup/SM\nprenuptial\npreoccupation/SM\npreoccupy/DSG\npreoperative\npreordain/GDS\nprep/MS\nprepackage/DSG\nprepacked\nprepaid\npreparation/SM\npreparatory\nprepare/GDS\nprepared/UP\npreparedness/UM\nprepay/GSL\nprepayment/MS\npreponderance/SM\npreponderant/Y\npreponderate/GDS\npreposition/SM\nprepositional/Y\nprepossess/GDS\nprepossessing/U\nprepossession/SM\npreposterous/Y\nprepped\nprepping\npreppy/TRSM\nprepubescence/M\nprepubescent/SM\nprepuce/MS\nprequel/MS\nprerecord/GSD\npreregister/SGD\npreregistration/M\nprerequisite/MS\nprerogative/SM\npres\npresage/MGDS\npresbyopia/M\npresbyter/SM\npresbytery/SM\npreschool/SZMR\npreschooler/M\nprescience/M\nprescient/Y\nprescribe/DSG\nprescript/SVM\nprescription/SM\nprescriptive/Y\npreseason/SM\npresence/SM\npresent/LMDRYZGSB\npresentably\npresentation/ASM\npresenter/M\npresentiment/SM\npresentment/SM\npreservation/M\npreservationist/SM\npreservative/SM\npreserve/BDRSMZG\npreserver/M\npreset/S\npresetting\npreshrank\npreshrink/GS\npreshrunk\npreside/GDS\npresidency/SM\npresident/MS\npresidential\npresidium/M\npresort/DGS\npress's\npress/ACGSD\npressed/U\npresser/MS\npressie/S\npressing/SMY\npressman/M\npressmen\npressure/DSMG\npressurization/M\npressurize/CGDS\npressurizer/SM\nprestidigitation/M\nprestige/M\nprestigious\npresto/SM\npresumably\npresume/GDSB\npresumption/SM\npresumptive\npresumptuous/YP\npresumptuousness/M\npresuppose/DSG\npresupposition/MS\npretax\npreteen/MS\npretend/DRZGS\npretender/M\npretense/SXMN\npretension/M\npretentious/UY\npretentiousness/M\npreterit/SM\npreterm\npreternatural/Y\npretest/DGS\npretext/MS\npretrial/S\nprettify/GDS\nprettily\nprettiness/M\npretty/TGDRSMP\npretzel/MS\nprevail/DGS\nprevalence/M\nprevalent\nprevaricate/DSGNX\nprevarication/M\nprevaricator/SM\nprevent/DBSGV\npreventable/U\npreventative/MS\nprevention/M\npreventive/SM\npreview/MDRSZG\nprevious/Y\nprevision/MS\nprewar\nprey/GMDS\nprezzie/S\npriapic\nprice's\nprice/AGDS\npriceless\npricey\npricier\npriciest\nprick/MDRYSZG\npricker/M\nprickle/MGDS\nprickliness/M\nprickly/PRT\npride/MGDS\nprideful/Y\nprier/M\npriest/SMY\npriestess/MS\npriesthood/SM\npriestliness/M\npriestly/RTP\nprig/MS\npriggish/P\npriggishness/M\nprim/ZGDRYP\nprimacy/M\nprimal\nprimarily\nprimary/SM\nprimate/MS\nprime/MS\nprimer/M\nprimeval\npriming/M\nprimitive/SPMY\nprimitiveness/M\nprimmer\nprimmest\nprimness/M\nprimogenitor/SM\nprimogeniture/M\nprimordial/Y\nprimp/DSG\nprimrose/SM\nprimula/S\nprince/SMY\nprincedom/SM\nprinceliness/M\nprincely/PRT\nprincess/MS\nprincipal/SMY\nprincipality/SM\nprinciple/DSM\nprincipled/U\nprint/AMDSG\nprintable/U\nprinter/MS\nprinting/SM\nprintmaking\nprintout/SM\nprion/S\nprior/MS\nprioress/MS\nprioritization\nprioritize/DSG\npriority/SM\npriory/SM\nprism/MS\nprismatic\nprison/SZMR\nprisoner/M\nprissily\nprissiness/M\nprissy/PTR\npristine\nprithee\nprivacy/M\nprivate/XMYTNRS\nprivateer/SM\nprivation/CSM\nprivatization/SM\nprivatize/DSG\nprivet/SM\nprivilege/DSMG\nprivileged/U\nprivily\nprivy/RSMT\nprize/MGDS\nprized/A\nprizefight/ZGSMR\nprizefighter/M\nprizefighting/M\nprizewinner/MS\nprizewinning\npro/SM\nprobabilistic\nprobability/SM\nprobable/SM\nprobably\nprobate/MN\nprobation/ZMR\nprobational\nprobationary\nprobationer/M\nprobe/MGDSBJ\nprobity/M\nproblem/MS\nproblematic\nproblematical/Y\nprobosces\nproboscis/MS\nprocaine/M\nprocedural\nprocedure/SM\nproceed/GJDS\nproceeding/M\nproceeds/M\nprocess's\nprocess/AGDS\nprocessed/U\nprocession/GD\nprocessional/MS\nprocessor/SM\nproclamation/MS\nproclivity/SM\nprocrastinate/DSGN\nprocrastination/M\nprocrastinator/MS\nprocreate/V\nproctor/GMDS\nprocurement/M\nprod/MS\nprodigal/MYS\nprodigality/M\nprodigious/Y\nprodigy/SM\nproduce's\nproduce/AZGDRS\nproducer/AM\nproducible/A\nproduction/ASM\nproductive/UY\nproductiveness/M\nproductivity/M\nprof/MS\nprofanation/MS\nprofane/PYGDS\nprofaneness/M\nprofanity/SM\nprofessed/Y\nprofession/SM\nprofessional/MYS\nprofessionalism/M\nprofessionalization\nprofessionalize/DSG\nprofessor/SM\nprofessorial/Y\nprofessorship/SM\nproffer/GMDS\nproficiency/M\nproficient/MYS\nprofit/BGD\nprofitability/M\nprofitable/U\nprofitably/U\nprofiteer/MDGS\nprofiteering/M\nprofiterole/SM\nprofitless\nprofligacy/M\nprofligate/SMY\nproforma\nprofound/RYTP\nprofoundness/M\nprofundity/SM\nprofuse/PY\nprofuseness/M\nprogenitor/SM\nprogeny/M\nprogesterone/M\nprogestin/S\nprognathous\nprognoses\nprognosis/M\nprognostic/MS\nprognosticate/XGNDS\nprognostication/M\nprognosticator/MS\nprogram/CAS\nprogrammable/MS\nprogrammatic\nprogrammed/AC\nprogrammer/MS\nprogramming/SM\nprogress/MDSGV\nprogression/MS\nprogressive/PMYS\nprogressiveness/M\nprohibit/DGVS\nprohibition/SM\nprohibitionist/MS\nprohibitive/Y\nprohibitory\nproject/GMDS\nprojectile/SM\nprojection/SM\nprojectionist/SM\nprojector/MS\nprokaryotic\nprole/S\nproletarian/MS\nproletariat/M\nproliferate/DSGN\nproliferation/M\nprolific\nprolifically\nprolix/Y\nprolixity/M\nprologue/SM\nprolongation/SM\nprom/M\npromenade/MGDS\npromethium/M\nprominence/M\nprominent/Y\npromiscuity/M\npromiscuous/Y\npromise/DSMG\npromising/Y\npromissory\npromo/M\npromontory/SM\npromote/DRZG\npromoter/M\npromotional\nprompt/JPSMDRYZTG\nprompted/U\nprompter/M\nprompting/M\npromptitude/M\npromptness/M\npromulgate/GNDS\npromulgation/M\npromulgator/MS\nprone/P\nproneness/M\nprong/MDS\npronghorn/MS\npronominal/M\npronounce/DSLG\npronounceable/U\npronouncement/SM\npronto\npronunciation/MS\nproof/ADGSM\nproofread/SRZG\nproofreader/M\nprop/MS\npropaganda/M\npropagandist/MS\npropagandize/GDS\npropagate/DSGN\npropagation/M\npropagator/SM\npropel/S\npropellant/MS\npropelled\npropeller/SM\npropelling\npropensity/SM\nproper/MRYT\nproperty/DSM\nprophecy/SM\nprophesier/M\nprophesy/DRSMZG\nprophet/SM\nprophetess/MS\nprophetic\nprophetical/Y\nprophylactic/SM\nprophylaxes\nprophylaxis/M\npropinquity/M\npropitiate/DSGN\npropitiation/M\npropitiatory\npropitious/Y\nproponent/SM\nproportion/ESM\nproportional/YS\nproportionality\nproportionate/EY\nproposal/MS\npropped\npropping\nproprietary/SM\nproprieties/M\nproprietor/SM\nproprietorial/Y\nproprietorship/M\nproprietress/MS\npropriety/SM\npropulsion/M\npropulsive\nprorate/DSG\nprorogation/M\nprorogue/GD\nprosaic\nprosaically\nproscenium/SM\nprosciutto/M\nproscribe/DG\nproscription/MS\nprose/M\nprosecute/DSXGN\nprosecution/M\nprosecutor/MS\nproselyte/DSMG\nproselytism/M\nproselytize/DRSZG\nproselytizer/M\nprosody/SM\nprospect/MDGVS\nprospective/Y\nprospector/SM\nprospectus/MS\nprosper/GSD\nprosperity/M\nprosperous/Y\nprostate/MS\nprostheses\nprosthesis/M\nprosthetic\nprostitute/MGNDS\nprostitution/M\nprostrate/GNXDS\nprostration/M\nprosy/RT\nprotactinium/M\nprotagonist/SM\nprotean\nprotect/GVSD\nprotected/U\nprotection/SM\nprotectionism/M\nprotectionist/MS\nprotective/PY\nprotectiveness/M\nprotector/MS\nprotectorate/MS\nprotege/SM\nprotegee/S\nprotein/SM\nprotestant/S\nprotestation/MS\nprotocol/MS\nproton/SM\nprotoplasm/M\nprotoplasmic\nprototype/MGS\nprototypical\nprotozoa\nprotozoan/MS\nprotozoic\nprotract/GD\nprotrude/GDS\nprotrusile\nprotrusion/MS\nprotuberance/MS\nprotuberant\nproud/RYT\nprov/NB\nprovability/M\nprovably\nprove/EAGDS\nproved/U\nproven/U\nprovenance/SM\nprovender/M\nprovenience/M\nproverbial/Y\nprovide/DRSZG\nprovided/U\nprovidence/M\nprovident/Y\nprovidential/Y\nprovider/M\nprovince/MS\nprovincial/SMY\nprovincialism/M\nprovisional/Y\nproviso/SM\nprovocateur/S\nprovocative/PY\nprovocativeness/M\nprovoke/DRSZG\nprovoked/U\nprovoker/M\nprovoking/Y\nprovolone/M\nprovost/SM\nprow/MS\nprowess/M\nprowl/MDRSZG\nprowler/M\nproximal\nproximate\nproximity/M\nproxy/SM\nprude/MS\nprudence/M\nprudent/Y\nprudential/Y\nprudery/M\nprudish/YP\nprudishness/M\nprune/MZGDRS\npruner/M\nprurience/M\nprurient/Y\npry/ZTGDRSM\npsalm/MS\npsalmist/SM\npsaltery/SM\npsephologist/S\npsephology\npseud/S\npseudo/S\npseudonym/SM\npseudonymous\npseudoscience/MS\npseudy\npshaw/MS\npsi/SM\npsittacosis/M\npsoriasis/M\npsst\npsych/MDSG\npsyche/M\npsychedelia\npsychedelic/SM\npsychedelically\npsychiatric\npsychiatrist/SM\npsychiatry/M\npsychic/MS\npsychical/Y\npsycho/SM\npsychoactive\npsychoanalyses\npsychoanalysis/M\npsychoanalyst/SM\npsychoanalytic\npsychoanalytical/Y\npsychoanalyze/DSG\npsychobabble/M\npsychodrama/MS\npsychogenic\npsychokinesis\npsychokinetic\npsychological/Y\npsychologist/MS\npsychology/SM\npsychometric\npsychoneuroses\npsychoneurosis/M\npsychopath/M\npsychopathic\npsychopathology\npsychopaths\npsychopathy/M\npsychopharmacology\npsychos/S\npsychosis/M\npsychosomatic\npsychotherapist/MS\npsychotherapy/SM\npsychotic/SM\npsychotically\npsychotropic/MS\npsychs\npt/C\nptarmigan/MS\npterodactyl/MS\nptomaine/SM\npub/SM\npubertal\npuberty/M\npubes/M\npubescence/M\npubescent\npubic\npubis/M\npublic/AM\npublican/AMS\npublication/ASM\npublicist/MS\npublicity/M\npublicize/GDS\npublicly\npublish/AGDS\npublishable\npublished/U\npublisher/MS\npublishing/M\npuce/M\npuck/ZMRS\npucker/MDG\npuckish/YP\npuckishness/M\npud/S\npudding/SM\npuddle/DSMG\npuddling/M\npudenda\npudendum/M\npudginess/M\npudgy/PRT\npueblo/SM\npuerile\npuerility/M\npuerperal\npuff/ZGMDRS\npuffball/SM\npuffer/M\npuffin/SM\npuffiness/M\npuffy/PRT\npug/SM\npugilism/M\npugilist/SM\npugilistic\npugnacious/YP\npugnaciousness/M\npugnacity/M\npuke/MGDS\npukka\npulchritude/M\npulchritudinous\npule/GDS\npull/ZGMDRS\npullback/MS\npuller/M\npullet/SM\npulley/SM\npullout/MS\npullover/SM\npulmonary\npulp/GMDS\npulpiness/M\npulpit/SM\npulpwood/M\npulpy/RPT\npulsar/SM\npulsate/XGNDS\npulsation/M\npulse/AMGDS\npulverization/M\npulverize/DSG\npuma/MS\npumice/SM\npummel/SGD\npump/ZGMDRS\npumper/M\npumpernickel/M\npumpkin/MS\npun/SM\npunch/MDRSZG\npunchbag/S\npuncheon/MS\npuncher/M\npunchline/S\npunchy/TR\npunctilio/M\npunctilious/PY\npunctiliousness/M\npunctual/Y\npunctuality/M\npunctuate/GNDS\npunctuation/M\npuncture/DSMG\npundit/SM\npunditry/M\npungency/M\npungent/Y\npuniness/M\npunish/BLGDS\npunished/U\npunishing/Y\npunishment/MS\npunitive/Y\npunk/TMRS\npunned\npunnet/S\npunning\npunster/SM\npunt/ZGMDRS\npunter/M\npuny/TRP\npup/SM\npupa/M\npupae\npupal\npupate/DSG\npupil/MS\npupped\npuppet/MS\npuppeteer/SM\npuppetry/M\npupping\npuppy/SM\npurblind\npurchase/DRSMZGB\npurchaser/M\npurdah/M\npure/PYTR\npurebred/SM\npuree/MDS\npureeing\npureness/M\npurgative/SM\npurgatorial\npurgatory/SM\npurge/MZGDRS\npurger/M\npurification/M\npurifier/M\npurify/NDRSZG\npurine/MS\npurism/M\npurist/MS\npuristic\npuritan/SM\npuritanical/Y\npuritanism/M\npurity/M\npurl/GMDS\npurlieu/SM\npurloin/SGD\npurple/MTRS\npurplish\npurport/SMDG\npurported/Y\npurpose/DSMYG\npurposeful/YP\npurposefulness/M\npurposeless/PY\npurr/GMDS\npurse/MZGDRS\npurser/M\npursuance/M\npursuant\npursue/ZGDRS\npursuer/M\npursuit/SM\npurulence/M\npurulent\npurvey/DSG\npurveyance/M\npurveyor/SM\npurview/M\npus/M\npush/ZGMDRS\npushbike/S\npushcart/SM\npushchair/S\npusher/M\npushily\npushiness/M\npushover/MS\npushpin/S\npushy/TRP\npusillanimity/M\npusillanimous/Y\npuss/MS\npussy/TRSM\npussycat/MS\npussyfoot/DSG\npustular\npustule/SM\nput/ISM\nputative\nputout/MS\nputrefaction/M\nputrefactive\nputrefy/GDS\nputrescence/M\nputrescent\nputrid\nputsch/MS\nputt/ZGMDRS\nputted/I\nputtee/MS\nputter/MDRZG\nputterer/M\nputting/I\nputty/GDSM\nputz/S\npuzzle/MZGDRSL\npuzzlement/M\npuzzler/M\npvt\npwn/SGD\npyelonephritis\npygmy/SM\npylon/SM\npylori\npyloric\npylorus/M\npyorrhea/M\npyramid/GSMD\npyramidal\npyre/MS\npyrimidine/MS\npyrite/SM\npyrites/M\npyromania/M\npyromaniac/SM\npyrotechnic/S\npyrotechnical\npyrotechnics/M\npython/SM\npyx/MS\npzazz\nq\nqr\nqt\nqty\nqua\nquack/GMDS\nquackery/M\nquad/MS\nquadrangle/SM\nquadrangular\nquadrant/MS\nquadraphonic\nquadratic/MS\nquadrature\nquadrennial\nquadrennium/MS\nquadriceps/MS\nquadrilateral/SM\nquadrille/XMNS\nquadrillion/M\nquadriplegia/M\nquadriplegic/SM\nquadrivium/M\nquadruped/MS\nquadrupedal\nquadruple/MGDS\nquadruplet/MS\nquadruplicate/MGNDS\nquadruplication/M\nquaff/GMDS\nquagmire/SM\nquahog/MS\nquail/GMDS\nquaint/PRYT\nquaintness/M\nquake/MGDS\nquaky\nqualification/EM\nqualified/U\nqualifier/SM\nqualify/EGXNDS\nqualitative/Y\nquality/SM\nqualm/MS\nqualmish\nquandary/SM\nquango/S\nquanta\nquantifiable\nquantification/M\nquantifier/M\nquantify/NDRSZG\nquantitative/Y\nquantity/SM\nquantum/M\nquarantine/MGDS\nquark/MS\nquarrel/SZGMDR\nquarreler/M\nquarrelsome/P\nquarrelsomeness/M\nquarry/DSMG\nquart/MS\nquarter/SGMDY\nquarterback/GMDS\nquarterdeck/MS\nquarterfinal/SM\nquarterly/SM\nquartermaster/MS\nquarterstaff/M\nquarterstaves\nquartet/SM\nquarto/MS\nquartz/M\nquasar/MS\nquash/GDS\nquasi\nquatrain/MS\nquaver/MDSG\nquavery\nquay/MS\nquayside/S\nqueasily\nqueasiness/M\nqueasy/TPR\nqueen/GMDYS\nqueenly/RT\nqueer/PTGMDRYS\nqueerness/M\nquell/GDS\nquench/ZGDRSB\nquenchable/U\nquencher/M\nquenchless\nquerulous/YP\nquerulousness/M\nquery/DSMG\nques\nquesadilla/MS\nquest/IFAMS\nquested\nquesting\nquestion/SMDRZGBJ\nquestionable/U\nquestionably/U\nquestioned/U\nquestioner/M\nquestioning/MY\nquestionnaire/SM\nqueue/MDSG\nquibble/DRSMZG\nquibbler/M\nquiche/SM\nquick/MNRYXTP\nquicken/DG\nquickfire\nquickie/SM\nquicklime/M\nquickness/M\nquicksand/MS\nquicksilver/M\nquickstep/MS\nquid/MS\nquiescence/M\nquiescent/Y\nquiet/SMDNRYXTGP\nquieten/DG\nquietism\nquietness/M\nquietude/IEM\nquietus/MS\nquiff/S\nquill/SM\nquilt/SMDRZG\nquilter/M\nquilting/M\nquin/S\nquince/SM\nquine/S\nquinine/M\nquinoa\nquinsy/M\nquint/SM\nquintessence/SM\nquintessential/Y\nquintet/SM\nquintuple/MGDS\nquintuplet/MS\nquip/MS\nquipped\nquipping\nquipster/SM\nquire's\nquire/IAS\nquirk/SMDG\nquirkiness/M\nquirky/RTP\nquirt/SM\nquisling/SM\nquit/S\nquitclaim/MS\nquite\nquittance/M\nquitter/SM\nquitting\nquiver/SMDG\nquivery\nquixotic\nquixotically\nquiz/M\nquizzed\nquizzer/SM\nquizzes\nquizzical/Y\nquizzing\nquo/H\nquoin/SM\nquoit/SMDG\nquondam\nquorate/I\nquorum/SM\nquot/B\nquota/SM\nquotability/M\nquotation/SM\nquote's\nquote/UDSG\nquotidian\nquotient/SM\nqwerty\nr/S\nrabbet/GMDS\nrabbi/SM\nrabbinate/M\nrabbinic\nrabbinical\nrabbit/GMDS\nrabble/MS\nrabid/PY\nrabidness/M\nrabies/M\nraccoon/M\nrace/MZGDRS\nracecourse/SM\nracegoer/S\nracehorse/MS\nraceme/MS\nracer/M\nracetrack/MS\nraceway/MS\nracial/Y\nracialism/M\nracialist/MS\nracily\nraciness/M\nracing/M\nracism/M\nracist/SM\nrack/GMDS\nracket/SMDG\nracketeer/SMDG\nracketeering/M\nraconteur/SM\nracquetball/SM\nracy/PRT\nrad/SM\nradar/SM\nradarscope/SM\nraddled\nradial/SMY\nradiance/M\nradiant/Y\nradiate/DSGNX\nradiation/M\nradiator/SM\nradical/SMY\nradicalism/M\nradicalization/M\nradicalize/DSG\nradicchio/M\nradii\nradio/MDGS\nradioactive/Y\nradioactivity/M\nradiocarbon/M\nradiogram/MS\nradiographer/SM\nradiography/M\nradioisotope/MS\nradiologist/SM\nradiology/M\nradioman/M\nradiomen\nradiometer/MS\nradiometric\nradiometry/M\nradiophone/SM\nradioscopy/M\nradiosonde/SM\nradiosurgery\nradiotelegraph/M\nradiotelegraphs\nradiotelegraphy/M\nradiotelephone/MS\nradiotherapist/MS\nradiotherapy/M\nradish/MS\nradium/M\nradius/M\nradon/M\nraffia/M\nraffish/YP\nraffishness/M\nraffle/DSMG\nraft/ZGMDRS\nrafter/M\nrafting/M\nrag/SGMD\nraga/MS\nragamuffin/MS\nragbag/M\nrage/MS\nragga\nragged/RYTP\nraggedness/M\nraggedy/RT\nragging\nraging/Y\nraglan/SM\nragout/SM\nragtag/S\nragtime/M\nragweed/M\nragwort\nrah\nraid/ZGMDRS\nraider/M\nrail's\nrail/CGDS\nrailcard/S\nrailing/SM\nraillery/SM\nrailroad/SZGMDR\nrailroader/M\nrailroading/M\nrailway/SM\nrailwayman\nrailwaymen\nraiment/M\nrain/GMDS\nrainbow/SM\nraincoat/SM\nraindrop/SM\nrainfall/SM\nrainmaker/SM\nrainmaking/M\nrainproof\nrainstorm/MS\nrainwater/M\nrainy/RT\nraise/MZGDRS\nraiser/M\nraisin/SM\nrajah/M\nrajahs\nrake/MGDS\nrakish/YP\nrakishness/M\nrally/DSMG\nram/SM\nramble/DRSMZGJ\nrambler/M\nrambunctious/PY\nrambunctiousness/M\nramekin/SM\nramie/M\nramification/M\nramify/DSXNG\nramjet/SM\nrammed\nramming\nramp/GMS\nrampage/DSMG\nrampancy/M\nrampant/Y\nrampart/SM\nramrod/SM\nramrodded\nramrodding\nramshackle\nran/A\nranch/MDRSZG\nrancher/M\nranching/M\nrancid/P\nrancidity/M\nrancidness/M\nrancor/M\nrancorous/Y\nrand/M\nrandiness/M\nrandom/PSY\nrandomization/M\nrandomize/DSG\nrandomness/MS\nrandy/RTP\nranee/MS\nrang/ZR\nrange's\nrange/CGDS\nrangefinder/S\nranger/M\nranginess/M\nrangy/RTP\nrank/TGJPMDRYS\nranking/M\nrankle/DSG\nrankness/M\nransack/SGD\nransom/SZGMDR\nransomer/M\nrant/ZGMDJRS\nranter/M\nrap/SZGMDR\nrapacious/PY\nrapaciousness/M\nrapacity/M\nrape/MS\nraper/M\nrapeseed/M\nrapid/PMRYTS\nrapidity/M\nrapidness/M\nrapier/SM\nrapine/M\nrapist/SM\nrapped\nrappel/SM\nrappelled\nrappelling\nrapper/SM\nrapping\nrapport/MS\nrapporteur/S\nrapprochement/SM\nrapscallion/MS\nrapt/YP\nraptness/M\nraptor/S\nrapture/MS\nrapturous/Y\nrare/YTGPDRS\nrarebit/MS\nrarefaction/M\nrarefy/GDS\nrareness/M\nrarity/SM\nrascal/SMY\nrash/ZTMRSYP\nrasher/M\nrashness/M\nrasp/GMDS\nraspberry/SM\nraspy/RT\nraster\nrat/SM\nratatouille/M\nratbag/S\nratchet/GMDS\nrate/JXMZGNDRS\nrated/U\nratepayer/S\nrater/M\nrather\nrathskeller/SM\nratification/M\nratifier/M\nratify/NDRSZG\nrating/M\nratio/MS\nratiocinate/GNDS\nratiocination/M\nration/MDG\nrational/SMY\nrationale/MS\nrationalism/M\nrationalist/SM\nrationalistic\nrationality/M\nrationalization/MS\nrationalize/DSG\nratlike\nratline/SM\nrattan/SM\nratted\nratter/SM\nratting\nrattle/DRSMZGJ\nrattlebrain/SMD\nrattler/M\nrattlesnake/SM\nrattletrap/SM\nrattly\nrattrap/SM\nratty/RT\nraucous/YP\nraucousness/M\nraunchily\nraunchiness/M\nraunchy/TRP\nravage/DRSMZG\nravager/M\nravages/M\nrave/JMZGDRS\nravel's\nravel/UDSG\nraveling/S\nraven/MDSG\nravenous/Y\nravine/SM\nraving/M\nravioli/SM\nravish/DRSZGL\nravisher/M\nravishing/Y\nravishment/M\nraw/PTMR\nrawboned\nrawhide/M\nrawness/M\nray/SM\nrayon/M\nraze/GDS\nrazor/MS\nrazorback/MS\nrazz/GMDS\nrazzmatazz/M\nrcpt\nrd\nre/DSMYTGVJ\nreach/MDSGB\nreachable/U\nreacquire/DSG\nreact/V\nreactant/SM\nreactionary/SM\nreactivity\nread/ZGMRBJS\nreadability/SM\nreader/M\nreadership/SM\nreadily\nreadiness/M\nreading/M\nreadmitted\nreadout/SM\nready/DRSTGP\nreafforestation\nreal/TMRYPS\nrealism/M\nrealist/SM\nrealistic/U\nrealistically/U\nrealities\nreality/UM\nrealization/MS\nrealize/DSBG\nrealized/U\nrealm/MS\nrealness/M\nrealpolitik/M\nrealty/M\nream/ZGMDRS\nreamer/M\nreap/ZGDRS\nreaper/M\nrear/GMDS\nrearguard/MS\nrearmost\nrearward/S\nreason/SMDRZGB\nreasonable/UP\nreasonableness/UM\nreasonably/U\nreasoner/M\nreasoning/M\nreassuring/Y\nrebate/M\nrebel/MS\nrebellion/MS\nrebellious/YP\nrebelliousness/M\nrebid/S\nrebidding\nrebirth/M\nreboil/SDG\nrebuild/SG\nrebuke/DSMG\nrebuking/Y\nrebuttal/MS\nrec'd\nrec/M\nrecalcitrance/M\nrecalcitrant\nrecant/SDG\nrecantation/SM\nrecap/MS\nrecapitalization\nrecce/S\nrecd\nreceipt/SMDG\nreceivables/M\nreceive/DRSZGB\nreceiver/M\nreceivership/M\nrecent/RYTP\nrecentness/M\nreceptacle/SM\nreception/MS\nreceptionist/SM\nreceptive/PY\nreceptiveness/M\nreceptivity/M\nreceptor/SM\nrecess/MDSGV\nrecessional/SM\nrecessionary\nrecessive/SM\nrecherche\nrecidivism/M\nrecidivist/SM\nrecipe/SM\nrecipient/SM\nreciprocal/SMY\nreciprocate/GNDS\nreciprocation/M\nreciprocity/M\nrecital/SM\nrecitalist/MS\nrecitative/MS\nreciter/SM\nreckless/YP\nrecklessness/M\nreckon/SJDG\nreckoning/M\nreclamation/M\nrecline/DRSZG\nrecliner/M\nrecluse/SMV\nrecognizable/U\nrecognizably\nrecognize/DRSGB\nrecognized/U\nrecombination\nrecompense/DSMG\nrecompilation\nrecompile/GD\nrecon/S\nreconcile/GDSB\nreconciliation/S\nrecondite\nreconfiguration\nreconfigure/D\nreconnaissance/MS\nreconnoiter/DGS\nreconstruct/V\nreconstructed/U\nrecorded/U\nrecorder/MS\nrecording/MS\nrecoup/DG\nrecourse/M\nrecoverable/U\nrecovery/SM\nrecreant/MS\nrecreational\nrecriminate/DSGNX\nrecrimination/M\nrecriminatory\nrecrudesce/GDS\nrecrudescence/M\nrecrudescent\nrecruit/LSMDRZG\nrecruiter/M\nrecruitment/M\nrectal/Y\nrectangle/MS\nrectangular\nrectifiable\nrectification/M\nrectifier/M\nrectify/XNDRSZG\nrectilinear\nrectitude/M\nrecto/MS\nrector/SM\nrectory/SM\nrectum/SM\nrecumbent\nrecuperate/GNVDS\nrecuperation/M\nrecur/S\nrecurred\nrecurrence/SM\nrecurring\nrecursion/S\nrecuse\nrecyclable/SM\nrecycling/M\nred/PSM\nredact/SDG\nredaction/M\nredactor/SM\nredbird/SM\nredbreast/MS\nredbrick\nredcap/SM\nredcoat/SM\nredcurrant/S\nredden/SDG\nredder\nreddest\nreddish\nredeem/RZB\nredeemer/M\nredemption/M\nredemptive\nredhead/SMD\nredirection\nredistrict/GD\nredivide/GDS\nredlining/M\nredneck/SM\nredness/M\nredo/G\nredolence/M\nredolent\nredoubt/SBM\nredoubtably\nredound/SDG\nredraw/SG\nredskin/SM\nreduce/DRSZG\nreducer/M\nreducible\nreductase\nreduction/SM\nreductionist\nreductive\nredundancy/SM\nredundant/Y\nredwood/SM\nredye/DS\nreediness/M\nreedy/RTP\nreef/ZGMDRS\nreefer/M\nreek/GMDS\nreel's\nreel/UGDS\nreeve/G\nreexport/SDG\nref/SZM\nrefashion/DGS\nrefection/M\nrefectory/SM\nrefer/B\nreferee/DSM\nrefereeing\nreference/MGDS\nreferendum/MS\nreferent/SM\nreferential\nreferral/SM\nreferred\nreferrer/SM\nreferring\nreffed\nreffing\nrefill/BM\nrefined/U\nrefinement/SM\nrefiner/SM\nrefinery/S\nrefitting\nreflate/XDSGN\nreflationary\nreflect/GVSD\nreflection/MS\nreflective/Y\nreflector/MS\nreflexive/SMY\nreflexology\nreforge/DSG\nreform/MZ\nreformat/V\nreformatory/SM\nreformatting\nreformed/U\nreformist/S\nrefortify/GDS\nrefract/SGVD\nrefraction/M\nrefractory/SM\nrefrain/SGMD\nrefresh/ZGLDRS\nrefresher/M\nrefreshing/Y\nrefreshment/SM\nrefreshments/M\nrefrigerant/SM\nrefrigerate/DSGN\nrefrigeration/M\nrefrigerator/MS\nrefuge/SM\nrefugee/SM\nrefulgence/M\nrefulgent\nrefund/B\nrefurbishment/MS\nrefusal/MS\nrefutation/MS\nrefute/BDRSZG\nrefuter/M\nreg\nregal/DYG\nregalement/M\nregalia/M\nregard/ESMDG\nregardless\nregards/M\nregather/DGS\nregatta/SM\nregency/SM\nregeneracy/M\nregenerate/V\nregex/M\nregexp/S\nreggae/M\nregicide/MS\nregime/SM\nregimen/SM\nregiment/MDGS\nregimental\nregimentation/M\nregion/SM\nregional/Y\nregionalism/MS\nregister/GMDS\nregistered/U\nregistrant/MS\nregistrar/MS\nregistration/SM\nregistry/SM\nregnant\nregress/MDSGV\nregression/MS\nregret/SM\nregretful/Y\nregrettable\nregrettably\nregretted\nregretting\nregrind/GS\nreground\nregroup/DGS\nregular/MYS\nregularity/SM\nregularization/M\nregularize/DSG\nregulate/CDSGNV\nregulated/U\nregulation/CM\nregulations\nregulator/MS\nregulatory\nregurgitate/DSGN\nregurgitation/M\nrehab/MS\nrehabbed\nrehabbing\nrehabilitate/GNVDS\nrehabilitation/M\nrehang/SDG\nrehears/GD\nrehearsal/MS\nrehearsed/U\nrehi\nrehung\nreign/MDSG\nreimburse/BDSGL\nreimbursement/MS\nrein/GD\nreindeer/M\nreinforce/LGDS\nreinforcement/SM\nreinitialize\nreinstall/DG\nreinstatement/M\nreinsurance\nreiterate/V\nreject/GSMD\nrejection/SM\nrejoice/JGDS\nrejoicing/M\nrejoinder/SM\nrejuvenate/DSGN\nrejuvenation/M\nrel\nrelate/DRSXZGNV\nrelatedness/M\nrelater/M\nrelation/M\nrelational\nrelationship/MS\nrelative/MYS\nrelativism/M\nrelativist/S\nrelativistic\nrelativity/M\nrelax/DRSZG\nrelaxant/MS\nrelaxation/SM\nrelaxer/M\nrelay/D\nrelease/B\nreleased/U\nrelegate/GNDS\nrelent/SGD\nrelentless/PY\nrelentlessness/M\nrelevance/M\nrelevancy/M\nrelevant/Y\nreliability/UM\nreliable/U\nreliably/U\nreliance/M\nreliant\nrelic/MS\nrelief/SM\nrelieve/ZGDRS\nreliever/M\nreligion/SM\nreligiosity\nreligious/MYP\nreligiousness/M\nreline/DSG\nrelinquish/LDSG\nrelinquishment/M\nreliquary/SM\nrelish/GMDS\nrelist/SGD\nrelocate/B\nreluctance/M\nreluctant/Y\nrely/GDS\nrem/M\nremain/SGD\nremainder/GMDS\nremand/SGD\nremapping\nremark/B\nremarkableness/M\nremarkably\nremarked/U\nremediable\nremedy/GDSM\nremember/DG\nremembered/U\nremembrance/MS\nreminder/M\nreminisce/GDS\nreminiscence/MS\nreminiscent/Y\nremiss/PY\nremissness/M\nremit/S\nremittance/SM\nremitted\nremitting/U\nremix/DSG\nremnant/MS\nremodel/GDS\nremold/SGD\nremonstrant/SM\nremonstrate/DSG\nremorse/M\nremorseful/Y\nremorseless/PY\nremorselessness/M\nremote/RSMYTP\nremoteness/M\nremoval/SM\nremunerate/GNVXDS\nremuneration/M\nrenaissance/MS\nrenal\nrenascence/S\nrend/GS\nrender/SGMDJ\nrendering/M\nrendezvous/GMDS\nrendition/MS\nrenegade/DSMG\nrenege/DRSZG\nreneger/M\nrenew/DSBG\nrenewal/MS\nrennet/M\nrennin/M\nrenounce/LDSG\nrenouncement/M\nrenovate/DSXGN\nrenovation/M\nrenovator/MS\nrenown/MD\nrent/ZGMDRS\nrental/SM\nrenter/M\nrenunciation/SM\nreopen/SDG\nreorg/DSG\nrep/SM\nrepaint/GDS\nrepair/BZR\nrepairer/M\nrepairman/M\nrepairmen\nreparable\nreparation/MS\nreparations/M\nrepartee/M\nrepatriate/XDSMGN\nrepatriation/M\nrepeat/SMDRZGB\nrepeatable/U\nrepeatably\nrepeated/Y\nrepeater/M\nrepeating/M\nrepel/S\nrepelled\nrepellent/SM\nrepelling\nrepent/SDG\nrepentance/M\nrepentant/Y\nrepercussion/S\nrepertoire/MS\nrepertory/SM\nrepetition/MS\nrepetitious/YP\nrepetitiousness/M\nrepetitive/YP\nrepetitiveness/M\nrephotograph/DG\nreplaceable\nreplant/GSD\nreplenish/LGDS\nreplenishment/M\nreplete/PDSGN\nrepleteness/M\nrepletion/M\nreplica/SM\nreplicate/DSGNX\nreplication/M\nreplicator/S\nreportage/M\nreported/Y\nreportorial\nreposeful\nrepository/SM\nreprehend/DGS\nreprehensibility/M\nreprehensible\nreprehensibly\nreprehension/M\nrepresent/GDS\nrepresentational\nrepresentative/MS\nrepresented/U\nrepression/MS\nrepressive/PY\nreprieve/DSMG\nreprimand/GSMD\nreprisal/SM\nreprise/SMG\nreproach/GMDSB\nreproachful/Y\nreprobate/MS\nreproductive\nreprogramming\nreproving/Y\nreptile/SM\nreptilian/MS\nrepublic/S\nrepublicanism/M\nrepudiate/XGNDS\nrepudiation/M\nrepudiator/MS\nrepugnance/M\nrepugnant\nrepulsion/M\nrepulsive/YP\nrepulsiveness/M\nrepurchase/GDS\nreputability/M\nreputably/E\nreputation/MS\nrepute/DSMGB\nreputed/Y\nrequest/GDR\nrequiem/SM\nrequire/LDG\nrequirement/MS\nrequisite/XMNS\nrequisition/GMD\nrequital/M\nrequite/DRSZG\nrequited/U\nrequiter/M\nreread/SG\nrerecord/GDS\nrerunning\nresat\nrescind/SDG\nrescission/M\nrescue/DRSMZG\nrescuer/M\nreseal/B\nresell/SG\nresemble/DSG\nresend\nresent/LSDG\nresentful/YP\nresentfulness/M\nresentment/MS\nreserpine/M\nreservation/MS\nreserved/UY\nreservedness/M\nreservist/SM\nreservoir/SM\nresetting\nreshipping\nresidence/SM\nresidency/SM\nresident/MS\nresidential\nresidua\nresidual/MS\nresidue/SM\nresiduum/M\nresignation/SM\nresigned/Y\nresilience/M\nresiliency/M\nresilient/Y\nresinous\nresist/SMDRZG\nresistance/SM\nresistant/U\nresistible\nresistless\nresistor/MS\nresit/S\nresitting\nresold\nresole/DSG\nresolute/PY\nresoluteness/M\nresolve/RBM\nresolved/U\nresonance/SM\nresonant/Y\nresonate/GDS\nresonator/SM\nresorption/M\nresound/SGD\nresounding/Y\nresourceful/YP\nresourcefulness/M\nresp\nrespect/ESGVMD\nrespectability/M\nrespectable\nrespectably\nrespectful/EY\nrespectfulness/M\nrespective/Y\nrespell/SGD\nrespiration/M\nrespirator/SM\nrespiratory\nrespire/DG\nresplendence/M\nresplendent/Y\nrespond/SGD\nrespondent/SM\nresponse/MS\nresponsibility/SM\nresponsible\nresponsibly\nresponsive/UYP\nresponsiveness/UM\nrest/GVMDS\nrestate/GDS\nrestaurant/SM\nrestaurateur/MS\nrestful/YP\nrestfuller\nrestfullest\nrestfulness/M\nrestitution/M\nrestive/YP\nrestiveness/M\nrestless/PY\nrestlessness/M\nrestoration/SM\nrestorative/SM\nrestorer/SM\nrestrained/U\nrestraint/MS\nrestrict/SDGV\nrestricted/U\nrestriction/MS\nrestrictive/YP\nrestrictiveness/M\nrestring/SG\nrestroom/SM\nrestructuring/SM\nresult/GSMD\nresultant/SM\nresume/DSMG\nresumption/MS\nresupply/DSG\nresurgence/MS\nresurgent\nresurrect/GSD\nresurrection/MS\nresuscitate/GNDS\nresuscitation/M\nresuscitator/SM\nretailer/MS\nretain/SDRZG\nretainer/M\nretake/G\nretaliate/DSGNVX\nretaliation/M\nretaliatory\nretard/SMDRZG\nretardant/SM\nretardation/M\nretarder/M\nretch/DSG\nreteach/GS\nretention/M\nretentive/YP\nretentiveness/M\nrethink/SGM\nrethought\nreticence/M\nreticent/Y\nreticulated\nreticulation/MS\nretina/SM\nretinal\nretinue/SM\nretiree/SM\nretirement/MS\nretort/GMD\nretrace/GDS\nretract/DBG\nretractile\nretraction/S\nretrain/DGS\nretread/D\nretrenchment/MS\nretribution/MS\nretributive\nretrieval/SM\nretrieve/DRSMZGB\nretriever/M\nretro/MS\nretroactive/Y\nretrofire/GDS\nretrofit/SM\nretrofitted\nretrofitting\nretrograde/DSG\nretrogress/GVDS\nretrogression/M\nretrorocket/MS\nretrospect/MDSGV\nretrospection/M\nretrospective/MYS\nretrovirus/MS\nretsina/M\nreturnable/SM\nreturnee/SM\nrev/ZVM\nrevamping/M\nreveal/GJSD\nrevealed/U\nrevealing/Y\nreveille/M\nrevel/JMDRSZG\nrevelation/SM\nreveler/M\nrevelry/SM\nrevenge/MGDS\nrevenuer/SM\nreverb\nreverberate/DSGNX\nreverberation/M\nrevere/DSG\nreverence/DSMG\nreverend/SM\nreverent/Y\nreverential/Y\nreverie/MS\nrevers/M\nreversal/SM\nreverse/Y\nreversibility\nreversible\nreversibly\nrevert/GSD\nrevertible\nrevetment/SM\nrevile/DRSLZG\nrevilement/M\nreviler/M\nreviser/MS\nrevision/SM\nrevisionism/M\nrevisionist/SM\nrevival/MS\nrevivalism/M\nrevivalist/SM\nrevive/DSG\nrevivification/M\nrevocable\nrevoke/DSG\nrevolt/GD\nrevolting/Y\nrevolution/SM\nrevolutionary/SM\nrevolutionist/SM\nrevolutionize/DSG\nrevolve/BZGDRS\nrevolver/M\nrevue/MS\nrevulsion/M\nrevved\nrevving\nrewarded/U\nrewarding/U\nrewarm/GSD\nrewash/GDS\nreweave/GS\nrewedding\nrewind/MB\nrewound\nrewrite/MGS\nrhapsodic\nrhapsodical\nrhapsodize/GDS\nrhapsody/SM\nrhea/MS\nrhenium/M\nrheostat/SM\nrhesus/MS\nrhetoric/M\nrhetorical/Y\nrhetorician/SM\nrheum/M\nrheumatic/MS\nrheumatically\nrheumatism/M\nrheumatoid\nrheumy\nrhinestone/SM\nrhinitis/M\nrhino/MS\nrhinoceros/MS\nrhinoplasty\nrhinovirus/MS\nrhizome/MS\nrho/SM\nrhodium/M\nrhododendron/SM\nrhomboid/SM\nrhomboidal\nrhombus/MS\nrhubarb/MS\nrhyme/MZGDRS\nrhymer/M\nrhymester/MS\nrhythm/SM\nrhythmic\nrhythmical/Y\nrial/MS\nrib/SM\nribald\nribaldry/M\nribbed\nribber/SM\nribbing\nribbon/SM\nriboflavin/M\nrice/MZGDRS\nricer/M\nrich/TMRSYP\nrichness/M\nrick/GMDS\nrickets/M\nrickety/RT\nrickrack/M\nrickshaw/MS\nricochet/GMDS\nricotta/M\nrid/S\nriddance/M\nridden\nridding\nriddle/DSMG\nride/MZGRS\nrider/M\nriderless\nridership/M\nridge/MGDS\nridgepole/SM\nridgy\nridicule/MGDS\nridiculous/YP\nridiculousness/M\nriding/M\nrife/TR\nriff/GMDS\nriffle/DSMG\nriffraff/M\nrifle/MZGDRS\nrifleman/M\nriflemen\nrifler/M\nrifling/M\nrift/GMDS\nrig/SM\nrigatoni/M\nrigged\nrigger/SM\nrigging/M\nright/MDRYSPTG\nrighteous/UP\nrighteously\nrighteousness/UM\nrightful/PY\nrightfulness/M\nrightism/M\nrightist/SM\nrightmost\nrightness/M\nrighto\nrightsize/DSG\nrightward/S\nrigid/YP\nrigidity/M\nrigidness/M\nrigmarole/MS\nrigor/MS\nrigorous/YP\nrigorousness/M\nrile/GDS\nrill/MS\nrim/SGMD\nrime/MS\nrimless\nrimmed\nrimming\nrind/MS\nring/ZGMDRJ\nringer/M\nringgit/MS\nringleader/MS\nringlet/MS\nringlike\nringmaster/MS\nringside/M\nringtone/SM\nringworm/M\nrink/MS\nrinse/MGDS\nriot/ZGMDRS\nrioter/M\nrioting/M\nriotous/PY\nrip/SXTMNR\nriparian\nripcord/MS\nripe/YP\nripen/DG\nripened/U\nripeness/M\nripoff/SM\nriposte/MGDS\nripped\nripper/SM\nripping\nripple/DSMG\nripply\nripsaw/SM\nriptide/MS\nrise/JMZGRS\nrisen\nriser/M\nrisibility/M\nrisible\nrising/M\nrisk/GMDS\nriskily\nriskiness/M\nrisky/RPT\nrisotto/MS\nrisque\nrissole/S\nrite/MS\nritual/SMY\nritualism/M\nritualistic\nritualistically\nritualized\nritzy/RT\nriv/ZNR\nrival/MDSG\nrivaled/U\nrivalry/SM\nrive/CGDS\nriver/M\nriverbank/SM\nriverbed/MS\nriverboat/SM\nriverfront\nriverside/MS\nrivet/MDRSZG\nriveter/M\nriviera/S\nrivulet/MS\nriyal/MS\nrm\nroach/GMDS\nroad/IMS\nroadbed/SM\nroadblock/MDSG\nroadhouse/SM\nroadie/MS\nroadkill/M\nroadrunner/SM\nroadshow/SM\nroadside/SM\nroadster/SM\nroadway/SM\nroadwork/SM\nroadworthy\nroam/ZGDRS\nroamer/M\nroaming/M\nroan/MS\nroar/ZGMDRS\nroarer/M\nroaring/M\nroast/ZGMDRSJ\nroaster/M\nroasting/M\nrob/S\nrobbed\nrobber/MS\nrobbery/SM\nrobbing\nrobe's\nrobe/EGDS\nrobin/MS\nrobocall/SGD\nrobot/MS\nrobotic/S\nrobotics/M\nrobotize/GDS\nrobust/RYPT\nrobustness/M\nrock/ZGMDRS\nrockabilly/M\nrockbound\nrocker/M\nrockery/S\nrocket/MDSG\nrocketry/M\nrockfall/SM\nrockiness/M\nrocky/TRP\nrococo/M\nrod/SM\nrode\nrodent/MS\nrodeo/MS\nroe/SM\nroebuck/SM\nroentgen/MS\nroger/GDS\nrogue's\nrogue/KS\nroguery/M\nroguish/YP\nroguishness/M\nroil/GDS\nroister/ZGDRS\nroisterer/M\nrole/MS\nroll/MDRZGJS\nrollback/SM\nroller/M\nrollerblading\nrollerskating/M\nrollick/SDG\nrollicking/M\nrollmop/S\nrollover/SM\nromaine/MS\nroman/M\nromance/MZGDRS\nromancer/M\nromantic/MS\nromantically\nromanticism/M\nromanticist/SM\nromanticize/DSG\nromeo/MS\nromp/MDRZGS\nromper/M\nrondo/SM\nrood/MS\nroof/MDRZGS\nroofer/M\nroofing/M\nroofless\nrooftop/SM\nrook/MDGS\nrookery/SM\nrookie/SM\nroom/MDRZGS\nroomer/M\nroomette/SM\nroomful/SM\nroominess/M\nroommate/SM\nroomy/RTP\nroost/SMDRZG\nrooster/M\nroot/MDRZGS\nrooter/M\nrootkit/SM\nrootless/P\nrootlet/SM\nrope/MZGDRS\nroper/M\nropy/RT\nrosary/SM\nrose/MS\nroseate\nrosebud/SM\nrosebush/MS\nrosemary/M\nrosette/SM\nrosewater/M\nrosewood/MS\nrosily\nrosin/SMDG\nrosiness/M\nroster/SM\nrostrum/MS\nrosy/RTP\nrot/SM\nrota/S\nrotary/SM\nrotate/DSGNX\nrotation/M\nrotational\nrotatory\nrote/M\nrotgut/M\nrotisserie/SM\nrotogravure/MS\nrotor/SM\nrototiller/MS\nrotted\nrotten/TPRY\nrottenness/M\nrotter/S\nrotting\nrottweiler/S\nrotund/P\nrotunda/MS\nrotundity/M\nrotundness/M\nroue/MS\nrouge/DSMG\nrough/MDNRYXTGP\nroughage/M\nroughcast\nroughen/GD\nroughhouse/MGDS\nroughneck/GMDS\nroughness/M\nroughs\nroughshod\nroulette/M\nround/PSMDRYZTG\nroundabout/SM\nroundel/S\nroundelay/MS\nroundhouse/SM\nroundish\nroundness/M\nroundup/MS\nroundworm/SM\nrouse/DSG\nroust/SDG\nroustabout/SM\nrout/MRZS\nroute's\nroute/ADSG\nrouteing\nrouter/M\nroutine/MYS\nroutinize/GDS\nroux\nrove/ZGDRS\nrover/M\nrow/SZGMDR\nrowan/S\nrowboat/MS\nrowdily\nrowdiness/M\nrowdy/PRSMT\nrowdyism/M\nrowel/SMDG\nrower/M\nrowing/M\nrowlock/S\nroyal/SMY\nroyalist/SM\nroyalties/M\nroyalty/SM\nrpm\nrps\nrt\nrte\nrub/SM\nrubato/SM\nrubbed\nrubber/SM\nrubberize/GDS\nrubberneck/MDRSZG\nrubbernecker/M\nrubbery\nrubbing/S\nrubbish/MDSG\nrubbishy\nrubble/M\nrubdown/SM\nrube/MS\nrubella/M\nrubicund\nrubidium/M\nruble/SM\nrubric/SM\nruby/RSMT\nruched\nruck/DGS\nrucksack/MS\nruckus/MS\nructions\nrudder/SM\nrudderless\nruddiness/M\nruddy/RTP\nrude/YTRP\nrudeness/M\nrudiment/SM\nrudimentary\nrue/DSMG\nrueful/PY\nruefulness/M\nruff/MDYGS\nruffian/MYS\nruffle/DSMG\nruffled/U\nrug/SM\nrugby/M\nrugged/PTRY\nruggedness/M\nrugger\nrugrat/SM\nruin/MDGS\nruination/M\nruinous/Y\nrule/MZGJDRS\nruler/M\nruling/M\nrum/SM\nrumba/SMDG\nrumble/DSJMG\nrumbling/M\nrumbustious\nruminant/MS\nruminate/XGNVDS\nrumination/M\nruminative/Y\nrummage/DSMG\nrummer\nrummest\nrummy/M\nrumor/SMDG\nrumormonger/SM\nrump/MYS\nrumple/DSMG\nrumpus/MS\nrun/ASM\nrunabout/MS\nrunaround/SM\nrunaway/MS\nrundown/SM\nrune/MS\nrung/MS\nrunic\nrunlet/SM\nrunnel/SM\nrunner/SM\nrunning/M\nrunny/RT\nrunoff/SM\nrunt/MS\nrunty/RT\nrunway/SM\nrupee/SM\nrupiah/M\nrupiahs\nrupture/MGDS\nrural\nruse/MS\nrush/MDRSZG\nrusher/M\nrushy\nrusk/MS\nrusset/SM\nrust/MDGS\nrustic/SM\nrustically\nrusticate/GDS\nrustication/M\nrusticity/M\nrustiness/M\nrustle/DRSJMZG\nrustler/M\nrustproof/SDG\nrusty/RPNT\nrut/SM\nrutabaga/SM\nruthenium/M\nrutherfordium/M\nruthless/YP\nruthlessness/M\nrutted\nrutting\nrutty/RT\nrye/M\ns/NYXB\nsabbatical/SM\nsaber/MS\nsable/MS\nsabot/MS\nsabotage/DSMG\nsaboteur/SM\nsabra/MS\nsac/SM\nsaccharin/M\nsaccharine\nsacerdotal\nsachem/SM\nsachet/SM\nsack/GMDJS\nsackcloth/M\nsackful/MS\nsacking/M\nsacra\nsacrament/MS\nsacramental\nsacred/YP\nsacredness/M\nsacrifice/DSMG\nsacrificial/Y\nsacrilege/MS\nsacrilegious/Y\nsacristan/MS\nsacristy/SM\nsacroiliac/MS\nsacrosanct/P\nsacrosanctness/M\nsacrum/M\nsad/PY\nsadden/SDG\nsadder\nsaddest\nsaddle's\nsaddle/UDSG\nsaddlebag/MS\nsaddler/S\nsaddlery\nsades\nsadhu/S\nsadism/M\nsadist/SM\nsadistic\nsadistically\nsadness/M\nsadomasochism/M\nsadomasochist/MS\nsadomasochistic\nsafari/SGMD\nsafe/MYTPRS\nsafeguard/SMDG\nsafekeeping/M\nsafeness/M\nsafety/SM\nsafflower/MS\nsaffron/MS\nsag/SM\nsaga/MS\nsagacious/Y\nsagacity/M\nsage/MYTRS\nsagebrush/M\nsagged\nsagging\nsaggy/RT\nsago/M\nsaguaro/MS\nsahib/MS\nsaid/U\nsail/GMDSJ\nsailboard/MRZGS\nsailboarder/M\nsailboarding/M\nsailboat/MS\nsailcloth/M\nsailfish/MS\nsailing/M\nsailor/SM\nsailplane/MS\nsaint/MDYS\nsainthood/M\nsaintlike\nsaintliness/M\nsaintly/PRT\nsaith\nsake/M\nsalaam/SMDG\nsalable/U\nsalacious/PY\nsalaciousness/M\nsalacity/M\nsalad/MS\nsalamander/SM\nsalami/SM\nsalary/DSM\nsale/ABMS\nsaleroom/S\nsalesclerk/SM\nsalesgirl/SM\nsaleslady/SM\nsalesman/M\nsalesmanship/M\nsalesmen\nsalespeople/M\nsalesperson/MS\nsalesroom/S\nsaleswoman/M\nsaleswomen\nsalience/M\nsalient/SMY\nsaline/SM\nsalinity/M\nsaliva/M\nsalivary\nsalivate/GNDS\nsalivation/M\nsallow/RTP\nsallowness/M\nsally/DSMG\nsalmon/SM\nsalmonella/M\nsalmonellae\nsalon/MS\nsaloon/SM\nsalsa/MS\nsalt's\nsalt/CTGDS\nsaltbox/MS\nsaltcellar/SM\nsalted/U\nsalter\nsaltine/SM\nsaltiness/M\nsaltpeter/M\nsaltshaker/SM\nsaltwater/M\nsalty/RTP\nsalubrious/I\nsalutary\nsalutation/MS\nsalutatorian/MS\nsalutatory\nsalute/DSMG\nsalvage/DSMG\nsalvageable\nsalvation/M\nsalve/MZGDRS\nsalver/M\nsalvo/MS\nsamarium/M\nsamba/MDSG\nsame/SP\nsameness/M\nsamey\nsamizdat/S\nsamosa/S\nsamovar/SM\nsampan/SM\nsample/DRSMZGJ\nsampler/M\nsamurai/SM\nsanatorium/SM\nsanctification/M\nsanctify/GDSN\nsanctimonious/YP\nsanctimoniousness/M\nsanctimony/M\nsanction/GSMD\nsanctioned/U\nsanctity/M\nsanctuary/SM\nsanctum/SM\nsand/ZGMDRS\nsandal/SM\nsandalwood/M\nsandbag/SM\nsandbagged\nsandbagger/SM\nsandbagging\nsandbank/MS\nsandbar/SM\nsandblast/ZGMDRS\nsandblaster/M\nsandbox/MS\nsandcastle/MS\nsander/M\nsandhog/SM\nsandiness/M\nsandlot/SM\nsandlotter/MS\nsandman/M\nsandmen\nsandpaper/GMDS\nsandpiper/MS\nsandpit/S\nsandstone/M\nsandstorm/SM\nsandwich/MDSG\nsandy/RTP\nsane/IYTR\nsaneness/M\nsang/S\nsangfroid/M\nsangria/M\nsanguinary\nsanguine/Y\nsanitarian/SM\nsanitarium/SM\nsanitary/IU\nsanitation/M\nsanitize/GDS\nsanity/IM\nsank\nsans\nsanserif\nsap/SM\nsapience/M\nsapiens\nsapient\nsapless\nsapling/MS\nsapped\nsapper/S\nsapphire/SM\nsappiness/M\nsapping\nsappy/PRT\nsaprophyte/SM\nsaprophytic\nsapsucker/SM\nsapwood/M\nsaran/M\nsarcasm/MS\nsarcastic\nsarcastically\nsarcoma/MS\nsarcophagi\nsarcophagus/M\nsardine/MS\nsardonic\nsardonically\nsarge/MS\nsari/MS\nsarky\nsarnie/S\nsarong/SM\nsarsaparilla/MS\nsartorial/Y\nsash/MS\nsashay/SGMD\nsass/GMDS\nsassafras/MS\nsassy/RT\nsat\nsatanic\nsatanical/Y\nsatanism/M\nsatanist/MS\nsatay\nsatchel/MS\nsate/GDS\nsateen/M\nsatellite/DSMG\nsatiable/I\nsatiate/GNDS\nsatiation/M\nsatiety/M\nsatin/M\nsatinwood/SM\nsatiny\nsatire/SM\nsatiric\nsatirical/Y\nsatirist/SM\nsatirize/DSG\nsatisfaction/EM\nsatisfactions\nsatisfactorily/U\nsatisfactory/U\nsatisfied/U\nsatisfy/EDSG\nsatisfying/U\nsatisfyingly\nsatori/M\nsatrap/SM\nsatsuma/S\nsaturate/DSGN\nsaturated/U\nsaturation/M\nsaturnine\nsatyr/MS\nsatyriasis/M\nsatyric\nsauce/MZGDRS\nsaucepan/SM\nsaucer/M\nsaucily\nsauciness/M\nsaucy/RPT\nsauerkraut/M\nsauna/MDSG\nsaunter/MDGS\nsaurian\nsauropod/SM\nsausage/MS\nsaute/MS\nsauteed\nsauteing\nsavage/DRSMYTGP\nsavageness/M\nsavagery/SM\nsavanna/MS\nsavant/SM\nsave/BJMZGDRS\nsaved/U\nsaver/M\nsaving/M\nsavings/M\nsavior/SM\nsavor/MDSG\nsavoriness/M\nsavory/PTRSM\nsavoy/MS\nsavvy/DRSMTG\nsaw/SGMD\nsawbones/M\nsawbuck/MS\nsawdust/M\nsawfly/SM\nsawhorse/SM\nsawmill/MS\nsawyer/SM\nsax/MS\nsaxifrage/SM\nsaxophone/MS\nsaxophonist/SM\nsay's\nsay/USG\nsaying/SM\nscab/MS\nscabbard/MS\nscabbed\nscabbiness/M\nscabbing\nscabby/PTR\nscabies/M\nscabrous\nscad/MS\nscaffold/SMG\nscaffolding/M\nscag/S\nscagged\nscalar/S\nscalawag/MS\nscald/MDSG\nscale's\nscale/CGDS\nscaleless\nscalene\nscaliness/M\nscallion/MS\nscallop/GSMD\nscalp/MDRSZG\nscalpel/SM\nscalper/M\nscaly/RTP\nscam/MS\nscammed\nscammer/S\nscamming\nscamp/MRSZ\nscamper/GMD\nscampi/M\nscan/MS\nscandal/SM\nscandalize/DSG\nscandalmonger/SM\nscandalous/Y\nscandium/M\nscanned\nscanner/SM\nscanning\nscansion/M\nscant/CDSTG\nscanter\nscantily\nscantiness/M\nscantly\nscantness/M\nscanty/RSPT\nscapegoat/SGMD\nscapegrace/MS\nscapula/M\nscapulae\nscapular/SM\nscar/GMDS\nscarab/SM\nscarce/RYTP\nscarceness/M\nscarcity/SM\nscare/MS\nscarecrow/MS\nscaremonger/SMG\nscarf/MDSG\nscarification/M\nscarify/NDSG\nscarily\nscariness/M\nscarlatina/M\nscarlet/M\nscarp/MDRSZG\nscarper/DG\nscarred\nscarring\nscarves\nscary/RTP\nscat/MS\nscathing/Y\nscatological\nscatology/M\nscatted\nscatter/GJSMD\nscatterbrain/SMD\nscattering/M\nscattershot\nscatting\nscatty\nscavenge/ZGDRS\nscavenger/M\nscenario/MS\nscenarist/MS\nscene/MS\nscenery/M\nscenic\nscenically\nscent/CMS\nscented/U\nscenting\nscentless\nscepter/MS\nsch\nschadenfreude\nschedule's\nschedule/ADSG\nscheduled/U\nscheduler/S\nschema\nschemata\nschematic/SM\nschematically\nschematize/GDS\nscheme/DRSMZG\nschemer/M\nscherzo/MS\nschilling/MS\nschism/SM\nschismatic/SM\nschist/M\nschizo/SM\nschizoid/MS\nschizophrenia/M\nschizophrenic/SM\nschlemiel/SM\nschlep/SM\nschlepped\nschlepping\nschlock/M\nschmaltz/M\nschmaltzy/TR\nschmo/M\nschmoes\nschmooze/DRSZG\nschmuck/MS\nschnapps/M\nschnauzer/SM\nschnitzel/SM\nschnook/MS\nschnoz/MS\nschnozzle/SM\nscholar/MYS\nscholarship/MS\nscholastic\nscholastically\nscholasticism\nschool/SGMD\nschoolbag/MS\nschoolbook/SM\nschoolboy/MS\nschoolchild/M\nschoolchildren/M\nschooldays\nschooled/U\nschoolfellow/SM\nschoolgirl/SM\nschoolhouse/SM\nschooling/M\nschoolkid/S\nschoolmarm/SM\nschoolmarmish\nschoolmaster/MS\nschoolmate/SM\nschoolmistress/MS\nschoolroom/SM\nschoolteacher/MS\nschoolwork/M\nschoolyard/SM\nschooner/SM\nschuss/GMDS\nschussboomer/MS\nschwa/MS\nsci\nsciatic\nsciatica/M\nscience/FMS\nscientific/U\nscientifically/U\nscientist/SM\nscimitar/SM\nscintilla/MS\nscintillate/DSGN\nscintillation/M\nscion/MS\nscissor/GDS\nscleroses\nsclerosis/M\nsclerotic\nscoff/MDRSZG\nscoffer/M\nscofflaw/MS\nscold/MDSGJ\nscolding/M\nscoliosis/M\nsconce/SM\nscone/MS\nscoop/MDSG\nscoopful/MS\nscoot/DRSZG\nscooter/M\nscope/MGDS\nscorbutic\nscorch/MDRSZG\nscorcher/M\nscore/MZGDRS\nscoreboard/SM\nscorecard/MS\nscorekeeper/MS\nscoreless\nscoreline/S\nscorer/M\nscorn/MDRSZG\nscorner/M\nscornful/Y\nscorpion/MS\nscotch/MDSG\nscotchs\nscoundrel/MS\nscour/DRSZG\nscourer/M\nscourge/DSMG\nscout/MDRSZG\nscouting/M\nscoutmaster/MS\nscow/MS\nscowl/MDSG\nscrabble/MZGDRS\nscrabbler/M\nscrag/MS\nscraggly/RT\nscraggy/TR\nscram/S\nscramble's\nscramble/UGDS\nscrambler/MS\nscrammed\nscramming\nscrap/MDRSZGJ\nscrapbook/SM\nscrape/SM\nscraper/M\nscrapheap/SM\nscrapie\nscrapped\nscrapper/MS\nscrapping\nscrappy/TR\nscrapyard/SM\nscratch/GMDS\nscratchcard/S\nscratched/U\nscratchily\nscratchiness/M\nscratchpad/S\nscratchy/PRT\nscrawl/SMDG\nscrawly\nscrawniness/M\nscrawny/PTR\nscream/SMDRZG\nscreamer/M\nscreaming/Y\nscree/MDS\nscreech/GMDS\nscreechy/TR\nscreed/S\nscreen/SJMDG\nscreening/M\nscreenplay/SM\nscreensaver\nscreenshot/S\nscreenwriter/SM\nscreenwriting/M\nscrew's\nscrew/UDSG\nscrewball/MS\nscrewdriver/MS\nscrewiness/M\nscrewworm/SM\nscrewy/PRT\nscribal\nscribble/MZGDRS\nscribbler/M\nscribe's\nscribe/CKIS\nscrim/MS\nscrimmage/MGDS\nscrimp/SDG\nscrimshaw/MDGS\nscrip/MS\nscript/FSMDG\nscripted/U\nscriptural\nscripture/MS\nscriptwriter/SM\nscrivener/SM\nscrod/M\nscrofula/M\nscrofulous\nscrog/S\nscroll/GSMD\nscrooge/MS\nscrota\nscrotal\nscrotum/M\nscrounge/DRSZG\nscrounger/M\nscroungy/TR\nscrub/MS\nscrubbed\nscrubber/SM\nscrubbing\nscrubby/RT\nscruff/SM\nscruffily\nscruffiness/M\nscruffy/RPT\nscrum/S\nscrumhalf\nscrumhalves\nscrummage/S\nscrummed\nscrumming\nscrump/SGD\nscrumptious/Y\nscrumpy\nscrunch/MDSG\nscrunchy/SM\nscruple/MGDS\nscrupulosity/M\nscrupulous/UPY\nscrupulousness/UM\nscrutineer/S\nscrutinize/GDS\nscrutiny/M\nscuba/MDSG\nscud/MS\nscudded\nscudding\nscuff/MDSG\nscuffle/MGDS\nscull/MDRSZG\nsculler/M\nscullery/SM\nscullion/SM\nsculpt/SGD\nsculptor/SM\nsculptress/MS\nsculptural\nsculpture/DSMG\nscum/MS\nscumbag/MS\nscummed\nscumming\nscummy/TR\nscupper/MDGS\nscurf/M\nscurfy\nscurrility/M\nscurrilous/PY\nscurrilousness/M\nscurry/GDSM\nscurvily\nscurvy/TRM\nscutcheon/SM\nscuttle/MGDS\nscuttlebutt/M\nscuzzy/TR\nscythe/DSMG\nsea/SM\nseabed/SM\nseabird/MS\nseaboard/SM\nseaborne\nseacoast/SM\nseafarer/SM\nseafaring/M\nseafloor/SM\nseafood/M\nseafront/SM\nseagoing\nseagull/MS\nseahorse/MS\nseal's\nseal/AUSDG\nsealant/MS\nsealer/SM\nsealskin/M\nseam/GMDNS\nseaman/M\nseamanship/M\nseamless/Y\nseamount/MS\nseamstress/MS\nseamy/RT\nseance/SM\nseaplane/SM\nseaport/MS\nsear/GMDS\nsearch/AZGMDRS\nsearcher/AM\nsearching/Y\nsearchlight/MS\nsearing/Y\nseascape/SM\nseashell/SM\nseashore/SM\nseasick/P\nseasickness/M\nseaside/MS\nseason/SGMDBJ\nseasonable/U\nseasonably/U\nseasonal/Y\nseasonality\nseasoned/U\nseasoning/M\nseat's\nseat/UGDS\nseating/M\nseatmate/SM\nseawall/MS\nseaward/MS\nseawater/M\nseaway/SM\nseaweed/MS\nseaworthiness/M\nseaworthy/P\nsebaceous\nseborrhea/M\nsebum\nsec'y\nsec/SM\nsecant/SM\nsecateurs\nsecede/DSG\nsecession/M\nsecessionist/MS\nseclude/GDS\nseclusion/M\nseclusive\nsecond/SLZGMDRY\nsecondarily\nsecondary/SM\nseconder/M\nsecondhand\nsecondment/S\nsecrecy/M\nsecret/SGVMDY\nsecretarial\nsecretariat/MS\nsecretary/SM\nsecretaryship/M\nsecrete/XNS\nsecretion/M\nsecretive/PY\nsecretiveness/M\nsecretory\nsect/IMS\nsectarian/MS\nsectarianism/M\nsectary/SM\nsection/AESM\nsectional/MS\nsectionalism/M\nsectioned\nsectioning\nsector/ESM\nsecular\nsecularism/M\nsecularist/SM\nsecularization/M\nsecularize/DSG\nsecure/DRSYTG\nsecured/U\nsecurity/ISM\nsecy\nsedan/MS\nsedate/DRSYTGNVP\nsedateness/M\nsedation/M\nsedative/SM\nsedentary\nsedge/M\nsedgy\nsediment/MS\nsedimentary\nsedimentation/M\nsedition/M\nseditious\nseduce/DRSZG\nseducer/M\nseduction/SM\nseductive/YP\nseductiveness/M\nseductress/MS\nsedulous/Y\nsee/RSMZ\nseed's\nseed/AGDS\nseedbed/MS\nseedcase/MS\nseeded/U\nseeder/SM\nseediness/M\nseedless\nseedling/MS\nseedpod/MS\nseedy/RPT\nseeing/S\nseek/ZGRS\nseeker/M\nseem/GDS\nseeming/Y\nseemliness/UM\nseemly/URTP\nseen/U\nseep/GDS\nseepage/M\nseer/M\nseersucker/M\nseesaw/SMDG\nseethe/DSG\nsegfault/S\nsegment/GSMD\nsegmentation/M\nsegmented/U\nsegregate/CDSGN\nsegregated/U\nsegregation/CM\nsegregationist/MS\nsegue/MGDS\nsegueing\nseigneur/SM\nseignior/SM\nseine/MZGDRS\nseiner/M\nseismic\nseismically\nseismograph/ZMR\nseismographer/M\nseismographic\nseismographs\nseismography/M\nseismologic\nseismological\nseismologist/MS\nseismology/M\nseize/GDS\nseizure/MS\nseldom\nselect/CSGVD\nselection/SM\nselective/Y\nselectivity/M\nselectman/M\nselectmen\nselectness/M\nselector/MS\nselenium/M\nselenographer/MS\nselenography/M\nself/M\nselfie/SM\nselfish/UYP\nselfishness/UM\nselfless/PY\nselflessness/M\nselfsame\nsell/ZGMRS\nseller/M\nselloff/MS\nsellotape/DSG\nsellout/MS\nseltzer/MS\nselvage/MS\nselves\nsemantic/S\nsemantically\nsemanticist/MS\nsemantics/M\nsemaphore/DSMG\nsemblance/ASM\nsemen/M\nsemester/SM\nsemi/MS\nsemiannual/Y\nsemiarid\nsemiautomatic/MS\nsemibreve/S\nsemicircle/SM\nsemicircular\nsemicolon/MS\nsemiconducting\nsemiconductor/MS\nsemiconscious\nsemidarkness/M\nsemidetached\nsemifinal/SM\nsemifinalist/MS\nsemigloss/S\nsemimonthly/SM\nseminal\nseminar/MS\nseminarian/SM\nseminary/SM\nsemiofficial\nsemiotic/S\nsemiotics/M\nsemipermeable\nsemiprecious\nsemiprivate\nsemipro/S\nsemiprofessional/SM\nsemiquaver/S\nsemiretired\nsemiskilled\nsemisolid\nsemisweet\nsemitone/SM\nsemitrailer/MS\nsemitransparent\nsemitropical\nsemivowel/SM\nsemiweekly/SM\nsemiyearly\nsemolina/M\nsempstress/MS\nsenate/SM\nsenator/MS\nsenatorial\nsend/ZGRS\nsender/M\nsendoff/MS\nsenescence/M\nsenescent\nsenile\nsenility/M\nsenior/SM\nseniority/M\nsenna/M\nsenor/MS\nsenora/SM\nsenorita/SM\nsensation/MS\nsensational/Y\nsensationalism/M\nsensationalist/MS\nsensationalize/GDS\nsense/MGDS\nsenseless/PY\nsenselessness/M\nsensibilities\nsensibility/IM\nsensible/P\nsensibleness/M\nsensibly/I\nsensitive/SMYP\nsensitiveness/M\nsensitivities\nsensitivity/IM\nsensitization/CM\nsensitize/CDSG\nsensor/SM\nsensory\nsensual/Y\nsensualist/SM\nsensuality/M\nsensuous/YP\nsensuousness/M\nsent/FAU\nsentence/MGDS\nsententious/Y\nsentience/IM\nsentient/I\nsentiment/SM\nsentimental/Y\nsentimentalism/M\nsentimentalist/MS\nsentimentality/M\nsentimentalization/M\nsentimentalize/GDS\nsentinel/MS\nsentry/SM\nsepal/MS\nseparability/IM\nseparable\nseparably/I\nseparate/XMYGNVDSP\nseparateness/M\nseparation/M\nseparatism/M\nseparatist/MS\nseparator/MS\nsepia/M\nsepsis/M\nsepta\nseptal\nseptet/SM\nseptic\nsepticemia/M\nsepticemic\nseptuagenarian/MS\nseptum/M\nsepulcher/GMDS\nsepulchral\nseq\nsequel/SM\nsequence/MZGDRS\nsequencing/M\nsequential/FY\nsequester/SDG\nsequestrate/XGNDS\nsequestration/M\nsequin/SMD\nsequinned\nsequitur\nsequoia/MS\nseraglio/MS\nserape/SM\nseraph/M\nseraphic\nseraphs\nsere/TR\nserenade/MGDS\nserendipitous\nserendipity/M\nserene/RPYT\nsereneness/M\nserenity/M\nserf/MS\nserfdom/M\nserge/M\nsergeant/MS\nserial/SMY\nserialization/SM\nserialize/GDS\nseries/M\nserif/MS\nserigraph/M\nserigraphs\nserine\nserious/PY\nseriousness/M\nsermon/SM\nsermonize/GDS\nserology/M\nserotonin\nserous\nserpent/MS\nserpentine/M\nserrate/XND\nserration/M\nserried\nserum/MS\nservant/MS\nserve's/AF\nserve/FACGDS\nserver/SM\nservery/S\nservice/EMS\nserviceability/M\nserviceable\nserviced\nserviceman/M\nservicemen\nservicewoman/M\nservicewomen\nservicing\nserviette/MS\nservile\nservility/M\nserving's\nservings\nservitor/MS\nservitude/M\nservo/MS\nservomechanism/SM\nservomotor/MS\nsesame/SM\nsesquicentennial/MS\nsession/MS\nset/AISM\nsetback/MS\nsetscrew/SM\nsetsquare/S\nsett/BJZGRS\nsettee/MS\nsetter/M\nsetting/M\nsettle's\nsettle/AUGDS\nsettlement/AM\nsettlements\nsettler/SM\nsetup/MS\nseven/MHS\nseventeen/SMH\nseventeenth/M\nseventeenths\nseventh/M\nsevenths\nseventieth/M\nseventieths\nseventy/SMH\nsever/ETGDS\nseveral/MY\nseverance/SM\nsevere/YPR\nsevereness/M\nseverity/M\nsew/ASGD\nsewage/M\nsewer/MS\nsewerage/M\nsewing/M\nsewn/A\nsex/GMDS\nsexagenarian/SM\nsexily\nsexiness/M\nsexism/M\nsexist/MS\nsexless\nsexologist/SM\nsexology/M\nsexpot/MS\nsextant/SM\nsextet/MS\nsexting\nsexton/MS\nsextuplet/SM\nsexual/Y\nsexuality/M\nsexy/PTR\nsf\nsh\nshabbily\nshabbiness/M\nshabby/PTR\nshack/MDSG\nshackle's\nshackle/UGDS\nshad/GMDSJ\nshade/MS\nshadily\nshadiness/M\nshading/M\nshadow/SGMD\nshadowbox/GDS\nshadowy/RT\nshady/RPT\nshaft/MDSG\nshag/MS\nshagged\nshagginess/M\nshagging\nshaggy/TPR\nshah/M\nshahs\nshake/MZGRS\nshakedown/SM\nshaken/U\nshakeout/MS\nshaker/M\nshakeup/MS\nshakily\nshakiness/M\nshaky/RPT\nshale/M\nshall\nshallot/MS\nshallow/TPMRYS\nshallowness/M\nshalom\nshalt\nsham/GMDS\nshaman/SM\nshamanic\nshamanism\nshamanistic\nshamble/MGDS\nshambles/M\nshambolic\nshame/MS\nshamefaced/Y\nshameful/PY\nshamefulness/M\nshameless/YP\nshamelessness/M\nshammed\nshamming\nshampoo/ZGMDRS\nshampooer/M\nshamrock/MS\nshan't\nshandy/S\nshanghai/DSG\nshank/MS\nshantung/M\nshanty/SM\nshantytown/SM\nshape's\nshape/AGDS\nshaped/U\nshapeless/YP\nshapelessness/M\nshapeliness/M\nshapely/PTR\nshard/MS\nshare/MZGDRS\nshareable\nsharecrop/S\nsharecropped\nsharecropper/MS\nsharecropping\nshareholder/SM\nshareholding/S\nsharer/M\nshareware/M\nsharia/M\nshariah\nshark/MDSG\nsharkskin/M\nsharp/MDNRYSPXZTG\nsharpen/ADGS\nsharpener/MS\nsharper/M\nsharpie/MS\nsharpish\nsharpness/M\nsharpshooter/SM\nsharpshooting/M\nshatter/GMDS\nshatterproof\nshave/MZGDRSJ\nshaven/U\nshaver/M\nshaving/M\nshawl/MS\nshay/MS\nshe'd\nshe'll\nshe/DSM\nsheaf/M\nshear/MDRSZG\nshearer/M\nsheath/JM\nsheathe/UGDS\nsheathing/M\nsheaths\nsheave/DSMG\nshebang/MS\nshebeen/S\nshed/MS\nshedding\nsheen/M\nsheeny/TR\nsheep/M\nsheepdog/MS\nsheepfold/SM\nsheepherder/MS\nsheepish/YP\nsheepishness/M\nsheepskin/MS\nsheer/MDRSPTG\nsheerness/M\nsheet/MSG\nsheeting/M\nsheetlike\nsheikdom/MS\nsheikh/M\nsheikhs\nsheila/S\nshekel/SM\nshelf/M\nshell/MDRSG\nshellac/MS\nshellacked\nshellacking/MS\nshellfire/M\nshellfish/MS\nshelter/GMDS\nshelve/GDS\nshelving/M\nshenanigan/SM\nshepherd/SMDG\nshepherdess/MS\nsherbet/SM\nsheriff/SM\nsherry/SM\nshew/GDS\nshewn\nshh\nshiatsu/M\nshibboleth/M\nshibboleths\nshield/MDGS\nshift/GMDS\nshiftily\nshiftiness/M\nshiftless/PY\nshiftlessness/M\nshifty/RPT\nshiitake/S\nshill/GMDSJ\nshillelagh/M\nshillelaghs\nshilling/M\nshim/MS\nshimmed\nshimmer/SMDG\nshimmery\nshimming\nshimmy/DSMG\nshin/ZGMDRS\nshinbone/SM\nshindig/SM\nshine/MS\nshiner/M\nshingle/DSMG\nshinguard/M\nshininess/M\nshinned\nshinning\nshinny/DSG\nshinsplints/M\nshiny/TRP\nship's\nship/ALS\nshipboard/MS\nshipbuilder/SM\nshipbuilding/M\nshipload/SM\nshipmate/SM\nshipment/AM\nshipments\nshipowner/MS\nshipped/A\nshipper/SM\nshipping/M\nshipshape\nshipwreck/GMDS\nshipwright/MS\nshipyard/SM\nshire/MS\nshirk/ZGDRS\nshirker/M\nshirr/GMDSJ\nshirring/M\nshirt/GMDS\nshirtfront/SM\nshirting/M\nshirtless\nshirtsleeve/SM\nshirttail/SM\nshirtwaist/MS\nshirty\nshit/SM!\nshitfaced/!\nshithead/S!\nshitload/!\nshitted/!\nshitting/!\nshitty/RT!\nshiv/ZMRS\nshiver/MDG\nshivery\nshoal/GMDS\nshoat/MS\nshock/ZGMDRS\nshocker/M\nshocking/Y\nshockproof\nshod/U\nshoddily\nshoddiness/M\nshoddy/PRMT\nshoe/MS\nshoehorn/GMDS\nshoeing\nshoelace/MS\nshoemaker/SM\nshoeshine/SM\nshoestring/SM\nshoetree/MS\nshogun/MS\nshogunate/M\nshone\nshoo/GDS\nshook\nshoot/ZGMRSJ\nshooter/M\nshooting/M\nshootout/MS\nshop/MS\nshopaholic/S\nshopfitter/S\nshopfitting\nshopfront/S\nshopkeeper/MS\nshoplift/DRZGS\nshoplifter/M\nshoplifting/M\nshoppe/MZGDRS\nshopper/M\nshopping/M\nshoptalk/M\nshopworn\nshore/MGDS\nshorebird/SM\nshoreline/MS\nshoring/M\nshort/XTGMDNRYSP\nshortage/MS\nshortbread/M\nshortcake/MS\nshortchange/DSG\nshortcoming/MS\nshortcrust\nshortcut/MS\nshorten/JGD\nshortening/M\nshortfall/MS\nshorthand/MD\nshorthorn/MS\nshortish\nshortlist/DGS\nshortness/M\nshortsighted/PY\nshortsightedness/M\nshortstop/MS\nshortwave/MS\nshorty/SM\nshot/MS\nshotgun/SM\nshotgunned\nshotgunning\nshould\nshould've\nshoulder/MDGS\nshouldn't\nshout/ZGMDRS\nshouter/M\nshove/MGDS\nshovel/MDSG\nshovelful/SM\nshow/JZGMDRS\nshowbiz/M\nshowboat/MDGS\nshowcase/MGDS\nshowdown/MS\nshower/MDG\nshowerproof\nshowery\nshowgirl/MS\nshowground/S\nshowily\nshowiness/M\nshowing/M\nshowjumping\nshowman/M\nshowmanship/M\nshowmen\nshown\nshowoff/SM\nshowpiece/SM\nshowplace/SM\nshowroom/MS\nshowstopper/MS\nshowstopping\nshowtime\nshowy/TRP\nshpt\nshrank\nshrapnel/M\nshred/MS\nshredded\nshredder/MS\nshredding\nshrew/MS\nshrewd/RYPT\nshrewdness/M\nshrewish\nshriek/MDSG\nshrift/M\nshrike/MS\nshrill/DRSPTG\nshrillness/M\nshrilly\nshrimp/MDRSZG\nshrine/MS\nshrink/MSBG\nshrinkage/M\nshrive/GDS\nshrivel/SGD\nshriven\nshroud/GMDS\nshrub/MS\nshrubbery/SM\nshrubby/RT\nshrug/MS\nshrugged\nshrugging\nshrunk/N\nshtick/MS\nshuck/GMDS\nshucks/S\nshudder/MDSG\nshuffle/AMGDS\nshuffleboard/SM\nshuffler/SM\nshun/S\nshunned\nshunning\nshunt/MSDG\nshush/DSG\nshut/S\nshutdown/SM\nshuteye/M\nshutoff/SM\nshutout/SM\nshutter/SMDG\nshutterbug/MS\nshutting\nshuttle/DSMG\nshuttlecock/GMDS\nshy/TGDRSMY\nshyer\nshyest\nshyness/M\nshyster/SM\nsibilant/SM\nsibling/SM\nsibyl/MS\nsibylline\nsic/S\nsicced\nsiccing\nsick/PXTGDNRYS\nsickbay/S\nsickbed/SM\nsicken/DG\nsickening/Y\nsickie/MS\nsickish\nsickle/MS\nsickly/RT\nsickness/MS\nsicko/MS\nsickout/SM\nsickroom/MS\nside's\nside/AGDS\nsidearm/SM\nsidebar/SM\nsideboard/SM\nsideburns/M\nsidecar/SM\nsidekick/SM\nsidelight/MS\nsideline/DSMG\nsidelong\nsideman/M\nsidemen\nsidepiece/MS\nsidereal\nsidesaddle/MS\nsideshow/MS\nsidesplitting\nsidestep/MS\nsidestepped\nsidestepping\nsidestroke/DSMG\nsideswipe/DSMG\nsidetrack/SMDG\nsidewalk/MS\nsidewall/MS\nsideways\nsidewinder/SM\nsiding/MS\nsidle/MGDS\nsiege/MS\nsienna/M\nsierra/MS\nsiesta/MS\nsieve/MGDS\nsift/ZGDRS\nsifted/U\nsifter/M\nsigh/GMD\nsighs\nsight/GMDYSJ\nsighting/M\nsightless\nsightly/UTR\nsightread\nsightseeing/M\nsightseer/MS\nsigma/MS\nsign's/C\nsign/AFCGDS\nsignage/M\nsignal/MDRYSZG\nsignaler/M\nsignalization/M\nsignalize/GDS\nsignalman/M\nsignalmen\nsignatory/SM\nsignature/MS\nsignboard/MS\nsigned/U\nsigner/CMS\nsignet/MS\nsignificance/IM\nsignificant/IY\nsignification/M\nsignify/XDSNG\nsigning's/C\nsignings\nsignor/FMS\nsignora/SM\nsignore\nsignori\nsignorina/MS\nsignorine\nsignpost/GSMD\nsilage/M\nsilence/DRSMZG\nsilencer/M\nsilent/MRYST\nsilhouette/DSMG\nsilica/M\nsilicate/MS\nsiliceous\nsilicon/SM\nsilicone/M\nsilicosis/M\nsilk/MNS\nsilkily\nsilkiness/M\nsilkscreen/SM\nsilkworm/MS\nsilky/TRP\nsill/MS\nsilliness/M\nsilly/TRSMP\nsilo/MS\nsilt/GMDS\nsilty/TR\nsilver/GMDS\nsilverfish/MS\nsilversmith/M\nsilversmiths\nsilverware/M\nsilvery\nsim/S\nsimian/MS\nsimilar/Y\nsimilarity/ESM\nsimile/MS\nsimilitude/EM\nsimmer/GMDS\nsimonize/DSG\nsimony/M\nsimpatico\nsimper/GMDS\nsimpering/Y\nsimple/TRP\nsimpleminded\nsimpleness/M\nsimpleton/SM\nsimplex\nsimplicity/M\nsimplification/M\nsimplify/DSXNG\nsimplistic\nsimplistically\nsimply\nsimulacra\nsimulacrum/S\nsimulate/EDSGN\nsimulation/EM\nsimulations\nsimulator/EMS\nsimulcast/GMDS\nsimultaneity/M\nsimultaneous/Y\nsin/ASM\nsince\nsincere/IYT\nsincerer\nsincerity/IM\nsine/MS\nsinecure/MS\nsinew/MS\nsinewy\nsinful/PY\nsinfulness/M\nsing/BZGMDRYS\nsingalong/S\nsinge/MS\nsingeing\nsinger/M\nsinging/M\nsingle/PMGDS\nsingleness/M\nsingles/M\nsinglet/S\nsingleton/SM\nsingletree/SM\nsingsong/SMDG\nsingular/SMY\nsingularity/SM\nsinister\nsink/BZGMRS\nsinkable/U\nsinker/M\nsinkhole/SM\nsinless\nsinned\nsinner/MS\nsinning\nsinology\nsinuosity/M\nsinuous/Y\nsinus/MS\nsinusitis/M\nsinusoidal\nsip/SM\nsiphon/GMDS\nsipped\nsipper/SM\nsipping\nsir/SXMN\nsire/CMGDS\nsiren/M\nsirloin/SM\nsirocco/SM\nsirrah\nsirree/M\nsis/MS\nsisal/M\nsissified\nsissy/RSMT\nsister/ASM\nsisterhood/MS\nsisterliness/M\nsisterly/P\nsit/S\nsitar/SM\nsitarist/MS\nsitcom/SM\nsite/MGDS\nsitemap/SM\nsitter/SM\nsitting/SM\nsituate/DSXGN\nsituation/M\nsituational\nsix/MSH\nsixfold\nsixpence/MS\nsixshooter/M\nsixteen/SMH\nsixteenth/M\nsixteenths\nsixth/M\nsixths\nsixtieth/M\nsixtieths\nsixty/SMH\nsizable\nsize's\nsize/AGDS\nsizer\nsizing/M\nsizzle/DRSMZG\nska/M\nskate/MZGDRS\nskateboard/MDRSZG\nskateboarder/M\nskateboarding/M\nskater/M\nskating/M\nskedaddle/MGDS\nskeet/ZMR\nskein/MS\nskeletal\nskeleton/SM\nskeptic/SM\nskeptical/Y\nskepticism/M\nsketch/MDRSZG\nsketchbook/S\nsketcher/M\nsketchily\nsketchiness/M\nsketchpad/S\nsketchy/RTP\nskew/MDRZGS\nskewbald/S\nskewer/MDG\nski/SZGMDR\nskibob/S\nskid/MS\nskidded\nskidding\nskidpan/S\nskier/M\nskiff/SM\nskiffle\nskiing/M\nskilfully\nskill's\nskill/CSD\nskilled/U\nskillet/SM\nskillful/UY\nskillfulness/M\nskim/MS\nskimmed\nskimmer/SM\nskimming\nskimp/SDG\nskimpily\nskimpiness/M\nskimpy/RTP\nskin/MS\nskincare/M\nskinflint/MS\nskinful\nskinhead/MS\nskinless\nskinned\nskinniness/M\nskinning\nskinny/RMTP\nskint\nskintight\nskip/MS\nskipped\nskipper/SMDG\nskipping\nskirmish/ZGMDRS\nskirt/SMDG\nskit/MS\nskitter/GSD\nskittish/YP\nskittishness/M\nskittle/S\nskive/DRSZG\nskivvy/DSMG\nskoal/SM\nskua/S\nskulduggery/M\nskulk/SDRZG\nskulker/M\nskull/SM\nskullcap/MS\nskunk/SMDG\nsky/GSM\nskycap/SM\nskydive/DRSZG\nskydiver/M\nskydiving/M\nskyjack/JZGSDR\nskyjacker/M\nskyjacking/M\nskylark/SGMD\nskylight/MS\nskyline/SM\nskyrocket/GSMD\nskyscraper/SM\nskyward/S\nskywriter/SM\nskywriting/M\nslab/MS\nslabbed\nslabbing\nslack/PXZTGMDNRYS\nslacken/DG\nslacker/M\nslackness/M\nslacks/M\nslag/MS\nslagged\nslagging\nslagheap/S\nslain\nslake/GDS\nslalom/MSDG\nslam/MS\nslammed\nslammer/SM\nslamming\nslander/MZGDRS\nslanderer/M\nslanderous\nslang/M\nslangy/RT\nslant/MSDG\nslanting/Y\nslantwise\nslap/MS\nslapdash\nslaphappy\nslapped\nslapper/S\nslapping\nslapstick/M\nslash/MDRSZG\nslasher/M\nslat/MDGS\nslate/SM\nslather/SDG\nslatted\nslattern/SMY\nslaughter/MDRZGS\nslaughterer/M\nslaughterhouse/MS\nslave/DRSMZG\nslaveholder/MS\nslaver/MDG\nslavery/M\nslavish/PY\nslavishness/M\nslaw/M\nslay/DRZGJS\nslayer/M\nslaying/M\nsleaze/SM\nsleazebag/S\nsleazeball/S\nsleazily\nsleaziness/M\nsleazy/PRT\nsled/MS\nsledded\nsledder/SM\nsledding\nsledge/DSMG\nsledgehammer/GSMD\nsleek/SDRYTGP\nsleekness/M\nsleep/SMRZG\nsleeper/M\nsleepily\nsleepiness/M\nsleepless/PY\nsleeplessness/M\nsleepover/SM\nsleepwalk/ZGSDR\nsleepwalker/M\nsleepwalking/M\nsleepwear/M\nsleepy/RPT\nsleepyhead/MS\nsleet/SMDG\nsleety\nsleeve/DSM\nsleeveless\nsleigh/MDG\nsleighs\nsleight/SM\nslender/PRT\nslenderize/DSG\nslenderness/M\nslept\nsleuth/MG\nsleuths\nslew/MDGS\nslice/DRSMZG\nslicer/M\nslick/SMDRYZTGP\nslicker/M\nslickness/M\nslid\nslide/RSMZG\nslider/M\nslideshow/MS\nslight/SMDRYTGP\nslightness/M\nslim/PS\nslime/M\nsliminess/M\nslimline\nslimmed\nslimmer/S\nslimmest\nslimming/M\nslimness/M\nslimy/RTP\nsling/SMG\nslingback/S\nslingshot/SM\nslink/SG\nslinky/RT\nslip/MS\nslipcase/MS\nslipcover/MS\nslipknot/MS\nslippage/MS\nslipped\nslipper/SM\nslipperiness/M\nslippery/PRT\nslipping\nslippy\nslipshod\nslipstream/SM\nslipway/SM\nslit/MS\nslither/SGMD\nslithery\nslitter\nslitting\nsliver/GSMD\nslob/MS\nslobbed\nslobber/MDSG\nslobbery\nslobbing\nsloe/MS\nslog/MS\nslogan/SM\nsloganeering\nslogged\nslogging\nsloop/SM\nslop/MDGS\nslope/SM\nslopped\nsloppily\nsloppiness/M\nslopping\nsloppy/PTR\nslops/M\nslosh/DSG\nslot/MS\nsloth/M\nslothful/YP\nslothfulness/M\nsloths\nslotted\nslotting\nslouch/ZGMDRS\nsloucher/M\nslouchy/TR\nslough/GMD\nsloughs\nsloven/SMY\nslovenliness/M\nslovenly/PTR\nslow/DRYTGSP\nslowcoach/S\nslowdown/SM\nslowness/M\nslowpoke/SM\nsludge/M\nsludgy/RT\nslue/MGDS\nslug/MS\nsluggard/MS\nslugged\nslugger/SM\nslugging\nsluggish/PY\nsluggishness/M\nsluice/DSMG\nslum/MS\nslumber/GSMD\nslumberous\nslumdog/SM\nslumlord/MS\nslummed\nslummer\nslumming\nslummy/RT\nslump/SMDG\nslung\nslunk\nslur/MS\nslurp/SMDG\nslurred\nslurring\nslurry/M\nslush/M\nslushiness/M\nslushy/RPT\nslut/MS\nsluttish\nslutty/RT\nsly/TRY\nslyness/M\nsmack/SMDRZG\nsmacker/M\nsmall/SMRTP\nsmallholder/S\nsmallholding/S\nsmallish\nsmallness/M\nsmallpox/M\nsmarmy/RT\nsmart/SMDNRYXTGP\nsmarten/DG\nsmartness/M\nsmartphone/SM\nsmarts/M\nsmartwatch/MS\nsmarty/SM\nsmartypants/M\nsmash/MDRSZG\nsmasher/M\nsmashup/SM\nsmattering/MS\nsmear/SMDG\nsmeary/RT\nsmell/SMDG\nsmelliness/M\nsmelly/RPT\nsmelt/SMDRZG\nsmelter/M\nsmidgen/MS\nsmilax/M\nsmile/DSMG\nsmiley/SM\nsmiling/Y\nsmirch/GMDS\nsmirk/SMDG\nsmite/SG\nsmith/M\nsmithereens/M\nsmiths\nsmithy/SM\nsmitten\nsmock/SMDG\nsmocking/M\nsmog/MS\nsmoggy/RT\nsmoke/DRSMZG\nsmokehouse/MS\nsmokeless\nsmoker/M\nsmokescreen/SM\nsmokestack/SM\nsmokey\nsmokiness/M\nsmoking/M\nsmoky/RTP\nsmolder/SGMD\nsmooch/MDSG\nsmoochy\nsmooth/PDRYTG\nsmoothie/MS\nsmoothness/M\nsmooths\nsmorgasbord/SM\nsmote\nsmother/GSMD\nsmudge/DSMG\nsmudgy/TR\nsmug/YP\nsmugger\nsmuggest\nsmuggle/ZGDRS\nsmuggler/M\nsmuggling/M\nsmugness/M\nsmurf/S\nsmut/MS\nsmuttiness/M\nsmutty/TRP\nsnack/SMDG\nsnaffle/DSMG\nsnafu/SM\nsnag/MS\nsnagged\nsnagging\nsnail/SMDG\nsnake/DSMG\nsnakebite/MS\nsnakelike\nsnakeskin\nsnaky/RT\nsnap's\nsnap/US\nsnapdragon/SM\nsnapped/U\nsnapper/MS\nsnappily\nsnappiness/M\nsnapping/U\nsnappish/YP\nsnappishness/M\nsnappy/TRP\nsnapshot/SM\nsnare/DSMG\nsnarf/SDG\nsnark/S\nsnarky/TR\nsnarl's\nsnarl/USDG\nsnarling/Y\nsnarly/TR\nsnatch/ZGMDRS\nsnatcher/M\nsnazzily\nsnazzy/TR\nsneak/SMDRZG\nsneaker/M\nsneakily\nsneakiness/M\nsneaking/Y\nsneaky/TRP\nsneer/SJMDG\nsneering/Y\nsneeze/DSMG\nsnick/SDRZG\nsnicker/MDG\nsnide/RYT\nsniff/SMDRZG\nsniffer/M\nsniffle/DSMG\nsniffy/RT\nsnifter/SM\nsnip/MDRZGS\nsnipe/SM\nsniper/M\nsnipped\nsnippet/SM\nsnipping\nsnippy/RT\nsnips/M\nsnit/MS\nsnitch/MDSG\nsnivel/SMDRZG\nsniveler/M\nsnob/MS\nsnobbery/M\nsnobbish/PY\nsnobbishness/M\nsnobby/RT\nsnog/S\nsnogged\nsnogging\nsnood/SM\nsnooker/MDSG\nsnoop/SMDRZG\nsnooper/M\nsnoopy/TR\nsnoot/SM\nsnootily\nsnootiness/M\nsnooty/PTR\nsnooze/DSMG\nsnore/DRSMZG\nsnorer/M\nsnorkel/ZGMDRS\nsnorkeler/M\nsnorkeling/M\nsnort/SMDRZG\nsnorter/M\nsnot/MS\nsnottily\nsnottiness/M\nsnotty/TPR\nsnout/SM\nsnow/MDGS\nsnowball/GSMD\nsnowbank/SM\nsnowbird/SM\nsnowblower/MS\nsnowboard/ZGMDRS\nsnowboarder/M\nsnowboarding/M\nsnowbound\nsnowdrift/SM\nsnowdrop/SM\nsnowfall/SM\nsnowfield/SM\nsnowflake/SM\nsnowiness/M\nsnowline\nsnowman/M\nsnowmen\nsnowmobile/DSMG\nsnowplow/SGMD\nsnowshed\nsnowshoe/SM\nsnowshoeing\nsnowstorm/SM\nsnowsuit/SM\nsnowy/PRT\nsnub/MS\nsnubbed\nsnubbing\nsnuff/SMDRYZG\nsnuffbox/MS\nsnuffer/M\nsnuffle/MGDS\nsnug/MYSP\nsnugged\nsnugger\nsnuggest\nsnugging\nsnuggle/MGDS\nsnugness/M\nso\nsoak/MDGSJ\nsoaking/M\nsoap/MDGS\nsoapbox/MS\nsoapiness/M\nsoapstone/M\nsoapsuds/M\nsoapy/RPT\nsoar/MDGS\nsob/SM\nsobbed\nsobbing/Y\nsober/SDRYPTG\nsoberness/M\nsobriety/IM\nsobriquet/SM\nsoc\nsoccer/M\nsociability/M\nsociable/SM\nsociably\nsocial/SMY\nsocialism/M\nsocialist/SM\nsocialistic\nsocialite/SM\nsocialization/M\nsocialize/DSG\nsocietal\nsociety/SM\nsocioeconomic\nsocioeconomically\nsociological/Y\nsociologist/SM\nsociology/M\nsociopath/M\nsociopaths\nsociopolitical\nsock/MDGS\nsocket/SM\nsockeye/SM\nsod/SM\nsoda/MS\nsodded\nsodden/Y\nsodding\nsodium/M\nsodomite/MS\nsodomize/GDS\nsodomy/M\nsoever\nsofa/MS\nsoft/NRYXTP\nsoftback\nsoftball/MS\nsoftbound\nsoftcover\nsoften/DRZG\nsoftener/M\nsofthearted\nsoftness/M\nsoftware/M\nsoftwood/SM\nsofty/SM\nsoggily\nsogginess/M\nsoggy/RTP\nsoigne\nsoignee\nsoil/MDGS\nsoiled/U\nsoiree/SM\nsojourn/ZGMDRS\nsojourner/M\nsol/SM\nsolace/DSMG\nsolar\nsolaria\nsolarium/M\nsold\nsolder/ZGSMDR\nsolderer/M\nsoldier/MDYSG\nsoldiery/M\nsole/FSDGM\nsolecism/SM\nsolely\nsolemn/PTRY\nsolemness/M\nsolemnify/DSG\nsolemnity/SM\nsolemnization/M\nsolemnize/DSG\nsolemnness/M\nsolenoid/MS\nsolicit/GDS\nsolicitation/SM\nsolicited/U\nsolicitor/SM\nsolicitous/PY\nsolicitousness/M\nsolicitude/M\nsolid/PSMRYT\nsolidarity/M\nsolidi\nsolidification/M\nsolidify/DSNG\nsolidity/M\nsolidness/M\nsolidus/M\nsoliloquies\nsoliloquize/DSG\nsoliloquy/M\nsolipsism/M\nsolipsistic\nsolitaire/MS\nsolitariness/M\nsolitary/SMP\nsolitude/M\nsolo/MDGS\nsoloist/MS\nsolstice/MS\nsolubility/IM\nsoluble/MS\nsolute's\nsolute/AXN\nsolutes\nsolution's/AE\nsolvable/IU\nsolve/EADSG\nsolved/U\nsolvency/IM\nsolvent/IMS\nsolver/SM\nsomatic\nsomber/PY\nsomberness/M\nsombrero/MS\nsome\nsomebody/SM\nsomeday\nsomehow\nsomeone/MS\nsomeplace\nsomersault/MDGS\nsomerset/SM\nsomersetted\nsomersetting\nsomething/SM\nsometime/S\nsomeway/S\nsomewhat/S\nsomewhere\nsomnambulism/M\nsomnambulist/SM\nsomnolence/M\nsomnolent\nson/SM\nsonar/SM\nsonata/SM\nsonatina/SM\nsong/MS\nsongbird/SM\nsongbook/SM\nsongfest/SM\nsongster/MS\nsongstress/MS\nsongwriter/SM\nsongwriting\nsonic\nsonnet/SM\nsonny/SM\nsonogram/SM\nsonority/M\nsonorous/YP\nsonorousness/M\nsonsofbitches\nsoon/RT\nsoot/M\nsooth/MDRSZG\nsoothe\nsoother/M\nsoothing/Y\nsoothsayer/MS\nsoothsaying/M\nsooty/RT\nsop/SM\nsophism/M\nsophist/MS\nsophistic\nsophistical\nsophisticate/DSMGN\nsophisticated/U\nsophistication/M\nsophistry/SM\nsophomore/MS\nsophomoric\nsoporific/MS\nsoporifically\nsopped\nsopping\nsoppy/RT\nsoprano/MS\nsorbet/SM\nsorcerer/MS\nsorceress/MS\nsorcery/M\nsordid/PY\nsordidness/M\nsore/MYTRSP\nsorehead/MS\nsoreness/M\nsorghum/M\nsorority/SM\nsorrel/SM\nsorrily\nsorriness/M\nsorrow/SMDG\nsorrowful/YP\nsorrowfulness/M\nsorry/RTP\nsort/FASGDM\nsorta\nsorted/U\nsorter/SM\nsortie/DSM\nsortieing\nsot/SM\nsottish\nsou'wester\nsou/SMH\nsouffle/SM\nsough/MDG\nsoughs\nsought/U\nsouk/S\nsoul/MS\nsoulful/YP\nsoulfulness/M\nsoulless/YP\nsoulmate/S\nsound/JPSMDRYZTG\nsoundalike/S\nsoundbar/S\nsoundbite/S\nsoundboard/MS\nsoundcheck/S\nsounder/M\nsounding/M\nsoundless/Y\nsoundness/UM\nsoundproof/GDS\nsoundproofing/M\nsoundscape/S\nsoundtrack/SM\nsoup/MDGS\nsoupcon/MS\nsoupy/RT\nsour/MDRYTGSP\nsource/ADSMG\nsourdough/M\nsourdoughs\nsourish\nsourness/M\nsourpuss/MS\nsousaphone/MS\nsouse/DSMG\nsouth/M\nsouthbound\nsoutheast/ZMR\nsoutheaster/MY\nsoutheastern\nsoutheastward/S\nsoutherly/SM\nsouthern/SZMR\nsoutherner/M\nsouthernmost\nsouthpaw/SM\nsouthward/MS\nsouthwest/ZMR\nsouthwester/MY\nsouthwestern\nsouthwestward/S\nsouvenir/SM\nsovereign/SM\nsovereignty/M\nsoviet/SM\nsow's\nsow/ASGD\nsower/SM\nsown/A\nsoy/M\nsoybean/MS\nsozzled\nspa/SM\nspace/DRSMZG\nspacecraft/MS\nspaceflight/MS\nspaceman/M\nspacemen\nspaceport/SM\nspacer/M\nspaceship/SM\nspacesuit/SM\nspacewalk/SGMD\nspacewoman/M\nspacewomen\nspacey\nspacial\nspacier\nspaciest\nspaciness/M\nspacing/M\nspacious/YP\nspaciousness/M\nspade/DSMG\nspadeful/MS\nspadework/M\nspadices\nspadix/M\nspaghetti/M\nspake\nspam/MS\nspammed\nspammer/SM\nspamming\nspan/MS\nspandex/M\nspangle/DSMG\nspangly\nspaniel/SM\nspank/SMDGJ\nspanking/M\nspanned\nspanner/SM\nspanning\nspar/MS\nspare/DRSMYTGP\nspareness/M\nspareribs/M\nsparing/UY\nspark/SMDYG\nsparkle/DRSMZG\nsparkler/M\nsparky/RT\nsparred\nsparring\nsparrow/SM\nsparrowhawk/S\nsparse/RYTP\nsparseness/M\nsparsity/M\nspartan\nspasm/SM\nspasmodic\nspasmodically\nspastic/SM\nspat/MS\nspate/SM\nspathe/SM\nspatial/Y\nspatted\nspatter/SGMD\nspatting\nspatula/SM\nspavin/MD\nspawn/SMDG\nspay/DGS\nspeak/SRZGJ\nspeakeasy/SM\nspeaker/M\nspeakerphone/S\nspear/SMDG\nspearfish/GMDS\nspeargun\nspearhead/GMDS\nspearmint/M\nspec/MS\nspecial/SMY\nspecialism/S\nspecialist/MS\nspecialization/MS\nspecialize/GDS\nspecialty/SM\nspecie/SM\nspecies/M\nspecif\nspecifiable\nspecific/MS\nspecifically\nspecification/M\nspecificity/M\nspecified/U\nspecify/XNZDRSG\nspecimen/SM\nspecious/YP\nspeciousness/M\nspeck/SMDG\nspeckle/MGDS\nspecs/M\nspectacle/SM\nspectacles/M\nspectacular/MYS\nspectate/DSG\nspectator/SM\nspecter/AMS\nspectra\nspectral\nspectrometer/MS\nspectroscope/MS\nspectroscopic\nspectroscopy/M\nspectrum/M\nspeculate/DSXGNV\nspeculation/M\nspeculative/Y\nspeculator/MS\nsped\nspeech/MS\nspeechify/DSG\nspeechless/YP\nspeechlessness/M\nspeechwriter/S\nspeed/SMRZG\nspeedboat/SM\nspeeder/M\nspeedily\nspeediness/M\nspeeding/M\nspeedometer/MS\nspeedster/SM\nspeedup/MS\nspeedway/SM\nspeedwell/M\nspeedy/TPR\nspeleological\nspeleologist/MS\nspeleology/M\nspell/JSMDRZG\nspellbind/ZGRS\nspellbinder/M\nspellbound\nspellcheck/DRZGS\nspellchecker/M\nspelldown/SM\nspeller/M\nspelling/M\nspelunker/MS\nspelunking/M\nspend/BSRZG\nspender/M\nspending/M\nspendthrift/MS\nspent/U\nsperm/SM\nspermatozoa\nspermatozoon/M\nspermicidal\nspermicide/MS\nspew/MDRZGS\nspewer/M\nsphagnum/MS\nsphere/SM\nspherical/Y\nspheroid/SM\nspheroidal\nsphincter/MS\nsphinx/MS\nspic/S\nspice/DSMG\nspicily\nspiciness/M\nspicule/MS\nspicy/PRT\nspider/SM\nspiderweb/MS\nspidery\nspiel/SMDG\nspiff/SDG\nspiffy/TR\nspigot/SM\nspike/DSMG\nspikiness/M\nspiky/RPT\nspill/SMDG\nspillage/MS\nspillover/SM\nspillway/MS\nspin/MS\nspinach/M\nspinal/SMY\nspindle/MGDS\nspindly/TR\nspine/SM\nspineless/YP\nspinet/SM\nspinnaker/SM\nspinner/MS\nspinneret/SM\nspinney/S\nspinning/M\nspinster/SM\nspinsterhood/M\nspinsterish\nspiny/RT\nspiracle/SM\nspiral/SGMDY\nspire's\nspire/IFAS\nspirea/SM\nspirit's\nspirit/ISGD\nspirited/Y\nspiritless\nspiritual/MYS\nspiritualism/M\nspiritualist/MS\nspiritualistic\nspirituality/M\nspirituous\nspirochete/SM\nspiry\nspit/MDGS\nspitball/SM\nspite/ASM\nspiteful/PY\nspitefuller\nspitefullest\nspitefulness/M\nspitfire/SM\nspitted\nspitting\nspittle/M\nspittoon/MS\nspiv/S\nsplash/GMDS\nsplashdown/MS\nsplashily\nsplashiness/M\nsplashy/RTP\nsplat/SM\nsplatted\nsplatter/GSMD\nsplatting\nsplay/SMDG\nsplayfeet\nsplayfoot/MD\nspleen/SM\nsplendid/RYT\nsplendor/MS\nsplendorous\nsplenectomy\nsplenetic\nsplice/DRSMZG\nsplicer/M\nspliff/S\nspline/S\nsplint/SZGMDR\nsplinter/MDG\nsplintery\nsplit/SM\nsplitting/MS\nsplodge/S\nsplosh/DSG\nsplotch/MDSG\nsplotchy/TR\nsplurge/DSMG\nsplutter/GMDS\nspoil's\nspoil/CSDRZG\nspoilage/M\nspoiled/U\nspoiler/CM\nspoilsport/MS\nspoke/SM\nspoken/U\nspokesman/M\nspokesmen\nspokespeople\nspokesperson/MS\nspokeswoman/M\nspokeswomen\nspoliation/CM\nsponge/DRSMZG\nspongecake/M\nsponger/M\nsponginess/M\nspongy/RPT\nsponsor/MDGS\nsponsorship/M\nspontaneity/M\nspontaneous/Y\nspoof/SMDG\nspook/SMDG\nspookiness/M\nspooky/RPT\nspool/SMDG\nspoon/SMDG\nspoonbill/MS\nspoonerism/MS\nspoonful/SM\nspoor/SMDG\nsporadic\nsporadically\nspore/DSMG\nsporran/S\nsport/SMDGV\nsportiness/M\nsporting/Y\nsportive/Y\nsportscast/MRZGS\nsportscaster/M\nsportsman/M\nsportsmanlike/U\nsportsmanship/M\nsportsmen\nsportspeople\nsportsperson\nsportswear/M\nsportswoman/M\nsportswomen\nsportswriter/SM\nsporty/TPR\nspot/CMS\nspotless/PY\nspotlessness/M\nspotlight/GSMD\nspotlit\nspotted\nspotter/MS\nspottily\nspottiness/M\nspotting\nspotty/TPR\nspousal/MS\nspouse/SM\nspout/SMDG\nsprain/GSMD\nsprang\nsprat/SM\nsprawl/GSMD\nspray's\nspray/ASDG\nsprayer/MS\nspread/ZGBSMR\nspreadeagled\nspreader/M\nspreadsheet/MS\nspree/DSM\nspreeing\nsprig/SM\nsprigged\nsprightliness/M\nsprightly/RTP\nspring/GSM\nspringboard/MS\nspringbok/MS\nspringily\nspringiness/M\nspringlike\nspringtime/M\nspringy/RPT\nsprinkle/DRSJMZG\nsprinkler/M\nsprinkling/M\nsprint/ZGSMDR\nsprinter/M\nsprite/SM\nspritz/ZGMDRS\nspritzer/M\nsprocket/MS\nsprog/S\nsprout/GSMD\nspruce/DRSPMYTG\nspruceness/M\nsprung\nspry/RYT\nspryness/M\nspud/MS\nspume/DSMG\nspumoni/M\nspumy\nspun\nspunk/SM\nspunky/TR\nspur/MS\nspurge/M\nspurious/PY\nspuriousness/M\nspurn/SDG\nspurred\nspurring\nspurt/SMDG\nsputa\nsputnik/MS\nsputter/MDGS\nsputum/M\nspy/GDSM\nspyglass/MS\nspymaster/S\nspyware/M\nsq\nsqq\nsquab/SM\nsquabble/MZGDRS\nsquabbler/M\nsquad/SM\nsquadron/MS\nsqualid/PTRY\nsqualidness/M\nsquall/SGMD\nsqually\nsqualor/M\nsquamous\nsquander/GDS\nsquare/PDRSMYTG\nsquareness/M\nsquarish\nsquash/GMDS\nsquashy/TR\nsquat/SMP\nsquatness/M\nsquatted\nsquatter/MS\nsquattest\nsquatting\nsquaw/SM\nsquawk/SZGMDR\nsquawker/M\nsqueak/SZGMDR\nsqueaker/M\nsqueakily\nsqueakiness/M\nsqueaky/TRP\nsqueal/SZGMDR\nsquealer/M\nsqueamish/PY\nsqueamishness/M\nsqueegee/MDS\nsqueegeeing\nsqueeze/BMZGDRS\nsqueezebox/S\nsqueezer/M\nsquelch/GMDS\nsquelchy\nsquib/SM\nsquid/SM\nsquidgy\nsquiffy\nsquiggle/DSMG\nsquiggly\nsquint/STGMDR\nsquire/DSMG\nsquirm/SGMD\nsquirmy/RT\nsquirrel/SGMD\nsquirt/SGMD\nsquish/GMDS\nsquishy/RT\nsriracha\nssh\nst\nstab/MYS\nstabbed\nstabber/MS\nstabbing/MS\nstability/IM\nstabilization/CM\nstabilize/CDSG\nstabilizer/MS\nstable/DRSMTG\nstableman/M\nstablemate/S\nstablemen\nstably/U\nstaccato/MS\nstack/SMDG\nstadium/MS\nstaff's\nstaff/ASDG\nstaffer/MS\nstaffing/M\nstag/MDGSJ\nstage/SM\nstagecoach/MS\nstagecraft/M\nstagehand/MS\nstagestruck\nstagflation/M\nstagger/MDGS\nstaggering/Y\nstaging/M\nstagnancy/M\nstagnant/Y\nstagnate/DSGN\nstagnation/M\nstagy/RT\nstaid/PRYT\nstaidness/M\nstain/SMDG\nstained/U\nstainless/M\nstair/SM\nstaircase/MS\nstairway/MS\nstairwell/SM\nstake/DSMG\nstakeholder/MS\nstakeout/SM\nstalactite/MS\nstalagmite/MS\nstale/DRSTGP\nstalemate/DSMG\nstaleness/M\nstalk/SMDRJZG\nstalker/M\nstalking/M\nstall's\nstall/ISDG\nstallholder/S\nstallion/MS\nstalwart/MYS\nstamen/SM\nstamina/M\nstammer/ZGMDRS\nstammerer/M\nstammering/Y\nstamp/SMDRZG\nstampede/MGDS\nstamper/M\nstance/ISM\nstanch/TGDRS\nstanchion/SM\nstand/SMRJZG\nstandalone\nstandard/MS\nstandardization/M\nstandardize/DSG\nstandby/M\nstandbys\nstandee/MS\nstander/M\nstanding/M\nstandoff/MS\nstandoffish\nstandout/MS\nstandpipe/SM\nstandpoint/MS\nstandstill/MS\nstank\nstanza/SM\nstaph/M\nstaphylococcal\nstaphylococci\nstaphylococcus/M\nstaple/DRSMZG\nstapler/M\nstar/MDRZGS\nstarboard/M\nstarburst/S\nstarch/GMDS\nstarchily\nstarchiness/M\nstarchy/PTR\nstardom/M\nstardust/M\nstare/SM\nstarer/M\nstarfish/MS\nstarfruit\nstargaze/DRSZG\nstargazer/M\nstark/RYPZT\nstarkness/M\nstarless\nstarlet/MS\nstarlight/M\nstarling/SM\nstarlit\nstarred\nstarring\nstarry/TR\nstarstruck\nstart/ASMDG\nstarter/MS\nstartle/GDS\nstartling/Y\nstartup/MS\nstarvation/M\nstarve/DSJG\nstarveling/MS\nstash/MDSG\nstasis\nstat/MS\nstate/DRSMYGNLX\nstatecraft/M\nstated/U\nstatehood/M\nstatehouse/MS\nstateless/P\nstatelessness/M\nstateliness/M\nstately/PRT\nstatement/AMS\nstatemented\nstatementing\nstateroom/MS\nstateside\nstatesman/M\nstatesmanlike\nstatesmanship/M\nstatesmen\nstateswoman/M\nstateswomen\nstatewide\nstatic/SM\nstatically\nstation/MDRZG\nstationary\nstationer/M\nstationery/M\nstationmaster/S\nstatistic/MS\nstatistical/Y\nstatistician/SM\nstatuary/M\nstatue/SM\nstatuesque\nstatuette/MS\nstature/MS\nstatus/MS\nstatute/MS\nstatutorily\nstatutory\nstaunch/PDRSYTG\nstaunchness/M\nstave/DSMG\nstay/MDRZGS\nstd\nstdio\nstead/SM\nsteadfast/YP\nsteadfastness/M\nsteadily/U\nsteadiness/UM\nsteady/TGPDRSM\nsteak/SM\nsteakhouse/SM\nsteal/SMHG\nstealth/M\nstealthily\nstealthiness/M\nstealthy/TPR\nsteam/SMDRZG\nsteamboat/MS\nsteamer/M\nsteamfitter/SM\nsteamfitting/M\nsteaminess/M\nsteampunk\nsteamroll/ZGDRS\nsteamroller/MDG\nsteamship/MS\nsteamy/TPR\nsteed/SM\nsteel/SMDG\nsteeliness/M\nsteelmaker/S\nsteelworker/SM\nsteelworks/M\nsteely/PTR\nsteelyard/SM\nsteep/SMDNRYPXTG\nsteepen/GD\nsteeple/MS\nsteeplechase/MS\nsteeplejack/SM\nsteepness/M\nsteer/SMDBG\nsteerage/M\nsteering/M\nsteersman/M\nsteersmen\nstegosauri\nstegosaurus/MS\nstein/SM\nstellar\nstem/MS\nstemless\nstemmed\nstemming\nstemware/M\nstench/MS\nstencil/GMDS\nsteno/SM\nstenographer/SM\nstenographic\nstenography/M\nstenosis\nstent/S\nstentorian\nstep/IMS\nstepbrother/SM\nstepchild/M\nstepchildren/M\nstepdad/MS\nstepdaughter/SM\nstepfather/SM\nstepladder/MS\nstepmom/MS\nstepmother/SM\nstepparent/SM\nsteppe/DRSMZG\nstepper/M\nsteppingstone/SM\nstepsister/MS\nstepson/MS\nstereo/SM\nstereophonic\nstereoscope/MS\nstereoscopic\nstereotype/DSMG\nstereotypical\nsterile\nsterility/M\nsterilization/SM\nsterilize/DRSZG\nsterilizer/M\nsterling/M\nstern/SMRYPT\nsternness/M\nsternum/MS\nsteroid/MS\nsteroidal\nstertorous\nstet/S\nstethoscope/MS\nstetson/MS\nstetted\nstetting\nstevedore/SM\nstew/MDGS\nsteward/GMDS\nstewardess/MS\nstewardship/M\nstick/SMRZG\nsticker/M\nstickily\nstickiness/M\nstickleback/SM\nstickler/MS\nstickpin/MS\nstickup/MS\nsticky/PTRSM\nstiff/SMDNRYPXTG\nstiffen/ZGDR\nstiffener/M\nstiffening/M\nstiffness/M\nstifle/DSJG\nstifling/Y\nstigma/SM\nstigmata\nstigmatic\nstigmatization/M\nstigmatize/GDS\nstile/SM\nstiletto/SM\nstill's\nstill/ITGSD\nstillbirth/M\nstillbirths\nstillborn\nstiller\nstillness/M\nstilt/SMD\nstilted/Y\nstimulant/SM\nstimulate/DSGNV\nstimulation/M\nstimuli\nstimulus/M\nsting/ZGSMR\nstinger/M\nstingily\nstinginess/M\nstingray/SM\nstingy/RTP\nstink/ZGSMR\nstinkbug/SM\nstinker/M\nstinky/RT\nstint/GSMD\nstipend/SM\nstipendiary/S\nstipple/DSMG\nstippling/M\nstipulate/XDSGN\nstipulation/M\nstir/MS\nstirred\nstirrer/SM\nstirring/SY\nstirrup/SM\nstitch's\nstitch/ADSG\nstitchery/M\nstitching/M\nstoat/SM\nstochastic\nstock's\nstock/AGSD\nstockade/DSMG\nstockbreeder/MS\nstockbroker/SM\nstockbroking/M\nstockholder/SM\nstockily\nstockiness/M\nstockinette/M\nstocking/SM\nstockist/S\nstockpile/MGDS\nstockpot/SM\nstockroom/MS\nstocktaking/M\nstocky/RTP\nstockyard/MS\nstodge\nstodgily\nstodginess/M\nstodgy/RTP\nstogie/MS\nstoic/SM\nstoical/Y\nstoicism/M\nstoke/DRSZG\nstoker/M\nstole/SM\nstolen\nstolid/RYTP\nstolidity/M\nstolidness/M\nstolon/MS\nstomach/MDRZG\nstomachache/SM\nstomacher/M\nstomachs\nstomp/GSMD\nstone/DRSMZG\nstonemason/MS\nstoner/M\nstonewall/GSD\nstoneware/M\nstonewashed\nstonework/M\nstonily\nstoniness/M\nstonkered\nstonking\nstony/TRP\nstood\nstooge/MS\nstool/SM\nstoop/GSMD\nstop's\nstop/US\nstopcock/SM\nstopgap/SM\nstoplight/MS\nstopover/MS\nstoppable/U\nstoppage/MS\nstopped/U\nstopper/GSMD\nstopping/U\nstopple/DSMG\nstopwatch/MS\nstorage/M\nstore's\nstore/ADSG\nstorefront/MS\nstorehouse/MS\nstorekeeper/SM\nstoreroom/SM\nstork/SM\nstorm/GSMD\nstormily\nstorminess/M\nstormy/RPT\nstory/DSM\nstoryboard/MS\nstorybook/SM\nstoryteller/MS\nstorytelling/M\nstoup/SM\nstout/TSMRYP\nstouthearted\nstoutness/M\nstove/SM\nstovepipe/SM\nstow/DGS\nstowage/M\nstowaway/MS\nstraddle/DRSMZG\nstraddler/M\nstrafe/MGDS\nstraggle/DRSZG\nstraggler/M\nstraggly/TR\nstraight/SPXTMNRY\nstraightaway/SM\nstraightedge/SM\nstraighten/ZGDR\nstraightener/M\nstraightforward/YPS\nstraightforwardness/M\nstraightness/M\nstraightway\nstrain's\nstrain/FADSG\nstrainer/ASM\nstrait/MNSX\nstraiten/GD\nstraitjacket/SGMD\nstraitlaced\nstrand/MDSG\nstrange/PRYZT\nstrangeness/M\nstranger/M\nstrangle/ZGDRS\nstranglehold/SM\nstrangler/M\nstrangulate/GNDS\nstrangulation/M\nstrap's\nstrap/US\nstrapless/MS\nstrapped/U\nstrapping/M\nstrata\nstratagem/SM\nstrategic/S\nstrategical/Y\nstrategics/M\nstrategist/SM\nstrategy/SM\nstrati\nstratification/M\nstratify/DSGN\nstratosphere/SM\nstratospheric\nstratum/M\nstratus/M\nstraw/GSMD\nstrawberry/SM\nstray/GSMD\nstreak/MDRSZG\nstreaker/M\nstreaky/TR\nstream/MDRSZG\nstreamer/M\nstreamline/DSG\nstreet/MS\nstreetcar/MS\nstreetlamp/S\nstreetlight/SM\nstreetwalker/SM\nstreetwise\nstrength/M\nstrengthen/AGDS\nstrengthener/MS\nstrengths\nstrenuous/PY\nstrenuousness/M\nstrep/M\nstreptococcal\nstreptococci\nstreptococcus/M\nstreptomycin/M\nstress/MDSG\nstressed/U\nstressful\nstretch/BZGMDRS\nstretcher/MDG\nstretchmarks\nstretchy/TR\nstrew/GSDH\nstrewn\nstria/M\nstriae\nstriated\nstriation/MS\nstricken\nstrict/RYPT\nstrictness/M\nstricture/SM\nstridden\nstride/MGS\nstridency/M\nstrident/Y\nstrife/M\nstrike/MZGRSJ\nstrikebound\nstrikebreaker/SM\nstrikebreaking\nstrikeout/MS\nstriker/M\nstriking/Y\nstring/MDRSZG\nstringency/M\nstringent/Y\nstringer/M\nstringiness/M\nstringy/PTR\nstrip/GSMD\nstripe/MS\nstripey\nstripling/MS\nstripped\nstripper/MS\nstripping\nstriptease/MZGDRS\nstripteaser/M\nstripy\nstrive/GS\nstriven\nstrobe/MS\nstroboscope/MS\nstroboscopic\nstrode\nstroke/MGDS\nstroll/MDRSZG\nstroller/M\nstrong/RYT\nstrongbox/MS\nstronghold/MS\nstrongman/M\nstrongmen\nstrongroom/S\nstrontium/M\nstrop/SM\nstrophe/SM\nstrophic\nstropped\nstroppily\nstropping\nstroppy/TRP\nstrove\nstruck\nstructural/Y\nstructuralism\nstructuralist/S\nstructure's\nstructure/AGDS\nstructured/U\nstrudel/SM\nstruggle/MGDS\nstrum/SM\nstrummed\nstrumming\nstrumpet/MS\nstrung/UA\nstrut/SM\nstrutted\nstrutting\nstrychnine/M\nstub/MS\nstubbed\nstubbing\nstubble/M\nstubbly\nstubborn/RYPT\nstubbornness/M\nstubby/RT\nstucco/MDG\nstuccoes\nstuck/U\nstud/MYS\nstudbook/MS\nstudded\nstudding/M\nstudent/SM\nstudentship/S\nstudied/U\nstudiedly\nstudio/MS\nstudious/PY\nstudiousness/M\nstudly/RT\nstudy's\nstudy/AGDS\nstuff/GSMD\nstuffily\nstuffiness/M\nstuffing/M\nstuffy/RPT\nstultification/M\nstultify/DSNG\nstumble/DRSMZG\nstumbler/M\nstump/GSMD\nstumpy/TR\nstun/S\nstung\nstunk\nstunned\nstunner/S\nstunning/Y\nstunt/GSMD\nstuntman\nstuntmen\nstupefaction/M\nstupefy/DSG\nstupendous/Y\nstupid/TMRYS\nstupidity/SM\nstupor/MS\nsturdily\nsturdiness/M\nsturdy/TRP\nsturgeon/SM\nstutter/MDRSZG\nstutterer/M\nsty/SM\nstyle's\nstyle/ADSG\nstyli\nstylish/PY\nstylishness/M\nstylist/SM\nstylistic/S\nstylistically\nstylize/DSG\nstylus/MS\nstymie/MDS\nstymieing\nstyptic/SM\nsuasion/EM\nsuave/RYTP\nsuaveness/M\nsuavity/M\nsub/SM\nsubaltern/MS\nsubaqua\nsubarctic\nsubarea/MS\nsubatomic\nsubbasement/SM\nsubbed\nsubbing\nsubbranch/MS\nsubcategory/SM\nsubclass\nsubcommittee/SM\nsubcompact/SM\nsubconscious/PMY\nsubconsciousness/M\nsubcontinent/SM\nsubcontinental\nsubcontract/MDSG\nsubcontractor/MS\nsubculture/MS\nsubcutaneous/Y\nsubdivide/GDS\nsubdivision/SM\nsubdominant\nsubdue/DSG\nsubeditor/S\nsubfamily/SM\nsubfreezing\nsubgroup/MS\nsubhead/GJMS\nsubheading/M\nsubhuman/MS\nsubj\nsubject/GVMDS\nsubjection/M\nsubjective/Y\nsubjectivity/M\nsubjoin/GDS\nsubjugate/GNDS\nsubjugation/M\nsubjunctive/SM\nsublease/MGDS\nsublet/SM\nsubletting\nsublieutenant/S\nsublimate/GNDS\nsublimation/M\nsublime/YTGDRS\nsubliminal/Y\nsublimity/M\nsublingual\nsubmarginal\nsubmarine/MZRS\nsubmariner/M\nsubmerge/GDS\nsubmergence/M\nsubmerse/GNDS\nsubmersible/MS\nsubmersion/M\nsubmicroscopic\nsubmission/MS\nsubmissive/PY\nsubmissiveness/M\nsubmit/AS\nsubmitted/A\nsubmitter\nsubmitting/A\nsubnormal\nsuborbital\nsuborder/MS\nsubordinate/DSMGN\nsubordination/IM\nsuborn/SGD\nsubornation/M\nsubparagraph\nsubplot/MS\nsubpoena/GMDS\nsubprime\nsubprofessional/SM\nsubprogram/S\nsubroutine/SM\nsubscribe/UASDG\nsubscriber/MS\nsubscript/MS\nsubscription/MS\nsubsection/MS\nsubsequent/Y\nsubservience/M\nsubservient/Y\nsubset/SM\nsubside/GDS\nsubsidence/M\nsubsidiarity\nsubsidiary/SM\nsubsidization/M\nsubsidize/ZGDRS\nsubsidizer/M\nsubsidy/SM\nsubsist/SDG\nsubsistence/M\nsubsoil/M\nsubsonic\nsubspace\nsubspecies/M\nsubstance/SM\nsubstandard\nsubstantial/IY\nsubstantiate/GNDSX\nsubstantiated/U\nsubstantiation/FM\nsubstantive/SMY\nsubstation/MS\nsubstituent\nsubstitute/XMGNDS\nsubstitution/M\nsubstrata\nsubstrate/MS\nsubstratum/M\nsubstructure/SM\nsubsume/DSG\nsubsumption\nsubsurface/M\nsubsystem/SM\nsubteen/SM\nsubtenancy/M\nsubtenant/SM\nsubtend/SDG\nsubterfuge/SM\nsubterranean\nsubtext/SM\nsubtitle/DSMG\nsubtle/TR\nsubtlety/SM\nsubtly\nsubtopic/SM\nsubtotal/SGMD\nsubtract/GSD\nsubtraction/SM\nsubtrahend/SM\nsubtropic/S\nsubtropical\nsubtropics/M\nsuburb/MS\nsuburban/SM\nsuburbanite/SM\nsuburbia/M\nsubvention/SM\nsubversion/M\nsubversive/SPMY\nsubversiveness/M\nsubvert/SDG\nsubway/MS\nsubzero\nsucceed/GDS\nsuccess/VMS\nsuccessful/UY\nsuccession/SM\nsuccessive/Y\nsuccessor/SM\nsuccinct/RYTP\nsuccinctness/M\nsuccor/SGMD\nsuccotash/M\nsuccubi\nsuccubus\nsucculence/M\nsucculency/M\nsucculent/SM\nsuccumb/GDS\nsuch\nsuchlike\nsuck/MDRZGS\nsucker/GMD\nsuckle/DSJG\nsuckling/M\nsucrose/M\nsuction/SMDG\nsudden/PY\nsuddenness/M\nsuds/M\nsudsy/TR\nsue/DSG\nsuede/M\nsuet/M\nsuety\nsuffer/DRZGSJ\nsufferance/M\nsufferer/M\nsuffering/M\nsuffice/DSG\nsufficiency/IM\nsufficient/IY\nsuffix/MDSG\nsuffixation/M\nsuffocate/GNDS\nsuffocation/M\nsuffragan/MS\nsuffrage/M\nsuffragette/SM\nsuffragist/MS\nsuffuse/DSGN\nsuffusion/M\nsugar/GSMD\nsugarcane/M\nsugarcoat/GDS\nsugarless\nsugarplum/MS\nsugary/RT\nsuggest/GVSDR\nsuggestibility/M\nsuggestible\nsuggestion/SM\nsuggestive/YP\nsuggestiveness/M\nsuicidal\nsuicide/SM\nsuit/BMDGS\nsuitability/UM\nsuitableness/M\nsuitably/U\nsuitcase/SM\nsuite/SM\nsuited/U\nsuiting/M\nsuitor/MS\nsukiyaki/M\nsulfa/M\nsulfate/SM\nsulfide/SM\nsulfonamides\nsulfur/MDSG\nsulfuric\nsulfurous\nsulk/MDGS\nsulkily\nsulkiness/M\nsulky/TRSMP\nsullen/RYPT\nsullenness/M\nsullied/U\nsully/GDS\nsultan/MS\nsultana/SM\nsultanate/MS\nsultrily\nsultriness/M\nsultry/RPT\nsum/SM\nsumac/M\nsummarily\nsummarize/GDS\nsummary/SM\nsummat\nsummation/FMS\nsummed\nsummer/MDSG\nsummerhouse/SM\nsummertime/M\nsummery\nsumming\nsummit/MS\nsummitry/M\nsummon/DRSZG\nsummoner/M\nsummons/GMDS\nsumo/M\nsump/MS\nsumptuous/PY\nsumptuousness/M\nsun/SM\nsunbath/ZGMDRS\nsunbathe\nsunbather/M\nsunbathing/M\nsunbaths\nsunbeam/SM\nsunbed/S\nsunbelt\nsunblock/MS\nsunbonnet/SM\nsunburn/SGMD\nsunburst/MS\nsundae/MS\nsundeck/S\nsunder/DSG\nsundial/SM\nsundown/SM\nsundress/S\nsundries/M\nsundry/S\nsunfish/MS\nsunflower/MS\nsung/U\nsunglasses/M\nsunhat/S\nsunk/N\nsunlamp/SM\nsunless\nsunlight/M\nsunlit\nsunned\nsunniness/M\nsunning\nsunny/TRP\nsunrise/SM\nsunroof/SM\nsunscreen/MS\nsunset/MS\nsunshade/MS\nsunshine/M\nsunshiny\nsunspot/SM\nsunstroke/M\nsuntan/MS\nsuntanned\nsuntanning\nsuntrap/S\nsunup/M\nsup/SZMR\nsuper/M\nsuperabundance/MS\nsuperabundant\nsuperannuate/GNDS\nsuperannuation/M\nsuperb/RYT\nsupercargo/M\nsupercargoes\nsupercharge/ZGDRS\nsupercharger/M\nsupercilious/PY\nsuperciliousness/M\nsupercity/SM\nsupercomputer/MS\nsuperconducting\nsuperconductive\nsuperconductivity/M\nsuperconductor/SM\nsuperego/MS\nsupererogation/M\nsupererogatory\nsuperficial/Y\nsuperficiality/M\nsuperfine\nsuperfluity/M\nsuperfluous/YP\nsuperfluousness/M\nsuperglue\nsupergrass/S\nsuperhero/MS\nsuperheroes\nsuperhighway/SM\nsuperhuman\nsuperimpose/GDS\nsuperimposition/M\nsuperintend/DSG\nsuperintendence/M\nsuperintendency/M\nsuperintendent/SM\nsuperior/MS\nsuperiority/M\nsuperlative/SMY\nsuperman/M\nsupermarket/SM\nsupermen\nsupermodel/SM\nsupermom/MS\nsupernal\nsupernatural/SY\nsupernova/MS\nsupernovae\nsupernumerary/SM\nsuperpose/GDS\nsuperposition/M\nsuperpower/SM\nsupersaturate/GNDS\nsupersaturation/M\nsuperscribe/GDS\nsuperscript/MS\nsuperscription/M\nsupersede/GDS\nsupersize/GDS\nsupersonic\nsuperstar/MS\nsuperstate/S\nsuperstition/MS\nsuperstitious/Y\nsuperstore/MS\nsuperstructure/MS\nsupertanker/MS\nsuperuser/S\nsupervene/GDS\nsupervention/M\nsupervise/XGNDS\nsupervised/U\nsupervision/M\nsupervisor/MS\nsupervisory\nsuperwoman/M\nsuperwomen\nsupine/Y\nsupp/DRZG\nsupper/M\nsuppertime\nsuppl\nsupplant/SDG\nsupple/TLPR\nsupplement/MDGS\nsupplemental\nsupplementary\nsupplementation/M\nsuppleness/M\nsuppliant/SM\nsupplicant/MS\nsupplicate/GDS\nsupplication/M\nsupplier/M\nsupply/ZGDRSMXN\nsupport/MDRSBZGV\nsupportable/UI\nsupported/U\nsupporter/M\nsuppose/GDS\nsupposed/Y\nsupposition/MS\nsuppository/SM\nsuppress/GDS\nsuppressant/MS\nsuppressible\nsuppression/M\nsuppressor/SM\nsuppurate/DSGN\nsuppuration/M\nsupra\nsupranational\nsupremacist/MS\nsupremacy/M\nsupreme/Y\nsupremo/S\nsupt\nsurcease/DSMG\nsurcharge/DSMG\nsurcingle/SM\nsure/PYTR\nsurefire\nsurefooted\nsureness/M\nsurety/SM\nsurf/MDRZGS\nsurface's\nsurface/AGDS\nsurfboard/MDSG\nsurfeit/MDSG\nsurfer/M\nsurfing/M\nsurge/DSMG\nsurgeon/MS\nsurgery/SM\nsurgical/Y\nsurliness/M\nsurly/PTR\nsurmise/MGDS\nsurmount/DGSB\nsurmountable/I\nsurname/MS\nsurpass/GDS\nsurpassed/U\nsurplice/MS\nsurplus/MS\nsurplussed\nsurplussing\nsurprise/DSMGJ\nsurprising/UY\nsurreal\nsurrealism/M\nsurrealist/SM\nsurrealistic\nsurrealistically\nsurrender/MDSG\nsurreptitious/PY\nsurreptitiousness/M\nsurrey/MS\nsurrogacy/M\nsurrogate/SM\nsurround/GSDJ\nsurrounding/M\nsurroundings/M\nsurtax/MDSG\nsurtitle/S\nsurveillance/M\nsurvey's\nsurvey/ADGS\nsurveying/M\nsurveyor/SM\nsurvival/SM\nsurvivalist/SM\nsurvive/DSGB\nsurvivor/SM\nsusceptibility/SM\nsusceptible/I\nsushi/M\nsuspect/SMDG\nsuspected/U\nsuspend/SDRZG\nsuspender/M\nsuspense/XMN\nsuspenseful\nsuspension/M\nsuspicion/SM\nsuspicious/Y\nsuss/DSG\nsustain/SDBG\nsustainability\nsustainable/U\nsustenance/M\nsutler/MS\nsuttee\nsuture/MGDS\nsuzerain/MS\nsuzerainty/M\nsvelte/TR\nswab/MS\nswabbed\nswabbing\nswaddle/DSG\nswag/MS\nswagged\nswagger/SMDRG\nswagging\nswain/SM\nswallow/GSMD\nswallowtail/MS\nswam\nswami/SM\nswamp/GSMD\nswampland/M\nswampy/RT\nswan/MS\nswank/TGSMDR\nswankily\nswankiness/M\nswanky/RPT\nswanned\nswanning\nswansong/S\nswap/MS\nswapped\nswapping\nsward/SM\nswarm/GSMD\nswarthy/TR\nswash/GMDS\nswashbuckler/SM\nswashbuckling/M\nswastika/SM\nswat/MS\nswatch/MS\nswath/GMDS\nswathe/M\nswaths\nswatted\nswatter/SMDG\nswatting\nsway/MDGS\nswayback/MD\nswayed/U\nswear/ZGSR\nswearer/M\nswearword/MS\nsweat/ZGSMDR\nsweatband/MS\nsweater/M\nsweatpants/M\nsweats/M\nsweatshirt/SM\nsweatshop/MS\nsweatsuit/S\nsweaty/RT\nswede/SM\nsweep/ZGSMRJ\nsweeper/M\nsweeping/MY\nsweepings/M\nsweepstakes/M\nsweet/XTSMNRYP\nsweetbread/SM\nsweetbrier/SM\nsweetcorn\nsweetened/U\nsweetener/MS\nsweetening/M\nsweetheart/SM\nsweetie/SM\nsweetish\nsweetmeat/MS\nsweetness/M\nswell/TGSMDRJ\nswellhead/MDS\nswelling/M\nswelter/SGMD\nswept\nsweptback\nswerve/MGDS\nswerving/U\nswift/PTSMRY\nswiftness/M\nswig/MS\nswigged\nswigging\nswill/GSMD\nswim/MS\nswimmer/SM\nswimming/MY\nswimsuit/SM\nswimwear\nswindle/DRSMZG\nswindler/M\nswine/SM\nswineherd/SM\nswing/ZGSMR\nswingeing\nswinger/M\nswinish\nswipe/DSMG\nswirl/GSMD\nswirly\nswish/TGMDRS\nswitch/MDRSZGB\nswitchback/MS\nswitchblade/SM\nswitchboard/SM\nswitcher/M\nswivel/MDGS\nswiz\nswizz\nswizzle/DSG\nswollen\nswoon/SGMD\nswoop/SGMD\nswoosh/MDSG\nsword/SM\nswordfish/MS\nswordplay/M\nswordsman/M\nswordsmanship/M\nswordsmen\nswore\nsworn\nswot/S\nswotted\nswotting\nswum\nswung\nsybarite/SM\nsybaritic\nsycamore/MS\nsycophancy/M\nsycophant/SM\nsycophantic\nsyllabic\nsyllabicate/GNDS\nsyllabication/M\nsyllabification/M\nsyllabify/DSNG\nsyllable/MS\nsyllabub/S\nsyllabus/MS\nsyllogism/MS\nsyllogistic\nsylph/M\nsylphic\nsylphlike\nsylphs\nsylvan\nsymbioses\nsymbiosis/M\nsymbiotic\nsymbiotically\nsymbol/MS\nsymbolic\nsymbolical/Y\nsymbolism/M\nsymbolization/M\nsymbolize/DSG\nsymmetric\nsymmetrical/Y\nsymmetry/SM\nsympathetic/U\nsympathetically/U\nsympathies/M\nsympathize/ZGDRS\nsympathizer/M\nsympathy/SM\nsymphonic\nsymphony/SM\nsymposium/MS\nsymptom/MS\nsymptomatic\nsymptomatically\nsyn/H\nsynagogal\nsynagogue/SM\nsynapse/MS\nsynaptic\nsync/MDSG\nsynchronicity\nsynchronization/SM\nsynchronize/GDS\nsynchronous/Y\nsyncopate/DSGN\nsyncopation/M\nsyncope/M\nsyndicalism\nsyndicalist/S\nsyndicate/DSMGN\nsyndication/M\nsyndrome/SM\nsynergism/M\nsynergistic\nsynergy/SM\nsynfuel/MS\nsynod/SM\nsynonym/SM\nsynonymous\nsynonymy/M\nsynopses\nsynopsis/M\nsynoptic\nsynovial\nsyntactic\nsyntactical/Y\nsyntax/M\nsyntheses\nsynthesis/M\nsynthesize/ZGDRS\nsynthesizer/M\nsynthetic/SM\nsynthetically\nsynths\nsyphilis/M\nsyphilitic/SM\nsyringe/DSMG\nsyrup/SM\nsyrupy\nsysadmin/S\nsysop/S\nsystem/SM\nsystematic/U\nsystematical/Y\nsystematization/M\nsystematize/GDS\nsystemic/MS\nsystemically\nsystole/SM\nsystolic\nt/SDNXGBJ\nta\ntab/SM\ntabbed\ntabbing\ntabbouleh/M\ntabby/SM\ntabernacle/SM\ntabla/MS\ntable/MGDS\ntableau/M\ntableaux\ntablecloth/M\ntablecloths\ntableland/SM\ntablespoon/SM\ntablespoonful/SM\ntablet/SM\ntabletop/MS\ntableware/M\ntabloid/SM\ntaboo/MDSG\ntabor/MS\ntabular\ntabulate/DSGNX\ntabulation/M\ntabulator/SM\ntachograph\ntachographs\ntachometer/SM\ntachycardia/M\ntachyon\ntacit/PY\ntacitness/M\ntaciturn/Y\ntaciturnity/M\ntack/ZGMDRS\ntacker/M\ntackiness/M\ntackle/DRSMZG\ntackler/M\ntacky/RTP\ntaco/MS\ntact/FM\ntactful/YP\ntactfulness/M\ntactic/SM\ntactical/Y\ntactician/MS\ntactile\ntactility/M\ntactless/PY\ntactlessness/M\ntad/SM\ntadpole/MS\ntaffeta/M\ntaffrail/SM\ntaffy/SM\ntag/SM\ntagged\ntagger/SM\ntagging\ntagliatelle\ntagline/MS\ntaiga/MS\ntail/ACSDMG\ntailback/MS\ntailboard/S\ntailbone/S\ntailcoat/MS\ntailgate/MZGDRS\ntailgater/M\ntailless\ntaillight/MS\ntailor/SGMD\ntailoring/M\ntailpiece/S\ntailpipe/SM\ntailspin/SM\ntailwind/SM\ntaint/MDSG\ntainted/U\ntake/AIMS\ntakeaway/S\ntaken/A\ntakeoff/MS\ntakeout/MS\ntakeover/SM\ntaker/MS\ntaking/SM\ntakings/M\ntalc/M\ntalcum/M\ntale/MS\ntalebearer/MS\ntalent/SMD\ntalented/U\ntali\ntalisman/MS\ntalk/ZGMDRS\ntalkative/PY\ntalkativeness/M\ntalker/M\ntalkie/RSMT\ntalky\ntall/TRP\ntallboy/MS\ntallier/M\ntallish\ntallness/M\ntallow/M\ntallowy\ntally/DRSMZG\ntallyho/MDGS\ntalon/MS\ntalus/MS\ntam/SM\ntamale/SM\ntamarack/MS\ntamarind/MS\ntambourine/MS\ntame/BYZTGDRSP\ntamed/U\ntameness/M\ntamer/M\ntamoxifen\ntamp/ZGDRS\ntamper/ZGDR\ntamperer/M\ntampon/SM\ntan/SM\ntanager/MS\ntanbark/M\ntandem/SM\ntandoori/M\ntang/MS\ntangelo/MS\ntangent/MS\ntangential/Y\ntangerine/MS\ntangibility/IM\ntangible/IMS\ntangibleness/M\ntangibly/I\ntangle's\ntangle/UDSG\ntango/MDSG\ntangy/RT\ntank/ZGMDRS\ntankard/MS\ntanker/M\ntankful/MS\ntanned/U\ntanner/SM\ntannery/SM\ntannest\ntannin/M\ntanning/M\ntansy/M\ntantalization/M\ntantalize/ZGDRS\ntantalizer/M\ntantalizing/Y\ntantalum/M\ntantamount\ntantra/M\ntantrum/SM\ntap/SZGMDR\ntapas\ntape/MS\ntapeline/MS\ntaper/MDG\ntapestry/SM\ntapeworm/MS\ntapioca/M\ntapir/MS\ntapped/U\ntapper/MS\ntappet/MS\ntapping\ntaproom/SM\ntaproot/SM\ntar/SGMD\ntaramasalata\ntarantella/MS\ntarantula/SM\ntarball/S\ntardily\ntardiness/M\ntardy/TPR\ntare/MS\ntarget/MDGS\ntariff/MS\ntarmac/MS\ntarmacadam\ntarmacked\ntarmacking\ntarn/MS\ntarnish/GMDS\ntarnished/U\ntaro/MS\ntarot/MS\ntarp/MS\ntarpaulin/MS\ntarpon/MS\ntarragon/SM\ntarred\ntarring\ntarry/TGDRS\ntarsal/MS\ntarsi\ntarsus/M\ntart/PTGMDRYS\ntartan/MS\ntartar/MS\ntartaric\ntartness/M\ntarty/T\ntaser/GMDS\ntask/GMDS\ntaskmaster/MS\ntaskmistress/MS\ntassel/MDSG\ntaste/JMZGDRS\ntasted/U\ntasteful/EPY\ntastefulness/EM\ntasteless/PY\ntastelessness/M\ntaster/M\ntastily\ntastiness/M\ntasting/M\ntasty/TRP\ntat/SZR\ntatami/MS\ntater/M\ntatted\ntatter/MDSG\ntatterdemalion/MS\ntattie\ntatting/M\ntattle/MZGDRS\ntattler/M\ntattletale/MS\ntattoo/MDRSZG\ntattooer/M\ntattooist/SM\ntatty/TRS\ntau/SM\ntaught/UA\ntaunt/ZGMDRS\ntaunter/M\ntaunting/Y\ntaupe/M\ntaut/PXTNRY\ntauten/DG\ntautness/M\ntautological/Y\ntautologous\ntautology/SM\ntavern/MS\ntawdrily\ntawdriness/M\ntawdry/RTP\ntawny/TRM\ntax/BZGMDRS\ntaxa\ntaxation/M\ntaxer/M\ntaxi/GMDS\ntaxicab/SM\ntaxidermist/SM\ntaxidermy/M\ntaximeter/MS\ntaxiway/S\ntaxman\ntaxmen\ntaxon\ntaxonomic\ntaxonomist/MS\ntaxonomy/SM\ntaxpayer/MS\ntaxpaying\ntbs\ntbsp\ntea/SM\nteabag/S\nteacake/SM\nteach/ZGRSBJ\nteachable/U\nteacher/M\nteaching/M\nteacup/MS\nteacupful/MS\nteak/MS\nteakettle/SM\nteal/MS\ntealight/MS\nteam/GMDS\nteammate/MS\nteamster/MS\nteamwork/M\nteapot/MS\ntear/GMDS\ntearaway/S\nteardrop/SM\ntearful/Y\nteargas/MS\nteargassed\nteargassing\ntearjerker/MS\ntearoom/SM\nteary/TR\ntease/MZGDRS\nteasel/MS\nteaser/M\nteasing/Y\nteaspoon/SM\nteaspoonful/SM\nteat/MS\nteatime/S\ntech/M\ntechie/S\ntechnetium/M\ntechnical/Y\ntechnicality/SM\ntechnician/SM\ntechnicolor\ntechnique/SM\ntechno\ntechnobabble\ntechnocracy/SM\ntechnocrat/MS\ntechnocratic\ntechnological/Y\ntechnologist/MS\ntechnology/SM\ntechnophobe/S\ntechs\ntectonic/S\ntectonics/M\nted/S\nteddy/S\ntedious/PY\ntediousness/M\ntedium/M\ntee/DSMH\nteeing\nteem/GDS\nteen/MS\nteenage/RZ\nteenager/M\nteeny/TR\nteenybopper/MS\nteeter/MDSG\nteethe/GDS\nteething/M\nteetotal/RZ\nteetotaler/M\nteetotalism/M\ntektite/SM\ntel\ntelecast/SZGMR\ntelecaster/M\ntelecommunication/MS\ntelecommunications/M\ntelecommute/ZGDRS\ntelecommuter/M\ntelecommuting/M\nteleconference/MGDS\nteleconferencing/M\ntelegenic\ntelegram/MS\ntelegraph/MDRZG\ntelegrapher/M\ntelegraphese\ntelegraphic\ntelegraphically\ntelegraphist/SM\ntelegraphs\ntelegraphy/M\ntelekinesis/M\ntelekinetic\ntelemarketer/SM\ntelemarketing/M\ntelemeter/SM\ntelemetry/SM\nteleological\nteleology\ntelepathic\ntelepathically\ntelepathy/M\ntelephone/DRSMZG\ntelephoner/M\ntelephonic\ntelephonist/S\ntelephony/M\ntelephoto/SM\ntelephotography/M\nteleplay/MS\nteleport\nteleportation\nteleprinter/MS\nteleprocessing/M\nteleprompter/SM\ntelesales\ntelescope/DSMG\ntelescopic\ntelescopically\nteletext/MS\ntelethon/MS\nteletype/S\nteletypewriter/MS\ntelevangelism/M\ntelevangelist/MS\ntelevise/XGNDS\ntelevision/M\nteleworker/S\nteleworking\ntelex/MDSG\ntell/AGS\nteller/SM\ntelling/Y\ntelltale/SM\ntellurium/M\ntelly/SM\ntelnet\ntemblor/MS\ntemerity/M\ntemp/MDRZTGS\ntemper/MDG\ntempera/LSM\ntemperament/MS\ntemperamental/Y\ntemperance/IM\ntemperate/IY\ntemperateness/M\ntemperature/SM\ntempest/SM\ntempestuous/YP\ntempestuousness/M\ntemplate's\ntemplate/S\ntemple/SM\ntempo/SM\ntemporal/Y\ntemporarily\ntemporariness/M\ntemporary/FSM\ntemporize/ZGDRS\ntemporizer/M\ntempt/SDRZG\ntemptation/MS\ntempter/M\ntempting/Y\ntemptress/MS\ntempura/M\nten/BMH\ntenability/M\ntenable/U\ntenably\ntenacious/YP\ntenaciousness/M\ntenacity/M\ntenancy/SM\ntenant/SMDG\ntenanted/U\ntenantry/M\ntench\ntend/IEFDGS\ntended/U\ntendency/SM\ntendentious/YP\ntendentiousness/M\ntender/SMDRYTGP\ntenderfoot/MS\ntenderhearted/PY\ntenderheartedness/M\ntenderize/ZGDRS\ntenderizer/M\ntenderloin/SM\ntenderness/M\ntendinitis/M\ntendon/SM\ntendril/SM\ntenement/SM\ntenet/SM\ntenfold\ntenner/S\ntennis/M\ntenon/SMDG\ntenor/SM\ntenpin/SM\ntenpins/M\ntense/DRSMYTGNXP\ntenseness/M\ntensile\ntension/ESM\ntensity/IM\ntensor/S\ntent/DGSM\ntentacle/DSM\ntentative/PY\ntentativeness/M\ntenterhook/MS\ntenth/MY\ntenths\ntenuity/M\ntenuous/PY\ntenuousness/M\ntenure/DSMG\ntepee/SM\ntepid/YP\ntepidity/M\ntepidness/M\ntequila/SM\nterabit/SM\nterabyte/MS\nterahertz/M\nterapixel/MS\nterbium/M\ntercentenary/SM\ntercentennial/SM\nteriyaki\nterm/MDYGS\ntermagant/MS\nterminable/IC\nterminal/MYS\nterminate/DSGNX\ntermination/CSM\nterminator/S\ntermini\nterminological/Y\nterminology/SM\nterminus/M\ntermite/SM\ntern/IMS\nternary/SM\nterr\nterrace/DSMG\nterracotta/M\nterrain/SM\nterrapin/MS\nterrarium/SM\nterrazzo/MS\nterrestrial/SMY\nterrible/P\nterribleness/M\nterribly\nterrier/M\nterrific\nterrifically\nterrify/GDS\nterrifying/Y\nterrine/S\nterritorial/MS\nterritoriality\nterritory/SM\nterror/SM\nterrorism/M\nterrorist/SM\nterrorize/DSG\nterry/RMZ\nterrycloth/M\nterse/RYTP\nterseness/M\ntertiary\ntessellate/DSXGN\ntessellation/M\ntest's/AFK\ntest/AKFCDGS\ntestable/CF\ntestament/MS\ntestamentary\ntestate/S\ntestator/MS\ntestatrices\ntestatrix/M\ntested/U\ntester/KSM\ntestes\ntesticle/MS\ntesticular\ntestifier/M\ntestify/ZGDRS\ntestily\ntestimonial/MS\ntestimony/SM\ntestiness/M\ntestings\ntestis/M\ntestosterone/M\ntesty/PRT\ntetanus/M\ntetchily\ntetchy/PRT\ntether/SMDG\ntetra/SM\ntetracycline/M\ntetrahedral\ntetrahedron/MS\ntetrameter/SM\ntext/FMS\ntextbook/SM\ntexted\ntextile/MS\ntexting\ntextual/FY\ntextural\ntexture/MGDS\nthalami\nthalamus/M\nthalidomide/M\nthallium/M\nthan\nthane/SM\nthank/SDG\nthankful/YP\nthankfulness/M\nthankless/PY\nthanklessness/M\nthanksgiving/SM\nthat/M\nthatch/MDRSZG\nthatcher/M\nthatching/M\nthaw/MDGS\nthe/JG\ntheater/SM\ntheatergoer/SM\ntheatrical/YS\ntheatricality/M\ntheatricals/M\ntheatrics/M\nthee/S\ntheft/SM\ntheir/S\ntheism/M\ntheist/SM\ntheistic\nthem\nthematic\nthematically\ntheme/DSM\nthemselves\nthen/M\nthence\nthenceforth\nthenceforward\ntheocracy/SM\ntheocratic\ntheodolite/S\ntheologian/SM\ntheological/Y\ntheology/SM\ntheorem/MS\ntheoretic\ntheoretical/Y\ntheoretician/SM\ntheorist/SM\ntheorize/DSG\ntheory/SM\ntheosophic\ntheosophical\ntheosophist/SM\ntheosophy/M\ntherapeutic/S\ntherapeutically\ntherapeutics/M\ntherapist/SM\ntherapy/SM\nthere/M\nthereabout/S\nthereafter\nthereat\nthereby\ntherefor\ntherefore\ntherefrom\ntherein\ntheremin/SM\nthereof\nthereon\nthereto\ntheretofore\nthereunto\nthereupon\ntherewith\ntherm/SM\nthermal/MYS\nthermionic\nthermodynamic/S\nthermodynamics/M\nthermometer/MS\nthermometric\nthermonuclear\nthermoplastic/SM\nthermos/MS\nthermostat/MS\nthermostatic\nthermostatically\nthesauri\nthesaurus/MS\nthese/S\nthesis/M\nthespian/SM\ntheta/SM\nthew/MS\nthey\nthey'd\nthey'll\nthey're\nthey've\nthiamine/M\nthick/PMNRYXT\nthicken/DRJZG\nthickener/M\nthickening/M\nthicket/MS\nthickheaded/M\nthickness/MS\nthicko/S\nthickset\nthief/M\nthieve/DSG\nthievery/M\nthieving/M\nthievish\nthigh/M\nthighbone/MS\nthighs\nthimble/MS\nthimbleful/SM\nthin/YSP\nthine\nthing/M\nthingamabob/SM\nthingamajig/SM\nthingumabob/S\nthingummy/S\nthingy/S\nthink/SRBZG\nthinkable/U\nthinker/M\nthinking's\nthinned\nthinner/MS\nthinness/M\nthinnest\nthinning\nthird/SMY\nthirst/SGMD\nthirstily\nthirstiness/M\nthirsty/TPR\nthirteen/SMH\nthirteenth/M\nthirteenths\nthirtieth/M\nthirtieths\nthirty/HSM\nthis\nthistle/MS\nthistledown/M\nthither\ntho\nthole/SM\nthong/SM\nthoracic\nthorax/MS\nthorium/M\nthorn/SM\nthorniness/M\nthorny/PRT\nthorough/RYPT\nthoroughbred/MS\nthoroughfare/MS\nthoroughgoing\nthoroughness/M\nthose\nthou/MS\nthough\nthought/SM\nthoughtful/YP\nthoughtfulness/M\nthoughtless/PY\nthoughtlessness/M\nthousand/MHS\nthousandfold\nthousandth/M\nthousandths\nthrall/SMDG\nthralldom/M\nthrash/JMDRSZG\nthrasher/M\nthrashing/M\nthread/SMDRZG\nthreadbare\nthreader/M\nthreadlike\nthready/TR\nthreat/SMNX\nthreaten/DG\nthreatening/Y\nthree/SM\nthreefold\nthreepence/M\nthreescore/MS\nthreesome/SM\nthrenody/SM\nthresh/MDRSZG\nthresher/M\nthreshold/SM\nthrew\nthrice\nthrift/SM\nthriftily\nthriftiness/M\nthriftless\nthrifty/PTR\nthrill/SMDRZG\nthriller/M\nthrilling/Y\nthrive/DSG\nthroat/SM\nthroatily\nthroatiness/M\nthroaty/RTP\nthrob/SM\nthrobbed\nthrobbing\nthroe/SM\nthrombi\nthrombolytic\nthromboses\nthrombosis/M\nthrombotic\nthrombus/M\nthrone's\nthrone/S\nthrong/GSMD\nthrottle/DRSMZG\nthrottler/M\nthrough\nthroughout\nthroughput/M\nthrow/SMRZG\nthrowaway/SM\nthrowback/SM\nthrower/M\nthrown\nthru\nthrum/SM\nthrummed\nthrumming\nthrush/MS\nthrust/GSM\nthruway/MS\nthud/MS\nthudded\nthudding\nthug/MS\nthuggery/M\nthuggish\nthulium/M\nthumb/SMDG\nthumbnail/SM\nthumbprint/SM\nthumbscrew/SM\nthumbtack/SM\nthump/SMDG\nthumping/M\nthunder/ZGMDRS\nthunderbolt/SM\nthunderclap/SM\nthundercloud/MS\nthunderer/M\nthunderhead/SM\nthunderous/Y\nthundershower/SM\nthunderstorm/SM\nthunderstruck\nthundery\nthunk/S\nthus\nthwack/ZGSMDR\nthwacker/M\nthwart/GSMD\nthy\nthyme/M\nthymine/M\nthymus/MS\nthyroid/MS\nthyroidal\nthyself\nti/MRZ\ntiara/SM\ntibia/M\ntibiae\ntibial\ntic/SM\ntick/MDRZGS\nticker/M\nticket/GSMD\nticking/M\ntickle/DRSMZG\ntickler/M\nticklish/YP\nticklishness/M\nticktacktoe/M\nticktock/MS\ntidal/Y\ntidbit/SM\ntiddler/S\ntiddly\ntiddlywink/S\ntiddlywinks/M\ntide/MGJDS\ntideland/SM\ntidemark/S\ntidewater/MS\ntideway/MS\ntidily/U\ntidiness/UM\ntidings/M\ntidy/DRSMTGP\ntie's\ntie/AUSD\ntieback/MS\ntiebreak/RSZ\ntiebreaker/M\ntiepin/S\ntier/MD\ntiff/MDGS\ntiger/SM\ntigerish\ntight/SNRYPXT\ntighten/ZGDR\ntightener/M\ntightfisted\ntightness/M\ntightrope/MS\ntights/M\ntightwad/MS\ntigress/MS\ntil\ntilde/SM\ntile/MZGDRS\ntiler/M\ntiling/M\ntill's\ntill/EDRZGS\ntillable\ntillage/M\ntiller/EM\ntilt/MDGS\ntimber/SMDG\ntimberland/M\ntimberline/MS\ntimbre/SM\ntimbrel/SM\ntime/MYZGJDRS\ntimekeeper/MS\ntimekeeping/M\ntimeless/PY\ntimelessness/M\ntimeline/MS\ntimeliness/UM\ntimely/UPRT\ntimeout/SM\ntimepiece/MS\ntimer/M\ntimescale/S\ntimeserver/SM\ntimeserving/M\ntimeshare/S\ntimetable/DSMG\ntimeworn\ntimezone\ntimid/RYTP\ntimidity/M\ntimidness/M\ntiming/M\ntimorous/PY\ntimorousness/M\ntimothy/M\ntimpani/M\ntimpanist/SM\ntin/SM\ntincture/MGDS\ntinder/M\ntinderbox/MS\ntine/MS\ntinfoil/M\nting/MDYG\ntinge/SM\ntingeing\ntingle/DSMGJ\ntingling/M\ntininess/M\ntinker/ZGSMDR\ntinkerer/M\ntinkle/DSMG\ntinned\ntinniness/M\ntinning\ntinnitus/M\ntinny/PRT\ntinplate/M\ntinpot\ntinsel/GSMD\ntinsmith/M\ntinsmiths\ntint/MDGS\ntintinnabulation/MS\ntintype/MS\ntinware/M\ntiny/RTP\ntip/SM\ntipped\ntipper/SM\ntippet/SM\ntippex/GDS\ntipping\ntipple/DRSMZG\ntippler/M\ntipsily\ntipsiness/M\ntipster/MS\ntipsy/RPT\ntiptoe/DSM\ntiptoeing\ntiptop/SM\ntirade/SM\ntiramisu/MS\ntire's\ntire/AGDS\ntired/PRYT\ntiredness/M\ntireless/YP\ntirelessness/M\ntiresome/PY\ntiresomeness/M\ntissue/SM\ntit/SM\ntitan/SM\ntitanic\ntitanium/M\ntitch/S\ntitchy\ntithe/DRSMZG\ntither/M\ntitian/M\ntitillate/DSGN\ntitillating/Y\ntitillation/M\ntitivate/DSGN\ntitivation/M\ntitle/DSMG\ntitled/U\ntitleholder/MS\ntitlist/MS\ntitmice\ntitmouse/M\ntitter/SGMD\ntittle/SM\ntitty/S\ntitular\ntizz\ntizzy/SM\ntn\ntnpk\nto/IU\ntoad/MS\ntoadstool/MS\ntoady/DSMG\ntoadyism/M\ntoast/SMDRZG\ntoaster/M\ntoastmaster/SM\ntoastmistress/MS\ntoasty/TRS\ntobacco/MS\ntobacconist/SM\ntoboggan/ZGSMDR\ntobogganer/M\ntobogganing/M\ntoccata/S\ntocsin/SM\ntoday/M\ntoddle/DRSMZG\ntoddler/M\ntoddy/SM\ntoe/DSM\ntoecap/SM\ntoehold/MS\ntoeing\ntoenail/MS\ntoerag/S\ntoff/S\ntoffee/SM\ntofu/M\ntog/SM\ntoga/MDS\ntogether/P\ntogetherness/M\ntogged\ntogging\ntoggle/DSMG\ntogs/M\ntoil/MDRZGS\ntoiler/M\ntoilet/MDGS\ntoiletry/SM\ntoilette/M\ntoilsome\ntoke/MGDS\ntoken/SM\ntokenism/M\ntold/AU\ntole/M\ntolerable/I\ntolerably/I\ntolerance/IM\ntolerances\ntolerant/IY\ntolerate/GNDS\ntoleration/M\ntoll/MDGS\ntollbooth/M\ntollbooths\ntollgate/SM\ntollway/SM\ntoluene/M\ntom/SM\ntomahawk/SGMD\ntomato/M\ntomatoes\ntomb/MDGS\ntombola/S\ntomboy/MS\ntomboyish\ntombstone/MS\ntomcat/MS\ntome/MS\ntomfoolery/SM\ntomographic\ntomography/M\ntomorrow/MS\ntomtit/MS\nton/SM\ntonal/Y\ntonality/SM\ntone's\ntone/IZGDRS\ntonearm/SM\ntoneless/Y\ntoner/IM\ntong/MDGS\ntongue/MGDS\ntongueless\ntonic/SM\ntonight/M\ntonnage/SM\ntonne/SM\ntonsil/MS\ntonsillectomy/SM\ntonsillitis/M\ntonsorial\ntonsure/DSMG\ntony/RT\ntoo\ntook/A\ntool's\ntool/ADGS\ntoolbar/M\ntoolbox/MS\ntoolkit\ntoolmaker/MS\ntoot/MDRZGS\ntooter/M\ntooth/MD\ntoothache/MS\ntoothbrush/MS\ntoothily\ntoothless\ntoothpaste/SM\ntoothpick/SM\ntoothsome\ntoothy/RT\ntootle/GDS\ntootsie/S\ntop/SM\ntopaz/MS\ntopcoat/SM\ntopdressing/SM\ntopee/S\ntopflight\ntopi\ntopiary/M\ntopic/SM\ntopical/Y\ntopicality/M\ntopknot/SM\ntopless\ntopmast/SM\ntopmost\ntopnotch\ntopographer/SM\ntopographic\ntopographical/Y\ntopography/SM\ntopological/Y\ntopology\ntopped\ntopper/MS\ntopping/SM\ntopple/GDS\ntopsail/SM\ntopside/SM\ntopsoil/M\ntopspin/M\ntoque/SM\ntor/SM\ntorch/GMDS\ntorchbearer/MS\ntorchlight/M\ntore\ntoreador/MS\ntorment/SMDG\ntormenting/Y\ntormentor/MS\ntorn\ntornado/M\ntornadoes\ntorpedo/GMD\ntorpedoes\ntorpid/Y\ntorpidity/M\ntorpor/M\ntorque/MGDS\ntorrent/SM\ntorrential\ntorrid/YP\ntorridity/M\ntorridness/M\ntorsion/M\ntorsional\ntorso/SM\ntort's\ntort/FEAS\ntorte/SM\ntortellini/M\ntortilla/MS\ntortoise/MS\ntortoiseshell/SM\ntortoni/M\ntortuous/PY\ntortuousness/M\ntorture/DRSMZG\ntorturer/M\ntorturous\ntorus\ntosh\ntoss/MDRSZG\ntossup/MS\ntot/SGMD\ntotal/GSMDY\ntotalitarian/SM\ntotalitarianism/M\ntotality/SM\ntotalizator/SM\ntote/MS\ntotem/SM\ntotemic\ntotted\ntotter/ZGMDRS\ntotterer/M\ntotting\ntoucan/MS\ntouch/AGMDS\ntouchdown/SM\ntouche/BJ\ntouched/U\ntouchily\ntouchiness/M\ntouching/Y\ntouchline/S\ntouchpaper/S\ntouchscreen/MS\ntouchstone/MS\ntouchy/RPT\ntough/XTGMDNRYP\ntoughen/ZGDR\ntoughener/M\ntoughie/SM\ntoughness/M\ntoughs\ntoupee/MS\ntour/CFSGDM\ntourism/M\ntourist/MS\ntouristic\ntouristy\ntourmaline/M\ntournament/SM\ntourney/MS\ntourniquet/MS\ntousle/GDS\ntout/MDGS\ntow/SZGMDR\ntoward/S\ntowboat/MS\ntowel/JGSMD\ntowelette/SM\ntoweling/M\ntower/GMD\ntowhead/MDS\ntowhee/MS\ntowline/MS\ntown/MS\ntownee/S\ntownhouse/MS\ntownie/MS\ntownsfolk/M\ntownship/MS\ntownsman/M\ntownsmen\ntownspeople/M\ntownswoman/M\ntownswomen\ntowpath/M\ntowpaths\ntowrope/SM\ntoxemia/M\ntoxic\ntoxicity/SM\ntoxicological\ntoxicologist/SM\ntoxicology/M\ntoxin/SM\ntoy/SGMD\ntoyboy/S\ntr\ntrabecula\ntrabecular\ntrabecule\ntrace/JDRSMZG\ntraceable/U\ntracer/M\ntracery/SM\ntrachea/M\ntracheae\ntracheal\ntracheotomy/SM\ntracing/M\ntrack/ZGSMDR\ntrackball/SM\ntracker/M\ntrackless\ntracksuit/S\ntract's\ntract/CEKFAS\ntractability/IM\ntractable/I\ntractably/I\ntraction/EFACKM\ntractor/FCKMS\ntrad\ntrade/JDRSMZG\ntrademark/SGMD\ntrader/M\ntradesman/M\ntradesmen\ntradespeople/M\ntradeswoman/M\ntradeswomen\ntrading/M\ntradition/MS\ntraditional/Y\ntraditionalism/M\ntraditionalist/SM\ntraduce/DRSZG\ntraducer/M\ntraffic/SM\ntrafficked\ntrafficker/SM\ntrafficking/M\ntragedian/SM\ntragedienne/MS\ntragedy/SM\ntragic\ntragically\ntragicomedy/SM\ntragicomic\ntrail/ZGSMDR\ntrailblazer/MS\ntrailblazing/M\ntrailer/M\ntrain/ZGSMDRB\ntrained/U\ntrainee/SM\ntrainer/M\ntraining/M\ntrainload/MS\ntrainman/M\ntrainmen\ntrainspotter/S\ntrainspotting\ntraipse/DSMG\ntrait/SM\ntraitor/SM\ntraitorous/Y\ntrajectory/SM\ntram/MS\ntramcar/S\ntramlines\ntrammed\ntrammel/SGMD\ntrammeled/U\ntramming\ntramp/ZGSMDR\ntramper/M\ntrample/DRSMZG\ntrampler/M\ntrampoline/MGDS\ntramway/S\ntrance/MS\ntranche/S\ntranquil/RYT\ntranquility/M\ntranquilize/ZGDRS\ntranquilizer/M\ntrans/I\ntransact/DGS\ntransaction/SM\ntransactor/MS\ntransatlantic\ntransceiver/SM\ntranscend/GSD\ntranscendence/M\ntranscendent\ntranscendental/Y\ntranscendentalism/M\ntranscendentalist/SM\ntranscontinental\ntranscribe/ZGDRS\ntranscriber/M\ntranscript/MS\ntranscription/SM\ntransducer/MS\ntransect/DSG\ntransept/MS\ntransfer/MBS\ntransferal/MS\ntransference/M\ntransferred\ntransferring\ntransfiguration/M\ntransfigure/GDS\ntransfinite\ntransfix/DSG\ntransform/BSZGMDR\ntransformation/SM\ntransformer/M\ntransfuse/DSXGN\ntransfusion/M\ntransgender/S\ntransgenic\ntransgress/GDS\ntransgression/SM\ntransgressor/SM\ntransience/M\ntransiency/M\ntransient/SMY\ntransistor/SM\ntransistorize/DSG\ntransit/SGMD\ntransition/GSMD\ntransitional/Y\ntransitive/ISMY\ntransitiveness/M\ntransitivity/M\ntransitory\ntransl\ntranslatable/U\ntranslate/DSGNBX\ntranslated/U\ntranslation/M\ntranslator/SM\ntransliterate/DSGNX\ntransliteration/M\ntranslocation\ntranslucence/M\ntranslucency/M\ntranslucent/Y\ntransmigrate/GNDS\ntransmigration/M\ntransmissible\ntransmission/MS\ntransmit/S\ntransmittable\ntransmittal/M\ntransmittance/M\ntransmitted\ntransmitter/SM\ntransmitting\ntransmogrification/M\ntransmogrify/DSNG\ntransmutation/SM\ntransmute/BDSG\ntransnational/MS\ntransoceanic\ntransom/SM\ntranspacific\ntransparency/SM\ntransparent/Y\ntranspiration/M\ntranspire/DSG\ntransplant/MDGS\ntransplantation/M\ntranspolar\ntransponder/SM\ntransport/BSZGMDR\ntransportation/M\ntransporter/M\ntranspose/DSG\ntransposition/MS\ntranssexual/SM\ntranssexualism/M\ntransship/SL\ntransshipment/M\ntransshipped\ntransshipping\ntransubstantiation/M\ntransverse/MYS\ntransvestism/M\ntransvestite/MS\ntrap/MS\ntrapdoor/MS\ntrapeze/SM\ntrapezium/SM\ntrapezoid/SM\ntrapezoidal\ntrappable\ntrapped\ntrapper/SM\ntrapping/S\ntrappings/M\ntrapshooting/M\ntrash/GMDS\ntrashcan/MS\ntrashiness/M\ntrashy/RPT\ntrauma/MS\ntraumatic\ntraumatically\ntraumatize/GDS\ntravail/SGMD\ntravel/MDRSZGJ\ntraveled/U\ntraveler/M\ntraveling/M\ntravelogue/MS\ntraversal/SM\ntraverse/DSMG\ntravesty/GDSM\ntrawl/ZGSMDR\ntrawler/M\ntray/MS\ntreacherous/PY\ntreacherousness/M\ntreachery/SM\ntreacle/M\ntreacly\ntread/AGSM\ntreadle/DSMG\ntreadmill/MS\ntreas\ntreason/BM\ntreasonous\ntreasure/DRSMZG\ntreasurer/M\ntreasury/SM\ntreat/AGSMD\ntreatable\ntreated/U\ntreatise/SM\ntreatment/MS\ntreaty/SM\ntreble/MGDS\ntree/MDS\ntreeing\ntreeless\ntreelike\ntreeline\ntreetop/SM\ntrefoil/SM\ntrek/MS\ntrekked\ntrekker/SM\ntrekking\ntrellis/GMDS\ntrematode/MS\ntremble/DSMG\ntremendous/Y\ntremolo/SM\ntremor/MS\ntremulous/PY\ntremulousness/M\ntrench's\ntrench/ADSG\ntrenchancy/M\ntrenchant/Y\ntrencher/MS\ntrencherman/M\ntrenchermen\ntrend/GSMD\ntrendily\ntrendiness/M\ntrendsetter/S\ntrendsetting\ntrendy/RSMPT\ntrepidation/M\ntrespass/MDRSZG\ntrespasser/M\ntress/EMS\ntrestle/MS\ntrews\ntrey/MS\ntriad/SM\ntriage/M\ntrial/ASM\ntrialed\ntrialing\ntriangle/SM\ntriangular/Y\ntriangulate/GNDS\ntriangulation/M\ntriathlete/S\ntriathlon/SM\ntribal\ntribalism/M\ntribe/SM\ntribesman/M\ntribesmen\ntribeswoman/M\ntribeswomen\ntribulation/SM\ntribunal/SM\ntribune/MS\ntributary/SM\ntribute's\ntribute/FS\ntrice/M\ntricentennial/MS\ntriceps/MS\ntriceratops/M\ntrichina/M\ntrichinae\ntrichinosis/M\ntrick/GSMD\ntrickery/M\ntrickily\ntrickiness/M\ntrickle/MGDS\ntrickster/SM\ntricky/TRP\ntricolor/SM\ntricycle/SM\ntrident/MS\ntried/U\ntriennial/MYS\ntrier/SM\ntrifecta/SM\ntrifle/MZGDRS\ntrifler/M\ntrifocals/M\ntrig/M\ntrigger/MDSG\ntriglyceride/MS\ntrigonometric\ntrigonometrical\ntrigonometry/M\ntrike/SM\ntrilateral/S\ntrilby/SM\ntrill/GSMD\ntrillion/SMH\ntrillionth/M\ntrillionths\ntrillium/M\ntrilobite/SM\ntrilogy/SM\ntrim/PMYS\ntrimaran/MS\ntrimester/SM\ntrimmed/U\ntrimmer/SM\ntrimmest\ntrimming/SM\ntrimmings/M\ntrimness/M\ntrimonthly\ntrinitrotoluene/M\ntrinity/SM\ntrinket/SM\ntrio/MS\ntrip/MYS\ntripartite\ntripe/M\ntriple/MGDS\ntriplet/SM\ntriplex/MS\ntriplicate/MGDS\ntripod/MS\ntripodal\ntripos\ntripped\ntripper/SM\ntripping\ntriptych/M\ntriptychs\ntripwire/S\ntrireme/SM\ntrisect/SDG\ntrisection/M\ntrite/FPYT\ntriteness/FM\ntriter\ntritium/M\ntriumph/GMD\ntriumphal\ntriumphalism\ntriumphalist\ntriumphant/Y\ntriumphs\ntriumvir/MS\ntriumvirate/SM\ntrivalent\ntrivet/MS\ntrivia/M\ntrivial/Y\ntriviality/SM\ntrivialization/M\ntrivialize/GDS\ntrivium/M\ntrochaic\ntrochee/SM\ntrod/AU\ntrodden/A\ntroglodyte/SM\ntroika/MS\ntroll/SGMD\ntrolley/SM\ntrolleybus/MS\ntrollop/SM\ntrombone/MS\ntrombonist/MS\ntromp/SGD\ntron/S\ntroop/SZGMDR\ntrooper/M\ntroopship/MS\ntrope/SM\ntrophy/SM\ntropic/MS\ntropical/Y\ntropics/M\ntropism/SM\ntroposphere/SM\ntrot/MS\ntroth/M\ntrotted\ntrotter/SM\ntrotting\ntroubadour/MS\ntrouble/DSMG\ntroubled/U\ntroublemaker/MS\ntroubleshoot/DRZGS\ntroubleshooter/M\ntroubleshooting/M\ntroubleshot\ntroublesome/Y\ntrough/M\ntroughs\ntrounce/DRSZG\ntrouncer/M\ntroupe/MZGDRS\ntrouper/M\ntrouser/SM\ntrousers/M\ntrousseau/M\ntrousseaux\ntrout/SM\ntrove/SM\ntrow/DSG\ntrowel/MDSG\ntroy/S\ntruancy/M\ntruant/GMDS\ntruce/SM\ntruck/SZGMDR\ntrucker/M\ntrucking/M\ntruckle/MGDS\ntruckload/SM\ntruculence/M\ntruculent/Y\ntrudge/MGDS\ntrue/MTGDRS\ntruelove/SM\ntruffle/MS\ntrug/S\ntruism/MS\ntruly/U\ntrump/SGMD\ntrumpery/M\ntrumpet/ZGMDRS\ntrumpeter/M\ntruncate/GNDS\ntruncation/M\ntruncheon/SM\ntrundle/MZGDRS\ntrundler/M\ntrunk/SGM\ntruss/GMDS\ntrust/ESGMD\ntrustee/MS\ntrusteeship/SM\ntrustful/EY\ntrustfulness/M\ntrusting/Y\ntrustworthiness/M\ntrustworthy/TPR\ntrusty/TRSM\ntruth/UM\ntruthful/UYP\ntruthfulness/UM\ntruthiness\ntruths/U\ntry's\ntry/AGDS\ntrying/Y\ntryout/SM\ntryst/SMDG\ntsarists\ntsetse/MS\ntsp\ntsunami/SM\nttys\ntub/SZGMDR\ntuba/MS\ntubal\ntubby/TR\ntube/MS\ntubeless/M\ntuber/M\ntubercle/SM\ntubercular\ntuberculin/M\ntuberculosis/M\ntuberculous\ntuberose/M\ntuberous\ntubful/MS\ntubing/M\ntubular\ntubule/MS\ntuck/MDRSZG\ntucker/MDG\ntuft/MDRSZG\ntufter/M\ntug/SM\ntugboat/MS\ntugged\ntugging\ntuition/IM\ntularemia/M\ntulip/SM\ntulle/M\ntum/S\ntumble/DRSMZG\ntumbledown\ntumbler/M\ntumbleweed/SM\ntumbling/M\ntumbrel/SM\ntumescence/M\ntumescent\ntumid\ntumidity/M\ntummy/SM\ntumor/SM\ntumorous\ntumult/SM\ntumultuous/Y\ntun/SZGMDR\ntuna/MS\ntundra/SM\ntune/MS\ntuneful/YP\ntunefulness/M\ntuneless/Y\ntuner/M\ntuneup/SM\ntungsten/M\ntunic/SM\ntunnel/JSMDRZG\ntunneler/M\ntunny/SM\ntuple/S\ntuppence\ntuppenny\ntuque/SM\nturban/SMD\nturbid\nturbidity/M\nturbine/SM\nturbo/SM\nturbocharge/ZGDRS\nturbocharger/M\nturbofan/SM\nturbojet/SM\nturboprop/SM\nturbot/SM\nturbulence/M\nturbulent/Y\nturd/MS\nturducken/SM\ntureen/SM\nturf/MDSG\nturfy\nturgid/Y\nturgidity/M\nturkey/SM\nturmeric/SM\nturmoil/MS\nturn/AMDRSZG\nturnabout/SM\nturnaround/SM\nturnbuckle/SM\nturncoat/SM\nturner/AM\nturning/MS\nturnip/SM\nturnkey/MS\nturnoff/MS\nturnout/MS\nturnover/MS\nturnpike/MS\nturnstile/SM\nturntable/SM\nturpentine/M\nturpitude/M\nturps\nturquoise/SM\nturret/SMD\nturtle/SM\nturtledove/SM\nturtleneck/SMD\ntush/MS\ntusk/MDS\ntussle/DSMG\ntussock/MS\ntussocky\ntut/SM\ntutelage/M\ntutelary\ntutor/SMDG\ntutored/U\ntutorial/SM\ntutorship/M\ntutted\ntutti/SM\ntutting\ntutu/MS\ntux/MS\ntuxedo/SM\ntwaddle/MZGDRS\ntwaddler/M\ntwain/M\ntwang/SMDG\ntwangy/RT\ntwas\ntwat/S\ntweak/SMDG\ntwee\ntweed/SM\ntweeds/M\ntweedy/RT\ntween\ntweet/SMDRZG\ntweeter/M\ntweezers/M\ntwelfth/M\ntwelfths\ntwelve/SM\ntwelvemonth/M\ntwelvemonths\ntwentieth/M\ntwentieths\ntwenty/SMH\ntwerk/SDG\ntwerp/SM\ntwice\ntwiddle/MGDS\ntwiddly\ntwig/MS\ntwigged\ntwigging\ntwiggy/TR\ntwilight/M\ntwilit\ntwill/MD\ntwin/MDRSZG\ntwine/SM\ntwiner/M\ntwinge/DSMG\ntwink/SY\ntwinkle/MGJDS\ntwinkling/M\ntwinned\ntwinning\ntwinset/S\ntwirl/SMDRZG\ntwirler/M\ntwirly\ntwist's\ntwist/USDG\ntwister/MS\ntwisty/TR\ntwit/MS\ntwitch/GMDS\ntwitchy/RT\ntwitted\ntwitter/MDSG\ntwittery\ntwitting\ntwixt\ntwo/SM\ntwofer/SM\ntwofold\ntwopence/SM\ntwopenny\ntwosome/SM\ntwp\ntycoon/SM\ntying/AU\ntyke/MS\ntympani/M\ntympanic\ntympanist/MS\ntympanum/SM\ntype's\ntype/AGDS\ntypecast/GS\ntypeface/MS\ntypescript/MS\ntypeset/S\ntypesetter/MS\ntypesetting/M\ntypewrite/RSZG\ntypewriter/M\ntypewriting/M\ntypewritten\ntypewrote\ntyphoid/M\ntyphoon/MS\ntyphus/M\ntypical/UY\ntypicality/M\ntypification/M\ntypify/NGDS\ntyping/M\ntypist/SM\ntypo/MS\ntypographer/SM\ntypographic\ntypographical/Y\ntypography/M\ntypology/SM\ntyrannic\ntyrannical/Y\ntyrannize/GDS\ntyrannosaur/MS\ntyrannosaurus/MS\ntyrannous\ntyranny/SM\ntyrant/SM\ntyro/MS\nu/S\nubiquitous/Y\nubiquity/M\nudder/SM\nufologist/SM\nufology/M\nugh\nugliness/M\nugly/RTP\nuh\nukase/SM\nukulele/SM\nulcer/SM\nulcerate/DSGN\nulceration/M\nulcerous\nulna/M\nulnae\nulnar\nulster/MS\nult\nulterior\nultimate/MY\nultimatum/MS\nultimo\nultra/SM\nultraconservative/SM\nultrahigh\nultralight/SM\nultramarine/M\nultramodern\nultrasonic\nultrasonically\nultrasound/MS\nultraviolet/M\nululate/DSGNX\nululation/M\num\numbel/SM\number/M\numbilical\numbilici\numbilicus/M\numbra/SM\numbrage/M\numbrella/SM\numiak/SM\numlaut/MS\nump/SGMD\numpire/MGDS\numpteen/H\nunabridged/MS\nunacceptability\nunacceptable\nunaccommodating\nunaccountably\nunadventurous\nunaesthetic\nunalterably\nunambitious\nunanimity/M\nunanimous/Y\nunapparent\nunappetizing\nunappreciative\nunassertive\nunassuming/Y\nunavailing/Y\nunaware/S\nunbeknownst\nunbend/SG\nunbent\nunbid\nunblinking/Y\nunblushing/Y\nunbosom/DG\nunbound/D\nunbreakable\nunbroken\nuncanny/T\nuncap/S\nuncaring\nuncatalogued\nunceasing/Y\nunchangeable\nuncharacteristic\nuncharitable\nunchaste/RT\nuncial/M\nuncle/SM\nunclean/DRPT\nuncleanly/T\nunclear/DRT\nuncomfortable\nuncommon/T\nuncomplaining/Y\nuncomplicated\nuncomprehending/Y\nuncompromising/Y\nunconditional/Y\nuncongenial\nunconscionable\nunconscionably\nunconscious/M\nunconstitutional/Y\nuncontrollably\nuncontroversial\nuncool\nuncooperative\nuncouth/Y\nuncrushable\nunction/SM\nunctuous/YP\nunctuousness/M\nuncut\nundaunted/Y\nundecided/SM\nundemonstrative/Y\nundeniably\nunder\nunderachieve/LZGDRS\nunderachiever/M\nunderact/SDG\nunderage\nunderappreciated\nunderarm/SM\nunderbelly/SM\nunderbid/S\nunderbidding\nunderbrush/M\nundercarriage/MS\nundercharge/MGDS\nunderclass/MS\nunderclassman/M\nunderclassmen\nunderclothes/M\nunderclothing/M\nundercoat/GJSMD\nundercoating/M\nundercover\nundercurrent/SM\nundercut/SM\nundercutting\nunderdeveloped\nunderdevelopment/M\nunderdog/SM\nunderdone\nunderemployed\nunderemployment/M\nunderestimate/DSMGNX\nunderestimation/M\nunderexpose/GDS\nunderexposure/MS\nunderfed\nunderfeed/GS\nunderfloor\nunderflow\nunderfoot\nunderfunded\nunderfur/M\nundergarment/SM\nundergo/G\nundergoes\nundergone\nundergrad/S\nundergraduate/SM\nunderground/MS\nundergrowth/M\nunderhand\nunderhanded/PY\nunderhandedness/M\nunderlain\nunderlay/SM\nunderlie/S\nunderline/MGDS\nunderling/MS\nunderlip/SM\nunderlying\nundermanned\nundermentioned\nundermine/GDS\nundermost\nunderneath/M\nunderneaths\nundernourished\nundernourishment/M\nunderpaid\nunderpants/M\nunderpart/MS\nunderpass/MS\nunderpay/GSL\nunderpayment/SM\nunderpin/S\nunderpinned\nunderpinning/MS\nunderplay/DGS\nunderpopulated\nunderprivileged\nunderproduction/M\nunderrate/GDS\nunderrepresented\nunderscore/DSMG\nundersea/S\nundersecretary/SM\nundersell/GS\nundersexed\nundershirt/SM\nundershoot/SG\nundershorts/M\nundershot\nunderside/MS\nundersign/DGS\nundersigned/M\nundersized\nunderskirt/SM\nundersold\nunderstaffed\nunderstand/SGBJ\nunderstandably\nunderstanding/MY\nunderstate/DSLG\nunderstatement/SM\nunderstood\nunderstudy/GDSM\nundertake/ZGJRS\nundertaken\nundertaker/M\nundertaking/M\nunderthings/M\nundertone/MS\nundertook\nundertow/SM\nunderused\nunderutilized\nundervaluation/M\nundervalue/DSG\nunderwater\nunderway\nunderwear/M\nunderweight/M\nunderwent\nunderwhelm/DGS\nunderwire/DS\nunderworld/MS\nunderwrite/ZGRS\nunderwriter/M\nunderwritten\nunderwrote\nundesirable/MS\nundies/M\nundo\nundoubted/Y\nundramatic\nundue\nundulant\nundulate/DSXGN\nundulation/M\nundying\nunearthliness/M\nunease/M\nuneasy/T\nuneatable\nuneconomic\nunemployed/M\nunending\nunenterprising\nunequal/DY\nunerring/Y\nunessential\nuneven/Y\nunexceptionably\nunexcited\nunexciting\nunexpected/YP\nunexpectedness/M\nunfailing/Y\nunfair/PTRY\nunfaltering\nunfamiliar\nunfathomably\nunfed\nunfeeling/Y\nunfeminine\nunfit/S\nunfitting\nunfix/GDS\nunflagging/Y\nunflappability/M\nunflappable\nunflappably\nunflattering\nunflinching/Y\nunforgettably\nunforgivably\nunfortunate/MS\nunfriend/GD\nunfriendly/T\nunfrock/DG\nunfruitful\nunfunny\nungainliness/M\nungainly/RPT\nungenerous\nungentle\nungodly/T\nungraceful/Y\nungrudging\nunguarded\nunguent/SM\nungulate/MS\nunhandy/T\nunhappy/T\nunhealthful\nunhealthy/T\nunhistorical\nunholy/T\nunhurt\nunicameral\nunicellular\nunicorn/SM\nunicycle/SM\nunidirectional\nunification/AM\nuniform/SMDYG\nuniformity/M\nunify/AGDSN\nunilateral/Y\nunilateralism\nunimportant\nunimpressive\nuninformative\nuninhibited/Y\nuninstall/BSZGDR\nuninsured\nunintelligent\nunintended\nuninteresting\nuninterrupted/Y\nuninterruptible\nuninviting\nunion/ASM\nunionism/M\nunionist/MS\nunique/YTRP\nuniqueness/M\nunisex/M\nunison/M\nunitary\nunite/AEGSD\nunitedly\nunities\nunitize/DSG\nunity/EM\nunivalent\nunivalve/SM\nuniversal/MYS\nuniversality/M\nuniversalize/DSG\nuniverse/SM\nuniversity/SM\nunjust/Y\nunkempt\nunkind/T\nunkindly/T\nunknowable/M\nunknown/SM\nunleaded/M\nunless\nunlike/PB\nunlikely/T\nunlit\nunlock/DSG\nunlovable\nunlovely/TR\nunloving\nunlucky/T\nunmanly/T\nunmarried\nunmeaning\nunmentionable/MS\nunmentionables/M\nunmet\nunmindful\nunmissable\nunmistakably\nunmoral\nunmovable\nunmusical\nunnecessary\nunnerving/Y\nunobservant\nunoffensive\nunofficial/Y\nunoriginal\nunpeople\nunperceptive\nunpersuasive\nunpick/GDS\nunpin/S\nunpleasing\nunpolitical\nunpopular\nunpractical\nunprecedented/Y\nunprofessional/Y\nunpromising\nunpropitious\nunquestioning/Y\nunquiet/TR\nunread/B\nunready\nunreal\nunreasoning\nunregenerate\nunrelated\nunrelenting/Y\nunrelieved/Y\nunremarkable\nunremitting/Y\nunrepentant\nunreported\nunrepresentative\nunrest/M\nunripe/TR\nunroll/GDS\nunromantic\nunruliness/M\nunruly/RTP\nunsafe/YTR\nunsaleable\nunsavory\nunscathed\nunsearchable\nunseeing/Y\nunseemly/T\nunseen/M\nunsentimental\nunset\nunshakable\nunshakably\nunshapely\nunshockable\nunshorn\nunsightliness/M\nunsightly/PT\nunsmiling\nunsociable\nunsocial\nunsold\nunsound/PRYT\nunspeakable\nunspeakably\nunspecific\nunspectacular\nunsporting\nunstable\nunsteady/TRP\nunstinting/Y\nunstrapping\nunsubstantial\nunsubtle\nunsuitable\nunsure\nunsuspecting/Y\nunsymmetrical\nuntactful\nunthinkably\nunthinking/Y\nuntidy/PTR\nuntil\nuntimely/T\nuntiring/Y\nuntouchable/MS\nuntoward\nuntrue/RT\nuntrustworthy\nunutterable\nunutterably\nunwarrantable\nunwary/T\nunwavering\nunwed\nunwelcome/G\nunwell\nunwieldiness/M\nunwieldy/TRP\nunwise/RYT\nunworried\nunworthy/T\nunwound\nunwrapping\nunyielding\nup/S\nupbeat/MS\nupbraid/SGD\nupbringing/MS\nupchuck/SGD\nupcoming\nupcountry/M\nupdate/MGDRS\nupdraft/MS\nupend/SGD\nupfront\nupgrade/MGDS\nupheaval/MS\nupheld\nuphill/MS\nuphold/ZGRS\nupholder/M\nupholster/ASGD\nupholsterer/MS\nupholstery/M\nupkeep/M\nupland/MS\nuplift/JSMDG\nupload/SDG\nupmarket\nupon\nupped\nupper/SM\nuppercase/M\nupperclassman/M\nupperclassmen\nupperclasswoman\nupperclasswomen\nuppercut/MS\nuppercutting\nuppermost\nupping\nuppish\nuppity\nupraise/DSG\nuprear/GSD\nupright/MYPS\nuprightness/M\nuprising/SM\nupriver\nuproar/SM\nuproarious/Y\nuproot/GSD\nupscale\nupset/SM\nupsetting\nupshot/SM\nupside/SM\nupsilon/MS\nupstage/GDS\nupstairs\nupstanding\nupstart/MDSG\nupstate/M\nupstream\nupstroke/SM\nupsurge/MGDS\nupswing/MS\nuptake/SM\nuptempo\nupthrust/GSM\nuptick/SM\nuptight\nuptown/M\nuptrend\nupturn/GSMD\nupward/SY\nupwind\nuracil/M\nuranium/M\nurban\nurbane/RYT\nurbanity/M\nurbanization/M\nurbanize/DSG\nurbanologist/MS\nurbanology/M\nurchin/SM\nurea/M\nuremia/M\nuremic\nureter/SM\nurethane/M\nurethra/M\nurethrae\nurethral\nurge/MGDS\nurgency/M\nurgent/Y\nuric\nurinal/SM\nurinalyses\nurinalysis/M\nurinary\nurinate/GNDS\nurination/M\nurine/M\nurn/SM\nurogenital\nurological\nurologist/MS\nurology/M\nursine\nurticaria/M\nusability/M\nusable/UA\nusage/SM\nuse/AEDSMG\nused/U\nuseful/PY\nusefulness/M\nuseless/YP\nuselessness/M\nuser/MS\nusername/S\nusher/SMDG\nusherette/SM\nusu\nusual's\nusual/UY\nusurer/SM\nusurious\nusurp/SDRZG\nusurpation/M\nusurper/M\nusury/M\nutensil/SM\nuteri\nuterine\nuterus/M\nutilitarian/MS\nutilitarianism/M\nutility/SM\nutilization/M\nutilize/GBDS\nutmost/M\nutopia/SM\nutter/SDYG\nutterance/SM\nuttermost/M\nuveitis\nuvula/SM\nuvular/MS\nuxorious\nv/AS\nvac/S\nvacancy/SM\nvacant/Y\nvacate/DSG\nvacation/ZGMDRS\nvacationer/M\nvacationist/SM\nvaccinate/GNDSX\nvaccination/M\nvaccine/SM\nvacillate/XGNDS\nvacillation/M\nvacuity/M\nvacuole/MS\nvacuous/YP\nvacuousness/M\nvacuum/GSMD\nvagabond/SMDG\nvagabondage/M\nvagarious\nvagary/SM\nvagina/SM\nvaginae\nvaginal/Y\nvagrancy/M\nvagrant/MS\nvague/RYTP\nvagueness/M\nvagus\nvain/RYT\nvainglorious/Y\nvainglory/M\nval\nvalance/MS\nvale/MS\nvalediction/MS\nvaledictorian/SM\nvaledictory/SM\nvalence/MS\nvalency/SM\nvalentine/SM\nvalet/SMDG\nvaletudinarian/MS\nvaletudinarianism/M\nvaliance/M\nvaliant/Y\nvalid/Y\nvalidate/IGNDS\nvalidation/IM\nvalidations\nvalidity/IM\nvalidness/M\nvalise/SM\nvalley/SM\nvalor/M\nvalorous/Y\nvaluable/MS\nvaluate/DSG\nvaluation/CAMS\nvalue's\nvalue/CAGSD\nvalueless\nvaluer/SM\nvalve/DSMG\nvalveless\nvalvular\nvamoose/DSG\nvamp/AMDGS\nvampire/SM\nvan/SM\nvanadium/M\nvandal/SM\nvandalism/M\nvandalize/DSG\nvane/MS\nvanguard/MS\nvanilla/SM\nvanish/JDSG\nvanity/SM\nvanned\nvanning\nvanquish/ZGDRS\nvanquisher/M\nvantage/SM\nvape/GDS\nvapid/YP\nvapidity/M\nvapidness/M\nvapor/SM\nvaporization/M\nvaporize/DRSZG\nvaporizer/M\nvaporous\nvaporware\nvapory\nvaquero/MS\nvar/S\nvariability/IM\nvariable/ISM\nvariably/I\nvariance/SM\nvariant/MS\nvariate/NX\nvariation/M\nvaricolored\nvaricose\nvaried/U\nvariegate/DSGN\nvariegation/M\nvarietal/SM\nvariety/SM\nvarious/Y\nvarlet/SM\nvarmint/MS\nvarnish/GMDS\nvarnished/U\nvarsity/SM\nvary/DSG\nvarying/U\nvascular\nvase/MS\nvasectomy/SM\nvasoconstriction\nvasomotor\nvassal/SM\nvassalage/M\nvast/MRYTSP\nvastness/M\nvat/SM\nvatted\nvatting\nvaudeville/M\nvaudevillian/MS\nvault/SMDRZG\nvaulter/M\nvaulting/M\nvaunt/SMDG\nvb\nveal/M\nvector/SGMD\nveejay/SM\nveep/MS\nveer/MDGS\nveg/M\nvegan/SM\nveganism\nvegeburger/S\nveges\nvegetable/SM\nvegetarian/SM\nvegetarianism/M\nvegetate/GNVDS\nvegetation/M\nvegged\nvegges\nveggie/SM\nveggieburger/S\nvegging\nvehemence/M\nvehemency/M\nvehement/Y\nvehicle/MS\nvehicular\nveil's\nveil/UDGS\nvein/MDGS\nvela\nvelar/SM\nveld/MS\nvellum/M\nvelocipede/MS\nvelocity/SM\nvelodrome/S\nvelour/MS\nvelum/M\nvelvet/M\nvelveteen/M\nvelvety\nvenal/Y\nvenality/M\nvenation/M\nvend/DGS\nvendetta/SM\nvendible\nvendor/MS\nveneer/MDGS\nvenerability/M\nvenerable\nvenerate/DSGN\nveneration/M\nvenereal\nvengeance/M\nvengeful/AY\nvenial\nvenireman/M\nveniremen\nvenison/M\nvenom/M\nvenomous/Y\nvenous\nvent's\nvent/DGS\nventilate/GNDS\nventilation/M\nventilator/SM\nventral\nventricle/SM\nventricular\nventriloquism/M\nventriloquist/SM\nventriloquy/M\nventure/DSMG\nventuresome/PY\nventuresomeness/M\nventurous/PY\nventurousness/M\nvenue/ASM\nveracious/Y\nveracity/M\nveranda/SM\nverb/KMS\nverbal/MYS\nverbalization/M\nverbalize/GDS\nverbatim\nverbena/SM\nverbiage/MS\nverbose/Y\nverbosity/M\nverboten\nverdant/Y\nverdict/SM\nverdigris/GMDS\nverdure/M\nverge's\nverge/FDSG\nverger/MS\nverifiable/U\nverification/M\nverified/U\nverify/DSNG\nverily\nverisimilitude/M\nveritable\nveritably\nverity/SM\nvermicelli/M\nvermiculite/M\nvermiform\nvermilion/M\nvermin/M\nverminous\nvermouth/M\nvernacular/MS\nvernal\nvernier/SM\nveronica/M\nverruca/SM\nverrucae\nversa\nversatile\nversatility/M\nverse/AFNGMSDX\nversed/U\nversification/M\nversifier/M\nversify/ZGNDRS\nversion/AFIMS\nversioned\nversioning\nverso/SM\nversus\nvert/A\nvertebra/M\nvertebrae\nvertebral\nvertebrate/IMS\nvertex/MS\nvertical/MYS\nvertices\nvertiginous\nvertigo/M\nverve/M\nvery/RT\nvesicle/SM\nvesicular\nvesiculate\nvesper/MS\nvessel/MS\nvest's\nvest/ILDGS\nvestal/MS\nvestibule/MS\nvestige/SM\nvestigial/Y\nvesting/M\nvestment/IMS\nvestry/SM\nvestryman/M\nvestrymen\nvet/SM\nvetch/MS\nveteran/SM\nveterinarian/MS\nveterinary/SM\nveto/MDG\nvetoes\nvetted\nvetting\nvex/GDS\nvexation/SM\nvexatious/Y\nvhf\nvi\nvia\nviability/M\nviable\nviably\nviaduct/SM\nvial/MS\nviand/SM\nvibe/MS\nvibes/M\nvibraharp/SM\nvibrancy/M\nvibrant/Y\nvibraphone/MS\nvibraphonist/MS\nvibrate/GNDSX\nvibration/M\nvibrato/MS\nvibrator/SM\nvibratory\nviburnum/SM\nvicar/SM\nvicarage/SM\nvicarious/YP\nvicariousness/M\nvice/CMS\nviced\nvicegerent/SM\nvicennial\nviceregal\nviceroy/MS\nvichyssoise/M\nvicing\nvicinity/M\nvicious/YP\nviciousness/M\nvicissitude/SM\nvictim/MS\nvictimization/M\nvictimize/GDS\nvictor/MS\nvictorious/Y\nvictory/SM\nvictual/SMDG\nvicuna/MS\nvidelicet\nvideo/GSMD\nvideocassette/SM\nvideoconferencing\nvideodisc/MS\nvideophone/MS\nvideotape/DSMG\nvideotex\nvie/DS\nview/AMDRSZG\nviewer/AM\nviewership/M\nviewfinder/SM\nviewing/SM\nviewpoint/MS\nvigesimal\nvigil/SM\nvigilance/M\nvigilant/Y\nvigilante/SM\nvigilantism/M\nvigilantist/M\nvignette/DSMG\nvignettist/MS\nvigor/M\nvigorous/Y\nvii\nviii\nviking/MS\nvile/YTPR\nvileness/M\nvilification/M\nvilify/DSNG\nvilla/SM\nvillage/RSMZ\nvillager/M\nvillain/SM\nvillainous\nvillainy/SM\nvillein/SM\nvilleinage/M\nvilli\nvillus/M\nvim/M\nvinaigrette/M\nvincible/I\nvindicate/XDSGN\nvindication/M\nvindicator/MS\nvindictive/PY\nvindictiveness/M\nvine/MS\nvinegar/M\nvinegary\nvineyard/MS\nvino/M\nvinous\nvintage/MS\nvintner/MS\nvinyl/SM\nviol/MBS\nviola/SM\nviolable/I\nviolate/GNDSX\nviolation/M\nviolator/SM\nviolence/M\nviolent/Y\nviolet/MS\nviolin/MS\nviolincello/S\nviolinist/SM\nviolist/MS\nvioloncellist/SM\nvioloncello/MS\nviper/SM\nviperous\nvirago/M\nviragoes\nviral\nvireo/SM\nvirgin/MS\nvirginal/SM\nvirginity/M\nvirgule/MS\nvirile\nvirility/M\nvirologist/SM\nvirology/M\nvirtual/Y\nvirtualization\nvirtue/SM\nvirtuosity/M\nvirtuoso/M\nvirtuous/YP\nvirtuousness/M\nvirulence/M\nvirulent/Y\nvirus/MS\nvisa/MDSG\nvisage/MS\nviscera\nvisceral/Y\nviscid\nviscose/M\nviscosity/M\nviscount/SM\nviscountcy/SM\nviscountess/MS\nviscous\nviscus/M\nvise/ACMGDS\nvisibility/IM\nvisible/I\nvisibly/I\nvision/KGDSM\nvisionary/SM\nvisit's\nvisit/ASGD\nvisitant/MS\nvisitation/MS\nvisitor/MS\nvisor/SM\nvista/SM\nvisual/SMY\nvisualization/SM\nvisualize/DRSZG\nvisualizer/M\nvita/M\nvitae\nvital/SY\nvitality/M\nvitalization/AM\nvitalize/CAGSD\nvitals/M\nvitamin/MS\nvitiate/GNDS\nvitiation/M\nviticulture/M\nviticulturist/MS\nvitreous\nvitrifaction/M\nvitrification/M\nvitrify/GNDS\nvitrine/SM\nvitriol/M\nvitriolic\nvitriolically\nvittles/M\nvituperate/GNVDS\nvituperation/M\nviva/MS\nvivace\nvivacious/PY\nvivaciousness/M\nvivacity/M\nvivaria\nvivarium/SM\nvivid/RYTP\nvividness/M\nvivify/ADSG\nviviparous\nvivisect/DGS\nvivisection/M\nvivisectional\nvivisectionist/SM\nvixen/SM\nvixenish/Y\nviz\nvizier/SM\nvocab\nvocable/MS\nvocabulary/SM\nvocal/SMY\nvocalic\nvocalist/SM\nvocalization/MS\nvocalize/DSG\nvocation/FIKASM\nvocational/Y\nvocative/MS\nvociferate/DSGN\nvociferation/M\nvociferous/YP\nvociferousness/M\nvodka/SM\nvogue/SM\nvoguish\nvoice/IDSMG\nvoiced/U\nvoiceless/PY\nvoicelessness/M\nvoicemail/M\nvoid/MDSGB\nvoila\nvoile/M\nvol/S\nvolatile\nvolatility/M\nvolatilize/DSG\nvolcanic\nvolcano/M\nvolcanoes\nvole/MS\nvolition/M\nvolitional\nvolley/GSMD\nvolleyball/MS\nvolt/AMS\nvoltage/MS\nvoltaic\nvoltmeter/SM\nvolubility/M\nvoluble\nvolubly\nvolume/SM\nvoluminous/YP\nvoluminousness/M\nvoluntarily/I\nvoluntarism/M\nvoluntary/SM\nvolunteer/SGMD\nvolunteerism/M\nvoluptuary/SM\nvoluptuous/PY\nvoluptuousness/M\nvolute/SM\nvomit/SMDG\nvoodoo/GSMD\nvoodooism/M\nvoracious/PY\nvoraciousness/M\nvoracity/M\nvortex/MS\nvotary/SM\nvote's\nvote/CGVDS\nvoter/SM\nvouch/DRSZG\nvoucher/M\nvouchsafe/DSG\nvow/SGMD\nvowel/SM\nvoyage/MZGDRS\nvoyager/M\nvoyageur/SM\nvoyeur/MS\nvoyeurism/M\nvoyeuristic\nvulcanization/M\nvulcanize/GDS\nvulgar/RYT\nvulgarian/MS\nvulgarism/MS\nvulgarity/SM\nvulgarization/M\nvulgarize/ZGDRS\nvulgarizer/M\nvulnerabilities\nvulnerability/IM\nvulnerable/I\nvulnerably/I\nvulpine\nvulture/SM\nvulturous\nvulva/M\nvulvae\nvuvuzela/MS\nvying\nw/DNXTGVJ\nwabbit/S\nwack/RTS\nwackiness/M\nwacko/SM\nwacky/RPT\nwad/SZGMDR\nwadded\nwadding/M\nwaddle/DSMG\nwade/MS\nwader/M\nwaders/M\nwadge/S\nwadi/MS\nwafer/SM\nwaffle/MZGDRS\nwaffler/M\nwaft/MDGS\nwag/SZGMDR\nwage/MS\nwaged/U\nwager/ZGMDR\nwagerer/M\nwagged\nwaggery/SM\nwagging\nwaggish/YP\nwaggishness/M\nwaggle/MGDS\nwagon/ZSMR\nwagoner/M\nwagtail/SM\nwaif/MS\nwail/MDRZGS\nwailer/M\nwailing/M\nwain/MS\nwainscot/SJMDG\nwainscoting/M\nwainwright/MS\nwaist/SM\nwaistband/MS\nwaistcoat/MS\nwaistline/MS\nwait/MDRZGS\nwaiter/M\nwaiting/M\nwaitperson/MS\nwaitress/MS\nwaitstaff/M\nwaive/DRSZG\nwaiver/M\nwake/MGJDS\nwakeful/PY\nwakefulness/M\nwaken/GSD\nwaldo/S\nwaldoes\nwale/MGDS\nwalk/MDRZGS\nwalkabout/S\nwalkaway/MS\nwalker/M\nwalkies\nwalking/M\nwalkout/SM\nwalkover/MS\nwalkway/SM\nwall/MDGS\nwallaby/SM\nwallah\nwallahs\nwallboard/M\nwallet/MS\nwalleye/DSM\nwallflower/MS\nwallop/MDSJG\nwalloping/M\nwallow/MDSG\nwallpaper/SMDG\nwally/S\nwalnut/MS\nwalrus/MS\nwaltz/ZGMDRS\nwaltzer/M\nwampum/M\nwan/GPDY\nwand/MS\nwander/DRSJZG\nwanderer/M\nwanderings/M\nwanderlust/SM\nwane/MS\nwangle/MZGDRS\nwangler/M\nwank/DRZGS\nwanna\nwannabe/SM\nwannabee/S\nwanner\nwanness/M\nwannest\nwant/MDGS\nwanted/U\nwanton/MDYSPG\nwantonness/M\nwapiti/MS\nwar/SM\nwarble/MZGDRS\nwarbler/M\nwarbonnet/SM\nward/AMDGS\nwarden/MS\nwarder/MS\nwardress/S\nwardrobe/SM\nwardroom/SM\nware/MS\nwarehouse/DSMG\nwarez\nwarfare/M\nwarhead/MS\nwarhorse/SM\nwarily/U\nwariness/UM\nwarlike\nwarlock/MS\nwarlord/MS\nwarm/PDRYHZTGS\nwarmblooded\nwarmer/M\nwarmhearted/P\nwarmheartedness/M\nwarmish\nwarmness/M\nwarmonger/SMG\nwarmongering/M\nwarmth/M\nwarn/JDGS\nwarning/M\nwarp/MDGS\nwarpaint\nwarpath/M\nwarpaths\nwarplane/MS\nwarrant/GMDS\nwarranted/U\nwarranty/DSMG\nwarred\nwarren/MS\nwarring\nwarrior/SM\nwarship/SM\nwart/MS\nwarthog/SM\nwartime/M\nwarty/TR\nwary/UPRT\nwas\nwasabi\nwash/BMDRSZG\nwashable/SM\nwashbasin/SM\nwashboard/SM\nwashbowl/SM\nwashcloth/M\nwashcloths\nwashed/U\nwasher/M\nwasherwoman/M\nwasherwomen\nwashing/M\nwashout/MS\nwashrag/MS\nwashroom/MS\nwashstand/SM\nwashtub/MS\nwashy/TR\nwasn't\nwasp/MS\nwaspish/YP\nwaspishness/M\nwassail/SMDG\nwast\nwastage/M\nwaste/DRSMZG\nwastebasket/MS\nwasteful/PY\nwastefulness/M\nwasteland/SM\nwastepaper/M\nwaster/M\nwastewater\nwastrel/SM\nwatch/BZGMDRS\nwatchable/U\nwatchband/MS\nwatchdog/SM\nwatcher/M\nwatchful/YP\nwatchfulness/M\nwatchmaker/MS\nwatchmaking/M\nwatchman/M\nwatchmen\nwatchstrap/S\nwatchtower/SM\nwatchword/MS\nwater/GSMD\nwaterbed/MS\nwaterbird/SM\nwaterboard/DJSG\nwaterborne\nwatercolor/MS\nwatercourse/SM\nwatercraft/M\nwatercress/M\nwaterfall/SM\nwaterfowl/SM\nwaterfront/MS\nwaterhole/SM\nwateriness/M\nwaterlily/SM\nwaterline/MS\nwaterlogged\nwatermark/MDGS\nwatermelon/SM\nwatermill/MS\nwaterproof/SMDG\nwaterproofing/M\nwaters/M\nwatershed/MS\nwaterside/MS\nwaterspout/SM\nwatertight\nwaterway/MS\nwaterwheel/SM\nwaterworks/M\nwatery/PTR\nwatt/MS\nwattage/M\nwattle/MGDS\nwave/MZGDRS\nwaveband/S\nwaveform\nwavelength/M\nwavelengths\nwavelet/SM\nwavelike\nwaver/ZGMDR\nwaverer/M\nwavering/Y\nwaviness/M\nwavy/PRT\nwax/GMDNS\nwaxiness/M\nwaxwing/SM\nwaxwork/SM\nwaxy/RPT\nway/SM\nwaybill/SM\nwayfarer/MS\nwayfaring/SM\nwaylaid\nwaylay/RSZG\nwaylayer/M\nwayside/SM\nwayward/PY\nwaywardness/M\nwazoo/S\nwe\nwe'd\nwe'll\nwe're\nwe've\nweak/PNRYXT\nweaken/DRZG\nweakener/M\nweakfish/MS\nweakish\nweakling/SM\nweakness/MS\nweal/MHS\nwealth/M\nwealthiness/M\nwealthy/TRP\nwean/DGS\nweapon/MS\nweaponize\nweaponless\nweaponry/M\nwear/MRBJSZG\nwearable/U\nwearer/M\nwearied/U\nwearily\nweariness/M\nwearisome/Y\nweary/TGDRSP\nweasel/MDYSG\nweather/SMDG\nweatherboard/SG\nweathercock/MS\nweathering/M\nweatherization/M\nweatherize/DSG\nweatherman/M\nweathermen\nweatherperson/MS\nweatherproof/GSD\nweatherstrip/S\nweatherstripped\nweatherstripping/M\nweave/DRSMZG\nweaver/M\nweaving/M\nweb/SM\nwebbed\nwebbing/M\nwebcam/MS\nwebcast/SMG\nwebfeet\nwebfoot/M\nwebinar/SM\nwebisode/MS\nweblog/MS\nwebmaster/SM\nwebmistress/MS\nwebpage/SM\nwebsite/SM\nwed/AS\nwedded/A\nwedder\nwedding/SM\nwedge/DSMG\nwedgie/MS\nwedlock/M\nwee/RSMT\nweed/MDRSZG\nweeder/M\nweedkiller/S\nweedless\nweedy/TR\nweeing\nweek/MYS\nweekday/SM\nweekend/SZGMDR\nweekly/SM\nweeknight/SM\nween/DSG\nweenie/MTRS\nweensy/RT\nweeny\nweep/MRJSZG\nweeper/M\nweepie\nweepy/TRSM\nweevil/MS\nweft/MS\nweigh's\nweigh/AGD\nweighbridge/S\nweighs/A\nweight/MDSJG\nweighted/U\nweightily\nweightiness/M\nweightless/YP\nweightlessness/M\nweightlifter/MS\nweightlifting/M\nweighty/PTR\nweir/MS\nweird/PTRY\nweirdie/MS\nweirdness/M\nweirdo/MS\nwelcome/MGDS\nweld/MDRBSZG\nwelder/M\nwelfare/M\nwelkin/M\nwell/MDPSG\nwellhead/SM\nwellie\nwellington/MS\nwellness/M\nwellspring/MS\nwelly/S\nwelsh/ZGDRS\nwelsher/M\nwelt/MDRSZG\nwelter/GMD\nwelterweight/SM\nwen/M\nwench/MS\nwend/DSG\nwent\nwept\nwere\nweren't\nwerewolf/M\nwerewolves\nwest/M\nwestbound\nwesterly/SM\nwestern/SZMR\nwesterner/M\nwesternization/M\nwesternize/GDS\nwesternmost\nwestward/S\nwet/SMYP\nwetback/SM\nwetland/SM\nwetness/M\nwetter/SM\nwettest\nwetting\nwetware/S\nwhack/SJZGMDR\nwhacker/M\nwhale/DRSMZG\nwhaleboat/MS\nwhalebone/M\nwhaler/M\nwhaling/M\nwham/MS\nwhammed\nwhamming\nwhammy/SM\nwharf/M\nwharves\nwhat/MS\nwhatchamacallit/MS\nwhatever\nwhatnot/M\nwhatshername\nwhatshisname\nwhatsit/S\nwhatsoever\nwheal/SM\nwheat/MN\nwheatgerm\nwheatmeal\nwhee\nwheedle/DRSZG\nwheedler/M\nwheel/SMDRG\nwheelbarrow/SM\nwheelbase/SM\nwheelchair/SM\nwheelhouse/MS\nwheelie/SM\nwheelwright/MS\nwheeze/DSMG\nwheezily\nwheeziness/M\nwheezy/PRT\nwhelk/SMD\nwhelm/SDG\nwhelp/SMDG\nwhen/MS\nwhence\nwhenever\nwhensoever\nwhere/SM\nwhereabouts/M\nwhereas\nwhereat\nwhereby\nwherefore/MS\nwherein\nwhereof\nwhereon\nwheresoever\nwhereto\nwhereupon\nwherever\nwherewith\nwherewithal/M\nwherry/SM\nwhet/S\nwhether\nwhetstone/SM\nwhetted\nwhetting\nwhew\nwhey/M\nwhich\nwhichever\nwhiff/SMDG\nwhiffletree/MS\nwhile/DSMG\nwhilom\nwhilst\nwhim/MS\nwhimper/MDGS\nwhimsical/Y\nwhimsicality/M\nwhimsy/SM\nwhine/DRSMZG\nwhiner/M\nwhinge/DRSZG\nwhingeing\nwhinny/GDSM\nwhiny/RT\nwhip/MS\nwhipcord/M\nwhiplash/MS\nwhipped\nwhipper/MS\nwhippersnapper/MS\nwhippet/MS\nwhipping/SM\nwhippletree/SM\nwhippoorwill/MS\nwhipsaw/MDGS\nwhir/MS\nwhirl/SMDG\nwhirligig/MS\nwhirlpool/MS\nwhirlwind/MS\nwhirlybird/SM\nwhirred\nwhirring\nwhisk/SMDRZG\nwhisker/MD\nwhiskery\nwhiskey/MS\nwhiskys\nwhisper/MDRSZG\nwhisperer/M\nwhist/M\nwhistle/MZGDRS\nwhistler/M\nwhit/MDNRSXTGJ\nwhite/SPM\nwhitebait\nwhiteboard/S\nwhitecap/SM\nwhitefish/MS\nwhitehead/MS\nwhiten/ZGDRJ\nwhitener/M\nwhiteness/M\nwhitening/M\nwhiteout/SM\nwhitetail/MS\nwhitewall/SM\nwhitewash/MDSG\nwhitewater/M\nwhitey/SM\nwhither\nwhiting/M\nwhitish\nwhittle/ZGDRS\nwhittler/M\nwhiz/M\nwhizkid/M\nwhizzbang/MS\nwhizzed\nwhizzes\nwhizzing\nwho'd\nwho'll\nwho're\nwho've\nwho/M\nwhoa\nwhodunit/MS\nwhoever\nwhole/SMP\nwholefood/S\nwholegrain\nwholehearted/YP\nwholeheartedness/M\nwholemeal\nwholeness/M\nwholesale/MZGDRS\nwholesaler/M\nwholesome/UP\nwholesomely\nwholesomeness/UM\nwholewheat\nwholly\nwhom\nwhomever\nwhomsoever\nwhoop/SMDRZG\nwhoopee/S\nwhooper/M\nwhoosh/MDSG\nwhop/S\nwhopped\nwhopper/SM\nwhopping\nwhore/SMG\nwhorehouse/MS\nwhoreish\nwhorish\nwhorl/SMD\nwhose\nwhoso\nwhosoever\nwhup/S\nwhupped\nwhupping\nwhy'd\nwhy/M\nwhys\nwick/MDRSZ\nwicked/TPRY\nwickedness/M\nwicker/M\nwickerwork/M\nwicket/SM\nwide/YTRP\nwidemouthed\nwiden/SDRZG\nwidener/M\nwideness/M\nwidescreen/S\nwidespread\nwidget/S\nwidow/SMDRZG\nwidower/M\nwidowhood/M\nwidth/M\nwidths\nwield/SDRZG\nwielder/M\nwiener/SM\nwienie/SM\nwife/MY\nwifeless\nwig/SM\nwigeon/M\nwigged\nwigging\nwiggle/DRSMZG\nwiggler/M\nwiggly/TR\nwight/SM\nwiglet/SM\nwigwag/SM\nwigwagged\nwigwagging\nwigwam/SM\nwiki/MS\nwild/MRYSTP\nwildcard\nwildcat/MS\nwildcatted\nwildcatter/MS\nwildcatting\nwildebeest/MS\nwilderness/MS\nwildfire/MS\nwildflower/SM\nwildfowl/M\nwildlife/M\nwildness/M\nwilds/M\nwile/MGDS\nwiliness/M\nwill/MDS\nwillful/PY\nwillfulness/M\nwillies/M\nwilling/UPY\nwillingness/UM\nwilliwaw/MS\nwillow/SM\nwillowy\nwillpower/M\nwilly/S\nwilt/MDSG\nwily/RTP\nwimp/MDSG\nwimpish\nwimple/DSMG\nwimpy/RT\nwin/SGMD\nwince/DSMG\nwinch/MDSG\nwind's\nwind/UASG\nwindbag/SM\nwindblown\nwindbreak/SZMR\nwindbreaker/M\nwindburn/MD\nwindcheater/S\nwindchill/M\nwinded\nwinder/SM\nwindfall/MS\nwindflower/MS\nwindily\nwindiness/M\nwinding's\nwindjammer/SM\nwindlass/MS\nwindless\nwindmill/MDGS\nwindow/SMDG\nwindowless\nwindowpane/SM\nwindowsill/SM\nwindpipe/MS\nwindproof\nwindrow/SM\nwindscreen/SM\nwindshield/SM\nwindsock/MS\nwindstorm/MS\nwindsurf/ZGDRS\nwindsurfer/M\nwindsurfing/M\nwindswept\nwindup/SM\nwindward/M\nwindy/RTP\nwine/MS\nwineglass/MS\nwinegrower/MS\nwinemaker/MS\nwinery/SM\nwing/MDRZG\nwingding/MS\nwingless\nwinglike\nwingnut/SM\nwingspan/MS\nwingspread/SM\nwingtip/SM\nwink/MDRSZG\nwinker/M\nwinkle/DSMG\nwinnable/U\nwinner/SM\nwinning/MYS\nwinnow/ZGSDR\nwinnower/M\nwino/MS\nwinsome/YTRP\nwinsomeness/M\nwinter/GSMD\nwintergreen/M\nwinterize/GDS\nwintertime/M\nwintry/TR\nwiny/RT\nwipe/MZGDRS\nwiper/M\nwire's\nwire/AGDS\nwired/S\nwirehair/MS\nwireless/MS\nwiretap/MS\nwiretapped\nwiretapper/SM\nwiretapping/M\nwiriness/M\nwiring/M\nwiry/RTP\nwisdom/M\nwise/MYTGDRS\nwiseacre/SM\nwisecrack/MDSG\nwiseguy/S\nwish/MDRSZG\nwishbone/SM\nwisher/M\nwishful/Y\nwishlist/SM\nwisp/MS\nwispy/RT\nwist\nwisteria/SM\nwistful/YP\nwistfulness/M\nwit/SM\nwitch/MDSG\nwitchcraft/M\nwitchery/M\nwith\nwithal\nwithdraw/SG\nwithdrawal/MS\nwithdrawn\nwithdrew\nwithe/DRSMZG\nwither/JGD\nwithering/Y\nwithers/M\nwithheld\nwithhold/SG\nwithholding/M\nwithin/M\nwithout\nwithstand/GS\nwithstood\nwitless/PY\nwitlessness/M\nwitness/MDSG\nwits/M\nwitted\nwitter/SGD\nwitticism/SM\nwittily\nwittiness/M\nwitting/UY\nwitty/RPT\nwive/GDS\nwiz\nwizard/SMY\nwizardry/M\nwizened\nwk/Y\nwoad/M\nwobble/MGDS\nwobbliness/M\nwobbly/RTP\nwodge/S\nwoe/SM\nwoebegone\nwoeful/YP\nwoefuller\nwoefullest\nwoefulness/M\nwog/S\nwok/SMN\nwoke\nwold/MS\nwolf/MDSG\nwolfhound/SM\nwolfish\nwolfram/M\nwolverine/SM\nwolves\nwoman/M\nwomanhood/M\nwomanish\nwomanize/DRSZG\nwomanizer/M\nwomankind/M\nwomanlike/M\nwomanliness/M\nwomanly/RPT\nwomb/MS\nwombat/MS\nwomble/S\nwomen/M\nwomenfolk/SM\nwomenfolks/M\nwon't\nwon/M\nwonder/MDGLS\nwonderful/YP\nwonderfulness/M\nwondering/Y\nwonderland/MS\nwonderment/M\nwondrous/Y\nwonk/MS\nwonky/TR\nwont/MD\nwonted/U\nwoo/SZGDR\nwood/MDNSG\nwoodbine/M\nwoodblock/MS\nwoodcarver/MS\nwoodcarving/SM\nwoodchuck/MS\nwoodcock/SM\nwoodcraft/M\nwoodcut/SM\nwoodcutter/SM\nwoodcutting/M\nwooden/RYTP\nwoodenness/M\nwoodiness/M\nwoodland/SM\nwoodlice\nwoodlot/SM\nwoodlouse\nwoodman/M\nwoodmen\nwoodpecker/MS\nwoodpile/SM\nwoods/M\nwoodshed/SM\nwoodsiness/M\nwoodsman/M\nwoodsmen\nwoodsy/RTP\nwoodwind/MS\nwoodwork/MRZG\nwoodworker/M\nwoodworking/M\nwoodworm/S\nwoody/TPRSM\nwooer/M\nwoof/MDRSZG\nwoofer/M\nwool/MNX\nwoolen/M\nwoolgathering/M\nwooliness\nwoolliness/M\nwoolly/RSMPT\nwoozily\nwooziness/M\nwoozy/TRP\nwop/S!\nword's\nword/ADSG\nwordage/M\nwordbook/SM\nwordily\nwordiness/M\nwording/SM\nwordless/Y\nwordplay/M\nwordsmith\nwordsmiths\nwordy/TPR\nwore\nwork's\nwork/ADJSG\nworkable/U\nworkaday\nworkaholic/SM\nworkaround/S\nworkbasket/S\nworkbench/MS\nworkbook/MS\nworkday/SM\nworker/MS\nworkfare/M\nworkflow/MS\nworkforce/M\nworkhorse/SM\nworkhouse/SM\nworking's\nworkingman/M\nworkingmen\nworkings/M\nworkingwoman/M\nworkingwomen\nworkload/MS\nworkman/M\nworkmanlike\nworkmanship/M\nworkmate/S\nworkmen\nworkout/SM\nworkplace/MS\nworkroom/MS\nworks/M\nworksheet/MS\nworkshop/MS\nworkshy\nworkstation/MS\nworktable/MS\nworktop/S\nworkup/MS\nworkweek/SM\nworld/SM\nworldlier\nworldliness/UM\nworldly/UTP\nworldview/SM\nworldwide\nworm/MDSG\nwormhole/MS\nwormwood/M\nwormy/TR\nworn/U\nworried/Y\nworrier/M\nworriment/M\nworrisome\nworry/ZGDRSMJ\nworrying/Y\nworrywart/SM\nworse/M\nworsen/DSG\nworship/ZGSMDR\nworshiper/M\nworshipful\nworst/SGMD\nworsted/M\nwort/M\nworth/M\nworthies\nworthily/U\nworthiness/UM\nworthless/PY\nworthlessness/M\nworthwhile\nworthy's\nworthy/UPRT\nwot\nwotcha\nwould've\nwould/S\nwouldn't\nwouldst\nwound/SGMDR\nwove/A\nwoven/AU\nwow/SGMD\nwpm\nwrack/GSMD\nwraith/M\nwraiths\nwrangle/DRSMZGJ\nwrangler/M\nwrap's\nwrap/US\nwraparound/SM\nwrapped/U\nwrapper/SM\nwrapping/MS\nwrasse/MS\nwrath/M\nwrathful/Y\nwreak/SGD\nwreath/MDSG\nwreathe\nwreaths\nwreck/SZGMDR\nwreckage/M\nwrecker/M\nwren/MS\nwrench/MDSG\nwrest/SGMD\nwrestle/MZGDRS\nwrestler/M\nwrestling/M\nwretch/MS\nwretched/TPRY\nwretchedness/M\nwriggle/MZGDRS\nwriggler/M\nwriggly\nwright/MS\nwring/SZGMR\nwringer/M\nwrinkle/MGDS\nwrinkled/U\nwrinkly/TRSM\nwrist/SM\nwristband/MS\nwristwatch/MS\nwrit/MRBJSZG\nwrite/S\nwriter/M\nwrithe/MGDS\nwriting/M\nwritten/AU\nwrong/STGMPDRY\nwrongdoer/SM\nwrongdoing/SM\nwrongful/PY\nwrongfulness/M\nwrongheaded/YP\nwrongheadedness/M\nwrongness/M\nwrote/A\nwroth\nwrought\nwrung\nwry/Y\nwryer\nwryest\nwryness/M\nwt\nwunderkind/S\nwurst/SM\nwuss/MS\nwussy/RSMT\nx\nxci\nxcii\nxciv\nxcix\nxcvi\nxcvii\nxenon/M\nxenophobe/MS\nxenophobia/M\nxenophobic\nxerographic\nxerography/M\nxerox/MDSG\nxi/SM\nxii\nxiii\nxiv\nxix\nxor\nxref/S\nxterm/M\nxv\nxvi\nxvii\nxviii\nxx\nxxi\nxxii\nxxiii\nxxiv\nxxix\nxxv\nxxvi\nxxvii\nxxviii\nxxx\nxxxi\nxxxii\nxxxiii\nxxxiv\nxxxix\nxxxv\nxxxvi\nxxxvii\nxxxviii\nxylem/M\nxylene\nxylophone/SM\nxylophonist/MS\ny'all\ny/F\nya\nyacht/SMDG\nyachting/M\nyachtsman/M\nyachtsmen\nyachtswoman/M\nyachtswomen\nyahoo/SM\nyak/SM\nyakked\nyakking\nyam/SM\nyammer/SZGMDR\nyammerer/M\nyang/M\nyank/MDSG\nyap/SM\nyapped\nyapping\nyard/MS\nyardage/MS\nyardarm/MS\nyardman/M\nyardmaster/MS\nyardmen\nyardstick/MS\nyarmulke/SM\nyarn/MS\nyarrow/M\nyashmak/S\nyaw/SGMD\nyawl/MS\nyawn/MDRSZG\nyawner/M\nyaws/M\nyd\nye/RST\nyea/SM\nyeah/M\nyeahs\nyear/MYS\nyearbook/MS\nyearling/MS\nyearlong\nyearly/SM\nyearn/GSJD\nyearning/M\nyeast/SM\nyeasty/RT\nyegg/MS\nyell/MDSG\nyellow/MDRTGPS\nyellowhammer/S\nyellowish\nyellowness/M\nyellowy\nyelp/MDSG\nyen/SM\nyeoman/M\nyeomanry/M\nyeomen\nyep/SM\nyes/MS\nyeshiva/SM\nyessed\nyessing\nyesterday/MS\nyesteryear/M\nyet\nyeti/MS\nyew/SM\nyid/S\nyield/JSGMD\nyikes\nyin/M\nyip/SM\nyipe\nyipped\nyippee\nyipping\nyo\nyob/S\nyobbo/S\nyodel/SMDRZG\nyodeler/M\nyoga/M\nyogi/MS\nyogic\nyogurt/SM\nyoke's\nyoke/UGDS\nyokel/SM\nyolk/MDS\nyon\nyonder\nyonks\nyore/M\nyou'd\nyou'll\nyou're\nyou've\nyou/SMH\nyoung/TMR\nyoungish\nyoungster/MS\nyour/S\nyourself\nyourselves\nyouth/M\nyouthful/YP\nyouthfulness/M\nyouths\nyow\nyowl/MDSG\nyr/S\nytterbium/M\nyttrium/M\nyuan/M\nyucca/SM\nyuck\nyucky/TR\nyuk/SM\nyukked\nyukking\nyukky\nyule/M\nyuletide/M\nyum\nyummy/TR\nyup/SM\nyuppie/MS\nyuppify/GDS\nyurt/MS\nz/DNXTGJ\nzaniness/M\nzany/RSMPT\nzap/SM\nzapped\nzapper/MS\nzapping\nzappy\nzeal/M\nzealot/MS\nzealotry/M\nzealous/YP\nzealousness/M\nzebra/SM\nzebu/MS\nzed/SM\nzeitgeist/SM\nzenith/M\nzeniths\nzenned\nzeolite/S\nzephyr/MS\nzeppelin/MS\nzero/MDHSG\nzeroes\nzest/MS\nzestful/YP\nzestfulness/M\nzesty/RT\nzeta/MS\nzigzag/SM\nzigzagged\nzigzagging\nzilch/M\nzillion/MS\nzinc/MS\nzincked\nzincking\nzine/S\nzinfandel/M\nzing/MDRZG\nzinger/M\nzingy/RT\nzinnia/MS\nzip's\nzip/US\nzipped/U\nzipper/MDGS\nzipping/U\nzippy/TR\nzircon/MS\nzirconium/M\nzit/SM\nzither/MS\nzloty/SM\nzlotys\nzodiac/MS\nzodiacal\nzombie/MS\nzonal/Y\nzone's\nzone/AGDS\nzoning/M\nzonked\nzoo/SM\nzookeeper/SM\nzoological/Y\nzoologist/SM\nzoology/M\nzoom/MDSG\nzoophyte/SM\nzoophytic\nzooplankton\nzorch\nzoster\nzounds\nzucchini/MS\nzwieback/M\nzydeco/M\nzygote/SM\nzygotic\nzymurgy/M\n"
  },
  {
    "path": "public/vendor/inlineAttachment/codemirror.inline-attachment.js",
    "content": "/*jslint newcap: true */\n/*global inlineAttachment: false */\n/**\n * CodeMirror version for inlineAttachment\n *\n * Call inlineAttachment.attach(editor) to attach to a codemirror instance\n */\n(function() {\n  'use strict';\n\n  var codeMirrorEditor = function(instance) {\n\n    if (!instance.getWrapperElement) {\n      throw \"Invalid CodeMirror object given\";\n    }\n\n    this.codeMirror = instance;\n  };\n\n  codeMirrorEditor.prototype.getValue = function() {\n    return this.codeMirror.getValue();\n  };\n\n  codeMirrorEditor.prototype.insertValue = function(val) {\n    this.codeMirror.replaceSelection(val);\n  };\n\n  codeMirrorEditor.prototype.setValue = function(val) {\n    var cursor = this.codeMirror.getCursor();\n    this.codeMirror.setValue(val);\n    this.codeMirror.setCursor(cursor);\n  };\n    \n  codeMirrorEditor.prototype.replaceRange = function(val) {\n    this.codeMirror.replaceRange(val.replacement, val.from, val.to, \"+input\");\n  };\n\n  /**\n   * Attach InlineAttachment to CodeMirror\n   *\n   * @param {CodeMirror} codeMirror\n   */\n  codeMirrorEditor.attach = function(codeMirror, options) {\n\n    options = options || {};\n\n    var editor = new codeMirrorEditor(codeMirror),\n      inlineattach = new inlineAttachment(options, editor),\n      el = codeMirror.getWrapperElement();\n\n    el.addEventListener('paste', function(e) {\n      inlineattach.onPaste(e);\n    }, false);\n\n    codeMirror.setOption('onDragEvent', function(data, e) {\n      if (e.type === \"drop\") {\n        e.stopPropagation();\n        e.preventDefault();\n        return inlineattach.onDrop(e);\n      }\n    });\n  };\n\n  inlineAttachment.editors.codemirror3 = codeMirrorEditor;\n\n  var codeMirrorEditor4 = function(instance) {\n    codeMirrorEditor.call(this, instance);\n  };\n\n  codeMirrorEditor4.attach = function(codeMirror, options) {\n\n    options = options || {};\n\n    var editor = new codeMirrorEditor(codeMirror),\n      inlineattach = new inlineAttachment(options, editor),\n      el = codeMirror.getWrapperElement();\n\n    el.addEventListener('paste', function(e) {\n      inlineattach.onPaste(e);\n    }, false);\n\n    codeMirror.on('drop', function(data, e) {\n      if (inlineattach.onDrop(e)) {\n        e.stopPropagation();\n        e.preventDefault();\n        return true;\n      } else {\n        return false;\n      }\n    });\n      \n    return inlineattach;\n  };\n\n  inlineAttachment.editors.codemirror4 = codeMirrorEditor4;\n\n})();"
  },
  {
    "path": "public/vendor/inlineAttachment/inline-attachment.js",
    "content": "/*jslint newcap: true */\n/*global XMLHttpRequest: false, FormData: false */\n/*\n * Inline Text Attachment\n *\n * Author: Roy van Kaathoven\n * Contact: ik@royvankaathoven.nl\n */\n(function(document, window) {\n  'use strict';\n\n  var inlineAttachment = function(options, instance) {\n    this.settings = inlineAttachment.util.merge(options, inlineAttachment.defaults);\n    this.editor = instance;\n    this.filenameTag = '{filename}';\n    this.lastValue = null;\n  };\n\n  /**\n   * Will holds the available editors\n   *\n   * @type {Object}\n   */\n  inlineAttachment.editors = {};\n\n  /**\n   * Utility functions\n   */\n  inlineAttachment.util = {\n\n    /**\n     * Simple function to merge the given objects\n     *\n     * @param {Object[]} object Multiple object parameters\n     * @returns {Object}\n     */\n    merge: function() {\n      var result = {};\n      for (var i = arguments.length - 1; i >= 0; i--) {\n        var obj = arguments[i];\n        for (var k in obj) {\n          if (obj.hasOwnProperty(k)) {\n            result[k] = obj[k];\n          }\n        }\n      }\n      return result;\n    },\n\n    /**\n     * Append a line of text at the bottom, ensuring there aren't unnecessary newlines\n     *\n     * @param {String} appended Current content\n     * @param {String} previous Value which should be appended after the current content\n     */\n    appendInItsOwnLine: function(previous, appended) {\n      return (previous + \"\\n\\n[[D]]\" + appended)\n        .replace(/(\\n{2,})\\[\\[D\\]\\]/, \"\\n\\n\")\n        .replace(/^(\\n*)/, \"\");\n    },\n\n    /**\n     * Inserts the given value at the current cursor position of the textarea element\n     *\n     * @param  {HtmlElement} el\n     * @param  {String} value Text which will be inserted at the cursor position\n     */\n    insertTextAtCursor: function(el, text) {\n      var scrollPos = el.scrollTop,\n        strPos = 0,\n        browser = false,\n        range;\n\n      if ((el.selectionStart || el.selectionStart === '0')) {\n        browser = \"ff\";\n      } else if (document.selection) {\n        browser = \"ie\";\n      }\n\n      if (browser === \"ie\") {\n        el.focus();\n        range = document.selection.createRange();\n        range.moveStart('character', -el.value.length);\n        strPos = range.text.length;\n      } else if (browser === \"ff\") {\n        strPos = el.selectionStart;\n      }\n\n      var front = (el.value).substring(0, strPos);\n      var back = (el.value).substring(strPos, el.value.length);\n      el.value = front + text + back;\n      strPos = strPos + text.length;\n      if (browser === \"ie\") {\n        el.focus();\n        range = document.selection.createRange();\n        range.moveStart('character', -el.value.length);\n        range.moveStart('character', strPos);\n        range.moveEnd('character', 0);\n        range.select();\n      } else if (browser === \"ff\") {\n        el.selectionStart = strPos;\n        el.selectionEnd = strPos;\n        el.focus();\n      }\n      el.scrollTop = scrollPos;\n    }\n  };\n\n  /**\n   * Default configuration options\n   *\n   * @type {Object}\n   */\n  inlineAttachment.defaults = {\n    /**\n     * URL where the file will be send\n     */\n    uploadUrl: 'uploadimage',\n\n    /**\n     * Which method will be used to send the file to the upload URL\n     */\n    uploadMethod: 'POST',\n\n    /**\n     * Name in which the file will be placed\n     */\n    uploadFieldName: 'image',\n\n    /**\n     * Extension which will be used when a file extension could not\n     * be detected\n     */\n    defaultExtension: 'png',\n\n    /**\n     * JSON field which refers to the uploaded file URL\n     */\n    jsonFieldName: 'link',\n\n    /**\n     * Allowed MIME types\n     */\n    allowedTypes: window.allowedUploadMimeTypes,\n\n    /**\n     * Text which will be inserted when dropping or pasting a file.\n     * Acts as a placeholder which will be replaced when the file is done with uploading\n     */\n    progressText: '![Uploading file...{filename}]()',\n\n    /**\n     * When a file has successfully been uploaded the progressText\n     * will be replaced by the urlText, the {filename} tag will be replaced\n     * by the filename that has been returned by the server\n     */\n    urlText: \"![]({filename})\",\n\n    /**\n     * Text which will be used when uploading has failed\n     */\n    errorText: \"Error uploading file\",\n\n    /**\n     * Extra parameters which will be send when uploading a file\n     */\n    extraParams: {},\n\n    /**\n     * Extra headers which will be send when uploading a file\n     */\n    extraHeaders: {},\n\n    /**\n     * Before the file is send\n     */\n    beforeFileUpload: function() {\n      return true;\n    },\n\n    /**\n     * Triggers when a file is dropped or pasted\n     */\n    onFileReceived: function() {},\n\n    /**\n     * Custom upload handler\n     *\n     * @return {Boolean} when false is returned it will prevent default upload behavior\n     */\n    onFileUploadResponse: function() {\n      return true;\n    },\n\n    /**\n     * Custom error handler. Runs after removing the placeholder text and before the alert().\n     * Return false from this function to prevent the alert dialog.\n     *\n     * @return {Boolean} when false is returned it will prevent default error behavior\n     */\n    onFileUploadError: function() {\n      return true;\n    },\n\n    /**\n     * When a file has succesfully been uploaded\n     */\n    onFileUploaded: function() {}\n  };\n\n  /**\n   * Uploads the blob\n   *\n   * @param  {Blob} file blob data received from event.dataTransfer object\n   * @return {XMLHttpRequest} request object which sends the file\n   */\n  inlineAttachment.prototype.uploadFile = function(file, id) {\n    var me = this,\n      formData = new FormData(),\n      xhr = new XMLHttpRequest(),\n      id = id,\n      settings = this.settings,\n      extension = settings.defaultExtension;\n\n    if (typeof settings.setupFormData === 'function') {\n      settings.setupFormData(formData, file);\n    }\n\n    // Attach the file. If coming from clipboard, add a default filename (only works in Chrome for now)\n    // http://stackoverflow.com/questions/6664967/how-to-give-a-blob-uploaded-as-formdata-a-file-name\n    if (file.name) {\n      var fileNameMatches = file.name.match(/\\.(.+)$/);\n      if (fileNameMatches) {\n        extension = fileNameMatches[1];\n      }\n    }\n\n    var remoteFilename = \"image-\" + Date.now() + \".\" + extension;\n    if (typeof settings.remoteFilename === 'function') {\n      remoteFilename = settings.remoteFilename(file);\n    }\n\n    formData.append(settings.uploadFieldName, file, remoteFilename);\n\n    // Append the extra parameters to the formdata\n    if (typeof settings.extraParams === \"object\") {\n      for (var key in settings.extraParams) {\n        if (settings.extraParams.hasOwnProperty(key)) {\n          formData.append(key, settings.extraParams[key]);\n        }\n      }\n    }\n\n    xhr.open('POST', settings.uploadUrl);\n\n    // Add any available extra headers\n    if (typeof settings.extraHeaders === \"object\") {\n        for (var header in settings.extraHeaders) {\n            if (settings.extraHeaders.hasOwnProperty(header)) {\n                xhr.setRequestHeader(header, settings.extraHeaders[header]);\n            }\n        }\n    }\n\n    xhr.onload = function() {\n      // If HTTP status is OK or Created\n      if (xhr.status === 200 || xhr.status === 201) {\n        me.onFileUploadResponse(xhr, id);\n      } else {\n        me.onFileUploadError(xhr, id);\n      }\n    };\n    if (settings.beforeFileUpload(xhr) !== false) {\n      xhr.send(formData);\n    }\n    return xhr;\n  };\n\n  /**\n   * Returns if the given file is allowed to handle\n   *\n   * @param {File} clipboard data file\n   */\n  inlineAttachment.prototype.isFileAllowed = function(file) {\n    if (this.settings.allowedTypes.indexOf('*') === 0){\n      return true;\n    } else {\n      return this.settings.allowedTypes.indexOf(file.type) >= 0;\n    }\n  };\n\n  /**\n   * Handles upload response\n   *\n   * @param  {XMLHttpRequest} xhr\n   * @return {Void}\n   */\n  inlineAttachment.prototype.onFileUploadResponse = function(xhr, id) {\n    if (this.settings.onFileUploadResponse.call(this, xhr) !== false) {\n      var result = JSON.parse(xhr.responseText),\n        filename = result[this.settings.jsonFieldName];\n\n      if (result && filename) {\n          var replacements = [];\n          var string = this.settings.progressText.replace(this.filenameTag, id);\n          var lines = this.editor.getValue().split('\\n');\n        var newValue = this.settings.urlText.replace(this.filenameTag, filename);\n          for(var i = 0; i < lines.length; i++) {\n            var ch = lines[i].indexOf(string);\n            if(ch != -1)\n                replacements.push({replacement:newValue, from:{line:i, ch:ch}, to:{line:i, ch:ch + string.length}});\n        }\n          for(var i = 0; i < replacements.length; i++)\n            this.editor.replaceRange(replacements[i]);\n      }\n    }\n  };\n\n\n  /**\n   * Called when a file has failed to upload\n   *\n   * @param  {XMLHttpRequest} xhr\n   * @return {Void}\n   */\n  inlineAttachment.prototype.onFileUploadError = function(xhr, id) {\n    if (this.settings.onFileUploadError.call(this, xhr) !== false) {\n      var replacements = [];\n      var string = this.settings.progressText.replace(this.filenameTag, id);\n      var lines = this.editor.getValue().split('\\n');\n        for(var i = 0; i < lines.length; i++) {\n            var ch = lines[i].indexOf(this.lastValue);\n            if(ch != -1)\n                replacements.push({replacement:\"\", from:{line:i, ch:ch}, to:{line:i, ch:ch + string.length}});\n        }\n        for(var i = 0; i < replacements.length; i++)\n            this.editor.replaceRange(replacements[i]);\n    }\n  };\n\n  /**\n   * Called when a file has been inserted, either by drop or paste\n   *\n   * @param  {File} file\n   * @return {Void}\n   */\n  inlineAttachment.prototype.onFileInserted = function(file, id) {\n    if (this.settings.onFileReceived.call(this, file) !== false) {\n      this.lastValue = this.settings.progressText.replace(this.filenameTag, id);\n      this.editor.insertValue(this.lastValue + \"\\n\");\n    }\n  };\n\n\n  /**\n   * Called when a paste event occured\n   * @param  {Event} e\n   * @return {Boolean} if the event was handled\n   */\n  inlineAttachment.prototype.onPaste = function(e) {\n    var result = false,\n      clipboardData = e.clipboardData,\n      items;\n\n    if (typeof clipboardData === \"object\") {\n      items = clipboardData.items || clipboardData.files || [];\n\n      for (var i = 0; i < items.length; i++) {\n        var item = items[i];\n        if (this.isFileAllowed(item)) {\n          result = true;\n          var id = ID();\n          var file = item.getAsFile();\n          if (file !== null) {\n            this.onFileInserted(file, id);\n            this.uploadFile(file, id);\n          }\n        }\n      }\n    }\n\n    if (result) { e.preventDefault(); }\n\n    return result;\n  };\n\n  /**\n   * Called when a drop event occures\n   * @param  {Event} e\n   * @return {Boolean} if the event was handled\n   */\n  inlineAttachment.prototype.onDrop = function(e) {\n    var result = false;\n    for (var i = 0; i < e.dataTransfer.files.length; i++) {\n      var file = e.dataTransfer.files[i];\n      if (this.isFileAllowed(file)) {\n        result = true;\n        var id = ID();\n        this.onFileInserted(file, id);\n        this.uploadFile(file, id);\n      }\n    }\n\n    return result;\n  };\n\n  window.inlineAttachment = inlineAttachment;\n\n})(document, window);\n\n// Generate unique IDs for use as pseudo-private/protected names.\n// Similar in concept to\n// <http://wiki.ecmascript.org/doku.php?id=strawman:names>.\n//\n// The goals of this function are twofold:\n//\n// * Provide a way to generate a string guaranteed to be unique when compared\n//   to other strings generated by this function.\n// * Make the string complex enough that it is highly unlikely to be\n//   accidentally duplicated by hand (this is key if you're using `ID`\n//   as a private/protected name on an object).\n//\n// Use:\n//\n//     var privateName = ID();\n//     var o = { 'public': 'foo' };\n//     o[privateName] = 'bar';\nvar ID = function () {\n  // Math.random should be unique because of its seeding algorithm.\n  // Convert it to base 36 (numbers + letters), and grab the first 9 characters\n  // after the decimal.\n  return '_' + Math.random().toString(36).substr(2, 9);\n};\n"
  },
  {
    "path": "public/vendor/jquery-textcomplete/jquery.textcomplete.js",
    "content": "/*!\n * jQuery.textcomplete\n *\n * Repository: https://github.com/yuku-t/jquery-textcomplete\n * License:    MIT (https://github.com/yuku-t/jquery-textcomplete/blob/master/LICENSE)\n * Author:     Yuku Takahashi\n */\n\nif (typeof jQuery === 'undefined') {\n  throw new Error('jQuery.textcomplete requires jQuery');\n}\n\n+function ($) {\n  'use strict';\n\n  var warn = function (message) {\n    if (console.warn) { console.warn(message); }\n  };\n\n  $.fn.textcomplete = function (strategies, option) {\n    var args = Array.prototype.slice.call(arguments);\n    return this.each(function () {\n      var $this = $(this);\n      var completer = $this.data('textComplete');\n      if (!completer) {\n        completer = new $.fn.textcomplete.Completer(this, option || {});\n        $this.data('textComplete', completer);\n      }\n      if (typeof strategies === 'string') {\n        if (!completer) return;\n        args.shift()\n        completer[strategies].apply(completer, args);\n        if (strategies === 'destroy') {\n          $this.removeData('textComplete');\n        }\n      } else {\n        // For backward compatibility.\n        // TODO: Remove at v0.4\n        $.each(strategies, function (obj) {\n          $.each(['header', 'footer', 'placement', 'maxCount'], function (name) {\n            if (obj[name]) {\n              completer.option[name] = obj[name];\n              warn(name + 'as a strategy param is deprecated. Use option.');\n              delete obj[name];\n            }\n          });\n        });\n        completer.register($.fn.textcomplete.Strategy.parse(strategies));\n      }\n    });\n  };\n\n}(jQuery);\n\n+function ($) {\n  'use strict';\n\n  // Exclusive execution control utility.\n  //\n  // func - The function to be locked. It is executed with a function named\n  //        `free` as the first argument. Once it is called, additional\n  //        execution are ignored until the free is invoked. Then the last\n  //        ignored execution will be replayed immediately.\n  //\n  // Examples\n  //\n  //   var lockedFunc = lock(function (free) {\n  //     setTimeout(function { free(); }, 1000); // It will be free in 1 sec.\n  //     console.log('Hello, world');\n  //   });\n  //   lockedFunc();  // => 'Hello, world'\n  //   lockedFunc();  // none\n  //   lockedFunc();  // none\n  //   // 1 sec past then\n  //   // => 'Hello, world'\n  //   lockedFunc();  // => 'Hello, world'\n  //   lockedFunc();  // none\n  //\n  // Returns a wrapped function.\n  var lock = function (func) {\n    var locked, queuedArgsToReplay;\n\n    return function () {\n      // Convert arguments into a real array.\n      var args = Array.prototype.slice.call(arguments);\n      if (locked) {\n        // Keep a copy of this argument list to replay later.\n        // OK to overwrite a previous value because we only replay\n        // the last one.\n        queuedArgsToReplay = args;\n        return;\n      }\n      locked = true;\n      var self = this;\n      args.unshift(function replayOrFree() {\n        if (queuedArgsToReplay) {\n          // Other request(s) arrived while we were locked.\n          // Now that the lock is becoming available, replay\n          // the latest such request, then call back here to\n          // unlock (or replay another request that arrived\n          // while this one was in flight).\n          var replayArgs = queuedArgsToReplay;\n          queuedArgsToReplay = undefined;\n          replayArgs.unshift(replayOrFree);\n          func.apply(self, replayArgs);\n        } else {\n          locked = false;\n        }\n      });\n      func.apply(this, args);\n    };\n  };\n\n  var isString = function (obj) {\n    return Object.prototype.toString.call(obj) === '[object String]';\n  };\n\n  var uniqueId = 0;\n\n  function Completer(element, option) {\n    this.$el        = $(element);\n    this.id         = 'textcomplete' + uniqueId++;\n    this.strategies = [];\n    this.views      = [];\n    this.option     = $.extend({}, Completer._getDefaults(), option);\n\n    if (!this.$el.is('input[type=text]') && !this.$el.is('textarea') && !element.isContentEditable && element.contentEditable != 'true') {\n      throw new Error('textcomplete must be called on a Textarea or a ContentEditable.');\n    }\n\n    if (element === document.activeElement) {\n      // element has already been focused. Initialize view objects immediately.\n      this.initialize()\n    } else {\n      // Initialize view objects lazily.\n      var self = this;\n      this.$el.one('focus.' + this.id, function () { self.initialize(); });\n    }\n  }\n\n  Completer._getDefaults = function () {\n    if (!Completer.DEFAULTS) {\n      Completer.DEFAULTS = {\n        appendTo: $('body'),\n        zIndex: '100'\n      };\n    }\n\n    return Completer.DEFAULTS;\n  }\n\n  $.extend(Completer.prototype, {\n    // Public properties\n    // -----------------\n\n    id:         null,\n    option:     null,\n    strategies: null,\n    adapter:    null,\n    dropdown:   null,\n    $el:        null,\n\n    // Public methods\n    // --------------\n\n    initialize: function () {\n      var element = this.$el.get(0);\n      // Initialize view objects.\n      this.dropdown = new $.fn.textcomplete.Dropdown(element, this, this.option);\n      this.dropdown.upSideDown = false;\n      var Adapter, viewName;\n      if (this.option.adapter) {\n        Adapter = this.option.adapter;\n      } else {\n        if (this.$el.is('textarea') || this.$el.is('input[type=text]')) {\n          viewName = typeof element.selectionEnd === 'number' ? 'Textarea' : 'IETextarea';\n        } else {\n          viewName = 'ContentEditable';\n        }\n        Adapter = $.fn.textcomplete[viewName];\n      }\n      this.adapter = new Adapter(element, this, this.option);\n    },\n\n    destroy: function () {\n      this.$el.off('.' + this.id);\n      if (this.adapter) {\n        this.adapter.destroy();\n      }\n      if (this.dropdown) {\n        this.dropdown.destroy();\n      }\n      this.$el = this.adapter = this.dropdown = null;\n    },\n\n    // Invoke textcomplete.\n    trigger: function (text, skipUnchangedTerm) {\n      if (!this.dropdown) { this.initialize(); }\n      text != null || (text = this.adapter.getTextFromHeadToCaret());\n      var searchQuery = this._extractSearchQuery(text);\n      if (searchQuery.length) {\n        var term = searchQuery[1];\n        // Ignore shift-key, ctrl-key and so on.\n        if (skipUnchangedTerm && this._term === term) { return; }\n        this._term = term;\n        this.fire('textComplete:beforeSearch');\n        this._search.apply(this, searchQuery);\n        this.fire('textComplete:afterSearch');\n      } else {\n        this._term = null;\n        this.dropdown.deactivate();\n      }\n    },\n\n    fire: function (eventName) {\n      var args = Array.prototype.slice.call(arguments, 1);\n      this.$el.trigger(eventName, args);\n      return this;\n    },\n\n    register: function (strategies) {\n      Array.prototype.push.apply(this.strategies, strategies);\n    },\n\n    // Insert the value into adapter view. It is called when the dropdown is clicked\n    // or selected.\n    //\n    // value    - The selected element of the array callbacked from search func.\n    // strategy - The Strategy object.\n    select: function (value, strategy) {\n      this.adapter.select(value, strategy);\n      this.fire('change').fire('textComplete:select', value, strategy);\n      this.adapter.focus();\n    },\n\n    // Private properties\n    // ------------------\n\n    _clearAtNext: true,\n    _term:        null,\n\n    // Private methods\n    // ---------------\n\n    // Parse the given text and extract the first matching strategy.\n    //\n    // Returns an array including the strategy, the query term and the match\n    // object if the text matches an strategy; otherwise returns an empty array.\n    _extractSearchQuery: function (text) {\n      for (var i = 0; i < this.strategies.length; i++) {\n        var strategy = this.strategies[i];\n        var context = strategy.context(text);\n        if (context || context === '') {\n          if (isString(context)) { text = context; }\n            var cursor = editor.getCursor();\n            var line = editor.getLine(cursor.line);\n            var linematch = line.match(strategy.match);\n            if(linematch) {\n                text = line.slice(0, cursor.ch);\n                var textmatch = text.match(strategy.match);\n                if (textmatch) { return [strategy, textmatch[strategy.index], textmatch]; }\n            }\n        }\n      }\n      return []\n    },\n\n    // Call the search method of selected strategy..\n    _search: lock(function (free, strategy, term, match) {\n      var self = this;\n      strategy.search(term, function (data, stillSearching) {\n        if (!self.dropdown.shown) {\n          self.dropdown.activate();\n          self.dropdown.setPosition(self.adapter.getCaretPosition());\n        }\n        if (self._clearAtNext) {\n          // The first callback in the current lock.\n          self.dropdown.clear();\n          self._clearAtNext = false;\n        }\n        self.dropdown.render(self._zip(data, strategy));\n        if (!stillSearching) {\n          // The last callback in the current lock.\n          free();\n          self._clearAtNext = true; // Call dropdown.clear at the next time.\n        }\n      }, match);\n    }),\n\n    // Build a parameter for Dropdown#render.\n    //\n    // Examples\n    //\n    //  this._zip(['a', 'b'], 's');\n    //  //=> [{ value: 'a', strategy: 's' }, { value: 'b', strategy: 's' }]\n    _zip: function (data, strategy) {\n      return $.map(data, function (value) {\n        return { value: value, strategy: strategy };\n      });\n    }\n  });\n\n  $.fn.textcomplete.Completer = Completer;\n}(jQuery);\n\n+function ($) {\n  'use strict';\n\n  var include = function (zippedData, datum) {\n    var i, elem;\n    var idProperty = datum.strategy.idProperty\n    for (i = 0; i < zippedData.length; i++) {\n      elem = zippedData[i];\n      if (elem.strategy !== datum.strategy) continue;\n      if (idProperty) {\n        if (elem.value[idProperty] === datum.value[idProperty]) return true;\n      } else {\n        if (elem.value === datum.value) return true;\n      }\n    }\n    return false;\n  };\n\n  var dropdownViews = {};\n    /*\n  $(document).on('mousedown', function (e) {\n    var id = e.originalEvent && e.originalEvent.keepTextCompleteDropdown;\n    $.each(dropdownViews, function (key, view) {\n      if (key !== id) { view.deactivate(); }\n    });\n  });\n  */\n\n  // Dropdown view\n  // =============\n\n  // Construct Dropdown object.\n  //\n  // element - Textarea or contenteditable element.\n  function Dropdown(element, completer, option) {\n    this.$el       = Dropdown.findOrCreateElement(option);\n    this.completer = completer;\n    this.id        = completer.id + 'dropdown';\n    this._data     = []; // zipped data.\n    this.$inputEl  = $(element);\n    this.option    = option;\n    this.tap       = false;\n\n    // Override setPosition method.\n    if (option.listPosition) { this.setPosition = option.listPosition; }\n    if (option.height) { this.$el.height(option.height); }\n    var self = this;\n    $.each(['maxCount', 'placement', 'footer', 'header', 'className'], function (_i, name) {\n      if (option[name] != null) { self[name] = option[name]; }\n    });\n    this._bindEvents(element);\n    dropdownViews[this.id] = this;\n  }\n\n  $.extend(Dropdown, {\n    // Class methods\n    // -------------\n\n    findOrCreateElement: function (option) {\n      var $parent = option.appendTo;\n      if (!($parent instanceof $)) { $parent = $($parent); }\n      var $el = $parent.children('.dropdown-menu')\n      if (!$el.length) {\n        $el = $('<ul class=\"dropdown-menu\"></ul>').css({\n          display: 'none',\n          left: 0,\n          position: 'absolute',\n          zIndex: option.zIndex\n        }).appendTo($parent);\n      }\n      return $el;\n    }\n  });\n\n  $.extend(Dropdown.prototype, {\n    // Public properties\n    // -----------------\n\n    $el:       null,  // jQuery object of ul.dropdown-menu element.\n    $inputEl:  null,  // jQuery object of target textarea.\n    completer: null,\n    footer:    null,\n    header:    null,\n    id:        null,\n    maxCount:  10,\n    placement: '',\n    shown:     false,\n    data:      [],     // Shown zipped data.\n    className: '',\n\n    // Public methods\n    // --------------\n\n    destroy: function () {\n      // Don't remove $el because it may be shared by several textcompletes.\n      this.deactivate();\n\n      this.$el.off('.' + this.id);\n      this.$inputEl.off('.' + this.id);\n      this.clear();\n      this.$el = this.$inputEl = this.completer = null;\n      delete dropdownViews[this.id]\n    },\n\n    render: function (zippedData) {\n      var contentsHtml = this._buildContents(zippedData);\n      var unzippedData = $.map(this.data, function (d) { return d.value; });\n      if (this.data.length) {\n        this._renderHeader(unzippedData);\n        this._renderFooter(unzippedData);\n        if (contentsHtml) {\n          this._renderContents(contentsHtml);\n          this._activateIndexedItem();\n        }\n        this._setScroll();\n      } else if (this.shown) {\n        this.deactivate();\n      }\n    },\n\n    setPosition: function (position) {\n      this.$el.css(this._applyPlacement(position));\n\n      // Make the dropdown fixed if the input is also fixed\n      // This can't be done during init, as textcomplete may be used on multiple elements on the same page\n      // Because the same dropdown is reused behind the scenes, we need to recheck every time the dropdown is showed\n      var position = 'absolute';\n      // Check if input or one of its parents has positioning we need to care about\n      this.$inputEl.add(this.$inputEl.parents()).each(function() {\n        if($(this).css('position') === 'absolute') // The element has absolute positioning, so it's all OK\n          return false;\n        if($(this).css('position') === 'fixed') {\n          position = 'fixed';\n          return false;\n        }\n      });\n      this.$el.css({ position: position }); // Update positioning\n\n      return this;\n    },\n\n    clear: function () {\n      this.$el.html('');\n      this.data = [];\n      this._index = 0;\n      this._$header = this._$footer = null;\n    },\n\n    activate: function () {\n      if (!this.shown) {\n        this.clear();\n        this.$el.show();\n        if (this.className) { this.$el.addClass(this.className); }\n        this.completer.fire('textComplete:show');\n        this.shown = true;\n      }\n      return this;\n    },\n\n    deactivate: function () {\n      if (this.shown) {\n        this.$el.hide();\n        if (this.className) { this.$el.removeClass(this.className); }\n        this.completer.fire('textComplete:hide');\n        this.shown = false;\n      }\n      return this;\n    },\n\n    isUp: function (e) {\n      return e.keyCode === 38 || (e.ctrlKey && e.keyCode === 80);  // UP, Ctrl-P\n    },\n\n    isDown: function (e) {\n      return e.keyCode === 40 || (e.ctrlKey && e.keyCode === 78);  // DOWN, Ctrl-N\n    },\n\n    isEnter: function (e) {\n      var modifiers = e.ctrlKey || e.altKey || e.metaKey || e.shiftKey;\n      return !modifiers && (e.keyCode === 13 || e.keyCode === 9 || (this.option.completeOnSpace === true && e.keyCode === 32))  // ENTER, TAB\n    },\n\n    isPageup: function (e) {\n      return e.keyCode === 33;  // PAGEUP\n    },\n\n    isPagedown: function (e) {\n      return e.keyCode === 34;  // PAGEDOWN\n    },\n\n    isEscape: function (e) {\n      return e.keyCode === 27;  // ESCAPE\n    },\n\n    // Private properties\n    // ------------------\n\n    _data:    null,  // Currently shown zipped data.\n    _index:   null,\n    _$header: null,\n    _$footer: null,\n\n    // Private methods\n    // ---------------\n\n    _bindEvents: function () {\n      this.$inputEl.on('blur', $.proxy(this.deactivate, this));\n      this.$el.on('touchstart.' + this.id, '.textcomplete-item', $.proxy(function(e) {\n          this.tap = true;\n      }, this));\n      this.$el.on('touchmove.' + this.id, '.textcomplete-item', $.proxy(function(e) {\n          this.tap = false;\n      }, this));\n      this.$el.on('touchend.' + this.id, '.textcomplete-item', $.proxy(function(e) {\n          if(e.cancelable && this.tap) {\n              this._onClick(e);\n          }\n      }, this));\n      this.$el.on('mousedown.' + this.id, '.textcomplete-item', $.proxy(this._onClick, this));\n      this.$el.on('mouseover.' + this.id, '.textcomplete-item', $.proxy(this._onMouseover, this));\n      this.$inputEl.on('keydown.' + this.id, $.proxy(this._onKeydown, this));\n    },\n\n    _onClick: function (e) {\n      var $el = $(e.target);\n      e.stopPropagation();\n      e.preventDefault();\n      e.originalEvent.keepTextCompleteDropdown = this.id;\n      if (!$el.hasClass('textcomplete-item')) {\n        $el = $el.closest('.textcomplete-item');\n      }\n      var datum = this.data[parseInt($el.data('index'), 10)];\n      this.completer.select(datum.value, datum.strategy);\n      var self = this;\n      // Deactive at next tick to allow other event handlers to know whether\n      // the dropdown has been shown or not.\n      setTimeout(function () { self.deactivate(); }, 0);\n    },\n\n    // Activate hovered item.\n    _onMouseover: function (e) {\n      var $el = $(e.target);\n      e.preventDefault();\n      if (!$el.hasClass('textcomplete-item')) {\n        $el = $el.closest('.textcomplete-item');\n      }\n      this._index = parseInt($el.data('index'), 10);\n      this._activateIndexedItem();\n    },\n\n    _onKeydown: function (e) {\n      if (!this.shown) { return; }\n      if (this.isUp(e)) {\n        e.preventDefault();\n        if(this.upSideDown)\n          this._down();\n        else\n          this._up();\n      } else if (this.isDown(e)) {\n        e.preventDefault();\n        if(this.upSideDown)\n          this._up();\n        else\n          this._down();\n      } else if (this.isEnter(e)) {\n        e.preventDefault();\n        this._enter();\n      } else if (this.isPageup(e)) {\n        e.preventDefault();\n        this._pageup();\n      } else if (this.isPagedown(e)) {\n        e.preventDefault();\n        this._pagedown();\n      } else if (this.isEscape(e)) {\n        e.preventDefault();\n        this.deactivate();\n      }\n    },\n\n    _up: function () {\n      if (this._index === 0) {\n        this._index = this.data.length - 1;\n      } else {\n        this._index -= 1;\n      }\n      this._activateIndexedItem();\n      this._setScroll();\n    },\n\n    _down: function () {\n      if (this._index === this.data.length - 1) {\n        this._index = 0;\n      } else {\n        this._index += 1;\n      }\n      this._activateIndexedItem();\n      this._setScroll();\n    },\n\n    _enter: function () {\n      var datum = this.data[parseInt(this._getActiveElement().data('index'), 10)];\n      this.completer.select(datum.value, datum.strategy);\n      this.deactivate();\n    },\n\n    _pageup: function () {\n      var target = 0;\n      var threshold = this._getActiveElement().position().top - this.$el.innerHeight();\n      this.$el.children().each(function (i) {\n        if ($(this).position().top + $(this).outerHeight() > threshold) {\n          target = i;\n          return false;\n        }\n      });\n      this._index = target;\n      this._activateIndexedItem();\n      this._setScroll();\n    },\n\n    _pagedown: function () {\n      var target = this.data.length - 1;\n      var threshold = this._getActiveElement().position().top + this.$el.innerHeight();\n      this.$el.children().each(function (i) {\n        if ($(this).position().top > threshold) {\n          target = i;\n          return false\n        }\n      });\n      this._index = target;\n      this._activateIndexedItem();\n      this._setScroll();\n    },\n\n    _activateIndexedItem: function () {\n      this.$el.find('.textcomplete-item.active').removeClass('active');\n      this._getActiveElement().addClass('active');\n    },\n\n    _getActiveElement: function () {\n      return this.$el.children('.textcomplete-item[data-index=' + this._index + ']');\n    },\n\n    _setScroll: function () {\n      var $activeEl = this._getActiveElement();\n      var itemTop = $activeEl.position().top;\n      var itemHeight = $activeEl.outerHeight();\n      var visibleHeight = this.$el.innerHeight();\n      var visibleTop = this.$el.scrollTop();\n      if (this._index === 0 || this._index == this.data.length - 1 || itemTop < 0) {\n        this.$el.scrollTop(itemTop + visibleTop);\n      } else if (itemTop + itemHeight > visibleHeight) {\n        this.$el.scrollTop(itemTop + itemHeight + visibleTop - visibleHeight);\n      }\n    },\n\n    _buildContents: function (zippedData) {\n      var datum, i, index;\n      var item = [];\n      var html = '';\n          for (i = 0; i < zippedData.length; i++) {\n            if (this.data.length === this.maxCount) break;\n            datum = zippedData[i];\n            if (include(this.data, datum)) { continue; }\n            index = this.data.length;\n            this.data.push(datum);\n            item.push(datum.strategy.template(datum.value));\n          }\n          for (i = 0; i < item.length; i++) {\n                html += '<li class=\"textcomplete-item\" data-index=\"' + i + '\"><a>';\n            html += item[i];\n            html += '</a></li>';\n          }\n      return html;\n    },\n\n    _renderHeader: function (unzippedData) {\n      if (this.header) {\n        if (!this._$header) {\n          this._$header = $('<li class=\"textcomplete-header\"></li>').prependTo(this.$el);\n        }\n        var html = $.isFunction(this.header) ? this.header(unzippedData) : this.header;\n        this._$header.html(html);\n      }\n    },\n\n    _renderFooter: function (unzippedData) {\n      if (this.footer) {\n        if (!this._$footer) {\n          this._$footer = $('<li class=\"textcomplete-footer\"></li>').appendTo(this.$el);\n        }\n        var html = $.isFunction(this.footer) ? this.footer(unzippedData) : this.footer;\n        this._$footer.html(html);\n      }\n    },\n\n    _renderContents: function (html) {\n      if (this._$footer) {\n        this._$footer.before(html);\n      } else {\n        this.$el.append(html);\n      }\n    },\n\n    _applyPlacement: function (position) {\n      // If the 'placement' option set to 'top', move the position above the element.\n      if (this.placement.indexOf('top') !== -1) {\n        // Overwrite the position object to set the 'bottom' property instead of the top.\n        position = {\n          top: 'auto',\n          bottom: this.$el.parent().height() - position.top + position.lineHeight,\n          left: position.left\n        };\n      } else {\n        position.bottom = 'auto';\n        delete position.lineHeight;\n      }\n      if (this.placement.indexOf('absleft') !== -1) {\n        position.left = 0;\n      } else if (this.placement.indexOf('absright') !== -1) {\n        position.right = 0;\n        position.left = 'auto';\n      }\n      return position;\n    }\n  });\n\n  $.fn.textcomplete.Dropdown = Dropdown;\n}(jQuery);\n\n+function ($) {\n  'use strict';\n\n  // Memoize a search function.\n  var memoize = function (func) {\n    var memo = {};\n    return function (term, callback) {\n      if (memo[term]) {\n        callback(memo[term]);\n      } else {\n        func.call(this, term, function (data) {\n          memo[term] = (memo[term] || []).concat(data);\n          callback.apply(null, arguments);\n        });\n      }\n    };\n  };\n\n  function Strategy(options) {\n    $.extend(this, options);\n    if (this.cache) { this.search = memoize(this.search); }\n  }\n\n  Strategy.parse = function (optionsArray) {\n    return $.map(optionsArray, function (options) {\n      return new Strategy(options);\n    });\n  };\n\n  $.extend(Strategy.prototype, {\n    // Public properties\n    // -----------------\n\n    // Required\n    match:      null,\n    replace:    null,\n    search:     null,\n\n    // Optional\n    cache:      false,\n    context:    function () { return true; },\n    index:      2,\n    template:   function (obj) { return obj; },\n    idProperty: null\n  });\n\n  $.fn.textcomplete.Strategy = Strategy;\n\n}(jQuery);\n\n+function ($) {\n  'use strict';\n\n  var now = Date.now || function () { return new Date().getTime(); };\n\n  // Returns a function, that, as long as it continues to be invoked, will not\n  // be triggered. The function will be called after it stops being called for\n  // `wait` msec.\n  //\n  // This utility function was originally implemented at Underscore.js.\n  var debounce = function (func, wait) {\n    var timeout, args, context, timestamp, result;\n    var later = function () {\n      var last = now() - timestamp;\n      if (last < wait) {\n        timeout = setTimeout(later, wait - last);\n      } else {\n        timeout = null;\n        result = func.apply(context, args);\n        context = args = null;\n      }\n    };\n\n    return function () {\n      context = this;\n      args = arguments;\n      timestamp = now();\n      if (!timeout) {\n        timeout = setTimeout(later, wait);\n      }\n      return result;\n    };\n  };\n\n  function Adapter () {}\n\n  $.extend(Adapter.prototype, {\n    // Public properties\n    // -----------------\n\n    id:        null, // Identity.\n    completer: null, // Completer object which creates it.\n    el:        null, // Textarea element.\n    $el:       null, // jQuery object of the textarea.\n    option:    null,\n\n    // Public methods\n    // --------------\n\n    initialize: function (element, completer, option) {\n      this.el        = element;\n      this.$el       = $(element);\n      this.id        = completer.id + this.constructor.name;\n      this.completer = completer;\n      this.option    = option;\n      this.lastCurosr = null;\n\n      if (this.option.debounce) {\n        this._onKeyup = debounce(this._onKeyup, this.option.debounce);\n      }\n\n      this._bindEvents();\n    },\n\n    destroy: function () {\n      this.$el.off('.' + this.id); // Remove all event handlers.\n      this.$el = this.el = this.completer = null;\n    },\n\n    // Update the element with the given value and strategy.\n    //\n    // value    - The selected object. It is one of the item of the array\n    //            which was callbacked from the search function.\n    // strategy - The Strategy associated with the selected value.\n    select: function (/* value, strategy */) {\n      throw new Error('Not implemented');\n    },\n\n    // Returns the caret's relative coordinates from body's left top corner.\n    //\n    // FIXME: Calculate the left top corner of `this.option.appendTo` element.\n    getCaretPosition: function () {\n      if ($('.CodeMirror-cursor').length > 0) {\n        var position = $('.CodeMirror-cursor').position();\n        var menu = $('.cursor-menu .dropdown-menu');\n        var offsetLeft = parseFloat(menu.attr('data-offset-left'));\n        var offsetTop = parseFloat(menu.attr('data-offset-top'));\n        position.left += offsetLeft;\n        position.top += offsetTop;\n        return position;\n      } else {\n        var position = this._getCaretRelativePosition();\n        var offset = this.$el.offset();\n\n        // Calculate the left top corner of `this.option.appendTo` element.\n        var $parent = this.option.appendTo;\n        if ($parent) {\n          if (!($parent instanceof $)) { $parent = $($parent); }\n          var parentOffset = $parent.offsetParent().offset();\n          offset.top -= parentOffset.top;\n          offset.left -= parentOffset.left;\n        }\n\n        position.top += offset.top;\n        position.left += offset.left;\n        return position;\n      }\n    },\n\n    // Focus on the element.\n    focus: function () {\n      this.$el.focus();\n    },\n\n    // Private methods\n    // ---------------\n\n    _bindEvents: function () {\n      editor.on('cursorActivity', $.proxy(this._onKeyup, this));\n      $('.CodeMirror').on('touchend.' + this.id, $.proxy(this._onKeyup, this));\n      $('.CodeMirror').on('mouseup.' + this.id, $.proxy(this._onKeyup, this));\n      $(editor.getInputField()).on('focus', $.proxy(this._onKeyup, this));\n      this.$el.on('keyup.' + this.id, $.proxy(this._onKeyup, this));\n    },\n\n    _onKeyup: function (e) {\n      var focus = (e.type == 'focus');\n      var cursor = editor.getCursor();\n      var samePos = (cursor == this.lastCursor);\n      if (this._skipSearch(e)) { return; }\n      this.completer.trigger(this.getTextFromHeadToCaret(), focus ? false : samePos);\n      this.lastCursor = cursor;\n    },\n\n    // Suppress searching if it returns true.\n    _skipSearch: function (clickEvent) {\n      switch (clickEvent.keyCode) {\n        case 13: // ENTER\n        case 40: // DOWN\n        case 38: // UP\n          return true;\n      }\n      if (clickEvent.ctrlKey) switch (clickEvent.keyCode) {\n        case 78: // Ctrl-N\n        case 80: // Ctrl-P\n          return true;\n      }\n    }\n  });\n\n  $.fn.textcomplete.Adapter = Adapter;\n}(jQuery);\n\n+function ($) {\n  'use strict';\n\n  // Textarea adapter\n  // ================\n  //\n  // Managing a textarea. It doesn't know a Dropdown.\n  function Textarea(element, completer, option) {\n    this.initialize(element, completer, option);\n  }\n\n  Textarea.DIV_PROPERTIES = {\n    left: -9999,\n    position: 'absolute',\n    top: 0,\n    whiteSpace: 'pre-wrap'\n  }\n\n  Textarea.COPY_PROPERTIES = [\n    'border-width', 'font-family', 'font-size', 'font-style', 'font-variant',\n    'font-weight', 'height', 'letter-spacing', 'word-spacing', 'line-height',\n    'text-decoration', 'text-align', 'width', 'padding-top', 'padding-right',\n    'padding-bottom', 'padding-left', 'margin-top', 'margin-right',\n    'margin-bottom', 'margin-left', 'border-style', 'box-sizing', 'tab-size'\n  ];\n\n  $.extend(Textarea.prototype, $.fn.textcomplete.Adapter.prototype, {\n    // Public methods\n    // --------------\n\n    // Update the textarea with the given value and strategy.\n    select: function (value, strategy) {\n        /*\n      var pre = this.getTextFromHeadToCaret();\n      var post = this.el.value.substring(this.el.selectionEnd);\n      var newSubstr = strategy.replace(value);\n      if ($.isArray(newSubstr)) {\n        post = newSubstr[1] + post;\n        newSubstr = newSubstr[0];\n      }\n      pre = pre.replace(strategy.match, newSubstr);\n      this.$el.val(pre + post);\n      this.el.selectionStart = this.el.selectionEnd = pre.length;\n      */\n        var cursor = editor.getCursor();\n        var pre = editor.getLine(cursor.line).slice(0, cursor.ch);\n        var match = pre.match(strategy.match);\n        if (!match) return;\n        pre = match[0];\n        var newSubstr = strategy.replace(value);\n        newSubstr = pre.replace(strategy.match, newSubstr);\n        \n        editor.operation(function() {\n          var selections = editor.listSelections();\n          var bias = match.index - cursor.ch;\n          for (var i = 0, l = selections.length; i < l; i++) {\n            var sel = selections[i];\n            var start = {\n              line: sel.head.line,\n              ch: sel.head.ch + bias\n            };\n            var end = {\n              line: sel.head.line,\n              ch: sel.head.ch + bias + match[0].length\n            };\n            editor.replaceRange(newSubstr, start, end, \"+input\");\n          }\n        });\n        \n        if(strategy.done)\n            strategy.done();\n    },\n\n    // Private methods\n    // ---------------\n\n    // Returns the caret's relative coordinates from textarea's left top corner.\n    //\n    // Browser native API does not provide the way to know the position of\n    // caret in pixels, so that here we use a kind of hack to accomplish\n    // the aim. First of all it puts a dummy div element and completely copies\n    // the textarea's style to the element, then it inserts the text and a\n    // span element into the textarea.\n    // Consequently, the span element's position is the thing what we want.\n    _getCaretRelativePosition: function () {\n      var dummyDiv = $('<div></div>').css(this._copyCss())\n        .text(this.getTextFromHeadToCaret());\n      var span = $('<span></span>').text('.').appendTo(dummyDiv);\n      this.$el.before(dummyDiv);\n      var position = span.position();\n      position.top += span.height() - this.$el.scrollTop();\n      position.lineHeight = span.height();\n      dummyDiv.remove();\n      return position;\n    },\n\n    _copyCss: function () {\n      return $.extend({\n        // Set 'scroll' if a scrollbar is being shown; otherwise 'auto'.\n        overflow: this.el.scrollHeight > this.el.offsetHeight ? 'scroll' : 'auto'\n      }, Textarea.DIV_PROPERTIES, this._getStyles());\n    },\n\n    _getStyles: (function ($) {\n      var color = $('<div></div>').css(['color']).color;\n      if (typeof color !== 'undefined') {\n        return function () {\n          return this.$el.css(Textarea.COPY_PROPERTIES);\n        };\n      } else { // jQuery < 1.8\n        return function () {\n          var $el = this.$el;\n          var styles = {};\n          $.each(Textarea.COPY_PROPERTIES, function (i, property) {\n            styles[property] = $el.css(property);\n          });\n          return styles;\n        };\n      }\n    })($),\n\n    getTextFromHeadToCaret: function () {\n      return this.el.value.substring(0, this.el.selectionEnd);\n    }\n  });\n\n  $.fn.textcomplete.Textarea = Textarea;\n}(jQuery);\n\n+function ($) {\n  'use strict';\n\n  var sentinelChar = '吶';\n\n  function IETextarea(element, completer, option) {\n    this.initialize(element, completer, option);\n    $('<span>' + sentinelChar + '</span>').css({\n      position: 'absolute',\n      top: -9999,\n      left: -9999\n    }).insertBefore(element);\n  }\n\n  $.extend(IETextarea.prototype, $.fn.textcomplete.Textarea.prototype, {\n    // Public methods\n    // --------------\n\n    select: function (value, strategy) {\n      var pre = this.getTextFromHeadToCaret();\n      var post = this.el.value.substring(pre.length);\n      var newSubstr = strategy.replace(value);\n      if ($.isArray(newSubstr)) {\n        post = newSubstr[1] + post;\n        newSubstr = newSubstr[0];\n      }\n      pre = pre.replace(strategy.match, newSubstr);\n      this.$el.val(pre + post);\n      this.el.focus();\n      var range = this.el.createTextRange();\n      range.collapse(true);\n      range.moveEnd('character', pre.length);\n      range.moveStart('character', pre.length);\n      range.select();\n    },\n\n    getTextFromHeadToCaret: function () {\n      this.el.focus();\n      var range = document.selection.createRange();\n      range.moveStart('character', -this.el.value.length);\n      var arr = range.text.split(sentinelChar)\n      return arr.length === 1 ? arr[0] : arr[1];\n    }\n  });\n\n  $.fn.textcomplete.IETextarea = IETextarea;\n}(jQuery);\n\n// NOTE: TextComplete plugin has contenteditable support but it does not work\n//       fine especially on old IEs.\n//       Any pull requests are REALLY welcome.\n\n+function ($) {\n  'use strict';\n\n  // ContentEditable adapter\n  // =======================\n  //\n  // Adapter for contenteditable elements.\n  function ContentEditable (element, completer, option) {\n    this.initialize(element, completer, option);\n  }\n\n  $.extend(ContentEditable.prototype, $.fn.textcomplete.Adapter.prototype, {\n    // Public methods\n    // --------------\n\n    // Update the content with the given value and strategy.\n    // When an dropdown item is selected, it is executed.\n    select: function (value, strategy) {\n      var pre = this.getTextFromHeadToCaret();\n      var sel = window.getSelection()\n      var range = sel.getRangeAt(0);\n      var selection = range.cloneRange();\n      selection.selectNodeContents(range.startContainer);\n      var content = selection.toString();\n      var post = content.substring(range.startOffset);\n      var newSubstr = strategy.replace(value);\n      if ($.isArray(newSubstr)) {\n        post = newSubstr[1] + post;\n        newSubstr = newSubstr[0];\n      }\n      pre = pre.replace(strategy.match, newSubstr);\n      range.selectNodeContents(range.startContainer);\n      range.deleteContents();\n      var node = document.createTextNode(pre + post);\n      range.insertNode(node);\n      range.setStart(node, pre.length);\n      range.collapse(true);\n      sel.removeAllRanges();\n      sel.addRange(range);\n    },\n\n    // Private methods\n    // ---------------\n\n    // Returns the caret's relative position from the contenteditable's\n    // left top corner.\n    //\n    // Examples\n    //\n    //   this._getCaretRelativePosition()\n    //   //=> { top: 18, left: 200, lineHeight: 16 }\n    //\n    // Dropdown's position will be decided using the result.\n    _getCaretRelativePosition: function () {\n      var range = window.getSelection().getRangeAt(0).cloneRange();\n      var node = document.createElement('span');\n      range.insertNode(node);\n      range.selectNodeContents(node);\n      range.deleteContents();\n      var $node = $(node);\n      var position = $node.offset();\n      position.left -= this.$el.offset().left;\n      position.top += $node.height() - this.$el.offset().top;\n      position.lineHeight = $node.height();\n      $node.remove();\n      var dir = this.$el.attr('dir') || this.$el.css('direction');\n      if (dir === 'rtl') { position.left -= this.listView.$el.width(); }\n      return position;\n    },\n\n    // Returns the string between the first character and the caret.\n    // Completer will be triggered with the result for start autocompleting.\n    //\n    // Example\n    //\n    //   // Suppose the html is '<b>hello</b> wor|ld' and | is the caret.\n    //   this.getTextFromHeadToCaret()\n    //   // => ' wor'  // not '<b>hello</b> wor'\n    getTextFromHeadToCaret: function () {\n      var range = window.getSelection().getRangeAt(0);\n      var selection = range.cloneRange();\n      selection.selectNodeContents(range.startContainer);\n      return selection.toString().substring(0, range.startOffset);\n    }\n  });\n\n  $.fn.textcomplete.ContentEditable = ContentEditable;\n}(jQuery);\n"
  },
  {
    "path": "public/vendor/md-toc.js",
    "content": "/* eslint-env browser, jquery */\n/**\n * md-toc.js v1.0.2\n * https://github.com/yijian166/md-toc.js\n *\n * Adapted to accept data attributes\n */\n\n(function (window) {\n  function Toc (id, options) {\n    this.el = document.getElementById(id)\n    if (!this.el) return\n    this.options = options || {}\n    this.tocLevel = parseInt(options.level) || 0\n    this.tocClass = options['class'] || 'toc'\n    this.ulClass = options['ulClass']\n    this.tocTop = parseInt(options.top) || 0\n    this.elChilds = this.el.children\n    this.process = options['process']\n    this.data = options.data || {}\n    if (!this.elChilds.length) return\n    this._init()\n  }\n\n  Toc.prototype._init = function () {\n    this._collectTitleElements()\n    this._createTocContent()\n    this._showToc()\n  }\n\n  Toc.prototype._collectTitleElements = function () {\n    this._elTitlesNames = []\n    this.elTitleElements = []\n    for (var i = 1; i < 6; i++) {\n      if (this.el.getElementsByTagName('h' + i).length) {\n        this._elTitlesNames.push('h' + i)\n      }\n    }\n\n    this._elTitlesNames.length = this._elTitlesNames.length > this.tocLevel ? this.tocLevel : this._elTitlesNames.length\n\n    for (var j = 0; j < this.elChilds.length; j++) {\n      this._elChildName = this.elChilds[j].tagName.toLowerCase()\n      if (this._elTitlesNames.toString().match(this._elChildName)) {\n        this.elTitleElements.push(this.elChilds[j])\n      }\n    }\n  }\n\n  Toc.prototype._createTocContent = function recursiveToc(level = 0, titleElements = [], titleNames = [], ulClass = undefined, index = 0) {\n    // Inititalize our elements from the toc object\n    // which is only available on level 0\n    if (level === 0) {\n      titleElements = this.elTitleElements\n      titleNames = this._elTitlesNames\n      ulClass = this.ulClass\n    }\n    // No need to do anything for an empty ToC\n    if (!titleElements.length) return\n\n    var content = '<ul'\n    if (ulClass) {\n      content += ' class=\"' + ulClass + '\"'\n    }\n    content += '>\\n'\n    var iterTag = titleNames[level]\n    var recurse = false\n    var openTag = false\n\n    for (var element; element = titleElements.shift();) {\n      var elementTag = element.tagName.toLowerCase()\n\n      // We only care about tags on our level to add them as list item\n      if (elementTag == iterTag) {\n        // Let's do some cleaning\n        var elementTitle = element.textContent.replace(/\"/g, '&quot;')\n        var elementText = (typeof this.process === 'function' ? this.process(element) : element.innerHTML).replace(/<(?:.|\\n)*?>/gm, '')\n        var id = element.getAttribute('id')\n        if (!id) {\n          element.setAttribute('id', 'tip' + ++index)\n          id = '#tip' + index\n        } else {\n          id = '#' + id\n        }\n        if (openTag) {\n          content += '</li>\\n'\n          openTag = false\n        }\n        content += '<li><a href=\"' + id + '\" title=\"'+ elementTitle +'\">' + elementText + '</a>'\n        // Reset recursion. We need it for the next subsections\n        recurse = false\n        openTag = true\n      // Check if the current element has a lower level than ours, if so, we have to go down the rabbithole!\n      } else if (!recurse && titleNames.indexOf(elementTag.toLowerCase()) > level) {\n        recurse = true\n        if (!openTag) {\n          content += '<li class=\"invisable-node\">'\n          openTag = true\n        }\n        // This element is for the lower lever, we have to re-add it before we send the list down there.\n        titleElements.unshift(element)\n        // Let's call ourself and get to the next level\n        content += recursiveToc(level + 1, titleElements, titleNames, ulClass, index)\n      } else {\n        // When we end up here, met a higher level element\n        // This is not our business so back into the list with the element and let's end this loop\n        titleElements.unshift(element)\n        break\n      }\n    }\n\n    if (openTag) {\n      content += '</li>\\n'\n    }\n    content += '</ul>\\n'\n\n    // Set ToC content of the level 0 everything else pass things to the upper level!\n    if (level === 0) {\n      this.tocContent = content\n    } else {\n      return content\n    }\n  }\n\n  Toc.prototype._showToc = function () {\n    this.toc = document.createElement('div')\n    this.toc.innerHTML = this.tocContent\n    this.toc.setAttribute('class', this.tocClass)\n    if (this.data.tocDepth) {\n      this.toc.dataset.tocDepth = this.data.tocDepth\n    }\n    if (!this.options.targetId) {\n      this.el.appendChild(this.toc)\n    } else {\n      document.getElementById(this.options.targetId).appendChild(this.toc)\n    }\n    var self = this\n    if (this.tocTop > -1) {\n      window.onscroll = function () {\n        var t = document.documentElement.scrollTop || document.body.scrollTop\n        if (t < self.tocTop) {\n          self.toc.setAttribute('style', 'position:absolute;top:' + self.tocTop + 'px;')\n        } else {\n          self.toc.setAttribute('style', 'position:fixed;top:10px;')\n        }\n      }\n    }\n  }\n  window.Toc = Toc\n})(window)\n"
  },
  {
    "path": "public/vendor/ot/ajax-adapter.js",
    "content": "/*global ot, $ */\n\not.AjaxAdapter = (function () {\n  'use strict';\n\n  function AjaxAdapter (path, ownUserName, revision) {\n    if (path[path.length - 1] !== '/') { path += '/'; }\n    this.path = path;\n    this.ownUserName = ownUserName;\n    this.majorRevision = revision.major || 0;\n    this.minorRevision = revision.minor || 0;\n    this.poll();\n  }\n\n  AjaxAdapter.prototype.renderRevisionPath = function () {\n    return 'revision/' + this.majorRevision + '-' + this.minorRevision;\n  };\n\n  AjaxAdapter.prototype.handleResponse = function (data) {\n    var i;\n    var operations = data.operations;\n    for (i = 0; i < operations.length; i++) {\n      if (operations[i].user === this.ownUserName) {\n        this.trigger('ack');\n      } else {\n        this.trigger('operation', operations[i].operation);\n      }\n    }\n    if (operations.length > 0) {\n      this.majorRevision += operations.length;\n      this.minorRevision = 0;\n    }\n\n    var events = data.events;\n    if (events) {\n      for (i = 0; i < events.length; i++) {\n        var user = events[i].user;\n        if (user === this.ownUserName) { continue; }\n        switch (events[i].event) {\n          case 'joined':    this.trigger('set_name', user, user); break;\n          case 'left':      this.trigger('client_left', user); break;\n          case 'selection': this.trigger('selection', user, events[i].selection); break;\n        }\n      }\n      this.minorRevision += events.length;\n    }\n\n    var users = data.users;\n    if (users) {\n      delete users[this.ownUserName];\n      this.trigger('clients', users);\n    }\n\n    if (data.revision) {\n      this.majorRevision = data.revision.major;\n      this.minorRevision = data.revision.minor;\n    }\n  };\n\n  AjaxAdapter.prototype.poll = function () {\n    var self = this;\n    $.ajax({\n      url: this.path + this.renderRevisionPath(),\n      type: 'GET',\n      dataType: 'json',\n      timeout: 5000,\n      success: function (data) {\n        self.handleResponse(data);\n        self.poll();\n      },\n      error: function () {\n        setTimeout(function () { self.poll(); }, 500);\n      }\n    });\n  };\n\n  AjaxAdapter.prototype.sendOperation = function (revision, operation, selection) {\n    if (revision !== this.majorRevision) { throw new Error(\"Revision numbers out of sync\"); }\n    var self = this;\n    $.ajax({\n      url: this.path + this.renderRevisionPath(),\n      type: 'POST',\n      data: JSON.stringify({ operation: operation, selection: selection }),\n      contentType: 'application/json',\n      processData: false,\n      success: function (data) {},\n      error: function () {\n        setTimeout(function () { self.sendOperation(revision, operation, selection); }, 500);\n      }\n    });\n  };\n\n  AjaxAdapter.prototype.sendSelection = function (obj) {\n    $.ajax({\n      url: this.path + this.renderRevisionPath() + '/selection',\n      type: 'POST',\n      data: JSON.stringify(obj),\n      contentType: 'application/json',\n      processData: false,\n      timeout: 1000\n    });\n  };\n\n  AjaxAdapter.prototype.registerCallbacks = function (cb) {\n    this.callbacks = cb;\n  };\n\n  AjaxAdapter.prototype.trigger = function (event) {\n    var args = Array.prototype.slice.call(arguments, 1);\n    var action = this.callbacks && this.callbacks[event];\n    if (action) { action.apply(this, args); }\n  };\n\n  return AjaxAdapter;\n\n})();"
  },
  {
    "path": "public/vendor/ot/client.js",
    "content": "// translation of https://github.com/djspiewak/cccp/blob/master/agent/src/main/scala/com/codecommit/cccp/agent/state.scala\n\nif (typeof ot === 'undefined') {\n  var ot = {};\n}\n\not.Client = (function (global) {\n  'use strict';\n\n  // Client constructor\n  function Client (revision) {\n    this.revision = revision; // the next expected revision number\n    this.setState(synchronized_); // start state\n  }\n\n  Client.prototype.setState = function (state) {\n    this.state = state;\n  };\n\n  // Call this method when the user changes the document.\n  Client.prototype.applyClient = function (operation) {\n    this.setState(this.state.applyClient(this, operation));\n  };\n\n  // Call this method with a new operation from the server\n  Client.prototype.applyServer = function (revision, operation) {\n    this.setState(this.state.applyServer(this, revision, operation));\n  };\n\n  Client.prototype.applyOperations = function (head, operations) {\n    this.setState(this.state.applyOperations(this, head, operations));\n  };\n\n  Client.prototype.serverAck = function (revision) {\n    this.setState(this.state.serverAck(this, revision));\n  };\n\n  Client.prototype.serverReconnect = function () {\n    if (typeof this.state.resend === 'function') { this.state.resend(this); }\n  };\n\n  // Transforms a selection from the latest known server state to the current\n  // client state. For example, if we get from the server the information that\n  // another user's cursor is at position 3, but the server hasn't yet received\n  // our newest operation, an insertion of 5 characters at the beginning of the\n  // document, the correct position of the other user's cursor in our current\n  // document is 8.\n  Client.prototype.transformSelection = function (selection) {\n    return this.state.transformSelection(selection);\n  };\n\n  // Override this method.\n  Client.prototype.sendOperation = function (revision, operation) {\n    throw new Error(\"sendOperation must be defined in child class\");\n  };\n\n  // Override this method.\n  Client.prototype.applyOperation = function (operation) {\n    throw new Error(\"applyOperation must be defined in child class\");\n  };\n\n\n  // In the 'Synchronized' state, there is no pending operation that the client\n  // has sent to the server.\n  function Synchronized () {}\n  Client.Synchronized = Synchronized;\n\n  Synchronized.prototype.applyClient = function (client, operation) {\n    // When the user makes an edit, send the operation to the server and\n    // switch to the 'AwaitingConfirm' state\n    client.sendOperation(client.revision, operation);\n    return new AwaitingConfirm(operation);\n  };\n\n  Synchronized.prototype.applyServer = function (client, revision, operation) {\n    if (revision - client.revision > 1) {\n      throw new Error(\"Invalid revision.\");\n    }\n    client.revision = revision;\n    // When we receive a new operation from the server, the operation can be\n    // simply applied to the current document\n    client.applyOperation(operation);\n    return this;\n  };\n\n  Synchronized.prototype.serverAck = function (client, revision) {\n    throw new Error(\"There is no pending operation.\");\n  };\n\n  // Nothing to do because the latest server state and client state are the same.\n  Synchronized.prototype.transformSelection = function (x) { return x; };\n\n  // Singleton\n  var synchronized_ = new Synchronized();\n\n\n  // In the 'AwaitingConfirm' state, there's one operation the client has sent\n  // to the server and is still waiting for an acknowledgement.\n  function AwaitingConfirm (outstanding) {\n    // Save the pending operation\n    this.outstanding = outstanding;\n  }\n  Client.AwaitingConfirm = AwaitingConfirm;\n\n  AwaitingConfirm.prototype.applyClient = function (client, operation) {\n    // When the user makes an edit, don't send the operation immediately,\n    // instead switch to 'AwaitingWithBuffer' state\n    return new AwaitingWithBuffer(this.outstanding, operation);\n  };\n\n  AwaitingConfirm.prototype.applyServer = function (client, revision, operation) {\n    if (revision - client.revision > 1) {\n      throw new Error(\"Invalid revision.\");\n    }\n    client.revision = revision;\n    // This is another client's operation. Visualization:\n    //\n    //                   /\\\n    // this.outstanding /  \\ operation\n    //                 /    \\\n    //                 \\    /\n    //  pair[1]         \\  / pair[0] (new outstanding)\n    //  (can be applied  \\/\n    //  to the client's\n    //  current document)\n    var pair = operation.constructor.transform(this.outstanding, operation);\n    client.applyOperation(pair[1]);\n    return new AwaitingConfirm(pair[0]);\n  };\n\n  AwaitingConfirm.prototype.serverAck = function (client, revision) {\n    if (revision - client.revision > 1) {\n      return new Stale(this.outstanding, client, revision).getOperations();\n    }\n    client.revision = revision;\n    // The client's operation has been acknowledged\n    // => switch to synchronized state\n    return synchronized_;\n  };\n\n  AwaitingConfirm.prototype.transformSelection = function (selection) {\n    return selection.transform(this.outstanding);\n  };\n\n  AwaitingConfirm.prototype.resend = function (client) {\n    // The confirm didn't come because the client was disconnected.\n    // Now that it has reconnected, we resend the outstanding operation.\n    client.sendOperation(client.revision, this.outstanding);\n  };\n\n\n  // In the 'AwaitingWithBuffer' state, the client is waiting for an operation\n  // to be acknowledged by the server while buffering the edits the user makes\n  function AwaitingWithBuffer (outstanding, buffer) {\n    // Save the pending operation and the user's edits since then\n    this.outstanding = outstanding;\n    this.buffer = buffer;\n  }\n  Client.AwaitingWithBuffer = AwaitingWithBuffer;\n\n  AwaitingWithBuffer.prototype.applyClient = function (client, operation) {\n    // Compose the user's changes onto the buffer\n    var newBuffer = this.buffer.compose(operation);\n    return new AwaitingWithBuffer(this.outstanding, newBuffer);\n  };\n\n  AwaitingWithBuffer.prototype.applyServer = function (client, revision, operation) {\n    if (revision - client.revision > 1) {\n      throw new Error(\"Invalid revision.\");\n    }\n    client.revision = revision;\n    // Operation comes from another client\n    //\n    //                       /\\\n    //     this.outstanding /  \\ operation\n    //                     /    \\\n    //                    /\\    /\n    //       this.buffer /  \\* / pair1[0] (new outstanding)\n    //                  /    \\/\n    //                  \\    /\n    //          pair2[1] \\  / pair2[0] (new buffer)\n    // the transformed    \\/\n    // operation -- can\n    // be applied to the\n    // client's current\n    // document\n    //\n    // * pair1[1]\n    var transform = operation.constructor.transform;\n    var pair1 = transform(this.outstanding, operation);\n    var pair2 = transform(this.buffer, pair1[1]);\n    client.applyOperation(pair2[1]);\n    return new AwaitingWithBuffer(pair1[0], pair2[0]);\n  };\n\n  AwaitingWithBuffer.prototype.serverAck = function (client, revision) {\n    if (revision - client.revision > 1) {\n      return new StaleWithBuffer(this.outstanding, this.buffer, client, revision).getOperations();\n    }\n    client.revision = revision;\n    // The pending operation has been acknowledged\n    // => send buffer\n    client.sendOperation(client.revision, this.buffer);\n    return new AwaitingConfirm(this.buffer);\n  };\n\n  AwaitingWithBuffer.prototype.transformSelection = function (selection) {\n    return selection.transform(this.outstanding).transform(this.buffer);\n  };\n\n  AwaitingWithBuffer.prototype.resend = function (client) {\n    // The confirm didn't come because the client was disconnected.\n    // Now that it has reconnected, we resend the outstanding operation.\n    client.sendOperation(client.revision, this.outstanding);\n  };\n\n\n  function Stale(acknowlaged, client, revision) {\n    this.acknowlaged = acknowlaged;\n    this.client = client;\n    this.revision = revision;\n  }\n  Client.Stale = Stale;\n\n  Stale.prototype.applyClient = function (client, operation) {\n    return new StaleWithBuffer(this.acknowlaged, operation, client, this.revision);\n  };\n\n  Stale.prototype.applyServer = function (client, revision, operation) {\n    throw new Error(\"Ignored server-side change.\");\n  };\n\n  Stale.prototype.applyOperations = function (client, head, operations) {\n    var transform = this.acknowlaged.constructor.transform;\n    for (var i = 0; i < operations.length; i++) {\n      var op = ot.TextOperation.fromJSON(operations[i]);\n      var pair = transform(this.acknowlaged, op);\n      client.applyOperation(pair[1]);\n      this.acknowlaged = pair[0];\n    }\n    client.revision = this.revision;\n    return synchronized_;\n  };\n\n  Stale.prototype.serverAck = function (client, revision) {\n    throw new Error(\"There is no pending operation.\");\n  };\n\n  Stale.prototype.transformSelection = function (selection) {\n    return selection;\n  };\n\n  Stale.prototype.getOperations = function () {\n    this.client.getOperations(this.client.revision, this.revision - 1); // acknowlaged is the one at revision\n    return this;\n  };\n\n\n  function StaleWithBuffer(acknowlaged, buffer, client, revision) {\n    this.acknowlaged = acknowlaged;\n    this.buffer = buffer;\n    this.client = client;\n    this.revision = revision;\n  }\n  Client.StaleWithBuffer = StaleWithBuffer;\n\n  StaleWithBuffer.prototype.applyClient = function (client, operation) {\n    var buffer = this.buffer.compose(operation);\n    return new StaleWithBuffer(this.acknowlaged, buffer, client, this.revision);\n  };\n\n  StaleWithBuffer.prototype.applyServer = function (client, revision, operation) {\n    throw new Error(\"Ignored server-side change.\");\n  };\n\n  StaleWithBuffer.prototype.applyOperations = function (client, head, operations) {\n    var transform = this.acknowlaged.constructor.transform;\n    for (var i = 0; i < operations.length; i++) {\n      var op = ot.TextOperation.fromJSON(operations[i]);\n      var pair1 = transform(this.acknowlaged, op);\n      var pair2 = transform(this.buffer, pair1[1]);\n      client.applyOperation(pair2[1]);\n      this.acknowlaged = pair1[0];\n      this.buffer = pair2[0];\n    }\n    client.revision = this.revision;\n    client.sendOperation(client.revision, this.buffer);\n    return new AwaitingConfirm(this.buffer);\n  };\n\n  StaleWithBuffer.prototype.serverAck = function (client, revision) {\n    throw new Error(\"There is no pending operation.\");\n  };\n\n  StaleWithBuffer.prototype.transformSelection = function (selection) {\n    return selection;\n  };\n\n  StaleWithBuffer.prototype.getOperations = function () {\n    this.client.getOperations(this.client.revision, this.revision - 1); // acknowlaged is the one at revision\n    return this;\n  };\n\n\n  return Client;\n\n}(this));\n\nif (typeof module === 'object') {\n  module.exports = ot.Client;\n}\n\n"
  },
  {
    "path": "public/vendor/ot/codemirror-adapter.js",
    "content": "/*global ot */\n\not.CodeMirrorAdapter = (function (global) {\n    'use strict';\n\n    var TextOperation = ot.TextOperation;\n    var Selection = ot.Selection;\n\n    function CodeMirrorAdapter(cm) {\n        this.cm = cm;\n        this.ignoreNextChange = false;\n        this.changeInProgress = false;\n        this.selectionChanged = false;\n\n        bind(this, 'onChanges');\n        bind(this, 'onChange');\n        bind(this, 'onCursorActivity');\n        bind(this, 'onFocus');\n        bind(this, 'onBlur');\n\n        cm.on('changes', this.onChanges);\n        cm.on('change', this.onChange);\n        cm.on('cursorActivity', this.onCursorActivity);\n        cm.on('focus', this.onFocus);\n        cm.on('blur', this.onBlur);\n    }\n\n    // Removes all event listeners from the CodeMirror instance.\n    CodeMirrorAdapter.prototype.detach = function () {\n        this.cm.off('changes', this.onChanges);\n        this.cm.off('change', this.onChange);\n        this.cm.off('cursorActivity', this.onCursorActivity);\n        this.cm.off('focus', this.onFocus);\n        this.cm.off('blur', this.onBlur);\n    };\n\n    function cmpPos(a, b) {\n        if (a.line < b.line) {\n            return -1;\n        }\n        if (a.line > b.line) {\n            return 1;\n        }\n        if (a.ch < b.ch) {\n            return -1;\n        }\n        if (a.ch > b.ch) {\n            return 1;\n        }\n        return 0;\n    }\n\n    function posEq(a, b) {\n        return cmpPos(a, b) === 0;\n    }\n\n    function posLe(a, b) {\n        return cmpPos(a, b) <= 0;\n    }\n\n    function minPos(a, b) {\n        return posLe(a, b) ? a : b;\n    }\n\n    function maxPos(a, b) {\n        return posLe(a, b) ? b : a;\n    }\n\n    function codemirrorDocLength(doc) {\n        return doc.indexFromPos({\n                line: doc.lastLine(),\n                ch: 0\n            }) +\n            doc.getLine(doc.lastLine()).length;\n    }\n\n    // Converts a CodeMirror change array (as obtained from the 'changes' event\n    // in CodeMirror v4) or single change or linked list of changes (as returned\n    // by the 'change' event in CodeMirror prior to version 4) into a\n    // TextOperation and its inverse and returns them as a two-element array.\n    CodeMirrorAdapter.operationFromCodeMirrorChanges = function (changes, doc) {\n        // Approach: Replay the changes, beginning with the most recent one, and\n        // construct the operation and its inverse. We have to convert the position\n        // in the pre-change coordinate system to an index. We have a method to\n        // convert a position in the coordinate system after all changes to an index,\n        // namely CodeMirror's `indexFromPos` method. We can use the information of\n        // a single change object to convert a post-change coordinate system to a\n        // pre-change coordinate system. We can now proceed inductively to get a\n        // pre-change coordinate system for all changes in the linked list.\n        // A disadvantage of this approach is its complexity `O(n^2)` in the length\n        // of the linked list of changes.\n\n        var docEndLength = codemirrorDocLength(doc);\n        var operation = new TextOperation().retain(docEndLength);\n        var inverse = new TextOperation().retain(docEndLength);\n\n        var indexFromPos = function (pos) {\n            return doc.indexFromPos(pos);\n        };\n\n        function last(arr) {\n            return arr[arr.length - 1];\n        }\n\n        function sumLengths(strArr) {\n            if (strArr.length === 0) {\n                return 0;\n            }\n            var sum = 0;\n            for (var i = 0; i < strArr.length; i++) {\n                sum += strArr[i].length;\n            }\n            return sum + strArr.length - 1;\n        }\n\n        function updateIndexFromPos(indexFromPos, change) {\n            return function (pos) {\n                if (posLe(pos, change.from)) {\n                    return indexFromPos(pos);\n                }\n                if (posLe(change.to, pos)) {\n                    return indexFromPos({\n                        line: pos.line + change.text.length - 1 - (change.to.line - change.from.line),\n                        ch: (change.to.line < pos.line) ?\n                            pos.ch : (change.text.length <= 1) ?\n                            pos.ch - (change.to.ch - change.from.ch) + sumLengths(change.text) : pos.ch - change.to.ch + last(change.text).length\n                    }) + sumLengths(change.removed) - sumLengths(change.text);\n                }\n                if (change.from.line === pos.line) {\n                    return indexFromPos(change.from) + pos.ch - change.from.ch;\n                }\n                return indexFromPos(change.from) +\n                    sumLengths(change.removed.slice(0, pos.line - change.from.line)) +\n                    1 + pos.ch;\n            };\n        }\n\n        for (var i = changes.length - 1; i >= 0; i--) {\n            var change = changes[i];\n            indexFromPos = updateIndexFromPos(indexFromPos, change);\n\n            var fromIndex = indexFromPos(change.from);\n            var restLength = docEndLength - fromIndex - sumLengths(change.text);\n\n            operation = new TextOperation()\n                .retain(fromIndex)['delete'](sumLengths(change.removed))\n                .insert(change.text.join('\\n'))\n                .retain(restLength)\n                .compose(operation);\n\n            inverse = inverse.compose(new TextOperation()\n                .retain(fromIndex)['delete'](sumLengths(change.text))\n                .insert(change.removed.join('\\n'))\n                .retain(restLength)\n            );\n\n            docEndLength += sumLengths(change.removed) - sumLengths(change.text);\n        }\n\n        return [operation, inverse];\n    };\n\n    // Singular form for backwards compatibility.\n    CodeMirrorAdapter.operationFromCodeMirrorChange =\n        CodeMirrorAdapter.operationFromCodeMirrorChanges;\n\n    // Apply an operation to a CodeMirror instance.\n    CodeMirrorAdapter.applyOperationToCodeMirror = function (operation, cm) {\n        cm.operation(function () {\n            var ops = operation.ops;\n            var index = 0; // holds the current index into CodeMirror's content\n            for (var i = 0, l = ops.length; i < l; i++) {\n                var op = ops[i];\n                if (TextOperation.isRetain(op)) {\n                    index += op;\n                } else if (TextOperation.isInsert(op)) {\n                    cm.replaceRange(op, cm.posFromIndex(index), null, 'ignoreHistory');\n                    index += op.length;\n                } else if (TextOperation.isDelete(op)) {\n                    var from = cm.posFromIndex(index);\n                    var to = cm.posFromIndex(index - op);\n                    cm.replaceRange('', from, to, 'ignoreHistory');\n                }\n            }\n        });\n    };\n\n    CodeMirrorAdapter.prototype.registerCallbacks = function (cb) {\n        this.callbacks = cb;\n    };\n\n    CodeMirrorAdapter.prototype.onChange = function () {\n        // By default, CodeMirror's event order is the following:\n        // 1. 'change', 2. 'cursorActivity', 3. 'changes'.\n        // We want to fire the 'selectionChange' event after the 'change' event,\n        // but need the information from the 'changes' event. Therefore, we detect\n        // when a change is in progress by listening to the change event, setting\n        // a flag that makes this adapter defer all 'cursorActivity' events.\n        this.changeInProgress = true;\n    };\n\n    CodeMirrorAdapter.prototype.onChanges = function (_, changes) {\n        if (!this.ignoreNextChange) {\n            var pair = CodeMirrorAdapter.operationFromCodeMirrorChanges(changes, this.cm);\n            this.trigger('change', pair[0], pair[1]);\n        }\n        if (this.selectionChanged) {\n            this.trigger('selectionChange');\n        }\n        this.changeInProgress = false;\n        this.ignoreNextChange = false;\n    };\n\n    CodeMirrorAdapter.prototype.onCursorActivity =\n        CodeMirrorAdapter.prototype.onFocus = function () {\n            if (this.changeInProgress) {\n                this.selectionChanged = true;\n            } else {\n                this.trigger('selectionChange');\n            }\n        };\n\n    CodeMirrorAdapter.prototype.onBlur = function () {\n        if (!this.cm.somethingSelected()) {\n            this.trigger('blur');\n        }\n    };\n\n    CodeMirrorAdapter.prototype.getValue = function () {\n        return this.cm.getValue();\n    };\n\n    CodeMirrorAdapter.prototype.getSelection = function () {\n        var cm = this.cm;\n\n        var selectionList = cm.listSelections();\n        var ranges = [];\n        for (var i = 0; i < selectionList.length; i++) {\n            ranges[i] = new Selection.Range(\n                cm.indexFromPos(selectionList[i].anchor),\n                cm.indexFromPos(selectionList[i].head)\n            );\n        }\n\n        return new Selection(ranges);\n    };\n\n    CodeMirrorAdapter.prototype.setSelection = function (selection) {\n        var ranges = [];\n        for (var i = 0; selection && i < selection.ranges.length; i++) {\n            var range = selection.ranges[i];\n            ranges[i] = {\n                anchor: this.cm.posFromIndex(range.anchor),\n                head: this.cm.posFromIndex(range.head)\n            };\n        }\n        this.cm.setSelections(ranges);\n    };\n\n    var addStyleRule = (function () {\n        var added = {};\n        var styleElement = document.createElement('style');\n        document.documentElement.getElementsByTagName('head')[0].appendChild(styleElement);\n        var styleSheet = styleElement.sheet;\n\n        return function (css) {\n            if (added[css]) {\n                return;\n            }\n            added[css] = true;\n            styleSheet.insertRule(css, (styleSheet.cssRules || styleSheet.rules).length);\n        };\n    }());\n\n    CodeMirrorAdapter.prototype.setOtherCursor = function (position, color, clientId) {\n        var cursorPos = this.cm.posFromIndex(position);\n        var cursorCoords = this.cm.cursorCoords(cursorPos);\n        var cursorEl = document.createElement('span');\n        cursorEl.className = 'other-client';\n        cursorEl.style.display = 'none';\n        /*\n        cursorEl.style.padding = '0';\n        cursorEl.style.marginLeft = cursorEl.style.marginRight = '-1px';\n        cursorEl.style.borderLeftWidth = '2px';\n        cursorEl.style.borderLeftStyle = 'solid';\n        cursorEl.style.borderLeftColor = color;\n        cursorEl.style.height = (cursorCoords.bottom - cursorCoords.top) * 0.9 + 'px';\n        cursorEl.style.zIndex = 0;\n        */\n        cursorEl.setAttribute('data-clientid', clientId);\n        return this.cm.setBookmark(cursorPos, {\n            widget: cursorEl,\n            insertLeft: true\n        });\n    };\n\n    CodeMirrorAdapter.prototype.setOtherSelectionRange = function (range, color, clientId) {\n        var match = /^#([0-9a-fA-F]{6})$/.exec(color);\n        if (!match) {\n            throw new Error(\"only six-digit hex colors are allowed.\");\n        }\n        var selectionClassName = 'selection-' + match[1];\n        var rgbcolor = hex2rgb(color);\n        var rule = '.' + selectionClassName + ' { background: rgba(' + rgbcolor.red + ',' + rgbcolor.green + ',' + rgbcolor.blue + ',0.2); }';\n        addStyleRule(rule);\n\n        var anchorPos = this.cm.posFromIndex(range.anchor);\n        var headPos = this.cm.posFromIndex(range.head);\n\n        return this.cm.markText(\n            minPos(anchorPos, headPos),\n            maxPos(anchorPos, headPos), {\n                className: selectionClassName\n            }\n        );\n    };\n\n    CodeMirrorAdapter.prototype.setOtherSelection = function (selection, color, clientId) {\n        var selectionObjects = [];\n        for (var i = 0; i < selection.ranges.length; i++) {\n            var range = selection.ranges[i];\n            if (range.isEmpty()) {\n                //selectionObjects[i] = this.setOtherCursor(range.head, color, clientId);\n            } else {\n                selectionObjects[i] = this.setOtherSelectionRange(range, color, clientId);\n            }\n        }\n        return {\n            clear: function () {\n                for (var i = 0; i < selectionObjects.length; i++) {\n                    if (selectionObjects[i]) selectionObjects[i].clear();\n                }\n            }\n        };\n    };\n\n    CodeMirrorAdapter.prototype.trigger = function (event) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        var action = this.callbacks && this.callbacks[event];\n        if (action) {\n            action.apply(this, args);\n        }\n    };\n\n    CodeMirrorAdapter.prototype.applyOperation = function (operation) {\n        if (!operation.isNoop()) {\n            this.ignoreNextChange = true;\n        }\n        CodeMirrorAdapter.applyOperationToCodeMirror(operation, this.cm);\n    };\n\n    CodeMirrorAdapter.prototype.registerUndo = function (undoFn) {\n        this.cm.undo = undoFn;\n    };\n\n    CodeMirrorAdapter.prototype.registerRedo = function (redoFn) {\n        this.cm.redo = redoFn;\n    };\n\n    // Throws an error if the first argument is falsy. Useful for debugging.\n    function assert(b, msg) {\n        if (!b) {\n            throw new Error(msg || \"assertion error\");\n        }\n    }\n\n    // Bind a method to an object, so it doesn't matter whether you call\n    // object.method() directly or pass object.method as a reference to another\n    // function.\n    function bind(obj, method) {\n        var fn = obj[method];\n        obj[method] = function () {\n            fn.apply(obj, arguments);\n        };\n    }\n\n    return CodeMirrorAdapter;\n\n}(this));\n\nfunction hex2rgb(hex) {\n    if (hex[0] == \"#\") hex = hex.substr(1);\n    if (hex.length == 3) {\n        var temp = hex;\n        hex = '';\n        temp = /^([a-f0-9])([a-f0-9])([a-f0-9])$/i.exec(temp).slice(1);\n        for (var i = 0; i < 3; i++) hex += temp[i] + temp[i];\n    }\n    var triplets = /^([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i.exec(hex).slice(1);\n    return {\n        red: parseInt(triplets[0], 16),\n        green: parseInt(triplets[1], 16),\n        blue: parseInt(triplets[2], 16)\n    }\n}"
  },
  {
    "path": "public/vendor/ot/compress.sh",
    "content": "uglifyjs --compress --mangle --output ot.min.js \\\n./text-operation.js \\\n./selection.js \\\n./wrapped-operation.js \\\n./undo-manager.js \\\n./client.js \\\n./codemirror-adapter.js \\\n./socketio-adapter.js \\\n./ajax-adapter.js \\\n./editor-client.js"
  },
  {
    "path": "public/vendor/ot/editor-client.js",
    "content": "/*global ot */\n\not.EditorClient = (function () {\n  'use strict';\n\n  var Client = ot.Client;\n  var Selection = ot.Selection;\n  var UndoManager = ot.UndoManager;\n  var TextOperation = ot.TextOperation;\n  var WrappedOperation = ot.WrappedOperation;\n\n\n  function SelfMeta (selectionBefore, selectionAfter) {\n    this.selectionBefore = selectionBefore;\n    this.selectionAfter  = selectionAfter;\n  }\n\n  SelfMeta.prototype.invert = function () {\n    return new SelfMeta(this.selectionAfter, this.selectionBefore);\n  };\n\n  SelfMeta.prototype.compose = function (other) {\n    return new SelfMeta(this.selectionBefore, other.selectionAfter);\n  };\n\n  SelfMeta.prototype.transform = function (operation) {\n    return new SelfMeta(\n      (this.selectionBefore ? this.selectionBefore.transform(operation) : null),\n      (this.selectionAfter ? this.selectionAfter.transform(operation) : null)\n    );\n  };\n\n\n  function OtherMeta (clientId, selection) {\n    this.clientId  = clientId;\n    this.selection = selection;\n  }\n\n  OtherMeta.fromJSON = function (obj) {\n    return new OtherMeta(\n      obj.clientId,\n      obj.selection && Selection.fromJSON(obj.selection)\n    );\n  };\n\n  OtherMeta.prototype.transform = function (operation) {\n    return new OtherMeta(\n      this.clientId,\n      this.selection && this.selection.transform(operation)\n    );\n  };\n\n\n  function OtherClient (id, listEl, editorAdapter, name, color, selection) {\n    this.id = id;\n    this.listEl = listEl;\n    this.editorAdapter = editorAdapter;\n    this.name = name;\n    this.color = color;\n\n    this.li = document.createElement('li');\n    if (name) {\n      this.li.textContent = name;\n      this.listEl.appendChild(this.li);\n    }\n    \n    if(!color)\n      this.setColor(name ? hueFromName(name) : Math.random());\n    else\n      this.setForceColor(color);\n    if (selection) { this.updateSelection(selection); }\n  }\n\n  OtherClient.prototype.setColor = function (hue) {\n    this.hue = hue;\n    this.color = hsl2hex(hue, 0.75, 0.5);\n    this.lightColor = hsl2hex(hue, 0.5, 0.9);\n    if (this.li) { this.li.style.color = this.color; }\n  };\n    \n  OtherClient.prototype.setForceColor = function (color) {\n    this.hue = null;\n    this.color = color;\n    this.lightColor = color;\n    if (this.li) { this.li.style.color = this.color; }\n  };\n\n  OtherClient.prototype.setName = function (name) {\n    if (this.name === name) { return; }\n    this.name = name;\n\n    this.li.textContent = name;\n    if (!this.li.parentNode) {\n      this.listEl.appendChild(this.li);\n    }\n\n    this.setColor(hueFromName(name));\n  };\n\n  OtherClient.prototype.updateSelection = function (selection) {\n    this.removeSelection();\n    this.selection = selection;\n    this.mark = this.editorAdapter.setOtherSelection(\n      selection,\n      selection.position === selection.selectionEnd ? this.color : this.lightColor,\n      this.id\n    );\n  };\n\n  OtherClient.prototype.remove = function () {\n    if (this.li) { removeElement(this.li); }\n    this.removeSelection();\n  };\n\n  OtherClient.prototype.removeSelection = function () {\n    if (this.mark) {\n      this.mark.clear();\n      this.mark = null;\n    }\n  };\n\n\n  function EditorClient (revision, clients, serverAdapter, editorAdapter) {\n    Client.call(this, revision);\n    this.serverAdapter = serverAdapter;\n    this.editorAdapter = editorAdapter;\n    this.undoManager = new UndoManager();\n\n    this.initializeClientList();\n    this.initializeClients(clients);\n\n    var self = this;\n\n    this.editorAdapter.registerCallbacks({\n      change: function (operation, inverse) { self.onChange(operation, inverse); },\n      selectionChange: function () { self.onSelectionChange(); },\n      blur: function () { self.onBlur(); }\n    });\n    this.editorAdapter.registerUndo(function () { self.undo(); });\n    this.editorAdapter.registerRedo(function () { self.redo(); });\n\n    this.serverAdapter.registerCallbacks({\n      client_left: function (clientId) { self.onClientLeft(clientId); },\n      set_name: function (clientId, name) { self.getClientObject(clientId).setName(name); },\n      set_color: function (clientId, color) { self.getClientObject(clientId).setForceColor(color); },\n      ack: function (revision) { self.serverAck(revision); },\n      operation: function (revision, operation) {\n        self.applyServer(revision, TextOperation.fromJSON(operation));\n      },\n      operations: function (head, operations) {\n        self.applyOperations(head, operations);\n      },\n      selection: function (clientId, selection) {\n        if (selection) {\n          self.getClientObject(clientId).updateSelection(\n            self.transformSelection(Selection.fromJSON(selection))\n          );\n        } else {\n          self.getClientObject(clientId).removeSelection();\n        }\n      },\n      clients: function (clients) {\n        var clientId;\n        for (clientId in self.clients) {\n          if (self.clients.hasOwnProperty(clientId) && !clients.hasOwnProperty(clientId)) {\n            self.onClientLeft(clientId);\n          }\n        }\n\n        for (clientId in clients) {\n          if (clients.hasOwnProperty(clientId)) {\n            var clientObject = self.getClientObject(clientId);\n\n            if (clients[clientId].name) {\n              clientObject.setName(clients[clientId].name);\n            }\n\n            var selection = clients[clientId].selection;\n            if (selection) {\n              self.clients[clientId].updateSelection(\n                self.transformSelection(Selection.fromJSON(selection))\n              );\n            } else {\n              self.clients[clientId].removeSelection();\n            }\n          }\n        }\n      },\n      reconnect: function () { self.serverReconnect(); }\n    });\n  }\n\n  inherit(EditorClient, Client);\n\n  EditorClient.prototype.addClient = function (clientId, clientObj) {\n    this.clients[clientId] = new OtherClient(\n      clientId,\n      this.clientListEl,\n      this.editorAdapter,\n      clientObj.name || clientId,\n      clientObj.color || null,\n      clientObj.selection ? Selection.fromJSON(clientObj.selection) : null\n    );\n  };\n\n  EditorClient.prototype.initializeClients = function (clients) {\n    this.clients = {};\n    for (var clientId in clients) {\n      if (clients.hasOwnProperty(clientId)) {\n        this.addClient(clientId, clients[clientId]);\n      }\n    }\n  };\n\n  EditorClient.prototype.getClientObject = function (clientId) {\n    var client = this.clients[clientId];\n    if (client) { return client; }\n    return this.clients[clientId] = new OtherClient(\n      clientId,\n      this.clientListEl,\n      this.editorAdapter\n    );\n  };\n\n  EditorClient.prototype.onClientLeft = function (clientId) {\n    //console.log(\"User disconnected: \" + clientId);\n    var client = this.clients[clientId];\n    if (!client) { return; }\n    client.remove();\n    delete this.clients[clientId];\n  };\n\n  EditorClient.prototype.initializeClientList = function () {\n    this.clientListEl = document.createElement('ul');\n  };\n\n  EditorClient.prototype.applyUnredo = function (operation) {\n    this.undoManager.add(operation.invert(this.editorAdapter.getValue()));\n    this.editorAdapter.applyOperation(operation.wrapped);\n    this.selection = operation.meta.selectionAfter;\n    this.editorAdapter.setSelection(this.selection);\n    this.applyClient(operation.wrapped);\n  };\n\n  EditorClient.prototype.undo = function () {\n    var self = this;\n    if (!this.undoManager.canUndo()) { return; }\n    this.undoManager.performUndo(function (o) { self.applyUnredo(o); });\n  };\n\n  EditorClient.prototype.redo = function () {\n    var self = this;\n    if (!this.undoManager.canRedo()) { return; }\n    this.undoManager.performRedo(function (o) { self.applyUnredo(o); });\n  };\n\n  EditorClient.prototype.onChange = function (textOperation, inverse) {\n    var selectionBefore = this.selection;\n    this.updateSelection();\n    var meta = new SelfMeta(selectionBefore, this.selection);\n    var operation = new WrappedOperation(textOperation, meta);\n\n    var compose = this.undoManager.undoStack.length > 0 &&\n      inverse.shouldBeComposedWithInverted(last(this.undoManager.undoStack).wrapped);\n    var inverseMeta = new SelfMeta(this.selection, selectionBefore);\n    this.undoManager.add(new WrappedOperation(inverse, inverseMeta), compose);\n    this.applyClient(textOperation);\n  };\n\n  EditorClient.prototype.updateSelection = function () {\n    this.selection = this.editorAdapter.getSelection();\n  };\n\n  EditorClient.prototype.onSelectionChange = function () {\n    var oldSelection = this.selection;\n    this.updateSelection();\n    if (oldSelection && this.selection.equals(oldSelection)) { return; }\n    this.sendSelection(this.selection);\n  };\n\n  EditorClient.prototype.onBlur = function () {\n    this.selection = null;\n    this.sendSelection(null);\n  };\n\n  EditorClient.prototype.sendSelection = function (selection) {\n    if (this.state instanceof Client.AwaitingWithBuffer) { return; }\n    this.serverAdapter.sendSelection(selection);\n  };\n\n  EditorClient.prototype.sendOperation = function (revision, operation) {\n    this.serverAdapter.sendOperation(revision, operation.toJSON(), this.selection);\n  };\n\n  EditorClient.prototype.getOperations = function (base, head) {\n    this.serverAdapter.getOperations(base, head);\n  };\n\n  EditorClient.prototype.applyOperation = function (operation) {\n    this.editorAdapter.applyOperation(operation);\n    this.updateSelection();\n    this.undoManager.transform(new WrappedOperation(operation, null));\n  };\n\n  function rgb2hex (r, g, b) {\n    function digits (n) {\n      var m = Math.round(255*n).toString(16);\n      return m.length === 1 ? '0'+m : m;\n    }\n    return '#' + digits(r) + digits(g) + digits(b);\n  }\n\n  function hsl2hex (h, s, l) {\n    if (s === 0) { return rgb2hex(l, l, l); }\n    var var2 = l < 0.5 ? l * (1+s) : (l+s) - (s*l);\n    var var1 = 2 * l - var2;\n    var hue2rgb = function (hue) {\n      if (hue < 0) { hue += 1; }\n      if (hue > 1) { hue -= 1; }\n      if (6*hue < 1) { return var1 + (var2-var1)*6*hue; }\n      if (2*hue < 1) { return var2; }\n      if (3*hue < 2) { return var1 + (var2-var1)*6*(2/3 - hue); }\n      return var1;\n    };\n    return rgb2hex(hue2rgb(h+1/3), hue2rgb(h), hue2rgb(h-1/3));\n  }\n\n  function hueFromName (name) {\n    var a = 1;\n    for (var i = 0; i < name.length; i++) {\n      a = 17 * (a+name.charCodeAt(i)) % 360;\n    }\n    return a/360;\n  }\n\n  // Set Const.prototype.__proto__ to Super.prototype\n  function inherit (Const, Super) {\n    function F () {}\n    F.prototype = Super.prototype;\n    Const.prototype = new F();\n    Const.prototype.constructor = Const;\n  }\n\n  function last (arr) { return arr[arr.length - 1]; }\n\n  // Remove an element from the DOM.\n  function removeElement (el) {\n    if (el.parentNode) {\n      el.parentNode.removeChild(el);\n    }\n  }\n\n  return EditorClient;\n}());\n"
  },
  {
    "path": "public/vendor/ot/selection.js",
    "content": "if (typeof ot === 'undefined') {\n  // Export for browsers\n  var ot = {};\n}\n\not.Selection = (function (global) {\n  'use strict';\n\n  var TextOperation = global.ot ? global.ot.TextOperation : require('./text-operation');\n\n  // Range has `anchor` and `head` properties, which are zero-based indices into\n  // the document. The `anchor` is the side of the selection that stays fixed,\n  // `head` is the side of the selection where the cursor is. When both are\n  // equal, the range represents a cursor.\n  function Range (anchor, head) {\n    this.anchor = anchor;\n    this.head = head;\n  }\n\n  Range.fromJSON = function (obj) {\n    return new Range(obj.anchor, obj.head);\n  };\n\n  Range.prototype.equals = function (other) {\n    return this.anchor === other.anchor && this.head === other.head;\n  };\n\n  Range.prototype.isEmpty = function () {\n    return this.anchor === this.head;\n  };\n\n  Range.prototype.transform = function (other) {\n    function transformIndex (index) {\n      var newIndex = index;\n      var ops = other.ops;\n      for (var i = 0, l = other.ops.length; i < l; i++) {\n        if (TextOperation.isRetain(ops[i])) {\n          index -= ops[i];\n        } else if (TextOperation.isInsert(ops[i])) {\n          newIndex += ops[i].length;\n        } else {\n          newIndex -= Math.min(index, -ops[i]);\n          index += ops[i];\n        }\n        if (index < 0) { break; }\n      }\n      return newIndex;\n    }\n\n    var newAnchor = transformIndex(this.anchor);\n    if (this.anchor === this.head) {\n      return new Range(newAnchor, newAnchor);\n    }\n    return new Range(newAnchor, transformIndex(this.head));\n  };\n\n  // A selection is basically an array of ranges. Every range represents a real\n  // selection or a cursor in the document (when the start position equals the\n  // end position of the range). The array must not be empty.\n  function Selection (ranges) {\n    this.ranges = ranges || [];\n  }\n\n  Selection.Range = Range;\n\n  // Convenience method for creating selections only containing a single cursor\n  // and no real selection range.\n  Selection.createCursor = function (position) {\n    return new Selection([new Range(position, position)]);\n  };\n\n  Selection.fromJSON = function (obj) {\n    var objRanges = obj.ranges || obj;\n    for (var i = 0, ranges = []; i < objRanges.length; i++) {\n      ranges[i] = Range.fromJSON(objRanges[i]);\n    }\n    return new Selection(ranges);\n  };\n\n  Selection.prototype.equals = function (other) {\n    if (this.position !== other.position) { return false; }\n    if (this.ranges.length !== other.ranges.length) { return false; }\n    // FIXME: Sort ranges before comparing them?\n    for (var i = 0; i < this.ranges.length; i++) {\n      if (!this.ranges[i].equals(other.ranges[i])) { return false; }\n    }\n    return true;\n  };\n\n  Selection.prototype.somethingSelected = function () {\n    for (var i = 0; i < this.ranges.length; i++) {\n      if (!this.ranges[i].isEmpty()) { return true; }\n    }\n    return false;\n  };\n\n  // Return the more current selection information.\n  Selection.prototype.compose = function (other) {\n    return other;\n  };\n\n  // Update the selection with respect to an operation.\n  Selection.prototype.transform = function (other) {\n    for (var i = 0, newRanges = []; i < this.ranges.length; i++) {\n      newRanges[i] = this.ranges[i].transform(other);\n    }\n    return new Selection(newRanges);\n  };\n\n  return Selection;\n\n}(this));\n\n// Export for CommonJS\nif (typeof module === 'object') {\n  module.exports = ot.Selection;\n}\n"
  },
  {
    "path": "public/vendor/ot/socketio-adapter.js",
    "content": "/*global ot */\n\not.SocketIOAdapter = (function () {\n    'use strict';\n\n    function SocketIOAdapter(socket) {\n        this.socket = socket;\n\n        var self = this;\n        socket.on('client_left', function (clientId) {\n            self.trigger('client_left', clientId);\n        });\n        socket.on('set_name', function (clientId, name) {\n            self.trigger('set_name', clientId, name);\n        });\n        socket.on('set_color', function (clientId, color) {\n            self.trigger('set_color', clientId, color);\n        });\n        socket.on('ack', function (revision) {\n            self.trigger('ack', revision);\n        });\n        socket.on('operation', function (clientId, revision, operation, selection) {\n            self.trigger('operation', revision, operation);\n            self.trigger('selection', clientId, selection);\n        });\n        socket.on('operations', function (head, operations) {\n            self.trigger('operations', head, operations);\n        });\n        socket.on('selection', function (clientId, selection) {\n            self.trigger('selection', clientId, selection);\n        });\n        socket.on('reconnect', function () {\n            self.trigger('reconnect');\n        });\n    }\n\n    SocketIOAdapter.prototype.sendOperation = function (revision, operation, selection) {\n        this.socket.emit('operation', revision, operation, selection);\n    };\n\n    SocketIOAdapter.prototype.sendSelection = function (selection) {\n        this.socket.emit('selection', selection);\n    };\n\n    SocketIOAdapter.prototype.getOperations = function (base, head) {\n        this.socket.emit('get_operations', base, head);\n    };\n\n    SocketIOAdapter.prototype.registerCallbacks = function (cb) {\n        this.callbacks = cb;\n    };\n\n    SocketIOAdapter.prototype.trigger = function (event) {\n        var args = Array.prototype.slice.call(arguments, 1);\n        var action = this.callbacks && this.callbacks[event];\n        if (action) {\n            action.apply(this, args);\n        }\n    };\n\n    return SocketIOAdapter;\n\n}());"
  },
  {
    "path": "public/vendor/ot/text-operation.js",
    "content": "if (typeof ot === 'undefined') {\n  // Export for browsers\n  var ot = {};\n}\n\not.TextOperation = (function () {\n  'use strict';\n\n  // Constructor for new operations.\n  function TextOperation () {\n    if (!this || this.constructor !== TextOperation) {\n      // => function was called without 'new'\n      return new TextOperation();\n    }\n\n    // When an operation is applied to an input string, you can think of this as\n    // if an imaginary cursor runs over the entire string and skips over some\n    // parts, deletes some parts and inserts characters at some positions. These\n    // actions (skip/delete/insert) are stored as an array in the \"ops\" property.\n    this.ops = [];\n    // An operation's baseLength is the length of every string the operation\n    // can be applied to.\n    this.baseLength = 0;\n    // The targetLength is the length of every string that results from applying\n    // the operation on a valid input string.\n    this.targetLength = 0;\n  }\n\n  TextOperation.prototype.equals = function (other) {\n    if (this.baseLength !== other.baseLength) { return false; }\n    if (this.targetLength !== other.targetLength) { return false; }\n    if (this.ops.length !== other.ops.length) { return false; }\n    for (var i = 0; i < this.ops.length; i++) {\n      if (this.ops[i] !== other.ops[i]) { return false; }\n    }\n    return true;\n  };\n\n  // Operation are essentially lists of ops. There are three types of ops:\n  //\n  // * Retain ops: Advance the cursor position by a given number of characters.\n  //   Represented by positive ints.\n  // * Insert ops: Insert a given string at the current cursor position.\n  //   Represented by strings.\n  // * Delete ops: Delete the next n characters. Represented by negative ints.\n\n  var isRetain = TextOperation.isRetain = function (op) {\n    return typeof op === 'number' && op > 0;\n  };\n\n  var isInsert = TextOperation.isInsert = function (op) {\n    return typeof op === 'string';\n  };\n\n  var isDelete = TextOperation.isDelete = function (op) {\n    return typeof op === 'number' && op < 0;\n  };\n\n\n  // After an operation is constructed, the user of the library can specify the\n  // actions of an operation (skip/insert/delete) with these three builder\n  // methods. They all return the operation for convenient chaining.\n\n  // Skip over a given number of characters.\n  TextOperation.prototype.retain = function (n) {\n    if (typeof n !== 'number') {\n      throw new Error(\"retain expects an integer\");\n    }\n    if (n === 0) { return this; }\n    this.baseLength += n;\n    this.targetLength += n;\n    if (isRetain(this.ops[this.ops.length-1])) {\n      // The last op is a retain op => we can merge them into one op.\n      this.ops[this.ops.length-1] += n;\n    } else {\n      // Create a new op.\n      this.ops.push(n);\n    }\n    return this;\n  };\n\n  // Insert a string at the current position.\n  TextOperation.prototype.insert = function (str) {\n    if (typeof str !== 'string') {\n      throw new Error(\"insert expects a string\");\n    }\n    if (str === '') { return this; }\n    this.targetLength += str.length;\n    var ops = this.ops;\n    if (isInsert(ops[ops.length-1])) {\n      // Merge insert op.\n      ops[ops.length-1] += str;\n    } else if (isDelete(ops[ops.length-1])) {\n      // It doesn't matter when an operation is applied whether the operation\n      // is delete(3), insert(\"something\") or insert(\"something\"), delete(3).\n      // Here we enforce that in this case, the insert op always comes first.\n      // This makes all operations that have the same effect when applied to\n      // a document of the right length equal in respect to the `equals` method.\n      if (isInsert(ops[ops.length-2])) {\n        ops[ops.length-2] += str;\n      } else {\n        ops[ops.length] = ops[ops.length-1];\n        ops[ops.length-2] = str;\n      }\n    } else {\n      ops.push(str);\n    }\n    return this;\n  };\n\n  // Delete a string at the current position.\n  TextOperation.prototype['delete'] = function (n) {\n    if (typeof n === 'string') { n = n.length; }\n    if (typeof n !== 'number') {\n      throw new Error(\"delete expects an integer or a string\");\n    }\n    if (n === 0) { return this; }\n    if (n > 0) { n = -n; }\n    this.baseLength -= n;\n    if (isDelete(this.ops[this.ops.length-1])) {\n      this.ops[this.ops.length-1] += n;\n    } else {\n      this.ops.push(n);\n    }\n    return this;\n  };\n\n  // Tests whether this operation has no effect.\n  TextOperation.prototype.isNoop = function () {\n    return this.ops.length === 0 || (this.ops.length === 1 && isRetain(this.ops[0]));\n  };\n\n  // Pretty printing.\n  TextOperation.prototype.toString = function () {\n    // map: build a new array by applying a function to every element in an old\n    // array.\n    var map = Array.prototype.map || function (fn) {\n      var arr = this;\n      var newArr = [];\n      for (var i = 0, l = arr.length; i < l; i++) {\n        newArr[i] = fn(arr[i]);\n      }\n      return newArr;\n    };\n    return map.call(this.ops, function (op) {\n      if (isRetain(op)) {\n        return \"retain \" + op;\n      } else if (isInsert(op)) {\n        return \"insert '\" + op + \"'\";\n      } else {\n        return \"delete \" + (-op);\n      }\n    }).join(', ');\n  };\n\n  // Converts operation into a JSON value.\n  TextOperation.prototype.toJSON = function () {\n    return this.ops;\n  };\n\n  // Converts a plain JS object into an operation and validates it.\n  TextOperation.fromJSON = function (ops) {\n    var o = new TextOperation();\n    for (var i = 0, l = ops.length; i < l; i++) {\n      var op = ops[i];\n      if (isRetain(op)) {\n        o.retain(op);\n      } else if (isInsert(op)) {\n        o.insert(op);\n      } else if (isDelete(op)) {\n        o['delete'](op);\n      } else {\n        throw new Error(\"unknown operation: \" + JSON.stringify(op));\n      }\n    }\n    return o;\n  };\n\n  // Apply an operation to a string, returning a new string. Throws an error if\n  // there's a mismatch between the input string and the operation.\n  TextOperation.prototype.apply = function (str) {\n    var operation = this;\n    if (str.length !== operation.baseLength) {\n      throw new Error(\"The operation's base length must be equal to the string's length.\");\n    }\n    var newStr = [], j = 0;\n    var strIndex = 0;\n    var ops = this.ops;\n    for (var i = 0, l = ops.length; i < l; i++) {\n      var op = ops[i];\n      if (isRetain(op)) {\n        if (strIndex + op > str.length) {\n          throw new Error(\"Operation can't retain more characters than are left in the string.\");\n        }\n        // Copy skipped part of the old string.\n        newStr[j++] = str.slice(strIndex, strIndex + op);\n        strIndex += op;\n      } else if (isInsert(op)) {\n        // Insert string.\n        newStr[j++] = op;\n      } else { // delete op\n        strIndex -= op;\n      }\n    }\n    if (strIndex !== str.length) {\n      throw new Error(\"The operation didn't operate on the whole string.\");\n    }\n    return newStr.join('');\n  };\n\n  // Computes the inverse of an operation. The inverse of an operation is the\n  // operation that reverts the effects of the operation, e.g. when you have an\n  // operation 'insert(\"hello \"); skip(6);' then the inverse is 'delete(\"hello \");\n  // skip(6);'. The inverse should be used for implementing undo.\n  TextOperation.prototype.invert = function (str) {\n    var strIndex = 0;\n    var inverse = new TextOperation();\n    var ops = this.ops;\n    for (var i = 0, l = ops.length; i < l; i++) {\n      var op = ops[i];\n      if (isRetain(op)) {\n        inverse.retain(op);\n        strIndex += op;\n      } else if (isInsert(op)) {\n        inverse['delete'](op.length);\n      } else { // delete op\n        inverse.insert(str.slice(strIndex, strIndex - op));\n        strIndex -= op;\n      }\n    }\n    return inverse;\n  };\n\n  // Compose merges two consecutive operations into one operation, that\n  // preserves the changes of both. Or, in other words, for each input string S\n  // and a pair of consecutive operations A and B,\n  // apply(apply(S, A), B) = apply(S, compose(A, B)) must hold.\n  TextOperation.prototype.compose = function (operation2) {\n    var operation1 = this;\n    if (operation1.targetLength !== operation2.baseLength) {\n      throw new Error(\"The base length of the second operation has to be the target length of the first operation\");\n    }\n\n    var operation = new TextOperation(); // the combined operation\n    var ops1 = operation1.ops, ops2 = operation2.ops; // for fast access\n    var i1 = 0, i2 = 0; // current index into ops1 respectively ops2\n    var op1 = ops1[i1++], op2 = ops2[i2++]; // current ops\n    while (true) {\n      // Dispatch on the type of op1 and op2\n      if (typeof op1 === 'undefined' && typeof op2 === 'undefined') {\n        // end condition: both ops1 and ops2 have been processed\n        break;\n      }\n\n      if (isDelete(op1)) {\n        operation['delete'](op1);\n        op1 = ops1[i1++];\n        continue;\n      }\n      if (isInsert(op2)) {\n        operation.insert(op2);\n        op2 = ops2[i2++];\n        continue;\n      }\n\n      if (typeof op1 === 'undefined') {\n        throw new Error(\"Cannot compose operations: first operation is too short.\");\n      }\n      if (typeof op2 === 'undefined') {\n        throw new Error(\"Cannot compose operations: first operation is too long.\");\n      }\n\n      if (isRetain(op1) && isRetain(op2)) {\n        if (op1 > op2) {\n          operation.retain(op2);\n          op1 = op1 - op2;\n          op2 = ops2[i2++];\n        } else if (op1 === op2) {\n          operation.retain(op1);\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          operation.retain(op1);\n          op2 = op2 - op1;\n          op1 = ops1[i1++];\n        }\n      } else if (isInsert(op1) && isDelete(op2)) {\n        if (op1.length > -op2) {\n          op1 = op1.slice(-op2);\n          op2 = ops2[i2++];\n        } else if (op1.length === -op2) {\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          op2 = op2 + op1.length;\n          op1 = ops1[i1++];\n        }\n      } else if (isInsert(op1) && isRetain(op2)) {\n        if (op1.length > op2) {\n          operation.insert(op1.slice(0, op2));\n          op1 = op1.slice(op2);\n          op2 = ops2[i2++];\n        } else if (op1.length === op2) {\n          operation.insert(op1);\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          operation.insert(op1);\n          op2 = op2 - op1.length;\n          op1 = ops1[i1++];\n        }\n      } else if (isRetain(op1) && isDelete(op2)) {\n        if (op1 > -op2) {\n          operation['delete'](op2);\n          op1 = op1 + op2;\n          op2 = ops2[i2++];\n        } else if (op1 === -op2) {\n          operation['delete'](op2);\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          operation['delete'](op1);\n          op2 = op2 + op1;\n          op1 = ops1[i1++];\n        }\n      } else {\n        throw new Error(\n          \"This shouldn't happen: op1: \" +\n          JSON.stringify(op1) + \", op2: \" +\n          JSON.stringify(op2)\n        );\n      }\n    }\n    return operation;\n  };\n\n  function getSimpleOp (operation, fn) {\n    var ops = operation.ops;\n    var isRetain = TextOperation.isRetain;\n    switch (ops.length) {\n    case 1:\n      return ops[0];\n    case 2:\n      return isRetain(ops[0]) ? ops[1] : (isRetain(ops[1]) ? ops[0] : null);\n    case 3:\n      if (isRetain(ops[0]) && isRetain(ops[2])) { return ops[1]; }\n    }\n    return null;\n  }\n\n  function getStartIndex (operation) {\n    if (isRetain(operation.ops[0])) { return operation.ops[0]; }\n    return 0;\n  }\n\n  // When you use ctrl-z to undo your latest changes, you expect the program not\n  // to undo every single keystroke but to undo your last sentence you wrote at\n  // a stretch or the deletion you did by holding the backspace key down. This\n  // This can be implemented by composing operations on the undo stack. This\n  // method can help decide whether two operations should be composed. It\n  // returns true if the operations are consecutive insert operations or both\n  // operations delete text at the same position. You may want to include other\n  // factors like the time since the last change in your decision.\n  TextOperation.prototype.shouldBeComposedWith = function (other) {\n    if (this.isNoop() || other.isNoop()) { return true; }\n\n    var startA = getStartIndex(this), startB = getStartIndex(other);\n    var simpleA = getSimpleOp(this), simpleB = getSimpleOp(other);\n    if (!simpleA || !simpleB) { return false; }\n\n    if (isInsert(simpleA) && isInsert(simpleB)) {\n      return startA + simpleA.length === startB;\n    }\n\n    if (isDelete(simpleA) && isDelete(simpleB)) {\n      // there are two possibilities to delete: with backspace and with the\n      // delete key.\n      return (startB - simpleB === startA) || startA === startB;\n    }\n\n    return false;\n  };\n\n  // Decides whether two operations should be composed with each other\n  // if they were inverted, that is\n  // `shouldBeComposedWith(a, b) = shouldBeComposedWithInverted(b^{-1}, a^{-1})`.\n  TextOperation.prototype.shouldBeComposedWithInverted = function (other) {\n    if (this.isNoop() || other.isNoop()) { return true; }\n\n    var startA = getStartIndex(this), startB = getStartIndex(other);\n    var simpleA = getSimpleOp(this), simpleB = getSimpleOp(other);\n    if (!simpleA || !simpleB) { return false; }\n\n    if (isInsert(simpleA) && isInsert(simpleB)) {\n      return startA + simpleA.length === startB || startA === startB;\n    }\n\n    if (isDelete(simpleA) && isDelete(simpleB)) {\n      return startB - simpleB === startA;\n    }\n\n    return false;\n  };\n\n  // Transform takes two operations A and B that happened concurrently and\n  // produces two operations A' and B' (in an array) such that\n  // `apply(apply(S, A), B') = apply(apply(S, B), A')`. This function is the\n  // heart of OT.\n  TextOperation.transform = function (operation1, operation2) {\n    if (operation1.baseLength !== operation2.baseLength) {\n      throw new Error(\"Both operations have to have the same base length\");\n    }\n\n    var operation1prime = new TextOperation();\n    var operation2prime = new TextOperation();\n    var ops1 = operation1.ops, ops2 = operation2.ops;\n    var i1 = 0, i2 = 0;\n    var op1 = ops1[i1++], op2 = ops2[i2++];\n    while (true) {\n      // At every iteration of the loop, the imaginary cursor that both\n      // operation1 and operation2 have that operates on the input string must\n      // have the same position in the input string.\n\n      if (typeof op1 === 'undefined' && typeof op2 === 'undefined') {\n        // end condition: both ops1 and ops2 have been processed\n        break;\n      }\n\n      // next two cases: one or both ops are insert ops\n      // => insert the string in the corresponding prime operation, skip it in\n      // the other one. If both op1 and op2 are insert ops, prefer op1.\n      if (isInsert(op1)) {\n        operation1prime.insert(op1);\n        operation2prime.retain(op1.length);\n        op1 = ops1[i1++];\n        continue;\n      }\n      if (isInsert(op2)) {\n        operation1prime.retain(op2.length);\n        operation2prime.insert(op2);\n        op2 = ops2[i2++];\n        continue;\n      }\n\n      if (typeof op1 === 'undefined') {\n        throw new Error(\"Cannot compose operations: first operation is too short.\");\n      }\n      if (typeof op2 === 'undefined') {\n        throw new Error(\"Cannot compose operations: first operation is too long.\");\n      }\n\n      var minl;\n      if (isRetain(op1) && isRetain(op2)) {\n        // Simple case: retain/retain\n        if (op1 > op2) {\n          minl = op2;\n          op1 = op1 - op2;\n          op2 = ops2[i2++];\n        } else if (op1 === op2) {\n          minl = op2;\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          minl = op1;\n          op2 = op2 - op1;\n          op1 = ops1[i1++];\n        }\n        operation1prime.retain(minl);\n        operation2prime.retain(minl);\n      } else if (isDelete(op1) && isDelete(op2)) {\n        // Both operations delete the same string at the same position. We don't\n        // need to produce any operations, we just skip over the delete ops and\n        // handle the case that one operation deletes more than the other.\n        if (-op1 > -op2) {\n          op1 = op1 - op2;\n          op2 = ops2[i2++];\n        } else if (op1 === op2) {\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          op2 = op2 - op1;\n          op1 = ops1[i1++];\n        }\n      // next two cases: delete/retain and retain/delete\n      } else if (isDelete(op1) && isRetain(op2)) {\n        if (-op1 > op2) {\n          minl = op2;\n          op1 = op1 + op2;\n          op2 = ops2[i2++];\n        } else if (-op1 === op2) {\n          minl = op2;\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          minl = -op1;\n          op2 = op2 + op1;\n          op1 = ops1[i1++];\n        }\n        operation1prime['delete'](minl);\n      } else if (isRetain(op1) && isDelete(op2)) {\n        if (op1 > -op2) {\n          minl = -op2;\n          op1 = op1 + op2;\n          op2 = ops2[i2++];\n        } else if (op1 === -op2) {\n          minl = op1;\n          op1 = ops1[i1++];\n          op2 = ops2[i2++];\n        } else {\n          minl = op1;\n          op2 = op2 + op1;\n          op1 = ops1[i1++];\n        }\n        operation2prime['delete'](minl);\n      } else {\n        throw new Error(\"The two operations aren't compatible\");\n      }\n    }\n\n    return [operation1prime, operation2prime];\n  };\n\n  return TextOperation;\n\n}());\n\n// Export for CommonJS\nif (typeof module === 'object') {\n  module.exports = ot.TextOperation;\n}"
  },
  {
    "path": "public/vendor/ot/undo-manager.js",
    "content": "if (typeof ot === 'undefined') {\n  // Export for browsers\n  var ot = {};\n}\n\not.UndoManager = (function () {\n  'use strict';\n\n  var NORMAL_STATE = 'normal';\n  var UNDOING_STATE = 'undoing';\n  var REDOING_STATE = 'redoing';\n\n  // Create a new UndoManager with an optional maximum history size.\n  function UndoManager (maxItems) {\n    this.maxItems  = maxItems || 50;\n    this.state = NORMAL_STATE;\n    this.dontCompose = false;\n    this.undoStack = [];\n    this.redoStack = [];\n  }\n\n  // Add an operation to the undo or redo stack, depending on the current state\n  // of the UndoManager. The operation added must be the inverse of the last\n  // edit. When `compose` is true, compose the operation with the last operation\n  // unless the last operation was alread pushed on the redo stack or was hidden\n  // by a newer operation on the undo stack.\n  UndoManager.prototype.add = function (operation, compose) {\n    if (this.state === UNDOING_STATE) {\n      this.redoStack.push(operation);\n      this.dontCompose = true;\n    } else if (this.state === REDOING_STATE) {\n      this.undoStack.push(operation);\n      this.dontCompose = true;\n    } else {\n      var undoStack = this.undoStack;\n      if (!this.dontCompose && compose && undoStack.length > 0) {\n        undoStack.push(operation.compose(undoStack.pop()));\n      } else {\n        undoStack.push(operation);\n        if (undoStack.length > this.maxItems) { undoStack.shift(); }\n      }\n      this.dontCompose = false;\n      this.redoStack = [];\n    }\n  };\n\n  function transformStack (stack, operation) {\n    var newStack = [];\n    var Operation = operation.constructor;\n    for (var i = stack.length - 1; i >= 0; i--) {\n      var pair = Operation.transform(stack[i], operation);\n      if (typeof pair[0].isNoop !== 'function' || !pair[0].isNoop()) {\n        newStack.push(pair[0]);\n      }\n      operation = pair[1];\n    }\n    return newStack.reverse();\n  }\n\n  // Transform the undo and redo stacks against a operation by another client.\n  UndoManager.prototype.transform = function (operation) {\n    this.undoStack = transformStack(this.undoStack, operation);\n    this.redoStack = transformStack(this.redoStack, operation);\n  };\n\n  // Perform an undo by calling a function with the latest operation on the undo\n  // stack. The function is expected to call the `add` method with the inverse\n  // of the operation, which pushes the inverse on the redo stack.\n  UndoManager.prototype.performUndo = function (fn) {\n    this.state = UNDOING_STATE;\n    if (this.undoStack.length === 0) { throw new Error(\"undo not possible\"); }\n    fn(this.undoStack.pop());\n    this.state = NORMAL_STATE;\n  };\n\n  // The inverse of `performUndo`.\n  UndoManager.prototype.performRedo = function (fn) {\n    this.state = REDOING_STATE;\n    if (this.redoStack.length === 0) { throw new Error(\"redo not possible\"); }\n    fn(this.redoStack.pop());\n    this.state = NORMAL_STATE;\n  };\n\n  // Is the undo stack not empty?\n  UndoManager.prototype.canUndo = function () {\n    return this.undoStack.length !== 0;\n  };\n\n  // Is the redo stack not empty?\n  UndoManager.prototype.canRedo = function () {\n    return this.redoStack.length !== 0;\n  };\n\n  // Whether the UndoManager is currently performing an undo.\n  UndoManager.prototype.isUndoing = function () {\n    return this.state === UNDOING_STATE;\n  };\n\n  // Whether the UndoManager is currently performing a redo.\n  UndoManager.prototype.isRedoing = function () {\n    return this.state === REDOING_STATE;\n  };\n\n  return UndoManager;\n\n}());\n\n// Export for CommonJS\nif (typeof module === 'object') {\n  module.exports = ot.UndoManager;\n}\n"
  },
  {
    "path": "public/vendor/ot/wrapped-operation.js",
    "content": "if (typeof ot === 'undefined') {\n  // Export for browsers\n  var ot = {};\n}\n\not.WrappedOperation = (function (global) {\n  'use strict';\n\n  // A WrappedOperation contains an operation and corresponing metadata.\n  function WrappedOperation (operation, meta) {\n    this.wrapped = operation;\n    this.meta    = meta;\n  }\n\n  WrappedOperation.prototype.apply = function () {\n    return this.wrapped.apply.apply(this.wrapped, arguments);\n  };\n\n  WrappedOperation.prototype.invert = function () {\n    var meta = this.meta;\n    return new WrappedOperation(\n      this.wrapped.invert.apply(this.wrapped, arguments),\n      meta && typeof meta === 'object' && typeof meta.invert === 'function' ?\n        meta.invert.apply(meta, arguments) : meta\n    );\n  };\n\n  // Copy all properties from source to target.\n  function copy (source, target) {\n    for (var key in source) {\n      if (source.hasOwnProperty(key)) {\n        target[key] = source[key];\n      }\n    }\n  }\n\n  function composeMeta (a, b) {\n    if (a && typeof a === 'object') {\n      if (typeof a.compose === 'function') { return a.compose(b); }\n      var meta = {};\n      copy(a, meta);\n      copy(b, meta);\n      return meta;\n    }\n    return b;\n  }\n\n  WrappedOperation.prototype.compose = function (other) {\n    return new WrappedOperation(\n      this.wrapped.compose(other.wrapped),\n      composeMeta(this.meta, other.meta)\n    );\n  };\n\n  function transformMeta (meta, operation) {\n    if (meta && typeof meta === 'object') {\n      if (typeof meta.transform === 'function') {\n        return meta.transform(operation);\n      }\n    }\n    return meta;\n  }\n\n  WrappedOperation.transform = function (a, b) {\n    var transform = a.wrapped.constructor.transform;\n    var pair = transform(a.wrapped, b.wrapped);\n    return [\n      new WrappedOperation(pair[0], transformMeta(a.meta, b.wrapped)),\n      new WrappedOperation(pair[1], transformMeta(b.meta, a.wrapped))\n    ];\n  };\n\n  return WrappedOperation;\n\n}(this));\n\n// Export for CommonJS\nif (typeof module === 'object') {\n  module.exports = ot.WrappedOperation;\n}"
  },
  {
    "path": "public/vendor/showup/showup.css",
    "content": "/*\n * Showup.js jQuery Plugin\n * http://github.com/jonschlinkert/showup\n *\n * Copyright (c) 2013 Jon Schlinkert, contributors\n * Licensed under the MIT License (MIT).\n */\n\n/**\n * Docs navbar transitions effects\n */\n\n.navbar-tall,\n.navbar-show {\n  -webkit-transition: -webkit-transform .3s;\n     -moz-transition:    -moz-transform .3s;\n       -o-transition:      -o-transform .3s;\n          transition:         transform .3s;\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n\n.navbar-hide {\n  -webkit-transition: -webkit-transform .2s;\n     -moz-transition:    -moz-transform .2s;\n       -o-transition:      -o-transform .2s;\n          transition:         transform .2s;\n  -webkit-transform: translate(0, -60px);\n      -ms-transform: translate(0, -60px);\n          transform: translate(0, -60px);\n}\n\n\n.navbar-tall,\n.navbar-short,\n.navbar-tall .navbar-brand,\n.navbar-short .navbar-brand,\n.navbar-tall .navbar-nav > li > a,\n.navbar-short .navbar-nav > li > a {\n  -webkit-transition: all 0.2s linear;\n          transition: all 0.2s linear;\n}\n\n.navbar-short {\n  min-height: 40px;\n}\n.navbar-short .navbar-brand {\n  font-size: 16px;\n  padding: 13px 15px 10px;\n}\n.navbar-short .navbar-nav > li > a {\n  padding-top: 12px;\n  padding-bottom: 12px;\n}\n\n\n.navbar-tall {\n  min-height: 70px;\n}\n.navbar-tall .navbar-brand {\n  font-size: 24px;\n  padding: 25px 15px;\n}\n.navbar-tall .navbar-nav > li > a {\n  padding-top: 25px;\n}\n\n\n\n/**\n * Docs Buttons\n */\n\n/* Fixed button, bottom right */\n.btn-fixed-bottom {\n  position: fixed;\n  bottom: 30px;\n  display: none;\n  z-index: 5;\n  width: 40px;\n  height: 40px;\n}\n\n/* Toggles navbar classes */\n.btn-hide-show {\n  margin-right: 10px;\n}\n\n/* Light theme */\n.btn-light {\n  color: #555;\n  background-color: rgba(0, 0, 0,.1);\n}\n.btn-light:hover {\n  color: #111;\n  background-color: rgba(0, 0, 0,.25);\n}\n\n/* Dark theme */\n.btn-dark {\n  color: #fff;\n  background-color: rgba(0, 0, 0,.5);\n}\n.btn-dark:hover {\n  color: #fff;\n  background-color: rgba(0, 0, 0,.9);\n}\n\n/* Buttons displayed throughout the content */\n.btn-showup {\n  position: relative;\n  color: #fff;\n  font-weight: normal;\n  background-color: #463265;\n  border-color: #3F2961;\n}\n\n.btn-showup:hover,\n.btn-showup:focus {\n  color: #fff;\n  outline: none;\n  background-color: #39235A;\n  border-color: #39235A;\n}"
  },
  {
    "path": "public/vendor/showup/showup.js",
    "content": "/*\n * Showup.js jQuery Plugin\n * http://github.com/jonschlinkert/showup\n *\n * Copyright (c) 2013 Jon Schlinkert, contributors\n * Licensed under the MIT License (MIT).\n */\n\n\n(function( $ ) {\n  $.fn.showUp = function(ele, options) {\n    options = options || {};\n\n    var target         = $(ele);\n    var down           = options.down        || 'navbar-hide';\n    var up             = options.up          || 'navbar-show';\n    var btnHideShow    = options.btnHideShow || '.btn-hide-show';\n    var hideOffset     = options.offset      || 60;\n    var previousScroll = 0;\n\tvar isHide\t\t   = false;\n\n    $(window).scroll(function () {\n\t\tcheckScrollTop();\n    });\n\t\n\t$(window).resize(function () {\n\t\tcheckScrollTop();\n    });\n\t\n\t$(window).mousewheel(function () {\n\t\tcheckScrollTop();\n    });\n\t\n\tfunction checkScrollTop()\n\t{\n\t\ttarget.clearQueue();\n\t\ttarget.stop();\n\t  var currentScroll = $(this).scrollTop();\n      if (currentScroll > hideOffset && !target.hasClass('locked')) {\n          if(Math.abs(previousScroll - currentScroll) < 50) return;\n        if (currentScroll > previousScroll) {\n          // Action on scroll down\n\t\t  target.removeClass(up).addClass(down);\n        } else if (currentScroll < previousScroll) {\n          // Action on scroll up\n\t\t  target.removeClass(down).addClass(up);\n        }\n      } else {\n\t\ttarget.removeClass(down).addClass(up);\n\t  }\n      previousScroll = $(this).scrollTop();\n\t}\n\n    // Toggle visibility of target on click\n    $(btnHideShow).click(function () {\n      if (target.hasClass(down)) {\n        target.removeClass(down).addClass(up);\n      } else {\n        target.removeClass(up).addClass(down);\n      }\n    });\n  };\n})( jQuery );\n\n// TODO: make customizable\n$(document).ready(function () {\n  var duration      = 420;\n  var showOffset    = 220;\n  var btnFixed      = '.btn-fixed-bottom';\n  var btnToTopClass = '.back-to-top';\n\n  $(window).scroll(function () {\n    if ($(this).scrollTop() > showOffset) {\n      $(btnFixed).fadeIn(duration);\n    } else {\n      $(btnFixed).fadeOut(duration);\n    }\n  });\n\n  $(btnToTopClass).click(function (event) {\n    event.preventDefault();\n    $('html, body').animate({\n      scrollTop: 0\n    }, duration);\n    return false;\n  });\n});"
  },
  {
    "path": "public/views/codimd/body.ejs",
    "content": "<div class=\"row ui-content\" style=\"display: none;\">\n    <div class=\"ui-edit-area unselectable\">\n        <textarea id=\"textit\"></textarea>\n    </div>\n    <div class=\"ui-view-area\">\n        <div class=\"ui-infobar container-fluid unselectable hidden-print\">\n            <small>\n                <span>\n                    <span class=\"ui-lastchangeuser\" style=\"display: none;\">&thinsp;<i class=\"ui-user-icon small\" data-toggle=\"tooltip\" data-placement=\"right\"></i></span>\n                    <span class=\"ui-no-lastchangeuser\">&thinsp;<i class=\"fa fa-clock-o fa-fw\" style=\"width: 18px;\"></i></span>\n                    &nbsp;<span class=\"text-uppercase ui-status-lastchange\"></span>\n                    <span class=\"ui-lastchange text-uppercase\"></span>\n                </span>\n                <span class=\"ui-permission dropdown pull-right\">\n                    <a id=\"permissionLabelFreely\" class=\"ui-permission-label text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" style=\"display: none;\" title=\"<%= __('Anyone can edit') %>\"><i class=\"fa fa-leaf\"></i> <%= __('Freely') %> <i class=\"ui-permission-caret-down fa fa-caret-down\" style=\"display: none;\"></i></a>\n                    <a id=\"permissionLabelEditable\" class=\"ui-permission-label text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" style=\"display: none;\" title=\"<%= __('Signed-in people can edit') %>\"><i class=\"fa fa-shield fa-fw\"></i> <%= __('Editable') %> <i class=\"ui-permission-caret-down fa fa-caret-down\" style=\"display: none;\"></i></a>\n                    <a id=\"permissionLabelLimited\" class=\"ui-permission-label text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" style=\"display: none;\" title=\"<%= __('Signed-in people can edit (forbid guests)') %>\"><i class=\"fa fa-id-card fa-fw\"></i> <%= __('Limited') %> <i class=\"ui-permission-caret-down fa fa-caret-down\" style=\"display: none;\"></i></a>\n                    <a id=\"permissionLabelLocked\" class=\"ui-permission-label text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" style=\"display: none;\" title=\"<%= __('Only owner can edit') %>\"><i class=\"fa fa-lock fa-fw\"></i> <%= __('Locked') %> <i class=\"ui-permission-caret-down fa fa-caret-down\" style=\"display: none;\"></i></a>\n                    <a id=\"permissionLabelProtected\" class=\"ui-permission-label text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" style=\"display: none;\" title=\"<%= __('Only owner can edit (forbid guests)') %>\"><i class=\"fa fa-umbrella fa-fw\"></i> <%= __('Protected') %> <i class=\"ui-permission-caret-down fa fa-caret-down\" style=\"display: none;\"></i></a>\n                    <a id=\"permissionLabelPrivate\" class=\"ui-permission-label text-uppercase\" data-toggle=\"dropdown\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" style=\"display: none;\" title=\"<%= __('Only owner can view & edit') %>\"><i class=\"fa fa-hand-stop-o fa-fw\"></i> <%= __('Private') %> <i class=\"ui-permission-caret-down fa fa-caret-down\" style=\"display: none;\"></i></a>\n                    <ul class=\"dropdown-menu\" aria-labelledby=\"permissionLabelFreely permissionLabelEditable permissionLabelLimited permissionLabelLocked permissionLabelProtected permissionLabelPrivate\">\n                        <li class=\"ui-permission-freely\"<% if(!('freely' in permission)) { %> style=\"display: none;\"<% } %>><a><i class=\"fa fa-leaf fa-fw\"></i> <%= __('Freely') %> - <%= __('Anyone can edit') %></a></li>\n                        <li class=\"ui-permission-editable\"<% if(!('editable' in permission)) { %> style=\"display: none;\"<% } %>><a><i class=\"fa fa-shield fa-fw\"></i> <%= __('Editable') %> - <%= __('Signed-in people can edit') %></a></li>\n                        <li class=\"ui-permission-limited\"<% if(!('limited' in permission)) { %> style=\"display: none;\"<% } %>><a><i class=\"fa fa-id-card fa-fw\"></i> <%= __('Limited') %> - <%= __('Signed-in people can edit (forbid guests)') %></a></li>\n                        <li class=\"ui-permission-locked\"<% if(!('locked' in permission)) { %> style=\"display: none;\"<% } %>><a><i class=\"fa fa-lock fa-fw\"></i> <%= __('Locked') %> - <%= __('Only owner can edit') %></a></li>\n                        <li class=\"ui-permission-protected\"<% if(!('protected' in permission)) { %> style=\"display: none;\"<% } %>><a><i class=\"fa fa-umbrella fa-fw\"></i> <%= __('Protected') %> - <%= __('Only owner can edit (forbid guests)') %></a></li>\n                        <li class=\"ui-permission-private\"<% if(!('private' in permission)) { %> style=\"display: none;\"<% } %>><a><i class=\"fa fa-hand-stop-o fa-fw\"></i> <%= __('Private') %> - <%= __('Only owner can view & edit') %></a></li>\n                        <li class=\"divider\"></li>\n                        <li class=\"ui-delete-note\"><a><i class=\"fa fa-trash-o fa-fw\"></i> <%= __('Delete this note') %></a></li>\n                    </ul>\n                </span>\n                <br>\n                <span class=\"ui-owner\" style=\"display: none;\">\n                    &thinsp;<i class=\"ui-user-icon small\" data-toggle=\"tooltip\" data-placement=\"right\"></i>\n                    &nbsp;<span class=\"text-uppercase\"><%= __('owned this note') %></span>\n                </span>\n            </small>\n        </div>\n        <div id=\"doc\" class=\"markdown-body container-fluid\"></div>\n        <div class=\"ui-toc dropup unselectable hidden-print\" style=\"display:none;\">\n            <div class=\"pull-right dropdown\">\n                <a id=\"tocLabel\" class=\"ui-toc-label btn btn-default\" data-toggle=\"dropdown\" href=\"#\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Table of content\">\n                    <i class=\"fa fa-bars\"></i>\n                </a>\n                <ul id=\"ui-toc\" class=\"ui-toc-dropdown dropdown-menu\" aria-labelledby=\"tocLabel\">\n                </ul>\n            </div>\n        </div>\n        <div id=\"ui-toc-affix\" class=\"ui-affix-toc ui-toc-dropdown unselectable hidden-print\" data-spy=\"affix\" style=\"top:51px;display:none;\"></div>\n    </div>\n</div>\n<!-- toc menu -->\n<div class=\"toc-menu\" style=\"display: none;\">\n    <a class=\"expand-toggle expand-all\" href=\"#\"><%= __('Expand all') %></a>\n    <a class=\"expand-toggle collapse-all\" href=\"#\" style=\"display: none;\"><%= __('Collapse all') %></a>\n    <a class=\"back-to-top\" href=\"#\"><%= __('Back to top') %></a>\n    <a class=\"go-to-bottom\" href=\"#\"><%= __('Go to bottom') %></a>\n</div>\n<!-- clipboard modal -->\n<div class=\"modal fade\" id=\"clipboardModal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-lg\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\"><%= __('Import from clipboard') %></h4>\n            </div>\n            <div class=\"modal-body\">\n                <div contenteditable data-ph=\"<%= __('Paste your markdown or webpage here...') %>\" id=\"clipboardModalContent\" style=\"overflow:auto;max-height:50vh\"></div>\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\"><%= __('Cancel') %></button>\n                <button type=\"button\" class=\"btn btn-danger\" id=\"clipboardModalClear\"><%= __('Clear') %></button>\n                <button type=\"button\" class=\"btn btn-primary\" id=\"clipboardModalConfirm\"><%= __('Import') %></button>\n            </div>\n        </div>\n    </div>\n</div>\n<!-- locked modal -->\n<div class=\"modal fade locked-modal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-sm\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\"><i class=\"fa fa-lock\"></i> <%= __('This note is locked') %></h4>\n            </div>\n            <div class=\"modal-body\" style=\"color:black;\">\n                <h5><%= __('Sorry, only owner can edit this note.') %></h5>\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-danger\" data-dismiss=\"modal\"><%= __('OK') %></button>\n            </div>\n        </div>\n    </div>\n</div>\n<!-- limit modal -->\n<div class=\"modal fade limit-modal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-sm\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\"><i class=\"fa fa-exclamation-triangle\"></i> <%= __('Reach the limit') %></h4>\n            </div>\n            <div class=\"modal-body\" style=\"color:black;\">\n                <h5><%= __(\"Sorry, you've reached the max length this note can be.\") %></h5>\n                <strong><%= __('Please reduce the content or divide it to more notes, thank you!') %></strong>\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-warning\" data-dismiss=\"modal\"><%= __('OK') %></button>\n            </div>\n        </div>\n    </div>\n</div>\n<!-- message modal -->\n<div class=\"modal fade message-modal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-sm\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\"></h4>\n            </div>\n            <div class=\"modal-body\" style=\"color:black;\">\n                <h5></h5>\n                <a target=\"_blank\" rel=\"noopener\" style=\"word-break: break-all;\"></a>\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\"><%= __('OK') %></button>\n            </div>\n        </div>\n    </div>\n</div>\n<!-- gist import modal -->\n<div class=\"modal fade\" id=\"gistImportModal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\"><%= __('Import from Gist') %></h4>\n            </div>\n            <div class=\"modal-body\">\n                <input type=\"url\" class=\"form-control\" placeholder=\"<%= __('Paste your gist url here...') %> (like: https://gist.github.com/username/gistid)\" id=\"gistImportModalContent\">\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\"><%= __('Cancel') %></button>\n                <button type=\"button\" class=\"btn btn-danger\" id=\"gistImportModalClear\"><%= __('Clear') %></button>\n                <button type=\"button\" class=\"btn btn-primary\" id=\"gistImportModalConfirm\"><%= __('Import') %></button>\n            </div>\n        </div>\n    </div>\n</div>\n<!-- snippet import modal -->\n<div class=\"modal fade\" id=\"snippetImportModal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\"><%= __('Import from Snippet') %></h4>\n            </div>\n            <div class=\"modal-body\">\n                <input type=\"hidden\" id=\"snippetImportModalAccessToken\" />\n                <input type=\"hidden\" id=\"snippetImportModalBaseURL\" />\n                <input type=\"hidden\" id=\"snippetImportModalVersion\" />\n                <div class=\"ui-field-contain\" style=\"display:table;margin-bottom:10px;width:100%;\">\n                    <div style=\"display:table-row;margin-bottom:5px;\">\n                        <label style=\"display:table-cell;\">Project:</label>\n                        <select class=\"form-control\" id=\"snippetImportModalProjects\" style=\"display:table-cell;\" disabled=\"disabled\">\n                            <option value=\"init\" selected=\"selected\" disabled=\"disabled\"><%= __('Select From Available Projects') %></option>\n                        </select>\n                    </div>\n                    <div style=\"display:table-row;\">\n                        <label style=\"display:table-cell;\">Snippet</label>\n                        <select class=\"form-control\" id=\"snippetImportModalSnippets\" style=\"display:table-cell;\" disabled=\"disabled\">\n                            <option value=\"init\" selected=\"selected\" disabled=\"disabled\"><%= __('Select From Available Snippets') %></option>\n                        </select>\n                    </div>\n                </div>\n                <p class=\"snippet-import-or\"><%= __('OR') %></p>\n                <input type=\"url\" class=\"form-control\" placeholder=\"/projects/:id/snippets/:snippet_id\" id=\"snippetImportModalContent\" disabled=\"disabled\">\n            </div>\n            <div class=\"modal-footer\">\n                <span id=\"snippetImportModalLoading\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\"><%= __('Cancel') %></button>\n                <button type=\"button\" class=\"btn btn-danger\" id=\"snippetImportModalClear\"><%= __('Clear') %></button>\n                <button type=\"button\" class=\"btn btn-primary\" id=\"snippetImportModalConfirm\" disabled=\"disabled\"><%= __('Import') %></button>\n            </div>\n        </div>\n    </div>\n</div>\n<!-- snippet export modal -->\n<div class=\"modal fade\" id=\"snippetExportModal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\"><%= __('Export to Snippet') %></h4>\n            </div>\n            <div class=\"modal-body\">\n                <input type=\"hidden\" id=\"snippetExportModalAccessToken\" />\n                <input type=\"hidden\" id=\"snippetExportModalBaseURL\" />\n                <input type=\"hidden\" id=\"snippetExportModalVersion\" />\n                <div class=\"ui-field-contain\" style=\"display:table;margin-bottom:10px;width:100%;\">\n                    <div style=\"display:table-row;margin-bottom:5px;\">\n                        <label style=\"display:table-cell;\">Title:</label>\n                        <input class=\"form-control\" placeholder=\"new snippet\" type=\"text\" id=\"snippetExportModalTitle\" />\n                    </div>\n                    <div style=\"display:table-row;margin-bottom:5px;\">\n                        <label style=\"display:table-cell;\">File Name:</label>\n                        <input class=\"form-control\" placeholder=\"new_snippet.md\" type=\"text\" id=\"snippetExportModalFileName\" />\n                    </div>\n                    <div style=\"display:table-row;margin-bottom:5px;\">\n                        <label style=\"display:table-cell;\">Project:</label>\n                        <select class=\"form-control\" id=\"snippetExportModalProjects\" style=\"display:table-cell;\">\n                            <option value=\"init\" selected=\"selected\" disabled=\"disabled\"><%= __('Select From Available Projects') %></option>\n                        </select>\n                    </div>\n                    <div style=\"display:table-row;margin-bottom:5px;\">\n                        <label style=\"display:table-cell;\">Visibility:</label>\n                        <select class=\"form-control\" id=\"snippetExportModalVisibility\" style=\"display:table-cell;\">\n                            <option value=\"\" selected=\"selected\" disabled=\"disabled\"><%= __('Select Visibility Level') %></option>\n                            <option value=\"0\">Private</option>\n                            <option value=\"10\">Internal</option>\n                        </select>\n                    </div>\n                </div>\n            </div>\n            <div class=\"modal-footer\">\n                <span id=\"snippetExportModalLoading\"><i class=\"fa fa-refresh fa-spin fa-fw\"></i></span>\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\"><%= __('Cancel') %></button>\n                <button type=\"button\" class=\"btn btn-primary\" id=\"snippetExportModalConfirm\"><%= __('Export') %></button>\n            </div>\n        </div>\n    </div>\n</div>\n<!-- delete modal -->\n<div class=\"modal fade delete-modal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-sm\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\"><%= __('Are you sure?') %></h4>\n            </div>\n            <div class=\"modal-body\">\n                <h5 class=\"ui-delete-modal-msg\"><%= __('Do you really want to delete this note?') %></h5>\n                <strong class=\"ui-delete-modal-item\"><%= __('All users will lose their connection.') %></strong>\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\"><%= __('Cancel') %></button>\n                <button type=\"button\" class=\"btn btn-danger ui-delete-modal-confirm\"><%= __('Yes, do it!') %></button>\n            </div>\n        </div>\n    </div>\n</div>\n<%- include('../shared/refresh-modal') %>\n<%- include('../shared/signin-modal') %>\n<%- include('../shared/help-modal') %>\n<%- include('../shared/revision-modal') %>\n<%- include('../shared/pandoc-export-modal') %>\n"
  },
  {
    "path": "public/views/codimd/foot.ejs",
    "content": "<script src=\"<%= serverURL %>/js/mathjax-config-extra.js\"></script>\n<% if(useCDN) { %>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.3.2/spin.min.js\" integrity=\"sha256-PieqE0QdEDMppwXrTzSZQr6tWFX3W5KkyRVyF1zN3eg=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js\" integrity=\"sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=\" crossorigin=\"anonymous\"></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/velocity/1.4.0/velocity.min.js\" integrity=\"sha256-bhm0lgEt6ITaZCDzZpkr/VXVrLa5RP4u9v2AYsbzSUk=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js\" integrity=\"sha256-kJrlY+s09+QoWjpkOrXXwhxeaoDz9FW5SaxF8I0DibQ=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js\" integrity=\"sha256-jnOjDTXIPqall8M0MyTSt98JetJuZ7Yu+1Jm7hLTF7U=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/js-yaml/3.7.0/js-yaml.min.js\" integrity=\"sha256-8PanqYAVOGlOct+i65R+HqibK3KPsXINnrSfxN+Y/J0=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js\" integrity=\"sha256-yYfngbEKv4RENfGDvNUqJTqGFcKf31NJEe9OTnnMH3Y=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/TeX-AMS-MML_HTMLorMML.js\" integrity=\"sha256-immzXfCGLhnx3Zfi9F/dUcqxEM8K3o3oTFy9Bh6HCwg=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/Safe.js\" integrity=\"sha256-0ygBUDksNDXZS4vm5HMNH1a33KUu6QT1cdNTN+ZLF+4=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js\" integrity=\"sha256-AdQN98MVZs44Eq2yTwtoKufhnU+uZ7v2kXnD5vqzZVo=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/mermaid/11.5.0/mermaid.min.js\" integrity=\"sha512-3EZqKCkk3nMLmbrI7mfry81KH7dkzy/BoDfQrodwLQnS/RbsVlERdYP6J0oiJegRUxSOmx7Y35WNbVKSw7mipw==\" crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\" defer></script>\n<script src=\"https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/js/emojify-browser.min.js\" integrity=\"sha256-swgfXtqk2bC98KzPoE8tXRz5tmrzpjJWhhXlhYo/wRA=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js\" integrity=\"sha256-Cv5v4i4SuYvwRYzIONifZjoc99CkwfncROMSWat1cVA=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js\" integrity=\"sha256-ji09tECORKvr8xB9iCl8DJ8iNMLriDchC1+p+yt1hSs=\" crossorigin=\"anonymous\"></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.2/handlebars.min.js\" integrity=\"sha256-ngJY93C4H39YbmrWhnLzSyiepRuQDVKDNCWO2iyMzFw=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/highlight.min.js\" integrity=\"sha256-1zu+3BnLYV9LdiY85uXMzii3bdrkelyp37e0ZyTAQh0=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/gist-embed/2.6.0/gist-embed.min.js\" integrity=\"sha256-KyF2D6xPIJUW5sUDSs93vWyZm+1RzIpKCexxElmxl8g=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/viz.js/2.1.2/viz.js\" integrity=\"sha256-8RHyK+AFzq9iXwbFo2unqidwPbwHU5FFWe3RwkcVtuU=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/viz.js/2.1.2/full.render.js\" integrity=\"sha256-Ogqs510LFnekr9o7OLdpelaaAmNss9egQRTyzCqV2NQ=\" crossorigin=\"anonymous\" defer></script>\n\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/abcjs/6.4.4/abcjs-basic.min.js\" integrity=\"sha512-uVrpuoBZLoqLvjKDI0tCpD1HBOIZNTf9EwCrNaxVkk47zpRB54pW81gm8z2DkjtPGPjLZNy/jO5lJ8aXCATuVQ==\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/vega/5.17.1/vega.min.js\" integrity=\"sha512-VaNhWxxm7c02xaYMBd8FTS1V89mnFLopQ2/ClJkrSmh421NROVQNJMqeL5KnwpFW14POUzFIzEIETV/5SAbH/Q==\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/vega-lite/4.17.0/vega-lite.min.js\" integrity=\"sha512-GUsnbKvdacPXIFZvHFFFnWEulYU74fanU2z9aie8g3/F/xcX9vxZuQFLwv9NjdV261fxj9SyAJ3Cf65jvYWMxw==\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/vega-embed/6.14.2/vega-embed.min.js\" integrity=\"sha512-Nhf4uoYFL/Mu9UESXLF9Mo22qmhuWEhAQWHAZOHpNntSvtzjsg5dWn8PBQN6l573WPNWgL6F7VwzTY9Y+l+RPg==\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.6.0/leaflet.js\" integrity=\"sha256-fNoRrwkP2GuYPbNSJmMJOCyfRB2DhPQe0rGTgzRsyso=\" crossorigin=\"anonymous\" defer></script>\n<%- include('../build/index-scripts') %>\n<% } else { %>\n<script src=\"<%- serverURL %>/build/MathJax/MathJax.js\" defer></script>\n<script src=\"<%- serverURL %>/build/MathJax/config/TeX-AMS-MML_HTMLorMML.js\" defer></script>\n<script src=\"<%- serverURL %>/build/MathJax/config/Safe.js\" defer></script>\n<script src=\"<%- serverURL %>/build/mermaid/mermaid.min.js\" defer></script>\n<%- include('../build/index-pack-scripts') %>\n<% } %>\n"
  },
  {
    "path": "public/views/codimd/footer.ejs",
    "content": ""
  },
  {
    "path": "public/views/codimd/head.ejs",
    "content": "<meta charset=\"utf-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\">\n<meta name=\"mobile-web-app-capable\" content=\"yes\">\n<meta name=\"codeium:type\" content=\"codemirror5\">\n<title><%= title %></title>\n<link rel=\"icon\" type=\"image/png\" href=\"<%- serverURL %>/favicon.png\">\n<link rel=\"apple-touch-icon\" href=\"<%- serverURL %>/apple-touch-icon.png\">\n<% if(useCDN) { %>\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css\" integrity=\"sha256-H0KfTigpUV+0/5tn2HXC0CPwhhDhWgSawJdnFd0CGCo=\" crossorigin=\"anonymous\" />\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/fork-awesome/1.1.3/css/fork-awesome.min.css\" integrity=\"sha256-ZhApazu+kejqTYhMF+1DzNKjIzP7KXu6AzyXcC1gMus=\" crossorigin=\"anonymous\" />\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/bootstrap-social/4.9.0/bootstrap-social.min.css\" integrity=\"sha256-02JtFTurpwBjQJ6q13iJe82/NF0RbZlJroDegK5g87Y=\" crossorigin=\"anonymous\" />\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css\" integrity=\"sha256-3iu9jgsy9TpTwXKb7bNQzqWekRX7pPK+2OLj3R922fo=\" crossorigin=\"anonymous\" />\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/css/basic/emojify.min.css\" integrity=\"sha256-UOrvMOsSDSrW6szVLe8ZDZezBxh5IoIfgTwdNDgTjiU=\" crossorigin=\"anonymous\" />\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.6.0/leaflet.css\" integrity=\"sha256-SHMGCYmST46SoyGgo4YR/9AlK1vf3ff84Aq9yK4hdqM=\" crossorigin=\"anonymous\" />\n<%- include('../build/index-header') %>\n<%- include('../shared/polyfill') %>\n<% } else { %>\n<link rel=\"stylesheet\" href='<%- serverURL %>/build/emojify.js/dist/css/basic/emojify.min.css'>\n<link rel=\"stylesheet\" href='<%- serverURL %>/css/font.css'>\n<link rel=\"stylesheet\" href='<%- serverURL %>/build/fork-awesome/css/fork-awesome.min.css'>\n<%- include('../build/index-pack-header') %>\n<% } %>\n<link rel=\"stylesheet\" href='<%- serverURL %>/markdown-lint/css/lint.css'>\n"
  },
  {
    "path": "public/views/codimd/header.ejs",
    "content": "<nav class=\"navbar navbar-default navbar-fixed-top unselectable hidden-print\">\n    <!-- Brand and toggle get grouped for better mobile display -->\n    <div class=\"navbar-header\">\n        <div class=\"pull-right\" style=\"margin-top: 17px; color: #777;\">\n            <div class=\"visible-xs\">&nbsp;</div>\n            <div class=\"visible-sm\">&nbsp;</div>\n            <div class=\"visible-md\">&nbsp;</div>\n            <div class=\"visible-lg\">&nbsp;</div>\n        </div>\n        <div class=\"nav-mobile nav-status visible-xs\" id=\"short-online-user-list\">\n            <a class=\"ui-short-status\" data-toggle=\"dropdown\">\n                <span class=\"label label-warning ui-status-connected\" style=\"display: none;\"><i class=\"fa fa-wifi\"></i></span>\n                <span class=\"label label-primary ui-status-online\" style=\"display: none;\"><i class=\"fa fa-users\"></i> <span class=\"ui-status-short-msg\"></span></span>\n                <span class=\"label label-danger ui-status-offline\"><i class=\"fa fa-plug\"></i></span>\n            </a>\n            <ul class=\"dropdown-menu list\" role=\"menu\" aria-labelledby=\"menu\">\n            </ul>\n        </div>\n        <a class=\"navbar-brand pull-left\" href=\"<%- serverURL %>/\"><i class=\"fa fa-file-text\"></i> CodiMD</a>\n        <div class=\"nav-mobile pull-right visible-xs\">\n            <span class=\"btn btn-link btn-file ui-upload-image\" title=\"Upload Image\" style=\"display:none;\">\n                <i class=\"fa fa-camera\"></i><input type=\"file\" accept=\"image/*\" name=\"upload\" multiple>\n            </span>\n            <a data-toggle=\"dropdown\" class=\"btn btn-link\">\n                <i class=\"fa fa-caret-down\"></i>\n            </a>\n            <ul class=\"dropdown-menu list\" role=\"menu\" aria-labelledby=\"menu\">\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-new\" tabindex=\"-1\" href=\"<%- serverURL %>/new\" target=\"_blank\" rel=\"noopener\"><i class=\"fa fa-plus fa-fw\"></i> <%= __('New') %></a>\n                </li>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-publish\" tabindex=\"-1\" href=\"#\" target=\"_blank\" rel=\"noopener\"><i class=\"fa fa-share-square-o fa-fw\"></i> <%= __('Publish') %></a>\n                </li>\n                <li class=\"divider\"></li>\n                <li class=\"dropdown-header\"><%= __('Extra') %></li>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-extra-revision\" tabindex=\"-1\" data-toggle=\"modal\" data-target=\"#revisionModal\"><i class=\"fa fa-history fa-fw\"></i> <%= __('Revision') %></a>\n                </li>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-extra-slide\" tabindex=\"-1\" href=\"#\" target=\"_blank\" rel=\"noopener\"><i class=\"fa fa-tv fa-fw\"></i> <%= __('Slide Mode') %></a>\n                </li>\n                <% if(enableGitHubGist || enableDropBoxSave || enableGitlabSnippets) { %>\n                <li class=\"divider\"></li>\n                <li class=\"dropdown-header\"><%= __('Export') %></li>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-save-dropbox\" tabindex=\"-1\" href=\"#\" target=\"_self\"><i class=\"fa fa-dropbox fa-fw\"></i> Dropbox</a>\n                </li>\n                <% if(enableGitHubGist) { %>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-save-gist\" tabindex=\"-1\" href=\"#\" target=\"_blank\" rel=\"noopener\"><i class=\"fa fa-github fa-fw\"></i> Gist</a>\n                </li>\n                <% } %>\n                <% if(enableGitlabSnippets) { %>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-save-snippet\" href=\"#\"><i class=\"fa fa-gitlab fa-fw\"></i> Snippet</a>\n                </li>\n                <% } %>\n                <% } %>\n                <li class=\"divider\"></li>\n                <li class=\"dropdown-header\"><%= __('Import') %></li>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-import-dropbox\" tabindex=\"-1\" href=\"#\" target=\"_self\"><i class=\"fa fa-dropbox fa-fw\"></i> Dropbox</a>\n                </li>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-import-gist\" href=\"#\" data-toggle=\"modal\" data-target=\"#gistImportModal\"><i class=\"fa fa-github fa-fw\"></i> Gist</a>\n                </li>\n                <% if(enableGitlabSnippets) { %>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-import-snippet\" href=\"#\"><i class=\"fa fa-gitlab fa-fw\"></i> Snippet</a>\n                </li>\n                <% } %>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-import-clipboard\" href=\"#\" data-toggle=\"modal\" data-target=\"#clipboardModal\"><i class=\"fa fa-clipboard fa-fw\"></i> <%= __('Clipboard') %></a>\n                </li>\n                <li class=\"divider\"></li>\n                <li class=\"dropdown-header\"><%= __('Download') %></li>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-download-markdown\" tabindex=\"-1\" href=\"#\" target=\"_self\"><i class=\"fa fa-file-text fa-fw\"></i> Markdown</a>\n                </li>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-download-html\" tabindex=\"-1\" href=\"#\" target=\"_self\"><i class=\"fa fa-file-code-o fa-fw\"></i> HTML</a>\n                </li>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-download-raw-html\" tabindex=\"-1\" href=\"#\" target=\"_self\"><i class=\"fa fa-file-code-o fa-fw\"></i> <%= __('Raw HTML') %></a>\n                </li>\n                <% if(typeof allowPDFExport !== 'undefined' && allowPDFExport) {%>\n                  <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-download-pdf-beta\" tabindex=\"-1\" href=\"#\" target=\"_self\"><i class=\"fa fa-file-pdf-o fa-fw\"></i> PDF (Beta)</a>\n                  </li>\n                <% } %>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-download-pandoc\" tabindex=\"-1\" href=\"#\" target=\"_self\" data-toggle=\"modal\" data-target=\".pandoc-export-modal\"><i class=\"fa fa-cloud-download fa-fw\"></i> Pandoc (Beta)</a>\n                </li>\n                <li class=\"divider\"></li>\n                <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-help\" href=\"#\" data-toggle=\"modal\" data-target=\".help-modal\"><i class=\"fa fa-question-circle fa-fw\"></i> Help</a>\n                </li>\n            </ul>\n            <a class=\"btn btn-link ui-mode\">\n                <i class=\"fa fa-pencil\"></i>\n            </a>\n        </div>\n    </div>\n    <div class=\"collapse navbar-collapse\">\n        <ul class=\"nav navbar-nav navbar-form navbar-left\" style=\"padding:0;\">\n            <div class=\"btn-group\" data-toggle=\"buttons\">\n                <label class=\"btn btn-default ui-edit\" title=\"<%= __('Edit') %> (Ctrl+Alt+E)\">\n                    <input type=\"radio\" name=\"mode\" autocomplete=\"off\"><i class=\"fa fa-pencil\"></i>\n                </label>\n                <label class=\"btn btn-default ui-both\" title=\"<%= __('Both') %> (Ctrl+Alt+B)\">\n                    <input type=\"radio\" name=\"mode\" autocomplete=\"off\"><i class=\"fa fa-columns\"></i>\n                </label>\n                <label class=\"btn btn-default ui-view\" title=\"<%= __('View') %> (Ctrl+Alt+V)\">\n                    <input type=\"radio\" name=\"mode\" autocomplete=\"off\"><i class=\"fa fa-eye\"></i>\n                </label>\n            </div>\n            <div class=\"btn-group\" data-toggle=\"buttons\">\n                <label class=\"btn ui-night\" title=\"<%= __('Night Theme') %>\">\n                    <input type=\"checkbox\" name=\"night\"><i class=\"fa fa-moon-o\"></i>\n                </label>\n            </div>\n            <span class=\"btn btn-link btn-file ui-help\" title=\"<%= __('Help') %>\" data-toggle=\"modal\" data-target=\".help-modal\">\n                <i class=\"fa fa-question-circle\"></i>\n            </span>\n            <span class=\"btn btn-link btn-file ui-upload-image\" title=\"<%= __('Upload Image') %>\" style=\"display:none;\">\n                <i class=\"fa fa-camera\"></i><input type=\"file\" accept=\"image/*\" name=\"upload\" multiple>\n            </span>\n        </ul>\n        <ul class=\"nav navbar-nav navbar-right\">\n            <li id=\"online-user-list\">\n                <a class=\"ui-status\" data-toggle=\"dropdown\">\n                    <span class=\"label label-warning ui-status-connected\" style=\"display: none;\"><i class=\"fa fa-wifi\"></i> <%= __('CONNECTED') %></span>\n                    <span class=\"label label-primary ui-status-online\" style=\"display: none;\"><i class=\"fa fa-users\"></i> <span class=\"ui-status-short-msg\"></span> <%= __('ONLINE') %></span>\n                    <span class=\"label label-danger ui-status-offline\"><i class=\"fa fa-plug\"></i> <%= __('OFFLINE') %></span>\n                </a>\n                <ul class=\"dropdown-menu list\" role=\"menu\" aria-labelledby=\"menu\" style=\"right: 15px;width: 200px;\">\n                </ul>\n            </li>\n        </ul>\n        <ul class=\"nav navbar-nav navbar-right\" style=\"padding:0;\">\n            <li>\n                <a href=\"<%- serverURL %>/new\" target=\"_blank\" rel=\"noopener\" class=\"ui-new\">\n                    <i class=\"fa fa-plus\"></i> <%= __('New') %>\n                </a>\n            </li>\n            <li>\n                <a href=\"#\" target=\"_blank\" rel=\"noopener\" class=\"ui-publish\">\n                    <i class=\"fa fa-share-square-o\"></i> <%= __('Publish') %>\n                </a>\n            </li>\n            <li>\n                <a data-toggle=\"dropdown\">\n                    <%= __('Menu') %> <i class=\"fa fa-caret-down\"></i>\n                </a>\n                <ul class=\"dropdown-menu list\" role=\"menu\" aria-labelledby=\"menu\">\n                    <li class=\"dropdown-header\"><%= __('Extra') %></li>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-extra-revision\" tabindex=\"-1\" data-toggle=\"modal\" data-target=\"#revisionModal\"><i class=\"fa fa-history fa-fw\"></i> <%= __('Revision') %></a>\n                    </li>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-extra-slide\" tabindex=\"-1\" href=\"#\" target=\"_blank\" rel=\"noopener\"><i class=\"fa fa-tv fa-fw\"></i> <%= __('Slide Mode') %></a>\n                    </li>\n                    <% if(enableGitHubGist || enableDropBoxSave || enableGitlabSnippets) { %>\n                    <li class=\"divider\"></li>\n                    <li class=\"dropdown-header\"><%= __('Export') %></li>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-save-dropbox\" tabindex=\"-1\" href=\"#\" target=\"_self\"><i class=\"fa fa-dropbox fa-fw\"></i> Dropbox</a>\n                    </li>\n                    <% if(enableGitHubGist) { %>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-save-gist\" tabindex=\"-1\" href=\"#\" target=\"_blank\" rel=\"noopener\"><i class=\"fa fa-github fa-fw\"></i> Gist</a>\n                    </li>\n                    <% } %>\n                    <% if(enableGitlabSnippets) { %>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-save-snippet\" href=\"#\"><i class=\"fa fa-gitlab fa-fw\"></i> Snippet</a>\n                    </li>\n                    <% } %>\n                    <% } %>\n                    <li class=\"divider\"></li>\n                    <li class=\"dropdown-header\"><%= __('Import') %></li>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-import-dropbox\" tabindex=\"-1\" href=\"#\" target=\"_self\"><i class=\"fa fa-dropbox fa-fw\"></i> Dropbox</a>\n                    </li>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-import-gist\" href=\"#\" data-toggle=\"modal\" data-target=\"#gistImportModal\"><i class=\"fa fa-github fa-fw\"></i> Gist</a>\n                    </li>\n                    <% if(enableGitlabSnippets) { %>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-import-snippet\" href=\"#\"><i class=\"fa fa-gitlab fa-fw\"></i> Snippet</a>\n                    </li>\n                    <% } %>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-import-clipboard\" href=\"#\" data-toggle=\"modal\" data-target=\"#clipboardModal\"><i class=\"fa fa-clipboard fa-fw\"></i> <%= __('Clipboard') %></a>\n                    </li>\n                    <li class=\"divider\"></li>\n                    <li class=\"dropdown-header\"><%= __('Download') %></li>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-download-markdown\" tabindex=\"-1\" href=\"#\" target=\"_self\"><i class=\"fa fa-file-text fa-fw\"></i> Markdown</a>\n                    </li>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-download-html\" tabindex=\"-1\" href=\"#\" target=\"_self\"><i class=\"fa fa-file-code-o fa-fw\"></i> HTML</a>\n                    </li>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-download-raw-html\" tabindex=\"-1\" href=\"#\" target=\"_self\"><i class=\"fa fa-file-code-o fa-fw\"></i> <%= __('Raw HTML') %></a>\n                    </li>\n                    <% if(typeof allowPDFExport !== 'undefined' && allowPDFExport) {%>\n                      <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-download-pdf-beta\" tabindex=\"-1\" href=\"#\" target=\"_self\"><i class=\"fa fa-file-pdf-o fa-fw\"></i> PDF (Beta)</a>\n                      </li>\n                    <% } %>\n                    <li role=\"presentation\"><a role=\"menuitem\" class=\"ui-download-pandoc\" tabindex=\"-1\" href=\"#\" target=\"_self\" data-toggle=\"modal\" data-target=\".pandoc-export-modal\"><i class=\"fa fa-cloud-download fa-fw\"></i> Pandoc (Beta)</a>\n                    </li>\n                </ul>\n            </li>\n        </ul>\n    </div>\n</nav>\n<div class=\"ui-spinner unselectable hidden-print\"></div>\n"
  },
  {
    "path": "public/views/codimd.ejs",
    "content": "<!DOCTYPE html>\n<html lang=\"<%= getLocale() %>\">\n\n<head>\n    <%- include('codimd/head') %>\n</head>\n\n<body>\n    <%- include('codimd/header') %>\n    <%- include('codimd/body') %>\n    <%- include('codimd/footer') %>\n    <%- include('codimd/foot') %>\n</body>\n\n</html>\n"
  },
  {
    "path": "public/views/error.ejs",
    "content": "<!DOCTYPE html>\n<html lang=\"<%= getLocale() %>\">\n\n<head>\n    <%- include('codimd/head') %>\n    <link rel=\"stylesheet\" href=\"<%- serverURL %>/css/center.css\">\n</head>\n\n<body>\n    <%- include('codimd/header') %>\n    <div class=\"container-fluid text-center\">\n        <div class=\"vertical-center-row\">\n            <h1><%- code %> <%- detail %> <small><%- msg %></small></h1>\n        </div>\n    </div>\n    <%- include('codimd/footer') %>\n</body>\n\n</html>\n"
  },
  {
    "path": "public/views/html.hbs",
    "content": "<!DOCTYPE html>\n\n<html lang=\"en\">\n\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n    <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n    <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\">\n    <meta name=\"mobile-web-app-capable\" content=\"yes\">\n    <title>\n        {{title}}\n    </title>\n    <link rel=\"icon\" type=\"image/png\" href=\"{{{url}}}/favicon.png\">\n    <link rel=\"apple-touch-icon\" href=\"{{{url}}}/apple-touch-icon.png\">\n\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css\" integrity=\"sha256-H0KfTigpUV+0/5tn2HXC0CPwhhDhWgSawJdnFd0CGCo=\" crossorigin=\"anonymous\" />\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/fork-awesome/1.1.3/css/fork-awesome.min.css\" integrity=\"sha256-ZhApazu+kejqTYhMF+1DzNKjIzP7KXu6AzyXcC1gMus=\" crossorigin=\"anonymous\" />\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css\" integrity=\"sha256-3iu9jgsy9TpTwXKb7bNQzqWekRX7pPK+2OLj3R922fo=\" crossorigin=\"anonymous\" />\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/prism/1.5.1/themes/prism.min.css\" integrity=\"sha256-vtR0hSWRc3Tb26iuN2oZHt3KRUomwTufNIf5/4oeCyg=\" crossorigin=\"anonymous\" />\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github-gist.min.css\" integrity=\"sha256-tAflq+ymku3Khs+I/WcAneIlafYgDiOQ9stIHH985Wo=\" crossorigin=\"anonymous\" />\n    <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/css/basic/emojify.min.css\" integrity=\"sha256-UOrvMOsSDSrW6szVLe8ZDZezBxh5IoIfgTwdNDgTjiU=\" crossorigin=\"anonymous\" />\n    <style>\n        {{{css}}}\n    </style>\n    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->\n    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->\n    <!--[if lt IE 9]>\n    \t<script src=\"https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js\" integrity=\"sha256-3Jy/GbSLrg0o9y5Z5n1uw0qxZECH7C6OQpVBgNFYa0g=\" crossorigin=\"anonymous\"></script>\n    \t<script src=\"https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js\" integrity=\"sha256-g6iAfvZp+nDQ2TdTR/VVKJf3bGro4ub5fvWSWVRi2NE=\" crossorigin=\"anonymous\"></script>\n\t\t<script src=\"https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js\" integrity=\"sha256-8E4Is26QH0bD52WoQpcB+R/tcWQtpzlCojrybUd7Mxo=\" crossorigin=\"anonymous\"></script>\n    <![endif]-->\n</head>\n\n<body>\n    {{{html}}}\n    <div class=\"ui-toc dropup unselectable hidden-print\" style=\"display:none;\">\n        <div class=\"pull-right dropdown\">\n            <a id=\"tocLabel\" class=\"ui-toc-label btn btn-default\" data-toggle=\"dropdown\" href=\"#\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Table of content\">\n                <i class=\"fa fa-bars\"></i>\n            </a>\n            <ul id=\"ui-toc\" class=\"ui-toc-dropdown dropdown-menu\" aria-labelledby=\"tocLabel\">\n                {{{ui-toc}}}\n            </ul>\n        </div>\n    </div>\n    <div id=\"ui-toc-affix\" class=\"ui-affix-toc ui-toc-dropdown unselectable hidden-print\" data-spy=\"affix\" style=\"top:17px;display:none;\" {{{lang}}} {{{dir}}}>\n        {{{ui-toc-affix}}}\n    </div>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js\" integrity=\"sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js\" integrity=\"sha256-kJrlY+s09+QoWjpkOrXXwhxeaoDz9FW5SaxF8I0DibQ=\" crossorigin=\"anonymous\" defer></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/gist-embed/2.6.0/gist-embed.min.js\" integrity=\"sha256-KyF2D6xPIJUW5sUDSs93vWyZm+1RzIpKCexxElmxl8g=\" crossorigin=\"anonymous\" defer></script>\n    <script>\n        var markdown = $(\".markdown-body\");\n        //smooth all hash trigger scrolling\n        function smoothHashScroll() {\n            var hashElements = $(\"a[href^='#']\").toArray();\n            for (var i = 0; i < hashElements.length; i++) {\n                var element = hashElements[i];\n                var $element = $(element);\n                var hash = element.hash;\n                if (hash) {\n                    $element.on('click', function (e) {\n                        // store hash\n                        var hash = this.hash;\n                        if ($(hash).length <= 0) return;\n                        // prevent default anchor click behavior\n                        e.preventDefault();\n                        // animate\n                        $('body, html').stop(true, true).animate({\n                            scrollTop: $(hash).offset().top\n                        }, 100, \"linear\", function () {\n                            // when done, add hash to url\n                            // (default click behaviour)\n                            window.location.hash = hash;\n                        });\n                    });\n                }\n            }\n        }\n\n        smoothHashScroll();\n        var toc = $('.ui-toc');\n        var tocAffix = $('.ui-affix-toc');\n        var tocDropdown = $('.ui-toc-dropdown');\n        //toc\n        tocDropdown.click(function (e) {\n            e.stopPropagation();\n        });\n\n        var enoughForAffixToc = true;\n\n        function generateScrollspy() {\n            $(document.body).scrollspy({\n                target: ''\n            });\n            $(document.body).scrollspy('refresh');\n            if (enoughForAffixToc) {\n                toc.hide();\n                tocAffix.show();\n            } else {\n                tocAffix.hide();\n                toc.show();\n            }\n            $(document.body).scroll();\n        }\n\n        function windowResize() {\n            //toc right\n            var paddingRight = parseFloat(markdown.css('padding-right'));\n            var right = ($(window).width() - (markdown.offset().left + markdown.outerWidth() - paddingRight));\n            toc.css('right', right + 'px');\n            //affix toc left\n            var newbool;\n            var rightMargin = (markdown.parent().outerWidth() - markdown.outerWidth()) / 2;\n            //for ipad or wider device\n            if (rightMargin >= 133) {\n                newbool = true;\n                var affixLeftMargin = (tocAffix.outerWidth() - tocAffix.width()) / 2;\n                var left = markdown.offset().left + markdown.outerWidth() - affixLeftMargin;\n                tocAffix.css('left', left + 'px');\n            } else {\n                newbool = false;\n            }\n            if (newbool != enoughForAffixToc) {\n                enoughForAffixToc = newbool;\n                generateScrollspy();\n            }\n        }\n        $(window).resize(function () {\n            windowResize();\n        });\n        $(document).ready(function () {\n            windowResize();\n            generateScrollspy();\n        });\n\n        //remove hash\n        function removeHash() {\n            window.location.hash = '';\n        }\n\n        var backtotop = $('.back-to-top');\n        var gotobottom = $('.go-to-bottom');\n\n        backtotop.click(function (e) {\n            e.preventDefault();\n            e.stopPropagation();\n            if (scrollToTop)\n                scrollToTop();\n            removeHash();\n        });\n        gotobottom.click(function (e) {\n            e.preventDefault();\n            e.stopPropagation();\n            if (scrollToBottom)\n                scrollToBottom();\n            removeHash();\n        });\n\n        var toggle = $('.expand-toggle');\n        var tocExpand = false;\n\n        checkExpandToggle();\n        toggle.click(function (e) {\n            e.preventDefault();\n            e.stopPropagation();\n            tocExpand = !tocExpand;\n            checkExpandToggle();\n        })\n\n        function checkExpandToggle () {\n            var toc = $('.ui-toc-dropdown .toc');\n            var toggle = $('.expand-toggle');\n            if (!tocExpand) {\n                toc.removeClass('expand');\n                toggle.text('Expand all');\n            } else {\n                toc.addClass('expand');\n                toggle.text('Collapse all');\n            }\n        }\n\n        function scrollToTop() {\n            $('body, html').stop(true, true).animate({\n                scrollTop: 0\n            }, 100, \"linear\");\n        }\n\n        function scrollToBottom() {\n            $('body, html').stop(true, true).animate({\n                scrollTop: $(document.body)[0].scrollHeight\n            }, 100, \"linear\");\n        }\n    </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "public/views/includes/header.ejs",
    "content": "<% for (var css in htmlWebpackPlugin.files.css) { %>\n<link href=\"<%= '\\<\\%= serverURL \\%\\>'%><%= htmlWebpackPlugin.files.css[css] %>\" rel=\"stylesheet\">\n<% } %>\n"
  },
  {
    "path": "public/views/includes/scripts.ejs",
    "content": "<script src=\"<%= '\\<\\%= serverURL \\%\\>' %>/config\"></script>\n<% for (var js in htmlWebpackPlugin.files.js) { %>\n<script src=\"<%= '\\<\\%= serverURL \\%\\>'%><%= htmlWebpackPlugin.files.js[js] %>\" defer></script>\n<% } %>\n"
  },
  {
    "path": "public/views/index/body.ejs",
    "content": "<div class=\"site-wrapper\">\n    <div class=\"site-wrapper-inner\">\n        <div class=\"cover-container\">\n\n            <div class=\"masthead clearfix\">\n                <div class=\"inner\">\n                    <h3 class=\"masthead-brand\"></h3>\n                    <nav>\n                        <ul class=\"nav masthead-nav\">\n                            <li class=\"ui-home<% if(!signin) { %> active<% } %>\"><a href=\"#\"><%= __('Intro') %></a>\n                            </li>\n                            <li class=\"ui-history<% if(signin) { %> active<% } %>\"><a href=\"#\"><%= __('History') %></a>\n                            </li>\n                            <div class=\"ui-signin\" style=\"float: right; margin-top: 8px;<% if(signin) { %> display: none;<% } %>\">\n                                <% if (allowAnonymous) { %>\n                                <a type=\"button\" href=\"<%- serverURL %>/new\" class=\"btn btn-sm btn-primary\"><i class=\"fa fa-plus\"></i> <%= __('New guest note') %></a>\n                                <% } %>\n                                <% if (authProviders.facebook || authProviders.twitter || authProviders.github || authProviders.bitbucket || authProviders.gitlab ||authProviders.mattermost || authProviders.dropbox || authProviders.google || authProviders.ldap || authProviders.saml || authProviders.oauth2 || authProviders.email) { %>\n                                <button class=\"btn btn-sm btn-success ui-signin\" data-toggle=\"modal\" data-target=\".signin-modal\"><%= __('Sign In') %></button>\n                                <% } %>\n                            </div>\n                            <form name=\"exportNoteData\" action=\"<%- serverURL %>/me/export\" method=\"post\" style=\"display: none;\">\n                                <input type=\"hidden\" name=\"_csrf\" value=\"<%- csrfToken %>\">\n                            </form>\n                            <div class=\"ui-signout\" style=\"float: right; margin-top: 8px;<% if(!signin) { %> display: none;<% } %>\">\n                                <a type=\"button\" href=\"<%- serverURL %>/new\" class=\"btn btn-sm btn-primary\"><i class=\"fa fa-plus\"></i> <%= __('New note') %></a>\n                                <span class=\"ui-profile dropdown pull-right\">\n                                    <button id=\"profileLabel\" class=\"btn btn-sm btn-link ui-profile-label\" style=\"padding-right: 0;\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">\n                                        <img class=\"ui-avatar\" width=\"20\" height=\"20\"><span class=\"hidden-xs hidden-sm\">&ensp;<span class=\"ui-name\"></span></span>&ensp;<i class=\"fa fa-caret-down\"></i>\n                                    </button>\n                                    <ul class=\"dropdown-menu\" aria-labelledby=\"profileLabel\">\n                                        <li><a href=\"<%- serverURL %>/features\"><i class=\"fa fa-dot-circle-o fa-fw\"></i> <%= __('Features') %></a></li>\n                                        <li><a href=\"#\" class=\"ui-export-user-data\"><i class=\"fa fa-cloud-download fa-fw\"></i> <%= __('Export user data') %></a></li>\n                                        <li><a class=\"ui-delete-user\" data-toggle=\"modal\" data-target=\".delete-user-modal\"><i class=\"fa fa-trash fa-fw\"></i> <%= __('Delete user') %></a></li>\n                                        <li><a href=\"<%- serverURL %>/logout\"><i class=\"fa fa-sign-out fa-fw\"></i> <%= __('Sign Out') %></a></li>\n                                    </ul>\n                                </span>\n                            </div>\n                        </ul>\n                    </nav>\n                </div>\n            </div>\n\n            <div id=\"home\" class=\"section\"<% if(signin) { %> style=\"display:none;\"<% } %>>\n                <div class=\"inner cover\">\n                    <h1 class=\"cover-heading\"><i class=\"fa fa-file-text\"></i> CodiMD</h1>\n                    <p class=\"lead\">\n                        <%= __('Best way to write and share your knowledge in markdown.') %>\n                    </p>\n                    <% if (infoMessage && infoMessage.length > 0) { %>\n                    <div class=\"alert alert-info\" style=\"max-width: 400px; margin: 0 auto;\"><%= infoMessage %></div>\n                    <% } %>\n                    <% if (errorMessage && errorMessage.length > 0) { %>\n                    <div class=\"alert alert-danger\" style=\"max-width: 400px; margin: 0 auto;\"><%= errorMessage %></div>\n                    <% } %>\n                    <% if (authProviders.facebook || authProviders.twitter || authProviders.github|| authProviders.bitbucket || authProviders.gitlab || authProviders.mattermost || authProviders.dropbox || authProviders.google || authProviders.ldap || authProviders.saml || authProviders.oauth2 || authProviders.email) { %>\n                    <span class=\"ui-signin\">\n                        <br>\n                        <a type=\"button\" class=\"btn btn-lg btn-success ui-signin\" data-toggle=\"modal\" data-target=\".signin-modal\" style=\"min-width: 200px;\"><%= __('Sign In') %></a>\n                    </span>\n                    <span class=\"ui-or\"><%= __('or') %></span>\n                    <% } %>\n                    <span class=\"ui-signin\">\n                        <a type=\"button\" href=\"<%- serverURL %>/features\" class=\"btn btn-lg btn-primary\" style=\"min-width: 200px;\"><%= __('Explore all features') %></a>\n                        <br>\n                        <br>\n                        <img src=\"<%- serverURL %>/screenshot.png\" class=\"screenshot ui-signin\">\n                    </span>\n                    <div class=\"lead row\" style=\"width: 90%; margin: 0 auto;\">\n                        <div class=\"col-md-4 inner\">\n                            <a href=\"<%- serverURL %>/features#Share-Notes\">\n                                <i class=\"fa fa-bolt fa-3x\"></i>\n                                <h4><%= __('Collaborate with URL') %></h4>\n                            </a>\n                        </div>\n                        <div class=\"col-md-4 inner\">\n                            <a href=\"<%- serverURL %>/features#MathJax\">\n                                <i class=\"fa fa-bar-chart fa-3x\"></i>\n                                <h4><%= __('Support charts and MathJax') %></h4>\n                            </a>\n                        </div>\n                        <div class=\"col-md-4 inner\">\n                            <a href=\"<%- serverURL %>/features#Slide-Mode\">\n                                <i class=\"fa fa-tv fa-3x\"></i>\n                                <h4><%= __('Support slide mode') %></h4>\n                            </a>\n                        </div>\n                    </div>\n                </div>\n            </div>\n\n            <div id=\"history\" class=\"section\"<% if(!signin) { %> style=\"display:none;\"<% } %>>\n                <div class=\"ui-signin\"<% if(signin) { %> style=\"display:none;\"<% } %>>\n                    <p><%= __('Below is the history from browser') %></p>\n                </div>\n                <br>\n                <form class=\"form-inline\">\n                    <div class=\"form-group\" style=\"vertical-align: bottom;\">\n                        <input class=\"form-control ui-use-tags\" placeholder=\"<%= __('Select tags...') %>\" />\n                    </div>\n                    <div class=\"form-group\">\n                        <input class=\"search form-control\" placeholder=\"<%= __('Search keyword...') %>\" />\n                    </div>\n                    <a href=\"#\" class=\"sort btn btn-default\" data-sort=\"text\" title=\"<%= __('Sort by title') %>\">\n                    <%= __('Title') %>\n                    </a>\n                    <a href=\"#\" class=\"sort btn btn-default\" data-sort=\"timestamp\" title=\"<%= __('Sort by time') %>\">\n                    <%= __('Time') %>\n                    </a>\n                    <span class=\"hidden-xs hidden-sm\">\n                        <a href=\"#\" class=\"btn btn-default ui-save-history\" title=\"<%= __('Export history') %>\"><i class=\"fa fa-save\"></i></a>\n                        <span class=\"btn btn-default btn-file ui-open-history\" title=\"<%= __('Import history') %>\">\n                            <i class=\"fa fa-folder-open-o\"></i><input type=\"file\" />\n                        </span>\n                    <a href=\"#\" class=\"btn btn-default ui-clear-history\" title=\"<%= __('Clear history') %>\" data-toggle=\"modal\" data-target=\".delete-history-modal\"><i class=\"fa fa-trash-o\"></i></a>\n                    </span>\n                    <a href=\"#\" class=\"btn btn-default ui-refresh-history\" title=\"<%= __('Refresh history') %>\"><i class=\"fa fa-refresh\"></i></a>\n                </form>\n                <h4 class=\"ui-nohistory\" style=\"display:none;\">\n                    <%= __('No history') %>\n                </h4>\n                <a href=\"#\" class=\"btn btn-primary ui-import-from-browser\" style=\"display:none;\"><%= __('Import from browser') %></a>\n                <ul id=\"history-list\" class=\"list\">\n                </ul>\n                <ul class=\"pagination\"></ul>\n            </div>\n\n            <div class=\"mastfoot\">\n                <div class=\"inner\">\n                    <select class=\"ui-locale\">\n                        <option value=\"en\">English</option>\n                        <option value=\"zh-CN\">简体中文</option>\n                        <option value=\"zh-TW\">繁體中文</option>\n                        <option value=\"fr\">Français</option>\n                        <option value=\"de\">Deutsch</option>\n                        <option value=\"ja\">日本語</option>\n                        <option value=\"es\">Español</option>\n                        <option value=\"ca\">Català</option>\n                        <option value=\"el\">Ελληνικά</option>\n                        <option value=\"pt\">Português</option>\n                        <option value=\"it\">italiano</option>\n                        <option value=\"tr\">Türkçe</option>\n                        <option value=\"ru\">Русский</option>\n                        <option value=\"nl\">Nederlands</option>\n                        <option value=\"hr\">hrvatski jezik</option>\n                        <option value=\"pl\">język polski</option>\n                        <option value=\"uk\">Українська</option>\n                        <option value=\"hi\">हिन्दी</option>\n                        <option value=\"sv\">svenska</option>\n                        <option value=\"eo\">Esperanto</option>\n                        <option value=\"da\">dansk</option>\n                        <option value=\"ko\">한국어</option>\n                        <option value=\"id\">Bahasa Indonesia</option>\n                        <option value=\"sr\">српски</option>\n                    </select>\n                    <p>\n                        <%- __('Powered by %s', '<a href=\"https://github.com/hackmdio/codimd\">CodiMD</a>') %> | <a href=\"<%- serverURL %>/s/release-notes\" target=\"_blank\" rel=\"noopener\"><%= __('Releases') %></a> | <a href=\"<%- sourceURL %>\" target=\"_blank\" rel=\"noopener\"><%= __('Source Code') %></a><% if(privacyStatement) { %> | <a href=\"<%- serverURL %>/s/privacy\" target=\"_blank\" rel=\"noopener\"><%= __('Privacy') %></a><% } %><% if(termsOfUse) { %> | <a href=\"<%- serverURL %>/s/terms-of-use\" target=\"_blank\" rel=\"noopener\"><%= __('Terms of Use') %></a><% } %>\n                    </p>\n                    <h6 class=\"social-foot\">\n                        <%- __('Follow us on %s and %s.', '<a href=\"https://github.com/hackmdio/CodiMD\" target=\"_blank\" rel=\"noopener\"><i class=\"fa fa-github\"></i> GitHub</a>, <a href=\"https://gitter.im/hackmdio/hackmd\" target=\"_blank\" rel=\"noopener\"><i class=\"fa fa-comments\"></i> Gitter</a>', '<a href=\"https://poeditor.com/join/project/q0nuPWyztp\" target=\"_blank\" rel=\"noopener\"><i class=\"fa fa-globe\"></i> POEditor</a>') %>\n                    </h6>\n                    <% if(privacyPolicyURL && privacyPolicyURL.length > 0) { %><p><a href=\"<%- privacyPolicyURL %>\"><%= __('Privacy Policy') %></a></p><% } %>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n<!-- delete history modal -->\n<div class=\"modal fade delete-history-modal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-sm\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\"><%= __('Are you sure?') %></h4>\n            </div>\n            <div class=\"modal-body\">\n                <h5 class=\"ui-delete-history-modal-msg\"></h5>\n                <strong class=\"ui-delete-history-modal-item\"></strong>\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\"><%= __('Cancel') %></button>\n                <button type=\"button\" class=\"btn btn-danger ui-delete-history-modal-confirm\"><%= __('Yes, do it!') %></button>\n            </div>\n        </div>\n    </div>\n</div>\n<!-- delete user modal -->\n<div class=\"modal fade delete-user-modal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-sm\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\"><%= __('Are you sure?') %></h4>\n            </div>\n            <div class=\"modal-body\">\n                <h5 class=\"ui-delete-user-modal-msg\"><%= __('Do you really want to delete your user account?') %></h5>\n                <strong class=\"ui-delete-user-modal-item\"><%= __('This will delete your account, all notes that are owned by you and remove all references to your account from other notes.') %></strong>\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default ui-delete-user-modal-cancel\" data-dismiss=\"modal\"><%= __('Cancel') %></button>\n                <a type=\"button\" class=\"btn btn-danger\" href=\"<%- serverURL %>/me/delete/<%- deleteToken %>\"><%= __('Yes, do it!') %></a>\n            </div>\n        </div>\n    </div>\n</div>\n<%- include('../shared/signin-modal') %>\n"
  },
  {
    "path": "public/views/index/foot.ejs",
    "content": "<% if(useCDN) { %>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js\" integrity=\"sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=\" crossorigin=\"anonymous\"></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.2/velocity.min.js\" integrity=\"sha256-1HqoI76JGKA17K0C0s9K8L/iy8PAC43KVLt1hRD/Ojc=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js\" integrity=\"sha256-kJrlY+s09+QoWjpkOrXXwhxeaoDz9FW5SaxF8I0DibQ=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/list.pagination.js/0.1.1/list.pagination.min.js\" integrity=\"sha256-WwTza96H3BgcQTfEfxX7MFaFc/dZA0QrPRKDRLdFHJo=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.min.js\" integrity=\"sha256-HzzZFiY4t0PIv02Tm8/R3CVvLpcjHhO1z/YAUCp4oQ4=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js\" integrity=\"sha256-AdQN98MVZs44Eq2yTwtoKufhnU+uZ7v2kXnD5vqzZVo=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/js-url/2.3.0/url.min.js\" integrity=\"sha256-HOZJz4x+1mn1Si84WT5XKXPtOlTytmZLnMb6n1v4+5Q=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/1000hz-bootstrap-validator/0.11.8/validator.min.js\" integrity=\"sha256-LHeY7YoYJ0SSXbCx7sR14Pqna+52moaH3bhv0Mjzd/M=\" crossorigin=\"anonymous\" defer></script>\n<%- include('../build/cover-scripts') %>\n<% } else { %>\n<%- include('../build/cover-pack-scripts') %>\n<% } %>\n"
  },
  {
    "path": "public/views/index/footer.ejs",
    "content": ""
  },
  {
    "path": "public/views/index/head.ejs",
    "content": "<meta charset=\"utf-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\">\n<meta name=\"mobile-web-app-capable\" content=\"yes\">\n<meta name=\"description\" content=\"<%= __('Best way to write and share your knowledge in markdown.') %>\">\n<meta name=\"keywords\" content=\"Collaborative, Markdown, Notes\">\n<title>CodiMD - <%= __('Collaborative markdown notes') %></title>\n<link rel=\"icon\" type=\"image/png\" href=\"<%- serverURL %>/favicon.png\">\n<link rel=\"apple-touch-icon\" href=\"<%- serverURL %>/apple-touch-icon.png\">\n<% if(useCDN) { %>\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css\" integrity=\"sha256-H0KfTigpUV+0/5tn2HXC0CPwhhDhWgSawJdnFd0CGCo=\" crossorigin=\"anonymous\" />\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/fork-awesome/1.1.7/css/fork-awesome.min.css\" integrity=\"sha256-gsmEoJAws/Kd3CjuOQzLie5Q3yshhvmo7YNtBG7aaEY=\" crossorigin=\"anonymous\" />\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/bootstrap-social/4.9.0/bootstrap-social.min.css\" integrity=\"sha256-02JtFTurpwBjQJ6q13iJe82/NF0RbZlJroDegK5g87Y=\" crossorigin=\"anonymous\" />\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.min.css\" integrity=\"sha256-k5tPXFBQl+dOk8OmqCtptRa7bRYNRJuvs37bcqsmDB0=\" crossorigin=\"anonymous\" />\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2-bootstrap.min.css\" integrity=\"sha256-HbewCP50syA/2d3zPv+/CdQ4ufX6bI2ntjD3MwsA0UE=\" crossorigin=\"anonymous\" />\n<%- include('../build/cover-header') %>\n<%- include('../shared/polyfill') %>\n<% } else { %>\n<link rel=\"stylesheet\" href='<%- serverURL %>/css/font.css'>\n  <link rel=\"stylesheet\" href='<%- serverURL %>/build/fork-awesome/css/fork-awesome.min.css'>\n<%- include('../build/cover-pack-header') %>\n<% } %>\n"
  },
  {
    "path": "public/views/index/header.ejs",
    "content": ""
  },
  {
    "path": "public/views/index.ejs",
    "content": "<!DOCTYPE html>\n<html lang=\"<%= getLocale() %>\">\n\n<head>\n    <%- include('index/head') %>\n</head>\n\n<body>\n    <%- include('index/header') %>\n    <%- include('index/body') %>\n    <%- include('index/footer') %>\n    <%- include('index/foot') %>\n</body>\n\n</html>\n"
  },
  {
    "path": "public/views/pretty.ejs",
    "content": "<!DOCTYPE html>\n<html lang=\"<%= getLocale() %>\">\n\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n    <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n    <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\">\n    <meta name=\"mobile-web-app-capable\" content=\"yes\">\n    <% if(typeof robots !== 'undefined' && robots) { %>\n    <meta name=\"robots\" content=\"<%= robots %>\">\n    <% } %>\n    <% if(typeof image !== 'undefined' && image) { %>\n    <meta name=\"image\" content=\"<%= image %>\">\n    <% } %>\n    <% if(typeof description !== 'undefined' && description) { %>\n    <meta name=\"description\" content=\"<%= description %>\">\n    <% } %>\n    <title><%= title %></title>\n    <link rel=\"icon\" type=\"image/png\" href=\"<%- serverURL %>/favicon.png\">\n    <link rel=\"apple-touch-icon\" href=\"<%- serverURL %>/apple-touch-icon.png\">\n  <% if(useCDN) { %>\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css\" integrity=\"sha256-H0KfTigpUV+0/5tn2HXC0CPwhhDhWgSawJdnFd0CGCo=\" crossorigin=\"anonymous\" />\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/fork-awesome/1.1.3/css/fork-awesome.min.css\" integrity=\"sha256-ZhApazu+kejqTYhMF+1DzNKjIzP7KXu6AzyXcC1gMus=\" crossorigin=\"anonymous\" />\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css\" integrity=\"sha256-3iu9jgsy9TpTwXKb7bNQzqWekRX7pPK+2OLj3R922fo=\" crossorigin=\"anonymous\" />\n    <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/css/basic/emojify.min.css\" integrity=\"sha256-UOrvMOsSDSrW6szVLe8ZDZezBxh5IoIfgTwdNDgTjiU=\" crossorigin=\"anonymous\" />\n    <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.6.0/leaflet.css\" integrity=\"sha256-SHMGCYmST46SoyGgo4YR/9AlK1vf3ff84Aq9yK4hdqM=\" crossorigin=\"anonymous\" />\n    <%- include('build/pretty-header') %>\n    <%- include('shared/polyfill') %>\n  <% } else { %>\n    <link rel=\"stylesheet\" href='<%- serverURL %>/build/emojify.js/dist/css/basic/emojify.min.css'>\n    <link rel=\"stylesheet\" href='<%- serverURL %>/css/font.css'>\n    <link rel=\"stylesheet\" href='<%- serverURL %>/build/fork-awesome/css/fork-awesome.min.css'>\n    <%- include('build/pretty-pack-header') %>\n  <% } %>\n</head>\n\n<body style=\"display:none;\">\n    <div class=\"ui-infobar container-fluid unselectable hidden-print\">\n        <small>\n            <span>\n                <% if(lastchangeuserprofile) { %>\n                    <span class=\"ui-lastchangeuser\">&thinsp;<i class=\"ui-user-icon small\" style=\"background-image: url(<%- lastchangeuserprofile.photo %>);\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"<%- lastchangeuserprofile.name %>\"></i></span>\n                <% } else { %>\n                  <span class=\"ui-no-lastchangeuser\">&thinsp;<i class=\"fa fa-clock-o fa-fw\" style=\"width: 18px;\"></i></span>\n                <% } %>\n                &nbsp;<span class=\"text-uppercase ui-status-lastchange\"></span>\n                <span class=\"ui-lastchange text-uppercase\" data-createtime=\"<%- createtime %>\" data-updatetime=\"<%- updatetime %>\"></span>\n            </span>\n            <span class=\"pull-right\"><%- viewcount %> views <a href=\"#\" class=\"ui-edit\" title=\"Edit this note\"><i class=\"fa fa-fw fa-pencil\"></i></a></span>\n            <br>\n            <% if(ownerprofile && owner !== lastchangeuser) { %>\n            <span class=\"ui-owner\">\n                &thinsp;<i class=\"ui-user-icon small\" style=\"background-image: url(<%- ownerprofile.photo %>);\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"<%- ownerprofile.name %>\"></i>\n                &nbsp;<span class=\"text-uppercase\">owned this note</span>\n            </span>\n            <% } %>\n        </small>\n    </div>\n    <div id=\"doc\" class=\"container markdown-body\"><%= body %></div>\n    <div class=\"ui-toc dropup unselectable hidden-print\" style=\"display:none;\">\n        <div class=\"pull-right dropdown\">\n            <a id=\"tocLabel\" class=\"ui-toc-label btn btn-default\" data-toggle=\"dropdown\" href=\"#\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\" title=\"Table of content\">\n                <i class=\"fa fa-bars\"></i>\n            </a>\n            <ul id=\"ui-toc\" class=\"ui-toc-dropdown dropdown-menu\" aria-labelledby=\"tocLabel\">\n            </ul>\n        </div>\n    </div>\n    <div id=\"ui-toc-affix\" class=\"ui-affix-toc ui-toc-dropdown unselectable hidden-print\" data-spy=\"affix\" style=\"display:none;\"></div>\n    <% if(typeof disqus !== 'undefined' && disqus) { %>\n    <div class=\"container-fluid\" style=\"max-width: 758px; margin-bottom: 40px;\">\n        <%- include('shared/disqus') %>\n    </div>\n    <% } %>\n</body>\n\n</html>\n<script src=\"<%= serverURL %>/js/mathjax-config-extra.js\"></script>\n<% if(useCDN) { %>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js\" integrity=\"sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=\" crossorigin=\"anonymous\"></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.2/velocity.min.js\" integrity=\"sha256-1HqoI76JGKA17K0C0s9K8L/iy8PAC43KVLt1hRD/Ojc=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js\" integrity=\"sha256-kJrlY+s09+QoWjpkOrXXwhxeaoDz9FW5SaxF8I0DibQ=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js\" integrity=\"sha256-jnOjDTXIPqall8M0MyTSt98JetJuZ7Yu+1Jm7hLTF7U=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/js-yaml/3.7.0/js-yaml.min.js\" integrity=\"sha256-8PanqYAVOGlOct+i65R+HqibK3KPsXINnrSfxN+Y/J0=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js\" integrity=\"sha256-yYfngbEKv4RENfGDvNUqJTqGFcKf31NJEe9OTnnMH3Y=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/TeX-AMS-MML_HTMLorMML.js\" integrity=\"sha256-immzXfCGLhnx3Zfi9F/dUcqxEM8K3o3oTFy9Bh6HCwg=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/Safe.js\" integrity=\"sha256-0ygBUDksNDXZS4vm5HMNH1a33KUu6QT1cdNTN+ZLF+4=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js\" integrity=\"sha256-AdQN98MVZs44Eq2yTwtoKufhnU+uZ7v2kXnD5vqzZVo=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/mermaid/11.5.0/mermaid.min.js\" integrity=\"sha512-3EZqKCkk3nMLmbrI7mfry81KH7dkzy/BoDfQrodwLQnS/RbsVlERdYP6J0oiJegRUxSOmx7Y35WNbVKSw7mipw==\" crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\" defer></script>\n<script src=\"https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/js/emojify-browser.min.js\" integrity=\"sha256-swgfXtqk2bC98KzPoE8tXRz5tmrzpjJWhhXlhYo/wRA=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.2/handlebars.min.js\" integrity=\"sha256-ngJY93C4H39YbmrWhnLzSyiepRuQDVKDNCWO2iyMzFw=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/highlight.min.js\" integrity=\"sha256-1zu+3BnLYV9LdiY85uXMzii3bdrkelyp37e0ZyTAQh0=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/gist-embed/2.6.0/gist-embed.min.js\" integrity=\"sha256-KyF2D6xPIJUW5sUDSs93vWyZm+1RzIpKCexxElmxl8g=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/viz.js/2.1.2/viz.js\" integrity=\"sha256-8RHyK+AFzq9iXwbFo2unqidwPbwHU5FFWe3RwkcVtuU=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/viz.js/2.1.2/full.render.js\" integrity=\"sha256-Ogqs510LFnekr9o7OLdpelaaAmNss9egQRTyzCqV2NQ=\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/abcjs/6.4.4/abcjs-basic.min.js\" integrity=\"sha512-uVrpuoBZLoqLvjKDI0tCpD1HBOIZNTf9EwCrNaxVkk47zpRB54pW81gm8z2DkjtPGPjLZNy/jO5lJ8aXCATuVQ==\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/vega/5.17.1/vega.min.js\" integrity=\"sha512-VaNhWxxm7c02xaYMBd8FTS1V89mnFLopQ2/ClJkrSmh421NROVQNJMqeL5KnwpFW14POUzFIzEIETV/5SAbH/Q==\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/vega-lite/4.17.0/vega-lite.min.js\" integrity=\"sha512-GUsnbKvdacPXIFZvHFFFnWEulYU74fanU2z9aie8g3/F/xcX9vxZuQFLwv9NjdV261fxj9SyAJ3Cf65jvYWMxw==\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/vega-embed/6.14.2/vega-embed.min.js\" integrity=\"sha512-Nhf4uoYFL/Mu9UESXLF9Mo22qmhuWEhAQWHAZOHpNntSvtzjsg5dWn8PBQN6l573WPNWgL6F7VwzTY9Y+l+RPg==\" crossorigin=\"anonymous\" defer></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.6.0/leaflet.js\" integrity=\"sha256-fNoRrwkP2GuYPbNSJmMJOCyfRB2DhPQe0rGTgzRsyso=\" crossorigin=\"anonymous\" defer></script>\n<%- include('build/pretty-scripts') %>\n<% } else { %>\n<script src=\"<%- serverURL %>/build/MathJax/MathJax.js\" defer></script>\n<script src=\"<%- serverURL %>/build/MathJax/config/TeX-AMS-MML_HTMLorMML.js\" defer></script>\n<script src=\"<%- serverURL %>/build/MathJax/config/Safe.js\" defer></script>\n<script src=\"<%- serverURL %>/build/mermaid/mermaid.min.js\" defer></script>\n<%- include('build/pretty-pack-scripts') %>\n<% } %>\n<%- include('shared/ga') %>\n"
  },
  {
    "path": "public/views/shared/disqus.ejs",
    "content": "<div id=\"disqus_thread\"></div>\n<script nonce=\"<%= cspNonce %>\">\n    var disqus_config = function () {\n        this.page.identifier = window.location.pathname.split('/').slice(-1)[0];\n    };\n    (function() {\n        var d = document, s = d.createElement('script');\n        s.src = 'https://<%= disqus.replace(/[^A-Za-z0-9-]+/g, '') %>.disqus.com/embed.js';\n        s.setAttribute('data-timestamp', +new Date());\n        (d.head || d.body).appendChild(s);\n    })();\n</script>\n<noscript\n    >Please enable JavaScript to view the\n    <a href=\"https://disqus.com/?ref_noscript\"\n        >comments powered by Disqus.</a\n    ></noscript\n>\n"
  },
  {
    "path": "public/views/shared/ga.ejs",
    "content": "<% if(typeof GA !== 'undefined' && GA) { %>\n<script nonce=\"<%= cspNonce %>\" async src=\"https://www.googletagmanager.com/gtag/js?id=<%= GA %>\">\n</script>\n<script>\nwindow.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', '<%= GA %>');\ngtag('event', 'page_view');\n</script>\n<% } %>\n"
  },
  {
    "path": "public/views/shared/help-modal.ejs",
    "content": "<!-- help modal -->\n<div class=\"modal fade help-modal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"mySmallModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-lg\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"mySmallModalLabel\"><i class=\"fa fa-question-circle\"></i> <%= __('Help') %></h4>\n            </div>\n            <div class=\"modal-body\">\n                <div class=\"row\">\n                    <div class=\"col-lg-3\">\n                        <div class=\"panel panel-default\">\n                            <div class=\"panel-heading\">\n                                <h3 class=\"panel-title\"><%= __('Contacts') %></h3>\n                            </div>\n                            <div class=\"panel-body\">\n                                <a href=\"https://github.com/hackmdio/codimd/issues\" target=\"_blank\"><i class=\"fa fa-tag fa-fw\"></i> <%= __('Report an issue') %></a>\n                                <br>\n                                <a href=\"https://gitter.im/hackmdio/hackmd\" target=\"_blank\"><i class=\"fa fa-hashtag fa-fw\"></i> <%= __('Meet us on %s', 'Gitter') %></a>\n                                <br>\n                                <a href=\"https://poeditor.com/join/project/q0nuPWyztp\" target=\"_blank\"><i class=\"fa fa-language fa-fw\"></i> <%= __('Help us translating on %s', 'POEditor') %></a>\n                            </div>\n                        </div>\n                        <div class=\"panel panel-default\">\n                            <div class=\"panel-heading\">\n                                <h3 class=\"panel-title\"><%= __('Documents') %></h3>\n                            </div>\n                            <div class=\"panel-body\">\n                                <a href=\"./features\" title=\"Features\" target=\"_blank\"><i class=\"fa fa-dot-circle-o fa-fw\"></i> <%= __('Features') %></a>\n                                <br>\n                                <a href=\"./yaml-metadata\" title=\"YAML Metadata\" target=\"_blank\"><i class=\"fa fa-dot-circle-o fa-fw\"></i> <%= __('YAML Metadata') %></a>\n                                <br>\n                                <a href=\"./slide-example\" title=\"Slide Example\" target=\"_blank\"><i class=\"fa fa-dot-circle-o fa-fw\"></i> <%= __('Slide Example') %></a>\n                            </div>\n                        </div>\n                    </div>\n                    <div class=\"col-lg-9\">\n                        <div class=\"panel panel-default\">\n                            <div class=\"panel-heading\">\n                                <h3 class=\"panel-title\"><%= __('Cheatsheet') %></h3>\n                            </div>\n                            <div class=\"panel-body\" style=\"height: calc(100vh - 215px); overflow: auto;\">\n                                <table class=\"table table-condensed table-cheatsheet\">\n                                    <thead>\n                                        <tr>\n                                            <th><%= __('Example') %></th>\n                                            <th><%= __('Syntax') %></th>\n                                        </tr>\n                                    </thead>\n                                    <tbody class=\"markdown-body\" style=\"font-family: inherit; font-size: 14px; padding: 0; max-width: inherit;\">\n                                        <tr>\n                                            <td><%= __('Header') %></td>\n                                            <td># <%= __('Header') %></td>\n                                        </tr>\n                                        <tr>\n                                            <td><ul><li><%= __('Unordered List') %></li></ul></td>\n                                            <td>- <%= __('Unordered List') %></td>\n                                        </tr>\n                                        <tr>\n                                            <td><ol><li><%= __('Ordered List') %></li></ol></td>\n                                            <td>1. <%= __('Ordered List') %></td>\n                                        </tr>\n                                        <tr>\n                                            <td><ul><li class=\"task-list-item\"><input type=\"checkbox\" class=\"task-list-item-checkbox\" disabled><label></label><%= __('Todo List') %></li></ul></td>\n                                            <td>- [ ] <%= __('Todo List') %></td>\n                                        </tr>\n                                        <tr>\n                                            <td><blockquote> <%= __('Blockquote') %></blockquote></td>\n                                            <td>> <%= __('Blockquote') %></td>\n                                        </tr>\n                                        <tr>\n                                            <td><strong><%= __('Bold font') %></strong></td>\n                                            <td>**<%= __('Bold font') %>**</td>\n                                        </tr>\n                                        <tr>\n                                            <td><i><%= __('Italics font') %></i></td>\n                                            <td>*<%= __('Italics font') %>*</td>\n                                        </tr>\n                                        <tr>\n                                            <td><s><%= __('Strikethrough') %></s></td>\n                                            <td>~~<%= __('Strikethrough') %>~~</td>\n                                        </tr>\n                                        <tr>\n                                            <td>19<sup>th</sup></td>\n                                            <td>19^th^</td>\n                                        </tr>\n                                        <tr>\n                                            <td>H<sub>2</sub>O</td>\n                                            <td>H~2~O</td>\n                                        </tr>\n                                        <tr>\n                                            <td><ins><%= __('Inserted text') %></ins></td>\n                                            <td>++<%= __('Inserted text') %>++</td>\n                                        </tr>\n                                        <tr>\n                                            <td><mark><%= __('Marked text') %></mark></td>\n                                            <td>==<%= __('Marked text') %>==</td>\n                                        </tr>\n                                        <tr>\n                                            <td><a><%= __('Link') %></a></td>\n                                            <td>[link text](https:// \"title\")</td>\n                                        </tr>\n                                        <tr>\n                                            <td><%= __('Image') %></td>\n                                            <td>![image alt](https:// \"title\")</td>\n                                        </tr>\n                                        <tr>\n                                            <td><code><%= __('Code') %></code></td>\n                                            <td>`<%= __('Code') %>`</td>\n                                        </tr>\n                                        <tr>\n                                            <td><pre style=\"border:none !important;\"><code class=\"javascript hljs\"><div class=\"wrapper\"><div class=\"gutter linenumber\"><span data-linenumber=\"1\"></span></div><div class=\"code\"><span class=\"hljs-keyword\">var</span> i = <span class=\"hljs-number\">0</span>;\n</div></div></code></pre></td>\n                                            <td>```javascript<br>var i = 0;<br>```</td>\n                                        </tr>\n                                        <tr>\n                                            <td><img align=\"absmiddle\" alt=\":smile:\" class=\"emoji\" src=\"./build/emojify.js/dist/images/basic/smile.png\" title=\":smile:\"></img></td>\n                                            <td>:smile:</td>\n                                        </tr>\n                                        <tr>\n                                            <td><%= __('Externals') %></td>\n                                            <td>{%youtube youtube_id %}</td>\n                                        </tr>\n                                        <tr>\n                                            <td>L<sup>a</sup>T<sub>e</sub>X</td>\n                                            <td>$L^aT_eX$</td>\n                                        </tr>\n                                        <tr>\n                                            <td><div class=\"alert alert-info\"><p><%= __('This is a alert area.') %></p></div></td>\n                                            <td>:::info<br><%= __('This is a alert area.') %><br>:::</td>\n                                        </tr>\n                                    </tbody>\n                                </table>\n                            </div>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n</div>\n<style>\n    table.table-cheatsheet tr > td:nth-child(2) {\n        font-family: \"Source Code Pro\", Consolas, monaco, monospace;\n        letter-spacing: 0.025em;\n        line-height: 1.25;\n    }\n</style>\n"
  },
  {
    "path": "public/views/shared/pandoc-export-modal.ejs",
    "content": "<!-- pandoc export modal -->\n<div class=\"modal fade pandoc-export-modal\" id=\"pandoc-export-modal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-sm\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\"><%= __('Export with pandoc') %></h4>\n            </div>\n            <form action=\"#\" class=\"form-inline\">\n                <div class=\"modal-body\">\n                    <strong><%= __('Select output format') %></strong>\n                    <select name=\"output\" id=\"output\" class=\"form-control\">\n                        <option value=\"asciidoc\">AsciiDoc</option>\n                        <option value=\"context\">ConTeXt</option>\n                        <option value=\"epub\">EPUB (.epub)</option>\n                        <option value=\"epub3\">EPUB v3 (.epub3)</option>\n                        <option value=\"latex\">LaTeX</option>\n                        <option value=\"odt\">OpenOffice (.odt)</option>\n                        <option value=\"rst\">reStructuredText (.rst)</option>\n                        <option value=\"rtf\">Rich Text Format (.rtf)</option>\n                        <option value=\"textile\">Textile</option>\n                        <option value=\"docx\">Word (.docx)</option>\n                        <option value=\"mediawiki\">Mediawiki</option>\n                    </select>\n                </div>\n                <div class=\"modal-footer\">\n                    <button type=\"submit\" class=\"btn btn-primary\" id=\"pandoc-export-download\"><%= __('Export') %></button>\n                </div>\n            </form>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "public/views/shared/polyfill.ejs",
    "content": "<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->\n<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->\n<!--[if lt IE 9]>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js\" integrity=\"sha256-3Jy/GbSLrg0o9y5Z5n1uw0qxZECH7C6OQpVBgNFYa0g=\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js\" integrity=\"sha256-g6iAfvZp+nDQ2TdTR/VVKJf3bGro4ub5fvWSWVRi2NE=\" crossorigin=\"anonymous\"></script>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js\" integrity=\"sha256-8E4Is26QH0bD52WoQpcB+R/tcWQtpzlCojrybUd7Mxo=\" crossorigin=\"anonymous\"></script>\n<![endif]-->\n"
  },
  {
    "path": "public/views/shared/refresh-modal.ejs",
    "content": "<!-- refresh modal -->\n<div class=\"modal fade\" id=\"refreshModal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-sm\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\"><%= __('This page need refresh') %></h4>\n            </div>\n            <div class=\"modal-body\">\n                <div class=\"incompatible-version\">\n                    <h5><%= __('You have an incompatible client version.') %></h5>\n                    <strong><%= __('Refresh to update.') %></strong>\n                </div>\n                <div class=\"new-version\" style=\"display:none;\">\n                    <h5><%= __('New version available!') %></h5>\n                    <a href=\"<%- serverURL %>/s/release-notes\" target=\"_blank\" rel=\"noopener\"><%= __('See releases notes here') %></a>\n                    <br>\n                    <strong><%= __('Refresh to enjoy new features.') %></strong>\n                </div>\n                <div class=\"user-state-changed\" style=\"display:none;\">\n                    <h5><%= __('Your user state has changed.') %></h5>\n                    <strong><%= __('Refresh to load new user state.') %></strong>\n                </div>\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-primary\" id=\"refreshModalRefresh\"><%= __('Refresh') %></button>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "public/views/shared/revision-modal.ejs",
    "content": "<!-- revision modal -->\n<div class=\"modal fade\" id=\"revisionModal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"mySmallModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-lg\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"mySmallModalLabel\"><i class=\"fa fa-history\"></i> <%= __('Revision') %></h4>\n            </div>\n            <div class=\"modal-body\">\n                <div class=\"row\">\n                    <div class=\"col-lg-4\" style=\"max-height: calc(100vh - 215px); overflow: auto;\">\n                        <div class=\"list-group ui-revision-list\"></div>\n                    </div>\n                    <div class=\"col-lg-8\" style=\"height: calc(100vh - 215px); overflow: hidden;\">\n                        <textarea id=\"revisionViewer\" style=\"display:none;\"></textarea>\n                    </div>\n                </div>\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\"><%= __('Cancel') %></button>\n                <button type=\"button\" class=\"btn btn-primary\" id=\"revisionModalDownload\"><%= __('Download') %></button>\n                <button type=\"button\" class=\"btn btn-danger\" id=\"revisionModalRevert\"><%= __('Revert') %></button>\n            </div>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "public/views/shared/signin-modal.ejs",
    "content": "<!-- signin modal -->\n<div class=\"modal fade signin-modal\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"mySmallModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog modal-sm\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"mySmallModalLabel\"><%= __('Choose method') %></h4>\n            </div>\n            <div class=\"modal-body\" style=\"text-align: center;\">\n                <% if (authProviders.facebook) { %>\n                <a href=\"<%- serverURL %>/auth/facebook\" class=\"btn btn-lg btn-block btn-login-method btn-facebook\">\n                    <i class=\"fa fa-facebook\"></i> <%= __('Sign in via %s', 'Facebook') %>\n                </a>\n                <% } %>\n                <% if (authProviders.twitter) { %>\n                <a href=\"<%- serverURL %>/auth/twitter\" class=\"btn btn-lg btn-block btn-login-method btn-twitter\">\n                    <i class=\"fa fa-twitter\"></i> <%= __('Sign in via %s', 'Twitter') %>\n                </a>\n                <% } %>\n                <% if (authProviders.github) { %>\n                <a href=\"<%- serverURL %>/auth/github\" class=\"btn btn-lg btn-block btn-login-method btn-github\">\n                    <i class=\"fa fa-github\"></i> <%= __('Sign in via %s', 'GitHub') %>\n                </a>\n                <% } %>\n                <% if (authProviders.bitbucket) { %>\n                <a href=\"<%- serverURL %>/auth/bitbucket\" class=\"btn btn-lg btn-block btn-login-method btn-bitbucket\">\n                    <i class=\"fa fa-bitbucket\"></i> <%= __('Sign in via %s', 'Bitbucket') %>\n                </a>\n                <% } %>\n                <% if (authProviders.gitlab) { %>\n                <a href=\"<%- serverURL %>/auth/gitlab\" class=\"btn btn-lg btn-block btn-login-method btn-gitlab\">\n                    <i class=\"fa fa-gitlab\"></i> <%= __('Sign in via %s', 'GitLab') %>\n                </a>\n                <% } %>\n                <% if (authProviders.mattermost) { %>\n                <a href=\"<%- serverURL %>/auth/mattermost\" class=\"btn btn-lg btn-block btn-login-method btn-mattermost\">\n                    <i class=\"oauth-icon\"><img alt=\"mattermost-logo\" src=\"<%- serverURL %>/images/mattermost-logo.svg\" /></i> <%= __('Sign in via %s', 'Mattermost') %>\n                </a>\n                <% } %>\n                <% if (authProviders.dropbox) { %>\n                <a href=\"<%- serverURL %>/auth/dropbox\" class=\"btn btn-lg btn-block btn-login-method btn-dropbox\">\n                    <i class=\"fa fa-dropbox\"></i> <%= __('Sign in via %s', 'Dropbox') %>\n                </a>\n                <% } %>\n                <% if (authProviders.google) { %>\n                <a href=\"<%- serverURL %>/auth/google\" class=\"btn btn-lg btn-block\" style=\"color: #fff; background-color: #4285F4; vertical-align: middle; font-size: 14px; font-family: Roboto;\">\n                    <svg aria-hidden=\"true\" width=\"34\" height=\"34\" viewBox=\"-8 -8 34 34\" style=\"vertical-align: middle; margin-right: 16; background-color=#fff;\"><path d=\"M16.51 8H8.98v3h4.3c-.18 1-.74 1.48-1.6 2.04v2.01h2.6a7.8 7.8 0 002.38-5.88c0-.57-.05-.66-.15-1.18z\" fill=\"#4285F4\"></path><path d=\"M8.98 17c2.16 0 3.97-.72 5.3-1.94l-2.6-2a4.8 4.8 0 01-7.18-2.54H1.83v2.07A8 8 0 008.98 17z\" fill=\"#34A853\"></path><path d=\"M4.5 10.52a4.8 4.8 0 010-3.04V5.41H1.83a8 8 0 000 7.18l2.67-2.07z\" fill=\"#FBBC05\"></path><path d=\"M8.98 4.18c1.17 0 2.23.4 3.06 1.2l2.3-2.3A8 8 0 001.83 5.4L4.5 7.49a4.77 4.77 0 014.48-3.3z\" fill=\"#EA4335\"></path></svg> <%= __('Sign in via %s', 'Google') %>\n                </a>\n                <% } %>\n                <% if (authProviders.saml) { %>\n                <a href=\"<%- serverURL %>/auth/saml\" class=\"btn btn-lg btn-block btn-login-method btn-success\">\n                    <i class=\"fa fa-users\"></i> <%= __('Sign in via %s', 'SAML') %>\n                </a>\n                <% } %>\n                <% if (authProviders.oauth2) { %>\n                <a href=\"<%- serverURL %>/auth/oauth2\" class=\"btn btn-lg btn-block btn-login-method btn-soundcloud\">\n                    <i class=\"fa fa-mail-forward\"></i> <%= __('Sign in via %s', authProviders.oauth2ProviderName || 'OAuth2') %>\n                </a>\n                <% } %>\n                <% if ((authProviders.facebook || authProviders.twitter || authProviders.github || authProviders.bitbucket || authProviders.gitlab || authProviders.mattermost || authProviders.dropbox || authProviders.google || authProviders.saml || authProviders.oauth2) && authProviders.ldap) { %>\n                <hr>\n                <% }%>\n                <% if (authProviders.ldap) { %>\n                <h4><%= __('Sign in via %s', authProviders.ldapProviderName ? authProviders.ldapProviderName + ' (LDAP)' : 'LDAP') %></h4>\n                <form data-toggle=\"validator\" role=\"form\" class=\"form-horizontal\" method=\"post\" enctype=\"application/x-www-form-urlencoded\">\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-12\">\n                            <input type=\"username\" class=\"form-control\" name=\"username\" placeholder=\"Username\" required>\n                            <span class=\"help-block control-label with-errors\" style=\"display: inline;\"></span>\n                        </div>\n                    </div>\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-12\">\n                            <input type=\"password\" class=\"form-control\" name=\"password\" placeholder=\"Password\" required>\n                            <span class=\"help-block control-label with_errors\" style=\"display: inline;\"></span>\n                        </div>\n                    </div>\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-12\">\n                            <button type=\"submit\" class=\"btn btn-primary\" formaction=\"<%- serverURL %>/auth/ldap\"><%= __('Sign In') %></button>\n                        </div>\n                    </div>\n                </form>\n                <% } %>\n                <% if ((authProviders.facebook || authProviders.twitter || authProviders.github || authProviders.bitbucket || authProviders.gitlab || authProviders.mattermost || authProviders.dropbox || authProviders.google || authProviders.ldap || authProviders.oauth2) && authProviders.openID) { %>\n                <hr>\n                <% }%>\n                <% if (authProviders.openID) { %>\n                <h4><%= __('Sign in via %s', 'OpenID') %></h4>\n                <form data-toggle=\"validator\" role=\"form\" class=\"form-horizontal\" method=\"post\" enctype=\"application/x-www-form-urlencoded\">\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-12\">\n                            <input type=\"text\" class=\"form-control\" name=\"openid_identifier\" placeholder=\"OpenID\" required>\n                            <span class=\"help-block control-label with-errors\" style=\"display: inline;\"></span>\n                        </div>\n                    </div>\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-12\">\n                            <button type=\"submit\" class=\"btn btn-primary\" formaction=\"<%- serverURL %>/auth/openid\"><%= __('Sign In') %></button>\n                        </div>\n                    </div>\n                </form>\n                <% } %>\n                <% if ((authProviders.facebook || authProviders.twitter || authProviders.github|| authProviders.bitbucket || authProviders.gitlab || authProviders.mattermost || authProviders.dropbox || authProviders.google || authProviders.ldap || authProviders.oauth2 || authProviders.openID) && authProviders.email) { %>\n                <hr>\n                <% }%>\n                <% if (authProviders.email) { %>\n                <h4><%= __('Sign in via %s', 'E-Mail') %></h4>\n                <form data-toggle=\"validator\" role=\"form\" class=\"form-horizontal\" method=\"post\" enctype=\"application/x-www-form-urlencoded\">\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-12\">\n                            <input type=\"email\" class=\"form-control\" name=\"email\" placeholder=\"E-Mail\" required>\n                            <span class=\"help-block control-label with-errors\" style=\"display: inline;\"></span>\n                        </div>\n                    </div>\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-12\">\n                            <input type=\"password\" class=\"form-control\" name=\"password\" placeholder=\"Password\" required>\n                            <span class=\"help-block control-label with-errors\" style=\"display: inline;\"></span>\n                        </div>\n                    </div>\n                    <div class=\"form-group\">\n                        <div class=\"col-sm-12\">\n                            <button type=\"submit\" class=\"btn btn-primary\" formaction=\"<%- serverURL %>/login\"><%= __('Sign In') %></button>\n                            <% if (authProviders.allowEmailRegister) { %><button type=\"submit\" class=\"btn btn-default\" formaction=\"<%- serverURL %>/register\"><%= __('Register') %></button><% }%>\n                        </div>\n                    </div>\n                </form>\n                <% }%>\n            </div>\n        </div>\n    </div>\n</div>\n"
  },
  {
    "path": "public/views/slide.ejs",
    "content": "<!doctype html>\n<html lang=\"<%= getLocale() %>\">\n    <head>\n        <meta charset=\"utf-8\">\n        <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n        <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\">\n        <meta name=\"mobile-web-app-capable\" content=\"yes\">\n        <% if(typeof robots !== 'undefined' && robots) { %>\n        <meta name=\"robots\" content=\"<%= robots %>\">\n        <% } %>\n        <% if(typeof description !== 'undefined' && description) { %>\n        <meta name=\"description\" content=\"<%= description %>\">\n        <% } %>\n        <title><%= title %></title>\n        <link rel=\"icon\" type=\"image/png\" href=\"<%- serverURL %>/favicon.png\">\n        <link rel=\"apple-touch-icon\" href=\"<%- serverURL %>/apple-touch-icon.png\">\n\n        <% if(useCDN) { %>\n        <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/fork-awesome/1.1.7/css/fork-awesome.min.css\" integrity=\"sha256-gsmEoJAws/Kd3CjuOQzLie5Q3yshhvmo7YNtBG7aaEY=\" crossorigin=\"anonymous\" />\n        <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css\" integrity=\"sha256-3iu9jgsy9TpTwXKb7bNQzqWekRX7pPK+2OLj3R922fo=\" crossorigin=\"anonymous\" />\n        <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/reveal.js@3.9.2/css/reveal.min.css\" integrity=\"sha256-h2NhWerL2k7KAzo6YqYMo1T5B6+QT2Bb/CprRV2aW20=\" crossorigin=\"anonymous\" />\n        <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/css/basic/emojify.min.css\" integrity=\"sha256-UOrvMOsSDSrW6szVLe8ZDZezBxh5IoIfgTwdNDgTjiU=\" crossorigin=\"anonymous\" />\n        <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.6.0/leaflet.css\" integrity=\"sha256-SHMGCYmST46SoyGgo4YR/9AlK1vf3ff84Aq9yK4hdqM=\" crossorigin=\"anonymous\" />\n        <%- include('build/slide-header') %>\n        <%- include('shared/polyfill') %>\n        <% } else { %>\n        <link rel=\"stylesheet\" href=\"<%- serverURL %>/build/reveal.js/css/reveal.css\">\n        <link rel=\"stylesheet\" href='<%- serverURL %>/build/emojify.js/dist/css/basic/emojify.min.css'>\n        <link rel=\"stylesheet\" href='<%- serverURL %>/css/font.css'>\n        <link rel=\"stylesheet\" href='<%- serverURL %>/build/fork-awesome/css/fork-awesome.min.css'>\n        <%- include('build/slide-pack-header') %>\n        <% } %>\n\n        <!-- For reveal.js theme -->\n        <% if(typeof theme !== 'undefined' && theme) { %>\n        <link rel=\"stylesheet\" href=\"<%- serverURL %>/build/reveal.js/css/theme/<%= theme %>.css\" id=\"theme\">\n        <% } else { %>\n        <link rel=\"stylesheet\" href=\"<%- serverURL %>/build/reveal.js/css/theme/black.css\" id=\"theme\">\n        <% } %>\n        <!-- For syntax highlighting -->\n        <link rel=\"stylesheet\" href=\"<%- serverURL %>/build/reveal.js/lib/css/zenburn.css\">\n        <!-- For overwrite reveal.js -->\n        <link rel=\"stylesheet\" href=\"<%- serverURL %>/css/slide.css\">\n\n        <!-- Printing and PDF exports -->\n        <script nonce=\"<%= cspNonce %>\">\n            var link = document.createElement( 'link' );\n            link.rel = 'stylesheet';\n            link.type = 'text/css';\n            link.href = '<%- serverURL %>/build/reveal.js/' + (window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css');\n            document.getElementsByTagName( 'head' )[0].appendChild( link );\n        </script>\n    </head>\n    <body>\n        <div class=\"container\">\n            <div class=\"reveal\">\n                <div class=\"slides\"><%= body %></div>\n            </div>\n\n            <div id=\"meta\"><%= meta %></div>\n\n            <div class=\"footer\">\n                <div class=\"unselectable hidden-print gray-font\">\n                    <small>\n                        <span>\n                            <% if(lastchangeuserprofile) { %>\n                                <span class=\"ui-lastchangeuser\">&thinsp;<i class=\"ui-user-icon small\" style=\"background-image: url(<%- lastchangeuserprofile.photo %>);\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"<%- lastchangeuserprofile.name %>\"></i></span>\n                            <% } else { %>\n                                <span class=\"ui-no-lastchangeuser\">&thinsp;<i class=\"fa fa-clock-o fa-fw\"></i></span>\n                            <% } %>\n                            &nbsp;<span class=\"text-uppercase ui-status-lastchange\"></span>\n                            <span class=\"ui-lastchange text-uppercase\" data-createtime=\"<%- createtime %>\" data-updatetime=\"<%- updatetime %>\"></span>\n                        </span>\n                        <span class=\"pull-right\"><%- viewcount %> views <a href=\"#\" class=\"ui-edit\" title=\"Edit this note\"><i class=\"fa fa-fw fa-pencil\"></i></a><a class=\"ui-print\" href=\"\" title=\"Open print view\"><i class=\"fa fa-fw fa-print\"></i></a></span>\n                        <br>\n                        <% if(ownerprofile && owner !== lastchangeuser) { %>\n                        <span class=\"ui-owner\">\n                            &thinsp;<i class=\"ui-user-icon small\" style=\"background-image: url(<%- ownerprofile.photo %>);\" data-toggle=\"tooltip\" data-placement=\"right\" title=\"<%- ownerprofile.name %>\"></i>\n                            &nbsp;<span class=\"text-uppercase\">owned this note</span>\n                        </span>\n                        <% } %>\n                    </small>\n                </div>\n                <% if(typeof disqus !== 'undefined' && disqus) { %>\n                <div class=\"slides-disqus\">\n                    <%- include('shared/disqus') %>\n                </div>\n                <% } %>\n            </div>\n        </div>\n\n        <script src=\"<%= serverURL %>/js/mathjax-config-extra.js\"></script>\n        <% if(useCDN) { %>\n        <script src=\"https://cdn.jsdelivr.net/npm/reveal.js@3.9.2/js/reveal.min.js\" integrity=\"sha256-1fq1NvUmkMIWOBgIEzGFr0UUNuwWmOa29YqMkXnYlH4=\" crossorigin=\"anonymous\"></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js\" integrity=\"sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=\" crossorigin=\"anonymous\"></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.2/velocity.min.js\" integrity=\"sha256-1HqoI76JGKA17K0C0s9K8L/iy8PAC43KVLt1hRD/Ojc=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js\" integrity=\"sha256-jnOjDTXIPqall8M0MyTSt98JetJuZ7Yu+1Jm7hLTF7U=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/js-yaml/3.13.1/js-yaml.min.js\" integrity=\"sha256-ry6nlLQ1JmRl5RUPQ4eSuaSp/rGNPvl144WHHs7BiNE=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js\" integrity=\"sha256-yYfngbEKv4RENfGDvNUqJTqGFcKf31NJEe9OTnnMH3Y=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/TeX-AMS-MML_HTMLorMML.js\" integrity=\"sha256-immzXfCGLhnx3Zfi9F/dUcqxEM8K3o3oTFy9Bh6HCwg=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/Safe.js\" integrity=\"sha256-0ygBUDksNDXZS4vm5HMNH1a33KUu6QT1cdNTN+ZLF+4=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js\" integrity=\"sha256-AdQN98MVZs44Eq2yTwtoKufhnU+uZ7v2kXnD5vqzZVo=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/mermaid/11.5.0/mermaid.min.js\" integrity=\"sha512-3EZqKCkk3nMLmbrI7mfry81KH7dkzy/BoDfQrodwLQnS/RbsVlERdYP6J0oiJegRUxSOmx7Y35WNbVKSw7mipw==\" crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\" defer></script>\n        <script src=\"https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/js/emojify-browser.min.js\" integrity=\"sha256-swgfXtqk2bC98KzPoE8tXRz5tmrzpjJWhhXlhYo/wRA=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.2/handlebars.min.js\" integrity=\"sha256-ngJY93C4H39YbmrWhnLzSyiepRuQDVKDNCWO2iyMzFw=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.10/highlight.min.js\" integrity=\"sha256-1zu+3BnLYV9LdiY85uXMzii3bdrkelyp37e0ZyTAQh0=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/gist-embed/2.6.0/gist-embed.min.js\" integrity=\"sha256-KyF2D6xPIJUW5sUDSs93vWyZm+1RzIpKCexxElmxl8g=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/viz.js/2.1.2/viz.js\" integrity=\"sha256-8RHyK+AFzq9iXwbFo2unqidwPbwHU5FFWe3RwkcVtuU=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/viz.js/2.1.2/full.render.js\" integrity=\"sha256-Ogqs510LFnekr9o7OLdpelaaAmNss9egQRTyzCqV2NQ=\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/abcjs/6.4.4/abcjs-basic.min.js\" integrity=\"sha512-uVrpuoBZLoqLvjKDI0tCpD1HBOIZNTf9EwCrNaxVkk47zpRB54pW81gm8z2DkjtPGPjLZNy/jO5lJ8aXCATuVQ==\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/vega/5.17.1/vega.min.js\" integrity=\"sha512-VaNhWxxm7c02xaYMBd8FTS1V89mnFLopQ2/ClJkrSmh421NROVQNJMqeL5KnwpFW14POUzFIzEIETV/5SAbH/Q==\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/vega-lite/4.17.0/vega-lite.min.js\" integrity=\"sha512-GUsnbKvdacPXIFZvHFFFnWEulYU74fanU2z9aie8g3/F/xcX9vxZuQFLwv9NjdV261fxj9SyAJ3Cf65jvYWMxw==\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/vega-embed/6.14.2/vega-embed.min.js\" integrity=\"sha512-Nhf4uoYFL/Mu9UESXLF9Mo22qmhuWEhAQWHAZOHpNntSvtzjsg5dWn8PBQN6l573WPNWgL6F7VwzTY9Y+l+RPg==\" crossorigin=\"anonymous\" defer></script>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.6.0/leaflet.js\" integrity=\"sha256-fNoRrwkP2GuYPbNSJmMJOCyfRB2DhPQe0rGTgzRsyso=\" crossorigin=\"anonymous\" defer></script>\n        <%- include('build/slide-scripts') %>\n        <% } else { %>\n        <script src=\"<%- serverURL %>/build/MathJax/MathJax.js\" defer></script>\n        <script src=\"<%- serverURL %>/build/MathJax/config/TeX-AMS-MML_HTMLorMML.js\" defer></script>\n        <script src=\"<%- serverURL %>/build/MathJax/config/Safe.js\" defer></script>\n        <script src=\"<%- serverURL %>/build/mermaid/mermaid.min.js\" defer></script>\n        <%- include('build/slide-pack-scripts') %>\n        <% } %>\n    </body>\n</html>\n\n<%- include('shared/ga') %>\n"
  },
  {
    "path": "scalingo.json",
    "content": "{\n    \"name\": \"CodiMD\",\n    \"description\": \"Realtime collaborative markdown notes on all platforms\",\n    \"keywords\": [\n        \"Collaborative\",\n        \"Markdown\",\n        \"Notes\"\n    ],\n    \"website\": \"https://github.com/hackmdio/codimd\",\n    \"repository\": \"https://github.com/hackmdio/codimd\",\n    \"logo\": \"https://github.com/hackmdio/codimd/raw/master/public/codimd-icon-1024.png\",\n    \"success_url\": \"/\",\n    \"env\": {\n        \"NPM_CONFIG_PRODUCTION\": {\n            \"description\": \"Let npm also install development build tool\",\n            \"value\": \"false\"\n        },\n        \"CMD_SESSION_SECRET\": {\n            \"description\": \"Secret used to secure session cookies.\",\n            \"required\": false\n        },\n        \"CMD_HSTS_ENABLE\": {\n            \"description\": \"whether to also use HSTS if HTTPS is enabled\",\n            \"required\": false\n        },\n        \"CMD_HSTS_MAX_AGE\": {\n            \"description\": \"max duration, in seconds, to tell clients to keep HSTS status\",\n            \"required\": false\n        },\n        \"CMD_HSTS_INCLUDE_SUBDOMAINS\": {\n            \"description\": \"whether to tell clients to also regard subdomains as HSTS hosts\",\n            \"required\": false\n        },\n        \"CMD_HSTS_PRELOAD\": {\n            \"description\": \"whether to allow at all adding of the site to HSTS preloads (e.g. in browsers)\",\n            \"required\": false\n        },\n        \"CMD_DOMAIN\": {\n            \"description\": \"domain name\",\n            \"required\": false\n        },\n        \"CMD_URL_PATH\": {\n            \"description\": \"sub url path, like `www.example.com/<URL_PATH>`\",\n            \"required\": false\n        },\n        \"CMD_ALLOW_ORIGIN\": {\n            \"description\": \"domain name whitelist (use comma to separate)\",\n            \"required\": false,\n            \"value\": \"localhost\"\n        },\n        \"CMD_PROTOCOL_USESSL\": {\n            \"description\": \"set to use ssl protocol for resources path (only applied when domain is set)\",\n            \"required\": false\n        },\n        \"CMD_URL_ADDPORT\": {\n            \"description\": \"set to add port on callback url (port 80 or 443 won't applied) (only applied when domain is set)\",\n            \"required\": false\n        },\n        \"CMD_FACEBOOK_CLIENTID\": {\n            \"description\": \"Facebook API client id\",\n            \"required\": false\n        },\n        \"CMD_FACEBOOK_CLIENTSECRET\": {\n            \"description\": \"Facebook API client secret\",\n            \"required\": false\n        },\n        \"CMD_TWITTER_CONSUMERKEY\": {\n            \"description\": \"Twitter API consumer key\",\n            \"required\": false\n        },\n        \"CMD_TWITTER_CONSUMERSECRET\": {\n            \"description\": \"Twitter API consumer secret\",\n            \"required\": false\n        },\n        \"CMD_GITHUB_CLIENTID\": {\n            \"description\": \"GitHub API client id\",\n            \"required\": false\n        },\n        \"CMD_GITHUB_CLIENTSECRET\": {\n            \"description\": \"GitHub API client secret\",\n            \"required\": false\n        },\n        \"CMD_GITHUB_ORGANIZATIONS\": {\n            \"description\": \"GitHub whitelist of orgs\",\n            \"required\": false\n        },\n        \"CMD_GITHUB_SCOPES\": {\n            \"description\": \"GitHub OAuth API scopes\",\n            \"required\": false\n        },\n        \"CMD_BITBUCKET_CLIENTID\": {\n            \"description\": \"Bitbucket API client id\",\n            \"required\": false\n        },\n        \"CMD_BITBUCKET_CLIENTSECRET\": {\n            \"description\": \"Bitbucket API client secret\",\n            \"required\": false\n        },\n        \"CMD_GITLAB_BASEURL\": {\n            \"description\": \"GitLab authentication endpoint, set to use other endpoint than GitLab.com (optional)\",\n            \"required\": false\n        },\n        \"CMD_GITLAB_CLIENTID\": {\n            \"description\": \"GitLab API client id\",\n            \"required\": false\n        },\n        \"CMD_GITLAB_CLIENTSECRET\": {\n            \"description\": \"GitLab API client secret\",\n            \"required\": false\n        },\n        \"CMD_GITLAB_SCOPE\": {\n            \"description\": \"GitLab API client scope (optional)\",\n            \"required\": false\n        },\n        \"CMD_MATTERMOST_BASEURL\": {\n            \"description\": \"Mattermost authentication endpoint\",\n            \"required\": false\n        },\n        \"CMD_MATTERMOST_CLIENTID\": {\n            \"description\": \"Mattermost API client id\",\n            \"required\": false\n        },\n        \"CMD_MATTERMOST_CLIENTSECRET\": {\n            \"description\": \"Mattermost API client secret\",\n            \"required\": false\n        },\n        \"CMD_DROPBOX_CLIENTID\": {\n            \"description\": \"Dropbox API client id\",\n            \"required\": false\n        },\n        \"CMD_DROPBOX_CLIENTSECRET\": {\n            \"description\": \"Dropbox API client secret\",\n            \"required\": false\n        },\n        \"CMD_DROPBOX_APP_KEY\": {\n            \"description\": \"Dropbox app key (for import/export)\",\n            \"required\": false\n        },\n        \"CMD_GOOGLE_CLIENTID\": {\n            \"description\": \"Google API client id\",\n            \"required\": false\n        },\n        \"CMD_GOOGLE_CLIENTSECRET\": {\n            \"description\": \"Google API client secret\",\n            \"required\": false\n        },\n        \"CMD_IMGUR_CLIENTID\": {\n            \"description\": \"Imgur API client id\",\n            \"required\": false\n        },\n        \"CMD_ALLOW_PDF_EXPORT\": {\n            \"description\": \"Enable or disable PDF exports\",\n            \"required\": false\n        },\n        \"CMD_DB_URL\": {\n            \"description\": \"Database query url\",\n            \"value\": \"$DATABASE_URL\"\n        },\n        \"CMD_PORT\": {\n            \"description\": \"Listening Port\",\n            \"value\": \"$PORT\"\n        },\n        \"DYNO\": {\n            \"description\": \"Require this env var for deploy correctly the app\",\n            \"value\": \"Scalingo\"\n        }\n    },\n    \"formation\": {\n        \"web\": {\n            \"amount\": 1,\n            \"size\": \"S\"\n        }\n    },\n    \"addons\": [\n        \"postgresql:postgresql-sandbox\"\n    ]\n}\n"
  },
  {
    "path": "test/auth/oauth2/strategy.test.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst assert = require('assert')\nconst chance = require('chance')()\n\nconst { extractProfileAttribute } = require('../../../lib/auth/oauth2/strategy')\n\ndescribe('OAuth2CustomStrategy', function () {\n  describe('#extractProfileAttribute', function () {\n    const data = {\n      user: {\n        email: chance.email()\n      },\n      arrayData: [\n        {\n          email: chance.email()\n        },\n        {\n          email: chance.email()\n        }\n      ]\n    }\n\n    it('should parse normal attribute correctly', function () {\n      assert(extractProfileAttribute(data, 'user.email') === data.user.email)\n    })\n\n    it('should return undefined when nested object key not exists', function () {\n      assert(extractProfileAttribute(data, 'user.profile') === undefined)\n    })\n\n    it('should return undefined when whole object key not exists', function () {\n      assert(extractProfileAttribute(data, 'profile.email') === undefined)\n    })\n\n    it('should return attribute in array correct', function () {\n      assert(extractProfileAttribute(data, 'arrayData[0].email') === data.arrayData[0].email)\n      assert(extractProfileAttribute(data, 'arrayData[1].email') === data.arrayData[1].email)\n    })\n\n    it('should return undefined when array index out of bound', function () {\n      assert(extractProfileAttribute(data, 'arrayData[3].email') === undefined)\n    })\n\n    it('should return undefined when array key not exists', function () {\n      assert(extractProfileAttribute(data, 'notExistsArray[5].email') === undefined)\n    })\n\n    it('should return undefined when data is undefined', function () {\n      assert(extractProfileAttribute(undefined, 'email') === undefined)\n      assert(extractProfileAttribute(null, 'email') === undefined)\n      assert(extractProfileAttribute({}, 'email') === undefined)\n    })\n  })\n})\n"
  },
  {
    "path": "test/connectionQueue.test.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst assert = require('assert')\nconst sinon = require('sinon')\n\nconst { ProcessQueue } = require('../lib/realtime/processQueue')\n\ndescribe('ProcessQueue', function () {\n  let clock\n  const waitTimeForCheckResult = 50\n\n  beforeEach(() => {\n    clock = sinon.useFakeTimers({\n      toFake: ['setInterval']\n    })\n  })\n\n  afterEach(() => {\n    clock.restore()\n    sinon.restore()\n  })\n\n  it('should not accept more than maximum task', () => {\n    const queue = new ProcessQueue({ maximumLength: 2 })\n\n    queue.start()\n    assert(queue.push(1, () => (Promise.resolve())))\n    assert(queue.push(1, () => (Promise.resolve())) === false)\n  })\n\n  it('should run task every interval', (done) => {\n    const runningClock = []\n    const queue = new ProcessQueue({ maximumLength: 2 })\n    const task = async () => {\n      runningClock.push(clock.now)\n    }\n    queue.start()\n    assert(queue.push(1, task))\n    assert(queue.push(2, task))\n    clock.tick(5)\n    setTimeout(() => {\n      clock.tick(5)\n    }, 1)\n    setTimeout(() => {\n      clock.tick(5)\n    }, 2)\n    setTimeout(() => {\n      clock.tick(5)\n    }, 3)\n\n    setTimeout(() => {\n      queue.stop()\n      assert(runningClock.length === 2)\n      done()\n    }, waitTimeForCheckResult)\n  })\n\n  it('should not crash when repeat stop queue', () => {\n    const queue = new ProcessQueue({ maximumLength: 2, triggerTimeInterval: 10 })\n    try {\n      queue.stop()\n      queue.stop()\n      queue.stop()\n      assert.ok(true)\n    } catch (e) {\n      assert.fail(e)\n    }\n  })\n\n  it('should run process when queue is empty', (done) => {\n    const queue = new ProcessQueue({ maximumLength: 2, triggerTimeInterval: 100 })\n    const processSpy = sinon.spy(queue, 'process')\n    queue.start()\n    clock.tick(100)\n    setTimeout(() => {\n      assert(processSpy.called)\n      done()\n    }, waitTimeForCheckResult)\n  })\n\n  it('should run process although error occurred', (done) => {\n    const queue = new ProcessQueue({ maximumLength: 2, triggerTimeInterval: 100 })\n    const failedTask = sinon.spy(async () => {\n      throw new Error('error')\n    })\n    const normalTask = sinon.spy(async () => {\n    })\n    queue.start()\n    assert(queue.push(1, failedTask))\n    assert(queue.push(2, normalTask))\n    clock.tick(100)\n    setTimeout(() => {\n      clock.tick(100)\n    }, 1)\n    setTimeout(() => {\n      // assert(queue.queue.length === 0)\n      assert(failedTask.called)\n      assert(normalTask.called)\n      done()\n    }, waitTimeForCheckResult)\n  })\n\n  it('should ignore trigger when event not complete', (done) => {\n    const queue = new ProcessQueue({ maximumLength: 2, triggerTimeInterval: 10 })\n    const processSpy = sinon.spy(queue, 'process')\n    const longTask = async () => {\n      return new Promise((resolve) => {\n        setInterval(() => {\n          resolve()\n        }, 50)\n      })\n    }\n    queue.start()\n    queue.push(1, longTask)\n    clock.tick(10)\n    setTimeout(() => {\n      clock.tick(10)\n    }, 0)\n    setTimeout(() => {\n      clock.tick(10)\n    }, 1)\n    setTimeout(() => {\n      assert(processSpy.callCount === 1)\n      assert(processSpy.calledOnce)\n      done()\n    }, waitTimeForCheckResult)\n  })\n})\n"
  },
  {
    "path": "test/csp.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst assert = require('assert')\nconst crypto = require('crypto')\nconst fs = require('fs')\nconst path = require('path')\nconst mock = require('mock-require')\n\ndescribe('Content security policies', function () {\n  let defaultConfig, csp\n\n  before(function () {\n    csp = require('../lib/csp')\n  })\n\n  beforeEach(function () {\n    // Reset config to make sure we don't influence other tests\n    defaultConfig = {\n      csp: {\n        enable: true,\n        directives: {\n        },\n        addDefaults: true,\n        addDisqus: true,\n        addGoogleAnalytics: true,\n        upgradeInsecureRequests: 'auto',\n        reportURI: undefined\n      },\n      useCDN: true\n    }\n  })\n\n  afterEach(function () {\n    mock.stop('../lib/config')\n    csp = mock.reRequire('../lib/csp')\n  })\n\n  after(function () {\n    mock.stopAll()\n    csp = mock.reRequire('../lib/csp')\n  })\n\n  // beginnging Tests\n  it('Disable CDN', function () {\n    const testconfig = defaultConfig\n    testconfig.useCDN = false\n    mock('../lib/config', testconfig)\n    csp = mock.reRequire('../lib/csp')\n\n    assert(!csp.computeDirectives().scriptSrc.includes('https://cdnjs.cloudflare.com'))\n    assert(!csp.computeDirectives().scriptSrc.includes('https://cdn.jsdelivr.net'))\n    assert(!csp.computeDirectives().scriptSrc.includes('https://cdn.mathjax.org'))\n    assert(!csp.computeDirectives().styleSrc.includes('https://cdnjs.cloudflare.com'))\n    assert(!csp.computeDirectives().styleSrc.includes('https://cdn.jsdelivr.net'))\n    assert(!csp.computeDirectives().styleSrc.includes('https://fonts.googleapis.com'))\n    assert(!csp.computeDirectives().fontSrc.includes('https://cdnjs.cloudflare.com'))\n    assert(!csp.computeDirectives().fontSrc.includes('https://fonts.gstatic.com'))\n  })\n\n  it('Disable Google Analytics', function () {\n    const testconfig = defaultConfig\n    testconfig.csp.addGoogleAnalytics = false\n    mock('../lib/config', testconfig)\n    csp = mock.reRequire('../lib/csp')\n\n    assert(!csp.computeDirectives().scriptSrc.includes('https://www.google-analytics.com'))\n  })\n\n  it('Disable Disqus', function () {\n    const testconfig = defaultConfig\n    testconfig.csp.addDisqus = false\n    mock('../lib/config', testconfig)\n    csp = mock.reRequire('../lib/csp')\n\n    assert(!csp.computeDirectives().scriptSrc.includes('https://disqus.com'))\n    assert(!csp.computeDirectives().scriptSrc.includes('https://*.disqus.com'))\n    assert(!csp.computeDirectives().scriptSrc.includes('https://*.disquscdn.com'))\n    assert(!csp.computeDirectives().styleSrc.includes('https://*.disquscdn.com'))\n    assert(!csp.computeDirectives().fontSrc.includes('https://*.disquscdn.com'))\n  })\n\n  it('Set ReportURI', function () {\n    const testconfig = defaultConfig\n    testconfig.csp.reportURI = 'https://example.com/reportURI'\n    mock('../lib/config', testconfig)\n    csp = mock.reRequire('../lib/csp')\n\n    assert.strictEqual(csp.computeDirectives().reportUri, 'https://example.com/reportURI')\n  })\n\n  it('Set own directives', function () {\n    const testconfig = defaultConfig\n    mock('../lib/config', defaultConfig)\n    csp = mock.reRequire('../lib/csp')\n    const unextendedCSP = csp.computeDirectives()\n    testconfig.csp.directives = {\n      defaultSrc: ['https://default.example.com'],\n      scriptSrc: ['https://script.example.com'],\n      imgSrc: ['https://img.example.com'],\n      styleSrc: ['https://style.example.com'],\n      fontSrc: ['https://font.example.com'],\n      objectSrc: ['https://object.example.com'],\n      mediaSrc: ['https://media.example.com'],\n      childSrc: ['https://child.example.com'],\n      connectSrc: ['https://connect.example.com']\n    }\n    mock('../lib/config', testconfig)\n    csp = mock.reRequire('../lib/csp')\n\n    const variations = ['default', 'script', 'img', 'style', 'font', 'object', 'media', 'child', 'connect']\n\n    for (let i = 0; i < variations.length; i++) {\n      assert.strictEqual(csp.computeDirectives()[variations[i] + 'Src'].toString(), ['https://' + variations[i] + '.example.com'].concat(unextendedCSP[variations[i] + 'Src']).toString())\n    }\n  })\n\n  /*\n   * This test reminds us to update the CSP hash for the speaker notes\n   */\n  it('Unchanged hash for reveal.js speaker notes plugin', function () {\n    const hash = crypto.createHash('sha1')\n    hash.update(fs.readFileSync(path.resolve(__dirname, '../node_modules/reveal.js/plugin/notes/notes.html'), 'utf8'), 'utf8')\n    assert.strictEqual(hash.digest('hex'), 'd5d872ae49b5db27f638b152e6e528837204d380')\n  })\n})\n"
  },
  {
    "path": "test/letter-avatars.js",
    "content": "/* eslint-env node, mocha */\n\n'use strict'\n\nconst assert = require('assert')\nconst mock = require('mock-require')\n\ndescribe('generateAvatarURL() gravatar enabled', function () {\n  let avatars\n  beforeEach(function () {\n    // Reset config to make sure we don't influence other tests\n    const testconfig = {\n      allowGravatar: true,\n      serverURL: 'http://localhost:3000',\n      port: 3000\n    }\n    mock('../lib/config', testconfig)\n    avatars = mock.reRequire('../lib/letter-avatars')\n  })\n\n  it('should return correct urls', function () {\n    assert.strictEqual(avatars.generateAvatarURL('Daan Sprenkels', 'hello@dsprenkels.com', true), 'https://www.gravatar.com/avatar/d41b5f3508cc3f31865566a47dd0336b?s=400')\n    assert.strictEqual(avatars.generateAvatarURL('Daan Sprenkels', 'hello@dsprenkels.com', false), 'https://www.gravatar.com/avatar/d41b5f3508cc3f31865566a47dd0336b?s=96')\n  })\n\n  it('should return correct urls for names with spaces', function () {\n    assert.strictEqual(avatars.generateAvatarURL('Daan Sprenkels'), 'http://localhost:3000/user/Daan%20Sprenkels/avatar.svg')\n  })\n})\n\ndescribe('generateAvatarURL() gravatar disabled', function () {\n  let avatars\n  beforeEach(function () {\n    // Reset config to make sure we don't influence other tests\n    const testconfig = {\n      allowGravatar: false,\n      serverURL: 'http://localhost:3000',\n      port: 3000\n    }\n    mock('../lib/config', testconfig)\n    avatars = mock.reRequire('../lib/letter-avatars')\n  })\n\n  it('should return correct urls', function () {\n    assert.strictEqual(avatars.generateAvatarURL('Daan Sprenkels', 'hello@dsprenkels.com', true), 'http://localhost:3000/user/Daan%20Sprenkels/avatar.svg')\n    assert.strictEqual(avatars.generateAvatarURL('Daan Sprenkels', 'hello@dsprenkels.com', false), 'http://localhost:3000/user/Daan%20Sprenkels/avatar.svg')\n  })\n\n  it('should return correct urls for names with spaces', function () {\n    assert.strictEqual(avatars.generateAvatarURL('Daan Sprenkels'), 'http://localhost:3000/user/Daan%20Sprenkels/avatar.svg')\n  })\n})\n"
  },
  {
    "path": "test/realtime/cleanDanglingUser.test.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst assert = require('assert')\nconst mock = require('mock-require')\nconst sinon = require('sinon')\nconst { removeModuleFromRequireCache, makeMockSocket } = require('./utils')\n\ndescribe('cleanDanglingUser', function () {\n  let clock\n  beforeEach(() => {\n    clock = sinon.useFakeTimers()\n    mock('../../lib/processQueue', require('../testDoubles/ProcessQueueFake'))\n    mock('../../lib/logger', {\n      error: () => {},\n      info: () => {}\n    })\n    mock('../../lib/history', {})\n    mock('../../lib/models', {\n      Revision: {\n        saveAllNotesRevision: () => {\n        }\n      }\n    })\n    mock('../../lib/config', {\n      debug: true\n    })\n    mock('../../lib/realtimeUpdateDirtyNoteJob', require('../testDoubles/realtimeJobStub'))\n    mock('../../lib/realtimeSaveRevisionJob', require('../testDoubles/realtimeJobStub'))\n  })\n\n  afterEach(() => {\n    clock.restore()\n    removeModuleFromRequireCache('../../lib/realtime/realtime')\n    mock.stopAll()\n    sinon.restore()\n  })\n\n  it('should call queueForDisconnectSpy when user is dangling', (done) => {\n    const realtime = require('../../lib/realtime/realtime')\n    const queueForDisconnectSpy = sinon.spy(realtime, 'queueForDisconnect')\n    realtime.io = {\n      to: sinon.stub().callsFake(function () {\n        return {\n          emit: sinon.fake()\n        }\n      }),\n      sockets: {\n        connected: {}\n      }\n    }\n    const user1Socket = makeMockSocket()\n    const user2Socket = makeMockSocket()\n\n    user1Socket.rooms.push('room1')\n\n    realtime.io.sockets.connected[user1Socket.id] = user1Socket\n    realtime.io.sockets.connected[user2Socket.id] = user2Socket\n\n    realtime.users[user1Socket.id] = user1Socket\n    realtime.users[user2Socket.id] = user2Socket\n    clock.tick(60000)\n    clock.restore()\n    setTimeout(() => {\n      assert(queueForDisconnectSpy.called)\n      done()\n    }, 50)\n  })\n})\n"
  },
  {
    "path": "test/realtime/connection.test.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst assert = require('assert')\nconst mock = require('mock-require')\nconst sinon = require('sinon')\n\nconst { createFakeLogger } = require('../testDoubles/loggerFake')\nconst { removeLibModuleCache, makeMockSocket } = require('./utils')\nconst realtimeJobStub = require('../testDoubles/realtimeJobStub')\n\ndescribe('realtime#connection', function () {\n  describe('connection', function () {\n    let realtime\n    let modelStub\n\n    beforeEach(() => {\n      removeLibModuleCache()\n      modelStub = {\n        Note: {\n          findOne: sinon.stub()\n        },\n        User: {},\n        Author: {}\n      }\n      mock('../../lib/logger', createFakeLogger())\n      mock('../../lib/history', {})\n      mock('../../lib/models', modelStub)\n      mock('../../lib/config', {})\n      mock('../../lib/realtimeUpdateDirtyNoteJob', realtimeJobStub)\n      mock('../../lib/realtimeCleanDanglingUserJob', realtimeJobStub)\n      mock('../../lib/realtimeSaveRevisionJob', realtimeJobStub)\n      mock('../../lib/ot', require('../testDoubles/otFake'))\n      realtime = require('../../lib/realtime/realtime')\n    })\n\n    afterEach(() => {\n      mock.stopAll()\n      sinon.restore()\n    })\n\n    describe('fail', function () {\n      it('should fast return when server not start', () => {\n        const mockSocket = makeMockSocket()\n        realtime.maintenance = true\n        const spy = sinon.spy(realtime, 'parseNoteIdFromSocketAsync')\n        realtime.connection(mockSocket)\n        assert(!spy.called)\n      })\n\n      it('should failed when parse noteId occur error', (done) => {\n        const mockSocket = makeMockSocket()\n        realtime.maintenance = false\n        const parseNoteIdFromSocketSpy = sinon.stub(realtime, 'parseNoteIdFromSocketAsync').callsFake(async (socket) => {\n          /* eslint-disable-next-line */\n          throw 'error'\n        })\n\n        const failConnectionSpy = sinon.stub(realtime, 'failConnection')\n\n        realtime.connection(mockSocket)\n\n        setTimeout(() => {\n          assert(parseNoteIdFromSocketSpy.called)\n          assert(failConnectionSpy.calledOnce)\n          assert.deepStrictEqual(failConnectionSpy.lastCall.args, [500, 'error', mockSocket])\n          done()\n        }, 50)\n      })\n\n      it('should failed when noteId not exists', (done) => {\n        const mockSocket = makeMockSocket()\n        realtime.maintenance = false\n        const parseNoteIdFromSocketSpy = sinon.stub(realtime, 'parseNoteIdFromSocketAsync').callsFake(async (socket) => {\n          return null\n        })\n\n        const failConnectionSpy = sinon.stub(realtime, 'failConnection')\n\n        realtime.connection(mockSocket)\n\n        setTimeout(() => {\n          assert(parseNoteIdFromSocketSpy.called)\n          assert(failConnectionSpy.calledOnce)\n          assert.deepStrictEqual(failConnectionSpy.lastCall.args, [404, 'note id not found', mockSocket])\n          done()\n        }, 50)\n      })\n    })\n\n    it('should success connect', function (done) {\n      const mockSocket = makeMockSocket()\n      const noteId = 'note123'\n      realtime.maintenance = false\n      const parseNoteIdFromSocketSpy = sinon.stub(realtime, 'parseNoteIdFromSocketAsync').callsFake(async (socket) => {\n        return noteId\n      })\n      const updateUserDataStub = sinon.stub(realtime, 'updateUserData')\n\n      realtime.connection(mockSocket)\n\n      setTimeout(() => {\n        assert.ok(parseNoteIdFromSocketSpy.calledOnce)\n        assert(updateUserDataStub.calledOnce)\n        done()\n      }, 50)\n    })\n\n    describe('flow', function () {\n      it('should establish connection', function (done) {\n        const noteId = 'note123'\n        const mockSocket = makeMockSocket(null, {\n          noteId: noteId\n        })\n        mockSocket.request.user.logged_in = true\n        mockSocket.request.user.id = 'user1'\n        mockSocket.noteId = noteId\n        realtime.maintenance = false\n        sinon.stub(realtime, 'parseNoteIdFromSocketAsync').callsFake(async (socket) => {\n          return noteId\n        })\n        const updateHistoryStub = sinon.stub(realtime, 'updateHistory')\n        const emitOnlineUsersStub = sinon.stub(realtime, 'emitOnlineUsers')\n        const emitRefreshStub = sinon.stub(realtime, 'emitRefresh')\n        const failConnectionSpy = sinon.spy(realtime, 'failConnection')\n\n        const note = {\n          id: noteId,\n          authors: [\n            {\n              userId: 'user1',\n              color: 'red',\n              user: {\n                id: 'user1',\n                name: 'Alice'\n              }\n            },\n            {\n              userId: 'user2',\n              color: 'blue',\n              user: {\n                id: 'user2',\n                name: 'Bob'\n              }\n            }\n          ]\n        }\n        modelStub.Note.findOne.returns(Promise.resolve(note))\n        modelStub.User.getProfile = sinon.stub().callsFake((user) => {\n          return user\n        })\n        sinon.stub(realtime, 'checkViewPermission').returns(true)\n        realtime.connection(mockSocket)\n        setTimeout(() => {\n          assert(modelStub.Note.findOne.calledOnce)\n          assert.deepStrictEqual(modelStub.Note.findOne.lastCall.args[0].include, [\n            {\n              model: modelStub.User,\n              as: 'owner'\n            }, {\n              model: modelStub.User,\n              as: 'lastchangeuser'\n            }, {\n              model: modelStub.Author,\n              as: 'authors',\n              include: [{\n                model: modelStub.User,\n                as: 'user'\n              }]\n            }\n          ])\n          assert(modelStub.Note.findOne.lastCall.args[0].where.id === noteId)\n          assert(updateHistoryStub.calledOnce)\n          assert(emitOnlineUsersStub.calledOnce)\n          assert(emitRefreshStub.calledOnce)\n          assert(failConnectionSpy.callCount === 0)\n          assert(realtime.getNotePool()[noteId].id === noteId)\n          assert(realtime.getNotePool()[noteId].socks.length === 1)\n          assert.deepStrictEqual(realtime.getNotePool()[noteId].authors, {\n            user1: {\n              userid: 'user1', color: 'red', photo: undefined, name: 'Alice'\n            },\n            user2: {\n              userid: 'user2', color: 'blue', photo: undefined, name: 'Bob'\n            }\n          })\n          assert(Object.keys(realtime.getNotePool()[noteId].users).length === 1)\n          done()\n        }, 50)\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/realtime/dirtyNoteUpdate.test.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst assert = require('assert')\nconst mock = require('mock-require')\nconst sinon = require('sinon')\nconst { removeModuleFromRequireCache, makeMockSocket, removeLibModuleCache } = require('./utils')\n\ndescribe('realtime#update note is dirty timer', function () {\n  let realtime\n  let clock\n\n  beforeEach(() => {\n    removeLibModuleCache()\n    clock = sinon.useFakeTimers({\n      toFake: ['setInterval']\n    })\n    mock('../../lib/logger', {\n      error: () => {\n      }\n    })\n    mock('../../lib/history', {})\n    mock('../../lib/models', {\n      Revision: {\n        saveAllNotesRevision: () => {\n        }\n      }\n    })\n    mock('../../lib/config', {})\n    realtime = require('../../lib/realtime/realtime')\n\n    realtime.io = {\n      to: sinon.stub().callsFake(function () {\n        return {\n          emit: sinon.fake()\n        }\n      })\n    }\n  })\n\n  afterEach(() => {\n    removeModuleFromRequireCache('../../lib/realtime/realtimeUpdateDirtyNoteJob')\n    removeModuleFromRequireCache('../../lib/realtime/realtime')\n    mock.stopAll()\n    clock.restore()\n  })\n\n  it('should update note when note is dirty', (done) => {\n    sinon.stub(realtime, 'updateNote').callsFake(function (note, callback) {\n      callback(null, note)\n    })\n\n    realtime.notes.note1 = {\n      server: {\n        isDirty: false\n      },\n      socks: []\n    }\n\n    const note2 = {\n      server: {\n        isDirty: true\n      },\n      socks: []\n    }\n\n    realtime.notes.note2 = note2\n\n    clock.tick(1000)\n    setTimeout(() => {\n      assert(note2.server.isDirty === false)\n      done()\n    }, 10)\n  })\n\n  it('should not do anything when note missing', function (done) {\n    sinon.stub(realtime, 'updateNote').callsFake(function (note, callback) {\n      delete realtime.notes.note\n      callback(null, note)\n    })\n\n    const note = {\n      server: {\n        isDirty: true\n      },\n      socks: [makeMockSocket()]\n    }\n    realtime.notes.note = note\n\n    clock.tick(1000)\n\n    setTimeout(() => {\n      assert(note.server.isDirty === false)\n      assert(note.socks[0].disconnect.called === false)\n      done()\n    }, 50)\n  })\n\n  it('should disconnect all clients when update note error', function (done) {\n    sinon.stub(realtime, 'updateNote').callsFake(function (note, callback) {\n      callback(new Error('some error'), null)\n    })\n\n    realtime.io = {\n      to: sinon.stub().callsFake(function () {\n        return {\n          emit: sinon.fake()\n        }\n      })\n    }\n\n    const note = {\n      server: {\n        isDirty: true\n      },\n      socks: [makeMockSocket(), undefined, makeMockSocket()]\n    }\n    realtime.notes.note = note\n\n    clock.tick(1000)\n\n    setTimeout(() => {\n      assert(note.server.isDirty === false)\n      assert(note.socks[0].disconnect.called)\n      assert(note.socks[2].disconnect.called)\n      done()\n    }, 50)\n  })\n})\n"
  },
  {
    "path": "test/realtime/disconnect-process.test.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst assert = require('assert')\nconst mock = require('mock-require')\nconst sinon = require('sinon')\n\nconst { makeMockSocket, removeModuleFromRequireCache } = require('./utils')\n\ndescribe('realtime#disconnect', function () {\n  const noteId = 'note1_id'\n  let realtime\n  let updateNoteStub\n  let emitOnlineUsersStub\n  let client\n\n  beforeEach(() => {\n    mock('../../lib/logger', {\n      error: () => {\n      }\n    })\n    mock('../../lib/history', {})\n    mock('../../lib/models', {\n      Revision: {\n        saveAllNotesRevision: () => {\n        }\n      }\n    })\n    mock('../../lib/config', {})\n\n    realtime = require('../../lib/realtime/realtime')\n    updateNoteStub = sinon.stub(realtime, 'updateNote').callsFake((note, callback) => {\n      callback(null, note)\n    })\n    emitOnlineUsersStub = sinon.stub(realtime, 'emitOnlineUsers')\n    client = makeMockSocket()\n    client.noteId = noteId\n\n    realtime.users[client.id] = {\n      id: client.id,\n      color: '#ff0000',\n      cursor: null,\n      login: false,\n      userid: null,\n      name: null,\n      idle: false,\n      type: null\n    }\n\n    realtime.getNotePool()[noteId] = {\n      id: noteId,\n      server: {\n        isDirty: true\n      },\n      users: {\n        [client.id]: realtime.users[client.id]\n      },\n      socks: [client]\n    }\n  })\n\n  afterEach(() => {\n    removeModuleFromRequireCache('../../lib/realtime/realtime')\n    mock.stopAll()\n    sinon.restore()\n  })\n\n  it('should disconnect success', function (done) {\n    realtime.queueForDisconnect(client)\n\n    setTimeout(() => {\n      assert(typeof realtime.users[client.id] === 'undefined')\n      assert(emitOnlineUsersStub.called)\n      assert(updateNoteStub.called)\n      assert(Object.keys(realtime.users).length === 0)\n      assert(Object.keys(realtime.notes).length === 0)\n      done()\n    }, 5)\n  })\n\n  it('should disconnect success when note is not dirty', function (done) {\n    realtime.notes[noteId].server.isDirty = false\n    realtime.queueForDisconnect(client)\n\n    setTimeout(() => {\n      assert(typeof realtime.users[client.id] === 'undefined')\n      assert(emitOnlineUsersStub.called)\n      assert(updateNoteStub.called === false)\n      assert(Object.keys(realtime.users).length === 0)\n      assert(Object.keys(realtime.notes).length === 0)\n      done()\n    }, 5)\n  })\n})\n"
  },
  {
    "path": "test/realtime/extractNoteIdFromSocket.test.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst mock = require('mock-require')\nconst assert = require('assert')\n\nconst { makeMockSocket } = require('./utils')\n\ndescribe('realtime#extractNoteIdFromSocket', function () {\n  beforeEach(() => {\n    mock('../../lib/logger', {})\n    mock('../../lib/history', {})\n    mock('../../lib/models', {})\n  })\n\n  afterEach(() => {\n    delete require.cache[require.resolve('../../lib/realtime/realtime')]\n    mock.stopAll()\n  })\n\n  describe('urlPath not set', function () {\n    beforeEach(() => {\n      mock('../../lib/config', {})\n      realtime = require('../../lib/realtime/realtime')\n    })\n\n    let realtime\n\n    it('return false if socket or socket.handshake not exists', function () {\n      let noteId = realtime.extractNoteIdFromSocket()\n      assert.strictEqual(false, noteId)\n\n      noteId = realtime.extractNoteIdFromSocket({})\n      assert.strictEqual(false, noteId)\n    })\n\n    it('return false if query not set and referer not set', function () {\n      const noteId = realtime.extractNoteIdFromSocket(makeMockSocket({\n        otherHeader: 1\n      }, {\n        otherQuery: 1\n      }))\n      assert.strictEqual(false, noteId)\n    })\n\n    it('return noteId from query', function () {\n      // Arrange\n      const incomingNoteId = 'myNoteId'\n      const incomingSocket = makeMockSocket(undefined, { noteId: incomingNoteId })\n\n      // Act\n      const noteId = realtime.extractNoteIdFromSocket(incomingSocket)\n      // Assert\n      assert.strictEqual(noteId, incomingNoteId)\n    })\n\n    it('return noteId from old method (referer)', function () {\n      // Arrange\n      const incomingNoteId = 'myNoteId'\n      const incomingSocket = makeMockSocket({\n        referer: `https://localhost:3000/${incomingNoteId}`\n      })\n\n      // Act\n      const noteId = realtime.extractNoteIdFromSocket(incomingSocket)\n      // Assert\n      assert.strictEqual(noteId, incomingNoteId)\n    })\n  })\n\n  describe('urlPath is set', function () {\n    let realtime\n    it('return noteId from old method (referer) and urlPath set', function () {\n      // Arrange\n      const urlPath = 'hello'\n      mock('../../lib/config', {\n        urlPath: urlPath\n      })\n      realtime = require('../../lib/realtime/realtime')\n      const incomingNoteId = 'myNoteId'\n      const incomingSocket = makeMockSocket({\n        referer: `https://localhost:3000/${urlPath}/${incomingNoteId}`\n      })\n\n      // Act\n      const noteId = realtime.extractNoteIdFromSocket(incomingSocket)\n      // Assert\n      assert.strictEqual(noteId, incomingNoteId)\n    })\n  })\n})\n"
  },
  {
    "path": "test/realtime/ifMayEdit.test.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst assert = require('assert')\nconst mock = require('mock-require')\nconst sinon = require('sinon')\n\nconst { createFakeLogger } = require('../testDoubles/loggerFake')\nconst realtimeJobStub = require('../testDoubles/realtimeJobStub')\nconst { removeLibModuleCache, makeMockSocket } = require('./utils')\n\ndescribe('realtime#ifMayEdit', function () {\n  let modelsStub\n  beforeEach(() => {\n    removeLibModuleCache()\n    mock('../../lib/config', {})\n    mock('../../lib/logger', createFakeLogger())\n    mock('../../lib/models', modelsStub)\n    mock('../../lib/realtimeUpdateDirtyNoteJob', realtimeJobStub)\n    mock('../../lib/realtimeCleanDanglingUserJob', realtimeJobStub)\n    mock('../../lib/realtimeSaveRevisionJob', realtimeJobStub)\n  })\n\n  afterEach(() => {\n    mock.stopAll()\n    sinon.restore()\n  })\n\n  const Role = {\n    Guest: 'guest',\n    LoggedIn: 'LoggedIn',\n    Owner: 'Owner'\n  }\n\n  const Permission = {\n    Freely: 'freely',\n    Editable: 'editable',\n    Limited: 'limited',\n    Locked: 'locked',\n    Protected: 'protected',\n    Private: 'private'\n  }\n\n  const testcases = [\n    { role: Role.Guest, permission: Permission.Freely, canEdit: true },\n    { role: Role.LoggedIn, permission: Permission.Freely, canEdit: true },\n    { role: Role.Owner, permission: Permission.Freely, canEdit: true },\n    { role: Role.Guest, permission: Permission.Editable, canEdit: false },\n    { role: Role.LoggedIn, permission: Permission.Editable, canEdit: true },\n    { role: Role.Owner, permission: Permission.Editable, canEdit: true },\n    { role: Role.Guest, permission: Permission.Limited, canEdit: false },\n    { role: Role.LoggedIn, permission: Permission.Limited, canEdit: true },\n    { role: Role.Owner, permission: Permission.Limited, canEdit: true },\n    { role: Role.Guest, permission: Permission.Locked, canEdit: false },\n    { role: Role.LoggedIn, permission: Permission.Locked, canEdit: false },\n    { role: Role.Owner, permission: Permission.Locked, canEdit: true },\n    { role: Role.Guest, permission: Permission.Protected, canEdit: false },\n    { role: Role.LoggedIn, permission: Permission.Protected, canEdit: false },\n    { role: Role.Owner, permission: Permission.Protected, canEdit: true },\n    { role: Role.Guest, permission: Permission.Private, canEdit: false },\n    { role: Role.LoggedIn, permission: Permission.Private, canEdit: false },\n    { role: Role.Owner, permission: Permission.Private, canEdit: true }\n  ]\n\n  const noteOwnerId = 'owner'\n  const loggedInUserId = 'user1'\n  const noteId = 'noteId'\n\n  testcases.forEach((tc) => {\n    it(`${tc.role} ${tc.canEdit ? 'can' : 'can\\'t'} edit note with permission ${tc.permission}`, function () {\n      const client = makeMockSocket()\n      const note = {\n        permission: tc.permission,\n        owner: noteOwnerId\n      }\n      if (tc.role === Role.LoggedIn) {\n        client.request.user.logged_in = true\n        client.request.user.id = loggedInUserId\n      } else if (tc.role === Role.Owner) {\n        client.request.user.logged_in = true\n        client.request.user.id = noteOwnerId\n      }\n      client.noteId = noteId\n      const realtime = require('../../lib/realtime/realtime')\n      realtime.getNotePool()[noteId] = note\n      const callback = sinon.stub()\n      realtime.ifMayEdit(client, callback)\n      assert(callback.calledOnce)\n      assert(callback.lastCall.args[0] === tc.canEdit)\n    })\n  })\n\n  it('should set lsatchangeuser to null if guest edit operation', function () {\n    const note = {\n      permission: Permission.Freely\n    }\n    const client = makeMockSocket()\n    client.noteId = noteId\n    const callback = sinon.stub()\n    client.origin = 'operation'\n    const realtime = require('../../lib/realtime/realtime')\n    realtime.getNotePool()[noteId] = note\n    realtime.ifMayEdit(client, callback)\n    assert(callback.calledOnce)\n    assert(callback.lastCall.args[0])\n    assert(note.lastchangeuser === null)\n  })\n\n  it('should set lastchangeuser to logged_in user id if user edit', function () {\n    const note = {\n      permission: Permission.Freely\n    }\n    const client = makeMockSocket()\n    client.noteId = noteId\n    client.request.user.logged_in = true\n    client.request.user.id = loggedInUserId\n    const callback = sinon.stub()\n    client.origin = 'operation'\n    const realtime = require('../../lib/realtime/realtime')\n    realtime.getNotePool()[noteId] = note\n    realtime.ifMayEdit(client, callback)\n    assert(callback.calledOnce)\n    assert(callback.lastCall.args[0])\n    assert(note.lastchangeuser === loggedInUserId)\n  })\n})\n"
  },
  {
    "path": "test/realtime/parseNoteIdFromSocket.test.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst assert = require('assert')\nconst mock = require('mock-require')\n\nconst { makeMockSocket, removeModuleFromRequireCache } = require('./utils')\n\ndescribe('realtime#parseNoteIdFromSocketAsync', function () {\n  let realtime\n\n  beforeEach(() => {\n    mock('../../lib/logger', {})\n    mock('../../lib/history', {})\n    mock('../../lib/models', {\n      Note: {\n        parseNoteId: function (noteId, callback) {\n          callback(null, noteId)\n        }\n      }\n    })\n    mock('../../lib/config', {})\n  })\n\n  afterEach(() => {\n    removeModuleFromRequireCache('../../lib/realtime/realtime')\n    mock.stopAll()\n  })\n\n  it('should return null when socket not send noteId', async function () {\n    realtime = require('../../lib/realtime/realtime')\n    const mockSocket = makeMockSocket()\n    try {\n      const notes = await realtime.parseNoteIdFromSocketAsync(mockSocket)\n      assert(notes === null)\n    } catch (err) {\n      assert.fail('should not occur any error')\n    }\n  })\n\n  describe('noteId exists', function () {\n    beforeEach(() => {\n      mock('../../lib/models', {\n        Note: {\n          parseNoteId: function (noteId, callback) {\n            callback(null, noteId)\n          }\n        }\n      })\n    })\n    it('should return noteId when noteId exists', async function () {\n      realtime = require('../../lib/realtime/realtime')\n      const noteId = '123456'\n      const mockSocket = makeMockSocket(undefined, {\n        noteId: noteId\n      })\n      realtime = require('../../lib/realtime/realtime')\n      let parsedNoteId\n      try {\n        parsedNoteId = await realtime.parseNoteIdFromSocketAsync(mockSocket)\n      } catch (err) {\n        assert.fail(`should not occur any error ${err} `)\n      }\n      assert(parsedNoteId === noteId)\n    })\n  })\n\n  describe('noteId not exists', function () {\n    beforeEach(() => {\n      mock('../../lib/models', {\n        Note: {\n          parseNoteId: function (noteId, callback) {\n            callback(null, null)\n          }\n        }\n      })\n    })\n    it('should return null when noteId not exists', async function () {\n      realtime = require('../../lib/realtime/realtime')\n      const noteId = '123456'\n      const mockSocket = makeMockSocket(undefined, {\n        noteId: noteId\n      })\n      realtime = require('../../lib/realtime/realtime')\n      const parsedNoteId = await realtime.parseNoteIdFromSocketAsync(mockSocket)\n      assert(parsedNoteId === null)\n    })\n  })\n\n  describe('parse note error', function () {\n    beforeEach(() => {\n      mock('../../lib/models', {\n        Note: {\n          parseNoteId: function (noteId, callback) {\n            /* eslint-disable-next-line */\n            callback('error', null)\n          }\n        }\n      })\n    })\n    it('should return error when noteId parse error', async function () {\n      realtime = require('../../lib/realtime/realtime')\n      const noteId = '123456'\n      const mockSocket = makeMockSocket(undefined, {\n        noteId: noteId\n      })\n      realtime = require('../../lib/realtime/realtime')\n      try {\n        await realtime.parseNoteIdFromSocketAsync(mockSocket)\n      } catch (err) {\n        assert(err === 'error')\n      }\n    })\n  })\n})\n"
  },
  {
    "path": "test/realtime/realtime.test.js",
    "content": "'use strict'\n\n/* eslint-env node, mocha */\n\nconst mock = require('mock-require')\nconst assert = require('assert')\n\ndescribe('realtime', function () {\n  describe('checkViewPermission', function () {\n    // role -> guest, loggedInUser, loggedInOwner\n    const viewPermission = {\n      freely: [true, true, true],\n      editable: [true, true, true],\n      limited: [false, true, true],\n      locked: [true, true, true],\n      protected: [false, true, true],\n      private: [false, false, true]\n    }\n    const loggedInUserId = 'user1_id'\n    const ownerUserId = 'user2_id'\n    const guestReq = {}\n    const loggedInUserReq = {\n      user: {\n        id: loggedInUserId,\n        logged_in: true\n      }\n    }\n    const loggedInOwnerReq = {\n      user: {\n        id: ownerUserId,\n        logged_in: true\n      }\n    }\n\n    const note = {\n      owner: ownerUserId\n    }\n\n    let realtime\n\n    beforeEach(() => {\n      mock('../../lib/logger', {\n        error: () => {\n        }\n      })\n      mock('../../lib/history', {})\n      mock('../../lib/models', {\n        Note: {\n          parseNoteTitle: (data) => (data)\n        }\n      })\n      mock('../../lib/config', {})\n      realtime = require('../../lib/realtime/realtime')\n    })\n\n    Object.keys(viewPermission).forEach(function (permission) {\n      describe(permission, function () {\n        beforeEach(() => {\n          note.permission = permission\n        })\n        it('guest permission test', function () {\n          assert(realtime.checkViewPermission(guestReq, note) === viewPermission[permission][0])\n        })\n        it('loggedIn User permission test', function () {\n          assert(realtime.checkViewPermission(loggedInUserReq, note) === viewPermission[permission][1])\n        })\n        it('loggedIn Owner permission test', function () {\n          assert(realtime.checkViewPermission(loggedInOwnerReq, note) === viewPermission[permission][2])\n        })\n      })\n    })\n  })\n})\n"
  },
  {
    "path": "test/realtime/saveRevisionJob.test.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst assert = require('assert')\nconst mock = require('mock-require')\nconst sinon = require('sinon')\nconst { removeModuleFromRequireCache, removeLibModuleCache } = require('./utils')\n\ndescribe('save revision job', function () {\n  let clock\n  let mockModels\n  let realtime\n  beforeEach(() => {\n    removeLibModuleCache()\n    mockModels = {\n      Revision: {\n        saveAllNotesRevision: sinon.stub()\n      }\n    }\n    clock = sinon.useFakeTimers()\n    mock('../../lib/processQueue', require('../testDoubles/ProcessQueueFake'))\n    mock('../../lib/logger', {\n      error: () => {},\n      info: () => {}\n    })\n    mock('../../lib/history', {})\n    mock('../../lib/models', mockModels)\n    mock('../../lib/config', {\n      debug: true\n    })\n    mock('../../lib/realtimeUpdateDirtyNoteJob', require('../testDoubles/realtimeJobStub'))\n    mock('../../lib/realtimeCleanDanglingUserJob', require('../testDoubles/realtimeJobStub'))\n  })\n\n  afterEach(() => {\n    clock.restore()\n    removeModuleFromRequireCache('../../lib/realtime/realtime')\n    removeModuleFromRequireCache('../../lib/realtime/realtimeSaveRevisionJob')\n    mock.stopAll()\n    sinon.restore()\n  })\n\n  it('should execute save revision job every 5 min', (done) => {\n    mockModels.Revision.saveAllNotesRevision.callsFake((callback) => {\n      callback(null, [])\n    })\n    realtime = require('../../lib/realtime/realtime')\n    clock.tick(5 * 60 * 1000)\n    clock.restore()\n    setTimeout(() => {\n      assert(mockModels.Revision.saveAllNotesRevision.called)\n      assert(realtime.saveRevisionJob.getSaverSleep() === true)\n      done()\n    }, 50)\n  })\n\n  it('should not set saverSleep when more than 1 note save revision', (done) => {\n    mockModels.Revision.saveAllNotesRevision.callsFake((callback) => {\n      callback(null, [1])\n    })\n    realtime = require('../../lib/realtime/realtime')\n    clock.tick(5 * 60 * 1000)\n    clock.restore()\n    setTimeout(() => {\n      assert(mockModels.Revision.saveAllNotesRevision.called)\n      assert(realtime.saveRevisionJob.getSaverSleep() === false)\n      done()\n    }, 50)\n  })\n})\n"
  },
  {
    "path": "test/realtime/socket-events.test.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst assert = require('assert')\nconst mock = require('mock-require')\nconst sinon = require('sinon')\n\nconst { makeMockSocket, removeModuleFromRequireCache } = require('./utils')\n\ndescribe('realtime#socket event', function () {\n  const noteId = 'note123'\n  const note = {\n    id: noteId,\n    authors: [\n      {\n        userId: 'user1',\n        color: 'red',\n        user: {\n          id: 'user1',\n          name: 'Alice'\n        }\n      },\n      {\n        userId: 'user2',\n        color: 'blue',\n        user: {\n          id: 'user2',\n          name: 'Bob'\n        }\n      }\n    ]\n  }\n  let realtime\n  let clientSocket\n  let modelsMock\n  let eventFuncMap\n  let configMock\n  let clock\n\n  beforeEach(function (done) {\n    clock = sinon.useFakeTimers({\n      toFake: ['setInterval']\n    })\n    eventFuncMap = new Map()\n    modelsMock = {\n      Note: {\n        parseNoteTitle: (data) => (data),\n        destroy: sinon.stub().returns(Promise.resolve(1)),\n        update: sinon.stub().returns(Promise.resolve([1])),\n        findOne: sinon.stub().returns(Promise.resolve(note))\n      },\n      User: {}\n    }\n    modelsMock.User.getProfile = sinon.stub().callsFake((user) => {\n      return user\n    })\n    configMock = {\n      fullversion: '1.5.0',\n      minimumCompatibleVersion: '1.0.0',\n      permission: {\n        freely: 'freely',\n        editable: 'editable',\n        limited: 'limited',\n        locked: 'locked',\n        protected: 'protected',\n        private: 'private'\n      }\n    }\n    mock('../../lib/logger', {\n      error: () => {\n      },\n      info: () => {\n      }\n    })\n    mock('../../lib/history', {})\n    mock('../../lib/models', modelsMock)\n    mock('../../lib/config', configMock)\n    mock('../../lib/ot', require('../testDoubles/otFake'))\n    realtime = require('../../lib/realtime/realtime')\n\n    // get all socket event handler\n    clientSocket = makeMockSocket(null, {\n      noteId: noteId\n    })\n    clientSocket.request.user.logged_in = true\n    clientSocket.request.user.id = 'user1'\n    // clientSocket.noteId = noteId\n    clientSocket.on = function (event, func) {\n      eventFuncMap.set(event, func)\n    }\n    realtime.maintenance = false\n\n    realtime.io = (function () {\n      const roomMap = new Map()\n      return {\n        to: function (roomId) {\n          if (!roomMap.has(roomId)) {\n            roomMap.set(roomId, {\n              emit: sinon.stub()\n            })\n          }\n          return roomMap.get(roomId)\n        }\n      }\n    }())\n\n    const wrappedFuncs = []\n    wrappedFuncs.push(sinon.stub(realtime, 'updateUserData'))\n    wrappedFuncs.push(sinon.stub(realtime, 'emitOnlineUsers'))\n    wrappedFuncs.push(sinon.stub(realtime, 'parseNoteIdFromSocketAsync').returns(Promise.resolve(noteId)))\n    wrappedFuncs.push(sinon.stub(realtime, 'updateHistory'))\n    wrappedFuncs.push(sinon.stub(realtime, 'emitRefresh'))\n\n    realtime.connection(clientSocket)\n\n    setTimeout(() => {\n      wrappedFuncs.forEach((wrappedFunc) => {\n        wrappedFunc.restore()\n      })\n      done()\n    }, 50)\n  })\n\n  afterEach(function () {\n    removeModuleFromRequireCache('../../lib/realtime/realtime')\n    removeModuleFromRequireCache('../../lib/realtime/realtimeClientConnection')\n    mock.stopAll()\n    sinon.restore()\n    clock.restore()\n    clientSocket = null\n  })\n\n  describe('refresh', function () {\n    it('should call refresh', () => {\n      const refreshFunc = eventFuncMap.get('refresh')\n      const emitRefreshStub = sinon.stub(realtime, 'emitRefresh')\n      refreshFunc()\n      assert(emitRefreshStub.calledOnce)\n      assert.deepStrictEqual(emitRefreshStub.lastCall.args[0], clientSocket)\n    })\n  })\n\n  describe('user status', function () {\n    it('should call emitUserStatus and update user data', () => {\n      const userStatusFunc = eventFuncMap.get('user status')\n      const emitUserStatusStub = sinon.stub(realtime, 'emitUserStatus')\n      realtime.notes[noteId] = {}\n\n      const userData = {\n        idle: true,\n        type: 'xs'\n      }\n      userStatusFunc(userData)\n      assert(emitUserStatusStub.calledOnce)\n      assert.deepStrictEqual(emitUserStatusStub.lastCall.args[0], clientSocket)\n      assert(realtime.users[clientSocket.id].idle === true)\n      assert(realtime.users[clientSocket.id].type === 'xs')\n    })\n\n    it('should call emitUserStatus without userdata', () => {\n      const userStatusFunc = eventFuncMap.get('user status')\n      const emitUserStatusStub = sinon.stub(realtime, 'emitUserStatus')\n      realtime.notes[noteId] = {}\n      userStatusFunc()\n      assert(emitUserStatusStub.calledOnce)\n      assert.deepStrictEqual(emitUserStatusStub.lastCall.args[0], clientSocket)\n      assert(realtime.users[clientSocket.id].idle === false)\n      assert(realtime.users[clientSocket.id].type === null)\n    })\n\n    it('should not call emitUserStatus when user not exists', () => {\n      const userStatusFunc = eventFuncMap.get('user status')\n      const emitUserStatusStub = sinon.stub(realtime, 'emitUserStatus')\n      realtime.notes[noteId] = {}\n      delete realtime.users[clientSocket.id]\n      const userData = {\n        idle: true,\n        type: 'xs'\n      }\n      userStatusFunc(userData)\n      assert(emitUserStatusStub.called === false)\n    })\n\n    it('should not call emitUserStatus when note not exists', () => {\n      const userStatusFunc = eventFuncMap.get('user status')\n      const emitUserStatusStub = sinon.stub(realtime, 'emitUserStatus')\n      realtime.deleteAllNoteFromPool()\n      realtime.users[clientSocket.id] = {}\n      const userData = {\n        idle: true,\n        type: 'xs'\n      }\n      userStatusFunc(userData)\n      assert(emitUserStatusStub.called === false)\n    })\n  })\n\n  describe('disconnect', function () {\n    it('should push socket to disconnect queue and call disconnect function', () => {\n      const disconnectFunc = eventFuncMap.get('disconnect')\n      const queueForDisconnectStub = sinon.stub(realtime, 'queueForDisconnect')\n      disconnectFunc()\n      assert(queueForDisconnectStub.calledOnce)\n    })\n\n    it('should quick return when socket is in disconnect queue', () => {\n      const disconnectFunc = eventFuncMap.get('disconnect')\n      const queueForDisconnectStub = sinon.stub(realtime, 'queueForDisconnect')\n      realtime.disconnectProcessQueue.push(clientSocket.id, async () => {})\n      disconnectFunc()\n      assert(queueForDisconnectStub.called === false)\n    })\n  })\n\n  ;['cursor focus', 'cursor activity', 'cursor blur'].forEach((event) => {\n    describe(event, function () {\n      let cursorFocusFunc\n\n      const cursorData = {\n        cursor: 10\n      }\n\n      beforeEach(() => {\n        cursorFocusFunc = eventFuncMap.get(event)\n        realtime.notes[noteId] = {}\n      })\n\n      it('should broadcast to all client', () => {\n        cursorFocusFunc(cursorData)\n        const broadChannelEmitFake = clientSocket.broadcast.to(noteId).emit\n        assert(broadChannelEmitFake.calledOnce)\n        assert(broadChannelEmitFake.lastCall.args[0] === event)\n        if (event === 'cursor blur') {\n          assert(broadChannelEmitFake.lastCall.args[1].id === clientSocket.id)\n        } else {\n          assert.deepStrictEqual(broadChannelEmitFake.lastCall.args[1].cursor, cursorData)\n        }\n      })\n\n      it('should not broadcast when note not exists', () => {\n        delete realtime.notes[noteId]\n        cursorFocusFunc(cursorData)\n        const broadChannelEmitFake = clientSocket.broadcast.to(noteId).emit\n        assert(broadChannelEmitFake.called === false)\n      })\n\n      it('should not broadcast when user not exists', () => {\n        delete realtime.users[clientSocket.id]\n        cursorFocusFunc(cursorData)\n        const broadChannelEmitFake = clientSocket.broadcast.to(noteId).emit\n        assert(broadChannelEmitFake.called === false)\n      })\n    })\n  })\n\n  describe('version', function () {\n    it('should emit server version ', () => {\n      const versionFunc = eventFuncMap.get('version')\n      versionFunc()\n      assert(clientSocket.emit.called)\n      assert(clientSocket.emit.lastCall.args[0], 'version')\n      assert.deepStrictEqual(clientSocket.emit.lastCall.args[1], {\n        version: '1.5.0',\n        minimumCompatibleVersion: '1.0.0'\n      })\n    })\n  })\n\n  describe('online users', function () {\n    it('should return online user list', function () {\n      const onlineUsersFunc = eventFuncMap.get('online users')\n      realtime.notes[noteId] = {\n        users: {\n          10: {\n            id: 10\n          },\n          20: {\n            id: 20\n          }\n        }\n      }\n      onlineUsersFunc()\n      assert(clientSocket.emit.called)\n      assert(clientSocket.emit.lastCall.args[0] === 'online users')\n      const returnUserList = clientSocket.emit.lastCall.args[1].users\n      assert(returnUserList.length === 2)\n      assert(returnUserList[0].id === 10)\n      assert(returnUserList[1].id === 20)\n    })\n\n    it('should not return user list when note not exists', function () {\n      const onlineUsersFunc = eventFuncMap.get('online users')\n      realtime.deleteAllNoteFromPool()\n      onlineUsersFunc()\n      assert(clientSocket.emit.called === false)\n    })\n  })\n\n  describe('user changed', function () {\n    it('should call updateUserData', () => {\n      const userChangedFunc = eventFuncMap.get('user changed')\n      realtime.notes[noteId] = {\n        users: {\n          [clientSocket.id]: {}\n        }\n      }\n      const updateUserDataStub = sinon.stub(realtime, 'updateUserData')\n      const emitOnlineUsersStub = sinon.stub(realtime, 'emitOnlineUsers')\n      userChangedFunc()\n      assert(updateUserDataStub.calledOnce)\n      assert(emitOnlineUsersStub.calledOnce)\n    })\n\n    it('should direct return when note not exists', function () {\n      const userChangedFunc = eventFuncMap.get('user changed')\n      const updateUserDataStub = sinon.stub(realtime, 'updateUserData')\n      const emitOnlineUsersStub = sinon.stub(realtime, 'emitOnlineUsers')\n      realtime.deleteAllNoteFromPool()\n      userChangedFunc()\n      assert(updateUserDataStub.called === false)\n      assert(emitOnlineUsersStub.called === false)\n    })\n\n    it('should direct return when note\\'s users not exists', function () {\n      const userChangedFunc = eventFuncMap.get('user changed')\n      realtime.notes[noteId] = {\n        users: {}\n      }\n      delete realtime.users[clientSocket.id]\n      const updateUserDataStub = sinon.stub(realtime, 'updateUserData')\n      const emitOnlineUsersStub = sinon.stub(realtime, 'emitOnlineUsers')\n      userChangedFunc()\n      assert(updateUserDataStub.called === false)\n      assert(emitOnlineUsersStub.called === false)\n    })\n  })\n\n  describe('delete', function () {\n    it('should delete note when owner request', function (done) {\n      const currentUserId = 'user1_id'\n      const noteOwnerId = 'user1_id'\n      const otherClient = makeMockSocket()\n      clientSocket.request = {\n        user: {\n          logged_in: true,\n          id: currentUserId\n        }\n      }\n      realtime.notes[noteId] = {\n        owner: noteOwnerId,\n        socks: [clientSocket, undefined, otherClient]\n      }\n      const deleteFunc = eventFuncMap.get('delete')\n      deleteFunc()\n      setTimeout(() => {\n        assert(otherClient.disconnect.calledOnce)\n        assert(otherClient.emit.calledOnce)\n        assert(otherClient.emit.lastCall.args[0] === 'delete')\n        assert(clientSocket.disconnect.calledOnce)\n        assert(clientSocket.emit.calledOnce)\n        assert(clientSocket.emit.lastCall.args[0] === 'delete')\n        assert(modelsMock.Note.destroy.calledOnce)\n        done()\n      }, 10)\n    })\n\n    it('should not do anything when user not login', function (done) {\n      const noteOwnerId = 'user1_id'\n      clientSocket.request = {}\n      realtime.notes[noteId] = {\n        owner: noteOwnerId,\n        socks: [clientSocket]\n      }\n      const deleteFunc = eventFuncMap.get('delete')\n      deleteFunc()\n      setTimeout(() => {\n        assert(modelsMock.Note.destroy.called === false)\n        assert(clientSocket.disconnect.called === false)\n        done()\n      }, 10)\n    })\n\n    it('should not do anything when note not exists', function (done) {\n      const currentUserId = 'user1_id'\n      clientSocket.request = {\n        user: {\n          logged_in: true,\n          id: currentUserId\n        }\n      }\n      const deleteFunc = eventFuncMap.get('delete')\n      deleteFunc()\n      setTimeout(() => {\n        assert(modelsMock.Note.destroy.called === false)\n        assert(clientSocket.disconnect.called === false)\n        done()\n      }, 10)\n    })\n\n    it('should not do anything when note owner is not me', function (done) {\n      const currentUserId = 'user1_id'\n      const noteOwnerId = 'user2_id'\n      const otherClient = makeMockSocket()\n      clientSocket.request = {\n        user: {\n          logged_in: true,\n          id: currentUserId\n        }\n      }\n      realtime.notes[noteId] = {\n        owner: noteOwnerId,\n        socks: [clientSocket, otherClient]\n      }\n      const deleteFunc = eventFuncMap.get('delete')\n      deleteFunc()\n      setTimeout(() => {\n        assert(clientSocket.disconnect.called === false)\n        assert(modelsMock.Note.destroy.called === false)\n        done()\n      }, 10)\n    })\n\n    it('should not do anything when note destroy fail', function (done) {\n      const currentUserId = 'user1_id'\n      const noteOwnerId = 'user1_id'\n      modelsMock.Note.destroy.withArgs({\n        where: {\n          id: noteId\n        }\n      }).returns(Promise.resolve(0))\n\n      const otherClient = makeMockSocket()\n      clientSocket.request = {\n        user: {\n          logged_in: true,\n          id: currentUserId\n        }\n      }\n      realtime.notes[noteId] = {\n        id: noteId,\n        owner: noteOwnerId,\n        socks: [clientSocket, otherClient]\n      }\n      const deleteFunc = eventFuncMap.get('delete')\n      deleteFunc()\n      setTimeout(() => {\n        assert(modelsMock.Note.destroy.calledOnce)\n        assert(clientSocket.disconnect.called === false)\n        done()\n      }, 10)\n    })\n  })\n\n  describe('permission', function () {\n    const ownerId = 'user1_id'\n    const otherSignInUserId = 'user2_id'\n    let otherClient\n    let checkViewPermissionSpy\n    let permissionFunc\n\n    beforeEach(function () {\n      otherClient = makeMockSocket()\n      clientSocket.request = {\n        user: {\n          id: ownerId,\n          logged_in: true\n        }\n      }\n\n      otherClient.request = {\n        user: {\n          id: otherSignInUserId,\n          logged_in: true\n        }\n      }\n\n      realtime.deleteAllNoteFromPool()\n      realtime.addNote({\n        id: noteId,\n        owner: ownerId\n      })\n\n      checkViewPermissionSpy = sinon.spy(realtime, 'checkViewPermission')\n      permissionFunc = eventFuncMap.get('permission')\n    })\n\n    it('should disconnect when lose view permission', function (done) {\n      realtime.getNoteFromNotePool(noteId).permission = 'editable'\n      realtime.getNoteFromNotePool(noteId).socks = [clientSocket, undefined, otherClient]\n\n      permissionFunc('private')\n\n      setTimeout(() => {\n        // should change note permission to private\n        assert(modelsMock.Note.update.calledOnce)\n        assert(modelsMock.Note.update.lastCall.args[0].permission === 'private')\n        assert(modelsMock.Note.update.lastCall.args[1].where.id === noteId)\n        // should check all connected client\n        assert(checkViewPermissionSpy.callCount === 2)\n        assert(otherClient.emit.calledOnce)\n        assert(otherClient.disconnect.calledOnce)\n        done()\n      }, 5)\n    })\n\n    it('should not do anything when user not logged in', function (done) {\n      clientSocket.request = {}\n      permissionFunc('private')\n      setTimeout(() => {\n        assert(modelsMock.Note.update.called === false)\n        done()\n      }, 5)\n    })\n\n    it('should not do anything when note not exists', function (done) {\n      delete realtime.notes[noteId]\n      permissionFunc('private')\n      setTimeout(() => {\n        assert(modelsMock.Note.update.called === false)\n        done()\n      }, 5)\n    })\n\n    it('should not do anything when not note owner', function (done) {\n      clientSocket.request.user.id = 'other_user_id'\n      permissionFunc('private')\n      setTimeout(() => {\n        assert(modelsMock.Note.update.called === false)\n        done()\n      }, 5)\n    })\n\n    it('should change permission to freely when config allowAnonymous, allowAnonymousEdits and allowAnonymousViews are true', function (done) {\n      configMock.allowAnonymous = true\n      configMock.allowAnonymousEdits = true\n      configMock.allowAnonymousViews = true\n      realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]\n\n      permissionFunc('freely')\n\n      setTimeout(() => {\n        assert(checkViewPermissionSpy.callCount === 2)\n        assert(otherClient.emit.called === false)\n        assert(otherClient.disconnect.called === false)\n        assert(clientSocket.emit.called === false)\n        assert(clientSocket.disconnect.called === false)\n        done()\n      }, 5)\n    })\n\n    it('should not change permission to freely when config allowAnonymous, allowAnonymousEdits and allowAnonymousViews are false', function (done) {\n      configMock.allowAnonymous = false\n      configMock.allowAnonymousEdits = false\n      configMock.allowAnonymousViews = false\n      realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]\n\n      permissionFunc('freely')\n\n      setTimeout(() => {\n        assert(modelsMock.Note.update.called === false)\n        assert(checkViewPermissionSpy.called === false)\n        done()\n      }, 5)\n    })\n\n    it('should change permission to freely when config allowAnonymous is true', function (done) {\n      configMock.allowAnonymous = true\n      configMock.allowAnonymousEdits = false\n      configMock.allowAnonymousViews = false\n      realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]\n\n      permissionFunc('freely')\n\n      setTimeout(() => {\n        assert(checkViewPermissionSpy.callCount === 2)\n        assert(otherClient.emit.called === false)\n        assert(otherClient.disconnect.called === false)\n        assert(clientSocket.emit.called === false)\n        assert(clientSocket.disconnect.called === false)\n        done()\n      }, 5)\n    })\n\n    it('should not change permission to freely when config allowAnonymousEdits is true', function (done) {\n      configMock.allowAnonymous = false\n      configMock.allowAnonymousEdits = true\n      configMock.allowAnonymousViews = false\n      realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]\n\n      permissionFunc('freely')\n\n      setTimeout(() => {\n        assert(modelsMock.Note.update.called === false)\n        assert(checkViewPermissionSpy.called === false)\n        done()\n      }, 5)\n    })\n\n    it('should not change permission to freely when config allowAnonymousViews is true', function (done) {\n      configMock.allowAnonymous = false\n      configMock.allowAnonymousEdits = false\n      configMock.allowAnonymousViews = true\n      realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]\n\n      permissionFunc('freely')\n\n      setTimeout(() => {\n        assert(modelsMock.Note.update.called === false)\n        assert(checkViewPermissionSpy.called === false)\n        done()\n      }, 5)\n    })\n\n    it('should change permission to editable when config allowAnonymousViews is true', function (done) {\n      configMock.allowAnonymous = false\n      configMock.allowAnonymousEdits = false\n      configMock.allowAnonymousViews = true\n      realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]\n\n      permissionFunc('editable')\n\n      setTimeout(() => {\n        assert(checkViewPermissionSpy.callCount === 2)\n        assert(otherClient.emit.called === false)\n        assert(otherClient.disconnect.called === false)\n        assert(clientSocket.emit.called === false)\n        assert(clientSocket.disconnect.called === false)\n        done()\n      }, 5)\n    })\n\n    it('should change permission to freely when config allowAnonymousEdits and allowAnonymousViews are false true', function (done) {\n      configMock.allowAnonymous = false\n      configMock.allowAnonymousEdits = true\n      configMock.allowAnonymousViews = true\n      realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]\n\n      permissionFunc('freely')\n\n      setTimeout(() => {\n        assert(checkViewPermissionSpy.callCount === 2)\n        assert(otherClient.emit.called === false)\n        assert(otherClient.disconnect.called === false)\n        assert(clientSocket.emit.called === false)\n        assert(clientSocket.disconnect.called === false)\n        done()\n      }, 5)\n    })\n\n    it('should change permission to editable when config allowAnonymousEdits and allowAnonymousViews are false true', function (done) {\n      configMock.allowAnonymous = false\n      configMock.allowAnonymousEdits = true\n      configMock.allowAnonymousViews = true\n      realtime.notes[noteId].socks = [clientSocket, undefined, otherClient]\n\n      permissionFunc('editable')\n\n      setTimeout(() => {\n        assert(checkViewPermissionSpy.callCount === 2)\n        assert(otherClient.emit.called === false)\n        assert(otherClient.disconnect.called === false)\n        assert(clientSocket.emit.called === false)\n        assert(clientSocket.disconnect.called === false)\n        done()\n      }, 5)\n    })\n  })\n})\n"
  },
  {
    "path": "test/realtime/updateNote.test.js",
    "content": "/* eslint-env node, mocha */\n'use strict'\n\nconst assert = require('assert')\nconst mock = require('mock-require')\nconst sinon = require('sinon')\n\nconst { removeLibModuleCache } = require('./utils')\nconst { createFakeLogger } = require('../testDoubles/loggerFake')\nconst realtimeJobStub = require('../testDoubles/realtimeJobStub')\n\ndescribe('realtime#updateNote', function () {\n  let modelsStub\n  let realtime\n  const now = 1546300800000\n  let clock\n\n  beforeEach(() => {\n    removeLibModuleCache()\n    clock = sinon.useFakeTimers({\n      now,\n      toFake: ['Date']\n    })\n    modelsStub = {\n      Note: {\n        findOne: sinon.stub()\n      },\n      User: {\n        findOne: sinon.stub()\n      }\n    }\n\n    mock('../../lib/config', {})\n    mock('../../lib/logger', createFakeLogger())\n    mock('../../lib/models', modelsStub)\n    mock('../../lib/realtimeUpdateDirtyNoteJob', realtimeJobStub)\n    mock('../../lib/realtimeCleanDanglingUserJob', realtimeJobStub)\n    // mock('../../lib/realtimeSaveRevisionJob', realtimeJobStub)\n  })\n\n  afterEach(() => {\n    mock.stopAll()\n    clock.restore()\n    sinon.restore()\n    removeLibModuleCache()\n  })\n\n  it('should save history to each edited user', function (done) {\n    modelsStub.Note.findOne.returns(Promise.resolve({}))\n    realtime = require('../../lib/realtime/realtime')\n    const updateHistoryStub = sinon.stub(realtime, 'updateHistory')\n\n    const callback = sinon.stub()\n    const note = {\n      tempUsers: {\n        user1: Date.now()\n      }\n    }\n    realtime.updateNote(note, callback)\n    clock.restore()\n    setTimeout(() => {\n      assert(updateHistoryStub.calledOnce)\n      assert(updateHistoryStub.lastCall.calledWith('user1', note, now))\n      done()\n    }, 50)\n  })\n\n  it('should set lastchangeprofile when lastchangeuser is set', function (done) {\n    const callback = sinon.stub()\n\n    const note = {\n      lastchangeuser: 'user1'\n    }\n\n    modelsStub.Note.findOne.returns(Promise.resolve({}))\n\n    modelsStub.User.findOne.withArgs({\n      where: {\n        id: 'user1'\n      }\n    }).returns(Promise.resolve({\n      id: 'user1',\n      profile: '{ \"displayName\": \"User 01\" }'\n    }))\n    modelsStub.User.getProfile = sinon.stub().returns({\n      name: 'User 01'\n    })\n\n    realtime = require('../../lib/realtime/realtime')\n\n    realtime.updateNote(note, callback)\n    clock.restore()\n    setTimeout(() => {\n      assert(note.lastchangeuserprofile.name === 'User 01')\n      done()\n    }, 50)\n  })\n\n  it('should save note with new data', function (done) {\n    const callback = sinon.stub()\n    const note = {\n      lastchangeuser: 'user1',\n      server: {\n        document: '# title\\n\\n## test2'\n      },\n      authorship: []\n    }\n\n    modelsStub.Note.parseNoteTitle = sinon.stub().returns('title')\n    const updateNoteStub = sinon.stub().returns(Promise.resolve({}))\n    modelsStub.Note.findOne.returns(Promise.resolve({\n      update: updateNoteStub\n    }))\n\n    modelsStub.User.findOne.withArgs({\n      where: {\n        id: 'user1'\n      }\n    }).returns(Promise.resolve({\n      id: 'user1',\n      profile: '{ \"displayName\": \"User 01\" }'\n    }))\n    modelsStub.User.getProfile = sinon.stub().returns({\n      name: 'User 01'\n    })\n    clock.tick(1000)\n\n    realtime = require('../../lib/realtime/realtime')\n    realtime.updateNote(note, callback)\n    setTimeout(() => {\n      assert(note.lastchangeuserprofile.name === 'User 01')\n      assert(callback.calledOnce)\n      assert(callback.lastCall.args[0] === null)\n      assert(updateNoteStub.calledOnce)\n      assert(updateNoteStub.lastCall.args[0].lastchangeAt === now + 1000)\n      assert(updateNoteStub.lastCall.args[0].title === 'title')\n      assert(updateNoteStub.lastCall.args[0].content === '# title\\n\\n## test2')\n      done()\n    }, 50)\n  })\n\n  it('should save note when lsatChangeUser is guest', function (done) {\n    const callback = sinon.stub()\n    const note = {\n      server: {\n        document: '# title\\n\\n## test2'\n      },\n      authorship: []\n    }\n\n    modelsStub.Note.parseNoteTitle = sinon.stub().returns('title')\n    const updateNoteStub = sinon.stub().returns(Promise.resolve({}))\n    modelsStub.Note.findOne.returns(Promise.resolve({\n      update: updateNoteStub\n    }))\n\n    modelsStub.User.getProfile = sinon.stub().returns({\n      name: 'User 01'\n    })\n    clock.tick(1000)\n\n    realtime = require('../../lib/realtime/realtime')\n    realtime.updateNote(note, callback)\n    setTimeout(() => {\n      assert(modelsStub.User.findOne.callCount === 0)\n      assert(note.lastchangeuserprofile === null)\n      assert(callback.calledOnce)\n      assert(callback.lastCall.args[0] === null)\n      assert(updateNoteStub.calledOnce)\n      assert(updateNoteStub.lastCall.args[0].lastchangeAt === now + 1000)\n      assert(updateNoteStub.lastCall.args[0].title === 'title')\n      assert(updateNoteStub.lastCall.args[0].content === '# title\\n\\n## test2')\n      done()\n    }, 50)\n  })\n\n  it('should save note when lastChangeUser as same as database', function (done) {\n    const callback = sinon.stub()\n    const note = {\n      lastchangeuser: 'user1',\n      server: {\n        document: '# title\\n\\n## test2'\n      },\n      authorship: []\n    }\n\n    modelsStub.Note.parseNoteTitle = sinon.stub().returns('title')\n    const updateNoteStub = sinon.stub().returns(Promise.resolve({}))\n    modelsStub.Note.findOne.returns(Promise.resolve({\n      update: updateNoteStub,\n      lastchangeuserId: 'user1'\n    }))\n\n    modelsStub.User.getProfile = sinon.stub().returns({\n      name: 'User 01'\n    })\n    clock.tick(1000)\n\n    realtime = require('../../lib/realtime/realtime')\n    realtime.updateNote(note, callback)\n    setTimeout(() => {\n      assert(modelsStub.User.findOne.callCount === 0)\n      assert(modelsStub.User.getProfile.callCount === 0)\n      assert(callback.calledOnce)\n      assert(callback.lastCall.args[0] === null)\n      assert(updateNoteStub.calledOnce)\n      assert(updateNoteStub.lastCall.args[0].lastchangeAt === now + 1000)\n      assert(updateNoteStub.lastCall.args[0].lastchangeuserId === 'user1')\n      assert(updateNoteStub.lastCall.args[0].title === 'title')\n      assert(updateNoteStub.lastCall.args[0].content === '# title\\n\\n## test2')\n      done()\n    }, 50)\n  })\n\n  it('should not save note when lastChangeUser not found in database', function (done) {\n    const callback = sinon.stub()\n    const note = {\n      lastchangeuser: 'user1',\n      server: {\n        document: '# title\\n\\n## test2'\n      },\n      authorship: []\n    }\n\n    modelsStub.Note.parseNoteTitle = sinon.stub().returns('title')\n    const updateNoteStub = sinon.stub().returns(Promise.resolve({}))\n    modelsStub.Note.findOne.returns(Promise.resolve({\n      update: updateNoteStub\n    }))\n    modelsStub.User.findOne.returns(Promise.resolve(null))\n    modelsStub.User.getProfile = sinon.stub().returns({\n      name: 'User 01'\n    })\n    clock.tick(1000)\n\n    realtime = require('../../lib/realtime/realtime')\n    realtime.updateNote(note, callback)\n    setTimeout(() => {\n      assert(modelsStub.User.findOne.called)\n      assert(modelsStub.User.getProfile.callCount === 0)\n      assert(callback.calledOnce)\n      assert(callback.lastCall.args[0] === null)\n      assert(callback.lastCall.args[1] === null)\n      assert(updateNoteStub.callCount === 0)\n      done()\n    }, 50)\n  })\n\n  it('should not save note when note.server not exists', function (done) {\n    const callback = sinon.stub()\n    const note = {\n      lastchangeuser: 'user1',\n      authorship: []\n    }\n\n    modelsStub.Note.parseNoteTitle = sinon.stub().returns('title')\n    const updateNoteStub = sinon.stub().returns(Promise.resolve({}))\n    modelsStub.Note.findOne.returns(Promise.resolve({\n      update: updateNoteStub\n    }))\n\n    modelsStub.User.findOne.withArgs({\n      where: {\n        id: 'user1'\n      }\n    }).returns(Promise.resolve({\n      id: 'user1',\n      profile: '{ \"displayName\": \"User 01\" }'\n    }))\n    modelsStub.User.getProfile = sinon.stub().returns({\n      name: 'User 01'\n    })\n    clock.tick(1000)\n\n    realtime = require('../../lib/realtime/realtime')\n    realtime.updateNote(note, callback)\n    setTimeout(() => {\n      assert(note.lastchangeuserprofile.name === 'User 01')\n      assert(callback.calledOnce)\n      assert(callback.lastCall.args[0] === null)\n      assert(callback.lastCall.args[1] === null)\n      assert(updateNoteStub.callCount === 0)\n      done()\n    }, 50)\n  })\n})\n"
  },
  {
    "path": "test/realtime/utils.js",
    "content": "'use strict'\n\nconst sinon = require('sinon')\nconst path = require('path')\n\nfunction makeMockSocket (headers, query) {\n  const broadCastChannelCache = {}\n  return {\n    id: Math.round(Math.random() * 10000),\n    request: {\n      user: {}\n    },\n    handshake: {\n      headers: Object.assign({}, headers),\n      query: Object.assign({}, query)\n    },\n    on: sinon.fake(),\n    emit: sinon.fake(),\n    broadCastChannelCache: {},\n    broadcast: {\n      to: (channel) => {\n        if (!broadCastChannelCache[channel]) {\n          broadCastChannelCache[channel] = {\n            channel: channel,\n            emit: sinon.fake()\n          }\n        }\n        return broadCastChannelCache[channel]\n      }\n    },\n    disconnect: sinon.fake(),\n    rooms: []\n  }\n}\n\nfunction removeModuleFromRequireCache (modulePath) {\n  delete require.cache[require.resolve(modulePath)]\n}\nfunction removeLibModuleCache () {\n  const libPath = path.resolve(path.join(__dirname, '../../lib'))\n  Object.keys(require.cache).forEach(key => {\n    if (key.startsWith(libPath)) {\n      delete require.cache[require.resolve(key)]\n    }\n  })\n}\n\nexports.makeMockSocket = makeMockSocket\nexports.removeModuleFromRequireCache = removeModuleFromRequireCache\nexports.removeLibModuleCache = removeLibModuleCache\n"
  },
  {
    "path": "test/testDoubles/ProcessQueueFake.js",
    "content": "'use strict'\n\nclass ProcessQueueFake {\n  constructor () {\n    this.taskMap = new Map()\n    this.queue = []\n  }\n\n  start () {\n\n  }\n\n  stop () {\n\n  }\n\n  checkTaskIsInQueue (id) {\n    return this.taskMap.has(id)\n  }\n\n  push (id, processFunc) {\n    this.queue.push({\n      id: id,\n      processFunc: processFunc\n    })\n    this.taskMap.set(id, true)\n  }\n\n  process () {\n\n  }\n}\n\nexports.ProcessQueueFake = ProcessQueueFake\nexports.ProcessQueue = ProcessQueueFake\n"
  },
  {
    "path": "test/testDoubles/loggerFake.js",
    "content": "'use strict'\n\nconst sinon = require('sinon')\n\nfunction createFakeLogger () {\n  return {\n    error: sinon.stub(),\n    warn: sinon.stub(),\n    info: sinon.stub(),\n    debug: sinon.stub(),\n    log: sinon.stub()\n  }\n}\n\nexports.createFakeLogger = createFakeLogger\n"
  },
  {
    "path": "test/testDoubles/otFake.js",
    "content": "'use strict'\n\nconst sinon = require('sinon')\n\nclass EditorSocketIOServerFake {\n  constructor () {\n    this.addClient = sinon.stub()\n    this.onOperation = sinon.stub()\n    this.onGetOperations = sinon.stub()\n    this.updateSelection = sinon.stub()\n    this.setName = sinon.stub()\n    this.setColor = sinon.stub()\n    this.getClient = sinon.stub()\n    this.onDisconnect = sinon.stub()\n  }\n}\n\nexports.EditorSocketIOServer = EditorSocketIOServerFake\n"
  },
  {
    "path": "test/testDoubles/realtimeJobStub.js",
    "content": "'use strict'\n\nclass realtimeJobStub {\n  start () {\n  }\n\n  stop () {\n  }\n}\n\nexports.realtimeJobStub = realtimeJobStub\nexports.UpdateDirtyNoteJob = realtimeJobStub\nexports.CleanDanglingUserJob = realtimeJobStub\nexports.SaveRevisionJob = realtimeJobStub\n"
  },
  {
    "path": "utils/string.js",
    "content": "'use strict'\n\nfunction stripTags (s) {\n  return s.replace(RegExp('</?[^<>]*>', 'gi'), '')\n}\n\nexports.stripTags = stripTags\n"
  },
  {
    "path": "webpack.common.js",
    "content": "const webpack = require('webpack')\nconst path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst CopyWebpackPlugin = require('copy-webpack-plugin')\nconst MiniCssExtractPlugin = require('mini-css-extract-plugin')\n\n// Fix possible nofile-issues\nconst fs = require('fs')\nconst gracefulFs = require('graceful-fs')\ngracefulFs.gracefulify(fs)\n\nmodule.exports = {\n  name: 'app',\n  plugins: [\n    new webpack.ProvidePlugin({\n      Visibility: 'visibilityjs',\n      Cookies: 'js-cookie',\n      key: 'keymaster',\n      $: 'jquery',\n      jQuery: 'jquery',\n      'window.jQuery': 'jquery',\n      'moment': 'moment',\n      'Handlebars': 'handlebars'\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/header.ejs',\n      chunks: ['font', 'index-styles', 'index'],\n      filename: path.join(__dirname, 'public/views/build/index-header.ejs'),\n      inject: false,\n      chunksSortMode: 'manual'\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/header.ejs',\n      chunks: ['index-styles-pack', 'index-styles', 'index'],\n      filename: path.join(__dirname, 'public/views/build/index-pack-header.ejs'),\n      inject: false,\n      chunksSortMode: 'manual'\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/scripts.ejs',\n      chunks: ['index'],\n      filename: path.join(__dirname, 'public/views/build/index-scripts.ejs'),\n      inject: false\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/scripts.ejs',\n      chunks: ['common', 'index-pack'],\n      filename: path.join(__dirname, 'public/views/build/index-pack-scripts.ejs'),\n      inject: false,\n      chunksSortMode: 'manual'\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/header.ejs',\n      chunks: ['font', 'cover'],\n      filename: path.join(__dirname, 'public/views/build/cover-header.ejs'),\n      inject: false,\n      chunksSortMode: 'manual'\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/header.ejs',\n      chunks: ['cover-styles-pack', 'cover'],\n      filename: path.join(__dirname, 'public/views/build/cover-pack-header.ejs'),\n      inject: false,\n      chunksSortMode: 'manual'\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/scripts.ejs',\n      chunks: ['cover'],\n      filename: path.join(__dirname, 'public/views/build/cover-scripts.ejs'),\n      inject: false\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/scripts.ejs',\n      chunks: ['common', 'cover-pack'],\n      filename: path.join(__dirname, 'public/views/build/cover-pack-scripts.ejs'),\n      inject: false,\n      chunksSortMode: 'manual'\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/header.ejs',\n      chunks: ['font', 'pretty-styles', 'pretty'],\n      filename: path.join(__dirname, 'public/views/build/pretty-header.ejs'),\n      inject: false,\n      chunksSortMode: 'manual'\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/header.ejs',\n      chunks: ['pretty-styles-pack', 'pretty-styles', 'pretty'],\n      filename: path.join(__dirname, 'public/views/build/pretty-pack-header.ejs'),\n      inject: false,\n      chunksSortMode: 'manual'\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/scripts.ejs',\n      chunks: ['pretty'],\n      filename: path.join(__dirname, 'public/views/build/pretty-scripts.ejs'),\n      inject: false\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/scripts.ejs',\n      chunks: ['common', 'pretty-pack'],\n      filename: path.join(__dirname, 'public/views/build/pretty-pack-scripts.ejs'),\n      inject: false,\n      chunksSortMode: 'manual'\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/header.ejs',\n      chunks: ['font', 'slide-styles', 'slide'],\n      filename: path.join(__dirname, 'public/views/build/slide-header.ejs'),\n      inject: false,\n      chunksSortMode: 'manual'\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/header.ejs',\n      chunks: ['slide-styles-pack', 'slide-styles', 'slide'],\n      filename: path.join(__dirname, 'public/views/build/slide-pack-header.ejs'),\n      inject: false,\n      chunksSortMode: 'manual'\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/scripts.ejs',\n      chunks: ['slide'],\n      filename: path.join(__dirname, 'public/views/build/slide-scripts.ejs'),\n      inject: false\n    }),\n    new HtmlWebpackPlugin({\n      template: 'public/views/includes/scripts.ejs',\n      chunks: ['slide-pack'],\n      filename: path.join(__dirname, 'public/views/build/slide-pack-scripts.ejs'),\n      inject: false\n    }),\n    new CopyWebpackPlugin([\n      {\n        context: path.join(__dirname, 'node_modules/mathjax'),\n        from: {\n          glob: '**/*',\n          dot: false\n        },\n        to: 'MathJax/'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/@hackmd/emojify.js'),\n        from: {\n          glob: 'dist/**/*',\n          dot: false\n        },\n        to: 'emojify.js/'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/reveal.js'),\n        from: 'js',\n        to: 'reveal.js/js'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/reveal.js'),\n        from: 'css',\n        to: 'reveal.js/css'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/reveal.js'),\n        from: 'lib',\n        to: 'reveal.js/lib'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/reveal.js'),\n        from: 'plugin',\n        to: 'reveal.js/plugin'\n      },\n      {\n        context: path.join(__dirname, 'public/js'),\n        from: 'revealjs-plugins',\n        to: 'revealjs-plugins'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/dictionary-de'),\n        from: '*',\n        to: 'dictionary-de/'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/dictionary-de-at'),\n        from: '*',\n        to: 'dictionary-de-at/'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/dictionary-de-ch'),\n        from: '*',\n        to: 'dictionary-de-ch/'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/dictionary-en-gb'),\n        from: '*',\n        to: 'dictionary-en-gb/'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/leaflet'),\n        from: 'dist',\n        to: 'leaflet'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/fork-awesome'),\n        from: 'fonts',\n        to: 'fork-awesome/fonts'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/fork-awesome'),\n        from: 'css',\n        to: 'fork-awesome/css'\n      },\n      {\n        context: path.join(__dirname, 'node_modules/mermaid'),\n        from: 'dist/mermaid.min.js',\n        to: 'mermaid/mermaid.min.js'\n      }\n    ]),\n    new MiniCssExtractPlugin(\n      process.env.NODE_ENV === 'production'\n      ? {\n          filename: '[name].[contenthash].css',\n          chunkFilename: '[name].[contenthash].css',\n        }\n      : {},\n    )\n  ],\n\n  entry: {\n    font: path.join(__dirname, 'public/css/google-font.css'),\n    common: [\n      'expose-loader?jQuery!expose-loader?$!jquery',\n      'velocity-animate',\n      'imports-loader?$=jquery!jquery-mousewheel',\n      'bootstrap'\n    ],\n    cover: [\n      'core-js/stable',\n      'regenerator-runtime/runtime',\n      path.join(__dirname, 'public/js/cover.js')\n    ],\n    'cover-styles-pack': [\n      path.join(__dirname, 'node_modules/bootstrap/dist/css/bootstrap.min.css'),\n      path.join(__dirname, 'public/css/bootstrap-social.css'),\n      path.join(__dirname, 'node_modules/select2/select2.css'),\n      path.join(__dirname, 'node_modules/select2/select2-bootstrap.css')\n    ],\n    'cover-pack': [\n      'core-js/stable',\n      'regenerator-runtime/runtime',\n      'bootstrap-validator',\n      'expose-loader?select2!select2',\n      'expose-loader?moment!moment',\n      path.join(__dirname, 'public/js/cover.js')\n    ],\n    index: [\n      'core-js/stable',\n      'regenerator-runtime/runtime',\n      'script-loader!jquery-ui-resizable',\n      'script-loader!codemirror',\n      'script-loader!inlineAttachment',\n      'script-loader!jqueryTextcomplete',\n      'script-loader!codemirrorInlineAttachment',\n      'script-loader!ot',\n      'flowchart.js',\n      'imports-loader?Raphael=raphael!js-sequence-diagrams',\n      path.join(__dirname, 'public/js/index.js')\n    ],\n    'index-styles': [\n      path.join(__dirname, 'public/vendor/jquery-ui/jquery-ui.min.css'),\n      path.join(__dirname, 'public/vendor/codemirror-spell-checker/spell-checker.min.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/lib/codemirror.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/addon/fold/foldgutter.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/addon/display/fullscreen.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/addon/dialog/dialog.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/addon/scroll/simplescrollbars.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/addon/search/matchesonscrollbar.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/monokai.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/one-dark.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/dracula.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/material.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/nord.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/panda-syntax.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/solarized.css'),\n      path.join(__dirname, 'public/css/codemirror-extend/ayu-dark.css'),\n      path.join(__dirname, 'public/css/codemirror-extend/ayu-mirage.css'),\n      path.join(__dirname, 'public/css/codemirror-extend/tomorrow-night-bright.css'),\n      path.join(__dirname, 'public/css/codemirror-extend/tomorrow-night-eighties.css'),\n      path.join(__dirname, 'public/css/codemirror-extend/one-dark.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/mode/tiddlywiki/tiddlywiki.css'),\n      path.join(__dirname, 'node_modules/@hackmd/codemirror/mode/mediawiki/mediawiki.css'),\n      path.join(__dirname, 'public/css/github-extract.css'),\n      path.join(__dirname, 'public/vendor/showup/showup.css'),\n      path.join(__dirname, 'public/css/mermaid.css'),\n      path.join(__dirname, 'public/css/markdown.css'),\n      path.join(__dirname, 'public/css/slide-preview.css')\n    ],\n    'index-styles-pack': [\n      path.join(__dirname, 'node_modules/bootstrap/dist/css/bootstrap.min.css'),\n      path.join(__dirname, 'public/css/bootstrap-social.css'),\n      path.join(__dirname, 'node_modules/ionicons/css/ionicons.min.css'),\n      path.join(__dirname, 'node_modules/leaflet/dist/leaflet.css')\n    ],\n    'index-pack': [\n      'core-js/stable',\n      'regenerator-runtime/runtime',\n      'script-loader!jquery-ui-resizable',\n      'bootstrap-validator',\n      'expose-loader?jsyaml!js-yaml',\n      'expose-loader?moment!moment',\n      'script-loader!handlebars',\n      'expose-loader?hljs!highlight.js',\n      'emojify.js',\n      'script-loader!gist-embed',\n      'script-loader!codemirror',\n      'script-loader!inlineAttachment',\n      'script-loader!jqueryTextcomplete',\n      'script-loader!codemirrorInlineAttachment',\n      'script-loader!ot',\n      'flowchart.js',\n      'imports-loader?Raphael=raphael!js-sequence-diagrams',\n      'script-loader!viz.js',\n      'script-loader!viz.render.js',\n      'script-loader!abcjs',\n      'script-loader!vega',\n      'script-loader!vega-lite',\n      'script-loader!vega-embed',\n      'expose-loader?io!socket.io-client',\n      'expose-loader?L!leaflet',\n      path.join(__dirname, 'public/js/index.js')\n    ],\n    pretty: [\n      'core-js/stable',\n      'regenerator-runtime/runtime',\n      'flowchart.js',\n      'imports-loader?Raphael=raphael!js-sequence-diagrams',\n      path.join(__dirname, 'public/js/pretty.js')\n    ],\n    'pretty-styles': [\n      path.join(__dirname, 'public/css/github-extract.css'),\n      path.join(__dirname, 'public/css/mermaid.css'),\n      path.join(__dirname, 'public/css/markdown.css'),\n      path.join(__dirname, 'public/css/slide-preview.css')\n    ],\n    'pretty-styles-pack': [\n      path.join(__dirname, 'node_modules/bootstrap/dist/css/bootstrap.min.css'),\n      path.join(__dirname, 'node_modules/ionicons/css/ionicons.min.css'),\n      path.join(__dirname, 'node_modules/leaflet/dist/leaflet.css')\n    ],\n    'pretty-pack': [\n      'core-js/stable',\n      'regenerator-runtime/runtime',\n      'expose-loader?jsyaml!js-yaml',\n      'expose-loader?moment!moment',\n      'script-loader!handlebars',\n      'expose-loader?hljs!highlight.js',\n      'emojify.js',\n      'script-loader!gist-embed',\n      'flowchart.js',\n      'imports-loader?Raphael=raphael!js-sequence-diagrams',\n      'script-loader!viz.js',\n      'script-loader!viz.render.js',\n      'script-loader!abcjs',\n      'script-loader!vega',\n      'script-loader!vega-lite',\n      'script-loader!vega-embed',\n      'expose-loader?L!leaflet',\n      path.join(__dirname, 'public/js/pretty.js')\n    ],\n    slide: [\n      'core-js/stable',\n      'regenerator-runtime/runtime',\n      'bootstrap-tooltip',\n      'flowchart.js',\n      'imports-loader?Raphael=raphael!js-sequence-diagrams',\n      path.join(__dirname, 'public/js/slide.js')\n    ],\n    'slide-styles': [\n      path.join(__dirname, 'public/vendor/bootstrap/tooltip.min.css'),\n      path.join(__dirname, 'public/css/github-extract.css'),\n      path.join(__dirname, 'public/css/mermaid.css'),\n      path.join(__dirname, 'public/css/markdown.css')\n    ],\n    'slide-styles-pack': [\n      path.join(__dirname, 'node_modules/ionicons/css/ionicons.min.css'),\n      path.join(__dirname, 'node_modules/leaflet/dist/leaflet.css')\n    ],\n    'slide-pack': [\n      'core-js/stable',\n      'regenerator-runtime/runtime',\n      'expose-loader?jQuery!expose-loader?$!jquery',\n      'velocity-animate',\n      'imports-loader?$=jquery!jquery-mousewheel',\n      'bootstrap-tooltip',\n      'expose-loader?jsyaml!js-yaml',\n      'expose-loader?moment!moment',\n      'script-loader!handlebars',\n      'expose-loader?hljs!highlight.js',\n      'emojify.js',\n      'script-loader!gist-embed',\n      'flowchart.js',\n      'imports-loader?Raphael=raphael!js-sequence-diagrams',\n      'script-loader!viz.js',\n      'script-loader!viz.render.js',\n      'script-loader!abcjs',\n      'script-loader!vega',\n      'script-loader!vega-lite',\n      'script-loader!vega-embed',\n      'expose-loader?Reveal!reveal.js',\n      'expose-loader?L!leaflet',\n      path.join(__dirname, 'public/js/slide.js')\n    ]\n  },\n\n  output: {\n    path: path.join(__dirname, 'public/build'),\n    publicPath: '/build/',\n    filename: '[name].js'\n  },\n\n  resolve: {\n    modules: ['node_modules'],\n    extensions: ['.js', '.mjs'],\n    alias: {\n      codemirror: path.join(__dirname, 'node_modules/@hackmd/codemirror/codemirror.min.js'),\n      inlineAttachment: path.join(__dirname, 'public/vendor/inlineAttachment/inline-attachment.js'),\n      jqueryTextcomplete: path.join(__dirname, 'public/vendor/jquery-textcomplete/jquery.textcomplete.js'),\n      codemirrorInlineAttachment: path.join(__dirname, 'public/vendor/inlineAttachment/codemirror.inline-attachment.js'),\n      ot: path.join(__dirname, 'public/vendor/ot/ot.min.js'),\n      handlebars: path.join(__dirname, 'node_modules/handlebars/dist/handlebars.min.js'),\n      'jquery-ui-resizable': path.join(__dirname, 'public/vendor/jquery-ui/jquery-ui.min.js'),\n      'gist-embed': path.join(__dirname, 'node_modules/gist-embed/gist-embed.min.js'),\n      'bootstrap-tooltip': path.join(__dirname, 'public/vendor/bootstrap/tooltip.min.js'),\n      'reveal-markdown': path.join(__dirname, 'public/js/reveal-markdown.js'),\n      abcjs: path.join(__dirname, 'public/vendor/abcjs_basic_3.1.1-min.js'),\n      raphael: path.join(__dirname, 'node_modules/raphael/raphael.min.js'),\n      'js-sequence-diagrams': path.join(__dirname, 'node_modules/@hackmd/js-sequence-diagrams/build/main.js'),\n      vega: path.join(__dirname, 'node_modules/vega/build/vega.min.js'),\n      'vega-lite': path.join(__dirname, 'node_modules/vega-lite/build/vega-lite.min.js'),\n      'vega-embed': path.join(__dirname, 'node_modules/vega-embed/build/vega-embed.min.js'),\n      'emojify.js': path.join(__dirname, 'node_modules/@hackmd/emojify.js/dist/js/emojify-browser.min.js'),\n      'markdown-it': path.join(__dirname, 'node_modules/markdown-it/dist/markdown-it.js'),\n      'viz.js': path.join(__dirname, 'node_modules/viz.js/viz.js'),\n      'viz.render.js': path.join(__dirname, 'node_modules/viz.js/full.render.js'),\n      markdownlint: path.join(__dirname, 'node_modules/markdownlint/demo/markdownlint-browser.js')\n    }\n  },\n\n  externals: {\n    'viz.js': 'Viz',\n    'socket.io-client': 'io',\n    'jquery': '$',\n    'moment': 'moment',\n    'handlebars': 'Handlebars',\n    'highlight.js': 'hljs',\n    'select2': 'select2'\n  },\n\n  module: {\n    rules: [{\n      test: /\\.mjs$/,\n      type: 'javascript/auto',\n      include: /node_modules/\n    }, {\n      test: /node_modules\\/markmap.*\\/.*\\.mjs$/,\n      use: [{ loader: 'babel-loader' }],\n      type: 'javascript/auto'\n    }, {\n      test: /node_modules\\/markmap.*\\/.*\\.js$/,\n      use: [{\n        loader: 'babel-loader',\n        options: {\n          presets: [\n            ['@babel/preset-env', {\n              modules: 'cjs'\n            }]\n          ]\n        }\n      }]\n    }, {\n      test: /node_modules\\/yaml\\/browser\\/dist\\/.*\\.js$/,\n      use: [{ loader: 'babel-loader' }]\n    }, {\n      test: /node_modules\\/@vscode\\/markdown-it-katex\\/.*\\.js$/,\n      use: [{\n        loader: 'babel-loader',\n        options: {\n          presets: [\n            ['@babel/preset-env', {\n              modules: 'cjs'\n            }]\n          ],\n          plugins: [\n            '@babel/plugin-transform-optional-chaining'\n          ]\n        }\n      }]\n    }, {\n      test: /\\.js$/,\n      use: [{ loader: 'babel-loader' }],\n      exclude: [\n        path.resolve(__dirname, 'node_modules'),\n        path.resolve(__dirname, 'public/vendor')\n      ]\n    }, {\n      test: /\\.css$/,\n      use: [\n        MiniCssExtractPlugin.loader,\n        'css-loader'\n      ]\n    }, {\n      test: /\\.scss$/,\n      use: [\n        MiniCssExtractPlugin.loader,\n        {\n          loader: 'css-loader',\n          options: {\n            importLoaders: 1\n          }\n        },\n        'sass-loader'\n      ]\n    }, {\n      test: /\\.less$/,\n      use: [\n        MiniCssExtractPlugin.loader,\n        {\n          loader: 'css-loader',\n          options: {\n            importLoaders: 1\n          }\n        },\n        'less-loader'\n      ]\n    }, {\n      test: /\\.eot(\\?v=\\d+\\.\\d+\\.\\d+)?$/,\n      use: [{ loader: 'file-loader' }]\n    }, {\n      test: /\\.html$/,\n      use: [{ loader: 'string-loader' }]\n    }, {\n      test: /\\.(woff|woff2)(\\?v=\\d+\\.\\d+\\.\\d+)?$/,\n      use: [{\n        loader: 'url-loader',\n        options: { prefix: 'font/', limit: '5000' }\n      }]\n    }, {\n      test: /\\.ttf(\\?v=\\d+\\.\\d+\\.\\d+)?$/,\n      use: [{\n        loader: 'url-loader',\n        options: { limit: '5000', mimetype: 'application/octet-stream' }\n      }]\n    }, {\n      test: /\\.svg(\\?v=\\d+\\.\\d+\\.\\d+)?$/,\n      exclude: path.resolve(__dirname, 'public/js/lib/renderer/fretboard'),\n      use: [{\n        loader: 'url-loader',\n        options: { limit: '10000', mimetype: 'svg+xml' }\n      }]\n    }, {\n      test: /.*\\/fretboard\\/svg\\/.*\\.svg$/,\n      loader: 'string-loader'\n    }, {\n      test: /\\.png(\\?v=\\d+\\.\\d+\\.\\d+)?$/,\n      use: [{\n        loader: 'url-loader',\n        options: { limit: '10000', mimetype: 'image/png' }\n      }]\n    }, {\n      test: /\\.gif(\\?v=\\d+\\.\\d+\\.\\d+)?$/,\n      use: [{\n        loader: 'url-loader',\n        options: { limit: '10000', mimetype: 'image/gif' }\n      }]\n    }, {\n      test: /@hackmd\\/codemirror\\/addon\\/lint\\/lint/,\n      use: [{\n        loader: 'script-loader'\n      }]\n    }]\n  },\n  node: {\n    fs: 'empty',\n    os: 'empty'\n  },\n\n  stats: {\n    assets: false\n  }\n}\n"
  },
  {
    "path": "webpack.dev.js",
    "content": "const common = require('./webpack.common.js')\nconst htmlexport = require('./webpack.htmlexport')\nconst merge = require('webpack-merge')\n\nmodule.exports = [\n  // merge common config\n  merge(common, {\n    mode: 'development',\n    devtool: 'cheap-module-eval-source-map'\n  }),\n  merge(htmlexport, {\n    mode: 'development',\n    devtool: 'cheap-module-eval-source-map'\n  })]\n"
  },
  {
    "path": "webpack.htmlexport.js",
    "content": "const MiniCssExtractPlugin = require('mini-css-extract-plugin')\nconst path = require('path')\n\nmodule.exports = {\n  name: 'save-as-html',\n  entry: {\n    htmlExport: path.join(__dirname, 'public/js/htmlExport.js')\n  },\n  module: {\n    rules: [{\n      test: /\\.css$/,\n      use: [MiniCssExtractPlugin.loader, 'css-loader']\n    }]\n  },\n  output: {\n    path: path.join(__dirname, 'public/build'),\n    publicPath: '/build/',\n    filename: '[name].js'\n  },\n  plugins: [\n    new MiniCssExtractPlugin({\n      filename: 'html.min.css'\n    })\n  ]\n}\n"
  },
  {
    "path": "webpack.prod.js",
    "content": "const common = require('./webpack.common.js')\nconst htmlexport = require('./webpack.htmlexport')\nconst merge = require('webpack-merge')\nconst path = require('path')\nconst OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')\n\nmodule.exports = [\n  merge(common, {\n    mode: 'production',\n    output: {\n      path: path.join(__dirname, 'public/build'),\n      publicPath: '/build/',\n      filename: '[name].[contenthash].js'\n    }\n  }),\n  merge(htmlexport, {\n    mode: 'production',\n    optimization: {\n      minimizer: [\n        new OptimizeCSSAssetsPlugin({})\n      ]\n    }\n  })]\n"
  }
]