├── .editorconfig ├── .eslintrc.json ├── .gitattributes ├── .github └── workflows │ ├── check.yml │ └── publish.yml ├── .gitignore ├── .prettierignore ├── LICENSE.txt ├── README.md ├── package-lock.json ├── package.json ├── src ├── ecmarkdown.ts ├── emitter.ts ├── node-types.ts ├── parser.ts ├── tokenizer.ts ├── tsconfig.json └── visitor.ts └── test ├── .eslintrc ├── cases ├── code.ecmarkdown ├── code.html ├── comment-at-end.ecmarkdown ├── comment-at-end.html ├── dunderproto.fragment.ecmarkdown ├── dunderproto.fragment.html ├── embedded-list.fragment.ecmarkdown ├── embedded-list.fragment.html ├── empty.fragment.ecmarkdown ├── empty.fragment.html ├── escape-cases.ecmarkdown ├── escape-cases.html ├── extra-linebreaks.fragment.ecmarkdown ├── extra-linebreaks.fragment.html ├── flexible-indent-nested-list.ecmarkdown ├── flexible-indent-nested-list.html ├── format-at-end.fragment.ecmarkdown ├── format-at-end.fragment.html ├── formats-in-text.fragment.ecmarkdown ├── formats-in-text.fragment.html ├── html-chars.fragment.ecmarkdown ├── html-chars.fragment.html ├── html-comment-inside-item.ecmarkdown ├── html-comment-inside-item.html ├── html-comment-multiline-2.ecmarkdown ├── html-comment-multiline-2.html ├── html-comment-multiline-3.ecmarkdown ├── html-comment-multiline-3.html ├── html-comment-multiline.ecmarkdown ├── html-comment-multiline.html ├── html-comment-nested-list.ecmarkdown ├── html-comment-nested-list.html ├── html-comment-singleline.ecmarkdown ├── html-comment-singleline.html ├── html-elements.ecmarkdown ├── html-elements.html ├── html-escaping.fragment.ecmarkdown ├── html-escaping.fragment.html ├── html-tag-with-special-chars.ecmarkdown ├── html-tag-with-special-chars.html ├── iterator-close.ecmarkdown ├── iterator-close.html ├── just-leading-whitespace.fragment.ecmarkdown ├── just-leading-whitespace.fragment.html ├── leading-linebreaks.ecmarkdown ├── leading-linebreaks.html ├── leading-space.ecmarkdown ├── leading-space.html ├── leading-spaces.fragment.ecmarkdown ├── leading-spaces.fragment.html ├── linebreaks.fragment.ecmarkdown ├── linebreaks.fragment.html ├── list-attrs.ecmarkdown ├── list-attrs.html ├── list-numbering.ecmarkdown ├── list-numbering.html ├── list.ecmarkdown ├── list.html ├── lt.fragment.ecmarkdown ├── lt.fragment.html ├── mangled-list-items.ecmarkdown ├── mangled-list-items.html ├── multiline-items.ecmarkdown ├── multiline-items.html ├── multiline.fragment.ecmarkdown ├── multiline.fragment.html ├── multiple-formats.fragment.ecmarkdown ├── multiple-formats.fragment.html ├── nested-list.ecmarkdown ├── nested-list.html ├── no-list-without-newline.ecmarkdown ├── no-list-without-newline.html ├── nonterminals.ecmarkdown ├── nonterminals.html ├── opaque-tags.fragment.ecmarkdown ├── opaque-tags.fragment.html ├── simple.fragment.ecmarkdown ├── simple.fragment.html ├── spec-constants.ecmarkdown ├── spec-constants.html ├── trailing-linebreak.fragment.ecmarkdown ├── trailing-linebreak.fragment.html ├── trailing-long-parabreak.fragment.ecmarkdown ├── trailing-long-parabreak.fragment.html ├── trailing-parabreak.fragment.ecmarkdown ├── trailing-parabreak.fragment.html ├── values.ecmarkdown ├── values.html ├── variables.ecmarkdown └── variables.html ├── errors.js ├── helpers └── beautify.js ├── parser.js ├── run-cases.js └── tokenizer.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | charset = utf-8 8 | indent_style = space 9 | indent_size = 2 10 | 11 | # Input/output is 2-space indent 12 | [test/*-cases/*] 13 | indent_size = 2 14 | 15 | [test/**/*] 16 | insert_final_newline = false 17 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "parserOptions": { 5 | "sourceType": "module", 6 | "ecmaVersion": 2018 7 | }, 8 | "extends": [ 9 | "eslint:recommended", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "prettier" 12 | ], 13 | "plugins": [ 14 | "@typescript-eslint", 15 | "prettier" 16 | ], 17 | "env": { 18 | "node": true, 19 | "es6": true 20 | }, 21 | "overrides": [ 22 | { 23 | "files": ["test/**/*"], 24 | "env": { 25 | "mocha": true 26 | }, 27 | "parserOptions": { 28 | "sourceType": "script", 29 | "ecmaVersion": 2020 30 | } 31 | }, 32 | { 33 | "files": ["bin/**/*"], 34 | "parserOptions": { 35 | "sourceType": "script", 36 | "ecmaVersion": 2020 37 | } 38 | } 39 | ], 40 | "rules": { 41 | "prettier/prettier": "error", 42 | "consistent-return": "off", 43 | "no-floating-decimal": "error", 44 | "no-self-compare": "error", 45 | "no-throw-literal": "error", 46 | "no-void": "error", 47 | "strict": [ 48 | "error", 49 | "global" 50 | ], 51 | "no-use-before-define": [ 52 | "error", 53 | "nofunc" 54 | ], 55 | "no-underscore-dangle": "off", 56 | "no-constant-condition": "off", 57 | "no-control-regex": "off", 58 | "camelcase": [ 59 | "error", 60 | { 61 | "properties": "never" 62 | } 63 | ], 64 | "no-empty": "error", 65 | "curly": [ 66 | "error", 67 | "multi-line" 68 | ], 69 | "no-var": "error", 70 | "no-unused-vars": "off", 71 | "@typescript-eslint/no-unused-vars": "error" 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: check 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | check: 11 | name: Check 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v2 16 | 17 | - name: Setup node 18 | uses: actions/setup-node@v2 19 | with: 20 | node-version: '12' 21 | 22 | - name: Install dependencies 23 | run: npm ci 24 | 25 | - name: Build 26 | run: npm run build 27 | 28 | - name: Test 29 | run: npm test 30 | 31 | - name: Lint 32 | run: npm run lint 33 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: publish 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | 14 | - name: Setup node 15 | uses: actions/setup-node@v2 16 | with: 17 | node-version: '16' 18 | registry-url: 'https://registry.npmjs.org' 19 | 20 | - name: Install dependencies 21 | run: npm ci 22 | 23 | - name: Publish 24 | run: npm publish 25 | env: 26 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN_FOR_TC39_USER }} 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | dist/ 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.md 3 | *.json 4 | *.yml 5 | *.css 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright © 2014–2015 Domenic Denicola 2 | 3 | This work is free. You can redistribute it and/or modify it under the 4 | terms of the Do What The Fuck You Want To Public License, Version 2, 5 | as published by Sam Hocevar. See below for more details. 6 | 7 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 8 | Version 2, December 2004 9 | 10 | Copyright (C) 2004 Sam Hocevar 11 | 12 | Everyone is permitted to copy and distribute verbatim or modified 13 | copies of this license document, and changing it is allowed as long 14 | as the name is changed. 15 | 16 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 17 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 18 | 19 | 0. You just DO WHAT THE FUCK YOU WANT TO. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ecmarkdown 2 | 3 | **Ecmarkdown** is a Markdown-inspired syntax for writing text and algorithms in the style of [the ECMAScript spec](https://tc39.github.io/ecma262/). This package will convert Ecmarkdown input to HTML output. 4 | 5 | ## Examples 6 | 7 | ### An algorithm 8 | 9 | Some of Ecmarkdown's biggest benefits are when using it to write algorithm steps, without the many formalities HTML requires for list items and inline formatting of common algorithmic constructs. 10 | 11 | ``` 12 | 1. Assert: Type(_iterator_) is Object. 13 | 1. Assert: _completion_ is a Completion Record. 14 | 1. Let _hasReturn_ be HasProperty(_iterator_, `"return"`). 15 | 1. ReturnIfAbrupt(_hasReturn_). 16 | 1. If _hasReturn_ is *true*, then 17 | 1. Let _innerResult_ be Invoke(_iterator_, `"return"`, ( )). 18 | 1. If _completion_.[[type]] is not ~throw~ and _innerResult_.[[type]] is ~throw~, then 19 | 1. Return _innerResult_. 20 | 1. Return _completion_. 21 | ``` 22 | 23 | will be converted to 24 | 25 | ```html 26 | 27 |
    28 |
  1. Assert: Type(iterator) is Object.
  2. 29 |
  3. Assert: completion is a Completion Record.
  4. 30 |
  5. Let hasReturn be HasProperty(iterator, "return").
  6. 31 |
  7. ReturnIfAbrupt(hasReturn). 32 |
      33 |
    1. If hasReturn is true, then 34 |
        35 |
      1. Let innerResult be Invoke(iterator, "return", ( )).
      2. 36 |
      3. If completion.[[type]] is not throw and innerResult.[[type]] is throw, then 37 |
          38 |
        1. Return innerResult.
        2. 39 |
        40 |
      4. 41 |
      42 |
    2. 43 |
    44 |
  8. 45 |
  9. Return completion.
  10. 46 |
47 |
48 | ``` 49 | 50 | ## Syntax 51 | 52 | #### Lists 53 | 54 | Lists are written as a series of lines, each starting with either a number, e.g. `1.`, or a star, e.g. `*`. Inside a list item line you can use inline Ecmarkdown constructs. The first list item's number determines the starting number in the output (via `
    `); subsequent list items' numbers are ignored. 55 | 56 | Lists can be nested. To do so, use any number of spaces to indent; as long as the number of spaces is consistent, list items will stay together in a nested list. 57 | 58 | List items can be given arbitrary attributes by putting `[attr="something"]` at the start of the item, as in `1. [attr="something"]`. This will generate `
  1. `. Multiple attributes are also supported as comma-seperated lists, as in `[attr1="a", attr2="b"]`. 59 | 60 | #### HTML Blocks 61 | 62 | Any line which starts with a block-level HTML tag ([as defined by CommonMark](http://spec.commonmark.org/0.22/#html-blocks), with the addition of ``, ``, ``, ``, ``, ``, ``, ``, ``, ``, and ``) is a HTML block line. Ecmarkdown cannot be used on the line starting a HTML block, but subsequent lines before the closing tag do allow it. 63 | 64 | #### Opaque HTML Blocks 65 | 66 | The tags ``, ``, ``, `
    `, ``, `