emdp 1.0.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.
Files changed (199) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +124 -0
  3. package/dist/cjs/cli.js +36 -0
  4. package/dist/cjs/gfm.js +26 -0
  5. package/dist/cjs/index.js +26 -0
  6. package/dist/cjs/parser/block-parser.js +644 -0
  7. package/dist/cjs/parser/blocks/blockquote.js +28 -0
  8. package/dist/cjs/parser/blocks/code-block-fenced.js +58 -0
  9. package/dist/cjs/parser/blocks/code-block-indented.js +47 -0
  10. package/dist/cjs/parser/blocks/heading-atx.js +29 -0
  11. package/dist/cjs/parser/blocks/heading-setext.js +24 -0
  12. package/dist/cjs/parser/blocks/html-block.js +83 -0
  13. package/dist/cjs/parser/blocks/link-reference.js +109 -0
  14. package/dist/cjs/parser/blocks/list.js +155 -0
  15. package/dist/cjs/parser/blocks/paragraph.js +20 -0
  16. package/dist/cjs/parser/blocks/table.js +163 -0
  17. package/dist/cjs/parser/blocks/task-list.js +66 -0
  18. package/dist/cjs/parser/blocks/thematic-break.js +17 -0
  19. package/dist/cjs/parser/entities.js +2133 -0
  20. package/dist/cjs/parser/gfm/block-parser.js +773 -0
  21. package/dist/cjs/parser/gfm/index.js +125 -0
  22. package/dist/cjs/parser/gfm/inline-parser.js +813 -0
  23. package/dist/cjs/parser/gfm/renderer.js +513 -0
  24. package/dist/cjs/parser/index.js +104 -0
  25. package/dist/cjs/parser/inline-parser.js +564 -0
  26. package/dist/cjs/parser/inlines/autolink-extended.js +364 -0
  27. package/dist/cjs/parser/inlines/autolink.js +44 -0
  28. package/dist/cjs/parser/inlines/code-span.js +48 -0
  29. package/dist/cjs/parser/inlines/emphasis.js +64 -0
  30. package/dist/cjs/parser/inlines/entity.js +25 -0
  31. package/dist/cjs/parser/inlines/escape.js +25 -0
  32. package/dist/cjs/parser/inlines/footnote.js +41 -0
  33. package/dist/cjs/parser/inlines/hard-break.js +45 -0
  34. package/dist/cjs/parser/inlines/image.js +9 -0
  35. package/dist/cjs/parser/inlines/link.js +166 -0
  36. package/dist/cjs/parser/inlines/soft-break.js +18 -0
  37. package/dist/cjs/parser/inlines/strikethrough.js +48 -0
  38. package/dist/cjs/parser/inlines/text.js +20 -0
  39. package/dist/cjs/parser/renderer.js +345 -0
  40. package/dist/cjs/parser/types.js +5 -0
  41. package/dist/cjs/parser/utils.js +277 -0
  42. package/dist/cli.d.ts +6 -0
  43. package/dist/cli.js +36 -0
  44. package/dist/esm/cli.js +34 -0
  45. package/dist/esm/gfm.js +5 -0
  46. package/dist/esm/index.js +5 -0
  47. package/dist/esm/package.json +3 -0
  48. package/dist/esm/parser/block-parser.js +640 -0
  49. package/dist/esm/parser/blocks/blockquote.js +22 -0
  50. package/dist/esm/parser/blocks/code-block-fenced.js +52 -0
  51. package/dist/esm/parser/blocks/code-block-indented.js +42 -0
  52. package/dist/esm/parser/blocks/heading-atx.js +24 -0
  53. package/dist/esm/parser/blocks/heading-setext.js +19 -0
  54. package/dist/esm/parser/blocks/html-block.js +77 -0
  55. package/dist/esm/parser/blocks/link-reference.js +105 -0
  56. package/dist/esm/parser/blocks/list.js +145 -0
  57. package/dist/esm/parser/blocks/paragraph.js +15 -0
  58. package/dist/esm/parser/blocks/table.js +152 -0
  59. package/dist/esm/parser/blocks/task-list.js +61 -0
  60. package/dist/esm/parser/blocks/thematic-break.js +13 -0
  61. package/dist/esm/parser/entities.js +2130 -0
  62. package/dist/esm/parser/gfm/block-parser.js +769 -0
  63. package/dist/esm/parser/gfm/index.js +115 -0
  64. package/dist/esm/parser/gfm/inline-parser.js +809 -0
  65. package/dist/esm/parser/gfm/renderer.js +509 -0
  66. package/dist/esm/parser/index.js +80 -0
  67. package/dist/esm/parser/inline-parser.js +560 -0
  68. package/dist/esm/parser/inlines/autolink-extended.js +357 -0
  69. package/dist/esm/parser/inlines/autolink.js +40 -0
  70. package/dist/esm/parser/inlines/code-span.js +44 -0
  71. package/dist/esm/parser/inlines/emphasis.js +59 -0
  72. package/dist/esm/parser/inlines/entity.js +21 -0
  73. package/dist/esm/parser/inlines/escape.js +21 -0
  74. package/dist/esm/parser/inlines/footnote.js +38 -0
  75. package/dist/esm/parser/inlines/hard-break.js +41 -0
  76. package/dist/esm/parser/inlines/image.js +4 -0
  77. package/dist/esm/parser/inlines/link.js +156 -0
  78. package/dist/esm/parser/inlines/soft-break.js +14 -0
  79. package/dist/esm/parser/inlines/strikethrough.js +42 -0
  80. package/dist/esm/parser/inlines/text.js +16 -0
  81. package/dist/esm/parser/renderer.js +341 -0
  82. package/dist/esm/parser/types.js +4 -0
  83. package/dist/esm/parser/utils.js +254 -0
  84. package/dist/gfm.d.ts +6 -0
  85. package/dist/gfm.js +26 -0
  86. package/dist/index.d.ts +5 -0
  87. package/dist/index.js +26 -0
  88. package/dist/parser/block-parser.d.ts +25 -0
  89. package/dist/parser/block-parser.js +644 -0
  90. package/dist/parser/blocks/blockquote.d.ts +8 -0
  91. package/dist/parser/blocks/blockquote.js +28 -0
  92. package/dist/parser/blocks/code-block-fenced.d.ts +14 -0
  93. package/dist/parser/blocks/code-block-fenced.js +58 -0
  94. package/dist/parser/blocks/code-block-indented.d.ts +7 -0
  95. package/dist/parser/blocks/code-block-indented.js +47 -0
  96. package/dist/parser/blocks/heading-atx.d.ts +10 -0
  97. package/dist/parser/blocks/heading-atx.js +29 -0
  98. package/dist/parser/blocks/heading-setext.d.ts +8 -0
  99. package/dist/parser/blocks/heading-setext.js +24 -0
  100. package/dist/parser/blocks/html-block.d.ts +9 -0
  101. package/dist/parser/blocks/html-block.js +83 -0
  102. package/dist/parser/blocks/link-reference.d.ts +11 -0
  103. package/dist/parser/blocks/link-reference.js +109 -0
  104. package/dist/parser/blocks/list.d.ts +25 -0
  105. package/dist/parser/blocks/list.js +155 -0
  106. package/dist/parser/blocks/paragraph.d.ts +7 -0
  107. package/dist/parser/blocks/paragraph.js +20 -0
  108. package/dist/parser/blocks/table.d.ts +13 -0
  109. package/dist/parser/blocks/table.js +163 -0
  110. package/dist/parser/blocks/task-list.d.ts +10 -0
  111. package/dist/parser/blocks/task-list.js +66 -0
  112. package/dist/parser/blocks/thematic-break.d.ts +6 -0
  113. package/dist/parser/blocks/thematic-break.js +17 -0
  114. package/dist/parser/entities.d.ts +4 -0
  115. package/dist/parser/entities.js +2133 -0
  116. package/dist/parser/gfm/block-parser.d.ts +32 -0
  117. package/dist/parser/gfm/block-parser.js +773 -0
  118. package/dist/parser/gfm/index.d.ts +31 -0
  119. package/dist/parser/gfm/index.js +125 -0
  120. package/dist/parser/gfm/inline-parser.d.ts +25 -0
  121. package/dist/parser/gfm/inline-parser.js +813 -0
  122. package/dist/parser/gfm/renderer.d.ts +43 -0
  123. package/dist/parser/gfm/renderer.js +513 -0
  124. package/dist/parser/index.d.ts +33 -0
  125. package/dist/parser/index.js +104 -0
  126. package/dist/parser/inline-parser.d.ts +16 -0
  127. package/dist/parser/inline-parser.js +564 -0
  128. package/dist/parser/inlines/autolink-extended.d.ts +24 -0
  129. package/dist/parser/inlines/autolink-extended.js +364 -0
  130. package/dist/parser/inlines/autolink.d.ts +9 -0
  131. package/dist/parser/inlines/autolink.js +44 -0
  132. package/dist/parser/inlines/code-span.d.ts +9 -0
  133. package/dist/parser/inlines/code-span.js +48 -0
  134. package/dist/parser/inlines/emphasis.d.ts +14 -0
  135. package/dist/parser/inlines/emphasis.js +64 -0
  136. package/dist/parser/inlines/entity.d.ts +8 -0
  137. package/dist/parser/inlines/entity.js +25 -0
  138. package/dist/parser/inlines/escape.d.ts +8 -0
  139. package/dist/parser/inlines/escape.js +25 -0
  140. package/dist/parser/inlines/footnote.d.ts +9 -0
  141. package/dist/parser/inlines/footnote.js +41 -0
  142. package/dist/parser/inlines/hard-break.d.ts +9 -0
  143. package/dist/parser/inlines/hard-break.js +45 -0
  144. package/dist/parser/inlines/image.d.ts +4 -0
  145. package/dist/parser/inlines/image.js +9 -0
  146. package/dist/parser/inlines/link.d.ts +33 -0
  147. package/dist/parser/inlines/link.js +166 -0
  148. package/dist/parser/inlines/soft-break.d.ts +9 -0
  149. package/dist/parser/inlines/soft-break.js +18 -0
  150. package/dist/parser/inlines/strikethrough.d.ts +16 -0
  151. package/dist/parser/inlines/strikethrough.js +48 -0
  152. package/dist/parser/inlines/text.d.ts +6 -0
  153. package/dist/parser/inlines/text.js +20 -0
  154. package/dist/parser/renderer.d.ts +33 -0
  155. package/dist/parser/renderer.js +345 -0
  156. package/dist/parser/types.d.ts +152 -0
  157. package/dist/parser/types.js +5 -0
  158. package/dist/parser/utils.d.ts +32 -0
  159. package/dist/parser/utils.js +277 -0
  160. package/dist/types/cli.d.ts +6 -0
  161. package/dist/types/gfm.d.ts +6 -0
  162. package/dist/types/index.d.ts +5 -0
  163. package/dist/types/parser/block-parser.d.ts +25 -0
  164. package/dist/types/parser/blocks/blockquote.d.ts +8 -0
  165. package/dist/types/parser/blocks/code-block-fenced.d.ts +14 -0
  166. package/dist/types/parser/blocks/code-block-indented.d.ts +7 -0
  167. package/dist/types/parser/blocks/heading-atx.d.ts +10 -0
  168. package/dist/types/parser/blocks/heading-setext.d.ts +8 -0
  169. package/dist/types/parser/blocks/html-block.d.ts +9 -0
  170. package/dist/types/parser/blocks/link-reference.d.ts +11 -0
  171. package/dist/types/parser/blocks/list.d.ts +25 -0
  172. package/dist/types/parser/blocks/paragraph.d.ts +7 -0
  173. package/dist/types/parser/blocks/table.d.ts +13 -0
  174. package/dist/types/parser/blocks/task-list.d.ts +10 -0
  175. package/dist/types/parser/blocks/thematic-break.d.ts +6 -0
  176. package/dist/types/parser/entities.d.ts +4 -0
  177. package/dist/types/parser/gfm/block-parser.d.ts +32 -0
  178. package/dist/types/parser/gfm/index.d.ts +31 -0
  179. package/dist/types/parser/gfm/inline-parser.d.ts +25 -0
  180. package/dist/types/parser/gfm/renderer.d.ts +43 -0
  181. package/dist/types/parser/index.d.ts +33 -0
  182. package/dist/types/parser/inline-parser.d.ts +16 -0
  183. package/dist/types/parser/inlines/autolink-extended.d.ts +24 -0
  184. package/dist/types/parser/inlines/autolink.d.ts +9 -0
  185. package/dist/types/parser/inlines/code-span.d.ts +9 -0
  186. package/dist/types/parser/inlines/emphasis.d.ts +14 -0
  187. package/dist/types/parser/inlines/entity.d.ts +8 -0
  188. package/dist/types/parser/inlines/escape.d.ts +8 -0
  189. package/dist/types/parser/inlines/footnote.d.ts +9 -0
  190. package/dist/types/parser/inlines/hard-break.d.ts +9 -0
  191. package/dist/types/parser/inlines/image.d.ts +4 -0
  192. package/dist/types/parser/inlines/link.d.ts +33 -0
  193. package/dist/types/parser/inlines/soft-break.d.ts +9 -0
  194. package/dist/types/parser/inlines/strikethrough.d.ts +16 -0
  195. package/dist/types/parser/inlines/text.d.ts +6 -0
  196. package/dist/types/parser/renderer.d.ts +33 -0
  197. package/dist/types/parser/types.d.ts +152 -0
  198. package/dist/types/parser/utils.d.ts +32 -0
  199. package/package.json +54 -0
@@ -0,0 +1,560 @@
1
+ /**
2
+ * Inline parsing phase that builds inline nodes such as emphasis, links, images, code spans,
3
+ * autolinks, and HTML.
4
+ */
5
+ import { parseEscape } from './inlines/escape.js';
6
+ import { parseEntity } from './inlines/entity.js';
7
+ import { parseCodeSpan } from './inlines/code-span.js';
8
+ import { parseDelimiterRun, canDelimitersMatch } from './inlines/emphasis.js';
9
+ import { parseAutolink } from './inlines/autolink.js';
10
+ import { parseInlineLink, parseLinkLabel, createLinkNode, createImageNode } from './inlines/link.js';
11
+ import { createTextNode } from './inlines/text.js';
12
+ import { normalizeLabel } from './utils.js';
13
+ export class InlineParser {
14
+ linkReferences = new Map();
15
+ setLinkReferences(refs) {
16
+ this.linkReferences = refs;
17
+ }
18
+ parse(text) {
19
+ const nodes = [];
20
+ let delimiterStack = null;
21
+ let bracketStack = null;
22
+ let pos = 0;
23
+ let textBuffer = '';
24
+ const flushText = () => {
25
+ if (textBuffer.length > 0) {
26
+ nodes.push(createTextNode(textBuffer));
27
+ textBuffer = '';
28
+ }
29
+ };
30
+ const pushDelimiter = (run, node) => {
31
+ const d = {
32
+ run,
33
+ node,
34
+ active: true,
35
+ prev: delimiterStack,
36
+ next: null,
37
+ };
38
+ if (delimiterStack) {
39
+ delimiterStack.next = d;
40
+ }
41
+ delimiterStack = d;
42
+ };
43
+ while (pos < text.length) {
44
+ const char = text[pos];
45
+ const escapeResult = parseEscape(text, pos);
46
+ if (escapeResult) {
47
+ if (escapeResult.char === '\n') {
48
+ textBuffer = textBuffer.replace(/ *$/, '');
49
+ flushText();
50
+ nodes.push({ type: 'hardbreak' });
51
+ pos += escapeResult.length;
52
+ while (pos < text.length && text[pos] === ' ') {
53
+ pos++;
54
+ }
55
+ }
56
+ else if (escapeResult.char === '*' || escapeResult.char === '_') {
57
+ flushText();
58
+ nodes.push(createTextNode(escapeResult.char, true));
59
+ pos += escapeResult.length;
60
+ }
61
+ else if (escapeResult.char === '"' || escapeResult.char === "'" ||
62
+ escapeResult.char === '-' || escapeResult.char === '.') {
63
+ flushText();
64
+ const node = createTextNode(escapeResult.char);
65
+ node.noSmart = true;
66
+ nodes.push(node);
67
+ pos += escapeResult.length;
68
+ }
69
+ else {
70
+ textBuffer += escapeResult.char;
71
+ pos += escapeResult.length;
72
+ }
73
+ continue;
74
+ }
75
+ const entityResult = parseEntity(text, pos);
76
+ if (entityResult) {
77
+ textBuffer += entityResult.char;
78
+ pos += entityResult.length;
79
+ continue;
80
+ }
81
+ if (char === '`') {
82
+ const codeSpanResult = parseCodeSpan(text, pos);
83
+ if (codeSpanResult) {
84
+ flushText();
85
+ nodes.push(codeSpanResult.node);
86
+ pos += codeSpanResult.length;
87
+ continue;
88
+ }
89
+ else {
90
+ textBuffer += char;
91
+ pos++;
92
+ while (pos < text.length && text[pos] === '`') {
93
+ textBuffer += text[pos];
94
+ pos++;
95
+ }
96
+ continue;
97
+ }
98
+ }
99
+ if (char === '<') {
100
+ const autolinkResult = parseAutolink(text, pos);
101
+ if (autolinkResult) {
102
+ flushText();
103
+ nodes.push(autolinkResult.node);
104
+ pos += autolinkResult.length;
105
+ continue;
106
+ }
107
+ const openingTagMatch = text.slice(pos).match(/^<[a-zA-Z][a-zA-Z0-9-]*(?:\s+[a-zA-Z_:][a-zA-Z0-9_.:-]*(?:\s*=\s*(?:[^\s"'=<>`]+|'[^']*'|"[^"]*"))?)*\s*\/?>/);
108
+ if (openingTagMatch) {
109
+ flushText();
110
+ nodes.push({ type: 'html_inline', literal: openingTagMatch[0] });
111
+ pos += openingTagMatch[0].length;
112
+ continue;
113
+ }
114
+ const closingTagMatch = text.slice(pos).match(/^<\/[a-zA-Z][a-zA-Z0-9-]*\s*>/);
115
+ if (closingTagMatch) {
116
+ flushText();
117
+ nodes.push({ type: 'html_inline', literal: closingTagMatch[0] });
118
+ pos += closingTagMatch[0].length;
119
+ continue;
120
+ }
121
+ const shortCommentMatch = text.slice(pos).match(/^<!---?>/);
122
+ if (shortCommentMatch) {
123
+ flushText();
124
+ nodes.push({ type: 'html_inline', literal: '<!---->' });
125
+ pos += shortCommentMatch[0].length;
126
+ continue;
127
+ }
128
+ const commentMatch = text.slice(pos).match(/^<!--(?!>)(?!-?>)[\s\S]*?-->/);
129
+ if (commentMatch) {
130
+ flushText();
131
+ nodes.push({ type: 'html_inline', literal: commentMatch[0] });
132
+ pos += commentMatch[0].length;
133
+ continue;
134
+ }
135
+ const piMatch = text.slice(pos).match(/^<\?[\s\S]*?\?>/);
136
+ if (piMatch) {
137
+ flushText();
138
+ nodes.push({ type: 'html_inline', literal: piMatch[0] });
139
+ pos += piMatch[0].length;
140
+ continue;
141
+ }
142
+ const cdataMatch = text.slice(pos).match(/^<!\[CDATA\[[\s\S]*?\]\]>/);
143
+ if (cdataMatch) {
144
+ flushText();
145
+ nodes.push({ type: 'html_inline', literal: cdataMatch[0] });
146
+ pos += cdataMatch[0].length;
147
+ continue;
148
+ }
149
+ const declMatch = text.slice(pos).match(/^<![a-zA-Z][\s\S]*?>/);
150
+ if (declMatch) {
151
+ flushText();
152
+ nodes.push({ type: 'html_inline', literal: declMatch[0] });
153
+ pos += declMatch[0].length;
154
+ continue;
155
+ }
156
+ }
157
+ if (char === ' ') {
158
+ let spaceCount = 0;
159
+ let j = pos;
160
+ while (j < text.length && text[j] === ' ') {
161
+ spaceCount++;
162
+ j++;
163
+ }
164
+ if (text[j] === '\n' && spaceCount >= 2) {
165
+ textBuffer = textBuffer.replace(/ *$/, '');
166
+ flushText();
167
+ nodes.push({ type: 'hardbreak' });
168
+ pos = j + 1;
169
+ while (pos < text.length && text[pos] === ' ') {
170
+ pos++;
171
+ }
172
+ continue;
173
+ }
174
+ }
175
+ if (char === '\n') {
176
+ textBuffer = textBuffer.replace(/ *$/, '');
177
+ flushText();
178
+ nodes.push({ type: 'softbreak' });
179
+ pos++;
180
+ while (pos < text.length && text[pos] === ' ') {
181
+ pos++;
182
+ }
183
+ continue;
184
+ }
185
+ if (char === '*' || char === '_') {
186
+ flushText();
187
+ const run = parseDelimiterRun(text, pos);
188
+ if (run) {
189
+ const node = createTextNode(text.slice(pos, pos + run.length));
190
+ node.delimiterOrigLength = run.length;
191
+ nodes.push(node);
192
+ if (run.canOpen || run.canClose) {
193
+ pushDelimiter(run, node);
194
+ }
195
+ pos += run.length;
196
+ continue;
197
+ }
198
+ }
199
+ if (char === '!' && text[pos + 1] === '[') {
200
+ flushText();
201
+ const node = createTextNode('![');
202
+ nodes.push(node);
203
+ const bracket = {
204
+ type: 'image',
205
+ node,
206
+ nodeIndex: nodes.length - 1,
207
+ active: true,
208
+ prev: bracketStack,
209
+ bracketAfter: false,
210
+ delimiterBefore: delimiterStack,
211
+ textPos: pos + 2,
212
+ };
213
+ if (bracketStack)
214
+ bracketStack.bracketAfter = true;
215
+ bracketStack = bracket;
216
+ pos += 2;
217
+ continue;
218
+ }
219
+ if (char === '[') {
220
+ flushText();
221
+ const node = createTextNode('[');
222
+ nodes.push(node);
223
+ const bracket = {
224
+ type: 'link',
225
+ node,
226
+ nodeIndex: nodes.length - 1,
227
+ active: true,
228
+ prev: bracketStack,
229
+ bracketAfter: false,
230
+ delimiterBefore: delimiterStack,
231
+ textPos: pos + 1,
232
+ };
233
+ if (bracketStack)
234
+ bracketStack.bracketAfter = true;
235
+ bracketStack = bracket;
236
+ pos += 1;
237
+ continue;
238
+ }
239
+ if (char === ']' && bracketStack) {
240
+ flushText();
241
+ let opener = bracketStack;
242
+ if (!opener) {
243
+ textBuffer += ']';
244
+ pos++;
245
+ continue;
246
+ }
247
+ if (!opener.active) {
248
+ bracketStack = opener.prev;
249
+ textBuffer += ']';
250
+ pos++;
251
+ continue;
252
+ }
253
+ let matched = false;
254
+ let destination = '';
255
+ let title = '';
256
+ let consumed = 1;
257
+ if (text[pos + 1] === '(') {
258
+ const linkResult = parseInlineLink(text, pos + 1);
259
+ if (linkResult) {
260
+ matched = true;
261
+ destination = linkResult.destination;
262
+ title = linkResult.title;
263
+ consumed = 1 + linkResult.length;
264
+ }
265
+ }
266
+ if (!matched && text[pos + 1] === '[') {
267
+ const labelResult = parseLinkLabel(text, pos + 1);
268
+ if (labelResult && labelResult.label) {
269
+ if (this.linkReferences.has(labelResult.label)) {
270
+ matched = true;
271
+ const ref = this.linkReferences.get(labelResult.label);
272
+ destination = ref.destination;
273
+ title = ref.title;
274
+ consumed = 1 + labelResult.length;
275
+ }
276
+ }
277
+ else if (labelResult && labelResult.label === '') {
278
+ const innerText = this.extractTextFromNodes(nodes.slice(opener.nodeIndex + 1));
279
+ const label = normalizeLabel(innerText);
280
+ if (this.linkReferences.has(label)) {
281
+ matched = true;
282
+ const ref = this.linkReferences.get(label);
283
+ destination = ref.destination;
284
+ title = ref.title;
285
+ consumed = 1 + labelResult.length;
286
+ }
287
+ }
288
+ }
289
+ if (!matched && text[pos + 1] !== '[') {
290
+ const rawLabel = text.slice(opener.textPos, pos);
291
+ const label = normalizeLabel(this.normalizeLabelForMatching(rawLabel));
292
+ if (label && this.linkReferences.has(label)) {
293
+ matched = true;
294
+ const ref = this.linkReferences.get(label);
295
+ destination = ref.destination;
296
+ title = ref.title;
297
+ }
298
+ }
299
+ if (matched) {
300
+ const innerNodes = nodes.splice(opener.nodeIndex + 1);
301
+ nodes.pop();
302
+ this.processEmphasis(innerNodes, opener.delimiterBefore);
303
+ if (opener.type === 'image') {
304
+ const alt = this.extractTextFromNodes(innerNodes);
305
+ nodes.push(createImageNode(destination, title, alt));
306
+ }
307
+ else {
308
+ const linkNode = createLinkNode(destination, title);
309
+ linkNode.children = innerNodes;
310
+ nodes.push(linkNode);
311
+ }
312
+ if (opener.type === 'link') {
313
+ let b = opener.prev;
314
+ while (b) {
315
+ if (b.type === 'link')
316
+ b.active = false;
317
+ b = b.prev;
318
+ }
319
+ }
320
+ bracketStack = opener.prev;
321
+ pos += consumed;
322
+ }
323
+ else {
324
+ bracketStack = opener.prev;
325
+ textBuffer += ']';
326
+ pos++;
327
+ }
328
+ continue;
329
+ }
330
+ textBuffer += char;
331
+ pos++;
332
+ }
333
+ flushText();
334
+ this.processEmphasis(nodes, null);
335
+ return nodes;
336
+ }
337
+ extractTextFromNodes(nodes) {
338
+ let result = '';
339
+ for (const node of nodes) {
340
+ if (node.type === 'text') {
341
+ result += node.literal;
342
+ }
343
+ else if (node.type === 'code_span') {
344
+ result += node.literal;
345
+ }
346
+ else if (node.type === 'image') {
347
+ result += node.alt;
348
+ }
349
+ else if (node.type === 'softbreak' || node.type === 'hardbreak') {
350
+ result += ' ';
351
+ }
352
+ else if ('children' in node && Array.isArray(node.children)) {
353
+ result += this.extractTextFromNodes(node.children);
354
+ }
355
+ }
356
+ return result;
357
+ }
358
+ normalizeLabelForMatching(rawLabel) {
359
+ let result = '';
360
+ let i = 0;
361
+ while (i < rawLabel.length) {
362
+ if (rawLabel[i] === '\\' && i + 1 < rawLabel.length) {
363
+ const next = rawLabel[i + 1];
364
+ if (next === '[' || next === ']' || next === '\\') {
365
+ result += next;
366
+ i += 2;
367
+ continue;
368
+ }
369
+ }
370
+ result += rawLabel[i];
371
+ i++;
372
+ }
373
+ return result;
374
+ }
375
+ processEmphasis(nodes, stackBottom) {
376
+ const delimiters = [];
377
+ let prevDelim = null;
378
+ for (let i = 0; i < nodes.length; i++) {
379
+ const node = nodes[i];
380
+ if (node.type === 'text' && (node.literal.match(/^[*_]+$/) || node.literal === '')) {
381
+ }
382
+ }
383
+ const nodeDelims = [];
384
+ for (let i = 0; i < nodes.length; i++) {
385
+ const node = nodes[i];
386
+ if (node.type === 'text' && node.literal.length > 0 && !node.noDelim) {
387
+ const firstChar = node.literal[0];
388
+ if ((firstChar === '*' || firstChar === '_') && node.literal.match(/^[*_]+$/)) {
389
+ const beforeNode = i > 0 ? nodes[i - 1] : null;
390
+ const afterNode = i < nodes.length - 1 ? nodes[i + 1] : null;
391
+ let charBefore = '\n';
392
+ if (beforeNode) {
393
+ if (beforeNode.type === 'text') {
394
+ charBefore = this.getLastChar(beforeNode.literal);
395
+ }
396
+ else if (beforeNode.type === 'softbreak' || beforeNode.type === 'hardbreak') {
397
+ charBefore = '\n';
398
+ }
399
+ else {
400
+ charBefore = 'a';
401
+ }
402
+ }
403
+ let charAfter = '\n';
404
+ if (afterNode) {
405
+ if (afterNode.type === 'text') {
406
+ charAfter = this.getFirstChar(afterNode.literal);
407
+ }
408
+ else if (afterNode.type === 'softbreak' || afterNode.type === 'hardbreak') {
409
+ charAfter = '\n';
410
+ }
411
+ else {
412
+ charAfter = 'a';
413
+ }
414
+ }
415
+ const run = this.computeDelimiterRun(node.literal, charBefore, charAfter);
416
+ node.delimiterOrigLength = node.delimiterOrigLength ?? node.literal.length;
417
+ run.origLength = node.delimiterOrigLength;
418
+ if (run.canOpen || run.canClose) {
419
+ nodeDelims.push({ node, index: i, run });
420
+ }
421
+ }
422
+ }
423
+ }
424
+ if (nodeDelims.length === 0)
425
+ return;
426
+ const openerBottomByChar = { '*': -1, '_': -1 };
427
+ let closerIdx = 0;
428
+ while (closerIdx < nodeDelims.length) {
429
+ const closer = nodeDelims[closerIdx];
430
+ if (!closer.run.canClose) {
431
+ closerIdx++;
432
+ continue;
433
+ }
434
+ let openerIdx = closerIdx - 1;
435
+ let openerFound = false;
436
+ while (openerIdx >= 0 && openerIdx > openerBottomByChar[closer.run.char]) {
437
+ const opener = nodeDelims[openerIdx];
438
+ if (opener.run.canOpen && opener.run.char === closer.run.char &&
439
+ canDelimitersMatch(opener.run, closer.run)) {
440
+ openerFound = true;
441
+ break;
442
+ }
443
+ openerIdx--;
444
+ }
445
+ if (!openerFound) {
446
+ if (!closer.run.canOpen) {
447
+ openerBottomByChar[closer.run.char] = closerIdx - 1;
448
+ }
449
+ closerIdx++;
450
+ continue;
451
+ }
452
+ const opener = nodeDelims[openerIdx];
453
+ const strong = opener.run.length >= 2 && closer.run.length >= 2;
454
+ const numDelims = strong ? 2 : 1;
455
+ opener.node.literal = opener.node.literal.slice(0, -numDelims);
456
+ closer.node.literal = closer.node.literal.slice(numDelims);
457
+ opener.run.length -= numDelims;
458
+ closer.run.length -= numDelims;
459
+ const openerNodeIdx = nodes.indexOf(opener.node);
460
+ const closerNodeIdx = nodes.indexOf(closer.node);
461
+ const contentNodes = nodes.slice(openerNodeIdx + 1, closerNodeIdx);
462
+ const emphNode = strong
463
+ ? { type: 'strong', children: contentNodes }
464
+ : { type: 'emphasis', children: contentNodes };
465
+ nodes.splice(openerNodeIdx + 1, closerNodeIdx - openerNodeIdx - 1, emphNode);
466
+ const shift = closerNodeIdx - openerNodeIdx - 2;
467
+ for (let i = openerIdx + 1; i < nodeDelims.length; i++) {
468
+ if (i < closerIdx) {
469
+ nodeDelims[i].run.length = 0;
470
+ }
471
+ }
472
+ if (opener.run.length === 0) {
473
+ const idx = nodes.indexOf(opener.node);
474
+ if (idx !== -1 && opener.node.literal === '') {
475
+ nodes.splice(idx, 1);
476
+ }
477
+ }
478
+ if (closer.run.length === 0) {
479
+ const idx = nodes.indexOf(closer.node);
480
+ if (idx !== -1 && closer.node.literal === '') {
481
+ nodes.splice(idx, 1);
482
+ }
483
+ }
484
+ nodeDelims.length = 0;
485
+ for (let i = 0; i < nodes.length; i++) {
486
+ const node = nodes[i];
487
+ if (node.type === 'text' && node.literal.length > 0 && !node.noDelim) {
488
+ const firstChar = node.literal[0];
489
+ if ((firstChar === '*' || firstChar === '_') && node.literal.match(/^[*_]+$/)) {
490
+ const beforeNode = i > 0 ? nodes[i - 1] : null;
491
+ const afterNode = i < nodes.length - 1 ? nodes[i + 1] : null;
492
+ let charBefore = '\n';
493
+ let charAfter = '\n';
494
+ if (beforeNode) {
495
+ if (beforeNode.type === 'text')
496
+ charBefore = this.getLastChar(beforeNode.literal);
497
+ else if (beforeNode.type !== 'softbreak' && beforeNode.type !== 'hardbreak')
498
+ charBefore = 'a';
499
+ }
500
+ if (afterNode) {
501
+ if (afterNode.type === 'text')
502
+ charAfter = this.getFirstChar(afterNode.literal);
503
+ else if (afterNode.type !== 'softbreak' && afterNode.type !== 'hardbreak')
504
+ charAfter = 'a';
505
+ }
506
+ const run = this.computeDelimiterRun(node.literal, charBefore, charAfter);
507
+ node.delimiterOrigLength = node.delimiterOrigLength ?? node.literal.length;
508
+ run.origLength = node.delimiterOrigLength;
509
+ if (run.canOpen || run.canClose) {
510
+ nodeDelims.push({ node, index: i, run });
511
+ }
512
+ }
513
+ }
514
+ }
515
+ closerIdx = 0;
516
+ }
517
+ for (let i = nodes.length - 1; i >= 0; i--) {
518
+ const node = nodes[i];
519
+ if (node.type === 'text' && node.literal === '') {
520
+ nodes.splice(i, 1);
521
+ }
522
+ }
523
+ }
524
+ computeDelimiterRun(literal, charBefore, charAfter) {
525
+ const char = literal[0];
526
+ const length = literal.length;
527
+ const isWhitespace = (c) => /\s/.test(c) || c === '\n';
528
+ const isPunctuation = (c) => /[\p{P}\p{S}]/u.test(c);
529
+ const beforeIsWhitespace = isWhitespace(charBefore);
530
+ const afterIsWhitespace = isWhitespace(charAfter);
531
+ const beforeIsPunctuation = isPunctuation(charBefore);
532
+ const afterIsPunctuation = isPunctuation(charAfter);
533
+ const leftFlanking = !afterIsWhitespace &&
534
+ (!afterIsPunctuation || beforeIsWhitespace || beforeIsPunctuation);
535
+ const rightFlanking = !beforeIsWhitespace &&
536
+ (!beforeIsPunctuation || afterIsWhitespace || afterIsPunctuation);
537
+ let canOpen;
538
+ let canClose;
539
+ if (char === '*') {
540
+ canOpen = leftFlanking;
541
+ canClose = rightFlanking;
542
+ }
543
+ else {
544
+ canOpen = leftFlanking && (!rightFlanking || beforeIsPunctuation);
545
+ canClose = rightFlanking && (!leftFlanking || afterIsPunctuation);
546
+ }
547
+ return { char, length, canOpen, canClose, position: 0, origLength: length };
548
+ }
549
+ getFirstChar(text) {
550
+ if (!text)
551
+ return '\n';
552
+ return Array.from(text)[0] ?? '\n';
553
+ }
554
+ getLastChar(text) {
555
+ if (!text)
556
+ return '\n';
557
+ const chars = Array.from(text);
558
+ return chars.length > 0 ? chars[chars.length - 1] : '\n';
559
+ }
560
+ }