@thi.ng/hiccup-markdown 3.2.46 → 3.2.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2023-12-03T12:13:31Z
3
+ - **Last updated**: 2023-12-11T10:07:09Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
package/README.md CHANGED
@@ -536,7 +536,7 @@ For Node.js REPL:
536
536
  const hiccupMarkdown = await import("@thi.ng/hiccup-markdown");
537
537
  ```
538
538
 
539
- Package sizes (brotli'd, pre-treeshake): ESM: 4.72 KB
539
+ Package sizes (brotli'd, pre-treeshake): ESM: 4.62 KB
540
540
 
541
541
  ## Dependencies
542
542
 
package/api.js CHANGED
@@ -1 +0,0 @@
1
- export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/hiccup-markdown",
3
- "version": "3.2.46",
3
+ "version": "3.2.48",
4
4
  "description": "Markdown parser & serializer from/to Hiccup format",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -24,7 +24,9 @@
24
24
  "author": "Karsten Schmidt (https://thi.ng)",
25
25
  "license": "Apache-2.0",
26
26
  "scripts": {
27
- "build": "yarn clean && tsc --declaration",
27
+ "build": "yarn build:esbuild && yarn build:decl",
28
+ "build:decl": "tsc --declaration --emitDeclarationOnly",
29
+ "build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
28
30
  "clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc",
29
31
  "doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
30
32
  "doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
@@ -33,21 +35,21 @@
33
35
  "test": "bun test"
34
36
  },
35
37
  "dependencies": {
36
- "@thi.ng/api": "^8.9.10",
37
- "@thi.ng/arrays": "^2.7.6",
38
- "@thi.ng/checks": "^3.4.10",
39
- "@thi.ng/defmulti": "^3.0.8",
40
- "@thi.ng/emoji": "^0.1.16",
41
- "@thi.ng/errors": "^2.4.4",
42
- "@thi.ng/hiccup": "^5.0.9",
43
- "@thi.ng/logger": "^2.0.1",
44
- "@thi.ng/parse": "^2.4.8",
45
- "@thi.ng/strings": "^3.7.1",
46
- "@thi.ng/text-canvas": "^2.6.21"
38
+ "@thi.ng/api": "^8.9.12",
39
+ "@thi.ng/arrays": "^2.7.8",
40
+ "@thi.ng/checks": "^3.4.12",
41
+ "@thi.ng/defmulti": "^3.0.10",
42
+ "@thi.ng/emoji": "^0.1.18",
43
+ "@thi.ng/errors": "^2.4.6",
44
+ "@thi.ng/hiccup": "^5.1.1",
45
+ "@thi.ng/logger": "^2.0.2",
46
+ "@thi.ng/parse": "^2.4.10",
47
+ "@thi.ng/strings": "^3.7.3",
48
+ "@thi.ng/text-canvas": "^2.6.23"
47
49
  },
48
50
  "devDependencies": {
49
51
  "@microsoft/api-extractor": "^7.38.3",
50
- "@thi.ng/testament": "^0.4.3",
52
+ "esbuild": "^0.19.8",
51
53
  "rimraf": "^5.0.5",
52
54
  "tools": "^0.0.1",
53
55
  "typedoc": "^0.25.4",
@@ -97,5 +99,5 @@
97
99
  ],
98
100
  "year": 2018
99
101
  },
100
- "gitHead": "04d1de79f256d7a53c6b5fd157b37f49bc88e11d\n"
102
+ "gitHead": "5e7bafedfc3d53bc131469a28de31dd8e5b4a3ff\n"
101
103
  }
package/parse.js CHANGED
@@ -1,5 +1,3 @@
1
- // Downloaded @ 2023-03-07T13:30:37.046Z
2
- // Source: https://demo.thi.ng/umbrella/parse-playground/#l9oQo0ROTDE6IDxETkw-KyA9PiBkaXNjYXJkIDsKRE5MMjogPE5MPnsyLH0gOwpsYnI6ICdcXCchIDxOTD4hIDsKZXNjOiAnXFwnISAoJ18nIHwgJyonIHwgJ2AnIHwgJ34nIHwgJzonIHwgJy0nIHwgJzwnIHwgJz4nIHwgJ1snIHwgJ10nIHwgJygnIHwgJyknIHwgJ3snIHwgJ30nIHwgJyMnIHwgJy4nIHwgJ3wnIHwgJ1xcJykgOwpjZXNjOiAnXFwnISAoJ2AnfCAnXFwnKSA7CmNiZXNjOiAnXFwnISAnYCcgOwpjdWVzYzogJ1xcJyEgJzonIDsKbWVzYzogJ1xcJyEgJ30nIDsKaWRlbGltOiAoIiFbIiB8ICdbJyB8ICIqKiIgfCAnXycgfCAnYCcgfCAnPCcgfCAifn4iIHwgIiA6IiB8IDxsYnI-KSA7CmRlbGltOiAoPGlkZWxpbT4gfCA8RE5MMj4pIDsKZWJvZHk6ICg8ZXNjPnwuKSA7CmNib2R5OiAoPGNlc2M-fC4pIDsKY2Jib2R5OiAoPGNiZXNjPnwuKSA7CmN1Ym9keTogKDxjdWVzYz58LikgOwptYm9keTogKDxtZXNjPnwuKSA7CmJvZHk6IDxlYm9keT4oPy08ZGVsaW0-ISkgPT4gam9pbiA7Cmlib2R5OiA8ZWJvZHk-KD8tPGlkZWxpbT4hKSA9PiBqb2luIDsKCmNvbW1lbnQ6ICI8IS0tIiEgLig_KyItLT4iKSA9PiBkaXNjYXJkIDsKd2lraXJlZjogIltbIiEgPGVib2R5Pig_KyJdXSIhKSA9PiBqb2luIDsKZm5yZWY6ICJbXiIhIDxsYWJlbD4gOwpmbm90ZTogPExTVEFSVD4gIlteIiEgPGZubGFiZWw-IDxXUzE-IDxwYXJhPiA7CmZubGFiZWw6IDxlYm9keT4oPysiXToiISkgPT4gam9pbiA7CmxhYmVsOiA8ZWJvZHk-KD8rJ10nISkgPT4gam9pbiA7CnRhcmdldDogPGVib2R5Pig_KycpJyEpID0-IGpvaW4gOwpsaW5rOiAnWychIDxsaW5rbGFiZWw-ICcoJyEgPHRhcmdldD4gOwpsaW5rcmVmOiAnWychIDxsaW5rbGFiZWw-ICdbJyEgPGxhYmVsPiA7CmxpbmtkZWY6IDxMU1RBUlQ-ICdbJyEgPGxhYmVsPiAnOichIDxXUzE-IDxsZHRhcmdldD4gOwpsZHRhcmdldDogPGVib2R5Pig_KzxETkwxPikgPT4gam9pbiA7CmxpbmtsYWJlbDogKDxpbWc-IHwgPGJvbGQ-IHwgPGl0YWxpYz4gfCA8c3RyaWtlPiB8IDxjb2RlPiB8IDxlbW9qaT4gfCA8a2JkPiB8IDxzdWI-IHwgPHN1cD4gfCA8bGlua2JvZHk-KSogJ10nISA7CmxpbmtkZWxpbTogKCIhWyIgfCAnWycgfCAiKioiIHwgJ18nIHwgIn5-IiB8ICdgJyB8ICddJykgOwpsaW5rYm9keTogPGVib2R5Pig_LTxsaW5rZGVsaW0-ISkgPT4gam9pbiA7CmltZzogIiFbIiEgPGxhYmVsPiAnKCchIDx0YXJnZXQ-IDsKYm9sZDogIioqIiEgKDx3aWtpcmVmPiB8IDxpbWc-IHwgPGZucmVmPiB8IDxsaW5rcmVmPiB8IDxsaW5rPiB8IDxpdGFsaWM-IHwgPHN0cmlrZT4gfCA8Y29kZT4gfCA8ZW1vamk-IHwgPGtiZD4gfCA8c3ViPiB8IDxzdXA-IHwgPGlib2R5PikqICIqKiIhIDsKaXRhbGljOiAnXychICg8d2lraXJlZj4gfCA8aW1nPiB8IDxmbnJlZj4gfCA8bGlua3JlZj4gfCA8bGluaz4gfCA8Ym9sZD4gfCA8c3RyaWtlPiB8IDxjb2RlPiB8IDxlbW9qaT4gfCA8a2JkPiB8IDxzdWI-IHwgPHN1cD4gfCA8aWJvZHk-KSogJ18nISA7CnN0cmlrZTogIn5-IiEgKDx3aWtpcmVmPiB8IDxpbWc-IHwgPGZucmVmPiB8IDxsaW5rcmVmPiB8IDxsaW5rPiB8IDxib2xkPiB8IDxpdGFsaWM-IHwgPGNvZGU-IHwgPGVtb2ppPiB8IDxrYmQ-IHwgPHN1Yj4gfCA8c3VwPiB8IDxpYm9keT4pKiAifn4iISA7CmNvZGU6ICdgJyEgPGNib2R5Pig_KydgJyEpID0-IGpvaW4gOwprYmQ6ICI8a2JkPiIhIDxlYm9keT4oPysiPC9rYmQ-IiEpID0-IGpvaW4gOwpzdWI6ICI8c3ViPiIhIDxlYm9keT4oPysiPC9zdWI-IiEpID0-IGpvaW4gOwpzdXA6ICI8c3VwPiIhIDxlYm9keT4oPysiPC9zdXA-IiEpID0-IGpvaW4gOwplbW9qaTogJyAnPyAnOichICg8QUxQSEFfTlVNPiB8ICcrJykoPysnOichKSA9PiBqb2luIDsKcGFyYTogKDx3aWtpcmVmPiB8IDxpbWc-IHwgPGZucmVmPiB8IDxsaW5rcmVmPiB8IDxsaW5rPiB8IDxib2xkPiB8IDxpdGFsaWM-IHwgPHN0cmlrZT4gfCA8Y29kZT4gfCA8a2JkPiB8IDxzdWI-IHwgPHN1cD4gfCA8ZW1vamk-IHwgPGxicj4gfCA8Y29tbWVudD4gfCA8Ym9keT4pKiA8RE5MMj4hIDsKCmhkbGV2ZWw6ICcjJysgPT4gY291bnQgOwpoZGlkOiAieyMiISAoPEFMUEhBX05VTT4gfCAnLScpKyAnfSchID0-IGpvaW4gOwpoZGRlbGltOiAoPGlkZWxpbT4gfCA8Tkw-IHwgInsjIikgOwpoZGJvZHk6IDxlYm9keT4oPy08aGRkZWxpbT4hKSA9PiBqb2luIDsKaGQ6IDxMU1RBUlQ-IDxoZGxldmVsPiA8V1MwPgogICAgKDx3aWtpcmVmPiB8IDxpbWc-IHwgPGZucmVmPiB8IDxsaW5rPiB8IDxib2xkPiB8IDxpdGFsaWM-IHwgPHN0cmlrZT4gfCA8Y29kZT4gfCA8ZW1vamk-IHwgPGtiZD4gfCA8c3ViPiB8IDxzdXA-IHwgPGhkYm9keT4pKiA8aGRpZD4_IDxETkwxPiA7CgpsaWxldmVsOiAnICcqID0-IGNvdW50IDsKb2xpZDogKDxBTFBIQT4rfDxESUdJVD4rKSA9PiBqb2luIDsKdWxpbml0OiA8RE5MPiA8V1MwPiAnLSchIDsKb2xpbml0OiA8RE5MPiA8V1MwPiA8b2xpZD4hICcuJyEgOwpsaWRlbGltOiAoPGRlbGltPiB8IDx1bGluaXQ-IHwgPG9saW5pdD4pIDsKbGlib2R5OiA8ZWJvZHk-KD8tPGxpZGVsaW0-ISkgPT4gam9pbiA7CnRvZG86ICdbJyEgWyB4WF0gJ10nISA8V1MxPiA9PiBob2lzdFIgOwp1bGl0ZW06IDxMU1RBUlQ-IDxsaWxldmVsPiAiLSAiISA8dG9kbz4_CiAgICAgICAgKDx3aWtpcmVmPiB8IDxpbWc-IHwgPGZucmVmPiB8IDxsaW5rPiB8IDxib2xkPiB8IDxpdGFsaWM-IHwgPHN0cmlrZT4gfCA8Y29kZT4gfCA8ZW1vamk-IHwgPGtiZD4gfCA8c3ViPiB8IDxzdXA-IHwgPGxpYm9keT4gKSogPEROTD4gOwpvbGl0ZW06IDxMU1RBUlQ-IDxsaWxldmVsPiA8b2xpZD4gIi4gIiEgPHRvZG8-PwogICAgICAgICg8d2lraXJlZj4gfCA8aW1nPiB8IDxmbnJlZj4gfCA8bGluaz4gfCA8Ym9sZD4gfCA8aXRhbGljPiB8IDxzdHJpa2U-IHwgPGNvZGU-IHwgPGVtb2ppPiB8IDxrYmQ-IHwgPHN1Yj4gfCA8c3VwPiB8IDxsaWJvZHk-ICkqIDxETkw-IDsKbGlzdDogKDx1bGl0ZW0-IHwgPG9saXRlbT4pKyA8RE5MMT4gOwoKY2JkZWxpbTogPExTVEFSVD4gImBgYCIhIDsKY29kZWJsb2NrOiA8Y2JkZWxpbT4hIDxjb2RlbWV0YT4gPGNvZGVib2R5PiA8RE5MMT4gOwpjb2RlbWV0YTogLig_KzxOTD4hKSA9PiBqb2luIDsKY29kZWJvZHk6IDxjYmJvZHk-KD8rPGNiZGVsaW0-KSA9PiBqb2luIDsKCmN1ZGVsaW06IDxMU1RBUlQ-ICI6OjoiISA7CmN1c3RvbWJsb2NrOiA8Y3VkZWxpbT4hIDxjdXN0b21tZXRhPiA8Y3VzdG9tYm9keT4gPEROTDE-IDsKY3VzdG9tbWV0YTogLig_KzxOTD4hKSA9PiBqb2luIDsKY3VzdG9tYm9keTogPGN1Ym9keT4oPys8Y3VkZWxpbT4pID0-IGpvaW4gOwoKbWV0YWJsb2NrOiA8TFNUQVJUPiAie3t7IiEgPG1ldGFib2R5PiA8RE5MMT4gOwptZXRhYm9keTogPG1ib2R5Pig_KzxtZXRhZW5kPiEpID0-IGpvaW4gOwptZXRhZW5kOiAifX19IiA8TEVORD4gOwoKYnFsZXZlbDogJz4nKyA9PiBjb3VudCA7CmJxZGVsaW06ICg8aWRlbGltPiB8IDxOTD4pIDsKYnFib2R5OiA8ZWJvZHk-KD8tPGJxZGVsaW0-ISkgPT4gam9pbiA7CmJxbGluZTogPExTVEFSVD4gPGJxbGV2ZWw-ICcgJz8hCiAgICAgICAgKDx3aWtpcmVmPiB8IDxpbWc-IHwgPGZucmVmPiB8IDxsaW5rPiB8IDxib2xkPiB8IDxpdGFsaWM-IHwgPHN0cmlrZT4gfCA8Y29kZT4gfCA8ZW1vamk-IHwgPGtiZD4gfCA8c3ViPiB8IDxzdXA-IHwgPGJxbGJyPiB8IDxicWJvZHk-KSogPEROTD4gOwpicWxicjogJ1xcJyEoPy08RE5MPikgOwpicXVvdGU6IDxicWxpbmU-KyA8RE5MMT4gOwoKdGRlbGltOiAoPGlkZWxpbT4gfCAnfCcgKSA7CnRib2R5OiA8ZWJvZHk-KD8tPHRkZWxpbT4hKSA9PiBqb2luIDsKdGNlbGw6IDxXUzA-ICg8d2lraXJlZj4gfCA8aW1nPiB8IDxmbnJlZj4gfCA8bGluaz4gfCA8Ym9sZD4gfCA8aXRhbGljPiB8IDxzdHJpa2U-IHwgPGNvZGU-IHwgPGVtb2ppPiB8IDxrYmQ-IHwgPHN1Yj4gfCA8c3VwPiB8IDx0Ym9keT4gKSogJ3wnISA7CnRyb3c6IDxMU1RBUlQ-ICd8JyEgPHRjZWxsPig_KzxETkw-KSA7CnRhYmxlOiA8dHJvdz4rIDxETkwxPiA7CgpocjogIi0tIiAnLScrIDxETkwxPiA9PiBqb2luIDsKCm1haW46IDxXUzA-ICg8aGQ-IHwgPGxpc3Q-IHwgPGJxdW90ZT4gfCA8Y29kZWJsb2NrPiB8IDxjdXN0b21ibG9jaz4gfCA8bWV0YWJsb2NrPiB8IDx0YWJsZT4gfCA8aHI-IHwgPGZub3RlPiB8IDxsaW5rZGVmPiB8IDxjb21tZW50PiB8IDxwYXJhPiApKiA7pG1haW7aAtQjIEhlbGxvIFwhXFsgOndvcmxkOjpzbWlsZTpbXmFiY10geyNoZDF9CgojIyBhYmMgeyNoZDJ9CiMjIGRlZiA8c3VwPkNvbnRyb2w8L3N1cD4KCmEgXDwgYgoKTGV0IGBleHAyKHgpID0gMioqeGAKClByZXNzIDxrYmQ-Q29udHJvbDwva2JkPiArIDxrYmQ-Ujwva2JkPiB0byA8IS0tc2tpcC0tPiByZWxvYWQuCgo6OjphbGVydApUZXN0IFtsYWJlbF1bcmVmcmVmXQo6OjoKCi0tLQoKe3t7IHsiaWQiOiAxMjMsICJwcm90ZWN0ZWQiOiB0cnVlIH0gfX19ClNvIFtbc21pbGVfZm9vMTJdXSDwn5iNIHdoYXQncyBbdGhpc10oLi90aGlzLm1kKVteMl0gdGhlbjoKCkEgW2xpbmsgX3dpdGggKipuZXN0ZWQgfn5mb3JtYXR-fioqIGFuZCBgcmVmZXJlbmNlYF9dW3JlZnJlZl0uLi4KCmBgYHRzIHRhbmdsZTpubyBsbjp5ZXMKY29uc3QgcmUgPSAvW1xuXHJdKy9nOwovLyB0aGUgZW5kCmBgYAoKMS4gZm9vCiAgNC4gYmFyCiAgICAgYmF6IGFuZCBzbyBvbgogICAgIG11bHRpbGluZQoyLiBbIF0gdGFzawozLiBbeF0gKipkb25lKioKCj4gYmxvY2txdW90ZQo-IG11bHRpbGluZSB0b29cCj4-IG5lc3RlZAo-Pj4gbGV2ZWwgMwo-IC0tIHNvdXJjZQoKfCBmb28gfCBiYXIgfAp8Oi06fC06fAp8IFtbcmVmIzIyXV0gfCBgb25gICoqb2ZmKiogfAoKW15hYmNdOiBGb28gX2Jhcl8gYmF6CgpbXjJdOiBUT0RPCgpbcmVmcmVmXTogaHR0cDovL3RoaS5uZy8KW2Zvb106IC4vZm9vLm1kI2JhcgoK2VA8IS0tCmlnbm9yZQptdWx0aWxpbmUKLS0-CgoxMS4gYWJjCiAgLSB4eXoKMjEuIHh4eAogIGEuIGZvbwogICAgYi4gYmFyCjMxLiB5eXkKCtlSfCBjb2wxIHwgY29sMiB8CnwgLS0tLSB8IC0tLS06fAp8IDxrYmQ-Q3RybDwva2JkPiB8IDxzdXA-Ujwvc3VwPiBgW1thYmNcfGlkXV1gIHwKCrkqKjp3YXJuOiBhYmMKZGVmIDpvazoqKgoK2Ug-IGxpbmUxCj4-ICoqbGluZSAyKipcCj4-IGxpbmUgMmEKPj4gbGluZSAyYgo-PiAKPj4gbGluZSAyYwo-Pj4gbGluZSAzCgo
3
1
  import { peek } from "@thi.ng/arrays/peek";
4
2
  import { isArray } from "@thi.ng/checks/is-array";
5
3
  import { isPlainObject } from "@thi.ng/checks/is-plain-object";
@@ -11,7 +9,7 @@ import { defContext } from "@thi.ng/parse/context";
11
9
  import { defGrammar } from "@thi.ng/parse/grammar";
12
10
  import { escapeEntities } from "@thi.ng/strings/entities";
13
11
  import { slugifyGH } from "@thi.ng/strings/slugify";
14
- export const GRAMMAR = defGrammar(`
12
+ const GRAMMAR = defGrammar(`
15
13
  DNL1: <DNL>+ => discard ;
16
14
  DNL2: <NL>{2,} ;
17
15
  lbr: '\\\\'! <NL>! ;
@@ -107,176 +105,140 @@ hr: "--" '-'+ <DNL1> => join ;
107
105
 
108
106
  main: <WS0> (<hd> | <list> | <bquote> | <codeblock> | <customblock> | <metablock> | <table> | <hr> | <fnote> | <linkdef> | <comment> | <para> )* ;
109
107
  `);
110
- export const DEFAULT_TAG_TRANSFORMS = {
111
- bold: (_, body) => ["strong", {}, ...body],
112
- blockquote: (_, body, meta) => ["blockquote", withMeta({}, meta), ...body],
113
- br: () => ["br", {}],
114
- code: (_, body) => ["code", {}, body],
115
- codeblock: (_, lang, __head, body, meta) => [
116
- "pre",
117
- withMeta({ data: { lang }, __head }, meta),
118
- ["code", {}, body],
119
- ],
120
- custom: (_, type, __head, body, meta) => [
121
- "custom",
122
- withMeta({ type, __head }, meta),
123
- body,
124
- ],
125
- emoji: (_, id) => EMOJI[id] || id,
126
- footnote: (_, id, body, meta) => [
127
- "li",
128
- withMeta({ id: `fn-${id}` }, meta),
129
- ["sup", {}, `[${id}] `],
130
- ...body,
131
- " ",
132
- ["a", { href: `#fnref-${id}` }, "↩︎"],
133
- ],
134
- footnoteRef: (_, id) => [
135
- "sup",
136
- {},
137
- ["a", { id: `fnref-${id}`, href: `#fn-${id}` }, `[${id}]`],
138
- ],
139
- footnoteWrapper: (_, notes) => [
140
- "ul",
141
- { id: "footnotes" },
142
- ...Object.keys(notes)
143
- .sort()
144
- .map((id) => notes[id]),
145
- ],
146
- heading: (_, level, id, body, meta) => [
147
- level > 6 ? "p" : `h${level}`,
148
- withMeta({ id }, meta),
149
- ...body,
150
- ],
151
- hr: (_, __length, meta) => ["hr", withMeta({ __length }, meta)],
152
- img: (_, alt, src, title) => ["img", { src, alt, title }],
153
- italic: (_, body) => ["em", {}, ...body],
154
- kbd: (_, key) => ["kbd", {}, key],
155
- link: (_, href, title, body) => ["a", { href, title }, ...body],
156
- linkRef: (ctx, refID, body) => [
157
- "a",
158
- {
159
- href: () => ctx.linkRefs[refID]?.[0],
160
- title: () => ctx.linkRefs[refID]?.[1],
161
- },
162
- ...body,
163
- ],
164
- meta: (_, body) => body,
165
- olitem: (_, attribs, index, body) => [
166
- "li",
167
- { ...attribs, __index: index },
168
- ...body,
169
- ],
170
- ol: (_, items, meta) => ["ol", withMeta({}, meta), ...items],
171
- para: (_, body, meta) => ["p", withMeta({}, meta), ...body],
172
- strike: (_, body) => ["s", {}, ...body],
173
- sub: (_, body) => ["sub", {}, body],
174
- sup: (_, body) => ["sup", {}, body],
175
- table: (ctx, head, rows, meta) => [
176
- "table",
177
- withMeta({ __align: ctx.align }, meta),
178
- ["thead", {}, head],
179
- ["tbody", {}, ...rows],
180
- ],
181
- tableCell: (_, body) => ["td", {}, ...body],
182
- tableHead: (_, body) => ["th", {}, ...body],
183
- tableRow: (_, cells) => ["tr", {}, ...cells],
184
- ul: (_, items, meta) => ["ul", withMeta({}, meta), ...items],
185
- ulitem: (_, attribs, body) => ["li", attribs, ...body],
186
- wikiref: (_, id, label) => [
187
- "a",
188
- { class: "wikiref", href: encodeURI(id.replace(/\s+/g, "_")) },
189
- label || id,
190
- ],
108
+ const DEFAULT_TAG_TRANSFORMS = {
109
+ bold: (_, body) => ["strong", {}, ...body],
110
+ blockquote: (_, body, meta) => ["blockquote", withMeta({}, meta), ...body],
111
+ br: () => ["br", {}],
112
+ code: (_, body) => ["code", {}, body],
113
+ codeblock: (_, lang, __head, body, meta) => [
114
+ "pre",
115
+ withMeta({ data: { lang }, __head }, meta),
116
+ ["code", {}, body]
117
+ ],
118
+ custom: (_, type, __head, body, meta) => [
119
+ "custom",
120
+ withMeta({ type, __head }, meta),
121
+ body
122
+ ],
123
+ emoji: (_, id) => EMOJI[id] || id,
124
+ footnote: (_, id, body, meta) => [
125
+ "li",
126
+ withMeta({ id: `fn-${id}` }, meta),
127
+ ["sup", {}, `[${id}] `],
128
+ ...body,
129
+ " ",
130
+ ["a", { href: `#fnref-${id}` }, "\u21A9\uFE0E"]
131
+ ],
132
+ footnoteRef: (_, id) => [
133
+ "sup",
134
+ {},
135
+ ["a", { id: `fnref-${id}`, href: `#fn-${id}` }, `[${id}]`]
136
+ ],
137
+ footnoteWrapper: (_, notes) => [
138
+ "ul",
139
+ { id: "footnotes" },
140
+ ...Object.keys(notes).sort().map((id) => notes[id])
141
+ ],
142
+ heading: (_, level, id, body, meta) => [
143
+ level > 6 ? "p" : `h${level}`,
144
+ withMeta({ id }, meta),
145
+ ...body
146
+ ],
147
+ hr: (_, __length, meta) => ["hr", withMeta({ __length }, meta)],
148
+ img: (_, alt, src, title) => ["img", { src, alt, title }],
149
+ italic: (_, body) => ["em", {}, ...body],
150
+ kbd: (_, key) => ["kbd", {}, key],
151
+ link: (_, href, title, body) => ["a", { href, title }, ...body],
152
+ linkRef: (ctx, refID, body) => [
153
+ "a",
154
+ {
155
+ href: () => ctx.linkRefs[refID]?.[0],
156
+ title: () => ctx.linkRefs[refID]?.[1]
157
+ },
158
+ ...body
159
+ ],
160
+ meta: (_, body) => body,
161
+ olitem: (_, attribs, index, body) => [
162
+ "li",
163
+ { ...attribs, __index: index },
164
+ ...body
165
+ ],
166
+ ol: (_, items, meta) => ["ol", withMeta({}, meta), ...items],
167
+ para: (_, body, meta) => ["p", withMeta({}, meta), ...body],
168
+ strike: (_, body) => ["s", {}, ...body],
169
+ sub: (_, body) => ["sub", {}, body],
170
+ sup: (_, body) => ["sup", {}, body],
171
+ table: (ctx, head, rows, meta) => [
172
+ "table",
173
+ withMeta({ __align: ctx.align }, meta),
174
+ ["thead", {}, head],
175
+ ["tbody", {}, ...rows]
176
+ ],
177
+ tableCell: (_, body) => ["td", {}, ...body],
178
+ tableHead: (_, body) => ["th", {}, ...body],
179
+ tableRow: (_, cells) => ["tr", {}, ...cells],
180
+ ul: (_, items, meta) => ["ul", withMeta({}, meta), ...items],
181
+ ulitem: (_, attribs, body) => ["li", attribs, ...body],
182
+ wikiref: (_, id, label) => [
183
+ "a",
184
+ { class: "wikiref", href: encodeURI(id.replace(/\s+/g, "_")) },
185
+ label || id
186
+ ]
191
187
  };
192
- export class ParseError extends Error {
193
- state;
194
- constructor(state) {
195
- super(state
196
- ? `stopped line: ${state.l}, col: ${state.c} (pos: ${state.p})`
197
- : undefined);
198
- this.state = state;
199
- }
188
+ class ParseError extends Error {
189
+ constructor(state) {
190
+ super(
191
+ state ? `stopped line: ${state.l}, col: ${state.c} (pos: ${state.p})` : void 0
192
+ );
193
+ this.state = state;
194
+ }
200
195
  }
201
- /**
202
- * Parses given Markdown source string into a tree structure defined by given
203
- * {@link TagTransforms}.
204
- *
205
- * @remarks
206
- * The tag transforms are optional and the default implementations can be
207
- * overwritten on tag-by-tag basis. The default transforms yield a simple hiccup
208
- * tree (aka each tag will be an array in the form: `["tagname", {...},
209
- * ...body]`).
210
- *
211
- * See [thi.ng/hiccup](https://thi.ng/hiccup) and related packages for further
212
- * details.
213
- *
214
- * @param src
215
- * @param opts
216
- */
217
- export const parse = (src, { tags, opts, linkRefs, logger, } = {}) => {
218
- const parseCtx = parseRaw(src, opts?.retain);
219
- const mdCtx = defTransformContext(tags, opts, linkRefs, logger);
220
- const result = [];
221
- transformScope(parseCtx.root, mdCtx, result);
222
- return {
223
- result,
224
- ctx: mdCtx,
225
- complete: !!parseCtx.done,
226
- state: parseCtx.state,
227
- };
196
+ const parse = (src, {
197
+ tags,
198
+ opts,
199
+ linkRefs,
200
+ logger
201
+ } = {}) => {
202
+ const parseCtx = parseRaw(src, opts?.retain);
203
+ const mdCtx = defTransformContext(tags, opts, linkRefs, logger);
204
+ const result = [];
205
+ transformScope(parseCtx.root, mdCtx, result);
206
+ return {
207
+ result,
208
+ ctx: mdCtx,
209
+ complete: !!parseCtx.done,
210
+ state: parseCtx.state
211
+ };
228
212
  };
229
- /**
230
- * 1st stage of the parsing (with out result transformations). This calls the
231
- * `main` rule of the provided parse {@link GRAMMAR} and returns a parse
232
- * context, incl. the raw abstract syntax tree of the parsed document. If
233
- * parsing failed entirely (due to invalid input), throws a {@link ParseError}.
234
- *
235
- * @remarks
236
- * Note: Even if the function returns a result, parsing might only have
237
- * partially successful (can be checked via the [`.done`
238
- * flag](https://docs.thi.ng/umbrella/parse/classes/ParseContext.html#done)).
239
- *
240
- * This function is only for advanced use. Mostly you'll probably want to use
241
- * the main {@link parse} function instead.
242
- *
243
- * @param src
244
- * @param retain
245
- */
246
- export const parseRaw = (src, retain = false) => {
247
- const ctx = defContext(src + "\n\n", { retain });
248
- if (!GRAMMAR.rules.main(ctx))
249
- throw new ParseError(ctx.state);
250
- return ctx;
213
+ const parseRaw = (src, retain = false) => {
214
+ const ctx = defContext(src + "\n\n", { retain });
215
+ if (!GRAMMAR.rules.main(ctx))
216
+ throw new ParseError(ctx.state);
217
+ return ctx;
251
218
  };
252
- export const defTransformContext = (tags, opts, linkRefs, logger) => ({
253
- footnotes: {},
254
- headings: [],
255
- linkRefs: linkRefs || {},
256
- hasFootnotes: false,
257
- logger,
258
- meta: null,
259
- align: [],
260
- column: 0,
261
- row: 0,
262
- opts: {
263
- escape: false,
264
- retain: false,
265
- ...opts,
266
- },
267
- tags: { ...DEFAULT_TAG_TRANSFORMS, ...tags },
219
+ const defTransformContext = (tags, opts, linkRefs, logger) => ({
220
+ footnotes: {},
221
+ headings: [],
222
+ linkRefs: linkRefs || {},
223
+ hasFootnotes: false,
224
+ logger,
225
+ meta: null,
226
+ align: [],
227
+ column: 0,
228
+ row: 0,
229
+ opts: {
230
+ escape: false,
231
+ retain: false,
232
+ ...opts
233
+ },
234
+ tags: { ...DEFAULT_TAG_TRANSFORMS, ...tags }
268
235
  });
269
- /**
270
- * Polymorphic & recursive parse scope/node transformation function. Takes a
271
- * single scope, context and accumulator array, then calls itself recursively
272
- * for any child scopes and passes relevant data to its user defined
273
- * {@link TagTransforms} handler and adds result to the accumulator array.
274
- *
275
- */
276
- export const transformScope = defmulti((x, ctx) => {
236
+ const transformScope = defmulti(
237
+ (x, ctx) => {
277
238
  ctx.logger && ctx.logger.debug(x);
278
239
  return x.id;
279
- }, {
240
+ },
241
+ {
280
242
  bqbody: "body",
281
243
  bqlbr: "lbr",
282
244
  bqline: "repeat0",
@@ -287,286 +249,351 @@ export const transformScope = defmulti((x, ctx) => {
287
249
  linkbody: "body",
288
250
  main: "root",
289
251
  repeat1: "repeat0",
290
- tbody: "body",
291
- }, {
252
+ tbody: "body"
253
+ },
254
+ {
292
255
  [DEFAULT]: (scope, ctx) => {
293
- throw new Error(`unknown ID: ${scope.id}, ctx: ${JSON.stringify(ctx)}`);
256
+ throw new Error(
257
+ `unknown ID: ${scope.id}, ctx: ${JSON.stringify(ctx)}`
258
+ );
294
259
  },
295
260
  root: ({ children }, ctx, acc) => {
296
- if (!children)
297
- return;
298
- transformScope(children[0], ctx, acc);
299
- if (ctx.hasFootnotes) {
300
- __collect(acc, ctx.tags.footnoteWrapper(ctx, ctx.footnotes));
301
- }
261
+ if (!children)
262
+ return;
263
+ transformScope(children[0], ctx, acc);
264
+ if (ctx.hasFootnotes) {
265
+ __collect(acc, ctx.tags.footnoteWrapper(ctx, ctx.footnotes));
266
+ }
302
267
  },
303
268
  main: (scope, ctx, acc) => transformScope(scope.children[0], ctx, acc),
304
269
  repeat0: (scope, ctx, acc) => scope.children && __children(ctx, scope.children, acc),
305
270
  body: (scope, ctx, acc) => __collect(acc, __escape(ctx, scope.result)),
306
- bold: (scope, ctx, acc) => __collect(acc, ctx.tags.bold(ctx, __children(ctx, scope.children))),
271
+ bold: (scope, ctx, acc) => __collect(
272
+ acc,
273
+ ctx.tags.bold(ctx, __children(ctx, scope.children))
274
+ ),
307
275
  bquote: (scope, ctx, acc) => {
308
- const stack = [[]];
309
- const children = scope.children[0].children;
310
- const $unwind = (level) => {
311
- while (level < stack.length) {
312
- const nested = stack.pop();
313
- __collect(peek(stack), ctx.tags.blockquote(ctx, __trimBody(nested)));
314
- }
315
- return peek(stack);
316
- };
317
- for (let i = 0, n = children.length - 1; i <= n; i++) {
318
- const [{ result: level }, bqline] = children[i].children;
319
- let body = peek(stack);
320
- if (level > stack.length) {
321
- while (level > stack.length)
322
- stack.push((body = []));
323
- }
324
- else if (level < stack.length) {
325
- body = $unwind(level);
326
- }
327
- else if (body.length) {
328
- const prev = children[i - 1].children[1];
329
- if (!bqline.children) {
330
- __collect(body, ctx.tags.br(ctx));
331
- __collect(body, ctx.tags.br(ctx));
332
- }
333
- else if (prev.children &&
334
- peek(prev.children).id !== "bqlbr") {
335
- body.push(" ");
336
- }
337
- }
338
- transformScope(bqline, ctx, body);
276
+ const stack = [[]];
277
+ const children = scope.children[0].children;
278
+ const $unwind = (level) => {
279
+ while (level < stack.length) {
280
+ const nested = stack.pop();
281
+ __collect(
282
+ peek(stack),
283
+ ctx.tags.blockquote(ctx, __trimBody(nested))
284
+ );
339
285
  }
340
- __collect(acc, ctx.tags.blockquote(ctx, __trimBody($unwind(1)), ctx.meta));
341
- ctx.meta = null;
286
+ return peek(stack);
287
+ };
288
+ for (let i = 0, n = children.length - 1; i <= n; i++) {
289
+ const [{ result: level }, bqline] = children[i].children;
290
+ let body = peek(stack);
291
+ if (level > stack.length) {
292
+ while (level > stack.length)
293
+ stack.push(body = []);
294
+ } else if (level < stack.length) {
295
+ body = $unwind(level);
296
+ } else if (body.length) {
297
+ const prev = children[i - 1].children[1];
298
+ if (!bqline.children) {
299
+ __collect(body, ctx.tags.br(ctx));
300
+ __collect(body, ctx.tags.br(ctx));
301
+ } else if (prev.children && peek(prev.children).id !== "bqlbr") {
302
+ body.push(" ");
303
+ }
304
+ }
305
+ transformScope(bqline, ctx, body);
306
+ }
307
+ __collect(
308
+ acc,
309
+ ctx.tags.blockquote(ctx, __trimBody($unwind(1)), ctx.meta)
310
+ );
311
+ ctx.meta = null;
342
312
  },
343
313
  code: (scope, ctx, acc) => __collect(acc, ctx.tags.code(ctx, __escape(ctx, scope.result))),
344
314
  codeblock: ({ children }, ctx, acc) => {
345
- const [lang, ...head] = children[0].result.split(" ");
346
- const body = children[1].result.trim();
347
- __collect(acc, ctx.tags.codeblock(ctx, lang, head, __escape(ctx, body), ctx.meta));
348
- ctx.meta = null;
315
+ const [lang, ...head] = children[0].result.split(" ");
316
+ const body = children[1].result.trim();
317
+ __collect(
318
+ acc,
319
+ ctx.tags.codeblock(
320
+ ctx,
321
+ lang,
322
+ head,
323
+ __escape(ctx, body),
324
+ ctx.meta
325
+ )
326
+ );
327
+ ctx.meta = null;
349
328
  },
350
329
  customblock: ({ children }, ctx, acc) => {
351
- const [type, ...head] = children[0].result.split(" ");
352
- __collect(acc, ctx.tags.custom(ctx, type, head, children[1].result.trim(), ctx.meta));
353
- ctx.meta = null;
330
+ const [type, ...head] = children[0].result.split(" ");
331
+ __collect(
332
+ acc,
333
+ ctx.tags.custom(
334
+ ctx,
335
+ type,
336
+ head,
337
+ children[1].result.trim(),
338
+ ctx.meta
339
+ )
340
+ );
341
+ ctx.meta = null;
354
342
  },
355
343
  emoji: ({ result }, ctx, acc) => {
356
- if (result[0] === " ") {
357
- __collect(acc, " ");
358
- result = result.substring(1);
359
- }
360
- __collect(acc, ctx.tags.emoji(ctx, result));
344
+ if (result[0] === " ") {
345
+ __collect(acc, " ");
346
+ result = result.substring(1);
347
+ }
348
+ __collect(acc, ctx.tags.emoji(ctx, result));
361
349
  },
362
350
  fnote: ({ children }, ctx) => {
363
- const body = [];
364
- const id = children[0].result;
365
- transformScope(children[1].children[0], ctx, body);
366
- const res = ctx.tags.footnote(ctx, id, body, ctx.meta);
367
- if (res != null) {
368
- ctx.hasFootnotes = true;
369
- ctx.footnotes[id] = res;
370
- }
371
- ctx.meta = null;
351
+ const body = [];
352
+ const id = children[0].result;
353
+ transformScope(children[1].children[0], ctx, body);
354
+ const res = ctx.tags.footnote(ctx, id, body, ctx.meta);
355
+ if (res != null) {
356
+ ctx.hasFootnotes = true;
357
+ ctx.footnotes[id] = res;
358
+ }
359
+ ctx.meta = null;
372
360
  },
373
- fnref: (scope, ctx, acc) => __collect(acc, ctx.tags.footnoteRef(ctx, scope.children[0].result)),
361
+ fnref: (scope, ctx, acc) => __collect(
362
+ acc,
363
+ ctx.tags.footnoteRef(ctx, scope.children[0].result)
364
+ ),
374
365
  hd: ({ children }, ctx, acc) => {
375
- const body = [];
376
- const level = children[0].result;
377
- transformScope(children[1], ctx, body);
378
- __trimBody(body);
379
- const slug = children[2]?.result || slugifyGH(extractBody(body).join(""));
380
- ctx.headings.push({ level, body });
381
- __collect(acc, ctx.tags.heading(ctx, level, slug, body, ctx.meta));
382
- ctx.meta = null;
366
+ const body = [];
367
+ const level = children[0].result;
368
+ transformScope(children[1], ctx, body);
369
+ __trimBody(body);
370
+ const slug = children[2]?.result || slugifyGH(extractBody(body).join(""));
371
+ ctx.headings.push({ level, body });
372
+ __collect(acc, ctx.tags.heading(ctx, level, slug, body, ctx.meta));
373
+ ctx.meta = null;
383
374
  },
384
375
  hr: (scope, ctx, acc) => {
385
- __collect(acc, ctx.tags.hr(ctx, scope.result.length, ctx.meta));
386
- ctx.meta = null;
376
+ __collect(acc, ctx.tags.hr(ctx, scope.result.length, ctx.meta));
377
+ ctx.meta = null;
387
378
  },
388
- img: ({ children }, ctx, acc) => __collect(acc, ctx.tags.img(ctx, __escape(ctx, children[0].result.trim()), ...__linkTitle(children[1].result))),
389
- italic: (scope, ctx, acc) => __collect(acc, ctx.tags.italic(ctx, __children(ctx, scope.children))),
379
+ img: ({ children }, ctx, acc) => __collect(
380
+ acc,
381
+ ctx.tags.img(
382
+ ctx,
383
+ __escape(ctx, children[0].result.trim()),
384
+ ...__linkTitle(children[1].result)
385
+ )
386
+ ),
387
+ italic: (scope, ctx, acc) => __collect(
388
+ acc,
389
+ ctx.tags.italic(ctx, __children(ctx, scope.children))
390
+ ),
390
391
  kbd: (scope, ctx, acc) => __collectPrim(scope, ctx, acc, "kbd"),
391
392
  lbr: (_, ctx, acc) => __collect(acc, ctx.tags.br(ctx)),
392
- link: ({ children }, ctx, acc) => __collect(acc, ctx.tags.link(ctx, ...__linkTitle(children[1].result), __children(ctx, children[0].children))),
393
+ link: ({ children }, ctx, acc) => __collect(
394
+ acc,
395
+ ctx.tags.link(
396
+ ctx,
397
+ ...__linkTitle(children[1].result),
398
+ __children(ctx, children[0].children)
399
+ )
400
+ ),
393
401
  linkdef: ({ children }, ctx) => {
394
- ctx.linkRefs[children[0].result] = __linkTitle(children[1].result);
402
+ ctx.linkRefs[children[0].result] = __linkTitle(
403
+ children[1].result
404
+ );
395
405
  },
396
- linkref: ({ children }, ctx, acc) => __collect(acc, ctx.tags.linkRef(ctx, children[1].result, __children(ctx, children[0].children))),
406
+ linkref: ({ children }, ctx, acc) => __collect(
407
+ acc,
408
+ ctx.tags.linkRef(
409
+ ctx,
410
+ children[1].result,
411
+ __children(ctx, children[0].children)
412
+ )
413
+ ),
397
414
  list: (scope, ctx, acc) => {
398
- const children = scope.children[0].children;
399
- const stack = [
400
- [children[0].id === "ulitem" ? "ul" : "ol"],
401
- ];
402
- const levels = [0];
403
- for (let item of children) {
404
- const currLevel = item.children[0].result;
405
- if (currLevel > peek(levels)) {
406
- const sublist = [item.id === "ulitem" ? "ul" : "ol"];
407
- const parent = peek(stack);
408
- parent.length > 1
409
- ? peek(parent).push(sublist)
410
- : parent.push([
411
- parent[0] === "ul" ? "ulitem" : "olitem",
412
- {},
413
- sublist,
414
- ]);
415
- stack.push(sublist);
416
- levels.push(currLevel);
417
- }
418
- else if (currLevel < peek(levels)) {
419
- while (currLevel < peek(levels)) {
420
- stack.pop();
421
- levels.pop();
422
- }
423
- }
424
- transformScope(item, ctx, peek(stack));
415
+ const children = scope.children[0].children;
416
+ const stack = [
417
+ [children[0].id === "ulitem" ? "ul" : "ol"]
418
+ ];
419
+ const levels = [0];
420
+ for (let item of children) {
421
+ const currLevel = item.children[0].result;
422
+ if (currLevel > peek(levels)) {
423
+ const sublist = [item.id === "ulitem" ? "ul" : "ol"];
424
+ const parent = peek(stack);
425
+ parent.length > 1 ? peek(parent).push(sublist) : parent.push([
426
+ parent[0] === "ul" ? "ulitem" : "olitem",
427
+ {},
428
+ sublist
429
+ ]);
430
+ stack.push(sublist);
431
+ levels.push(currLevel);
432
+ } else if (currLevel < peek(levels)) {
433
+ while (currLevel < peek(levels)) {
434
+ stack.pop();
435
+ levels.pop();
436
+ }
425
437
  }
426
- const $list = (root, isRoot = false) => ctx.tags[root[0]](ctx, root.slice(1).map($item), isRoot ? ctx.meta : null);
427
- const $item = (item) => {
428
- let last = item[item.length - 1];
429
- if (last[0] === "ul" || last[0] === "ol")
430
- item[item.length - 1] = $list(last);
431
- return item[0] === "ulitem"
432
- ? ctx.tags.ulitem(ctx, item[1], item.slice(2))
433
- : ctx.tags.olitem(ctx, item[1], item[2], item.slice(3));
434
- };
435
- __collect(acc, $list(stack[0], true));
436
- ctx.meta = null;
438
+ transformScope(item, ctx, peek(stack));
439
+ }
440
+ const $list = (root, isRoot = false) => ctx.tags[root[0]](
441
+ ctx,
442
+ root.slice(1).map($item),
443
+ isRoot ? ctx.meta : null
444
+ );
445
+ const $item = (item) => {
446
+ let last = item[item.length - 1];
447
+ if (last[0] === "ul" || last[0] === "ol")
448
+ item[item.length - 1] = $list(last);
449
+ return item[0] === "ulitem" ? ctx.tags.ulitem(ctx, item[1], item.slice(2)) : ctx.tags.olitem(ctx, item[1], item[2], item.slice(3));
450
+ };
451
+ __collect(acc, $list(stack[0], true));
452
+ ctx.meta = null;
437
453
  },
438
454
  metablock: ({ children }, ctx) => {
439
- ctx.meta = ctx.tags.meta(ctx, children[0].result.trim());
455
+ ctx.meta = ctx.tags.meta(ctx, children[0].result.trim());
440
456
  },
441
457
  olitem: ({ children }, ctx, acc) => {
442
- const body = [];
443
- transformScope(children[3], ctx, body);
444
- __collect(acc, [
445
- "olitem",
446
- __listItemAttribs(children[2]),
447
- children[1].result,
448
- ...__trimBody(body),
449
- ]);
458
+ const body = [];
459
+ transformScope(children[3], ctx, body);
460
+ __collect(acc, [
461
+ "olitem",
462
+ __listItemAttribs(children[2]),
463
+ children[1].result,
464
+ ...__trimBody(body)
465
+ ]);
450
466
  },
451
467
  para: (scope, ctx, acc) => {
452
- __collect(acc, ctx.tags.para(ctx, __trimBody(__children(ctx, scope.children)), ctx.meta));
453
- ctx.meta = null;
468
+ __collect(
469
+ acc,
470
+ ctx.tags.para(
471
+ ctx,
472
+ __trimBody(__children(ctx, scope.children)),
473
+ ctx.meta
474
+ )
475
+ );
476
+ ctx.meta = null;
454
477
  },
455
- strike: (scope, ctx, acc) => __collect(acc, ctx.tags.strike(ctx, __children(ctx, scope.children))),
478
+ strike: (scope, ctx, acc) => __collect(
479
+ acc,
480
+ ctx.tags.strike(ctx, __children(ctx, scope.children))
481
+ ),
456
482
  sub: (scope, ctx, acc) => __collectPrim(scope, ctx, acc, "sub"),
457
483
  sup: (scope, ctx, acc) => __collectPrim(scope, ctx, acc, "sup"),
458
484
  table: (scope, ctx, acc) => {
459
- const children = scope.children[0].children;
460
- const head = [];
461
- const rows = [];
462
- ctx.row = 0;
463
- if (children.length > 1) {
464
- ctx.align = __columnAlignments(children[1].children[0].children);
465
- for (let i = 2, n = children.length; i < n; i++) {
466
- ctx.row = i - 1;
467
- transformScope(children[i], ctx, rows);
468
- }
469
- }
470
- else {
471
- ctx.align = new Array(children[0].children[0].children.length).fill("left");
485
+ const children = scope.children[0].children;
486
+ const head = [];
487
+ const rows = [];
488
+ ctx.row = 0;
489
+ if (children.length > 1) {
490
+ ctx.align = __columnAlignments(
491
+ children[1].children[0].children
492
+ );
493
+ for (let i = 2, n = children.length; i < n; i++) {
494
+ ctx.row = i - 1;
495
+ transformScope(children[i], ctx, rows);
472
496
  }
473
- ctx.row = 0;
474
- transformScope(children[0], ctx, head);
475
- __collect(acc, ctx.tags.table(ctx, head[0], rows, ctx.meta));
476
- ctx.meta = null;
497
+ } else {
498
+ ctx.align = new Array(
499
+ children[0].children[0].children.length
500
+ ).fill("left");
501
+ }
502
+ ctx.row = 0;
503
+ transformScope(children[0], ctx, head);
504
+ __collect(acc, ctx.tags.table(ctx, head[0], rows, ctx.meta));
505
+ ctx.meta = null;
477
506
  },
478
- tcell: ({ children }, ctx, acc) => __collect(acc, (ctx.row > 0 ? ctx.tags.tableCell : ctx.tags.tableHead)(ctx, __trimBody(__children(ctx, children)))),
507
+ tcell: ({ children }, ctx, acc) => __collect(
508
+ acc,
509
+ (ctx.row > 0 ? ctx.tags.tableCell : ctx.tags.tableHead)(
510
+ ctx,
511
+ __trimBody(__children(ctx, children))
512
+ )
513
+ ),
479
514
  trow: (scope, ctx, acc) => {
480
- const cells = [];
481
- scope.children[0].children.forEach((c, i) => {
482
- ctx.column = i;
483
- transformScope(c, ctx, cells);
484
- });
485
- __collect(acc, ctx.tags.tableRow(ctx, cells));
515
+ const cells = [];
516
+ scope.children[0].children.forEach((c, i) => {
517
+ ctx.column = i;
518
+ transformScope(c, ctx, cells);
519
+ });
520
+ __collect(acc, ctx.tags.tableRow(ctx, cells));
486
521
  },
487
522
  ulitem: ({ children }, ctx, acc) => {
488
- const body = [];
489
- transformScope(children[2], ctx, body);
490
- __collect(acc, [
491
- "ulitem",
492
- __listItemAttribs(children[1]),
493
- ...__trimBody(body),
494
- ]);
523
+ const body = [];
524
+ transformScope(children[2], ctx, body);
525
+ __collect(acc, [
526
+ "ulitem",
527
+ __listItemAttribs(children[1]),
528
+ ...__trimBody(body)
529
+ ]);
495
530
  },
496
531
  wikiref: (scope, ctx, acc) => {
497
- const [id, label] = scope.result.split("|");
498
- __collect(acc, ctx.tags.wikiref(ctx, id.trim(), label?.trim()));
499
- },
500
- });
501
- /**
502
- * Takes an attributes object and optional metadata. If `meta` is not nullish,
503
- * assigns it as `__meta` key in given object. Returns object.
504
- *
505
- * @param target
506
- * @param meta
507
- */
508
- export const withMeta = (target, meta) => {
509
- if (meta != null)
510
- target.__meta = meta;
511
- return target;
512
- };
513
- /**
514
- * Takes a hiccup tree and extracts only the primitive body values (strings,
515
- * numbers, booleans) and returns them as array.
516
- *
517
- * @param body
518
- * @param acc
519
- */
520
- export const extractBody = (body, acc = []) => {
521
- for (let x of isPlainObject(body[1]) ? body.slice(2) : body) {
522
- if (isPrimitive(x))
523
- acc.push(x);
524
- else if (isArray(x))
525
- extractBody(x, acc);
532
+ const [id, label] = scope.result.split("|");
533
+ __collect(acc, ctx.tags.wikiref(ctx, id.trim(), label?.trim()));
526
534
  }
527
- return acc;
535
+ }
536
+ );
537
+ const withMeta = (target, meta) => {
538
+ if (meta != null)
539
+ target.__meta = meta;
540
+ return target;
541
+ };
542
+ const extractBody = (body, acc = []) => {
543
+ for (let x of isPlainObject(body[1]) ? body.slice(2) : body) {
544
+ if (isPrimitive(x))
545
+ acc.push(x);
546
+ else if (isArray(x))
547
+ extractBody(x, acc);
548
+ }
549
+ return acc;
528
550
  };
529
- /** @internal */
530
551
  const __collect = (acc, x) => x != null && acc.push(x);
531
552
  const __collectPrim = (scope, ctx, acc, tag) => __collect(acc, ctx.tags[tag](ctx, scope.result));
532
- /** @internal */
533
553
  const __children = (ctx, children, acc = []) => {
534
- for (let c of children)
535
- transformScope(c, ctx, acc);
536
- return acc;
554
+ for (let c of children)
555
+ transformScope(c, ctx, acc);
556
+ return acc;
537
557
  };
538
- /** @internal */
539
558
  const __escape = (ctx, x) => ctx.opts.escape ? escapeEntities(x) : x;
540
- /** @internal */
541
- const __listItemAttribs = (scope) => scope?.id === "todo"
542
- ? {
543
- __todo: true,
544
- __done: scope.result === "x",
545
- }
546
- : {};
547
- /** @internal */
559
+ const __listItemAttribs = (scope) => scope?.id === "todo" ? {
560
+ __todo: true,
561
+ __done: scope.result === "x"
562
+ } : {};
548
563
  const __trimBody = (body) => {
549
- if (body.length === 1 && isString(body[0]))
550
- body[0] = body[0].trim();
551
- else {
552
- const last = peek(body);
553
- if (isString(last) && /^\s+$/.test(last))
554
- body.pop();
555
- }
556
- return body;
564
+ if (body.length === 1 && isString(body[0]))
565
+ body[0] = body[0].trim();
566
+ else {
567
+ const last = peek(body);
568
+ if (isString(last) && /^\s+$/.test(last))
569
+ body.pop();
570
+ }
571
+ return body;
557
572
  };
558
- /** @internal */
559
573
  const __columnAlignments = (children) => {
560
- const align = [];
561
- for (let c of children) {
562
- const raw = c.children[0].children[0].result.trim();
563
- const isLeft = raw.startsWith(":-") ? 1 : 0;
564
- const isRight = raw.endsWith("-:") ? 2 : 0;
565
- align.push((["default", "left", "right", "center"][isLeft | isRight]));
566
- }
567
- return align;
574
+ const align = [];
575
+ for (let c of children) {
576
+ const raw = c.children[0].children[0].result.trim();
577
+ const isLeft = raw.startsWith(":-") ? 1 : 0;
578
+ const isRight = raw.endsWith("-:") ? 2 : 0;
579
+ align.push(
580
+ ["default", "left", "right", "center"][isLeft | isRight]
581
+ );
582
+ }
583
+ return align;
568
584
  };
569
585
  const __linkTitle = (src) => {
570
- const match = /\s"(.+)"$/.exec(src);
571
- return match ? [src.substring(0, match.index), match[1]] : [src, undefined];
586
+ const match = /\s"(.+)"$/.exec(src);
587
+ return match ? [src.substring(0, match.index), match[1]] : [src, void 0];
588
+ };
589
+ export {
590
+ DEFAULT_TAG_TRANSFORMS,
591
+ GRAMMAR,
592
+ ParseError,
593
+ defTransformContext,
594
+ extractBody,
595
+ parse,
596
+ parseRaw,
597
+ transformScope,
598
+ withMeta
572
599
  };
package/serialize.js CHANGED
@@ -10,66 +10,77 @@ import { wrap } from "@thi.ng/strings/wrap";
10
10
  import { Border } from "@thi.ng/text-canvas/api";
11
11
  import { formatCanvas } from "@thi.ng/text-canvas/format";
12
12
  import { tableCanvas } from "@thi.ng/text-canvas/table";
13
- export const serialize = (tree, ctx) => __serialize(tree, ctx, { indent: 0, sep: "" })
14
- .replace(/\n{3,}/g, "\n\n")
15
- .trim();
13
+ const serialize = (tree, ctx) => __serialize(tree, ctx, { indent: 0, sep: "" }).replace(/\n{3,}/g, "\n\n").trim();
16
14
  const __serialize = (tree, ctx, state) => {
17
- if (tree == null)
18
- return "";
19
- if (Array.isArray(tree)) {
20
- if (!tree.length) {
21
- return "";
22
- }
23
- let tag = tree[0];
24
- if (isFunction(tag)) {
25
- return __serialize(tag.apply(null, [ctx, ...tree.slice(1)]), ctx, state);
26
- }
27
- if (implementsFunction(tag, "render")) {
28
- return __serialize(tag.render.apply(null, [ctx, ...tree.slice(1)]), ctx, state);
29
- }
30
- if (isString(tag)) {
31
- tree = normalize(tree);
32
- const attribs = tree[1];
33
- if (attribs.__skip || attribs.__serialize === false) {
34
- return "";
35
- }
36
- tag = tree[0];
37
- return serializeElement(tree, ctx, state);
38
- }
39
- if (isNotStringAndIterable(tree)) {
40
- return __serializeIter(tree, ctx, state);
41
- }
42
- illegalArgs(`invalid tree node: ${tree}`);
15
+ if (tree == null)
16
+ return "";
17
+ if (Array.isArray(tree)) {
18
+ if (!tree.length) {
19
+ return "";
43
20
  }
44
- if (isFunction(tree)) {
45
- return __serialize(tree(ctx), ctx, state);
21
+ let tag = tree[0];
22
+ if (isFunction(tag)) {
23
+ return __serialize(
24
+ tag.apply(null, [ctx, ...tree.slice(1)]),
25
+ ctx,
26
+ state
27
+ );
46
28
  }
47
- if (implementsFunction(tree, "toHiccup")) {
48
- return __serialize(tree.toHiccup(ctx), ctx, state);
29
+ if (implementsFunction(tag, "render")) {
30
+ return __serialize(
31
+ tag.render.apply(null, [ctx, ...tree.slice(1)]),
32
+ ctx,
33
+ state
34
+ );
49
35
  }
50
- if (implementsFunction(tree, "deref")) {
51
- return __serialize(tree.deref(), ctx, state);
36
+ if (isString(tag)) {
37
+ tree = normalize(tree);
38
+ const attribs = tree[1];
39
+ if (attribs.__skip || attribs.__serialize === false) {
40
+ return "";
41
+ }
42
+ tag = tree[0];
43
+ return serializeElement(tree, ctx, state);
52
44
  }
53
45
  if (isNotStringAndIterable(tree)) {
54
- return __serializeIter(tree, ctx, state);
46
+ return __serializeIter(tree, ctx, state);
55
47
  }
56
- return tree.toString();
48
+ illegalArgs(`invalid tree node: ${tree}`);
49
+ }
50
+ if (isFunction(tree)) {
51
+ return __serialize(tree(ctx), ctx, state);
52
+ }
53
+ if (implementsFunction(tree, "toHiccup")) {
54
+ return __serialize(tree.toHiccup(ctx), ctx, state);
55
+ }
56
+ if (implementsFunction(tree, "deref")) {
57
+ return __serialize(tree.deref(), ctx, state);
58
+ }
59
+ if (isNotStringAndIterable(tree)) {
60
+ return __serializeIter(tree, ctx, state);
61
+ }
62
+ return tree.toString();
57
63
  };
58
64
  const __serializeIter = (iter, ctx, state) => {
59
- if (!iter)
60
- return "";
61
- const res = [];
62
- for (let i of iter) {
63
- res.push(__serialize(i, ctx, state));
64
- }
65
- return res.join(state.sep);
65
+ if (!iter)
66
+ return "";
67
+ const res = [];
68
+ for (let i of iter) {
69
+ res.push(__serialize(i, ctx, state));
70
+ }
71
+ return res.join(state.sep);
66
72
  };
67
- const __heading = (level) => (el, ctx, state) => `\n${repeat("#", level)} ${__body(el, ctx, state)}\n`;
73
+ const __heading = (level) => (el, ctx, state) => `
74
+ ${repeat("#", level)} ${__body(el, ctx, state)}
75
+ `;
68
76
  const __body = (el, ctx, state) => __serializeIter(el[2], ctx, state);
69
- const __resolve = (x) => (isFunction(x) ? x() : x);
70
- export const serializeElement = defmulti((el) => el[0], {
71
- th: "strong",
72
- }, {
77
+ const __resolve = (x) => isFunction(x) ? x() : x;
78
+ const serializeElement = defmulti(
79
+ (el) => el[0],
80
+ {
81
+ th: "strong"
82
+ },
83
+ {
73
84
  [DEFAULT]: __body,
74
85
  h1: __heading(1),
75
86
  h2: __heading(2),
@@ -77,87 +88,104 @@ export const serializeElement = defmulti((el) => el[0], {
77
88
  h4: __heading(4),
78
89
  h5: __heading(5),
79
90
  h6: __heading(6),
80
- p: (el, ctx, state) => `\n${__body(el, ctx, state)}\n`,
91
+ p: (el, ctx, state) => `
92
+ ${__body(el, ctx, state)}
93
+ `,
81
94
  img: (el) => `![${el[1].alt || ""}](${el[1].src})`,
82
95
  a: (el, ctx, state) => {
83
- let { href, title } = el[1];
84
- title = __resolve(title);
85
- return `[${__body(el, ctx, state)}](${__resolve(href)}${title ? ` "${title}"` : ""})`;
96
+ let { href, title } = el[1];
97
+ title = __resolve(title);
98
+ return `[${__body(el, ctx, state)}](${__resolve(href)}${title ? ` "${title}"` : ""})`;
86
99
  },
87
100
  em: (el, ctx, state) => `_${__body(el, ctx, state)}_`,
88
101
  strong: (el, ctx, state) => `**${__body(el, ctx, state)}**`,
89
- pre: (el, ctx, state) => `\n\`\`\`${el[1].lang || ""}\n${__body(el, ctx, {
90
- ...state,
91
- pre: true,
92
- sep: "\n",
93
- })}\n\`\`\`\n`,
102
+ pre: (el, ctx, state) => `
103
+ \`\`\`${el[1].lang || ""}
104
+ ${__body(el, ctx, {
105
+ ...state,
106
+ pre: true,
107
+ sep: "\n"
108
+ })}
109
+ \`\`\`
110
+ `,
94
111
  code: (el, ctx, state) => state.pre ? el[2][0] : `\`${__body(el, ctx, state)}\``,
95
112
  ul: (el, ctx, state) => {
96
- const cstate = {
97
- ...state,
98
- indent: state.indent + 4,
99
- sep: "\n",
100
- };
101
- return wrap(state.indent === 0 ? "\n" : "")(__body(el, ctx, cstate));
113
+ const cstate = {
114
+ ...state,
115
+ indent: state.indent + 4,
116
+ sep: "\n"
117
+ };
118
+ return wrap(state.indent === 0 ? "\n" : "")(
119
+ __body(el, ctx, cstate)
120
+ );
102
121
  },
103
122
  ol: (el, ctx, state) => {
104
- const cstate = {
105
- ...state,
106
- indent: state.indent + 4,
107
- id: 0,
108
- sep: "\n",
109
- };
110
- return wrap(state.indent === 0 ? "\n" : "")(__body(el, ctx, cstate));
111
- },
112
- li: (el, ctx, state) => repeat(" ", state.indent - 4) +
113
- (state.id != null ? ++state.id + "." : "-") +
114
- " " +
115
- __body(el, ctx, { ...state, sep: "" }),
116
- blockquote: (el, ctx, state) => `\n${repeat(">", state.indent + 1)} ${__body(el, ctx, {
123
+ const cstate = {
117
124
  ...state,
118
- indent: state.indent + 1,
119
- blockquote: true,
120
- })}\n`,
121
- br: (_, __, state) => state.blockquote ? `\\\n${repeat(">", state.indent)} ` : "\\\n",
125
+ indent: state.indent + 4,
126
+ id: 0,
127
+ sep: "\n"
128
+ };
129
+ return wrap(state.indent === 0 ? "\n" : "")(
130
+ __body(el, ctx, cstate)
131
+ );
132
+ },
133
+ li: (el, ctx, state) => repeat(" ", state.indent - 4) + (state.id != null ? ++state.id + "." : "-") + " " + __body(el, ctx, { ...state, sep: "" }),
134
+ blockquote: (el, ctx, state) => `
135
+ ${repeat(">", state.indent + 1)} ${__body(el, ctx, {
136
+ ...state,
137
+ indent: state.indent + 1,
138
+ blockquote: true
139
+ })}
140
+ `,
141
+ br: (_, __, state) => state.blockquote ? `\\
142
+ ${repeat(">", state.indent)} ` : "\\\n",
122
143
  hr: () => "\n---\n",
123
144
  table: (el, ctx, state) => {
124
- let caption = "";
125
- let thead = [];
126
- let tbody = [];
127
- let colWidths = [];
128
- const rows = (rows) => rows.map((x) => normalize(x)[2].map((td, i) => {
129
- const cell = serialize(td, ctx);
130
- colWidths[i] = Math.max(colWidths[i] || 3, cell.length);
131
- return cell;
132
- }));
133
- for (let child of el[2]) {
134
- child = normalize(child);
135
- switch (child[0]) {
136
- case "thead":
137
- thead = rows(child[2]);
138
- break;
139
- case "tbody":
140
- tbody = rows(child[2]);
141
- break;
142
- case "caption":
143
- caption = __body(child, ctx, state);
144
- break;
145
- default:
146
- // TODO output warning?
147
- }
145
+ let caption = "";
146
+ let thead = [];
147
+ let tbody = [];
148
+ let colWidths = [];
149
+ const rows = (rows2) => rows2.map(
150
+ (x) => normalize(x)[2].map((td, i) => {
151
+ const cell = serialize(td, ctx);
152
+ colWidths[i] = Math.max(colWidths[i] || 3, cell.length);
153
+ return cell;
154
+ })
155
+ );
156
+ for (let child of el[2]) {
157
+ child = normalize(child);
158
+ switch (child[0]) {
159
+ case "thead":
160
+ thead = rows(child[2]);
161
+ break;
162
+ case "tbody":
163
+ tbody = rows(child[2]);
164
+ break;
165
+ case "caption":
166
+ caption = __body(child, ctx, state);
167
+ break;
168
+ default:
148
169
  }
149
- return ("\n" +
150
- formatCanvas(tableCanvas({
151
- cols: colWidths.map((width) => ({ width })),
152
- padding: [1, 0],
153
- border: Border.V,
154
- }, [
155
- ...thead,
156
- colWidths.map((w) => repeat("-", w)),
157
- ...tbody,
158
- ])) +
159
- "\n" +
160
- caption +
161
- "\n");
162
- },
163
- });
170
+ }
171
+ return "\n" + formatCanvas(
172
+ tableCanvas(
173
+ {
174
+ cols: colWidths.map((width) => ({ width })),
175
+ padding: [1, 0],
176
+ border: Border.V
177
+ },
178
+ [
179
+ ...thead,
180
+ colWidths.map((w) => repeat("-", w)),
181
+ ...tbody
182
+ ]
183
+ )
184
+ ) + "\n" + caption + "\n";
185
+ }
186
+ }
187
+ );
188
+ export {
189
+ serialize,
190
+ serializeElement
191
+ };