pantsdown 2.2.6 → 2.2.8
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/README.md +2 -0
- package/package.json +20 -18
- package/src/lexer.ts +47 -51
- package/src/parser.ts +51 -125
- package/src/renderer.ts +133 -63
- package/src/rules/block.ts +41 -34
- package/src/rules/inline.ts +93 -29
- package/src/rules/other.ts +79 -0
- package/src/rules/utils.ts +2 -2
- package/src/text-renderer.ts +57 -0
- package/src/tokenizer.ts +352 -175
- package/src/types.ts +12 -2
- package/src/utils.ts +62 -40
- package/.oxfmtrc.json +0 -17
- package/CLAUDE.md +0 -73
- package/bun.lock +0 -1504
- package/eslint.config.ts +0 -46
- package/tsconfig.json +0 -32
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pantsdown",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.8",
|
|
4
4
|
"description": "Markdown to 'GitHub HTML' parser",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "wallpants",
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git://github.com/wallpants/pantsdown.git"
|
|
10
10
|
},
|
|
11
|
+
"files": [
|
|
12
|
+
"src",
|
|
13
|
+
"!src/**/*.test.ts"
|
|
14
|
+
],
|
|
11
15
|
"type": "module",
|
|
12
16
|
"exports": {
|
|
13
17
|
"./*": "./*",
|
|
@@ -26,33 +30,31 @@
|
|
|
26
30
|
"commit": "cz",
|
|
27
31
|
"format": "oxfmt .",
|
|
28
32
|
"typecheck": "tsc",
|
|
29
|
-
"lint": "
|
|
33
|
+
"lint": "oxlint .",
|
|
30
34
|
"check": "bun run typecheck && bun run lint",
|
|
31
|
-
"docs:build": "bun run docs/build.ts"
|
|
35
|
+
"docs:build": "bun run docs/build.ts",
|
|
36
|
+
"prepare": "husky"
|
|
32
37
|
},
|
|
33
38
|
"dependencies": {
|
|
34
39
|
"github-slugger": "^2.0.0",
|
|
35
40
|
"highlight.js": "^11.11.1",
|
|
36
|
-
"katex": "^0.
|
|
41
|
+
"katex": "^0.18.0"
|
|
37
42
|
},
|
|
38
43
|
"devDependencies": {
|
|
39
|
-
"@commitlint/
|
|
40
|
-
"@commitlint/
|
|
41
|
-
"@
|
|
44
|
+
"@commitlint/cli": "^21.2.1",
|
|
45
|
+
"@commitlint/config-conventional": "^21.2.0",
|
|
46
|
+
"@commitlint/cz-commitlint": "^21.2.0",
|
|
47
|
+
"@happy-dom/global-registrator": "^20.11.0",
|
|
42
48
|
"@types/bun": "^1.3.14",
|
|
43
49
|
"@types/katex": "^0.16.8",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"commitizen": "^4.3.1",
|
|
47
|
-
"commitlint": "^21.0.2",
|
|
48
|
-
"eslint": "^9.39.4",
|
|
49
|
-
"eslint-import-resolver-typescript": "^4.4.4",
|
|
50
|
-
"eslint-plugin-import-x": "^4.16.2",
|
|
50
|
+
"commitizen": "^4.3.2",
|
|
51
|
+
"husky": "^9.1.7",
|
|
51
52
|
"inquirer": "^12.11.1",
|
|
52
|
-
"oxfmt": "^0.
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
53
|
+
"oxfmt": "^0.59.0",
|
|
54
|
+
"oxlint": "^1.73.0",
|
|
55
|
+
"oxlint-tsgolint": "^0.25.0",
|
|
56
|
+
"semantic-release": "^25.0.8",
|
|
57
|
+
"typescript": "7.0.2"
|
|
56
58
|
},
|
|
57
59
|
"commitlint": {
|
|
58
60
|
"extends": [
|
package/src/lexer.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { inline } from "./rules/inline.ts";
|
|
2
|
+
import { other } from "./rules/other.ts";
|
|
2
3
|
import { Tokenizer } from "./tokenizer.ts";
|
|
3
4
|
import { type Links, type SourceMap, type Token, type Tokens } from "./types.ts";
|
|
4
5
|
|
|
5
6
|
export class Lexer {
|
|
6
7
|
private tokenizer: Tokenizer;
|
|
7
|
-
|
|
8
|
+
inlineQueue: { src: string; tokens: Token[] }[];
|
|
8
9
|
private links: Links = {};
|
|
9
10
|
|
|
10
11
|
tokens: Token[] = [];
|
|
@@ -31,8 +32,13 @@ export class Lexer {
|
|
|
31
32
|
this.tokens = [];
|
|
32
33
|
this.links = {};
|
|
33
34
|
this.line = 1;
|
|
35
|
+
this.state = {
|
|
36
|
+
inLink: false,
|
|
37
|
+
inRawBlock: false,
|
|
38
|
+
top: true,
|
|
39
|
+
};
|
|
34
40
|
|
|
35
|
-
src = src.replace(
|
|
41
|
+
src = src.replace(other.carriageReturn, "\n");
|
|
36
42
|
|
|
37
43
|
this.blockTokens(src, this.tokens);
|
|
38
44
|
|
|
@@ -70,17 +76,19 @@ export class Lexer {
|
|
|
70
76
|
/**
|
|
71
77
|
* Lexing
|
|
72
78
|
*/
|
|
73
|
-
blockTokens(src: string, tokens: Token[]): Token[] {
|
|
74
|
-
src = src.replace(/^( *)(\t+)/gm, (_, leading: string, tabs: string) => {
|
|
75
|
-
return leading + " ".repeat(tabs.length);
|
|
76
|
-
});
|
|
77
|
-
|
|
79
|
+
blockTokens(src: string, tokens: Token[], lastParagraphClipped = false): Token[] {
|
|
78
80
|
let token: Token | undefined;
|
|
79
81
|
let lastToken: Token | undefined;
|
|
80
82
|
let cutSrc;
|
|
81
|
-
let lastParagraphClipped;
|
|
82
83
|
|
|
84
|
+
let srcLength = Infinity;
|
|
83
85
|
while (src) {
|
|
86
|
+
if (src.length < srcLength) {
|
|
87
|
+
srcLength = src.length;
|
|
88
|
+
} else {
|
|
89
|
+
this.infiniteLoopError(src.charCodeAt(0));
|
|
90
|
+
}
|
|
91
|
+
|
|
84
92
|
// newline
|
|
85
93
|
if ((token = this.tokenizer.space(src))) {
|
|
86
94
|
src = src.substring(token.raw.length);
|
|
@@ -101,7 +109,7 @@ export class Lexer {
|
|
|
101
109
|
lastToken = tokens[tokens.length - 1];
|
|
102
110
|
// An indented code block cannot interrupt a paragraph.
|
|
103
111
|
if (lastToken && (lastToken.type === "paragraph" || lastToken.type === "text")) {
|
|
104
|
-
lastToken.raw += "\n" + token.raw;
|
|
112
|
+
lastToken.raw += (lastToken.raw.endsWith("\n") ? "" : "\n") + token.raw;
|
|
105
113
|
lastToken.text += "\n" + token.text;
|
|
106
114
|
const lastInline = this.inlineQueue[this.inlineQueue.length - 1];
|
|
107
115
|
if (lastInline) lastInline.src = lastToken.text;
|
|
@@ -172,7 +180,7 @@ export class Lexer {
|
|
|
172
180
|
src = src.substring(token.raw.length);
|
|
173
181
|
lastToken = tokens[tokens.length - 1];
|
|
174
182
|
if (lastToken && (lastToken.type === "paragraph" || lastToken.type === "text")) {
|
|
175
|
-
lastToken.raw += "\n" + token.raw;
|
|
183
|
+
lastToken.raw += (lastToken.raw.endsWith("\n") ? "" : "\n") + token.raw;
|
|
176
184
|
lastToken.text += "\n" + token.raw;
|
|
177
185
|
const lastInline = this.inlineQueue[this.inlineQueue.length - 1];
|
|
178
186
|
if (lastInline) lastInline.src = lastToken.text;
|
|
@@ -205,7 +213,7 @@ export class Lexer {
|
|
|
205
213
|
if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {
|
|
206
214
|
lastToken = tokens[tokens.length - 1];
|
|
207
215
|
if (lastParagraphClipped && lastToken?.type === "paragraph") {
|
|
208
|
-
lastToken.raw += "\n" + token.raw;
|
|
216
|
+
lastToken.raw += (lastToken.raw.endsWith("\n") ? "" : "\n") + token.raw;
|
|
209
217
|
lastToken.text += "\n" + token.text;
|
|
210
218
|
this.inlineQueue.pop();
|
|
211
219
|
const lastInline = this.inlineQueue[this.inlineQueue.length - 1];
|
|
@@ -223,7 +231,7 @@ export class Lexer {
|
|
|
223
231
|
src = src.substring(token.raw.length);
|
|
224
232
|
lastToken = tokens[tokens.length - 1];
|
|
225
233
|
if (lastToken?.type === "text") {
|
|
226
|
-
lastToken.raw += "\n" + token.raw;
|
|
234
|
+
lastToken.raw += (lastToken.raw.endsWith("\n") ? "" : "\n") + token.raw;
|
|
227
235
|
lastToken.text += "\n" + token.text;
|
|
228
236
|
this.inlineQueue.pop();
|
|
229
237
|
const lastInline = this.inlineQueue[this.inlineQueue.length - 1];
|
|
@@ -235,8 +243,7 @@ export class Lexer {
|
|
|
235
243
|
}
|
|
236
244
|
|
|
237
245
|
if (src) {
|
|
238
|
-
|
|
239
|
-
throw new Error(errMsg);
|
|
246
|
+
this.infiniteLoopError(src.charCodeAt(0));
|
|
240
247
|
}
|
|
241
248
|
}
|
|
242
249
|
|
|
@@ -257,42 +264,34 @@ export class Lexer {
|
|
|
257
264
|
|
|
258
265
|
// String with links masked to avoid interference with em and strong
|
|
259
266
|
let maskedSrc = src;
|
|
260
|
-
let match;
|
|
261
267
|
let keepPrevChar, prevChar;
|
|
262
268
|
|
|
263
269
|
// Mask out reflinks
|
|
264
270
|
const links = Object.keys(this.links);
|
|
265
271
|
if (links.length > 0) {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
"a".repeat(match[0].length - 2) +
|
|
272
|
-
"]" +
|
|
273
|
-
maskedSrc.slice(inline.reflinkSearch.lastIndex);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
272
|
+
maskedSrc = maskedSrc.replace(inline.reflinkSearch, (match0) =>
|
|
273
|
+
links.includes(match0.slice(match0.lastIndexOf("[") + 1, -1))
|
|
274
|
+
? "[" + "a".repeat(match0.length - 2) + "]"
|
|
275
|
+
: match0,
|
|
276
|
+
);
|
|
276
277
|
}
|
|
277
|
-
// Mask out other blocks
|
|
278
|
-
while ((match = inline.blockSkip.exec(maskedSrc)) != null) {
|
|
279
|
-
maskedSrc =
|
|
280
|
-
maskedSrc.slice(0, match.index) +
|
|
281
|
-
"[" +
|
|
282
|
-
"a".repeat(match[0].length - 2) +
|
|
283
|
-
"]" +
|
|
284
|
-
maskedSrc.slice(inline.blockSkip.lastIndex);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
278
|
// Mask out escaped characters
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
279
|
+
maskedSrc = maskedSrc.replace(inline.anyPunctuation, "++");
|
|
280
|
+
|
|
281
|
+
// Mask out other blocks
|
|
282
|
+
maskedSrc = maskedSrc.replace(
|
|
283
|
+
inline.blockSkip,
|
|
284
|
+
(match0) => "[" + "a".repeat(match0.length - 2) + "]",
|
|
285
|
+
);
|
|
294
286
|
|
|
287
|
+
let srcLength = Infinity;
|
|
295
288
|
while (src) {
|
|
289
|
+
if (src.length < srcLength) {
|
|
290
|
+
srcLength = src.length;
|
|
291
|
+
} else {
|
|
292
|
+
this.infiniteLoopError(src.charCodeAt(0));
|
|
293
|
+
}
|
|
294
|
+
|
|
296
295
|
if (!keepPrevChar) {
|
|
297
296
|
prevChar = "";
|
|
298
297
|
}
|
|
@@ -315,13 +314,7 @@ export class Lexer {
|
|
|
315
314
|
// tag
|
|
316
315
|
if ((token = this.tokenizer.tag(src))) {
|
|
317
316
|
src = src.substring(token.raw.length);
|
|
318
|
-
|
|
319
|
-
if (lastToken && token.type === "text" && lastToken.type === "text") {
|
|
320
|
-
lastToken.raw += token.raw;
|
|
321
|
-
lastToken.text += token.text;
|
|
322
|
-
} else {
|
|
323
|
-
tokens.push(token);
|
|
324
|
-
}
|
|
317
|
+
tokens.push(token);
|
|
325
318
|
continue;
|
|
326
319
|
}
|
|
327
320
|
|
|
@@ -374,7 +367,7 @@ export class Lexer {
|
|
|
374
367
|
}
|
|
375
368
|
|
|
376
369
|
// del (gfm)
|
|
377
|
-
if ((token = this.tokenizer.del(src))) {
|
|
370
|
+
if ((token = this.tokenizer.del(src, maskedSrc, prevChar))) {
|
|
378
371
|
src = src.substring(token.raw.length);
|
|
379
372
|
tokens.push(token);
|
|
380
373
|
continue;
|
|
@@ -415,11 +408,14 @@ export class Lexer {
|
|
|
415
408
|
}
|
|
416
409
|
|
|
417
410
|
if (src) {
|
|
418
|
-
|
|
419
|
-
throw new Error(errMsg);
|
|
411
|
+
this.infiniteLoopError(src.charCodeAt(0));
|
|
420
412
|
}
|
|
421
413
|
}
|
|
422
414
|
|
|
423
415
|
return tokens;
|
|
424
416
|
}
|
|
417
|
+
|
|
418
|
+
private infiniteLoopError(byte: number): never {
|
|
419
|
+
throw new Error("Infinite loop on byte: " + String(byte));
|
|
420
|
+
}
|
|
425
421
|
}
|
package/src/parser.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { type Pantsdown } from "./pantsdown.ts";
|
|
2
2
|
import { Renderer } from "./renderer.ts";
|
|
3
|
+
import { TextRenderer } from "./text-renderer.ts";
|
|
3
4
|
import { type Token, type Tokens } from "./types.ts";
|
|
4
|
-
import { injectHtmlAttributes } from "./utils.ts";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Parsing & Compiling
|
|
8
8
|
*/
|
|
9
9
|
export class Parser {
|
|
10
10
|
renderer: Renderer;
|
|
11
|
+
textRenderer: TextRenderer;
|
|
11
12
|
|
|
12
13
|
constructor(pantsdown: Pantsdown) {
|
|
13
14
|
this.renderer = new Renderer(pantsdown);
|
|
15
|
+
this.renderer.parser = this;
|
|
16
|
+
this.textRenderer = new TextRenderer();
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
/**
|
|
@@ -24,156 +27,75 @@ export class Parser {
|
|
|
24
27
|
|
|
25
28
|
switch (token.type) {
|
|
26
29
|
case "space": {
|
|
30
|
+
out += this.renderer.space(token);
|
|
27
31
|
continue;
|
|
28
32
|
}
|
|
29
33
|
case "hr": {
|
|
30
|
-
out += this.renderer.hr(token
|
|
34
|
+
out += this.renderer.hr(token);
|
|
31
35
|
continue;
|
|
32
36
|
}
|
|
33
37
|
case "heading": {
|
|
34
|
-
out += this.renderer.heading(
|
|
35
|
-
this.parseInline(token.tokens),
|
|
36
|
-
token.depth,
|
|
37
|
-
token.sourceMap,
|
|
38
|
-
);
|
|
38
|
+
out += this.renderer.heading(token);
|
|
39
39
|
continue;
|
|
40
40
|
}
|
|
41
41
|
case "code": {
|
|
42
|
-
out += this.renderer.code(token
|
|
42
|
+
out += this.renderer.code(token);
|
|
43
43
|
continue;
|
|
44
44
|
}
|
|
45
45
|
case "table": {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// header
|
|
49
|
-
let cell = "";
|
|
50
|
-
for (let j = 0, len = token.header.length; j < len; j++) {
|
|
51
|
-
cell += this.renderer.tablecell(this.parseInline(token.header[j]!.tokens), {
|
|
52
|
-
header: true,
|
|
53
|
-
align: token.align[j]!,
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
const sourceMapLineStart = token.sourceMap?.[0];
|
|
57
|
-
header += this.renderer.tablerow(cell, sourceMapLineStart);
|
|
58
|
-
|
|
59
|
-
let body = "";
|
|
60
|
-
for (let j = 0, rowsLen = token.rows.length; j < rowsLen; j++) {
|
|
61
|
-
const row = token.rows[j]!;
|
|
62
|
-
|
|
63
|
-
cell = "";
|
|
64
|
-
for (let k = 0, rowLen = row.length; k < rowLen; k++) {
|
|
65
|
-
cell += this.renderer.tablecell(this.parseInline(row[k]!.tokens), {
|
|
66
|
-
header: false,
|
|
67
|
-
align: token.align[k]!,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
body += this.renderer.tablerow(
|
|
72
|
-
cell,
|
|
73
|
-
sourceMapLineStart ? sourceMapLineStart + 2 + j : undefined,
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
out += this.renderer.table(header, body);
|
|
46
|
+
out += this.renderer.table(token);
|
|
77
47
|
continue;
|
|
78
48
|
}
|
|
79
49
|
case "alert": {
|
|
80
|
-
|
|
81
|
-
out += this.renderer.alert(body, token);
|
|
50
|
+
out += this.renderer.alert(token);
|
|
82
51
|
continue;
|
|
83
52
|
}
|
|
84
53
|
case "blockquote": {
|
|
85
|
-
|
|
86
|
-
out += this.renderer.blockquote(body);
|
|
54
|
+
out += this.renderer.blockquote(token);
|
|
87
55
|
continue;
|
|
88
56
|
}
|
|
89
57
|
case "list": {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
let body = "";
|
|
96
|
-
for (let j = 0, itemsLen = token.items.length; j < itemsLen; j++) {
|
|
97
|
-
const item = token.items[j]!;
|
|
98
|
-
const checked = item.checked;
|
|
99
|
-
const task = item.task;
|
|
100
|
-
|
|
101
|
-
let itemBody = "";
|
|
102
|
-
if (item.task) {
|
|
103
|
-
containsTaskList = true;
|
|
104
|
-
const checkbox = this.renderer.checkbox(Boolean(checked), [
|
|
105
|
-
"task-list-item-checkbox",
|
|
106
|
-
]);
|
|
107
|
-
if (loose) {
|
|
108
|
-
if (item.tokens.length > 0 && item.tokens[0]!.type === "paragraph") {
|
|
109
|
-
item.tokens[0].text = checkbox + " " + item.tokens[0].text;
|
|
110
|
-
if (
|
|
111
|
-
item.tokens[0].tokens.length > 0 &&
|
|
112
|
-
item.tokens[0].tokens[0]!.type === "text"
|
|
113
|
-
) {
|
|
114
|
-
item.tokens[0].tokens[0]!.text =
|
|
115
|
-
checkbox + " " + item.tokens[0].tokens[0]!.text;
|
|
116
|
-
}
|
|
117
|
-
} else {
|
|
118
|
-
item.tokens.unshift({
|
|
119
|
-
type: "text",
|
|
120
|
-
text: checkbox + " ",
|
|
121
|
-
} as Tokens["Text"]);
|
|
122
|
-
}
|
|
123
|
-
} else {
|
|
124
|
-
itemBody += checkbox + " ";
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
itemBody += this.parse(item.tokens, loose);
|
|
129
|
-
body += this.renderer.listitem(itemBody, task, Boolean(checked), item.sourceMap);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const listClasses: string[] = [];
|
|
133
|
-
if (containsTaskList) listClasses.push("contains-task-list");
|
|
134
|
-
out += this.renderer.list(body, ordered, start, listClasses);
|
|
58
|
+
out += this.renderer.list(token);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
case "checkbox": {
|
|
62
|
+
out += this.renderer.checkbox(token);
|
|
135
63
|
continue;
|
|
136
64
|
}
|
|
137
65
|
case "html": {
|
|
138
|
-
out += this.renderer.html(
|
|
139
|
-
token.text,
|
|
140
|
-
token.block,
|
|
141
|
-
"sourceMap" in token ? token.sourceMap : undefined,
|
|
142
|
-
);
|
|
66
|
+
out += this.renderer.html(token);
|
|
143
67
|
continue;
|
|
144
68
|
}
|
|
145
69
|
case "footnotes": {
|
|
146
|
-
|
|
147
|
-
let footnoteItem = `<li id="footnote-${encodeURIComponent(label)}">\n`;
|
|
148
|
-
footnoteItem += this.parse(content);
|
|
149
|
-
footnoteItem += "</li>\n";
|
|
150
|
-
|
|
151
|
-
footnoteItem = injectHtmlAttributes(footnoteItem, [], sourceMap);
|
|
152
|
-
|
|
153
|
-
return acc + footnoteItem;
|
|
154
|
-
}, "");
|
|
155
|
-
|
|
156
|
-
out += this.renderer.footnotes(token, body);
|
|
70
|
+
out += this.renderer.footnotes(token);
|
|
157
71
|
continue;
|
|
158
72
|
}
|
|
159
73
|
case "paragraph": {
|
|
160
|
-
out += this.renderer.paragraph(
|
|
74
|
+
out += this.renderer.paragraph(token);
|
|
161
75
|
continue;
|
|
162
76
|
}
|
|
163
77
|
case "text": {
|
|
164
|
-
let textToken
|
|
165
|
-
let body =
|
|
78
|
+
let textToken: Tokens["Text"] = token;
|
|
79
|
+
let body = this.renderer.text(textToken);
|
|
166
80
|
while (i + 1 < tokens.length && tokens[i + 1]?.type === "text") {
|
|
167
81
|
textToken = tokens[++i] as Tokens["Text"];
|
|
168
|
-
body +=
|
|
169
|
-
|
|
170
|
-
|
|
82
|
+
body += "\n" + this.renderer.text(textToken);
|
|
83
|
+
}
|
|
84
|
+
if (top) {
|
|
85
|
+
out += this.renderer.paragraph({
|
|
86
|
+
type: "paragraph",
|
|
87
|
+
raw: body,
|
|
88
|
+
text: body,
|
|
89
|
+
tokens: [{ type: "text", raw: body, text: body, escaped: true }],
|
|
90
|
+
sourceMap: textToken.sourceMap,
|
|
91
|
+
});
|
|
92
|
+
} else {
|
|
93
|
+
out += body;
|
|
171
94
|
}
|
|
172
|
-
out += top ? this.renderer.paragraph(body, textToken.sourceMap) : body;
|
|
173
95
|
continue;
|
|
174
96
|
}
|
|
175
97
|
case "latexBlock": {
|
|
176
|
-
out += this.renderer.latexBlock(token
|
|
98
|
+
out += this.renderer.latexBlock(token);
|
|
177
99
|
continue;
|
|
178
100
|
}
|
|
179
101
|
|
|
@@ -190,7 +112,7 @@ export class Parser {
|
|
|
190
112
|
/**
|
|
191
113
|
* Parse Inline Tokens
|
|
192
114
|
*/
|
|
193
|
-
parseInline(tokens: Token[]): string {
|
|
115
|
+
parseInline(tokens: Token[], renderer: Renderer | TextRenderer = this.renderer): string {
|
|
194
116
|
let out = "";
|
|
195
117
|
|
|
196
118
|
for (let i = 0, len = tokens.length; i < len; i++) {
|
|
@@ -198,51 +120,55 @@ export class Parser {
|
|
|
198
120
|
|
|
199
121
|
switch (token.type) {
|
|
200
122
|
case "escape": {
|
|
201
|
-
out +=
|
|
123
|
+
out += renderer.text(token);
|
|
202
124
|
break;
|
|
203
125
|
}
|
|
204
126
|
case "html": {
|
|
205
|
-
out +=
|
|
127
|
+
out += renderer.html(token);
|
|
206
128
|
break;
|
|
207
129
|
}
|
|
208
130
|
case "link": {
|
|
209
|
-
out +=
|
|
131
|
+
out += renderer.link(token);
|
|
210
132
|
break;
|
|
211
133
|
}
|
|
212
134
|
case "image": {
|
|
213
|
-
out +=
|
|
135
|
+
out += renderer.image(token);
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
case "checkbox": {
|
|
139
|
+
out += renderer.checkbox(token);
|
|
214
140
|
break;
|
|
215
141
|
}
|
|
216
142
|
case "strong": {
|
|
217
|
-
out +=
|
|
143
|
+
out += renderer.strong(token);
|
|
218
144
|
break;
|
|
219
145
|
}
|
|
220
146
|
case "em": {
|
|
221
|
-
out +=
|
|
147
|
+
out += renderer.em(token);
|
|
222
148
|
break;
|
|
223
149
|
}
|
|
224
150
|
case "footnoteRef": {
|
|
225
|
-
out +=
|
|
151
|
+
out += renderer.footnoteRef(token);
|
|
226
152
|
break;
|
|
227
153
|
}
|
|
228
154
|
case "codespan": {
|
|
229
|
-
out +=
|
|
155
|
+
out += renderer.codespan(token);
|
|
230
156
|
break;
|
|
231
157
|
}
|
|
232
158
|
case "br": {
|
|
233
|
-
out +=
|
|
159
|
+
out += renderer.br(token);
|
|
234
160
|
break;
|
|
235
161
|
}
|
|
236
162
|
case "del": {
|
|
237
|
-
out +=
|
|
163
|
+
out += renderer.del(token);
|
|
238
164
|
break;
|
|
239
165
|
}
|
|
240
166
|
case "text": {
|
|
241
|
-
out +=
|
|
167
|
+
out += renderer.text(token);
|
|
242
168
|
break;
|
|
243
169
|
}
|
|
244
170
|
case "latexInline": {
|
|
245
|
-
out +=
|
|
171
|
+
out += renderer.latexInline(token);
|
|
246
172
|
break;
|
|
247
173
|
}
|
|
248
174
|
default: {
|