markdown-codec 4.0.15 → 4.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 (62) hide show
  1. package/README.md +14 -13
  2. package/dist/block/block.d.cts +3 -3
  3. package/dist/block/block.d.ts +3 -3
  4. package/dist/block/definitions.d.cts +2 -2
  5. package/dist/block/definitions.d.ts +2 -2
  6. package/dist/codec.d.cts +30 -10
  7. package/dist/codec.d.ts +30 -10
  8. package/dist/diagnostics/diagnostics.cjs +12 -4
  9. package/dist/diagnostics/diagnostics.d.cts +2 -2
  10. package/dist/diagnostics/diagnostics.d.ts +2 -2
  11. package/dist/diagnostics/diagnostics.js +12 -5
  12. package/dist/{diagnostics-BWK1iGy7.d.cts → diagnostics-CUMLtGHJ.d.cts} +7 -5
  13. package/dist/{diagnostics-BWK1iGy7.d.ts → diagnostics-CUMLtGHJ.d.ts} +7 -5
  14. package/dist/emit/emit.cjs +93 -27
  15. package/dist/emit/emit.js +96 -30
  16. package/dist/emit/inline.cjs +22 -14
  17. package/dist/emit/inline.d.cts +7 -5
  18. package/dist/emit/inline.d.ts +7 -5
  19. package/dist/emit/inline.js +21 -15
  20. package/dist/emit/table.cjs +1 -1
  21. package/dist/emit/table.d.cts +1 -1
  22. package/dist/emit/table.d.ts +1 -1
  23. package/dist/emit/table.js +1 -1
  24. package/dist/index.cjs +1 -0
  25. package/dist/index.d.cts +2 -2
  26. package/dist/index.d.ts +2 -2
  27. package/dist/index.js +2 -2
  28. package/dist/inline/inline.d.cts +1 -1
  29. package/dist/inline/inline.d.ts +1 -1
  30. package/dist/inline/link.d.cts +17 -1
  31. package/dist/inline/link.d.ts +17 -1
  32. package/dist/{inline-CXVQWQnW.d.cts → inline-CoS1JzxI.d.cts} +1 -1
  33. package/dist/{inline-B_V7bs5j.d.ts → inline-OGXVE6hB.d.ts} +1 -1
  34. package/dist/lower/front-matter.cjs +7 -4
  35. package/dist/lower/front-matter.d.cts +2 -1
  36. package/dist/lower/front-matter.d.ts +2 -1
  37. package/dist/lower/front-matter.js +7 -4
  38. package/dist/lower/inline.cjs +73 -29
  39. package/dist/lower/inline.d.cts +7 -10
  40. package/dist/lower/inline.d.ts +7 -10
  41. package/dist/lower/inline.js +74 -29
  42. package/dist/lower/lower.cjs +140 -71
  43. package/dist/lower/lower.d.cts +8 -1
  44. package/dist/lower/lower.d.ts +8 -1
  45. package/dist/lower/lower.js +142 -74
  46. package/dist/lower/table.cjs +3 -2
  47. package/dist/lower/table.js +3 -2
  48. package/dist/options/options.d.cts +1 -1
  49. package/dist/options/options.d.ts +1 -1
  50. package/dist/read.cjs +45 -9
  51. package/dist/read.d.cts +1 -1
  52. package/dist/read.d.ts +1 -1
  53. package/dist/read.js +46 -10
  54. package/dist/shared/list-id.cjs +6 -0
  55. package/dist/shared/list-id.d.cts +2 -1
  56. package/dist/shared/list-id.d.ts +2 -1
  57. package/dist/shared/list-id.js +6 -1
  58. package/dist/write.cjs +31 -4
  59. package/dist/write.js +31 -4
  60. package/package.json +2 -2
  61. package/dist/link-Dv4kxVjk.d.cts +0 -18
  62. package/dist/link-Dv4kxVjk.d.ts +0 -18
@@ -1,8 +1,8 @@
1
1
  import { DEFAULT_MARGINS } from "../defaults/defaults.js";
2
2
  import { MarkdownDiagnosticCodes, MarkdownInputTooLargeError, NOOP_MARKDOWN_DIAGNOSTIC_SINK } from "../diagnostics/diagnostics.js";
3
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, MATH_BLOCK_STYLE_ID, QUOTE_STYLE_ID, headingStyleId } from "../shared/style-constants.js";
4
+ import { createNumIdMintState, mintListItemId, 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
6
  import { extractFrontMatter } from "./front-matter.js";
7
7
  import { resolveMarkdownImage } from "./image.js";
8
8
  import { lowerCodeBlockRun, lowerInlineNodes } from "./inline.js";
@@ -24,17 +24,21 @@ function decorateParagraph(paragraph, context) {
24
24
  };
25
25
  if (context.list !== void 0) result = {
26
26
  ...result,
27
- list: {
28
- numId: context.list.numId,
29
- level: context.list.level
30
- }
27
+ list: { ...context.list }
31
28
  };
32
29
  return result;
33
30
  }
31
+ function paragraphWithConstructs(runs, linkTitleExtents) {
32
+ return {
33
+ runs,
34
+ ...linkTitleExtents.length > 0 ? { constructs: [...linkTitleExtents] } : {}
35
+ };
36
+ }
34
37
  function lowerHeading(node, context) {
38
+ const inline = lowerInlineNodes(node.children, inlineContext(context));
35
39
  return [decorateParagraph({
36
40
  kind: "paragraph",
37
- runs: lowerInlineNodes(node.children, inlineContext(context)),
41
+ ...paragraphWithConstructs(inline.runs, inline.linkTitleExtents),
38
42
  styleId: headingStyleId(node.level),
39
43
  headingLevel: node.level
40
44
  }, context)];
@@ -45,9 +49,10 @@ function lowerParagraph(node, context) {
45
49
  let segment = [];
46
50
  const flushSegment = (force) => {
47
51
  if (segment.length === 0 && !force) return;
52
+ const inline = lowerInlineNodes(segment, inlineCtx);
48
53
  blocks.push(decorateParagraph({
49
54
  kind: "paragraph",
50
- runs: lowerInlineNodes(segment, inlineCtx)
55
+ ...paragraphWithConstructs(inline.runs, inline.linkTitleExtents)
51
56
  }, context));
52
57
  segment = [];
53
58
  };
@@ -69,39 +74,73 @@ function lowerParagraph(node, context) {
69
74
  segment.push(child);
70
75
  continue;
71
76
  }
72
- if (child.title !== void 0) context.sink({
73
- code: MarkdownDiagnosticCodes.LINK_TITLE_DROPPED,
74
- severity: "info",
75
- message: `image title "${child.title}" has no ContentImageBlock equivalent and was dropped`
76
- });
77
77
  flushSegment(false);
78
78
  if (context.list !== void 0) context.sink({
79
79
  code: MarkdownDiagnosticCodes.LIST_ITEM_BLOCK_UNLISTED,
80
80
  severity: "info",
81
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
82
  });
83
- blocks.push({
83
+ const image = {
84
84
  kind: "image",
85
85
  format: resolved.format,
86
86
  base64: resolved.base64,
87
87
  widthPt: resolved.widthPt,
88
88
  heightPt: resolved.heightPt,
89
89
  ...child.alt.length > 0 ? { altText: child.alt } : {}
90
- });
90
+ };
91
+ if (child.title === void 0) {
92
+ blocks.push(image);
93
+ continue;
94
+ }
95
+ blocks.push({
96
+ kind: "constructStart",
97
+ descriptor: {
98
+ kind: "link",
99
+ target: {
100
+ kind: "external",
101
+ uri: child.destination
102
+ },
103
+ title: child.title
104
+ }
105
+ }, image, { kind: "constructEnd" });
91
106
  }
92
107
  flushSegment(blocks.length === 0);
93
108
  return blocks;
94
109
  }
110
+ function splitInfoString(infoString) {
111
+ const firstWhitespace = infoString.search(/\s/);
112
+ if (firstWhitespace === -1) return infoString.startsWith("{") ? {
113
+ language: void 0,
114
+ remainder: infoString
115
+ } : {
116
+ language: infoString,
117
+ remainder: void 0
118
+ };
119
+ const firstWord = infoString.slice(0, firstWhitespace);
120
+ const remainder = infoString.slice(firstWhitespace).trim();
121
+ if (firstWord.startsWith("{")) return {
122
+ language: void 0,
123
+ remainder: infoString.trim()
124
+ };
125
+ return {
126
+ language: firstWord,
127
+ remainder: remainder.length > 0 ? remainder : void 0
128
+ };
129
+ }
95
130
  function lowerCodeBlock(node, context) {
96
- if (node.fenced && node.infoString !== void 0 && node.infoString.length > 0) context.sink({
97
- code: 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
- });
131
+ const info = node.fenced && node.infoString !== void 0 && node.infoString.length > 0 ? splitInfoString(node.infoString) : {
132
+ language: void 0,
133
+ remainder: void 0
134
+ };
101
135
  return [decorateParagraph({
102
136
  kind: "paragraph",
103
137
  runs: [lowerCodeBlockRun(node.literal.replace(/\n$/, ""))],
104
- styleId: CODE_BLOCK_STYLE_ID
138
+ styleId: CODE_BLOCK_STYLE_ID,
139
+ ...info.language !== void 0 ? { codeLanguage: info.language } : {},
140
+ ...info.remainder !== void 0 ? { source: {
141
+ format: "markdown",
142
+ xml: info.remainder
143
+ } } : {}
105
144
  }, context)];
106
145
  }
107
146
  function lowerThematicBreak(context) {
@@ -123,70 +162,95 @@ function lowerHtmlBlock(node, context) {
123
162
  context.sink({
124
163
  code: MarkdownDiagnosticCodes.RAW_HTML_PRESERVED_AS_TEXT,
125
164
  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"
165
+ 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, and its verbatim original rides the paragraph's own markdown residue for this package's writer to re-emit as-is"
127
166
  });
128
167
  const literal = node.literal.replace(/\n+$/, "");
129
168
  return [decorateParagraph({
130
169
  kind: "paragraph",
131
170
  runs: literal.length === 0 ? [] : [{ text: literal }],
132
- styleId: HTML_PREFORMATTED_STYLE_ID
171
+ styleId: HTML_PREFORMATTED_STYLE_ID,
172
+ source: {
173
+ format: "markdown",
174
+ xml: node.literal
175
+ }
133
176
  }, context)];
134
177
  }
135
178
  function lowerMathBlock(node, context) {
136
- context.sink({
137
- code: MarkdownDiagnosticCodes.MATH_BLOCK_PRESERVED_AS_TEXT,
179
+ if (context.list !== void 0) context.sink({
180
+ code: MarkdownDiagnosticCodes.LIST_ITEM_BLOCK_UNLISTED,
138
181
  severity: "info",
139
- message: "block math ($$...$$) was preserved as literal raw LaTeX text (styleId \"MathBlock\"); it is not parsed as LaTeX or converted to MathML by this package"
182
+ message: "a display-math 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"
140
183
  });
141
- const literal = node.literal.replace(/\n$/, "");
142
- return [decorateParagraph({
143
- kind: "paragraph",
144
- runs: literal.length === 0 ? [] : [{ text: literal }],
145
- styleId: MATH_BLOCK_STYLE_ID
146
- }, context)];
184
+ return [{
185
+ kind: "embeddedObject",
186
+ objectKind: "formula",
187
+ document: {
188
+ kind: "formula",
189
+ metadata: {},
190
+ formula: {
191
+ mathml: [],
192
+ presentation: { latex: node.literal.replace(/\n$/, "") }
193
+ }
194
+ },
195
+ frame: {
196
+ xPt: 0,
197
+ yPt: 0,
198
+ widthPt: 0,
199
+ heightPt: 0
200
+ }
201
+ }];
202
+ }
203
+ function blockquoteSubtreeContainsHeading(node) {
204
+ const walk = (block) => {
205
+ switch (block.type) {
206
+ case "heading": return true;
207
+ case "blockquote":
208
+ case "list":
209
+ case "listItem": return block.children.some(walk);
210
+ default: return false;
211
+ }
212
+ };
213
+ return node.children.some(walk);
147
214
  }
148
215
  function lowerBlockquote(node, context, contentWidthPt) {
149
- if (context.quoteDepth >= 1) context.sink({
150
- code: MarkdownDiagnosticCodes.BLOCKQUOTE_NESTED_DEPTH,
151
- severity: "info",
152
- 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`
153
- });
154
216
  const nested = {
155
217
  ...context,
156
218
  quoteDepth: context.quoteDepth + 1
157
219
  };
158
220
  const blocks = node.children.flatMap((child) => lowerBlock(child, nested, contentWidthPt));
159
- if (blocks.length === 0) return [decorateParagraph({
221
+ const inner = blocks.length === 0 ? [decorateParagraph({
160
222
  kind: "paragraph",
161
223
  runs: []
162
- }, nested)];
163
- return blocks;
164
- }
165
- function applyTaskCheckbox(blocks, checked) {
166
- const first = blocks[0];
167
- if (first?.kind !== "paragraph") return false;
168
- const checkboxRun = { text: `${checked ? "☒" : "☐"} ` };
169
- blocks[0] = {
170
- ...first,
171
- runs: [checkboxRun, ...first.runs]
172
- };
173
- return true;
224
+ }, nested)] : blocks;
225
+ if (blockquoteSubtreeContainsHeading(node)) {
226
+ context.sink({
227
+ code: MarkdownDiagnosticCodes.BLOCKQUOTE_CONTAINER_SKIPPED,
228
+ severity: "info",
229
+ message: "a blockquote containing a heading cannot carry its division construct -- a marker extent may not open a heading scope, and the last heading inside an extent always leaves one standing -- so this quote degrades to indent-only structure while the heading keeps its heading fidelity"
230
+ });
231
+ return inner;
232
+ }
233
+ return [
234
+ {
235
+ kind: "constructStart",
236
+ descriptor: { kind: "division" }
237
+ },
238
+ ...inner,
239
+ { kind: "constructEnd" }
240
+ ];
174
241
  }
175
242
  function lowerListItem(item, numId, level, context, contentWidthPt) {
176
- if (item.children.filter((child) => child.type !== "list").length > 1) context.sink({
177
- code: MarkdownDiagnosticCodes.LIST_ITEM_MULTI_BLOCK_FLATTENED,
178
- severity: "info",
179
- 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\""
180
- });
243
+ const membership = {
244
+ numId,
245
+ level,
246
+ ...item.checked !== void 0 ? { checked: item.checked } : {},
247
+ itemId: mintListItemId(context.numIdState)
248
+ };
181
249
  const itemContext = {
182
250
  ...context,
183
- list: {
184
- numId,
185
- level
186
- }
251
+ list: membership
187
252
  };
188
253
  const blocks = [];
189
- let checkboxApplied = item.checked === void 0;
190
254
  let ownLevelBlockCount = 0;
191
255
  for (const child of item.children) {
192
256
  if (child.type === "list") {
@@ -195,17 +259,12 @@ function lowerListItem(item, numId, level, context, contentWidthPt) {
195
259
  }
196
260
  const childBlocks = lowerBlock(child, itemContext, contentWidthPt);
197
261
  ownLevelBlockCount += childBlocks.length;
198
- if (!checkboxApplied) checkboxApplied = applyTaskCheckbox(childBlocks, item.checked === true);
199
262
  blocks.push(...childBlocks);
200
263
  }
201
- if (ownLevelBlockCount === 0) {
202
- const placeholder = [decorateParagraph({
203
- kind: "paragraph",
204
- runs: []
205
- }, itemContext)];
206
- if (!checkboxApplied) applyTaskCheckbox(placeholder, item.checked === true);
207
- blocks.unshift(...placeholder);
208
- }
264
+ if (ownLevelBlockCount === 0) blocks.unshift(decorateParagraph({
265
+ kind: "paragraph",
266
+ runs: []
267
+ }, itemContext));
209
268
  return blocks;
210
269
  }
211
270
  function lowerList(node, ancestorNumId, level, context, contentWidthPt) {
@@ -330,15 +389,16 @@ function lowerParsedMarkdown(parsed, options = {}, metadata = {}) {
330
389
  }]
331
390
  };
332
391
  }
333
- function lowerMarkdown(source, options = {}) {
392
+ function lowerMarkdownDetailed(source, options = {}) {
334
393
  if (options.maxInputBytes !== void 0) {
335
394
  const actualBytes = new TextEncoder().encode(source).length;
336
395
  if (actualBytes > options.maxInputBytes) throw new MarkdownInputTooLargeError(options.maxInputBytes, actualBytes);
337
396
  }
338
397
  const sink = options.sink ?? NOOP_MARKDOWN_DIAGNOSTIC_SINK;
339
- const { metadata, rest } = options.frontMatter ?? false ? extractFrontMatter(source, sink) : {
398
+ const extracted = options.frontMatter ?? false ? extractFrontMatter(source, sink) : {
340
399
  metadata: {},
341
- rest: source
400
+ rest: source,
401
+ source: void 0
342
402
  };
343
403
  const parseOptions = {
344
404
  gfmTables: options.gfmTables,
@@ -349,7 +409,15 @@ function lowerMarkdown(source, options = {}) {
349
409
  maxNesting: options.maxBlockNesting,
350
410
  sink
351
411
  };
352
- return lowerParsedMarkdown(parseMarkdown(rest, parseOptions), options, metadata);
412
+ const parsed = parseMarkdown(extracted.rest, parseOptions);
413
+ return {
414
+ document: lowerParsedMarkdown(parsed, options, extracted.metadata),
415
+ references: parsed.references,
416
+ frontMatterSource: extracted.source
417
+ };
418
+ }
419
+ function lowerMarkdown(source, options = {}) {
420
+ return lowerMarkdownDetailed(source, options).document;
353
421
  }
354
422
  //#endregion
355
- export { lowerMarkdown, lowerParsedMarkdown };
423
+ export { lowerMarkdown, lowerMarkdownDetailed, lowerParsedMarkdown };
@@ -6,11 +6,12 @@ function toParagraphAlignment(alignment) {
6
6
  return alignment === "none" ? void 0 : alignment;
7
7
  }
8
8
  function lowerTableCell(cell, alignment, context) {
9
- const runs = require_lower_inline.lowerInlineNodes(cell.children, context);
9
+ const inline = require_lower_inline.lowerInlineNodes(cell.children, context);
10
10
  const paragraphAlignment = toParagraphAlignment(alignment ?? "none");
11
11
  return { blocks: [{
12
12
  kind: "paragraph",
13
- runs,
13
+ runs: inline.runs,
14
+ ...inline.linkTitleExtents.length > 0 ? { constructs: [...inline.linkTitleExtents] } : {},
14
15
  ...paragraphAlignment === void 0 ? {} : { alignment: paragraphAlignment }
15
16
  }] };
16
17
  }
@@ -5,11 +5,12 @@ function toParagraphAlignment(alignment) {
5
5
  return alignment === "none" ? void 0 : alignment;
6
6
  }
7
7
  function lowerTableCell(cell, alignment, context) {
8
- const runs = lowerInlineNodes(cell.children, context);
8
+ const inline = lowerInlineNodes(cell.children, context);
9
9
  const paragraphAlignment = toParagraphAlignment(alignment ?? "none");
10
10
  return { blocks: [{
11
11
  kind: "paragraph",
12
- runs,
12
+ runs: inline.runs,
13
+ ...inline.linkTitleExtents.length > 0 ? { constructs: [...inline.linkTitleExtents] } : {},
13
14
  ...paragraphAlignment === void 0 ? {} : { alignment: paragraphAlignment }
14
15
  }] };
15
16
  }
@@ -1,4 +1,4 @@
1
- import { i as MarkdownDiagnosticSink } from "../diagnostics-BWK1iGy7.cjs";
1
+ import { i as MarkdownDiagnosticSink } from "../diagnostics-CUMLtGHJ.cjs";
2
2
  import { n as MarkdownImageResolver } from "../image-C4KYmz_L.cjs";
3
3
  import { Margins, PageSize } from "document-schema.js";
4
4
  //#region src/options/options.d.ts
@@ -1,4 +1,4 @@
1
- import { i as MarkdownDiagnosticSink } from "../diagnostics-BWK1iGy7.js";
1
+ import { i as MarkdownDiagnosticSink } from "../diagnostics-CUMLtGHJ.js";
2
2
  import { n as MarkdownImageResolver } from "../image-Cm3hT5PS.js";
3
3
  import { Margins, PageSize } from "document-schema.js";
4
4
  //#region src/options/options.d.ts
package/dist/read.cjs CHANGED
@@ -2,19 +2,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_lower_lower = require("./lower/lower.cjs");
3
3
  let document_schema_js = require("document-schema.js");
4
4
  //#region src/read.ts
5
- function readMarkdown(text, options = {}) {
6
- const { document, diagnostics } = readMarkdownContent(text, options);
7
- return {
8
- documentPackage: (0, document_schema_js.assemblePackage)(document),
9
- diagnostics
10
- };
11
- }
12
- function readMarkdownContent(text, options = {}) {
5
+ function readMarkdownDetail(text, options) {
13
6
  options.signal?.throwIfAborted();
14
7
  const diagnostics = [];
15
8
  const callerSink = options.sink;
16
9
  return {
17
- document: require_lower_lower.lowerMarkdown(text, {
10
+ ...require_lower_lower.lowerMarkdownDetailed(text, {
18
11
  ...options,
19
12
  sink: (diagnostic) => {
20
13
  diagnostics.push(diagnostic);
@@ -24,6 +17,49 @@ function readMarkdownContent(text, options = {}) {
24
17
  diagnostics
25
18
  };
26
19
  }
20
+ function linkDefinitionEntries(references) {
21
+ if (references.size === 0) return;
22
+ const entries = {};
23
+ for (const [label, definition] of references) entries[label] = definition.title === void 0 ? {
24
+ kind: "link",
25
+ destination: definition.destination
26
+ } : {
27
+ kind: "link",
28
+ destination: definition.destination,
29
+ title: definition.title
30
+ };
31
+ return entries;
32
+ }
33
+ function readMarkdown(text, options = {}) {
34
+ const detail = readMarkdownDetail(text, options);
35
+ const assembled = (0, document_schema_js.assemblePackage)(detail.document);
36
+ const definitions = linkDefinitionEntries(detail.references);
37
+ const frontMatterResidue = detail.frontMatterSource === void 0 ? void 0 : {
38
+ format: "markdown",
39
+ xml: detail.frontMatterSource
40
+ };
41
+ return {
42
+ documentPackage: definitions === void 0 && frontMatterResidue === void 0 ? assembled : {
43
+ ...assembled,
44
+ ...definitions !== void 0 ? { definitions: {
45
+ ...assembled.definitions,
46
+ ...definitions
47
+ } } : {},
48
+ ...frontMatterResidue !== void 0 ? { source: {
49
+ ...assembled.source ?? {},
50
+ frontmatter: frontMatterResidue
51
+ } } : {}
52
+ },
53
+ diagnostics: detail.diagnostics
54
+ };
55
+ }
56
+ function readMarkdownContent(text, options = {}) {
57
+ const detail = readMarkdownDetail(text, options);
58
+ return {
59
+ document: detail.document,
60
+ diagnostics: detail.diagnostics
61
+ };
62
+ }
27
63
  //#endregion
28
64
  exports.readMarkdown = readMarkdown;
29
65
  exports.readMarkdownContent = readMarkdownContent;
package/dist/read.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as MarkdownDiagnostic } from "./diagnostics-BWK1iGy7.cjs";
1
+ import { t as MarkdownDiagnostic } from "./diagnostics-CUMLtGHJ.cjs";
2
2
  import { ReadMarkdownOptions } from "./options/options.cjs";
3
3
  import { ContentDocument, DocumentPackage } from "document-schema.js";
4
4
  //#region src/read.d.ts
package/dist/read.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as MarkdownDiagnostic } from "./diagnostics-BWK1iGy7.js";
1
+ import { t as MarkdownDiagnostic } from "./diagnostics-CUMLtGHJ.js";
2
2
  import { ReadMarkdownOptions } from "./options/options.js";
3
3
  import { ContentDocument, DocumentPackage } from "document-schema.js";
4
4
  //#region src/read.d.ts
package/dist/read.js CHANGED
@@ -1,19 +1,12 @@
1
- import { lowerMarkdown } from "./lower/lower.js";
1
+ import { lowerMarkdownDetailed } from "./lower/lower.js";
2
2
  import { assemblePackage } from "document-schema.js";
3
3
  //#region src/read.ts
4
- function readMarkdown(text, options = {}) {
5
- const { document, diagnostics } = readMarkdownContent(text, options);
6
- return {
7
- documentPackage: assemblePackage(document),
8
- diagnostics
9
- };
10
- }
11
- function readMarkdownContent(text, options = {}) {
4
+ function readMarkdownDetail(text, options) {
12
5
  options.signal?.throwIfAborted();
13
6
  const diagnostics = [];
14
7
  const callerSink = options.sink;
15
8
  return {
16
- document: lowerMarkdown(text, {
9
+ ...lowerMarkdownDetailed(text, {
17
10
  ...options,
18
11
  sink: (diagnostic) => {
19
12
  diagnostics.push(diagnostic);
@@ -23,5 +16,48 @@ function readMarkdownContent(text, options = {}) {
23
16
  diagnostics
24
17
  };
25
18
  }
19
+ function linkDefinitionEntries(references) {
20
+ if (references.size === 0) return;
21
+ const entries = {};
22
+ for (const [label, definition] of references) entries[label] = definition.title === void 0 ? {
23
+ kind: "link",
24
+ destination: definition.destination
25
+ } : {
26
+ kind: "link",
27
+ destination: definition.destination,
28
+ title: definition.title
29
+ };
30
+ return entries;
31
+ }
32
+ function readMarkdown(text, options = {}) {
33
+ const detail = readMarkdownDetail(text, options);
34
+ const assembled = assemblePackage(detail.document);
35
+ const definitions = linkDefinitionEntries(detail.references);
36
+ const frontMatterResidue = detail.frontMatterSource === void 0 ? void 0 : {
37
+ format: "markdown",
38
+ xml: detail.frontMatterSource
39
+ };
40
+ return {
41
+ documentPackage: definitions === void 0 && frontMatterResidue === void 0 ? assembled : {
42
+ ...assembled,
43
+ ...definitions !== void 0 ? { definitions: {
44
+ ...assembled.definitions,
45
+ ...definitions
46
+ } } : {},
47
+ ...frontMatterResidue !== void 0 ? { source: {
48
+ ...assembled.source ?? {},
49
+ frontmatter: frontMatterResidue
50
+ } } : {}
51
+ },
52
+ diagnostics: detail.diagnostics
53
+ };
54
+ }
55
+ function readMarkdownContent(text, options = {}) {
56
+ const detail = readMarkdownDetail(text, options);
57
+ return {
58
+ document: detail.document,
59
+ diagnostics: detail.diagnostics
60
+ };
61
+ }
26
62
  //#endregion
27
63
  export { readMarkdown, readMarkdownContent };
@@ -29,8 +29,14 @@ function parseListNumId(numId) {
29
29
  function mintedListType(numId) {
30
30
  return parseListNumId(numId)?.type;
31
31
  }
32
+ function mintListItemId(state) {
33
+ const id = state.next;
34
+ state.next += 1;
35
+ return `md-i${String(id)}`;
36
+ }
32
37
  //#endregion
33
38
  exports.createNumIdMintState = createNumIdMintState;
39
+ exports.mintListItemId = mintListItemId;
34
40
  exports.mintListNumId = mintListNumId;
35
41
  exports.mintedListType = mintedListType;
36
42
  exports.parseListNumId = parseListNumId;
@@ -18,5 +18,6 @@ declare function createNumIdMintState(): NumIdMintState;
18
18
  declare function mintListNumId(state: NumIdMintState, options: ListNumIdMintOptions): string;
19
19
  declare function parseListNumId(numId: string): ListNumIdInfo | undefined;
20
20
  declare function mintedListType(numId: string): 'bullet' | 'ordered' | undefined;
21
+ declare function mintListItemId(state: NumIdMintState): string;
21
22
  //#endregion
22
- export { ListNumIdInfo, ListNumIdMintOptions, NumIdMintState, createNumIdMintState, mintListNumId, mintedListType, parseListNumId };
23
+ export { ListNumIdInfo, ListNumIdMintOptions, NumIdMintState, createNumIdMintState, mintListItemId, mintListNumId, mintedListType, parseListNumId };
@@ -18,5 +18,6 @@ declare function createNumIdMintState(): NumIdMintState;
18
18
  declare function mintListNumId(state: NumIdMintState, options: ListNumIdMintOptions): string;
19
19
  declare function parseListNumId(numId: string): ListNumIdInfo | undefined;
20
20
  declare function mintedListType(numId: string): 'bullet' | 'ordered' | undefined;
21
+ declare function mintListItemId(state: NumIdMintState): string;
21
22
  //#endregion
22
- export { ListNumIdInfo, ListNumIdMintOptions, NumIdMintState, createNumIdMintState, mintListNumId, mintedListType, parseListNumId };
23
+ export { ListNumIdInfo, ListNumIdMintOptions, NumIdMintState, createNumIdMintState, mintListItemId, mintListNumId, mintedListType, parseListNumId };
@@ -28,5 +28,10 @@ function parseListNumId(numId) {
28
28
  function mintedListType(numId) {
29
29
  return parseListNumId(numId)?.type;
30
30
  }
31
+ function mintListItemId(state) {
32
+ const id = state.next;
33
+ state.next += 1;
34
+ return `md-i${String(id)}`;
35
+ }
31
36
  //#endregion
32
- export { createNumIdMintState, mintListNumId, mintedListType, parseListNumId };
37
+ export { createNumIdMintState, mintListItemId, mintListNumId, mintedListType, parseListNumId };
package/dist/write.cjs CHANGED
@@ -1,11 +1,29 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_diagnostics_diagnostics = require("./diagnostics/diagnostics.cjs");
3
+ const require_emit_front_matter = require("./emit/front-matter.cjs");
4
+ const require_emit_inline = require("./emit/inline.cjs");
3
5
  const require_emit_emit = require("./emit/emit.cjs");
4
6
  let document_schema_js = require("document-schema.js");
5
7
  //#region src/write.ts
6
- function reportDroppedPackageTables(documentPackage, sink) {
8
+ function renderLinkDefinition(label, entry) {
9
+ const destination = entry.destination;
10
+ const title = entry.title;
11
+ if (typeof destination !== "string") return;
12
+ if (title !== void 0 && typeof title !== "string") return;
13
+ return `[${label}]: ${require_emit_inline.escapeLinkDestination(destination)}${title === void 0 ? "" : ` "${require_emit_inline.renderLinkTitle(title)}"`}`;
14
+ }
15
+ function renderLinkDefinitions(definitions) {
16
+ const lines = [];
17
+ for (const [label, entry] of Object.entries(definitions)) {
18
+ const line = renderLinkDefinition(label, entry);
19
+ if (line !== void 0) lines.push(line);
20
+ }
21
+ return lines.length > 0 ? lines.join("\n") : void 0;
22
+ }
23
+ function reportDroppedPackageTables(documentPackage, definitionsRendered, sink) {
24
+ const definitions = documentPackage.definitions;
7
25
  const tables = [
8
- ["definitions", documentPackage.definitions !== void 0 && Object.keys(documentPackage.definitions).length > 0],
26
+ ["definitions", definitions !== void 0 && !definitionsRendered && Object.keys(definitions).length > 0],
9
27
  ["layers", documentPackage.layers !== void 0 && Object.keys(documentPackage.layers).length > 0],
10
28
  ["attachments", documentPackage.attachments !== void 0 && Object.keys(documentPackage.attachments).length > 0],
11
29
  ["destinations", documentPackage.destinations !== void 0 && Object.keys(documentPackage.destinations).length > 0],
@@ -23,14 +41,23 @@ function reportDroppedPackageTables(documentPackage, sink) {
23
41
  function writeMarkdown(documentPackage, options = {}) {
24
42
  options.signal?.throwIfAborted();
25
43
  if (documentPackage.kind !== "wordprocessing") throw new require_diagnostics_diagnostics.MarkdownUnsupportedDocumentKindError(documentPackage.kind);
26
- reportDroppedPackageTables(documentPackage, options.sink ?? require_diagnostics_diagnostics.NOOP_MARKDOWN_DIAGNOSTIC_SINK);
44
+ const sink = options.sink ?? require_diagnostics_diagnostics.NOOP_MARKDOWN_DIAGNOSTIC_SINK;
45
+ const definitionsBlock = documentPackage.definitions === void 0 ? void 0 : renderLinkDefinitions(documentPackage.definitions);
46
+ reportDroppedPackageTables(documentPackage, definitionsBlock !== void 0, sink);
27
47
  let flattened;
28
48
  try {
29
49
  flattened = (0, document_schema_js.flattenPackage)(documentPackage);
30
50
  } catch (error) {
31
51
  throw new require_diagnostics_diagnostics.MarkdownPackageFlattenError(error);
32
52
  }
33
- return writeMarkdownContent(flattened, options);
53
+ const body = writeMarkdownContent(flattened, {
54
+ ...options,
55
+ frontMatter: false
56
+ });
57
+ const frontMatterResidue = documentPackage.source?.frontmatter;
58
+ const frontMatter = options.frontMatter === true ? frontMatterResidue?.format === "markdown" ? frontMatterResidue.xml : require_emit_front_matter.emitFrontMatter(flattened.metadata) : void 0;
59
+ const withFrontMatter = frontMatter === void 0 ? body : `${frontMatter}\n\n${body}`;
60
+ return definitionsBlock === void 0 ? withFrontMatter : withFrontMatter.length > 0 ? `${withFrontMatter}\n\n${definitionsBlock}` : definitionsBlock;
34
61
  }
35
62
  function writeMarkdownContent(document, options = {}) {
36
63
  options.signal?.throwIfAborted();