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,640 @@
1
+ /**
2
+ * Block parsing phase that builds block nodes like paragraphs, headings, lists, code blocks,
3
+ * blockquotes, and HTML blocks while collecting link reference definitions.
4
+ */
5
+ import { normalizeLineEndings, removeIndent, unescapeString, decodeHtmlEntities } from './utils.js';
6
+ import { isThematicBreak, parseThematicBreak } from './blocks/thematic-break.js';
7
+ import { parseAtxHeading, createHeadingNode } from './blocks/heading-atx.js';
8
+ import { getSetextLevel } from './blocks/heading-setext.js';
9
+ import { createIndentedCodeBlock } from './blocks/code-block-indented.js';
10
+ import { parseFenceOpen, isFenceClose, createFencedCodeBlock } from './blocks/code-block-fenced.js';
11
+ import { createBlockquoteNode } from './blocks/blockquote.js';
12
+ import { parseListMarker, createListNode, createListItemNode, listsMatch } from './blocks/list.js';
13
+ import { getHtmlBlockType, isHtmlBlockClose, createHtmlBlockNode } from './blocks/html-block.js';
14
+ import { createParagraphNode } from './blocks/paragraph.js';
15
+ import { parseLinkReferenceDefinition } from './blocks/link-reference.js';
16
+ function parseLine(raw) {
17
+ let indent = 0;
18
+ let i = 0;
19
+ while (i < raw.length) {
20
+ if (raw[i] === ' ') {
21
+ indent++;
22
+ i++;
23
+ }
24
+ else if (raw[i] === '\t') {
25
+ indent += 4 - (indent % 4);
26
+ i++;
27
+ }
28
+ else {
29
+ break;
30
+ }
31
+ }
32
+ return { raw, content: raw.slice(i), indent };
33
+ }
34
+ function getIndent(raw) {
35
+ let indent = 0;
36
+ for (const char of raw) {
37
+ if (char === ' ')
38
+ indent++;
39
+ else if (char === '\t')
40
+ indent += 4 - (indent % 4);
41
+ else
42
+ break;
43
+ }
44
+ return indent;
45
+ }
46
+ export class BlockParser {
47
+ lines = [];
48
+ lineIndex = 0;
49
+ linkReferences = new Map();
50
+ static LAZY_PREFIX = '\u0000';
51
+ parse(input) {
52
+ this.lines = normalizeLineEndings(input).split('\n');
53
+ this.lineIndex = 0;
54
+ this.linkReferences = new Map();
55
+ const document = {
56
+ type: 'document',
57
+ children: [],
58
+ };
59
+ this.parseBlocks(document, 0);
60
+ return { document, linkReferences: this.linkReferences };
61
+ }
62
+ currentLine() {
63
+ return this.lines[this.lineIndex];
64
+ }
65
+ advance() {
66
+ this.lineIndex++;
67
+ }
68
+ parseBlocks(container, baseIndent) {
69
+ let paragraphLines = [];
70
+ let paragraphCanBeInterrupted = true;
71
+ const finishParagraph = () => {
72
+ if (paragraphLines.length > 0) {
73
+ let text = paragraphLines.join('\n');
74
+ let consumed = 0;
75
+ while (text.length > 0) {
76
+ const result = parseLinkReferenceDefinition(text);
77
+ if (!result)
78
+ break;
79
+ if (!this.linkReferences.has(result.label)) {
80
+ this.linkReferences.set(result.label, result.definition);
81
+ }
82
+ text = text.slice(result.consumed);
83
+ consumed += result.consumed;
84
+ }
85
+ text = text.trim();
86
+ if (text.length > 0) {
87
+ const para = createParagraphNode();
88
+ para.rawContent = text;
89
+ container.children.push(para);
90
+ }
91
+ paragraphLines = [];
92
+ paragraphCanBeInterrupted = true;
93
+ return consumed > 0 || text.length > 0;
94
+ }
95
+ return false;
96
+ };
97
+ while (this.lineIndex < this.lines.length) {
98
+ const line = this.currentLine();
99
+ if (line.startsWith(BlockParser.LAZY_PREFIX)) {
100
+ const raw = line.slice(BlockParser.LAZY_PREFIX.length);
101
+ const rawIndent = getIndent(raw);
102
+ paragraphLines.push(removeIndent(raw, Math.min(rawIndent, 3)));
103
+ this.advance();
104
+ continue;
105
+ }
106
+ const lineIndent = getIndent(line);
107
+ if (line.trim() === '') {
108
+ finishParagraph();
109
+ this.advance();
110
+ continue;
111
+ }
112
+ const dedented = removeIndent(line, Math.min(3, lineIndent));
113
+ const dedentedIndent = getIndent(dedented);
114
+ if (isThematicBreak(line)) {
115
+ if (paragraphLines.length > 0 && /^ {0,3}-+[ \t]*$/.test(line)) {
116
+ const level = getSetextLevel(line);
117
+ let content = paragraphLines.join('\n');
118
+ while (content.length > 0) {
119
+ const result = parseLinkReferenceDefinition(content);
120
+ if (!result)
121
+ break;
122
+ if (!this.linkReferences.has(result.label)) {
123
+ this.linkReferences.set(result.label, result.definition);
124
+ }
125
+ content = content.slice(result.consumed);
126
+ }
127
+ content = content.trim();
128
+ paragraphLines = [];
129
+ if (content.length > 0) {
130
+ const heading = createHeadingNode(level);
131
+ heading.rawContent = content;
132
+ container.children.push(heading);
133
+ }
134
+ else {
135
+ container.children.push(parseThematicBreak(line));
136
+ }
137
+ this.advance();
138
+ continue;
139
+ }
140
+ finishParagraph();
141
+ container.children.push(parseThematicBreak(line));
142
+ this.advance();
143
+ continue;
144
+ }
145
+ const atxResult = parseAtxHeading(line);
146
+ if (atxResult) {
147
+ finishParagraph();
148
+ const heading = createHeadingNode(atxResult.level);
149
+ heading.rawContent = atxResult.content;
150
+ container.children.push(heading);
151
+ this.advance();
152
+ continue;
153
+ }
154
+ if (paragraphLines.length > 0 && /^ {0,3}=+[ \t]*$/.test(line)) {
155
+ let content = paragraphLines.join('\n');
156
+ while (content.length > 0) {
157
+ const result = parseLinkReferenceDefinition(content);
158
+ if (!result)
159
+ break;
160
+ if (!this.linkReferences.has(result.label)) {
161
+ this.linkReferences.set(result.label, result.definition);
162
+ }
163
+ content = content.slice(result.consumed);
164
+ }
165
+ content = content.trim();
166
+ paragraphLines = [];
167
+ if (content.length > 0) {
168
+ const heading = createHeadingNode(1);
169
+ heading.rawContent = content;
170
+ container.children.push(heading);
171
+ }
172
+ else {
173
+ paragraphLines.push(line);
174
+ }
175
+ this.advance();
176
+ continue;
177
+ }
178
+ const fenceInfo = parseFenceOpen(line);
179
+ if (fenceInfo) {
180
+ finishParagraph();
181
+ const codeLines = [];
182
+ this.advance();
183
+ let closedProperly = false;
184
+ while (this.lineIndex < this.lines.length) {
185
+ const codeLine = this.currentLine();
186
+ if (isFenceClose(codeLine, fenceInfo)) {
187
+ this.advance();
188
+ closedProperly = true;
189
+ break;
190
+ }
191
+ codeLines.push(codeLine);
192
+ this.advance();
193
+ }
194
+ if (!closedProperly) {
195
+ while (codeLines.length > 0 && codeLines[codeLines.length - 1] === '') {
196
+ codeLines.pop();
197
+ }
198
+ }
199
+ const info = unescapeString(decodeHtmlEntities(fenceInfo.info));
200
+ container.children.push(createFencedCodeBlock(info, codeLines, fenceInfo.indent));
201
+ continue;
202
+ }
203
+ if (paragraphLines.length === 0 && lineIndent >= 4) {
204
+ const codeLines = [removeIndent(line, 4)];
205
+ this.advance();
206
+ while (this.lineIndex < this.lines.length) {
207
+ const codeLine = this.currentLine();
208
+ const codeIndent = getIndent(codeLine);
209
+ if (codeIndent >= 4) {
210
+ codeLines.push(removeIndent(codeLine, 4));
211
+ this.advance();
212
+ }
213
+ else if (codeLine.trim() === '') {
214
+ codeLines.push('');
215
+ this.advance();
216
+ }
217
+ else {
218
+ break;
219
+ }
220
+ }
221
+ while (codeLines.length > 0 && codeLines[codeLines.length - 1] === '') {
222
+ codeLines.pop();
223
+ }
224
+ container.children.push(createIndentedCodeBlock(codeLines));
225
+ continue;
226
+ }
227
+ const bqMatch = line.match(/^ {0,3}>([ \t]?)/);
228
+ if (bqMatch) {
229
+ finishParagraph();
230
+ const blockquote = createBlockquoteNode();
231
+ const quoteLines = [];
232
+ let inFence = null;
233
+ while (this.lineIndex < this.lines.length) {
234
+ const quoteLine = this.currentLine();
235
+ const qMatch = quoteLine.match(/^ {0,3}>([ \t]?)/);
236
+ if (qMatch) {
237
+ const content = this.extractBlockquoteContent(quoteLine, qMatch);
238
+ quoteLines.push(content);
239
+ if (inFence) {
240
+ if (isFenceClose(content, inFence)) {
241
+ inFence = null;
242
+ }
243
+ }
244
+ else {
245
+ const fenceInfo = parseFenceOpen(content);
246
+ if (fenceInfo) {
247
+ inFence = fenceInfo;
248
+ }
249
+ }
250
+ this.advance();
251
+ }
252
+ else if (quoteLine.trim() === '') {
253
+ break;
254
+ }
255
+ else if (quoteLines.length > 0) {
256
+ if (inFence) {
257
+ break;
258
+ }
259
+ if (isThematicBreak(quoteLine) || parseFenceOpen(quoteLine)) {
260
+ break;
261
+ }
262
+ if (quoteLines[quoteLines.length - 1].trim() === '') {
263
+ break;
264
+ }
265
+ const lastContent = this.lastNonBlankLine(quoteLines);
266
+ if (lastContent &&
267
+ !parseFenceOpen(lastContent) &&
268
+ getIndent(lastContent) < 4 &&
269
+ this.allowsLazyAfterListMarker(lastContent)) {
270
+ const nestedPrefix = this.getBlockquotePrefix(lastContent);
271
+ quoteLines.push(nestedPrefix + BlockParser.LAZY_PREFIX + quoteLine);
272
+ this.advance();
273
+ }
274
+ else {
275
+ break;
276
+ }
277
+ }
278
+ else {
279
+ break;
280
+ }
281
+ }
282
+ const subParser = new BlockParser();
283
+ const result = subParser.parse(quoteLines.join('\n'));
284
+ blockquote.children = result.document.children;
285
+ result.linkReferences.forEach((def, label) => {
286
+ if (!this.linkReferences.has(label)) {
287
+ this.linkReferences.set(label, def);
288
+ }
289
+ });
290
+ container.children.push(blockquote);
291
+ continue;
292
+ }
293
+ const listMarker = parseListMarker(line);
294
+ if (listMarker) {
295
+ const canInterrupt = paragraphLines.length === 0 ||
296
+ (listMarker.type === 'bullet' || listMarker.start === 1) &&
297
+ line.slice(listMarker.indent + listMarker.marker.length + listMarker.padding).trim() !== '';
298
+ if (canInterrupt) {
299
+ finishParagraph();
300
+ const list = createListNode(listMarker);
301
+ this.parseList(list, listMarker);
302
+ container.children.push(list);
303
+ continue;
304
+ }
305
+ }
306
+ const htmlType = getHtmlBlockType(line, paragraphLines.length === 0);
307
+ if (htmlType !== null) {
308
+ finishParagraph();
309
+ const htmlLines = [line];
310
+ const closeOnSameLine = htmlType >= 1 && htmlType <= 5 && isHtmlBlockClose(line, htmlType);
311
+ this.advance();
312
+ if (!closeOnSameLine) {
313
+ while (this.lineIndex < this.lines.length) {
314
+ const htmlLine = this.currentLine();
315
+ if (htmlType === 6 || htmlType === 7) {
316
+ if (htmlLine.trim() === '') {
317
+ break;
318
+ }
319
+ htmlLines.push(htmlLine);
320
+ this.advance();
321
+ }
322
+ else {
323
+ htmlLines.push(htmlLine);
324
+ this.advance();
325
+ if (isHtmlBlockClose(htmlLine, htmlType)) {
326
+ break;
327
+ }
328
+ }
329
+ }
330
+ }
331
+ container.children.push(createHtmlBlockNode(htmlLines.join('\n') + '\n'));
332
+ continue;
333
+ }
334
+ paragraphLines.push(removeIndent(line, Math.min(lineIndent, 3)));
335
+ this.advance();
336
+ }
337
+ finishParagraph();
338
+ }
339
+ parseList(list, firstMarker) {
340
+ let sawBlankLine = false;
341
+ let sawBlankLineInItem = false;
342
+ let sawBlankBetweenItems = false;
343
+ while (this.lineIndex < this.lines.length) {
344
+ const line = this.currentLine();
345
+ if (isThematicBreak(line)) {
346
+ break;
347
+ }
348
+ const marker = parseListMarker(line);
349
+ if (marker && listsMatch(firstMarker, marker)) {
350
+ if (sawBlankLine) {
351
+ sawBlankBetweenItems = true;
352
+ }
353
+ sawBlankLine = false;
354
+ const item = createListItemNode();
355
+ const itemResult = this.parseListItem(item, marker);
356
+ if (itemResult.blankInItem) {
357
+ sawBlankLineInItem = true;
358
+ }
359
+ if (itemResult.endsWithBlank) {
360
+ sawBlankLine = true;
361
+ }
362
+ list.children.push(item);
363
+ }
364
+ else if (line.trim() === '') {
365
+ sawBlankLine = true;
366
+ this.advance();
367
+ let nextIdx = this.lineIndex;
368
+ while (nextIdx < this.lines.length && this.lines[nextIdx].trim() === '') {
369
+ nextIdx++;
370
+ }
371
+ if (nextIdx < this.lines.length) {
372
+ const nextLine = this.lines[nextIdx];
373
+ const nextMarker = parseListMarker(nextLine);
374
+ if (!nextMarker || !listsMatch(firstMarker, nextMarker)) {
375
+ if (getIndent(nextLine) < firstMarker.contentIndent) {
376
+ break;
377
+ }
378
+ }
379
+ }
380
+ else {
381
+ break;
382
+ }
383
+ }
384
+ else {
385
+ break;
386
+ }
387
+ }
388
+ if (sawBlankLineInItem || sawBlankBetweenItems) {
389
+ list.tight = false;
390
+ }
391
+ }
392
+ parseListItem(item, marker) {
393
+ const itemLines = [];
394
+ let firstLine = this.currentLine();
395
+ if (firstLine.startsWith(BlockParser.LAZY_PREFIX)) {
396
+ firstLine = firstLine.slice(BlockParser.LAZY_PREFIX.length);
397
+ }
398
+ let firstContent = this.extractListItemContent(firstLine, marker);
399
+ if (firstContent.trim() === '' && firstLine.slice(marker.indentChars + marker.marker.length).match(/^[ \t]/)) {
400
+ itemLines.push('');
401
+ }
402
+ else {
403
+ itemLines.push(firstContent);
404
+ }
405
+ this.advance();
406
+ let sawBlankLine = false;
407
+ let blankLineInItem = false;
408
+ let trailingBlanks = 0;
409
+ const contentIndent = marker.contentIndent;
410
+ const baseThreshold = contentIndent + 1;
411
+ let lastNonBlankIndent = firstContent.trim() === '' ? null : contentIndent;
412
+ let lastNonBlankWasListMarker = false;
413
+ let sawNonBlankContent = firstContent.trim() !== '';
414
+ let inFence = null;
415
+ if (firstContent.trim() !== '') {
416
+ const firstFence = parseFenceOpen(firstContent);
417
+ if (firstFence) {
418
+ inFence = firstFence;
419
+ }
420
+ lastNonBlankWasListMarker = parseListMarker(firstContent) !== null;
421
+ }
422
+ while (this.lineIndex < this.lines.length) {
423
+ let line = this.currentLine();
424
+ let lazyLine = false;
425
+ if (line.startsWith(BlockParser.LAZY_PREFIX)) {
426
+ line = line.slice(BlockParser.LAZY_PREFIX.length);
427
+ lazyLine = true;
428
+ }
429
+ const lineIndent = getIndent(line);
430
+ if (inFence) {
431
+ const contentLine = lineIndent >= contentIndent ? removeIndent(line, contentIndent) : line;
432
+ itemLines.push(contentLine);
433
+ if (isFenceClose(contentLine, inFence)) {
434
+ inFence = null;
435
+ }
436
+ this.advance();
437
+ continue;
438
+ }
439
+ if (line.trim() === '') {
440
+ sawBlankLine = true;
441
+ trailingBlanks++;
442
+ itemLines.push('');
443
+ this.advance();
444
+ continue;
445
+ }
446
+ const newMarker = lazyLine ? null : parseListMarker(line);
447
+ if (newMarker && listsMatch(marker, newMarker) && newMarker.indent < contentIndent) {
448
+ break;
449
+ }
450
+ if (!sawNonBlankContent && sawBlankLine && lineIndent >= contentIndent) {
451
+ break;
452
+ }
453
+ if (lineIndent >= contentIndent) {
454
+ const contentLine = removeIndent(line, contentIndent);
455
+ const isListMarker = parseListMarker(contentLine) !== null;
456
+ if (sawBlankLine && (lineIndent <= baseThreshold ||
457
+ (lastNonBlankIndent !== null && lastNonBlankIndent <= baseThreshold && !lastNonBlankWasListMarker))) {
458
+ blankLineInItem = true;
459
+ }
460
+ sawBlankLine = false;
461
+ trailingBlanks = 0;
462
+ itemLines.push(contentLine);
463
+ lastNonBlankIndent = lineIndent;
464
+ lastNonBlankWasListMarker = isListMarker;
465
+ sawNonBlankContent = true;
466
+ if (!inFence) {
467
+ const fenceInfo = parseFenceOpen(contentLine);
468
+ if (fenceInfo) {
469
+ inFence = fenceInfo;
470
+ }
471
+ }
472
+ this.advance();
473
+ }
474
+ else if (sawBlankLine) {
475
+ break;
476
+ }
477
+ else {
478
+ if (!isThematicBreak(line) && !parseAtxHeading(line) &&
479
+ !parseFenceOpen(line) && !line.match(/^ {0,3}>/) &&
480
+ !newMarker) {
481
+ trailingBlanks = 0;
482
+ itemLines.push(line);
483
+ lastNonBlankIndent = lineIndent;
484
+ lastNonBlankWasListMarker = false;
485
+ sawNonBlankContent = true;
486
+ this.advance();
487
+ }
488
+ else {
489
+ break;
490
+ }
491
+ }
492
+ }
493
+ const endsWithBlank = trailingBlanks > 0;
494
+ while (itemLines.length > 0 && itemLines[itemLines.length - 1] === '') {
495
+ itemLines.pop();
496
+ }
497
+ const subParser = new BlockParser();
498
+ const result = subParser.parse(itemLines.join('\n'));
499
+ item.children = result.document.children;
500
+ result.linkReferences.forEach((def, label) => {
501
+ if (!this.linkReferences.has(label)) {
502
+ this.linkReferences.set(label, def);
503
+ }
504
+ });
505
+ const paragraphCount = item.children.filter(child => child.type === 'paragraph').length;
506
+ if (paragraphCount >= 2) {
507
+ blankLineInItem = true;
508
+ }
509
+ return { blankInItem: blankLineInItem, endsWithBlank };
510
+ }
511
+ lastNonBlankLine(lines) {
512
+ for (let i = lines.length - 1; i >= 0; i--) {
513
+ const line = lines[i];
514
+ if (line.trim() !== '') {
515
+ return line;
516
+ }
517
+ }
518
+ return null;
519
+ }
520
+ getBlockquotePrefix(line) {
521
+ let i = 0;
522
+ let prefix = '';
523
+ while (i < line.length) {
524
+ let spaces = 0;
525
+ const start = i;
526
+ while (i < line.length && line[i] === ' ' && spaces < 3) {
527
+ spaces++;
528
+ i++;
529
+ }
530
+ if (i < line.length && line[i] === '>') {
531
+ i++;
532
+ if (i < line.length && (line[i] === ' ' || line[i] === '\t')) {
533
+ i++;
534
+ }
535
+ prefix += line.slice(start, i);
536
+ }
537
+ else {
538
+ break;
539
+ }
540
+ }
541
+ return prefix;
542
+ }
543
+ allowsLazyAfterListMarker(line) {
544
+ const marker = parseListMarker(line);
545
+ if (!marker) {
546
+ return true;
547
+ }
548
+ const afterMarker = line.slice(marker.contentCharIndex);
549
+ return /^[ \t]*>/.test(afterMarker);
550
+ }
551
+ extractBlockquoteContent(line, match) {
552
+ const fullMatch = match[0];
553
+ const optionalSpace = match[1];
554
+ let column = 0;
555
+ let charIndex = 0;
556
+ while (charIndex < line.length && line[charIndex] === ' ' && charIndex < 3) {
557
+ column++;
558
+ charIndex++;
559
+ }
560
+ charIndex++;
561
+ column++;
562
+ let result = '';
563
+ if (optionalSpace === '\t') {
564
+ const tabWidth = 4 - (column % 4);
565
+ const remaining = tabWidth - 1;
566
+ if (remaining > 0) {
567
+ result = ' '.repeat(remaining);
568
+ }
569
+ charIndex++;
570
+ column += tabWidth;
571
+ }
572
+ else if (optionalSpace === ' ') {
573
+ charIndex++;
574
+ column++;
575
+ }
576
+ while (charIndex < line.length) {
577
+ const char = line[charIndex];
578
+ if (char === '\t') {
579
+ const tabWidth = 4 - (column % 4);
580
+ result += ' '.repeat(tabWidth);
581
+ column += tabWidth;
582
+ }
583
+ else {
584
+ result += char;
585
+ column++;
586
+ }
587
+ charIndex++;
588
+ }
589
+ return result;
590
+ }
591
+ extractListItemContent(line, marker) {
592
+ const contentStartColumn = marker.indent + marker.marker.length + marker.padding;
593
+ let column = 0;
594
+ let charIndex = 0;
595
+ let result = '';
596
+ while (charIndex < line.length && charIndex < marker.indentChars) {
597
+ if (line[charIndex] === '\t') {
598
+ column = column + (4 - (column % 4));
599
+ }
600
+ else {
601
+ column++;
602
+ }
603
+ charIndex++;
604
+ }
605
+ charIndex += marker.marker.length;
606
+ column += marker.marker.length;
607
+ if (charIndex < line.length && marker.paddingChars > 0) {
608
+ const paddingChar = line[charIndex];
609
+ if (paddingChar === '\t') {
610
+ const tabWidth = 4 - (column % 4);
611
+ const consumed = Math.min(tabWidth, marker.padding);
612
+ column += consumed;
613
+ charIndex += marker.paddingChars;
614
+ const remaining = tabWidth - consumed;
615
+ if (remaining > 0) {
616
+ result += ' '.repeat(remaining);
617
+ column += remaining;
618
+ }
619
+ }
620
+ else {
621
+ column += marker.padding;
622
+ charIndex += marker.paddingChars;
623
+ }
624
+ }
625
+ while (charIndex < line.length) {
626
+ const char = line[charIndex];
627
+ if (char === '\t') {
628
+ const tabWidth = 4 - (column % 4);
629
+ result += ' '.repeat(tabWidth);
630
+ column += tabWidth;
631
+ }
632
+ else {
633
+ result += char;
634
+ column++;
635
+ }
636
+ charIndex++;
637
+ }
638
+ return result;
639
+ }
640
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Parser for blockquote elements prefixed with >.
3
+ */
4
+ const BLOCKQUOTE_REGEX = /^( {0,3})>( ?)/;
5
+ export function isBlockquoteStart(line) {
6
+ return BLOCKQUOTE_REGEX.test(line);
7
+ }
8
+ export function removeBlockquotePrefix(line) {
9
+ return line.replace(BLOCKQUOTE_REGEX, '');
10
+ }
11
+ export function createBlockquoteNode() {
12
+ return {
13
+ type: 'blockquote',
14
+ children: [],
15
+ };
16
+ }
17
+ export function getBlockquoteContent(line) {
18
+ const match = line.match(BLOCKQUOTE_REGEX);
19
+ if (!match)
20
+ return null;
21
+ return line.slice(match[0].length);
22
+ }