@jianwen-lang/parser 0.1.1

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 (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +95 -0
  3. package/dist/cli/render.d.ts +1 -0
  4. package/dist/cli/render.js +300 -0
  5. package/dist/core/ast.d.ts +286 -0
  6. package/dist/core/ast.js +2 -0
  7. package/dist/core/block/rules/heading.d.ts +9 -0
  8. package/dist/core/block/rules/heading.js +75 -0
  9. package/dist/core/block/rules/horizontal-rule.d.ts +9 -0
  10. package/dist/core/block/rules/horizontal-rule.js +87 -0
  11. package/dist/core/block/rules/include.d.ts +9 -0
  12. package/dist/core/block/rules/include.js +64 -0
  13. package/dist/core/block/rules/index.d.ts +2 -0
  14. package/dist/core/block/rules/index.js +16 -0
  15. package/dist/core/block/rules/types.d.ts +21 -0
  16. package/dist/core/block/rules/types.js +2 -0
  17. package/dist/core/block/types.d.ts +10 -0
  18. package/dist/core/block/types.js +2 -0
  19. package/dist/core/block-parser.d.ts +3 -0
  20. package/dist/core/block-parser.js +1385 -0
  21. package/dist/core/clone.d.ts +9 -0
  22. package/dist/core/clone.js +32 -0
  23. package/dist/core/diagnostics.d.ts +12 -0
  24. package/dist/core/diagnostics.js +24 -0
  25. package/dist/core/errors.d.ts +12 -0
  26. package/dist/core/errors.js +2 -0
  27. package/dist/core/inline/rules/backtick.d.ts +4 -0
  28. package/dist/core/inline/rules/backtick.js +90 -0
  29. package/dist/core/inline/rules/bracket.d.ts +4 -0
  30. package/dist/core/inline/rules/bracket.js +721 -0
  31. package/dist/core/inline/rules/disabled.d.ts +2 -0
  32. package/dist/core/inline/rules/disabled.js +34 -0
  33. package/dist/core/inline/rules/escape.d.ts +2 -0
  34. package/dist/core/inline/rules/escape.js +11 -0
  35. package/dist/core/inline/rules/index.d.ts +2 -0
  36. package/dist/core/inline/rules/index.js +25 -0
  37. package/dist/core/inline/rules/marker-highlight.d.ts +4 -0
  38. package/dist/core/inline/rules/marker-highlight.js +56 -0
  39. package/dist/core/inline/rules/style.d.ts +4 -0
  40. package/dist/core/inline/rules/style.js +120 -0
  41. package/dist/core/inline/rules/types.d.ts +22 -0
  42. package/dist/core/inline/rules/types.js +2 -0
  43. package/dist/core/inline/types.d.ts +1 -0
  44. package/dist/core/inline/types.js +2 -0
  45. package/dist/core/inline-parser.d.ts +3 -0
  46. package/dist/core/inline-parser.js +52 -0
  47. package/dist/core/location.d.ts +9 -0
  48. package/dist/core/location.js +30 -0
  49. package/dist/core/parser.d.ts +9 -0
  50. package/dist/core/parser.js +423 -0
  51. package/dist/core/traverse.d.ts +7 -0
  52. package/dist/core/traverse.js +71 -0
  53. package/dist/html/convert.d.ts +29 -0
  54. package/dist/html/convert.js +61 -0
  55. package/dist/html/format.d.ts +1 -0
  56. package/dist/html/format.js +17 -0
  57. package/dist/html/render/blocks.d.ts +4 -0
  58. package/dist/html/render/blocks.js +433 -0
  59. package/dist/html/render/html.d.ts +8 -0
  60. package/dist/html/render/html.js +89 -0
  61. package/dist/html/render/inlines.d.ts +4 -0
  62. package/dist/html/render/inlines.js +110 -0
  63. package/dist/html/render/meta.d.ts +3 -0
  64. package/dist/html/render/meta.js +51 -0
  65. package/dist/html/render/utils.d.ts +31 -0
  66. package/dist/html/render/utils.js +213 -0
  67. package/dist/html/theme/base/css.d.ts +2 -0
  68. package/dist/html/theme/base/css.js +383 -0
  69. package/dist/html/theme/dark/css.d.ts +2 -0
  70. package/dist/html/theme/dark/css.js +108 -0
  71. package/dist/html/theme/default/colors.d.ts +13 -0
  72. package/dist/html/theme/default/colors.js +2 -0
  73. package/dist/html/theme/default/css.d.ts +2 -0
  74. package/dist/html/theme/default/css.js +6 -0
  75. package/dist/html/theme/default/runtime.d.ts +0 -0
  76. package/dist/html/theme/default/runtime.js +31 -0
  77. package/dist/html/theme/light/css.d.ts +2 -0
  78. package/dist/html/theme/light/css.js +55 -0
  79. package/dist/html/theme/preset/colors.d.ts +10 -0
  80. package/dist/html/theme/preset/colors.js +14 -0
  81. package/dist/html/theme/runtime.d.ts +0 -0
  82. package/dist/html/theme/runtime.js +31 -0
  83. package/dist/html/theme/theme.d.ts +9 -0
  84. package/dist/html/theme/theme.js +21 -0
  85. package/dist/lexer/lexer.d.ts +17 -0
  86. package/dist/lexer/lexer.js +47 -0
  87. package/dist/parser.d.ts +6 -0
  88. package/dist/parser.js +22 -0
  89. package/package.json +50 -0
@@ -0,0 +1,433 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderBlocksToHtml = renderBlocksToHtml;
4
+ exports.renderBlockToHtml = renderBlockToHtml;
5
+ const utils_1 = require("./utils");
6
+ const inlines_1 = require("./inlines");
7
+ function renderBlocksToHtml(blocks, options = {}) {
8
+ const result = [];
9
+ let i = 0;
10
+ function wrapBlock(html) {
11
+ if (!html || !html.trim())
12
+ return '';
13
+ if (options.suppressBlockWrapper)
14
+ return html;
15
+ return `<div class="jw-block">${html}</div>`;
16
+ }
17
+ while (i < blocks.length) {
18
+ const block = blocks[i];
19
+ if (!block) {
20
+ i++;
21
+ continue;
22
+ }
23
+ if (block.type === 'heading' && block.foldable) {
24
+ const headingHtml = renderHeadingBlock(block, options);
25
+ const foldedBlocks = [];
26
+ let j = i + 1;
27
+ while (j < blocks.length) {
28
+ const nextBlock = blocks[j];
29
+ if (!nextBlock) {
30
+ j++;
31
+ continue;
32
+ }
33
+ const nextAttrs = 'blockAttrs' in nextBlock ? nextBlock.blockAttrs : undefined;
34
+ if (nextAttrs?.fold) {
35
+ foldedBlocks.push(wrapBlock(renderBlockToHtml(nextBlock, options)));
36
+ j++;
37
+ }
38
+ else {
39
+ break;
40
+ }
41
+ }
42
+ const detailsContent = foldedBlocks.join('');
43
+ const detailsHtml = `<details class="jw-foldable-section">${headingHtml}${detailsContent}</details>`;
44
+ result.push(wrapBlock(detailsHtml));
45
+ i = j;
46
+ continue;
47
+ }
48
+ const blockAttrs = 'blockAttrs' in block ? block.blockAttrs : undefined;
49
+ if (!blockAttrs?.sameLine) {
50
+ result.push(wrapBlock(renderBlockToHtml(block, options)));
51
+ i++;
52
+ continue;
53
+ }
54
+ const rowBlocks = [];
55
+ let rowStartIndex = i;
56
+ if (i > 0) {
57
+ const prevBlock = blocks[i - 1];
58
+ if (prevBlock) {
59
+ const prevAttrs = 'blockAttrs' in prevBlock ? prevBlock.blockAttrs : undefined;
60
+ if (!prevAttrs?.sameLine) {
61
+ rowStartIndex = i - 1;
62
+ result.pop();
63
+ }
64
+ }
65
+ }
66
+ for (let j = rowStartIndex; j < blocks.length; j++) {
67
+ const currentBlock = blocks[j];
68
+ if (!currentBlock) {
69
+ continue;
70
+ }
71
+ rowBlocks.push(currentBlock);
72
+ if (j + 1 >= blocks.length) {
73
+ break;
74
+ }
75
+ const nextBlock = blocks[j + 1];
76
+ if (nextBlock) {
77
+ const nextAttrs = 'blockAttrs' in nextBlock ? nextBlock.blockAttrs : undefined;
78
+ if (!nextAttrs?.sameLine) {
79
+ break;
80
+ }
81
+ }
82
+ }
83
+ const rowHtml = rowBlocks.map((b) => renderBlockToHtml(b, options)).join('');
84
+ result.push(wrapBlock(`<div class="jw-same-line-row">${rowHtml}</div>`));
85
+ i = rowStartIndex + rowBlocks.length;
86
+ }
87
+ return result.join('');
88
+ }
89
+ function renderBlockToHtml(block, options) {
90
+ switch (block.type) {
91
+ case 'paragraph':
92
+ return renderParagraphBlock(block, options);
93
+ case 'heading':
94
+ return renderHeadingBlock(block, options);
95
+ case 'contentTitle':
96
+ return renderContentTitleBlock(block, options);
97
+ case 'quote':
98
+ return renderQuoteBlock(block, options);
99
+ case 'list':
100
+ return renderListBlock(block, options);
101
+ case 'listItem':
102
+ return renderListItemBlock(block, options);
103
+ case 'code':
104
+ return renderCodeBlock(block, options);
105
+ case 'table':
106
+ return renderTableBlock(block, options);
107
+ case 'hr':
108
+ return renderHorizontalRuleBlock(block, options);
109
+ case 'image':
110
+ return renderImageBlock(block, options);
111
+ case 'html':
112
+ return renderHtmlBlock(block, options);
113
+ case 'footnotes':
114
+ return renderFootnotesBlock(block, options);
115
+ case 'footnoteDef':
116
+ return renderFootnoteDefBlock(block, options);
117
+ case 'commentBlock':
118
+ return options.includeComments ? renderCommentBlock(block, options) : '';
119
+ case 'disabledBlock':
120
+ return renderDisabledBlock(block, options);
121
+ case 'include':
122
+ return renderIncludeBlock(block, options);
123
+ case 'taggedBlock':
124
+ return renderTaggedBlock(block, options);
125
+ case 'raw':
126
+ return renderRawBlock(block, options);
127
+ default:
128
+ return '';
129
+ }
130
+ }
131
+ function renderParagraphBlock(block, options) {
132
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs);
133
+ const inner = (0, inlines_1.renderInlinesToHtml)(block.children, options);
134
+ const hasBlockElements = inner.includes('<div');
135
+ if (hasBlockElements) {
136
+ const trimmedInner = inner.trim();
137
+ return `<div class="jw-paragraph jw-paragraph-block"${attrs}>${trimmedInner}</div>`;
138
+ }
139
+ return `<p class="jw-paragraph"${attrs}>${inner}</p>`;
140
+ }
141
+ function renderHeadingBlock(block, options) {
142
+ const level = block.level;
143
+ const tag = level >= 1 && level <= 5 ? `h${level}` : 'h1';
144
+ const headingText = block.children.map((node) => extractTextFromInlineNode(node)).join('');
145
+ const headingId = (0, utils_1.buildHeadingIdFromText)(headingText);
146
+ const inner = (0, inlines_1.renderInlinesToHtml)(block.children, options);
147
+ if (block.foldable) {
148
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs);
149
+ const heading = `<${tag} id="${(0, utils_1.escapeAttr)(headingId)}" class="jw-heading level-${level}"${attrs}>${inner}</${tag}>`;
150
+ return `<summary class="jw-heading-summary">${heading}</summary>`;
151
+ }
152
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs);
153
+ return `<${tag} id="${(0, utils_1.escapeAttr)(headingId)}" class="jw-heading level-${level}"${attrs}>${inner}</${tag}>`;
154
+ }
155
+ function hasInlineChildren(node) {
156
+ return 'children' in node && Array.isArray(node.children);
157
+ }
158
+ function extractTextFromInlineNode(node) {
159
+ if (node.type === 'text') {
160
+ return node.value;
161
+ }
162
+ if (hasInlineChildren(node)) {
163
+ return node.children.map((child) => extractTextFromInlineNode(child)).join('');
164
+ }
165
+ return '';
166
+ }
167
+ function renderContentTitleBlock(block, options) {
168
+ const inner = (0, inlines_1.renderInlinesToHtml)(block.children, options);
169
+ const spacer = '<div class="jw-content-title-gap" aria-hidden="true"></div>';
170
+ return `<div class="jw-content-title">${inner}</div>${spacer}`;
171
+ }
172
+ function renderQuoteBlock(block, options) {
173
+ const inner = renderBlocksToHtml(block.children, options);
174
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
175
+ extraData: { 'data-jw-level': String(block.level) },
176
+ });
177
+ return `<blockquote class="jw-quote"${attrs}>${inner}</blockquote>`;
178
+ }
179
+ function renderListBlock(block, options) {
180
+ const isOrdered = block.kind === 'ordered';
181
+ const tag = isOrdered ? 'ol' : 'ul';
182
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
183
+ extraData: {
184
+ 'data-jw-list-kind': block.kind,
185
+ ...(block.orderedStyle ? { 'data-jw-ordered-style': block.orderedStyle } : {}),
186
+ },
187
+ });
188
+ const inner = block.children.map((child) => renderListItemBlock(child, options)).join('');
189
+ return `<${tag} class="jw-list"${attrs}>${inner}</${tag}>`;
190
+ }
191
+ function renderListItemBlock(block, options) {
192
+ const attrsParts = [];
193
+ attrsParts.push(`data-jw-list-kind="${(0, utils_1.escapeAttr)(block.kind)}"`);
194
+ attrsParts.push(`data-jw-indent="${block.indent}"`);
195
+ if (block.ordinal) {
196
+ attrsParts.push(`data-jw-ordinal="${(0, utils_1.escapeAttr)(block.ordinal)}"`);
197
+ }
198
+ if (block.taskStatus) {
199
+ attrsParts.push(`data-jw-task-status="${(0, utils_1.escapeAttr)(block.taskStatus)}"`);
200
+ }
201
+ const blockAttrStr = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
202
+ rawAttrs: attrsParts,
203
+ });
204
+ let prefix = '';
205
+ if (block.kind === 'ordered' && block.ordinal) {
206
+ prefix += `<span class="jw-list-ordinal">${(0, utils_1.escapeHtml)(block.ordinal)}.</span>`;
207
+ }
208
+ if (block.taskStatus) {
209
+ prefix += `<span class="jw-list-task-marker" data-jw-task-status="${(0, utils_1.escapeAttr)(block.taskStatus)}"></span>`;
210
+ }
211
+ const inner = renderBlocksToHtml(block.children, {
212
+ ...options,
213
+ suppressBlockWrapper: true,
214
+ });
215
+ if (block.kind === 'foldable') {
216
+ const firstChild = block.children[0];
217
+ if (firstChild && firstChild.type === 'paragraph') {
218
+ const summaryContent = renderBlockToHtml(firstChild, {
219
+ ...options,
220
+ suppressBlockWrapper: true,
221
+ });
222
+ const remainingChildren = block.children.slice(1);
223
+ const detailsContent = remainingChildren.length > 0
224
+ ? renderBlocksToHtml(remainingChildren, {
225
+ ...options,
226
+ suppressBlockWrapper: true,
227
+ })
228
+ : '';
229
+ return `<li class="jw-list-item"${blockAttrStr}><details class="jw-foldable-list-item"><summary class="jw-list-summary">${prefix}${summaryContent}</summary>${detailsContent}</details></li>`;
230
+ }
231
+ }
232
+ return `<li class="jw-list-item"${blockAttrStr}>${prefix}${inner}</li>`;
233
+ }
234
+ function renderCodeBlock(block, _options) {
235
+ if (block.htmlLike) {
236
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
237
+ extraData: { 'data-jw-html-like': 'true' },
238
+ });
239
+ const value = block.value ?? '';
240
+ return `<div class="jw-html-like"${attrs}><template shadowrootmode="open">${value}</template></div>`;
241
+ }
242
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
243
+ extraData: block.language ? { 'data-jw-language': block.language } : undefined,
244
+ });
245
+ const langClass = block.language ? ` language-${(0, utils_1.escapeAttr)(block.language)}` : '';
246
+ const normalized = (block.value ?? '').replace(/\r\n?/g, '\n');
247
+ const lines = normalized.split('\n');
248
+ if (lines.length === 0) {
249
+ lines.push('');
250
+ }
251
+ // Generate line numbers HTML
252
+ const lineNumbersHtml = lines
253
+ .map((_, index) => `<span class="jw-line-number">${index + 1}</span>`)
254
+ .join('');
255
+ // Generate code lines HTML
256
+ const linesHtml = lines
257
+ .map((line) => {
258
+ const escapedLine = (0, utils_1.escapeHtml)(line);
259
+ const contentWithSpaces = escapedLine
260
+ .replace(/\t/g, '&nbsp;&nbsp;&nbsp;&nbsp;')
261
+ .replace(/ /g, '&nbsp;');
262
+ const content = line.length === 0 ? '&nbsp;' : contentWithSpaces;
263
+ return `<span class="jw-code-line">${content}</span>`;
264
+ })
265
+ .join('');
266
+ // Build header with language label and copy button
267
+ const languageLabel = block.language
268
+ ? `<span class="jw-code-lang">${(0, utils_1.escapeHtml)(block.language)}</span>`
269
+ : '<span></span>';
270
+ const copyButton = `<button class="jw-code-copy" onclick="navigator.clipboard.writeText([...this.closest('.jw-code-block').querySelectorAll('.jw-code-line')].map(l=>l.textContent).join('\\n')).then(()=>{this.textContent='已复制';setTimeout(()=>this.textContent='复制',1500)})">复制</button>`;
271
+ const header = `<div class="jw-code-header">${languageLabel}${copyButton}</div>`;
272
+ const content = `<div class="jw-code-content"><span class="jw-line-numbers">${lineNumbersHtml}</span><code class="jw-code${langClass}">${linesHtml}</code></div>`;
273
+ return `<pre class="jw-code-block"${attrs}>${header}${content}</pre>`;
274
+ }
275
+ function renderTableBlock(block, options) {
276
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs);
277
+ if (!block.rows || block.rows.length === 0) {
278
+ return `<table class="jw-table"${attrs}></table>`;
279
+ }
280
+ const headerRow = block.rows[0];
281
+ if (!headerRow) {
282
+ return `<table class="jw-table"${attrs}></table>`;
283
+ }
284
+ const bodyRows = block.rows.slice(1);
285
+ const thead = `<thead>${renderTableRow(headerRow, block, options, true)}</thead>`;
286
+ const tbody = bodyRows.length
287
+ ? `<tbody>${bodyRows.map((row) => renderTableRow(row, block, options, false)).join('')}</tbody>`
288
+ : '';
289
+ return `<table class="jw-table"${attrs}>${thead}${tbody}</table>`;
290
+ }
291
+ function renderTableRow(row, table, options, isHeader) {
292
+ const cellTag = isHeader ? 'th' : 'td';
293
+ const cellsHtml = row.cells
294
+ .map((cell, index) => renderTableCell(cell, table, options, index, cellTag))
295
+ .join('');
296
+ return `<tr class="jw-table-row">${cellsHtml}</tr>`;
297
+ }
298
+ function renderTableCell(cell, table, options, columnIndex, tag) {
299
+ const align = cell.align ?? table.align?.[columnIndex];
300
+ const styleParts = [];
301
+ if (align) {
302
+ styleParts.push(`text-align:${align}`);
303
+ }
304
+ const styleAttr = styleParts.length > 0 ? ` style="${(0, utils_1.escapeAttr)(styleParts.join(';'))}"` : '';
305
+ const inner = (0, inlines_1.renderInlinesToHtml)(cell.children, options);
306
+ return `<${tag} class="jw-table-cell"${styleAttr}>${inner}</${tag}>`;
307
+ }
308
+ function renderHorizontalRuleBlock(block, _options) {
309
+ const attrsParts = [`data-jw-hr-style="${(0, utils_1.escapeAttr)(block.style)}"`];
310
+ const color = (0, utils_1.colorAttributeToCssColor)(block.colorAttr);
311
+ const extraStyle = [];
312
+ if (color) {
313
+ extraStyle.push(`color:${color}`);
314
+ extraStyle.push(`border-color:${color}`);
315
+ }
316
+ const attrStr = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
317
+ rawAttrs: attrsParts,
318
+ extraStyle: extraStyle.length > 0 ? extraStyle : undefined,
319
+ });
320
+ return `<hr class="jw-hr"${attrStr} />`;
321
+ }
322
+ function renderImageBlock(block, options) {
323
+ const extraData = {};
324
+ if (block.shape) {
325
+ extraData['data-jw-shape'] = block.shape;
326
+ }
327
+ if (block.roundedRadius !== undefined) {
328
+ extraData['data-jw-rounded-radius'] = String(block.roundedRadius);
329
+ }
330
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
331
+ extraData: Object.keys(extraData).length > 0 ? extraData : undefined,
332
+ });
333
+ let url = block.url;
334
+ if (options.resolveAssetPath) {
335
+ const resolved = options.resolveAssetPath(block.url);
336
+ if (resolved !== undefined) {
337
+ url = resolved;
338
+ }
339
+ }
340
+ const src = (0, utils_1.escapeAttr)(url);
341
+ const alt = block.title ? (0, utils_1.escapeAttr)(block.title) : '';
342
+ let imgStyle = '';
343
+ if (block.shape === 'rounded' && block.roundedRadius !== undefined) {
344
+ const radius = block.roundedRadius * 8;
345
+ imgStyle = ` style="border-radius:${radius}px"`;
346
+ }
347
+ const img = `<img class="jw-image" src="${src}" alt="${alt}"${imgStyle} />`;
348
+ if (!block.title) {
349
+ return `<figure class="jw-image-figure"${attrs}>${img}</figure>`;
350
+ }
351
+ const caption = `<figcaption class="jw-image-caption">${(0, utils_1.escapeHtml)(block.title)}</figcaption>`;
352
+ return `<figure class="jw-image-figure"${attrs}>${img}${caption}</figure>`;
353
+ }
354
+ function renderHtmlBlock(block, options) {
355
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs);
356
+ if (block.value) {
357
+ return `<div class="jw-html-block"${attrs}>${block.value}</div>`;
358
+ }
359
+ if (block.source) {
360
+ const resolved = options.resolveHtmlSource
361
+ ? options.resolveHtmlSource(block.source)
362
+ : undefined;
363
+ if (resolved !== undefined) {
364
+ return `<div class="jw-html-block"${attrs}>${resolved}</div>`;
365
+ }
366
+ let source = block.source;
367
+ if (options.resolveAssetPath) {
368
+ const resolvedPath = options.resolveAssetPath(block.source);
369
+ if (resolvedPath !== undefined) {
370
+ source = resolvedPath;
371
+ }
372
+ }
373
+ const dataAttrs = attrs.length > 0
374
+ ? `${attrs} data-jw-html-source="${(0, utils_1.escapeAttr)(source)}"`
375
+ : ` data-jw-html-source="${(0, utils_1.escapeAttr)(source)}"`;
376
+ return `<div class="jw-html-block"${dataAttrs}></div>`;
377
+ }
378
+ return `<div class="jw-html-block"${attrs}></div>`;
379
+ }
380
+ function renderFootnotesBlock(block, options) {
381
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs);
382
+ const items = block.children.map((def) => renderFootnoteDefBlock(def, options)).join('');
383
+ return `<section class="jw-footnotes"${attrs}><ol class="jw-footnote-list">${items}</ol></section>`;
384
+ }
385
+ function renderFootnoteDefBlock(block, options) {
386
+ const inner = renderBlocksToHtml(block.children, options);
387
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
388
+ extraData: { 'data-jw-footnote-id': block.id },
389
+ });
390
+ return `<li class="jw-footnote-def"${attrs}>${inner}</li>`;
391
+ }
392
+ function renderCommentBlock(block, options) {
393
+ const inner = renderBlocksToHtml(block.children, options);
394
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
395
+ extraData: { 'data-jw-comment': 'true' },
396
+ });
397
+ return `<aside class="jw-comment-block"${attrs}>${inner}</aside>`;
398
+ }
399
+ function renderDisabledBlock(block, _options) {
400
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs);
401
+ const text = (0, utils_1.escapeHtml)(block.raw ?? '');
402
+ return `<pre class="jw-disabled-block"${attrs}>${text}</pre>`;
403
+ }
404
+ function renderIncludeBlock(block, options) {
405
+ const attrsParts = [
406
+ `data-jw-include-mode="${(0, utils_1.escapeAttr)(block.mode)}"`,
407
+ `data-jw-include-target="${(0, utils_1.escapeAttr)(block.target)}"`,
408
+ ];
409
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
410
+ rawAttrs: attrsParts,
411
+ });
412
+ if (options.resolveInclude) {
413
+ const resolved = options.resolveInclude(block.mode, block.target);
414
+ if (resolved !== undefined) {
415
+ return `<div class="jw-include"${attrs}>${resolved}</div>`;
416
+ }
417
+ }
418
+ return `<div class="jw-include"${attrs}></div>`;
419
+ }
420
+ function renderTaggedBlock(block, options) {
421
+ const id = (0, utils_1.buildTagIdFromName)(block.name);
422
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
423
+ extraData: { 'data-jw-tag': block.name },
424
+ rawAttrs: [`id="${(0, utils_1.escapeAttr)(id)}"`],
425
+ });
426
+ const inner = renderBlockToHtml(block.child, options);
427
+ return `<div class="jw-tagged-block"${attrs}>${inner}</div>`;
428
+ }
429
+ function renderRawBlock(block, _options) {
430
+ const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs);
431
+ const text = (0, utils_1.escapeHtml)(block.value ?? '');
432
+ return `<pre class="jw-raw-block"${attrs}>${text}</pre>`;
433
+ }
@@ -0,0 +1,8 @@
1
+ import { JianwenDocument } from '../../core/ast';
2
+ import { RenderHtmlOptions } from './utils';
3
+ export { RenderHtmlOptions } from './utils';
4
+ export { DocumentTheme } from '../theme/theme';
5
+ export { renderBlocksToHtml } from './blocks';
6
+ export { renderInlinesToHtml } from './inlines';
7
+ export declare function createDefaultAssetPathResolver(sourceFilePath: string, outputFilePath: string): (assetPath: string) => string | undefined;
8
+ export declare function renderDocumentToHtml(doc: JianwenDocument, options?: RenderHtmlOptions): string;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.renderInlinesToHtml = exports.renderBlocksToHtml = void 0;
37
+ exports.createDefaultAssetPathResolver = createDefaultAssetPathResolver;
38
+ exports.renderDocumentToHtml = renderDocumentToHtml;
39
+ const path = __importStar(require("path"));
40
+ const format_1 = require("../format");
41
+ const utils_1 = require("./utils");
42
+ const meta_1 = require("./meta");
43
+ const blocks_1 = require("./blocks");
44
+ var blocks_2 = require("./blocks");
45
+ Object.defineProperty(exports, "renderBlocksToHtml", { enumerable: true, get: function () { return blocks_2.renderBlocksToHtml; } });
46
+ var inlines_1 = require("./inlines");
47
+ Object.defineProperty(exports, "renderInlinesToHtml", { enumerable: true, get: function () { return inlines_1.renderInlinesToHtml; } });
48
+ function createDefaultAssetPathResolver(sourceFilePath, outputFilePath) {
49
+ const sourceDir = path.dirname(sourceFilePath);
50
+ const outputDir = path.dirname(outputFilePath);
51
+ return (assetPath) => {
52
+ if (path.isAbsolute(assetPath) || /^https?:\/\//i.test(assetPath)) {
53
+ return assetPath;
54
+ }
55
+ const absoluteAssetPath = path.resolve(sourceDir, assetPath);
56
+ const relativeToOutput = path.relative(outputDir, absoluteAssetPath);
57
+ return relativeToOutput.replace(/\\/g, '/');
58
+ };
59
+ }
60
+ function renderDocumentToHtml(doc, options = {}) {
61
+ const wrapperTag = options.documentWrapperTag === undefined ? 'article' : options.documentWrapperTag;
62
+ const finalOptions = { ...options };
63
+ if (options.sourceFilePath && options.outputFilePath && !options.resolveAssetPath) {
64
+ finalOptions.resolveAssetPath = createDefaultAssetPathResolver(options.sourceFilePath, options.outputFilePath);
65
+ }
66
+ const innerParts = [];
67
+ if (finalOptions.includeMeta) {
68
+ innerParts.push((0, meta_1.renderMetaToHtml)(doc.meta));
69
+ }
70
+ if (!wrapperTag) {
71
+ innerParts.push((0, blocks_1.renderBlocksToHtml)(doc.children, {
72
+ ...finalOptions,
73
+ suppressBlockWrapper: true,
74
+ }));
75
+ }
76
+ else {
77
+ innerParts.push((0, blocks_1.renderBlocksToHtml)(doc.children, finalOptions));
78
+ }
79
+ const innerHtml = innerParts.join('');
80
+ if (!wrapperTag) {
81
+ return innerHtml;
82
+ }
83
+ const wrapperAttrs = (0, meta_1.buildDocumentWrapperAttributes)(doc.meta);
84
+ const themeAttr = finalOptions.documentTheme
85
+ ? ` data-jw-theme="${(0, utils_1.escapeAttr)(finalOptions.documentTheme)}"`
86
+ : '';
87
+ const html = `<${wrapperTag} class="jw-root"${wrapperAttrs}${themeAttr}>${innerHtml}</${wrapperTag}>`;
88
+ return finalOptions.format ? (0, format_1.formatHtml)(html) : html;
89
+ }
@@ -0,0 +1,4 @@
1
+ import { InlineNode } from '../../core/ast';
2
+ import { RenderHtmlOptions } from './utils';
3
+ export declare function renderInlinesToHtml(nodes: InlineNode[], options?: RenderHtmlOptions): string;
4
+ export declare function renderInlineToHtml(node: InlineNode, options: RenderHtmlOptions): string;
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderInlinesToHtml = renderInlinesToHtml;
4
+ exports.renderInlineToHtml = renderInlineToHtml;
5
+ const utils_1 = require("./utils");
6
+ function renderInlinesToHtml(nodes, options = {}) {
7
+ return nodes.map((node) => renderInlineToHtml(node, options)).join('');
8
+ }
9
+ function renderInlineToHtml(node, options) {
10
+ switch (node.type) {
11
+ case 'text': {
12
+ const escaped = (0, utils_1.escapeHtml)(node.value);
13
+ return escaped.replace(/\n/g, '<br/>');
14
+ }
15
+ case 'codeSpan':
16
+ return `<code class="jw-code-span">${(0, utils_1.escapeHtml)(node.value)}</code>`;
17
+ case 'em':
18
+ return `<em>${renderInlinesToHtml(node.children, options)}</em>`;
19
+ case 'strong':
20
+ return `<strong>${renderInlinesToHtml(node.children, options)}</strong>`;
21
+ case 'underline':
22
+ return `<span class="jw-underline">${renderInlinesToHtml(node.children, options)}</span>`;
23
+ case 'strike':
24
+ return `<span class="jw-strike">${renderInlinesToHtml(node.children, options)}</span>`;
25
+ case 'wave':
26
+ return `<span class="jw-wave">${renderInlinesToHtml(node.children, options)}</span>`;
27
+ case 'sup':
28
+ return `<sup>${renderInlinesToHtml(node.children, options)}</sup>`;
29
+ case 'sub':
30
+ return `<sub>${renderInlinesToHtml(node.children, options)}</sub>`;
31
+ case 'highlight':
32
+ return renderHighlightInline(node, options);
33
+ case 'link':
34
+ return renderLinkInline(node, options);
35
+ case 'footnoteRef':
36
+ return renderFootnoteRefInline(node);
37
+ case 'commentInline':
38
+ return options.includeComments
39
+ ? `<span class="jw-comment-inline" data-jw-comment="true">${renderInlinesToHtml(node.children, options)}</span>`
40
+ : '';
41
+ case 'inlineAttrs':
42
+ return renderInlineAttrsInline(node, options);
43
+ default:
44
+ return '';
45
+ }
46
+ }
47
+ function renderHighlightInline(node, options) {
48
+ const cssColor = (0, utils_1.colorAttributeToCssColor)(node.colorAttr);
49
+ const cssFillColor = (0, utils_1.colorAttributeToCssColor)(node.fillColorAttr);
50
+ const classes = ['jw-highlight', `jw-highlight-${node.mode}`];
51
+ const styleParts = [];
52
+ if (node.mode === 'marker') {
53
+ if (cssColor) {
54
+ styleParts.push(`background-color:${cssColor}`);
55
+ }
56
+ if (cssFillColor) {
57
+ styleParts.push(`border-color:${cssFillColor}`);
58
+ }
59
+ }
60
+ else {
61
+ if (cssColor) {
62
+ styleParts.push(`border-color:${cssColor}`);
63
+ }
64
+ if (cssFillColor) {
65
+ styleParts.push(`background-color:${cssFillColor}`);
66
+ }
67
+ }
68
+ if (node.shape === 'square') {
69
+ styleParts.push('border-radius:0');
70
+ }
71
+ else if (node.shape === 'rounded') {
72
+ const radius = node.roundedRadius ?? 1;
73
+ styleParts.push(`border-radius:${radius * 0.35}em`);
74
+ }
75
+ const styleAttr = styleParts.length > 0 ? ` style="${(0, utils_1.escapeAttr)(styleParts.join(';'))}"` : '';
76
+ const inner = renderInlinesToHtml(node.children, options);
77
+ const hasLineBreaks = inner.includes('<br/>');
78
+ if (hasLineBreaks) {
79
+ classes.push('jw-highlight-block');
80
+ const trimmedInner = inner.replace(/^(<br\/>)+|(<br\/>)+$/g, '');
81
+ return `<div class="${classes.join(' ')}"${styleAttr}>${trimmedInner}</div>`;
82
+ }
83
+ return `<span class="${classes.join(' ')}"${styleAttr}>${inner}</span>`;
84
+ }
85
+ function renderLinkInline(node, options) {
86
+ const resolvedHref = (0, utils_1.resolveLinkHref)(node.href);
87
+ const href = (0, utils_1.escapeAttr)(resolvedHref);
88
+ const styleParts = [];
89
+ const color = (0, utils_1.colorAttributeToCssColor)(node.colorAttr);
90
+ const underlineColor = (0, utils_1.colorAttributeToCssColor)(node.underlineColorAttr);
91
+ if (color) {
92
+ styleParts.push(`color:${color}`);
93
+ }
94
+ if (underlineColor) {
95
+ styleParts.push(`text-decoration-color:${underlineColor}`);
96
+ }
97
+ const styleAttr = styleParts.length > 0 ? ` style="${(0, utils_1.escapeAttr)(styleParts.join(';'))}"` : '';
98
+ const inner = renderInlinesToHtml(node.children, options);
99
+ return `<a href="${href}" class="jw-link"${styleAttr}>${inner}</a>`;
100
+ }
101
+ function renderFootnoteRefInline(node) {
102
+ const id = (0, utils_1.escapeAttr)(node.id);
103
+ return `<sup class="jw-footnote-ref" data-jw-footnote-id="${id}">[${id}]</sup>`;
104
+ }
105
+ function renderInlineAttrsInline(node, options) {
106
+ const style = (0, utils_1.buildInlineStyleFromInlineAttributes)(node.attrs);
107
+ const styleAttr = style ? ` style="${(0, utils_1.escapeAttr)(style)}"` : '';
108
+ const inner = renderInlinesToHtml(node.children, options);
109
+ return `<span class="jw-inline-attrs"${styleAttr}>${inner}</span>`;
110
+ }
@@ -0,0 +1,3 @@
1
+ import { JianwenMeta } from '../../core/ast';
2
+ export declare function renderMetaToHtml(meta: JianwenMeta | undefined): string;
3
+ export declare function buildDocumentWrapperAttributes(meta: JianwenMeta | undefined): string;