markdown-codec 0.0.0 → 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 (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +215 -0
  3. package/dist/ast/ast.cjs +25 -0
  4. package/dist/ast/ast.d.cts +2 -0
  5. package/dist/ast/ast.d.ts +2 -0
  6. package/dist/ast/ast.js +23 -0
  7. package/dist/ast-BXYwy08e.d.cts +160 -0
  8. package/dist/ast-BXYwy08e.d.ts +160 -0
  9. package/dist/block/block.cjs +530 -0
  10. package/dist/block/block.d.cts +18 -0
  11. package/dist/block/block.d.ts +18 -0
  12. package/dist/block/block.js +529 -0
  13. package/dist/block/definitions.cjs +59 -0
  14. package/dist/block/definitions.d.cts +6 -0
  15. package/dist/block/definitions.d.ts +6 -0
  16. package/dist/block/definitions.js +58 -0
  17. package/dist/block/line.cjs +76 -0
  18. package/dist/block/line.d.cts +28 -0
  19. package/dist/block/line.d.ts +28 -0
  20. package/dist/block/line.js +74 -0
  21. package/dist/block/list.cjs +110 -0
  22. package/dist/block/list.d.cts +8 -0
  23. package/dist/block/list.d.ts +8 -0
  24. package/dist/block/list.js +107 -0
  25. package/dist/block/node.cjs +68 -0
  26. package/dist/block/node.d.cts +45 -0
  27. package/dist/block/node.d.ts +45 -0
  28. package/dist/block/node.js +65 -0
  29. package/dist/block/table.cjs +64 -0
  30. package/dist/block/table.d.cts +7 -0
  31. package/dist/block/table.d.ts +7 -0
  32. package/dist/block/table.js +61 -0
  33. package/dist/codec.cjs +22 -0
  34. package/dist/codec.d.cts +361 -0
  35. package/dist/codec.d.ts +361 -0
  36. package/dist/codec.js +20 -0
  37. package/dist/defaults/defaults.cjs +31 -0
  38. package/dist/defaults/defaults.d.cts +16 -0
  39. package/dist/defaults/defaults.d.ts +16 -0
  40. package/dist/defaults/defaults.js +20 -0
  41. package/dist/diagnostics/diagnostics.cjs +85 -0
  42. package/dist/diagnostics/diagnostics.d.cts +2 -0
  43. package/dist/diagnostics/diagnostics.d.ts +2 -0
  44. package/dist/diagnostics/diagnostics.js +77 -0
  45. package/dist/diagnostics-DmuWc7d8.d.cts +61 -0
  46. package/dist/diagnostics-DmuWc7d8.d.ts +61 -0
  47. package/dist/emit/emit.cjs +228 -0
  48. package/dist/emit/emit.d.cts +6 -0
  49. package/dist/emit/emit.d.ts +6 -0
  50. package/dist/emit/emit.js +227 -0
  51. package/dist/emit/front-matter.cjs +24 -0
  52. package/dist/emit/front-matter.d.cts +5 -0
  53. package/dist/emit/front-matter.d.ts +5 -0
  54. package/dist/emit/front-matter.js +23 -0
  55. package/dist/emit/image.cjs +10 -0
  56. package/dist/emit/image.d.cts +5 -0
  57. package/dist/emit/image.d.ts +5 -0
  58. package/dist/emit/image.js +9 -0
  59. package/dist/emit/inline.cjs +183 -0
  60. package/dist/emit/inline.d.cts +12 -0
  61. package/dist/emit/inline.d.ts +12 -0
  62. package/dist/emit/inline.js +180 -0
  63. package/dist/emit/table.cjs +73 -0
  64. package/dist/emit/table.d.cts +10 -0
  65. package/dist/emit/table.d.ts +10 -0
  66. package/dist/emit/table.js +72 -0
  67. package/dist/html/html.cjs +116 -0
  68. package/dist/html/html.d.cts +2 -0
  69. package/dist/html/html.d.ts +2 -0
  70. package/dist/html/html.js +113 -0
  71. package/dist/html/render.cjs +193 -0
  72. package/dist/html/render.d.cts +8 -0
  73. package/dist/html/render.d.ts +8 -0
  74. package/dist/html/render.js +189 -0
  75. package/dist/html-bkz2QTuq.d.cts +7 -0
  76. package/dist/html-bkz2QTuq.d.ts +7 -0
  77. package/dist/image/image.cjs +129 -0
  78. package/dist/image/image.d.cts +2 -0
  79. package/dist/image/image.d.ts +2 -0
  80. package/dist/image/image.js +125 -0
  81. package/dist/image-C4KYmz_L.d.cts +19 -0
  82. package/dist/image-Cm3hT5PS.d.ts +19 -0
  83. package/dist/image-DescdRgq.d.cts +12 -0
  84. package/dist/image-DescdRgq.d.ts +12 -0
  85. package/dist/index.cjs +17 -0
  86. package/dist/index.d.cts +7 -0
  87. package/dist/index.d.ts +7 -0
  88. package/dist/index.js +5 -0
  89. package/dist/inline/chars.cjs +50 -0
  90. package/dist/inline/chars.d.cts +11 -0
  91. package/dist/inline/chars.d.ts +11 -0
  92. package/dist/inline/chars.js +42 -0
  93. package/dist/inline/delimiter.cjs +136 -0
  94. package/dist/inline/delimiter.d.cts +29 -0
  95. package/dist/inline/delimiter.d.ts +29 -0
  96. package/dist/inline/delimiter.js +132 -0
  97. package/dist/inline/entity.cjs +67 -0
  98. package/dist/inline/entity.d.cts +9 -0
  99. package/dist/inline/entity.d.ts +9 -0
  100. package/dist/inline/entity.js +65 -0
  101. package/dist/inline/gfm-autolink.cjs +156 -0
  102. package/dist/inline/gfm-autolink.d.cts +5 -0
  103. package/dist/inline/gfm-autolink.d.ts +5 -0
  104. package/dist/inline/gfm-autolink.js +155 -0
  105. package/dist/inline/inline.cjs +457 -0
  106. package/dist/inline/inline.d.cts +2 -0
  107. package/dist/inline/inline.d.ts +2 -0
  108. package/dist/inline/inline.js +456 -0
  109. package/dist/inline/link.cjs +130 -0
  110. package/dist/inline/link.d.cts +2 -0
  111. package/dist/inline/link.d.ts +2 -0
  112. package/dist/inline/link.js +124 -0
  113. package/dist/inline/node.cjs +57 -0
  114. package/dist/inline/node.d.cts +23 -0
  115. package/dist/inline/node.d.ts +23 -0
  116. package/dist/inline/node.js +55 -0
  117. package/dist/inline-B50cM6cn.d.ts +10 -0
  118. package/dist/inline-C9YEGDV5.d.cts +10 -0
  119. package/dist/link-Dv4kxVjk.d.cts +18 -0
  120. package/dist/link-Dv4kxVjk.d.ts +18 -0
  121. package/dist/lower/front-matter.cjs +75 -0
  122. package/dist/lower/front-matter.d.cts +10 -0
  123. package/dist/lower/front-matter.d.ts +10 -0
  124. package/dist/lower/front-matter.js +74 -0
  125. package/dist/lower/image.cjs +29 -0
  126. package/dist/lower/image.d.cts +2 -0
  127. package/dist/lower/image.d.ts +2 -0
  128. package/dist/lower/image.js +28 -0
  129. package/dist/lower/inline.cjs +96 -0
  130. package/dist/lower/inline.d.cts +19 -0
  131. package/dist/lower/inline.d.ts +19 -0
  132. package/dist/lower/inline.js +93 -0
  133. package/dist/lower/lower.cjs +293 -0
  134. package/dist/lower/lower.d.cts +8 -0
  135. package/dist/lower/lower.d.ts +8 -0
  136. package/dist/lower/lower.js +291 -0
  137. package/dist/lower/table.cjs +27 -0
  138. package/dist/lower/table.d.cts +7 -0
  139. package/dist/lower/table.d.ts +7 -0
  140. package/dist/lower/table.js +26 -0
  141. package/dist/options/options.cjs +0 -0
  142. package/dist/options/options.d.cts +43 -0
  143. package/dist/options/options.d.ts +43 -0
  144. package/dist/options/options.js +0 -0
  145. package/dist/read.cjs +20 -0
  146. package/dist/read.d.cts +11 -0
  147. package/dist/read.d.ts +11 -0
  148. package/dist/read.js +19 -0
  149. package/dist/scan/entity-table.cjs +2131 -0
  150. package/dist/scan/entity-table.d.cts +4 -0
  151. package/dist/scan/entity-table.d.ts +4 -0
  152. package/dist/scan/entity-table.js +2130 -0
  153. package/dist/scan/scan.cjs +80 -0
  154. package/dist/scan/scan.d.cts +2 -0
  155. package/dist/scan/scan.d.ts +2 -0
  156. package/dist/scan/scan.js +78 -0
  157. package/dist/scan-DeBxgG-r.d.cts +30 -0
  158. package/dist/scan-DeBxgG-r.d.ts +30 -0
  159. package/dist/shared/list-id.cjs +36 -0
  160. package/dist/shared/list-id.d.cts +22 -0
  161. package/dist/shared/list-id.d.ts +22 -0
  162. package/dist/shared/list-id.js +32 -0
  163. package/dist/shared/style-constants.cjs +34 -0
  164. package/dist/shared/style-constants.d.cts +14 -0
  165. package/dist/shared/style-constants.d.ts +14 -0
  166. package/dist/shared/style-constants.js +23 -0
  167. package/dist/write.cjs +9 -0
  168. package/dist/write.d.cts +6 -0
  169. package/dist/write.d.ts +6 -0
  170. package/dist/write.js +8 -0
  171. package/package.json +92 -2
@@ -0,0 +1,93 @@
1
+ import { MarkdownDiagnosticCodes } from "../diagnostics/diagnostics.js";
2
+ import { MONOSPACE_FONT_FAMILY } from "../shared/style-constants.js";
3
+ //#region src/lower/inline.ts
4
+ function buildRun(text, style, fontFamily) {
5
+ return {
6
+ text,
7
+ ...style.bold === true ? { bold: true } : {},
8
+ ...style.italic === true ? { italic: true } : {},
9
+ ...style.strike === true ? { strike: true } : {},
10
+ ...style.hyperlink !== void 0 ? { hyperlink: style.hyperlink } : {},
11
+ ...fontFamily !== void 0 ? { fontFamily } : {}
12
+ };
13
+ }
14
+ function lowerNestedEmphasisLike(kind, node, style, context) {
15
+ if (style[kind] === true) context.sink({
16
+ code: MarkdownDiagnosticCodes.NESTED_EMPHASIS_FLATTENED,
17
+ severity: "info",
18
+ message: `a ${kind === "italic" ? "emphasis" : kind === "bold" ? "strong emphasis" : "strikethrough"} span is nested inside another span of the same kind; ContentRun has no nesting depth of its own, so both collapse to one flat run`
19
+ });
20
+ const childStyle = {
21
+ ...style,
22
+ [kind]: true
23
+ };
24
+ return node.children.flatMap((child) => lowerInlineNode(child, childStyle, context));
25
+ }
26
+ function lowerInlineNode(node, style, context) {
27
+ switch (node.type) {
28
+ case "text": return node.value.length === 0 ? [] : [buildRun(node.value, style)];
29
+ case "entity": return node.value.length === 0 ? [] : [buildRun(node.value, style)];
30
+ case "softBreak": return [buildRun(" ", style)];
31
+ case "hardBreak": return [buildRun("\n", style)];
32
+ case "codeSpan": return [buildRun(node.literal, style, MONOSPACE_FONT_FAMILY)];
33
+ case "rawHtml":
34
+ if (context.rawHtml === "drop") {
35
+ context.sink({
36
+ code: MarkdownDiagnosticCodes.RAW_HTML_DROPPED,
37
+ severity: "info",
38
+ message: "inline raw HTML was dropped per the rawHtml: \"drop\" option"
39
+ });
40
+ return [];
41
+ }
42
+ context.sink({
43
+ code: MarkdownDiagnosticCodes.RAW_HTML_PRESERVED_AS_TEXT,
44
+ severity: "info",
45
+ message: "inline raw HTML was preserved as literal text; it will not be rendered as HTML by any consumer of the resulting ContentDocument"
46
+ });
47
+ return node.literal.length === 0 ? [] : [buildRun(node.literal, style)];
48
+ case "autolink": {
49
+ const destination = node.email ? `mailto:${node.destination}` : node.destination;
50
+ return [buildRun(node.destination, {
51
+ ...style,
52
+ hyperlink: destination
53
+ })];
54
+ }
55
+ case "link": {
56
+ if (node.title !== void 0) context.sink({
57
+ code: MarkdownDiagnosticCodes.LINK_TITLE_DROPPED,
58
+ severity: "info",
59
+ message: `link title "${node.title}" has no ContentRun equivalent and was dropped`
60
+ });
61
+ const childStyle = {
62
+ ...style,
63
+ hyperlink: node.destination
64
+ };
65
+ const runs = node.children.flatMap((child) => lowerInlineNode(child, childStyle, context));
66
+ return runs.length > 0 ? runs : [buildRun("", childStyle)];
67
+ }
68
+ case "image":
69
+ if (node.title !== void 0) context.sink({
70
+ code: MarkdownDiagnosticCodes.LINK_TITLE_DROPPED,
71
+ severity: "info",
72
+ message: `image title "${node.title}" has no ContentRun equivalent and was dropped`
73
+ });
74
+ return [buildRun(node.alt, {
75
+ ...style,
76
+ hyperlink: node.destination
77
+ })];
78
+ case "emphasis": return lowerNestedEmphasisLike("italic", node, style, context);
79
+ case "strong": return lowerNestedEmphasisLike("bold", node, style, context);
80
+ case "strikethrough": return lowerNestedEmphasisLike("strike", node, style, context);
81
+ }
82
+ }
83
+ function lowerInlineNodes(nodes, context) {
84
+ return nodes.flatMap((node) => lowerInlineNode(node, {}, context));
85
+ }
86
+ function lowerCodeBlockRun(literal) {
87
+ return {
88
+ text: literal,
89
+ fontFamily: MONOSPACE_FONT_FAMILY
90
+ };
91
+ }
92
+ //#endregion
93
+ export { lowerCodeBlockRun, lowerInlineNode, lowerInlineNodes };
@@ -0,0 +1,293 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_defaults_defaults = require("../defaults/defaults.cjs");
3
+ const require_diagnostics_diagnostics = require("../diagnostics/diagnostics.cjs");
4
+ const require_block_block = require("../block/block.cjs");
5
+ const require_shared_list_id = require("../shared/list-id.cjs");
6
+ const require_shared_style_constants = require("../shared/style-constants.cjs");
7
+ const require_lower_front_matter = require("./front-matter.cjs");
8
+ const require_lower_image = require("./image.cjs");
9
+ const require_lower_inline = require("./inline.cjs");
10
+ const require_lower_table = require("./table.cjs");
11
+ let document_schema_js = require("document-schema.js");
12
+ //#region src/lower/lower.ts
13
+ function inlineContext(context) {
14
+ return {
15
+ sink: context.sink,
16
+ rawHtml: context.rawHtmlMode
17
+ };
18
+ }
19
+ function decorateParagraph(paragraph, context) {
20
+ let result = paragraph;
21
+ if (context.quoteDepth > 0) result = {
22
+ ...result,
23
+ indentLeftPt: context.quoteDepth * 36,
24
+ ...result.styleId === void 0 ? { styleId: require_shared_style_constants.QUOTE_STYLE_ID } : {}
25
+ };
26
+ if (context.list !== void 0) result = {
27
+ ...result,
28
+ list: {
29
+ numId: context.list.numId,
30
+ level: context.list.level
31
+ }
32
+ };
33
+ return result;
34
+ }
35
+ function lowerHeading(node, context) {
36
+ return [decorateParagraph({
37
+ kind: "paragraph",
38
+ runs: require_lower_inline.lowerInlineNodes(node.children, inlineContext(context)),
39
+ styleId: require_shared_style_constants.headingStyleId(node.level)
40
+ }, context)];
41
+ }
42
+ function lowerParagraph(node, context) {
43
+ const blocks = [];
44
+ const inlineCtx = inlineContext(context);
45
+ let segment = [];
46
+ const flushSegment = (force) => {
47
+ if (segment.length === 0 && !force) return;
48
+ blocks.push(decorateParagraph({
49
+ kind: "paragraph",
50
+ runs: require_lower_inline.lowerInlineNodes(segment, inlineCtx)
51
+ }, context));
52
+ segment = [];
53
+ };
54
+ for (const child of node.children) {
55
+ if (child.type !== "image") {
56
+ segment.push(child);
57
+ continue;
58
+ }
59
+ const resolved = require_lower_image.resolveMarkdownImage(child.destination, {
60
+ alt: child.alt,
61
+ title: child.title
62
+ }, context.images);
63
+ if (resolved === void 0) {
64
+ context.sink({
65
+ code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.IMAGE_UNRESOLVED,
66
+ severity: "info",
67
+ message: `image "${child.destination}" could not be resolved to real bytes; it degrades to a text run of its own alt text, hyperlinked at its own destination`
68
+ });
69
+ segment.push(child);
70
+ continue;
71
+ }
72
+ if (child.title !== void 0) context.sink({
73
+ code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.LINK_TITLE_DROPPED,
74
+ severity: "info",
75
+ message: `image title "${child.title}" has no ContentImageBlock equivalent and was dropped`
76
+ });
77
+ flushSegment(false);
78
+ if (context.list !== void 0) context.sink({
79
+ code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.LIST_ITEM_BLOCK_UNLISTED,
80
+ severity: "info",
81
+ message: "a resolved image block directly inside a list item has no ContentListMembership field of its own -- only ContentParagraph carries .list -- so its association with the enclosing list item is lost"
82
+ });
83
+ blocks.push({
84
+ kind: "image",
85
+ format: resolved.format,
86
+ base64: resolved.base64,
87
+ widthPt: resolved.widthPt,
88
+ heightPt: resolved.heightPt,
89
+ ...child.alt.length > 0 ? { altText: child.alt } : {}
90
+ });
91
+ }
92
+ flushSegment(blocks.length === 0);
93
+ return blocks;
94
+ }
95
+ function lowerCodeBlock(node, context) {
96
+ if (node.fenced && node.infoString !== void 0 && node.infoString.length > 0) context.sink({
97
+ code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.CODE_BLOCK_INFO_STRING_DROPPED,
98
+ severity: "info",
99
+ message: `fenced code block's own info string "${node.infoString}" has no ContentParagraph equivalent and was dropped`
100
+ });
101
+ return [decorateParagraph({
102
+ kind: "paragraph",
103
+ runs: [require_lower_inline.lowerCodeBlockRun(node.literal.replace(/\n$/, ""))],
104
+ styleId: require_shared_style_constants.CODE_BLOCK_STYLE_ID
105
+ }, context)];
106
+ }
107
+ function lowerThematicBreak(context) {
108
+ return [decorateParagraph({
109
+ kind: "paragraph",
110
+ runs: [],
111
+ styleId: require_shared_style_constants.HORIZONTAL_RULE_STYLE_ID
112
+ }, context)];
113
+ }
114
+ function lowerHtmlBlock(node, context) {
115
+ if (context.rawHtmlMode === "drop") {
116
+ context.sink({
117
+ code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.RAW_HTML_DROPPED,
118
+ severity: "info",
119
+ message: "block-level raw HTML was dropped per the rawHtml: \"drop\" option"
120
+ });
121
+ return [];
122
+ }
123
+ context.sink({
124
+ code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.RAW_HTML_PRESERVED_AS_TEXT,
125
+ severity: "info",
126
+ message: "block-level raw HTML was preserved as literal text (styleId \"HTMLPreformatted\"); it will not be rendered as HTML by any consumer of the resulting ContentDocument"
127
+ });
128
+ const literal = node.literal.replace(/\n+$/, "");
129
+ return [decorateParagraph({
130
+ kind: "paragraph",
131
+ runs: literal.length === 0 ? [] : [{ text: literal }],
132
+ styleId: require_shared_style_constants.HTML_PREFORMATTED_STYLE_ID
133
+ }, context)];
134
+ }
135
+ function lowerBlockquote(node, context, contentWidthPt) {
136
+ if (context.quoteDepth >= 1) context.sink({
137
+ code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.BLOCKQUOTE_NESTED_DEPTH,
138
+ severity: "info",
139
+ message: `blockquote nesting beyond level 1 is represented only as a larger indentLeftPt (${String((context.quoteDepth + 1) * 36)}pt); recovering the exact nesting depth back out is an approximation, not an exact inverse`
140
+ });
141
+ const nested = {
142
+ ...context,
143
+ quoteDepth: context.quoteDepth + 1
144
+ };
145
+ const blocks = node.children.flatMap((child) => lowerBlock(child, nested, contentWidthPt));
146
+ if (blocks.length === 0) return [decorateParagraph({
147
+ kind: "paragraph",
148
+ runs: []
149
+ }, nested)];
150
+ return blocks;
151
+ }
152
+ function applyTaskCheckbox(blocks, checked) {
153
+ const first = blocks[0];
154
+ if (first?.kind !== "paragraph") return false;
155
+ const checkboxRun = { text: `${checked ? "☒" : "☐"} ` };
156
+ blocks[0] = {
157
+ ...first,
158
+ runs: [checkboxRun, ...first.runs]
159
+ };
160
+ return true;
161
+ }
162
+ function lowerListItem(item, numId, level, context, contentWidthPt) {
163
+ if (item.children.filter((child) => child.type !== "list").length > 1) context.sink({
164
+ code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.LIST_ITEM_MULTI_BLOCK_FLATTENED,
165
+ severity: "info",
166
+ message: "a list item directly containing more than one block loses its own item boundary once lowered -- ContentListMembership carries only numId/level, with no field distinguishing \"one item, several blocks\" from \"several items sharing this numId/level\""
167
+ });
168
+ const itemContext = {
169
+ ...context,
170
+ list: {
171
+ numId,
172
+ level
173
+ }
174
+ };
175
+ const blocks = [];
176
+ let checkboxApplied = item.checked === void 0;
177
+ let ownLevelBlockCount = 0;
178
+ for (const child of item.children) {
179
+ if (child.type === "list") {
180
+ blocks.push(...lowerList(child, numId, level + 1, context, contentWidthPt));
181
+ continue;
182
+ }
183
+ const childBlocks = lowerBlock(child, itemContext, contentWidthPt);
184
+ ownLevelBlockCount += childBlocks.length;
185
+ if (!checkboxApplied) checkboxApplied = applyTaskCheckbox(childBlocks, item.checked === true);
186
+ blocks.push(...childBlocks);
187
+ }
188
+ if (ownLevelBlockCount === 0) {
189
+ const placeholder = [decorateParagraph({
190
+ kind: "paragraph",
191
+ runs: []
192
+ }, itemContext)];
193
+ if (!checkboxApplied) applyTaskCheckbox(placeholder, item.checked === true);
194
+ blocks.unshift(...placeholder);
195
+ }
196
+ return blocks;
197
+ }
198
+ function lowerList(node, ancestorNumId, level, context, contentWidthPt) {
199
+ let numId;
200
+ if (ancestorNumId === void 0) {
201
+ const task = node.children.some((item) => item.checked !== void 0);
202
+ numId = require_shared_list_id.mintListNumId(context.numIdState, {
203
+ type: node.markerType,
204
+ start: node.start,
205
+ task,
206
+ loose: !node.tight
207
+ });
208
+ } else {
209
+ numId = ancestorNumId;
210
+ const mintedType = require_shared_list_id.mintedListType(numId);
211
+ if (mintedType !== void 0 && mintedType !== node.markerType) context.sink({
212
+ code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.LIST_MARKER_TYPE_CONFLICT,
213
+ severity: "warning",
214
+ message: `a nested ${node.markerType} list sits under a list minted as ${mintedType}; the enclosing list's own marker type is kept (first-wins) and this nested list's own type is not separately represented`
215
+ });
216
+ }
217
+ return node.children.flatMap((item) => lowerListItem(item, numId, level, context, contentWidthPt));
218
+ }
219
+ function lowerBlock(node, context, contentWidthPt) {
220
+ switch (node.type) {
221
+ case "paragraph": return lowerParagraph(node, context);
222
+ case "heading": return lowerHeading(node, context);
223
+ case "blockquote": return lowerBlockquote(node, context, contentWidthPt);
224
+ case "list": return lowerList(node, void 0, 0, context, contentWidthPt);
225
+ case "codeBlock": return lowerCodeBlock(node, context);
226
+ case "thematicBreak": return lowerThematicBreak(context);
227
+ case "htmlBlock": return lowerHtmlBlock(node, context);
228
+ case "table":
229
+ if (context.list !== void 0) context.sink({
230
+ code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.LIST_ITEM_BLOCK_UNLISTED,
231
+ severity: "info",
232
+ message: "a table directly inside a list item has no ContentListMembership field of its own -- only ContentParagraph carries .list -- so its association with the enclosing list item is lost"
233
+ });
234
+ return [require_lower_table.lowerTable(node, contentWidthPt, inlineContext(context))];
235
+ case "document":
236
+ case "listItem":
237
+ case "tableRow":
238
+ case "tableCell": return [];
239
+ }
240
+ }
241
+ function lowerParsedMarkdown(parsed, options = {}, metadata = {}) {
242
+ const sink = options.sink ?? require_diagnostics_diagnostics.NOOP_MARKDOWN_DIAGNOSTIC_SINK;
243
+ sink({
244
+ code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.INVENTED_PAGE_GEOMETRY,
245
+ severity: "info",
246
+ message: "markdown carries no page geometry of its own; the resulting ContentSection uses a synthesised page size and margins (ReadMarkdownOptions.pageSize/margins, or document-schema.js's own PAGE_SIZE_A4 default)"
247
+ });
248
+ const pageSize = options.pageSize ?? document_schema_js.PAGE_SIZE_A4;
249
+ const margins = options.margins ?? require_defaults_defaults.DEFAULT_MARGINS;
250
+ const contentWidthPt = pageSize.widthPt - margins.leftPt - margins.rightPt;
251
+ const context = {
252
+ sink,
253
+ images: options.images,
254
+ rawHtmlMode: options.rawHtml ?? "preserve",
255
+ numIdState: require_shared_list_id.createNumIdMintState(),
256
+ quoteDepth: 0,
257
+ list: void 0
258
+ };
259
+ const blocks = parsed.document.children.flatMap((child) => lowerBlock(child, context, contentWidthPt));
260
+ return {
261
+ kind: "wordprocessing",
262
+ formatVersion: document_schema_js.CONTENT_FORMAT_VERSION,
263
+ metadata,
264
+ sections: [{
265
+ pageSize,
266
+ margins,
267
+ blocks
268
+ }]
269
+ };
270
+ }
271
+ function lowerMarkdown(source, options = {}) {
272
+ if (options.maxInputBytes !== void 0) {
273
+ const actualBytes = new TextEncoder().encode(source).length;
274
+ if (actualBytes > options.maxInputBytes) throw new require_diagnostics_diagnostics.MarkdownInputTooLargeError(options.maxInputBytes, actualBytes);
275
+ }
276
+ const sink = options.sink ?? require_diagnostics_diagnostics.NOOP_MARKDOWN_DIAGNOSTIC_SINK;
277
+ const { metadata, rest } = options.frontMatter ?? false ? require_lower_front_matter.extractFrontMatter(source, sink) : {
278
+ metadata: {},
279
+ rest: source
280
+ };
281
+ const parseOptions = {
282
+ gfmTables: options.gfmTables,
283
+ gfmAutolinks: options.gfmAutolinks,
284
+ gfmStrikethrough: options.gfmStrikethrough,
285
+ gfmTaskLists: options.gfmTaskLists,
286
+ maxNesting: options.maxBlockNesting,
287
+ sink
288
+ };
289
+ return lowerParsedMarkdown(require_block_block.parseMarkdown(rest, parseOptions), options, metadata);
290
+ }
291
+ //#endregion
292
+ exports.lowerMarkdown = lowerMarkdown;
293
+ exports.lowerParsedMarkdown = lowerParsedMarkdown;
@@ -0,0 +1,8 @@
1
+ import { ParsedMarkdown } from "../block/block.cjs";
2
+ import { ReadMarkdownOptions } from "../options/options.cjs";
3
+ import { ContentDocument, LayoutMetadata } from "document-schema.js";
4
+ //#region src/lower/lower.d.ts
5
+ declare function lowerParsedMarkdown(parsed: ParsedMarkdown, options?: ReadMarkdownOptions, metadata?: LayoutMetadata): ContentDocument;
6
+ declare function lowerMarkdown(source: string, options?: ReadMarkdownOptions): ContentDocument;
7
+ //#endregion
8
+ export { lowerMarkdown, lowerParsedMarkdown };
@@ -0,0 +1,8 @@
1
+ import { ParsedMarkdown } from "../block/block.js";
2
+ import { ReadMarkdownOptions } from "../options/options.js";
3
+ import { ContentDocument, LayoutMetadata } from "document-schema.js";
4
+ //#region src/lower/lower.d.ts
5
+ declare function lowerParsedMarkdown(parsed: ParsedMarkdown, options?: ReadMarkdownOptions, metadata?: LayoutMetadata): ContentDocument;
6
+ declare function lowerMarkdown(source: string, options?: ReadMarkdownOptions): ContentDocument;
7
+ //#endregion
8
+ export { lowerMarkdown, lowerParsedMarkdown };
@@ -0,0 +1,291 @@
1
+ import { DEFAULT_MARGINS } from "../defaults/defaults.js";
2
+ import { MarkdownDiagnosticCodes, MarkdownInputTooLargeError, NOOP_MARKDOWN_DIAGNOSTIC_SINK } from "../diagnostics/diagnostics.js";
3
+ import { parseMarkdown } from "../block/block.js";
4
+ import { createNumIdMintState, mintListNumId, mintedListType } from "../shared/list-id.js";
5
+ import { CODE_BLOCK_STYLE_ID, HORIZONTAL_RULE_STYLE_ID, HTML_PREFORMATTED_STYLE_ID, QUOTE_STYLE_ID, headingStyleId } from "../shared/style-constants.js";
6
+ import { extractFrontMatter } from "./front-matter.js";
7
+ import { resolveMarkdownImage } from "./image.js";
8
+ import { lowerCodeBlockRun, lowerInlineNodes } from "./inline.js";
9
+ import { lowerTable } from "./table.js";
10
+ import { CONTENT_FORMAT_VERSION, PAGE_SIZE_A4 } from "document-schema.js";
11
+ //#region src/lower/lower.ts
12
+ function inlineContext(context) {
13
+ return {
14
+ sink: context.sink,
15
+ rawHtml: context.rawHtmlMode
16
+ };
17
+ }
18
+ function decorateParagraph(paragraph, context) {
19
+ let result = paragraph;
20
+ if (context.quoteDepth > 0) result = {
21
+ ...result,
22
+ indentLeftPt: context.quoteDepth * 36,
23
+ ...result.styleId === void 0 ? { styleId: QUOTE_STYLE_ID } : {}
24
+ };
25
+ if (context.list !== void 0) result = {
26
+ ...result,
27
+ list: {
28
+ numId: context.list.numId,
29
+ level: context.list.level
30
+ }
31
+ };
32
+ return result;
33
+ }
34
+ function lowerHeading(node, context) {
35
+ return [decorateParagraph({
36
+ kind: "paragraph",
37
+ runs: lowerInlineNodes(node.children, inlineContext(context)),
38
+ styleId: headingStyleId(node.level)
39
+ }, context)];
40
+ }
41
+ function lowerParagraph(node, context) {
42
+ const blocks = [];
43
+ const inlineCtx = inlineContext(context);
44
+ let segment = [];
45
+ const flushSegment = (force) => {
46
+ if (segment.length === 0 && !force) return;
47
+ blocks.push(decorateParagraph({
48
+ kind: "paragraph",
49
+ runs: lowerInlineNodes(segment, inlineCtx)
50
+ }, context));
51
+ segment = [];
52
+ };
53
+ for (const child of node.children) {
54
+ if (child.type !== "image") {
55
+ segment.push(child);
56
+ continue;
57
+ }
58
+ const resolved = resolveMarkdownImage(child.destination, {
59
+ alt: child.alt,
60
+ title: child.title
61
+ }, context.images);
62
+ if (resolved === void 0) {
63
+ context.sink({
64
+ code: MarkdownDiagnosticCodes.IMAGE_UNRESOLVED,
65
+ severity: "info",
66
+ message: `image "${child.destination}" could not be resolved to real bytes; it degrades to a text run of its own alt text, hyperlinked at its own destination`
67
+ });
68
+ segment.push(child);
69
+ continue;
70
+ }
71
+ if (child.title !== void 0) context.sink({
72
+ code: MarkdownDiagnosticCodes.LINK_TITLE_DROPPED,
73
+ severity: "info",
74
+ message: `image title "${child.title}" has no ContentImageBlock equivalent and was dropped`
75
+ });
76
+ flushSegment(false);
77
+ if (context.list !== void 0) context.sink({
78
+ code: MarkdownDiagnosticCodes.LIST_ITEM_BLOCK_UNLISTED,
79
+ severity: "info",
80
+ message: "a resolved image block directly inside a list item has no ContentListMembership field of its own -- only ContentParagraph carries .list -- so its association with the enclosing list item is lost"
81
+ });
82
+ blocks.push({
83
+ kind: "image",
84
+ format: resolved.format,
85
+ base64: resolved.base64,
86
+ widthPt: resolved.widthPt,
87
+ heightPt: resolved.heightPt,
88
+ ...child.alt.length > 0 ? { altText: child.alt } : {}
89
+ });
90
+ }
91
+ flushSegment(blocks.length === 0);
92
+ return blocks;
93
+ }
94
+ function lowerCodeBlock(node, context) {
95
+ if (node.fenced && node.infoString !== void 0 && node.infoString.length > 0) context.sink({
96
+ code: MarkdownDiagnosticCodes.CODE_BLOCK_INFO_STRING_DROPPED,
97
+ severity: "info",
98
+ message: `fenced code block's own info string "${node.infoString}" has no ContentParagraph equivalent and was dropped`
99
+ });
100
+ return [decorateParagraph({
101
+ kind: "paragraph",
102
+ runs: [lowerCodeBlockRun(node.literal.replace(/\n$/, ""))],
103
+ styleId: CODE_BLOCK_STYLE_ID
104
+ }, context)];
105
+ }
106
+ function lowerThematicBreak(context) {
107
+ return [decorateParagraph({
108
+ kind: "paragraph",
109
+ runs: [],
110
+ styleId: HORIZONTAL_RULE_STYLE_ID
111
+ }, context)];
112
+ }
113
+ function lowerHtmlBlock(node, context) {
114
+ if (context.rawHtmlMode === "drop") {
115
+ context.sink({
116
+ code: MarkdownDiagnosticCodes.RAW_HTML_DROPPED,
117
+ severity: "info",
118
+ message: "block-level raw HTML was dropped per the rawHtml: \"drop\" option"
119
+ });
120
+ return [];
121
+ }
122
+ context.sink({
123
+ code: MarkdownDiagnosticCodes.RAW_HTML_PRESERVED_AS_TEXT,
124
+ severity: "info",
125
+ message: "block-level raw HTML was preserved as literal text (styleId \"HTMLPreformatted\"); it will not be rendered as HTML by any consumer of the resulting ContentDocument"
126
+ });
127
+ const literal = node.literal.replace(/\n+$/, "");
128
+ return [decorateParagraph({
129
+ kind: "paragraph",
130
+ runs: literal.length === 0 ? [] : [{ text: literal }],
131
+ styleId: HTML_PREFORMATTED_STYLE_ID
132
+ }, context)];
133
+ }
134
+ function lowerBlockquote(node, context, contentWidthPt) {
135
+ if (context.quoteDepth >= 1) context.sink({
136
+ code: MarkdownDiagnosticCodes.BLOCKQUOTE_NESTED_DEPTH,
137
+ severity: "info",
138
+ message: `blockquote nesting beyond level 1 is represented only as a larger indentLeftPt (${String((context.quoteDepth + 1) * 36)}pt); recovering the exact nesting depth back out is an approximation, not an exact inverse`
139
+ });
140
+ const nested = {
141
+ ...context,
142
+ quoteDepth: context.quoteDepth + 1
143
+ };
144
+ const blocks = node.children.flatMap((child) => lowerBlock(child, nested, contentWidthPt));
145
+ if (blocks.length === 0) return [decorateParagraph({
146
+ kind: "paragraph",
147
+ runs: []
148
+ }, nested)];
149
+ return blocks;
150
+ }
151
+ function applyTaskCheckbox(blocks, checked) {
152
+ const first = blocks[0];
153
+ if (first?.kind !== "paragraph") return false;
154
+ const checkboxRun = { text: `${checked ? "☒" : "☐"} ` };
155
+ blocks[0] = {
156
+ ...first,
157
+ runs: [checkboxRun, ...first.runs]
158
+ };
159
+ return true;
160
+ }
161
+ function lowerListItem(item, numId, level, context, contentWidthPt) {
162
+ if (item.children.filter((child) => child.type !== "list").length > 1) context.sink({
163
+ code: MarkdownDiagnosticCodes.LIST_ITEM_MULTI_BLOCK_FLATTENED,
164
+ severity: "info",
165
+ message: "a list item directly containing more than one block loses its own item boundary once lowered -- ContentListMembership carries only numId/level, with no field distinguishing \"one item, several blocks\" from \"several items sharing this numId/level\""
166
+ });
167
+ const itemContext = {
168
+ ...context,
169
+ list: {
170
+ numId,
171
+ level
172
+ }
173
+ };
174
+ const blocks = [];
175
+ let checkboxApplied = item.checked === void 0;
176
+ let ownLevelBlockCount = 0;
177
+ for (const child of item.children) {
178
+ if (child.type === "list") {
179
+ blocks.push(...lowerList(child, numId, level + 1, context, contentWidthPt));
180
+ continue;
181
+ }
182
+ const childBlocks = lowerBlock(child, itemContext, contentWidthPt);
183
+ ownLevelBlockCount += childBlocks.length;
184
+ if (!checkboxApplied) checkboxApplied = applyTaskCheckbox(childBlocks, item.checked === true);
185
+ blocks.push(...childBlocks);
186
+ }
187
+ if (ownLevelBlockCount === 0) {
188
+ const placeholder = [decorateParagraph({
189
+ kind: "paragraph",
190
+ runs: []
191
+ }, itemContext)];
192
+ if (!checkboxApplied) applyTaskCheckbox(placeholder, item.checked === true);
193
+ blocks.unshift(...placeholder);
194
+ }
195
+ return blocks;
196
+ }
197
+ function lowerList(node, ancestorNumId, level, context, contentWidthPt) {
198
+ let numId;
199
+ if (ancestorNumId === void 0) {
200
+ const task = node.children.some((item) => item.checked !== void 0);
201
+ numId = mintListNumId(context.numIdState, {
202
+ type: node.markerType,
203
+ start: node.start,
204
+ task,
205
+ loose: !node.tight
206
+ });
207
+ } else {
208
+ numId = ancestorNumId;
209
+ const mintedType = mintedListType(numId);
210
+ if (mintedType !== void 0 && mintedType !== node.markerType) context.sink({
211
+ code: MarkdownDiagnosticCodes.LIST_MARKER_TYPE_CONFLICT,
212
+ severity: "warning",
213
+ message: `a nested ${node.markerType} list sits under a list minted as ${mintedType}; the enclosing list's own marker type is kept (first-wins) and this nested list's own type is not separately represented`
214
+ });
215
+ }
216
+ return node.children.flatMap((item) => lowerListItem(item, numId, level, context, contentWidthPt));
217
+ }
218
+ function lowerBlock(node, context, contentWidthPt) {
219
+ switch (node.type) {
220
+ case "paragraph": return lowerParagraph(node, context);
221
+ case "heading": return lowerHeading(node, context);
222
+ case "blockquote": return lowerBlockquote(node, context, contentWidthPt);
223
+ case "list": return lowerList(node, void 0, 0, context, contentWidthPt);
224
+ case "codeBlock": return lowerCodeBlock(node, context);
225
+ case "thematicBreak": return lowerThematicBreak(context);
226
+ case "htmlBlock": return lowerHtmlBlock(node, context);
227
+ case "table":
228
+ if (context.list !== void 0) context.sink({
229
+ code: MarkdownDiagnosticCodes.LIST_ITEM_BLOCK_UNLISTED,
230
+ severity: "info",
231
+ message: "a table directly inside a list item has no ContentListMembership field of its own -- only ContentParagraph carries .list -- so its association with the enclosing list item is lost"
232
+ });
233
+ return [lowerTable(node, contentWidthPt, inlineContext(context))];
234
+ case "document":
235
+ case "listItem":
236
+ case "tableRow":
237
+ case "tableCell": return [];
238
+ }
239
+ }
240
+ function lowerParsedMarkdown(parsed, options = {}, metadata = {}) {
241
+ const sink = options.sink ?? NOOP_MARKDOWN_DIAGNOSTIC_SINK;
242
+ sink({
243
+ code: MarkdownDiagnosticCodes.INVENTED_PAGE_GEOMETRY,
244
+ severity: "info",
245
+ message: "markdown carries no page geometry of its own; the resulting ContentSection uses a synthesised page size and margins (ReadMarkdownOptions.pageSize/margins, or document-schema.js's own PAGE_SIZE_A4 default)"
246
+ });
247
+ const pageSize = options.pageSize ?? PAGE_SIZE_A4;
248
+ const margins = options.margins ?? DEFAULT_MARGINS;
249
+ const contentWidthPt = pageSize.widthPt - margins.leftPt - margins.rightPt;
250
+ const context = {
251
+ sink,
252
+ images: options.images,
253
+ rawHtmlMode: options.rawHtml ?? "preserve",
254
+ numIdState: createNumIdMintState(),
255
+ quoteDepth: 0,
256
+ list: void 0
257
+ };
258
+ const blocks = parsed.document.children.flatMap((child) => lowerBlock(child, context, contentWidthPt));
259
+ return {
260
+ kind: "wordprocessing",
261
+ formatVersion: CONTENT_FORMAT_VERSION,
262
+ metadata,
263
+ sections: [{
264
+ pageSize,
265
+ margins,
266
+ blocks
267
+ }]
268
+ };
269
+ }
270
+ function lowerMarkdown(source, options = {}) {
271
+ if (options.maxInputBytes !== void 0) {
272
+ const actualBytes = new TextEncoder().encode(source).length;
273
+ if (actualBytes > options.maxInputBytes) throw new MarkdownInputTooLargeError(options.maxInputBytes, actualBytes);
274
+ }
275
+ const sink = options.sink ?? NOOP_MARKDOWN_DIAGNOSTIC_SINK;
276
+ const { metadata, rest } = options.frontMatter ?? false ? extractFrontMatter(source, sink) : {
277
+ metadata: {},
278
+ rest: source
279
+ };
280
+ const parseOptions = {
281
+ gfmTables: options.gfmTables,
282
+ gfmAutolinks: options.gfmAutolinks,
283
+ gfmStrikethrough: options.gfmStrikethrough,
284
+ gfmTaskLists: options.gfmTaskLists,
285
+ maxNesting: options.maxBlockNesting,
286
+ sink
287
+ };
288
+ return lowerParsedMarkdown(parseMarkdown(rest, parseOptions), options, metadata);
289
+ }
290
+ //#endregion
291
+ export { lowerMarkdown, lowerParsedMarkdown };