@thi.ng/hiccup-markdown 3.1.0 → 3.2.0
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 +26 -1
- package/README.md +107 -42
- package/api.d.ts +31 -10
- package/package.json +6 -3
- package/parse.js +89 -57
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2023-03-
|
|
3
|
+
- **Last updated**: 2023-03-07T14:54:11Z
|
|
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.
|
|
@@ -9,6 +9,31 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
## [3.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/hiccup-markdown@3.2.0) (2023-03-07)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- update parse grammar ([e0be40a](https://github.com/thi-ng/umbrella/commit/e0be40a))
|
|
17
|
+
- char escapes now usable in almost all situs
|
|
18
|
+
(excl. metadata for code/custom blocks)
|
|
19
|
+
- add support for these HTML tags:
|
|
20
|
+
- comments `<!-- ... -->`
|
|
21
|
+
- `<sub>` / `<sup>`
|
|
22
|
+
- add tests
|
|
23
|
+
- update parse grammar & handlers ([7bd4edb](https://github.com/thi-ng/umbrella/commit/7bd4edb))
|
|
24
|
+
- update TransformCtx, add .column & .align fields
|
|
25
|
+
- update table row/cell handlers
|
|
26
|
+
- update olitem handler (index now a string)
|
|
27
|
+
- this is to support alphabetical ordered lists
|
|
28
|
+
- add `<sub>`/`<sup>` handlers
|
|
29
|
+
- update tests
|
|
30
|
+
- update docs
|
|
31
|
+
- update char escapes & inline format nesting rules ([2fde69b](https://github.com/thi-ng/umbrella/commit/2fde69b))
|
|
32
|
+
- allow nested kbd/sub/sup elements
|
|
33
|
+
- update char escape rules for inline code, codeblocks, custom blocks & meta blocks
|
|
34
|
+
- update __trimBody() helper to remove isolate trailing WS
|
|
35
|
+
- add/update tests
|
|
36
|
+
|
|
12
37
|
## [3.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/hiccup-markdown@3.1.0) (2023-03-05)
|
|
13
38
|
|
|
14
39
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -13,11 +13,15 @@ This project is part of the
|
|
|
13
13
|
- [Parser](#parser)
|
|
14
14
|
- [Basic features](#basic-features)
|
|
15
15
|
- [Additional syntax & parser features/restrictions](#additional-syntax--parser-featuresrestrictions)
|
|
16
|
-
- [
|
|
17
|
-
- [Code block headers](#code-block-headers)
|
|
16
|
+
- [Code blocks](#code-blocks)
|
|
18
17
|
- [Custom blocks](#custom-blocks)
|
|
18
|
+
- [Escaping control characters](#escaping-control-characters)
|
|
19
|
+
- [Formatting](#formatting)
|
|
19
20
|
- [Headings with anchor IDs](#headings-with-anchor-ids)
|
|
20
21
|
- [Heading with anchor {#custom-id-123}](#heading-with-anchor-custom-id-123)
|
|
22
|
+
- [Images](#images)
|
|
23
|
+
- [Link formats](#link-formats)
|
|
24
|
+
- [Lists](#lists)
|
|
21
25
|
- [Metadata](#metadata)
|
|
22
26
|
- [Customizing tag transforms](#customizing-tag-transforms)
|
|
23
27
|
- [Serializing to HTML](#serializing-to-html)
|
|
@@ -26,6 +30,7 @@ This project is part of the
|
|
|
26
30
|
- [Behaviors](#behaviors)
|
|
27
31
|
- [Usage examples](#usage-examples)
|
|
28
32
|
- [Status](#status)
|
|
33
|
+
- [Related packages](#related-packages)
|
|
29
34
|
- [Installation](#installation)
|
|
30
35
|
- [Dependencies](#dependencies)
|
|
31
36
|
- [Usage examples](#usage-examples)
|
|
@@ -37,7 +42,8 @@ This project is part of the
|
|
|
37
42
|
|
|
38
43
|
Markdown parser & serializer from/to Hiccup format. This is a support package for [@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/develop/packages/hiccup).
|
|
39
44
|
|
|
40
|
-
**⚠️ IMPORTANT: With v3.0.0 the parser implementation underwent a complete
|
|
45
|
+
**⚠️ IMPORTANT: With v3.0.0 the parser implementation underwent a complete
|
|
46
|
+
rewrite (with breaking changes, but lots of improvements). ⚠️**
|
|
41
47
|
|
|
42
48
|
This package provides both a customizable
|
|
43
49
|
[Markdown](https://en.wikipedia.org/wiki/Markdown)-to-[Hiccup](https://github.com/thi-ng/umbrella/tree/develop/packages/hiccup)
|
|
@@ -45,48 +51,47 @@ parser and an extensible Hiccup-to-Markdown converter.
|
|
|
45
51
|
|
|
46
52
|
## Parser
|
|
47
53
|
|
|
54
|
+
Sadly, none of the available Markdown flavors have ever been designed with much
|
|
55
|
+
consistency and/or ease-of-implementation/parsing aspects in mind. The result is
|
|
56
|
+
a proliferation of Markdown-ish flavors, even though there've been attempts to
|
|
57
|
+
standardize the syntax.
|
|
58
|
+
|
|
48
59
|
### Basic features
|
|
49
60
|
|
|
50
|
-
The parser
|
|
51
|
-
|
|
52
|
-
features and some useful [additional
|
|
61
|
+
The parser provided here is _not_ aimed at supporting **all** of Markdown's (or
|
|
62
|
+
CommonMark's) quirky syntax features, but restricts itself to a large _sane
|
|
63
|
+
subset_ of features and some useful [additional
|
|
53
64
|
features](#additional-syntax--parser-featuresrestrictions) not part of the
|
|
54
|
-
standard syntax.
|
|
55
|
-
|
|
56
|
-
| Feature | Comments
|
|
57
|
-
|
|
58
|
-
| Blockquotes | Nestable, support for inline formatting and forced line breaks (trailing
|
|
59
|
-
| Code blocks | GFM style only (triple backtick prefix), w/ mandatory language hint & optional extra headers information
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
65
|
+
standard/common syntax.
|
|
66
|
+
|
|
67
|
+
| Feature | Comments |
|
|
68
|
+
|---------------|-------------------------------------------------------------------------------------------------------------------------|
|
|
69
|
+
| Blockquotes | Nestable, support for inline formatting and forced line breaks (trailing backslash) |
|
|
70
|
+
| Code blocks | GFM style only (triple backtick prefix), w/ mandatory language hint & optional extra headers information |
|
|
71
|
+
| Escaping | Uniformly escape MD control characters via backslash, e.g. `\*` |
|
|
72
|
+
| Formatting | Nestable inline formats supported in paragraphs, headings, link labels, lists, blockquotes, tables: |
|
|
73
|
+
| | **bold**, _italic_, `code`, ~~strike~~ |
|
|
74
|
+
| | <kbd>Key</kbd>, <sub>subscript</sub> and <sup>super</sup> |
|
|
75
|
+
| Footnotes | Supported and stored separately in parse context for further processing |
|
|
76
|
+
| Headings | ATX-style only (`#` line prefix), optional anchor ID (via `{#custom-id}` suffix), levels 1-6 then fallback to paragraph |
|
|
77
|
+
| Horiz. Rulers | Only dash supported (e.g. `---`), min 3 chars required, length retained for downstream transformations |
|
|
78
|
+
| HTML elements | Only `<kbd>`, `<sub>` `<sup>` |
|
|
79
|
+
| Images | Alt text is required, image can be used in link labels, optional title suffix |
|
|
80
|
+
| Links | Supports `[label](target)`, `[label][ref]`, `[[page id]]` or `[[page id\|label]]` style links, inline formats in label |
|
|
81
|
+
| Lists | Ordered & unordered, nestable, inline formatting, line breaks, GFM todo list items |
|
|
82
|
+
| Paragraphs | Support for forced line breaks (trailing backslash) |
|
|
83
|
+
| Tables | Support for column alignments, nestable inline formatting (no nested block elements) |
|
|
84
|
+
|
|
85
|
+
**Please visit the [interactive Markdown parser/editor
|
|
86
|
+
playground](https://demo.thi.ng/umbrella/markdown/) for further
|
|
87
|
+
details/examples...**
|
|
70
88
|
|
|
71
89
|
### Additional syntax & parser features/restrictions
|
|
72
90
|
|
|
73
|
-
####
|
|
74
|
-
|
|
75
|
-
To avoid ambiguity and simplify nesting, only the following formatting syntax is
|
|
76
|
-
supported for bold & italic:
|
|
77
|
-
|
|
78
|
-
- `**bold**`
|
|
79
|
-
- `_italic_`
|
|
80
|
-
|
|
81
|
-
`code` (\`) and ~~strikethrough~~ (`~~`) as usual...
|
|
82
|
-
|
|
83
|
-
For keyboard commands `<kbd>` can be used, e.g.:\
|
|
84
|
-
`<kbd>Control</kbd> + <kbd>R</kbd>`
|
|
91
|
+
#### Code blocks
|
|
85
92
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
In addition to the mandatory language hint, code blocks support optional user
|
|
89
|
-
defined headers/metadata. Items will be separated by spaces (e.g. see
|
|
93
|
+
In addition to the **mandatory language hint**, code blocks support optional
|
|
94
|
+
user defined headers/metadata. Items will be separated by spaces (e.g. see
|
|
90
95
|
[@thi.ng/tangle](https://github.com/thi-ng/umbrella/tree/develop/packages/tangle)
|
|
91
96
|
for concrete use cases).
|
|
92
97
|
|
|
@@ -101,8 +106,8 @@ layout breakage)
|
|
|
101
106
|
|
|
102
107
|
#### Custom blocks
|
|
103
108
|
|
|
104
|
-
Since the parser does not directly transform Markdown into HTML, blocks of
|
|
105
|
-
freeform content can be used to define arbitrary data structures (e.g. UI
|
|
109
|
+
Since the parser does not directly transform Markdown into HTML, blocks of
|
|
110
|
+
custom freeform content can be used to define arbitrary data structures (e.g. UI
|
|
106
111
|
components, diagrams/visualizations etc.). Similarly to code blocks, custom
|
|
107
112
|
blocks are wrapped with `:::` and a type specifier:
|
|
108
113
|
|
|
@@ -129,7 +134,34 @@ transformer. The default handler merely creates an element like this:
|
|
|
129
134
|
**Tip:** Use a
|
|
130
135
|
[`defmulti()`](https://github.com/thi-ng/umbrella/tree/develop/packages/defmulti)
|
|
131
136
|
polymorphic function as tag transformer to elegantly handle multiple types of
|
|
132
|
-
custom blocks (in an extensible manner).
|
|
137
|
+
custom blocks (in an easily extensible manner).
|
|
138
|
+
|
|
139
|
+
#### Escaping control characters
|
|
140
|
+
|
|
141
|
+
Unlike the weird & hard-to-memorize escape rules in "standard" Markdown, here
|
|
142
|
+
we're taking a more uniform approach of exclusively using backslash escapes
|
|
143
|
+
(e.g. `\*`) to ensure various Markdown control characters are used verbatim.
|
|
144
|
+
Only the following minor exceptions apply:
|
|
145
|
+
|
|
146
|
+
1. In inline code sections only backticks (`\``) need to be escaped and
|
|
147
|
+
backslashes _can_ be escaped. All others chars are used as is.
|
|
148
|
+
2. In fenced code blocks only backticks can be escaped (e.g. if escaping the
|
|
149
|
+
triple-backtick block fence itself). Backslashes and others chars are used as is.
|
|
150
|
+
3. In custom blocks only colons (`:`) can be escaped (e.g. if escaping the
|
|
151
|
+
triple-colon block fence itself). All other chars are used as is.
|
|
152
|
+
4. In metadata blocks only `}` can be escaped. All other chars are used as is.
|
|
153
|
+
|
|
154
|
+
#### Formatting
|
|
155
|
+
|
|
156
|
+
To avoid ambiguity and simplify nesting, only the following formatting syntax is
|
|
157
|
+
supported for bold & italic:
|
|
158
|
+
|
|
159
|
+
- `**bold**`
|
|
160
|
+
- `_italic_`
|
|
161
|
+
- `code` (\`) and ~~strikethrough~~ (`~~`) as usual...
|
|
162
|
+
- `<kbd>` for keyboard shortcuts (e.g. <kbd>Control</kbd>)
|
|
163
|
+
- `<sub>` for <sub>subscript</sub>
|
|
164
|
+
- `<sup>` for <sup>superscript</sup>
|
|
133
165
|
|
|
134
166
|
#### Headings with anchor IDs
|
|
135
167
|
|
|
@@ -160,6 +192,35 @@ Results in:
|
|
|
160
192
|
// ]
|
|
161
193
|
```
|
|
162
194
|
|
|
195
|
+
### Images
|
|
196
|
+
|
|
197
|
+
**Alt text for images is required**. Optional `title` attribute (e.g. for hover
|
|
198
|
+
tooltip or caption) can be given in quotes after the image URL. For example:
|
|
199
|
+
|
|
200
|
+
```markdown
|
|
201
|
+

|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Link formats
|
|
205
|
+
|
|
206
|
+
The following link formats are supported:
|
|
207
|
+
|
|
208
|
+
1. `[label](target)`
|
|
209
|
+
2. `[label](target "title")`
|
|
210
|
+
3. `[label][ref-id]` - the reference ID will have to provided somewhere else in
|
|
211
|
+
the document or pre-defined via options given to the parser
|
|
212
|
+
4. `[[page name]]` - Wiki-style page reference, non-standard Markdown
|
|
213
|
+
5. `[[page name|label]]` - like 4., but with added link label
|
|
214
|
+
|
|
215
|
+
### Lists
|
|
216
|
+
|
|
217
|
+
- Ordered and unordered lists are supported
|
|
218
|
+
- Fully nestable
|
|
219
|
+
- Ordered lists start with a `1.` (digit or letter followed by a dot) prefix
|
|
220
|
+
- Unordered lists **must** use a `-` line prefix
|
|
221
|
+
- [ ] TODO list items
|
|
222
|
+
- [x] ...are supported as well
|
|
223
|
+
|
|
163
224
|
#### Metadata
|
|
164
225
|
|
|
165
226
|
Arbitrary metadata can be assigned to _any_ block level element:
|
|
@@ -450,6 +511,10 @@ More info [here](http://thi.ng/hiccup-markdown).
|
|
|
450
511
|
|
|
451
512
|
[Search or submit any issues for this package](https://github.com/thi-ng/umbrella/issues?q=%5Bhiccup-markdown%5D+in%3Atitle)
|
|
452
513
|
|
|
514
|
+
## Related packages
|
|
515
|
+
|
|
516
|
+
- [@thi.ng/markdown-table](https://github.com/thi-ng/umbrella/tree/develop/packages/markdown-table) - Markdown table formatter/generator with support for column alignments
|
|
517
|
+
|
|
453
518
|
## Installation
|
|
454
519
|
|
|
455
520
|
```bash
|
|
@@ -470,7 +535,7 @@ For Node.js REPL:
|
|
|
470
535
|
const hiccupMarkdown = await import("@thi.ng/hiccup-markdown");
|
|
471
536
|
```
|
|
472
537
|
|
|
473
|
-
Package sizes (brotli'd, pre-treeshake): ESM: 4.
|
|
538
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 4.62 KB
|
|
474
539
|
|
|
475
540
|
## Dependencies
|
|
476
541
|
|
package/api.d.ts
CHANGED
|
@@ -189,7 +189,8 @@ export interface TagTransforms {
|
|
|
189
189
|
ol(ctx: TransformCtx, items: any[], meta?: any): any;
|
|
190
190
|
/**
|
|
191
191
|
* Handler for a single list item in an ordered list. The `index` arg is the
|
|
192
|
-
*
|
|
192
|
+
* raw item index specified in the MD source code for that item (e.g. a
|
|
193
|
+
* digit or letter).
|
|
193
194
|
*
|
|
194
195
|
* @remarks
|
|
195
196
|
* If the `attribs` object has a `__todo` attrib, the item is a task list
|
|
@@ -200,7 +201,7 @@ export interface TagTransforms {
|
|
|
200
201
|
* @param index
|
|
201
202
|
* @param body
|
|
202
203
|
*/
|
|
203
|
-
olitem(ctx: TransformCtx, attribs: TodoAttribs, index:
|
|
204
|
+
olitem(ctx: TransformCtx, attribs: TodoAttribs, index: string, body: any[]): any;
|
|
204
205
|
/**
|
|
205
206
|
* Handler for a paragraph of body content.
|
|
206
207
|
*
|
|
@@ -217,36 +218,54 @@ export interface TagTransforms {
|
|
|
217
218
|
*/
|
|
218
219
|
strike(ctx: TransformCtx, body: any[]): any;
|
|
219
220
|
/**
|
|
220
|
-
* Handler for
|
|
221
|
+
* Handler for subscript inline content.
|
|
222
|
+
*
|
|
223
|
+
* @param ctx
|
|
224
|
+
* @param body
|
|
225
|
+
*/
|
|
226
|
+
sub(ctx: TransformCtx, body: string): any;
|
|
227
|
+
/**
|
|
228
|
+
* Handler for superscript inline content.
|
|
229
|
+
*
|
|
230
|
+
* @param ctx
|
|
231
|
+
* @param body
|
|
232
|
+
*/
|
|
233
|
+
sup(ctx: TransformCtx, body: string): any;
|
|
234
|
+
/**
|
|
235
|
+
* Handler for a table container. The alignment settings for each column can
|
|
236
|
+
* be accessed via given context's {@link TransformCtx.align} array.
|
|
221
237
|
*
|
|
222
238
|
* @param ctx
|
|
223
|
-
* @param align
|
|
224
239
|
* @param head
|
|
225
240
|
* @param rows
|
|
226
241
|
* @param meta
|
|
227
242
|
*/
|
|
228
|
-
table(ctx: TransformCtx,
|
|
243
|
+
table(ctx: TransformCtx, head: any[], rows: any[], meta?: any): any;
|
|
229
244
|
/**
|
|
230
|
-
* Handler for a single table cell in a non-header row.
|
|
245
|
+
* Handler for a single table cell in a non-header row. The current column index can
|
|
246
|
+
* be accessed via given context's {@link TransformCtx.column} property.
|
|
231
247
|
*
|
|
232
248
|
* @param ctx
|
|
233
249
|
* @param body
|
|
234
250
|
*/
|
|
235
251
|
tableCell(ctx: TransformCtx, body: any[]): any;
|
|
236
252
|
/**
|
|
237
|
-
* Handler for a single table cell in the header row.
|
|
253
|
+
* Handler for a single table cell in the header row. The current column index can
|
|
254
|
+
* be accessed via given context's {@link TransformCtx.column} property.
|
|
238
255
|
*
|
|
239
256
|
* @param ctx
|
|
240
257
|
* @param body
|
|
241
258
|
*/
|
|
242
259
|
tableHead(ctx: TransformCtx, body: any[]): any;
|
|
243
260
|
/**
|
|
244
|
-
* Handler for a single table row. The
|
|
261
|
+
* Handler for a single table row. The current row index can be accessed via
|
|
262
|
+
* given context's {@link TransformCtx.row} property. The header row will
|
|
263
|
+
* have `index=0`. The first data row `index=1`.
|
|
245
264
|
*
|
|
246
265
|
* @param ctx
|
|
247
266
|
* @param body
|
|
248
267
|
*/
|
|
249
|
-
tableRow(ctx: TransformCtx,
|
|
268
|
+
tableRow(ctx: TransformCtx, cells: any[]): any;
|
|
250
269
|
/**
|
|
251
270
|
* Handler for an unordered list wrapper.
|
|
252
271
|
*
|
|
@@ -266,7 +285,7 @@ export interface TagTransforms {
|
|
|
266
285
|
* @param attribs
|
|
267
286
|
* @param body
|
|
268
287
|
*/
|
|
269
|
-
ulitem(ctx: TransformCtx, attribs: TodoAttribs,
|
|
288
|
+
ulitem(ctx: TransformCtx, attribs: TodoAttribs, body: any[]): any;
|
|
270
289
|
/**
|
|
271
290
|
* Handler for `[[page name]]` or `[[page name|label]]-style links.
|
|
272
291
|
*
|
|
@@ -291,6 +310,8 @@ export interface TransformCtx {
|
|
|
291
310
|
}[];
|
|
292
311
|
hasFootnotes: boolean;
|
|
293
312
|
meta?: any;
|
|
313
|
+
align: ColumnAlign[];
|
|
314
|
+
column: number;
|
|
294
315
|
row: number;
|
|
295
316
|
opts: ParseOpts;
|
|
296
317
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/hiccup-markdown",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "Markdown parser & serializer from/to Hiccup format",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@thi.ng/defmulti": "^2.1.31",
|
|
41
41
|
"@thi.ng/emoji": "^0.1.0",
|
|
42
42
|
"@thi.ng/errors": "^2.2.12",
|
|
43
|
-
"@thi.ng/hiccup": "^4.2.
|
|
43
|
+
"@thi.ng/hiccup": "^4.2.36",
|
|
44
44
|
"@thi.ng/logger": "^1.4.9",
|
|
45
45
|
"@thi.ng/parse": "^2.2.28",
|
|
46
46
|
"@thi.ng/strings": "^3.4.1",
|
|
@@ -93,7 +93,10 @@
|
|
|
93
93
|
},
|
|
94
94
|
"thi.ng": {
|
|
95
95
|
"parent": "@thi.ng/hiccup",
|
|
96
|
+
"related": [
|
|
97
|
+
"markdown-table"
|
|
98
|
+
],
|
|
96
99
|
"year": 2018
|
|
97
100
|
},
|
|
98
|
-
"gitHead": "
|
|
101
|
+
"gitHead": "31dd56eba72edd73a3ced5002c0f5145ce3d42d6\n"
|
|
99
102
|
}
|
package/parse.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// Downloaded @ 2023-03-
|
|
2
|
-
// Source: https://demo.thi.ng/umbrella/parse-playground/#
|
|
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
3
|
import { peek } from "@thi.ng/arrays/peek";
|
|
4
4
|
import { isArray } from "@thi.ng/checks/is-array";
|
|
5
5
|
import { isPlainObject } from "@thi.ng/checks/is-plain-object";
|
|
@@ -15,84 +15,97 @@ export const GRAMMAR = defGrammar(`
|
|
|
15
15
|
DNL1: <DNL>+ => discard ;
|
|
16
16
|
DNL2: <NL>{2,} ;
|
|
17
17
|
lbr: '\\\\'! <NL>! ;
|
|
18
|
-
esc: '\\\\'! ( '<' | '[' | '
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
esc: '\\\\'! ('_' | '*' | '\`' | '~' | ':' | '-' | '<' | '>' | '[' | ']' | '(' | ')' | '{' | '}' | '#' | '.' | '|' | '\\\\') ;
|
|
19
|
+
cesc: '\\\\'! ('\`'| '\\\\') ;
|
|
20
|
+
cbesc: '\\\\'! '\`' ;
|
|
21
|
+
cuesc: '\\\\'! ':' ;
|
|
22
|
+
mesc: '\\\\'! '}' ;
|
|
23
|
+
idelim: ("![" | '[' | "**" | '_' | '\`' | '<' | "~~" | " :" | <lbr>) ;
|
|
24
|
+
delim: (<idelim> | <DNL2>) ;
|
|
25
|
+
ebody: (<esc>|.) ;
|
|
26
|
+
cbody: (<cesc>|.) ;
|
|
27
|
+
cbbody: (<cbesc>|.) ;
|
|
28
|
+
cubody: (<cuesc>|.) ;
|
|
29
|
+
mbody: (<mesc>|.) ;
|
|
30
|
+
body: <ebody>(?-<delim>!) => join ;
|
|
31
|
+
ibody: <ebody>(?-<idelim>!) => join ;
|
|
24
32
|
|
|
25
|
-
|
|
33
|
+
comment: "<!--"! .(?+"-->") => discard ;
|
|
34
|
+
wikiref: "[["! <ebody>(?+"]]"!) => join ;
|
|
26
35
|
fnref: "[^"! <label> ;
|
|
27
36
|
fnote: <LSTART> "[^"! <fnlabel> <WS1> <para> ;
|
|
28
|
-
fnlabel:
|
|
29
|
-
label:
|
|
30
|
-
target:
|
|
37
|
+
fnlabel: <ebody>(?+"]:"!) => join ;
|
|
38
|
+
label: <ebody>(?+']'!) => join ;
|
|
39
|
+
target: <ebody>(?+')'!) => join ;
|
|
31
40
|
link: '['! <linklabel> '('! <target> ;
|
|
32
41
|
linkref: '['! <linklabel> '['! <label> ;
|
|
33
42
|
linkdef: <LSTART> '['! <label> ':'! <WS1> <ldtarget> ;
|
|
34
|
-
ldtarget:
|
|
35
|
-
linklabel: (<img> | <bold> | <italic> | <strike> | <code> | <emoji> | <linkbody>)* ']'! ;
|
|
36
|
-
linkdelim: (
|
|
37
|
-
linkbody:
|
|
43
|
+
ldtarget: <ebody>(?+<DNL1>) => join ;
|
|
44
|
+
linklabel: (<img> | <bold> | <italic> | <strike> | <code> | <emoji> | <kbd> | <sub> | <sup> | <linkbody>)* ']'! ;
|
|
45
|
+
linkdelim: ("![" | '[' | "**" | '_' | "~~" | '\`' | ']') ;
|
|
46
|
+
linkbody: <ebody>(?-<linkdelim>!) => join ;
|
|
38
47
|
img: "!["! <label> '('! <target> ;
|
|
39
|
-
bold: "**"! (<wikiref> | <img> | <fnref> | <linkref> | <link> | <italic> | <strike> | <code> | <emoji> | <
|
|
40
|
-
italic: '_'! (<wikiref> | <img> | <fnref> | <linkref> | <link> | <bold> | <strike> | <code> | <emoji> | <
|
|
41
|
-
strike: "~~"! (<wikiref> | <img> | <fnref> | <linkref> | <link> | <bold> | <italic> | <code> | <emoji> | <
|
|
42
|
-
code: '\`'!
|
|
43
|
-
kbd: "<kbd>"!
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
bold: "**"! (<wikiref> | <img> | <fnref> | <linkref> | <link> | <italic> | <strike> | <code> | <emoji> | <kbd> | <sub> | <sup> | <ibody>)* "**"! ;
|
|
49
|
+
italic: '_'! (<wikiref> | <img> | <fnref> | <linkref> | <link> | <bold> | <strike> | <code> | <emoji> | <kbd> | <sub> | <sup> | <ibody>)* '_'! ;
|
|
50
|
+
strike: "~~"! (<wikiref> | <img> | <fnref> | <linkref> | <link> | <bold> | <italic> | <code> | <emoji> | <kbd> | <sub> | <sup> | <ibody>)* "~~"! ;
|
|
51
|
+
code: '\`'! <cbody>(?+'\`'!) => join ;
|
|
52
|
+
kbd: "<kbd>"! <ebody>(?+"</kbd>"!) => join ;
|
|
53
|
+
sub: "<sub>"! <ebody>(?+"</sub>"!) => join ;
|
|
54
|
+
sup: "<sup>"! <ebody>(?+"</sup>"!) => join ;
|
|
55
|
+
emoji: ' '? ':'! (<ALPHA_NUM> | '+')(?+':'!) => join ;
|
|
56
|
+
para: (<wikiref> | <img> | <fnref> | <linkref> | <link> | <bold> | <italic> | <strike> | <code> | <kbd> | <sub> | <sup> | <emoji> | <lbr> | <comment> | <body>)* <DNL2>! ;
|
|
46
57
|
|
|
47
58
|
hdlevel: '#'+ => count ;
|
|
48
59
|
hdid: "{#"! (<ALPHA_NUM> | '-')+ '}'! => join ;
|
|
49
|
-
hddelim: ( <
|
|
50
|
-
hdbody:
|
|
60
|
+
hddelim: (<idelim> | <NL> | "{#") ;
|
|
61
|
+
hdbody: <ebody>(?-<hddelim>!) => join ;
|
|
51
62
|
hd: <LSTART> <hdlevel> <WS0>
|
|
52
|
-
(<wikiref> | <img> | <fnref> | <link> | <bold> | <italic> | <strike> | <code> | <emoji> | <hdbody>
|
|
63
|
+
(<wikiref> | <img> | <fnref> | <link> | <bold> | <italic> | <strike> | <code> | <emoji> | <kbd> | <sub> | <sup> | <hdbody>)* <hdid>? <DNL1> ;
|
|
53
64
|
|
|
54
65
|
lilevel: ' '* => count ;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
lidelim: (
|
|
59
|
-
libody:
|
|
66
|
+
olid: (<ALPHA>+|<DIGIT>+) => join ;
|
|
67
|
+
ulinit: <DNL> <WS0> '-'! ;
|
|
68
|
+
olinit: <DNL> <WS0> <olid>! '.'! ;
|
|
69
|
+
lidelim: (<delim> | <ulinit> | <olinit>) ;
|
|
70
|
+
libody: <ebody>(?-<lidelim>!) => join ;
|
|
60
71
|
todo: '['! [ xX] ']'! <WS1> => hoistR ;
|
|
61
72
|
ulitem: <LSTART> <lilevel> "- "! <todo>?
|
|
62
|
-
(<wikiref> | <img> | <fnref> | <link> | <bold> | <italic> | <strike> | <code> | <emoji> | <libody> )* <DNL> ;
|
|
63
|
-
olitem: <LSTART> <lilevel> <
|
|
64
|
-
(<wikiref> | <img> | <fnref> | <link> | <bold> | <italic> | <strike> | <code> | <emoji> | <libody> )* <DNL> ;
|
|
73
|
+
(<wikiref> | <img> | <fnref> | <link> | <bold> | <italic> | <strike> | <code> | <emoji> | <kbd> | <sub> | <sup> | <libody> )* <DNL> ;
|
|
74
|
+
olitem: <LSTART> <lilevel> <olid> ". "! <todo>?
|
|
75
|
+
(<wikiref> | <img> | <fnref> | <link> | <bold> | <italic> | <strike> | <code> | <emoji> | <kbd> | <sub> | <sup> | <libody> )* <DNL> ;
|
|
65
76
|
list: (<ulitem> | <olitem>)+ <DNL1> ;
|
|
66
77
|
|
|
67
78
|
cbdelim: <LSTART> "\`\`\`"! ;
|
|
68
79
|
codeblock: <cbdelim>! <codemeta> <codebody> <DNL1> ;
|
|
69
80
|
codemeta: .(?+<NL>!) => join ;
|
|
70
|
-
codebody:
|
|
81
|
+
codebody: <cbbody>(?+<cbdelim>) => join ;
|
|
71
82
|
|
|
72
|
-
|
|
73
|
-
customblock: <
|
|
83
|
+
cudelim: <LSTART> ":::"! ;
|
|
84
|
+
customblock: <cudelim>! <custommeta> <custombody> <DNL1> ;
|
|
74
85
|
custommeta: .(?+<NL>!) => join ;
|
|
75
|
-
custombody:
|
|
86
|
+
custombody: <cubody>(?+<cudelim>) => join ;
|
|
76
87
|
|
|
77
88
|
metablock: <LSTART> "{{{"! <metabody> <DNL1> ;
|
|
78
|
-
metabody:
|
|
89
|
+
metabody: <mbody>(?+<metaend>!) => join ;
|
|
79
90
|
metaend: "}}}" <LEND> ;
|
|
80
91
|
|
|
81
92
|
bqlevel: '>'+ => count ;
|
|
93
|
+
bqdelim: (<idelim> | <NL>) ;
|
|
94
|
+
bqbody: <ebody>(?-<bqdelim>!) => join ;
|
|
82
95
|
bqline: <LSTART> <bqlevel> ' '?!
|
|
83
|
-
(<wikiref> | <img> | <fnref> | <link> | <bold> | <italic> | <strike> | <code> | <emoji> | <bqlbr> | <
|
|
96
|
+
(<wikiref> | <img> | <fnref> | <link> | <bold> | <italic> | <strike> | <code> | <emoji> | <kbd> | <sub> | <sup> | <bqlbr> | <bqbody>)* <DNL> ;
|
|
84
97
|
bqlbr: '\\\\'!(?-<DNL>) ;
|
|
85
98
|
bquote: <bqline>+ <DNL1> ;
|
|
86
99
|
|
|
87
|
-
tdelim: (<
|
|
88
|
-
tbody:
|
|
89
|
-
tcell: <WS0> (<wikiref> | <img> | <fnref> | <link> | <bold> | <italic> | <strike> | <code> | <emoji> | <tbody> )* '|'! ;
|
|
100
|
+
tdelim: (<idelim> | '|' ) ;
|
|
101
|
+
tbody: <ebody>(?-<tdelim>!) => join ;
|
|
102
|
+
tcell: <WS0> (<wikiref> | <img> | <fnref> | <link> | <bold> | <italic> | <strike> | <code> | <emoji> | <kbd> | <sub> | <sup> | <tbody> )* '|'! ;
|
|
90
103
|
trow: <LSTART> '|'! <tcell>(?+<DNL>) ;
|
|
91
104
|
table: <trow>+ <DNL1> ;
|
|
92
105
|
|
|
93
106
|
hr: "--" '-'+ <DNL1> => join ;
|
|
94
107
|
|
|
95
|
-
main: <WS0> (<hd> | <list> | <bquote> | <codeblock> | <customblock> | <metablock> | <table> | <hr> | <fnote> | <linkdef> | <para>)* ;
|
|
108
|
+
main: <WS0> (<hd> | <list> | <bquote> | <codeblock> | <customblock> | <metablock> | <table> | <hr> | <fnote> | <linkdef> | <comment> | <para> )* ;
|
|
96
109
|
`);
|
|
97
110
|
export const DEFAULT_TAG_TRANSFORMS = {
|
|
98
111
|
bold: (_, body) => ["strong", {}, ...body],
|
|
@@ -157,15 +170,17 @@ export const DEFAULT_TAG_TRANSFORMS = {
|
|
|
157
170
|
ol: (_, items, meta) => ["ol", withMeta({}, meta), ...items],
|
|
158
171
|
para: (_, body, meta) => ["p", withMeta({}, meta), ...body],
|
|
159
172
|
strike: (_, body) => ["s", {}, ...body],
|
|
160
|
-
|
|
173
|
+
sub: (_, body) => ["sub", {}, body],
|
|
174
|
+
sup: (_, body) => ["sup", {}, body],
|
|
175
|
+
table: (ctx, head, rows, meta) => [
|
|
161
176
|
"table",
|
|
162
|
-
withMeta({ __align }, meta),
|
|
177
|
+
withMeta({ __align: ctx.align }, meta),
|
|
163
178
|
["thead", {}, head],
|
|
164
179
|
["tbody", {}, ...rows],
|
|
165
180
|
],
|
|
166
181
|
tableCell: (_, body) => ["td", {}, ...body],
|
|
167
182
|
tableHead: (_, body) => ["th", {}, ...body],
|
|
168
|
-
tableRow: (_,
|
|
183
|
+
tableRow: (_, cells) => ["tr", {}, ...cells],
|
|
169
184
|
ul: (_, items, meta) => ["ul", withMeta({}, meta), ...items],
|
|
170
185
|
ulitem: (_, attribs, body) => ["li", attribs, ...body],
|
|
171
186
|
wikiref: (_, id, label) => [
|
|
@@ -240,6 +255,8 @@ export const defTransformContext = (tags, opts, linkRefs, logger) => ({
|
|
|
240
255
|
hasFootnotes: false,
|
|
241
256
|
logger,
|
|
242
257
|
meta: null,
|
|
258
|
+
align: [],
|
|
259
|
+
column: 0,
|
|
243
260
|
row: 0,
|
|
244
261
|
opts: {
|
|
245
262
|
escape: false,
|
|
@@ -259,10 +276,11 @@ export const transformScope = defmulti((x, ctx) => {
|
|
|
259
276
|
ctx.logger && ctx.logger.debug(x);
|
|
260
277
|
return x.id;
|
|
261
278
|
}, {
|
|
262
|
-
|
|
279
|
+
bqbody: "body",
|
|
263
280
|
bqlbr: "lbr",
|
|
264
281
|
bqline: "repeat0",
|
|
265
282
|
hdbody: "body",
|
|
283
|
+
ibody: "body",
|
|
266
284
|
label: "body",
|
|
267
285
|
libody: "body",
|
|
268
286
|
linkbody: "body",
|
|
@@ -340,7 +358,6 @@ export const transformScope = defmulti((x, ctx) => {
|
|
|
340
358
|
}
|
|
341
359
|
__collect(acc, ctx.tags.emoji(ctx, result));
|
|
342
360
|
},
|
|
343
|
-
esc: (scope, ctx, acc) => acc.push(__escape(ctx, scope.children[0].result)),
|
|
344
361
|
fnote: ({ children }, ctx) => {
|
|
345
362
|
const body = [];
|
|
346
363
|
const id = children[0].result;
|
|
@@ -369,7 +386,7 @@ export const transformScope = defmulti((x, ctx) => {
|
|
|
369
386
|
},
|
|
370
387
|
img: ({ children }, ctx, acc) => __collect(acc, ctx.tags.img(ctx, __escape(ctx, children[0].result.trim()), ...__linkTitle(children[1].result))),
|
|
371
388
|
italic: (scope, ctx, acc) => __collect(acc, ctx.tags.italic(ctx, __children(ctx, scope.children))),
|
|
372
|
-
kbd: (scope, ctx, acc) =>
|
|
389
|
+
kbd: (scope, ctx, acc) => __collectPrim(scope, ctx, acc, "kbd"),
|
|
373
390
|
lbr: (_, ctx, acc) => __collect(acc, ctx.tags.br(ctx)),
|
|
374
391
|
link: ({ children }, ctx, acc) => __collect(acc, ctx.tags.link(ctx, ...__linkTitle(children[1].result), __children(ctx, children[0].children))),
|
|
375
392
|
linkdef: ({ children }, ctx) => {
|
|
@@ -435,28 +452,37 @@ export const transformScope = defmulti((x, ctx) => {
|
|
|
435
452
|
ctx.meta = null;
|
|
436
453
|
},
|
|
437
454
|
strike: (scope, ctx, acc) => __collect(acc, ctx.tags.strike(ctx, __children(ctx, scope.children))),
|
|
455
|
+
sub: (scope, ctx, acc) => __collectPrim(scope, ctx, acc, "sub"),
|
|
456
|
+
sup: (scope, ctx, acc) => __collectPrim(scope, ctx, acc, "sup"),
|
|
438
457
|
table: (scope, ctx, acc) => {
|
|
439
458
|
const children = scope.children[0].children;
|
|
440
459
|
const head = [];
|
|
441
460
|
const rows = [];
|
|
442
461
|
ctx.row = 0;
|
|
443
|
-
transformScope(children[0], ctx, head);
|
|
444
|
-
let align;
|
|
445
462
|
if (children.length > 1) {
|
|
446
|
-
align = __columnAlignments(children[1].children[0].children);
|
|
463
|
+
ctx.align = __columnAlignments(children[1].children[0].children);
|
|
447
464
|
for (let i = 2, n = children.length; i < n; i++) {
|
|
448
465
|
ctx.row = i - 1;
|
|
449
466
|
transformScope(children[i], ctx, rows);
|
|
450
467
|
}
|
|
451
468
|
}
|
|
452
469
|
else {
|
|
453
|
-
align = new Array(children[0].children[0].children.length).fill("left");
|
|
470
|
+
ctx.align = new Array(children[0].children[0].children.length).fill("left");
|
|
454
471
|
}
|
|
455
|
-
|
|
472
|
+
ctx.row = 0;
|
|
473
|
+
transformScope(children[0], ctx, head);
|
|
474
|
+
__collect(acc, ctx.tags.table(ctx, head[0], rows, ctx.meta));
|
|
456
475
|
ctx.meta = null;
|
|
457
476
|
},
|
|
458
477
|
tcell: ({ children }, ctx, acc) => __collect(acc, (ctx.row > 0 ? ctx.tags.tableCell : ctx.tags.tableHead)(ctx, __trimBody(__children(ctx, children)))),
|
|
459
|
-
trow: (
|
|
478
|
+
trow: (scope, ctx, acc) => {
|
|
479
|
+
const cells = [];
|
|
480
|
+
scope.children[0].children.forEach((c, i) => {
|
|
481
|
+
ctx.column = i;
|
|
482
|
+
transformScope(c, ctx, cells);
|
|
483
|
+
});
|
|
484
|
+
__collect(acc, ctx.tags.tableRow(ctx, cells));
|
|
485
|
+
},
|
|
460
486
|
ulitem: ({ children }, ctx, acc) => {
|
|
461
487
|
const body = [];
|
|
462
488
|
transformScope(children[2], ctx, body);
|
|
@@ -468,7 +494,7 @@ export const transformScope = defmulti((x, ctx) => {
|
|
|
468
494
|
},
|
|
469
495
|
wikiref: (scope, ctx, acc) => {
|
|
470
496
|
const [id, label] = scope.result.split("|");
|
|
471
|
-
__collect(acc, ctx.tags.wikiref(ctx, id, label));
|
|
497
|
+
__collect(acc, ctx.tags.wikiref(ctx, id.trim(), label?.trim()));
|
|
472
498
|
},
|
|
473
499
|
});
|
|
474
500
|
/**
|
|
@@ -501,6 +527,7 @@ export const extractBody = (body, acc = []) => {
|
|
|
501
527
|
};
|
|
502
528
|
/** @internal */
|
|
503
529
|
const __collect = (acc, x) => x != null && acc.push(x);
|
|
530
|
+
const __collectPrim = (scope, ctx, acc, tag) => __collect(acc, ctx.tags[tag](ctx, scope.result));
|
|
504
531
|
/** @internal */
|
|
505
532
|
const __children = (ctx, children, acc = []) => {
|
|
506
533
|
for (let c of children)
|
|
@@ -520,6 +547,11 @@ const __listItemAttribs = (scope) => scope?.id === "todo"
|
|
|
520
547
|
const __trimBody = (body) => {
|
|
521
548
|
if (body.length === 1 && isString(body[0]))
|
|
522
549
|
body[0] = body[0].trim();
|
|
550
|
+
else {
|
|
551
|
+
const last = peek(body);
|
|
552
|
+
if (isString(last) && /^\s+$/.test(last))
|
|
553
|
+
body.pop();
|
|
554
|
+
}
|
|
523
555
|
return body;
|
|
524
556
|
};
|
|
525
557
|
/** @internal */
|