markdown-codec 6.1.7 → 6.3.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.
- package/README.md +7 -4
- package/dist/block/block.cjs +11 -3
- package/dist/block/block.d.cts +6 -2
- package/dist/block/block.d.ts +6 -2
- package/dist/block/block.js +7 -3
- package/dist/block/definitions.d.cts +1 -1
- package/dist/block/definitions.d.ts +1 -1
- package/dist/codec.d.cts +2 -2
- package/dist/codec.d.ts +2 -2
- package/dist/diagnostics/diagnostics.cjs +3 -0
- package/dist/diagnostics/diagnostics.d.cts +1 -1
- package/dist/diagnostics/diagnostics.d.ts +1 -1
- package/dist/diagnostics/diagnostics.js +3 -0
- package/dist/{diagnostics-CH-xa2-s.d.cts → diagnostics-CnamCy6I.d.cts} +3 -0
- package/dist/{diagnostics-CH-xa2-s.d.ts → diagnostics-CnamCy6I.d.ts} +3 -0
- package/dist/emit/emit.cjs +109 -5
- package/dist/emit/emit.js +109 -5
- package/dist/emit/inline.cjs +4 -3
- package/dist/emit/inline.d.cts +1 -1
- package/dist/emit/inline.d.ts +1 -1
- package/dist/emit/inline.js +4 -3
- package/dist/emit/table.d.cts +1 -1
- package/dist/emit/table.d.ts +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/lower/front-matter.cjs +2 -2
- package/dist/lower/front-matter.d.cts +1 -1
- package/dist/lower/front-matter.d.ts +1 -1
- package/dist/lower/front-matter.js +1 -1
- package/dist/lower/inline.cjs +7 -1
- package/dist/lower/inline.d.cts +1 -1
- package/dist/lower/inline.d.ts +1 -1
- package/dist/lower/inline.js +7 -1
- package/dist/options/options.d.cts +1 -1
- package/dist/options/options.d.ts +1 -1
- package/dist/read.d.cts +1 -1
- package/dist/read.d.ts +1 -1
- package/dist/shared/line-ending.cjs +7 -0
- package/dist/shared/line-ending.d.cts +5 -0
- package/dist/shared/line-ending.d.ts +5 -0
- package/dist/shared/line-ending.js +5 -0
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -197,6 +197,9 @@ Every construct `src/lower`/`src/emit` cannot represent losslessly is a document
|
|
|
197
197
|
- **`md/raw-html-preserved-as-text` / `md/raw-html-dropped`** — raw HTML kept as literal text (default) or dropped; never interpreted. The preserved text's verbatim original quarantines as markdown residue on its node, and this package's own writer re-emits that residue as-is.
|
|
198
198
|
- **`md/front-matter-key-unmapped`** — no YAML/TOML engine; only five known `LayoutMetadata` keys recognised. The verbatim original block rides the package-level residue table (`readMarkdown`'s `documentPackage.source.frontmatter`), which `writeMarkdown` re-emits as-is.
|
|
199
199
|
- **`md/heading-level-clamped`** — styleId beyond `Heading6` (from another format) clamps to level 6 via document-schema.js's shared `clampHeadingLevel()`.
|
|
200
|
+
- **`md/heading-line-break-collapsed`** — a hard or soft break embedded in a heading's own runs (most commonly a setext heading read with more than one physical line) is promoted to setext output whenever the level admits one (1 or 2) and the break's own placement is safe to promote, the only markdown grammar that can hold a genuine line break inside heading text; a level 3-6 heading with the same shape has no such fallback and always collapses the break to a single space instead, as does a level 1/2 heading whose break placement is unsafe to promote (see `md/heading-line-break-unsafe-for-setext` below).
|
|
201
|
+
- **`md/heading-line-break-unsafe-for-setext`** — a level 1/2 heading's own embedded break sits where promoting to setext would violate one of the three clauses packed into setext's own grammar sentence (spec 0.31.2, "Setext headings"): "one or more lines of text, not interrupted by a blank line, of which the first line does not have more than 3 spaces of indentation, followed by a setext heading underline. The lines of text must be such that, were they not followed by the setext heading underline, they would be interpreted as a paragraph: they cannot be interpretable as a code fence, ATX heading, block quote, thematic break, list item, or HTML block." Reported when promoting would leave a blank line immediately before the underline (a trailing break) or in the middle of the heading's own text (an interior break between two embedded breaks, or a break immediately followed by incidental whitespace-only content); when the heading's own first content line opens with 4 or more columns of space/tab indentation — CommonMark's own tab-stop rule counts a tab by the same 4-column stop, so a single leading tab is exactly as unsafe as 4 leading spaces — since that line would read back as an indented code block rather than heading text; or when a line AFTER the first would itself be read as one of the spec's six interrupting constructs (a code fence, ATX heading, block quote, thematic break, list item, or HTML block) instead of ordinary paragraph continuation text — reachable from a bold or strikethrough run that becomes empty immediately after a break, whose bare pair of emphasis markers spells as a thematic break (`____`/`****`) or a code-fence opener (`~~~~`). ATX collapses the break to a single space instead of promoting into any of these corrupt reparses. A break at the very START of the heading's own text stays eligible for setext, but that exemption covers only a single leading blank line, and only the blank line itself: it sits before the text-and-underline run even begins, so it reparses as ordinary inter-block whitespace ahead of the heading rather than corrupting anything. A second consecutive leading blank line is not exempt — CommonMark's own list-item grammar allows at most one, so a second closes a list item as empty and spills the heading out with its list membership lost, even though it would be harmless at top level or inside a blockquote — and the indentation clause above still applies in full to the line that follows the leading blank line, the heading's own first real content: a leading break immediately followed by 4 or more columns of indentation is refused exactly as an unbroken heading in the same shape would be, since promoting would read that following line back as an indented code block regardless of the leading break ahead of it.
|
|
202
|
+
- **`md/heading-style-overridden-for-line-break`** — the setext promotion above overriding the effective `headingStyle: 'atx'` (this option's own default just as much as an explicit caller choice); that one heading renders as setext regardless because ATX cannot hold the embedded break at all.
|
|
200
203
|
- **`md/adjacent-links-merged`** / **`md/code-span-as-monospace-run`** — same-destination adjacent links merge; monospace runs emit as code spans.
|
|
201
204
|
- **`md/paragraph-indent-dropped`** — `indentLeftPt` without a recognised styleId; indent dropped, paragraph renders.
|
|
202
205
|
- **`md/list-numid-fallback`** — a foreign or absent `numId` (depth-only `ContentListMembership`) falls back to a plain bullet list.
|
|
@@ -228,11 +231,11 @@ Emission is the inverse and validates first: a section's markers must pair as ba
|
|
|
228
231
|
|
|
229
232
|
| Corpus | Examples | Passing round trip | Rate |
|
|
230
233
|
| ------------------------------------------------------------------------------------- | -------- | ------------------ | ----- |
|
|
231
|
-
| CommonMark 0.31.2 (`assets/commonmark/spec.json`) | 652 |
|
|
232
|
-
| GFM tagged extensions (table/strikethrough/autolink/task-list, `assets/gfm/spec.txt`) | 23 |
|
|
233
|
-
| Combined | 675 |
|
|
234
|
+
| CommonMark 0.31.2 (`assets/commonmark/spec.json`) | 652 | 575 | 88.2% |
|
|
235
|
+
| GFM tagged extensions (table/strikethrough/autolink/task-list, `assets/gfm/spec.txt`) | 23 | 23 | 100% |
|
|
236
|
+
| Combined | 675 | 598 | 88.6% |
|
|
234
237
|
|
|
235
|
-
Every non-passing example is named individually in `src/test-support/conformance-exclusions.ts`, attributed to a closed set of causes (shrink-only — see [Conventions](#conventions)): most commonly
|
|
238
|
+
Every non-passing example is named individually in `src/test-support/conformance-exclusions.ts`, attributed to a closed set of causes (shrink-only — see [Conventions](#conventions)): most commonly an emphasis-span collision, an image with no `data:` URI source for the harness to embed, or a blockquote whose heading content skips its container pair.
|
|
236
239
|
|
|
237
240
|
**Optional real-world corpus.** `test/corpus/` (gitignored) holds a `pnpm test:corpus` project for a manual sanity check against sibling READMEs on disk — asserts no throw and real content on reparse, not byte fidelity. Not part of `pnpm test`; run locally before significant parser/lower/emit changes.
|
|
238
241
|
|
package/dist/block/block.cjs
CHANGED
|
@@ -5,6 +5,7 @@ const require_diagnostics_diagnostics = require("../diagnostics/diagnostics.cjs"
|
|
|
5
5
|
const require_html_html = require("../html/html.cjs");
|
|
6
6
|
const require_inline_entity = require("../inline/entity.cjs");
|
|
7
7
|
const require_inline_inline = require("../inline/inline.cjs");
|
|
8
|
+
const require_shared_line_ending = require("../shared/line-ending.cjs");
|
|
8
9
|
const require_block_definitions = require("./definitions.cjs");
|
|
9
10
|
const require_block_line = require("./line.cjs");
|
|
10
11
|
const require_block_list = require("./list.cjs");
|
|
@@ -14,7 +15,6 @@ const require_block_table = require("./table.cjs");
|
|
|
14
15
|
const TASK_LIST_MARKER_PATTERN = /^\[([ xX])\][ \t]/;
|
|
15
16
|
const NUL_REPLACEMENT = "�";
|
|
16
17
|
const NUL_PATTERN = /\0/g;
|
|
17
|
-
const LINE_ENDING_PATTERN = /\r\n|\n|\r/;
|
|
18
18
|
const MAYBE_SPECIAL_PATTERN = /^[#$`~*+_=<>[0-9|:-]/;
|
|
19
19
|
const ATX_MARKER_PATTERN = /^#{1,6}(?:[ \t]+|$)/;
|
|
20
20
|
const ATX_ONLY_CLOSING_SEQUENCE_PATTERN = /^[ \t]*#+[ \t]*$/;
|
|
@@ -67,7 +67,7 @@ var BlockParser = class {
|
|
|
67
67
|
this.maxNesting = options.maxNesting ?? 250;
|
|
68
68
|
}
|
|
69
69
|
parse(source) {
|
|
70
|
-
const lines = source.split(LINE_ENDING_PATTERN);
|
|
70
|
+
const lines = source.split(require_shared_line_ending.LINE_ENDING_PATTERN);
|
|
71
71
|
const count = source.endsWith("\n") || source.endsWith("\r") ? lines.length - 1 : lines.length;
|
|
72
72
|
for (let index = 0; index < count; index += 1) {
|
|
73
73
|
const text = lines[index];
|
|
@@ -470,8 +470,12 @@ var BlockParser = class {
|
|
|
470
470
|
node.literal = breakIndex === -1 ? "" : node.content.slice(breakIndex + 1);
|
|
471
471
|
}
|
|
472
472
|
};
|
|
473
|
+
const BLOCK_EDGE_SPACE_OR_TAB_PATTERN = /^[ \t]+|[ \t]+$/g;
|
|
474
|
+
function trimBlockContent(text) {
|
|
475
|
+
return (text.endsWith("\n") ? text.slice(0, -1) : text).replace(BLOCK_EDGE_SPACE_OR_TAB_PATTERN, "");
|
|
476
|
+
}
|
|
473
477
|
function toInlineChildren(content, context) {
|
|
474
|
-
return require_inline_inline.parseInlines(content
|
|
478
|
+
return require_inline_inline.parseInlines(trimBlockContent(content), context.references, context.footnotes, context.options);
|
|
475
479
|
}
|
|
476
480
|
function toHeadingNode(node, context) {
|
|
477
481
|
return {
|
|
@@ -618,4 +622,8 @@ function parseMarkdown(source, options = {}) {
|
|
|
618
622
|
};
|
|
619
623
|
}
|
|
620
624
|
//#endregion
|
|
625
|
+
exports.ATX_MARKER_PATTERN = ATX_MARKER_PATTERN;
|
|
626
|
+
exports.CODE_FENCE_PATTERN = CODE_FENCE_PATTERN;
|
|
627
|
+
exports.MATH_BLOCK_MARKER_PATTERN = MATH_BLOCK_MARKER_PATTERN;
|
|
628
|
+
exports.THEMATIC_BREAK_PATTERN = THEMATIC_BREAK_PATTERN;
|
|
621
629
|
exports.parseMarkdown = parseMarkdown;
|
package/dist/block/block.d.cts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { s as MarkdownDocumentNode } from "../ast-CNfTgS0N.cjs";
|
|
2
2
|
import { r as FootnoteLabelSet } from "../footnote-CKk4JbLk.cjs";
|
|
3
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
3
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.cjs";
|
|
4
4
|
import { LinkReferenceMap } from "../inline/link.cjs";
|
|
5
5
|
import { t as InlineParseOptions } from "../inline-CnO86zMw.cjs";
|
|
6
6
|
//#region src/block/block.d.ts
|
|
7
|
+
declare const ATX_MARKER_PATTERN: RegExp;
|
|
8
|
+
declare const CODE_FENCE_PATTERN: RegExp;
|
|
9
|
+
declare const MATH_BLOCK_MARKER_PATTERN: RegExp;
|
|
10
|
+
declare const THEMATIC_BREAK_PATTERN: RegExp;
|
|
7
11
|
interface MarkdownParseOptions extends InlineParseOptions {
|
|
8
12
|
readonly gfmTables?: boolean;
|
|
9
13
|
readonly gfmTaskLists?: boolean;
|
|
@@ -18,4 +22,4 @@ interface ParsedMarkdown {
|
|
|
18
22
|
}
|
|
19
23
|
declare function parseMarkdown(source: string, options?: MarkdownParseOptions): ParsedMarkdown;
|
|
20
24
|
//#endregion
|
|
21
|
-
export { MarkdownParseOptions, ParsedMarkdown, parseMarkdown };
|
|
25
|
+
export { ATX_MARKER_PATTERN, CODE_FENCE_PATTERN, MATH_BLOCK_MARKER_PATTERN, MarkdownParseOptions, ParsedMarkdown, THEMATIC_BREAK_PATTERN, parseMarkdown };
|
package/dist/block/block.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { s as MarkdownDocumentNode } from "../ast-CNfTgS0N.js";
|
|
2
2
|
import { r as FootnoteLabelSet } from "../footnote-CKk4JbLk.js";
|
|
3
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
3
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.js";
|
|
4
4
|
import { LinkReferenceMap } from "../inline/link.js";
|
|
5
5
|
import { t as InlineParseOptions } from "../inline-DItZ-VVw.js";
|
|
6
6
|
//#region src/block/block.d.ts
|
|
7
|
+
declare const ATX_MARKER_PATTERN: RegExp;
|
|
8
|
+
declare const CODE_FENCE_PATTERN: RegExp;
|
|
9
|
+
declare const MATH_BLOCK_MARKER_PATTERN: RegExp;
|
|
10
|
+
declare const THEMATIC_BREAK_PATTERN: RegExp;
|
|
7
11
|
interface MarkdownParseOptions extends InlineParseOptions {
|
|
8
12
|
readonly gfmTables?: boolean;
|
|
9
13
|
readonly gfmTaskLists?: boolean;
|
|
@@ -18,4 +22,4 @@ interface ParsedMarkdown {
|
|
|
18
22
|
}
|
|
19
23
|
declare function parseMarkdown(source: string, options?: MarkdownParseOptions): ParsedMarkdown;
|
|
20
24
|
//#endregion
|
|
21
|
-
export { MarkdownParseOptions, ParsedMarkdown, parseMarkdown };
|
|
25
|
+
export { ATX_MARKER_PATTERN, CODE_FENCE_PATTERN, MATH_BLOCK_MARKER_PATTERN, MarkdownParseOptions, ParsedMarkdown, THEMATIC_BREAK_PATTERN, parseMarkdown };
|
package/dist/block/block.js
CHANGED
|
@@ -4,6 +4,7 @@ import { MarkdownDiagnosticCodes, MarkdownNestingLimitExceededError, NOOP_MARKDO
|
|
|
4
4
|
import { matchHtmlBlockStart, matchesHtmlBlockEnd } from "../html/html.js";
|
|
5
5
|
import { unescapeString } from "../inline/entity.js";
|
|
6
6
|
import { parseInlines } from "../inline/inline.js";
|
|
7
|
+
import { LINE_ENDING_PATTERN } from "../shared/line-ending.js";
|
|
7
8
|
import { extractDefinitions } from "./definitions.js";
|
|
8
9
|
import { LineCursor } from "./line.js";
|
|
9
10
|
import { finalizeListTightness, listsMatch, parseListMarker } from "./list.js";
|
|
@@ -13,7 +14,6 @@ import { fitRowToColumns, parseTableDelimiterRow, splitTableRow } from "./table.
|
|
|
13
14
|
const TASK_LIST_MARKER_PATTERN = /^\[([ xX])\][ \t]/;
|
|
14
15
|
const NUL_REPLACEMENT = "�";
|
|
15
16
|
const NUL_PATTERN = /\0/g;
|
|
16
|
-
const LINE_ENDING_PATTERN = /\r\n|\n|\r/;
|
|
17
17
|
const MAYBE_SPECIAL_PATTERN = /^[#$`~*+_=<>[0-9|:-]/;
|
|
18
18
|
const ATX_MARKER_PATTERN = /^#{1,6}(?:[ \t]+|$)/;
|
|
19
19
|
const ATX_ONLY_CLOSING_SEQUENCE_PATTERN = /^[ \t]*#+[ \t]*$/;
|
|
@@ -469,8 +469,12 @@ var BlockParser = class {
|
|
|
469
469
|
node.literal = breakIndex === -1 ? "" : node.content.slice(breakIndex + 1);
|
|
470
470
|
}
|
|
471
471
|
};
|
|
472
|
+
const BLOCK_EDGE_SPACE_OR_TAB_PATTERN = /^[ \t]+|[ \t]+$/g;
|
|
473
|
+
function trimBlockContent(text) {
|
|
474
|
+
return (text.endsWith("\n") ? text.slice(0, -1) : text).replace(BLOCK_EDGE_SPACE_OR_TAB_PATTERN, "");
|
|
475
|
+
}
|
|
472
476
|
function toInlineChildren(content, context) {
|
|
473
|
-
return parseInlines(content
|
|
477
|
+
return parseInlines(trimBlockContent(content), context.references, context.footnotes, context.options);
|
|
474
478
|
}
|
|
475
479
|
function toHeadingNode(node, context) {
|
|
476
480
|
return {
|
|
@@ -617,4 +621,4 @@ function parseMarkdown(source, options = {}) {
|
|
|
617
621
|
};
|
|
618
622
|
}
|
|
619
623
|
//#endregion
|
|
620
|
-
export { parseMarkdown };
|
|
624
|
+
export { ATX_MARKER_PATTERN, CODE_FENCE_PATTERN, MATH_BLOCK_MARKER_PATTERN, THEMATIC_BREAK_PATTERN, parseMarkdown };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
1
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.cjs";
|
|
2
2
|
import { LinkReferenceDefinition } from "../inline/link.cjs";
|
|
3
3
|
//#region src/block/definitions.d.ts
|
|
4
4
|
declare function extractDefinitions(content: string, references: Map<string, LinkReferenceDefinition>, sink?: MarkdownDiagnosticSink, startLine?: number): string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
1
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.js";
|
|
2
2
|
import { LinkReferenceDefinition } from "../inline/link.js";
|
|
3
3
|
//#region src/block/definitions.d.ts
|
|
4
4
|
declare function extractDefinitions(content: string, references: Map<string, LinkReferenceDefinition>, sink?: MarkdownDiagnosticSink, startLine?: number): string;
|
package/dist/codec.d.cts
CHANGED
|
@@ -1425,10 +1425,10 @@ declare const markdownContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffe
|
|
|
1425
1425
|
endColumn: z.ZodNumber;
|
|
1426
1426
|
}, z.core.$strip>>;
|
|
1427
1427
|
type: z.ZodEnum<{
|
|
1428
|
-
date: "date";
|
|
1429
|
-
custom: "custom";
|
|
1430
1428
|
decimal: "decimal";
|
|
1431
1429
|
list: "list";
|
|
1430
|
+
date: "date";
|
|
1431
|
+
custom: "custom";
|
|
1432
1432
|
time: "time";
|
|
1433
1433
|
whole: "whole";
|
|
1434
1434
|
textLength: "textLength";
|
package/dist/codec.d.ts
CHANGED
|
@@ -1425,10 +1425,10 @@ declare const markdownContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffe
|
|
|
1425
1425
|
endColumn: z.ZodNumber;
|
|
1426
1426
|
}, z.core.$strip>>;
|
|
1427
1427
|
type: z.ZodEnum<{
|
|
1428
|
-
date: "date";
|
|
1429
|
-
custom: "custom";
|
|
1430
1428
|
decimal: "decimal";
|
|
1431
1429
|
list: "list";
|
|
1430
|
+
date: "date";
|
|
1431
|
+
custom: "custom";
|
|
1432
1432
|
time: "time";
|
|
1433
1433
|
whole: "whole";
|
|
1434
1434
|
textLength: "textLength";
|
|
@@ -26,6 +26,9 @@ const MarkdownDiagnosticCodes = {
|
|
|
26
26
|
ADJACENT_LINKS_MERGED: "md/adjacent-links-merged",
|
|
27
27
|
CODE_SPAN_AS_MONOSPACE_RUN: "md/code-span-as-monospace-run",
|
|
28
28
|
PARAGRAPH_INDENT_DROPPED: "md/paragraph-indent-dropped",
|
|
29
|
+
HEADING_LINE_BREAK_COLLAPSED: "md/heading-line-break-collapsed",
|
|
30
|
+
HEADING_LINE_BREAK_UNSAFE_FOR_SETEXT: "md/heading-line-break-unsafe-for-setext",
|
|
31
|
+
HEADING_STYLE_OVERRIDDEN_FOR_LINE_BREAK: "md/heading-style-overridden-for-line-break",
|
|
29
32
|
LIST_NUMID_FALLBACK: "md/list-numid-fallback",
|
|
30
33
|
TABLE_CELL_FORMATTING_DROPPED: "md/table-cell-formatting-dropped",
|
|
31
34
|
TABLE_CELL_MULTI_PARAGRAPH_JOINED: "md/table-cell-multi-paragraph-joined"
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as MarkdownInputTooLargeError, c as MarkdownNestingLimitExceededError, d as MarkdownUnbalancedConstructMarkersError, f as MarkdownUnsupportedDocumentKindError, i as MarkdownDiagnosticSink, l as MarkdownPackageFlattenError, m as NOOP_MARKDOWN_DIAGNOSTIC_SINK, n as MarkdownDiagnosticCodes, o as MarkdownInvalidRunConstructExtentError, p as MarkdownWriteError, r as MarkdownDiagnosticSeverity, s as MarkdownInvalidUtf8Error, t as MarkdownDiagnostic, u as MarkdownParseError } from "../diagnostics-
|
|
1
|
+
import { a as MarkdownInputTooLargeError, c as MarkdownNestingLimitExceededError, d as MarkdownUnbalancedConstructMarkersError, f as MarkdownUnsupportedDocumentKindError, i as MarkdownDiagnosticSink, l as MarkdownPackageFlattenError, m as NOOP_MARKDOWN_DIAGNOSTIC_SINK, n as MarkdownDiagnosticCodes, o as MarkdownInvalidRunConstructExtentError, p as MarkdownWriteError, r as MarkdownDiagnosticSeverity, s as MarkdownInvalidUtf8Error, t as MarkdownDiagnostic, u as MarkdownParseError } from "../diagnostics-CnamCy6I.cjs";
|
|
2
2
|
export { MarkdownDiagnostic, MarkdownDiagnosticCodes, MarkdownDiagnosticSeverity, MarkdownDiagnosticSink, MarkdownInputTooLargeError, MarkdownInvalidRunConstructExtentError, MarkdownInvalidUtf8Error, MarkdownNestingLimitExceededError, MarkdownPackageFlattenError, MarkdownParseError, MarkdownUnbalancedConstructMarkersError, MarkdownUnsupportedDocumentKindError, MarkdownWriteError, NOOP_MARKDOWN_DIAGNOSTIC_SINK };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as MarkdownInputTooLargeError, c as MarkdownNestingLimitExceededError, d as MarkdownUnbalancedConstructMarkersError, f as MarkdownUnsupportedDocumentKindError, i as MarkdownDiagnosticSink, l as MarkdownPackageFlattenError, m as NOOP_MARKDOWN_DIAGNOSTIC_SINK, n as MarkdownDiagnosticCodes, o as MarkdownInvalidRunConstructExtentError, p as MarkdownWriteError, r as MarkdownDiagnosticSeverity, s as MarkdownInvalidUtf8Error, t as MarkdownDiagnostic, u as MarkdownParseError } from "../diagnostics-
|
|
1
|
+
import { a as MarkdownInputTooLargeError, c as MarkdownNestingLimitExceededError, d as MarkdownUnbalancedConstructMarkersError, f as MarkdownUnsupportedDocumentKindError, i as MarkdownDiagnosticSink, l as MarkdownPackageFlattenError, m as NOOP_MARKDOWN_DIAGNOSTIC_SINK, n as MarkdownDiagnosticCodes, o as MarkdownInvalidRunConstructExtentError, p as MarkdownWriteError, r as MarkdownDiagnosticSeverity, s as MarkdownInvalidUtf8Error, t as MarkdownDiagnostic, u as MarkdownParseError } from "../diagnostics-CnamCy6I.js";
|
|
2
2
|
export { MarkdownDiagnostic, MarkdownDiagnosticCodes, MarkdownDiagnosticSeverity, MarkdownDiagnosticSink, MarkdownInputTooLargeError, MarkdownInvalidRunConstructExtentError, MarkdownInvalidUtf8Error, MarkdownNestingLimitExceededError, MarkdownPackageFlattenError, MarkdownParseError, MarkdownUnbalancedConstructMarkersError, MarkdownUnsupportedDocumentKindError, MarkdownWriteError, NOOP_MARKDOWN_DIAGNOSTIC_SINK };
|
|
@@ -25,6 +25,9 @@ const MarkdownDiagnosticCodes = {
|
|
|
25
25
|
ADJACENT_LINKS_MERGED: "md/adjacent-links-merged",
|
|
26
26
|
CODE_SPAN_AS_MONOSPACE_RUN: "md/code-span-as-monospace-run",
|
|
27
27
|
PARAGRAPH_INDENT_DROPPED: "md/paragraph-indent-dropped",
|
|
28
|
+
HEADING_LINE_BREAK_COLLAPSED: "md/heading-line-break-collapsed",
|
|
29
|
+
HEADING_LINE_BREAK_UNSAFE_FOR_SETEXT: "md/heading-line-break-unsafe-for-setext",
|
|
30
|
+
HEADING_STYLE_OVERRIDDEN_FOR_LINE_BREAK: "md/heading-style-overridden-for-line-break",
|
|
28
31
|
LIST_NUMID_FALLBACK: "md/list-numid-fallback",
|
|
29
32
|
TABLE_CELL_FORMATTING_DROPPED: "md/table-cell-formatting-dropped",
|
|
30
33
|
TABLE_CELL_MULTI_PARAGRAPH_JOINED: "md/table-cell-multi-paragraph-joined"
|
|
@@ -33,6 +33,9 @@ declare const MarkdownDiagnosticCodes: {
|
|
|
33
33
|
readonly ADJACENT_LINKS_MERGED: "md/adjacent-links-merged";
|
|
34
34
|
readonly CODE_SPAN_AS_MONOSPACE_RUN: "md/code-span-as-monospace-run";
|
|
35
35
|
readonly PARAGRAPH_INDENT_DROPPED: "md/paragraph-indent-dropped";
|
|
36
|
+
readonly HEADING_LINE_BREAK_COLLAPSED: "md/heading-line-break-collapsed";
|
|
37
|
+
readonly HEADING_LINE_BREAK_UNSAFE_FOR_SETEXT: "md/heading-line-break-unsafe-for-setext";
|
|
38
|
+
readonly HEADING_STYLE_OVERRIDDEN_FOR_LINE_BREAK: "md/heading-style-overridden-for-line-break";
|
|
36
39
|
readonly LIST_NUMID_FALLBACK: "md/list-numid-fallback";
|
|
37
40
|
readonly TABLE_CELL_FORMATTING_DROPPED: "md/table-cell-formatting-dropped";
|
|
38
41
|
readonly TABLE_CELL_MULTI_PARAGRAPH_JOINED: "md/table-cell-multi-paragraph-joined";
|
|
@@ -33,6 +33,9 @@ declare const MarkdownDiagnosticCodes: {
|
|
|
33
33
|
readonly ADJACENT_LINKS_MERGED: "md/adjacent-links-merged";
|
|
34
34
|
readonly CODE_SPAN_AS_MONOSPACE_RUN: "md/code-span-as-monospace-run";
|
|
35
35
|
readonly PARAGRAPH_INDENT_DROPPED: "md/paragraph-indent-dropped";
|
|
36
|
+
readonly HEADING_LINE_BREAK_COLLAPSED: "md/heading-line-break-collapsed";
|
|
37
|
+
readonly HEADING_LINE_BREAK_UNSAFE_FOR_SETEXT: "md/heading-line-break-unsafe-for-setext";
|
|
38
|
+
readonly HEADING_STYLE_OVERRIDDEN_FOR_LINE_BREAK: "md/heading-style-overridden-for-line-break";
|
|
36
39
|
readonly LIST_NUMID_FALLBACK: "md/list-numid-fallback";
|
|
37
40
|
readonly TABLE_CELL_FORMATTING_DROPPED: "md/table-cell-formatting-dropped";
|
|
38
41
|
readonly TABLE_CELL_MULTI_PARAGRAPH_JOINED: "md/table-cell-multi-paragraph-joined";
|
package/dist/emit/emit.cjs
CHANGED
|
@@ -2,6 +2,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
const require_inline_footnote = require("../inline/footnote.cjs");
|
|
3
3
|
require("../defaults/defaults.cjs");
|
|
4
4
|
const require_diagnostics_diagnostics = require("../diagnostics/diagnostics.cjs");
|
|
5
|
+
const require_html_html = require("../html/html.cjs");
|
|
6
|
+
const require_shared_line_ending = require("../shared/line-ending.cjs");
|
|
7
|
+
require("../scan/scan.cjs");
|
|
8
|
+
const require_block_line = require("../block/line.cjs");
|
|
9
|
+
const require_block_list = require("../block/list.cjs");
|
|
10
|
+
const require_block_table = require("../block/table.cjs");
|
|
11
|
+
const require_block_block = require("../block/block.cjs");
|
|
5
12
|
const require_shared_list_id = require("../shared/list-id.cjs");
|
|
6
13
|
const require_shared_style_constants = require("../shared/style-constants.cjs");
|
|
7
14
|
const require_emit_front_matter = require("./front-matter.cjs");
|
|
@@ -19,7 +26,7 @@ const SETEXT_LEVEL_2_CHAR = "-";
|
|
|
19
26
|
const MIN_SETEXT_UNDERLINE_LENGTH = 1;
|
|
20
27
|
function renderSetextHeading(level, text) {
|
|
21
28
|
const underlineChar = level === 1 ? SETEXT_LEVEL_1_CHAR : SETEXT_LEVEL_2_CHAR;
|
|
22
|
-
const firstLine = text.split(
|
|
29
|
+
const firstLine = text.split(require_shared_line_ending.LINE_ENDING_PATTERN)[0] ?? "";
|
|
23
30
|
return `${text}\n${underlineChar.repeat(Math.max(MIN_SETEXT_UNDERLINE_LENGTH, firstLine.length))}`;
|
|
24
31
|
}
|
|
25
32
|
const MIN_CODE_FENCE_LENGTH = 3;
|
|
@@ -50,12 +57,78 @@ function terminatesCleanly(styleId) {
|
|
|
50
57
|
if (styleId === void 0 || styleId === "Quote" || styleId === "HTMLPreformatted") return false;
|
|
51
58
|
return styleId === "CodeBlock" || styleId === "MathBlock" || styleId === "HorizontalRule" || require_shared_style_constants.parseHeadingStyleId(styleId) !== void 0;
|
|
52
59
|
}
|
|
53
|
-
|
|
60
|
+
const BLANK_OR_WHITESPACE_ONLY_LINE = /^[ \t]*$/;
|
|
61
|
+
function firstContentLineIndex(text) {
|
|
62
|
+
return text.split(require_shared_line_ending.LINE_ENDING_PATTERN).findIndex((line) => !BLANK_OR_WHITESPACE_ONLY_LINE.test(line));
|
|
63
|
+
}
|
|
64
|
+
function leadingIndentColumns(line) {
|
|
65
|
+
let column = 0;
|
|
66
|
+
for (const char of line) if (char === " ") column += 1;
|
|
67
|
+
else if (char === " ") column += 4 - column % 4;
|
|
68
|
+
else break;
|
|
69
|
+
return column;
|
|
70
|
+
}
|
|
71
|
+
const MAX_LEADING_BLANK_LINES_FOR_SETEXT = 1;
|
|
72
|
+
function interruptsSetextParagraph(line, atBlockStart) {
|
|
73
|
+
const cursor = new require_block_line.LineCursor(line);
|
|
74
|
+
if (cursor.indented) return false;
|
|
75
|
+
if (cursor.peekNextNonspace() === ">") return true;
|
|
76
|
+
const rest = cursor.restFromNextNonspace();
|
|
77
|
+
if (require_block_block.ATX_MARKER_PATTERN.test(rest) || require_block_block.CODE_FENCE_PATTERN.test(rest) || require_block_block.THEMATIC_BREAK_PATTERN.test(rest) || require_block_block.MATH_BLOCK_MARKER_PATTERN.test(rest) || require_html_html.matchHtmlBlockStart(rest, !atBlockStart) !== void 0) return true;
|
|
78
|
+
return require_block_list.parseListMarker(cursor, !atBlockStart) !== void 0;
|
|
79
|
+
}
|
|
80
|
+
function tableDelimiterRowPromotesPrecedingLine(line, precedingLine) {
|
|
81
|
+
const cursor = new require_block_line.LineCursor(line);
|
|
82
|
+
if (cursor.indented) return false;
|
|
83
|
+
return require_block_table.parseTableDelimiterRow(cursor.restFromNextNonspace())?.length === require_block_table.splitTableRow(precedingLine).length;
|
|
84
|
+
}
|
|
85
|
+
function unsafeSetextBreakReason(text) {
|
|
86
|
+
let sawContentLine = false;
|
|
87
|
+
let leadingBlankLines = 0;
|
|
88
|
+
let precedingLine = "";
|
|
89
|
+
for (const line of text.split(require_shared_line_ending.LINE_ENDING_PATTERN)) {
|
|
90
|
+
const isBlank = BLANK_OR_WHITESPACE_ONLY_LINE.test(line);
|
|
91
|
+
if (!sawContentLine) {
|
|
92
|
+
if (isBlank) {
|
|
93
|
+
leadingBlankLines += 1;
|
|
94
|
+
if (leadingBlankLines > MAX_LEADING_BLANK_LINES_FOR_SETEXT) return "blank-line";
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
sawContentLine = true;
|
|
98
|
+
if (leadingIndentColumns(line) >= 4) return "leading-indentation";
|
|
99
|
+
if (interruptsSetextParagraph(line, true)) return "interrupting-line";
|
|
100
|
+
precedingLine = line;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (isBlank) return "blank-line";
|
|
104
|
+
if (interruptsSetextParagraph(line, false) || tableDelimiterRowPromotesPrecedingLine(line, precedingLine)) return "interrupting-line";
|
|
105
|
+
precedingLine = line;
|
|
106
|
+
}
|
|
107
|
+
return sawContentLine ? void 0 : "blank-line";
|
|
108
|
+
}
|
|
109
|
+
function embedsUnsafeBreakForSetext(text) {
|
|
110
|
+
return unsafeSetextBreakReason(text) !== void 0;
|
|
111
|
+
}
|
|
112
|
+
function unsafeSetextDiagnosticMessage(level, reason, embedsLineBreak) {
|
|
113
|
+
const hazard = reason === "leading-indentation" ? `the line that would become the setext heading's own first line of text opens with 4 or more columns of space/tab indentation -- setext's own grammar (spec 0.31.2) requires the first line to have "not more than 3 spaces of indentation", so promoting would read that line back as an indented code block instead of heading text` : reason === "interrupting-line" ? `a line of the heading's own text -- including possibly its first -- would itself be interpretable as a code fence, ATX heading, block quote, thematic break, list item, HTML block, math block, or GFM table delimiter row -- setext's own grammar (spec 0.31.2) requires every one of the heading's lines to instead read as ordinary paragraph text, so promoting would read that line back as the start of a fresh, unrelated block (or, for a table delimiter row, a conversion of the line before it) rather than more of the heading` : `promoting would leave the setext underline with no heading text of its own to attach to -- either a blank line immediately before it (a trailing break), a blank line in the middle of the heading's own text (a genuinely interior break), or the heading's own rendered text being entirely blank to begin with -- setext's own grammar requires "one or more lines of text, not interrupted by a blank line"`;
|
|
114
|
+
return embedsLineBreak ? `a level ${String(level)} heading's own content contains a line break, but ${hazard}; ATX collapses the break to a single space instead of promoting into a corrupt reparse` : `the effective WriteMarkdownOptions.headingStyle is 'setext' (an explicit caller choice -- a break-free heading only reaches this path when requested outright), but ${hazard}; rendered as ATX instead of promoting into a corrupt reparse`;
|
|
115
|
+
}
|
|
116
|
+
function willRenderAsSetext(paragraph, level, context) {
|
|
117
|
+
if (level > MAX_SETEXT_LEVEL) return false;
|
|
118
|
+
const text = require_emit_inline.emitRuns(paragraph.runs, {
|
|
119
|
+
sink: require_diagnostics_diagnostics.NOOP_MARKDOWN_DIAGNOSTIC_SINK,
|
|
120
|
+
emphasisMarker: context.emphasisMarker
|
|
121
|
+
}, paragraph.constructs);
|
|
122
|
+
if (embedsUnsafeBreakForSetext(text)) return false;
|
|
123
|
+
return context.headingStyle === "setext" || require_shared_line_ending.LINE_ENDING_PATTERN.test(text);
|
|
124
|
+
}
|
|
125
|
+
function canInterruptOpenParagraph(paragraph, context) {
|
|
126
|
+
const styleId = paragraph.styleId;
|
|
54
127
|
if (styleId === void 0 || styleId === "Quote" || styleId === "HTMLPreformatted") return false;
|
|
55
128
|
if (styleId === "CodeBlock" || styleId === "MathBlock") return true;
|
|
56
129
|
if (styleId === "HorizontalRule") return context.thematicBreakChar !== SETEXT_LEVEL_2_CHAR;
|
|
57
130
|
const headingLevel = require_shared_style_constants.parseHeadingStyleId(styleId);
|
|
58
|
-
if (headingLevel !== void 0) return !(
|
|
131
|
+
if (headingLevel !== void 0) return !willRenderAsSetext(paragraph, (0, document_schema_js.clampHeadingLevel)(headingLevel), context);
|
|
59
132
|
return false;
|
|
60
133
|
}
|
|
61
134
|
function quoteDepthOf(paragraph) {
|
|
@@ -83,7 +156,38 @@ function renderParagraphBody(paragraph, context) {
|
|
|
83
156
|
message: `heading level ${String(headingLevel)} exceeds ATX's own six-"#" ceiling and is clamped to ${String(level)}`
|
|
84
157
|
});
|
|
85
158
|
const text = require_emit_inline.emitRuns(paragraph.runs, context, paragraph.constructs);
|
|
86
|
-
|
|
159
|
+
const embedsLineBreak = require_shared_line_ending.LINE_ENDING_PATTERN.test(text);
|
|
160
|
+
const unsafeSetextReason = unsafeSetextBreakReason(text);
|
|
161
|
+
const unsafeForSetext = unsafeSetextReason !== void 0;
|
|
162
|
+
const setextRequested = context.headingStyle === "setext" || embedsLineBreak;
|
|
163
|
+
if (setextRequested && level <= MAX_SETEXT_LEVEL && !unsafeForSetext) {
|
|
164
|
+
if (context.headingStyle !== "setext") {
|
|
165
|
+
const leadingBreakAbsorbed = firstContentLineIndex(text) > 0;
|
|
166
|
+
context.sink({
|
|
167
|
+
code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.HEADING_STYLE_OVERRIDDEN_FOR_LINE_BREAK,
|
|
168
|
+
severity: "info",
|
|
169
|
+
message: leadingBreakAbsorbed ? `the effective WriteMarkdownOptions.headingStyle is 'atx' (its own default, or an explicit caller choice), but this level ${String(level)} heading's own content contains a line break ATX has no way to hold -- rendered as setext instead, though the heading's own leading blank line is absorbed as ordinary space ahead of it on read-back rather than reproduced inside it` : `the effective WriteMarkdownOptions.headingStyle is 'atx' (its own default, or an explicit caller choice), but this level ${String(level)} heading's own content contains a line break ATX has no way to hold -- rendered as setext instead so the break survives`
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
return renderSetextHeading(level, text);
|
|
173
|
+
}
|
|
174
|
+
if (setextRequested && level <= MAX_SETEXT_LEVEL && unsafeForSetext) {
|
|
175
|
+
context.sink({
|
|
176
|
+
code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.HEADING_LINE_BREAK_UNSAFE_FOR_SETEXT,
|
|
177
|
+
severity: "info",
|
|
178
|
+
message: unsafeSetextDiagnosticMessage(level, unsafeSetextReason, embedsLineBreak)
|
|
179
|
+
});
|
|
180
|
+
if (embedsLineBreak) return `${"#".repeat(level)} ${text.replace(require_shared_line_ending.ESCAPED_HARD_BREAK_PATTERN, " ").split(require_shared_line_ending.LINE_ENDING_PATTERN).join(" ")}`;
|
|
181
|
+
return `${"#".repeat(level)} ${text}`;
|
|
182
|
+
}
|
|
183
|
+
if (embedsLineBreak) {
|
|
184
|
+
context.sink({
|
|
185
|
+
code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.HEADING_LINE_BREAK_COLLAPSED,
|
|
186
|
+
severity: "info",
|
|
187
|
+
message: `a level ${String(level)} heading's own content contains a line break; only setext's own level-1/2 grammar can hold one, so ATX collapses it to a single space`
|
|
188
|
+
});
|
|
189
|
+
return `${"#".repeat(level)} ${text.replace(require_shared_line_ending.ESCAPED_HARD_BREAK_PATTERN, " ").split(require_shared_line_ending.LINE_ENDING_PATTERN).join(" ")}`;
|
|
190
|
+
}
|
|
87
191
|
return `${"#".repeat(level)} ${text}`;
|
|
88
192
|
}
|
|
89
193
|
return require_emit_inline.emitRuns(paragraph.runs, context, paragraph.constructs);
|
|
@@ -242,7 +346,7 @@ function collectListItem(items, start, level, itemId) {
|
|
|
242
346
|
};
|
|
243
347
|
}
|
|
244
348
|
function emitItemCanInterrupt(item, context) {
|
|
245
|
-
if (!isConstructItem(item)) return item.block.kind === "paragraph" ? canInterruptOpenParagraph(item.block
|
|
349
|
+
if (!isConstructItem(item)) return item.block.kind === "paragraph" ? canInterruptOpenParagraph(item.block, context) : true;
|
|
246
350
|
if (isMaterialisedDivision(item)) return true;
|
|
247
351
|
const first = item.children[0];
|
|
248
352
|
return first === void 0 ? true : emitItemCanInterrupt(first, context);
|
package/dist/emit/emit.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { isValidFootnoteLabel } from "../inline/footnote.js";
|
|
2
2
|
import "../defaults/defaults.js";
|
|
3
3
|
import { MarkdownDiagnosticCodes, MarkdownInvalidRunConstructExtentError, MarkdownUnbalancedConstructMarkersError, MarkdownUnsupportedDocumentKindError, NOOP_MARKDOWN_DIAGNOSTIC_SINK } from "../diagnostics/diagnostics.js";
|
|
4
|
+
import { matchHtmlBlockStart } from "../html/html.js";
|
|
5
|
+
import { ESCAPED_HARD_BREAK_PATTERN, LINE_ENDING_PATTERN } from "../shared/line-ending.js";
|
|
6
|
+
import "../scan/scan.js";
|
|
7
|
+
import { LineCursor } from "../block/line.js";
|
|
8
|
+
import { parseListMarker } from "../block/list.js";
|
|
9
|
+
import { parseTableDelimiterRow, splitTableRow } from "../block/table.js";
|
|
10
|
+
import { ATX_MARKER_PATTERN, CODE_FENCE_PATTERN, MATH_BLOCK_MARKER_PATTERN, THEMATIC_BREAK_PATTERN } from "../block/block.js";
|
|
4
11
|
import { parseListNumId } from "../shared/list-id.js";
|
|
5
12
|
import { CODE_BLOCK_STYLE_ID, HORIZONTAL_RULE_STYLE_ID, HTML_PREFORMATTED_STYLE_ID, MATH_BLOCK_STYLE_ID, QUOTE_STYLE_ID, parseHeadingStyleId } from "../shared/style-constants.js";
|
|
6
13
|
import { emitFrontMatter } from "./front-matter.js";
|
|
@@ -18,7 +25,7 @@ const SETEXT_LEVEL_2_CHAR = "-";
|
|
|
18
25
|
const MIN_SETEXT_UNDERLINE_LENGTH = 1;
|
|
19
26
|
function renderSetextHeading(level, text) {
|
|
20
27
|
const underlineChar = level === 1 ? SETEXT_LEVEL_1_CHAR : SETEXT_LEVEL_2_CHAR;
|
|
21
|
-
const firstLine = text.split(
|
|
28
|
+
const firstLine = text.split(LINE_ENDING_PATTERN)[0] ?? "";
|
|
22
29
|
return `${text}\n${underlineChar.repeat(Math.max(MIN_SETEXT_UNDERLINE_LENGTH, firstLine.length))}`;
|
|
23
30
|
}
|
|
24
31
|
const MIN_CODE_FENCE_LENGTH = 3;
|
|
@@ -49,12 +56,78 @@ function terminatesCleanly(styleId) {
|
|
|
49
56
|
if (styleId === void 0 || styleId === "Quote" || styleId === "HTMLPreformatted") return false;
|
|
50
57
|
return styleId === "CodeBlock" || styleId === "MathBlock" || styleId === "HorizontalRule" || parseHeadingStyleId(styleId) !== void 0;
|
|
51
58
|
}
|
|
52
|
-
|
|
59
|
+
const BLANK_OR_WHITESPACE_ONLY_LINE = /^[ \t]*$/;
|
|
60
|
+
function firstContentLineIndex(text) {
|
|
61
|
+
return text.split(LINE_ENDING_PATTERN).findIndex((line) => !BLANK_OR_WHITESPACE_ONLY_LINE.test(line));
|
|
62
|
+
}
|
|
63
|
+
function leadingIndentColumns(line) {
|
|
64
|
+
let column = 0;
|
|
65
|
+
for (const char of line) if (char === " ") column += 1;
|
|
66
|
+
else if (char === " ") column += 4 - column % 4;
|
|
67
|
+
else break;
|
|
68
|
+
return column;
|
|
69
|
+
}
|
|
70
|
+
const MAX_LEADING_BLANK_LINES_FOR_SETEXT = 1;
|
|
71
|
+
function interruptsSetextParagraph(line, atBlockStart) {
|
|
72
|
+
const cursor = new LineCursor(line);
|
|
73
|
+
if (cursor.indented) return false;
|
|
74
|
+
if (cursor.peekNextNonspace() === ">") return true;
|
|
75
|
+
const rest = cursor.restFromNextNonspace();
|
|
76
|
+
if (ATX_MARKER_PATTERN.test(rest) || CODE_FENCE_PATTERN.test(rest) || THEMATIC_BREAK_PATTERN.test(rest) || MATH_BLOCK_MARKER_PATTERN.test(rest) || matchHtmlBlockStart(rest, !atBlockStart) !== void 0) return true;
|
|
77
|
+
return parseListMarker(cursor, !atBlockStart) !== void 0;
|
|
78
|
+
}
|
|
79
|
+
function tableDelimiterRowPromotesPrecedingLine(line, precedingLine) {
|
|
80
|
+
const cursor = new LineCursor(line);
|
|
81
|
+
if (cursor.indented) return false;
|
|
82
|
+
return parseTableDelimiterRow(cursor.restFromNextNonspace())?.length === splitTableRow(precedingLine).length;
|
|
83
|
+
}
|
|
84
|
+
function unsafeSetextBreakReason(text) {
|
|
85
|
+
let sawContentLine = false;
|
|
86
|
+
let leadingBlankLines = 0;
|
|
87
|
+
let precedingLine = "";
|
|
88
|
+
for (const line of text.split(LINE_ENDING_PATTERN)) {
|
|
89
|
+
const isBlank = BLANK_OR_WHITESPACE_ONLY_LINE.test(line);
|
|
90
|
+
if (!sawContentLine) {
|
|
91
|
+
if (isBlank) {
|
|
92
|
+
leadingBlankLines += 1;
|
|
93
|
+
if (leadingBlankLines > MAX_LEADING_BLANK_LINES_FOR_SETEXT) return "blank-line";
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
sawContentLine = true;
|
|
97
|
+
if (leadingIndentColumns(line) >= 4) return "leading-indentation";
|
|
98
|
+
if (interruptsSetextParagraph(line, true)) return "interrupting-line";
|
|
99
|
+
precedingLine = line;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (isBlank) return "blank-line";
|
|
103
|
+
if (interruptsSetextParagraph(line, false) || tableDelimiterRowPromotesPrecedingLine(line, precedingLine)) return "interrupting-line";
|
|
104
|
+
precedingLine = line;
|
|
105
|
+
}
|
|
106
|
+
return sawContentLine ? void 0 : "blank-line";
|
|
107
|
+
}
|
|
108
|
+
function embedsUnsafeBreakForSetext(text) {
|
|
109
|
+
return unsafeSetextBreakReason(text) !== void 0;
|
|
110
|
+
}
|
|
111
|
+
function unsafeSetextDiagnosticMessage(level, reason, embedsLineBreak) {
|
|
112
|
+
const hazard = reason === "leading-indentation" ? `the line that would become the setext heading's own first line of text opens with 4 or more columns of space/tab indentation -- setext's own grammar (spec 0.31.2) requires the first line to have "not more than 3 spaces of indentation", so promoting would read that line back as an indented code block instead of heading text` : reason === "interrupting-line" ? `a line of the heading's own text -- including possibly its first -- would itself be interpretable as a code fence, ATX heading, block quote, thematic break, list item, HTML block, math block, or GFM table delimiter row -- setext's own grammar (spec 0.31.2) requires every one of the heading's lines to instead read as ordinary paragraph text, so promoting would read that line back as the start of a fresh, unrelated block (or, for a table delimiter row, a conversion of the line before it) rather than more of the heading` : `promoting would leave the setext underline with no heading text of its own to attach to -- either a blank line immediately before it (a trailing break), a blank line in the middle of the heading's own text (a genuinely interior break), or the heading's own rendered text being entirely blank to begin with -- setext's own grammar requires "one or more lines of text, not interrupted by a blank line"`;
|
|
113
|
+
return embedsLineBreak ? `a level ${String(level)} heading's own content contains a line break, but ${hazard}; ATX collapses the break to a single space instead of promoting into a corrupt reparse` : `the effective WriteMarkdownOptions.headingStyle is 'setext' (an explicit caller choice -- a break-free heading only reaches this path when requested outright), but ${hazard}; rendered as ATX instead of promoting into a corrupt reparse`;
|
|
114
|
+
}
|
|
115
|
+
function willRenderAsSetext(paragraph, level, context) {
|
|
116
|
+
if (level > MAX_SETEXT_LEVEL) return false;
|
|
117
|
+
const text = emitRuns(paragraph.runs, {
|
|
118
|
+
sink: NOOP_MARKDOWN_DIAGNOSTIC_SINK,
|
|
119
|
+
emphasisMarker: context.emphasisMarker
|
|
120
|
+
}, paragraph.constructs);
|
|
121
|
+
if (embedsUnsafeBreakForSetext(text)) return false;
|
|
122
|
+
return context.headingStyle === "setext" || LINE_ENDING_PATTERN.test(text);
|
|
123
|
+
}
|
|
124
|
+
function canInterruptOpenParagraph(paragraph, context) {
|
|
125
|
+
const styleId = paragraph.styleId;
|
|
53
126
|
if (styleId === void 0 || styleId === "Quote" || styleId === "HTMLPreformatted") return false;
|
|
54
127
|
if (styleId === "CodeBlock" || styleId === "MathBlock") return true;
|
|
55
128
|
if (styleId === "HorizontalRule") return context.thematicBreakChar !== SETEXT_LEVEL_2_CHAR;
|
|
56
129
|
const headingLevel = parseHeadingStyleId(styleId);
|
|
57
|
-
if (headingLevel !== void 0) return !(
|
|
130
|
+
if (headingLevel !== void 0) return !willRenderAsSetext(paragraph, clampHeadingLevel(headingLevel), context);
|
|
58
131
|
return false;
|
|
59
132
|
}
|
|
60
133
|
function quoteDepthOf(paragraph) {
|
|
@@ -82,7 +155,38 @@ function renderParagraphBody(paragraph, context) {
|
|
|
82
155
|
message: `heading level ${String(headingLevel)} exceeds ATX's own six-"#" ceiling and is clamped to ${String(level)}`
|
|
83
156
|
});
|
|
84
157
|
const text = emitRuns(paragraph.runs, context, paragraph.constructs);
|
|
85
|
-
|
|
158
|
+
const embedsLineBreak = LINE_ENDING_PATTERN.test(text);
|
|
159
|
+
const unsafeSetextReason = unsafeSetextBreakReason(text);
|
|
160
|
+
const unsafeForSetext = unsafeSetextReason !== void 0;
|
|
161
|
+
const setextRequested = context.headingStyle === "setext" || embedsLineBreak;
|
|
162
|
+
if (setextRequested && level <= MAX_SETEXT_LEVEL && !unsafeForSetext) {
|
|
163
|
+
if (context.headingStyle !== "setext") {
|
|
164
|
+
const leadingBreakAbsorbed = firstContentLineIndex(text) > 0;
|
|
165
|
+
context.sink({
|
|
166
|
+
code: MarkdownDiagnosticCodes.HEADING_STYLE_OVERRIDDEN_FOR_LINE_BREAK,
|
|
167
|
+
severity: "info",
|
|
168
|
+
message: leadingBreakAbsorbed ? `the effective WriteMarkdownOptions.headingStyle is 'atx' (its own default, or an explicit caller choice), but this level ${String(level)} heading's own content contains a line break ATX has no way to hold -- rendered as setext instead, though the heading's own leading blank line is absorbed as ordinary space ahead of it on read-back rather than reproduced inside it` : `the effective WriteMarkdownOptions.headingStyle is 'atx' (its own default, or an explicit caller choice), but this level ${String(level)} heading's own content contains a line break ATX has no way to hold -- rendered as setext instead so the break survives`
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
return renderSetextHeading(level, text);
|
|
172
|
+
}
|
|
173
|
+
if (setextRequested && level <= MAX_SETEXT_LEVEL && unsafeForSetext) {
|
|
174
|
+
context.sink({
|
|
175
|
+
code: MarkdownDiagnosticCodes.HEADING_LINE_BREAK_UNSAFE_FOR_SETEXT,
|
|
176
|
+
severity: "info",
|
|
177
|
+
message: unsafeSetextDiagnosticMessage(level, unsafeSetextReason, embedsLineBreak)
|
|
178
|
+
});
|
|
179
|
+
if (embedsLineBreak) return `${"#".repeat(level)} ${text.replace(ESCAPED_HARD_BREAK_PATTERN, " ").split(LINE_ENDING_PATTERN).join(" ")}`;
|
|
180
|
+
return `${"#".repeat(level)} ${text}`;
|
|
181
|
+
}
|
|
182
|
+
if (embedsLineBreak) {
|
|
183
|
+
context.sink({
|
|
184
|
+
code: MarkdownDiagnosticCodes.HEADING_LINE_BREAK_COLLAPSED,
|
|
185
|
+
severity: "info",
|
|
186
|
+
message: `a level ${String(level)} heading's own content contains a line break; only setext's own level-1/2 grammar can hold one, so ATX collapses it to a single space`
|
|
187
|
+
});
|
|
188
|
+
return `${"#".repeat(level)} ${text.replace(ESCAPED_HARD_BREAK_PATTERN, " ").split(LINE_ENDING_PATTERN).join(" ")}`;
|
|
189
|
+
}
|
|
86
190
|
return `${"#".repeat(level)} ${text}`;
|
|
87
191
|
}
|
|
88
192
|
return emitRuns(paragraph.runs, context, paragraph.constructs);
|
|
@@ -241,7 +345,7 @@ function collectListItem(items, start, level, itemId) {
|
|
|
241
345
|
};
|
|
242
346
|
}
|
|
243
347
|
function emitItemCanInterrupt(item, context) {
|
|
244
|
-
if (!isConstructItem(item)) return item.block.kind === "paragraph" ? canInterruptOpenParagraph(item.block
|
|
348
|
+
if (!isConstructItem(item)) return item.block.kind === "paragraph" ? canInterruptOpenParagraph(item.block, context) : true;
|
|
245
349
|
if (isMaterialisedDivision(item)) return true;
|
|
246
350
|
const first = item.children[0];
|
|
247
351
|
return first === void 0 ? true : emitItemCanInterrupt(first, context);
|
package/dist/emit/inline.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_inline_footnote = require("../inline/footnote.cjs");
|
|
3
3
|
const require_diagnostics_diagnostics = require("../diagnostics/diagnostics.cjs");
|
|
4
|
+
const require_shared_line_ending = require("../shared/line-ending.cjs");
|
|
4
5
|
require("../shared/style-constants.cjs");
|
|
5
6
|
//#region src/emit/inline.ts
|
|
6
7
|
const ESCAPE_CHARS = /* @__PURE__ */ new Set([
|
|
@@ -40,9 +41,9 @@ function escapeMarkdownText(text) {
|
|
|
40
41
|
let index = 0;
|
|
41
42
|
while (index < text.length) {
|
|
42
43
|
const char = text.charAt(index);
|
|
43
|
-
if (char === "\n") {
|
|
44
|
+
if (char === "\n" || char === "\r") {
|
|
44
45
|
out += "\\\n";
|
|
45
|
-
index += 1;
|
|
46
|
+
index += char === "\r" && text.charAt(index + 1) === "\n" ? 2 : 1;
|
|
46
47
|
continue;
|
|
47
48
|
}
|
|
48
49
|
if (ESCAPE_CHARS.has(char)) {
|
|
@@ -191,7 +192,7 @@ function emitRuns(runs, context, constructs) {
|
|
|
191
192
|
return out;
|
|
192
193
|
}
|
|
193
194
|
function emitRunsSingleLine(runs, context, constructs) {
|
|
194
|
-
return emitRuns(runs, context, constructs).replace(
|
|
195
|
+
return emitRuns(runs, context, constructs).replace(require_shared_line_ending.ESCAPED_HARD_BREAK_PATTERN, " ").split(require_shared_line_ending.LINE_ENDING_PATTERN).join(" ");
|
|
195
196
|
}
|
|
196
197
|
//#endregion
|
|
197
198
|
exports.emitRuns = emitRuns;
|
package/dist/emit/inline.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
1
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.cjs";
|
|
2
2
|
import { ContentRun, RunConstructExtent } from "document-schema.js";
|
|
3
3
|
//#region src/emit/inline.d.ts
|
|
4
4
|
interface InlineEmitContext {
|
package/dist/emit/inline.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
1
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.js";
|
|
2
2
|
import { ContentRun, RunConstructExtent } from "document-schema.js";
|
|
3
3
|
//#region src/emit/inline.d.ts
|
|
4
4
|
interface InlineEmitContext {
|
package/dist/emit/inline.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isValidFootnoteLabel } from "../inline/footnote.js";
|
|
2
2
|
import { MarkdownDiagnosticCodes } from "../diagnostics/diagnostics.js";
|
|
3
|
+
import { ESCAPED_HARD_BREAK_PATTERN, LINE_ENDING_PATTERN } from "../shared/line-ending.js";
|
|
3
4
|
import "../shared/style-constants.js";
|
|
4
5
|
//#region src/emit/inline.ts
|
|
5
6
|
const ESCAPE_CHARS = /* @__PURE__ */ new Set([
|
|
@@ -39,9 +40,9 @@ function escapeMarkdownText(text) {
|
|
|
39
40
|
let index = 0;
|
|
40
41
|
while (index < text.length) {
|
|
41
42
|
const char = text.charAt(index);
|
|
42
|
-
if (char === "\n") {
|
|
43
|
+
if (char === "\n" || char === "\r") {
|
|
43
44
|
out += "\\\n";
|
|
44
|
-
index += 1;
|
|
45
|
+
index += char === "\r" && text.charAt(index + 1) === "\n" ? 2 : 1;
|
|
45
46
|
continue;
|
|
46
47
|
}
|
|
47
48
|
if (ESCAPE_CHARS.has(char)) {
|
|
@@ -190,7 +191,7 @@ function emitRuns(runs, context, constructs) {
|
|
|
190
191
|
return out;
|
|
191
192
|
}
|
|
192
193
|
function emitRunsSingleLine(runs, context, constructs) {
|
|
193
|
-
return emitRuns(runs, context, constructs).replace(
|
|
194
|
+
return emitRuns(runs, context, constructs).replace(ESCAPED_HARD_BREAK_PATTERN, " ").split(LINE_ENDING_PATTERN).join(" ");
|
|
194
195
|
}
|
|
195
196
|
//#endregion
|
|
196
197
|
export { emitRuns, emitRunsSingleLine, escapeLinkDestination, escapeMarkdownText, renderLinkTitle };
|
package/dist/emit/table.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
1
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.cjs";
|
|
2
2
|
import { InlineEmitContext } from "./inline.cjs";
|
|
3
3
|
import { ContentTable } from "document-schema.js";
|
|
4
4
|
//#region src/emit/table.d.ts
|
package/dist/emit/table.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
1
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.js";
|
|
2
2
|
import { InlineEmitContext } from "./inline.js";
|
|
3
3
|
import { ContentTable } from "document-schema.js";
|
|
4
4
|
//#region src/emit/table.d.ts
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as MarkdownInputTooLargeError, c as MarkdownNestingLimitExceededError, d as MarkdownUnbalancedConstructMarkersError, f as MarkdownUnsupportedDocumentKindError, i as MarkdownDiagnosticSink, m as NOOP_MARKDOWN_DIAGNOSTIC_SINK, n as MarkdownDiagnosticCodes, o as MarkdownInvalidRunConstructExtentError, p as MarkdownWriteError, r as MarkdownDiagnosticSeverity, s as MarkdownInvalidUtf8Error, t as MarkdownDiagnostic, u as MarkdownParseError } from "./diagnostics-
|
|
1
|
+
import { a as MarkdownInputTooLargeError, c as MarkdownNestingLimitExceededError, d as MarkdownUnbalancedConstructMarkersError, f as MarkdownUnsupportedDocumentKindError, i as MarkdownDiagnosticSink, m as NOOP_MARKDOWN_DIAGNOSTIC_SINK, n as MarkdownDiagnosticCodes, o as MarkdownInvalidRunConstructExtentError, p as MarkdownWriteError, r as MarkdownDiagnosticSeverity, s as MarkdownInvalidUtf8Error, t as MarkdownDiagnostic, u as MarkdownParseError } from "./diagnostics-CnamCy6I.cjs";
|
|
2
2
|
import { MarkdownBytesSchema, markdownCodec, markdownContentCodec } from "./codec.cjs";
|
|
3
3
|
import { n as MarkdownImageResolver, r as MarkdownResolvedImageBytes, t as MarkdownImageResolveContext } from "./image-B5L0HpAJ.cjs";
|
|
4
4
|
import { MarkdownBulletListMarker, MarkdownCodeFenceChar, MarkdownEmphasisMarker, MarkdownHeadingStyle, MarkdownLineEnding, MarkdownOrderedListDelimiter, MarkdownThematicBreakChar, ReadMarkdownOptions, WriteMarkdownOptions, WriteMarkdownStyleOptions } from "./options/options.cjs";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as MarkdownInputTooLargeError, c as MarkdownNestingLimitExceededError, d as MarkdownUnbalancedConstructMarkersError, f as MarkdownUnsupportedDocumentKindError, i as MarkdownDiagnosticSink, m as NOOP_MARKDOWN_DIAGNOSTIC_SINK, n as MarkdownDiagnosticCodes, o as MarkdownInvalidRunConstructExtentError, p as MarkdownWriteError, r as MarkdownDiagnosticSeverity, s as MarkdownInvalidUtf8Error, t as MarkdownDiagnostic, u as MarkdownParseError } from "./diagnostics-
|
|
1
|
+
import { a as MarkdownInputTooLargeError, c as MarkdownNestingLimitExceededError, d as MarkdownUnbalancedConstructMarkersError, f as MarkdownUnsupportedDocumentKindError, i as MarkdownDiagnosticSink, m as NOOP_MARKDOWN_DIAGNOSTIC_SINK, n as MarkdownDiagnosticCodes, o as MarkdownInvalidRunConstructExtentError, p as MarkdownWriteError, r as MarkdownDiagnosticSeverity, s as MarkdownInvalidUtf8Error, t as MarkdownDiagnostic, u as MarkdownParseError } from "./diagnostics-CnamCy6I.js";
|
|
2
2
|
import { MarkdownBytesSchema, markdownCodec, markdownContentCodec } from "./codec.js";
|
|
3
3
|
import { n as MarkdownImageResolver, r as MarkdownResolvedImageBytes, t as MarkdownImageResolveContext } from "./image-C390OIB3.js";
|
|
4
4
|
import { MarkdownBulletListMarker, MarkdownCodeFenceChar, MarkdownEmphasisMarker, MarkdownHeadingStyle, MarkdownLineEnding, MarkdownOrderedListDelimiter, MarkdownThematicBreakChar, ReadMarkdownOptions, WriteMarkdownOptions, WriteMarkdownStyleOptions } from "./options/options.js";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_diagnostics_diagnostics = require("../diagnostics/diagnostics.cjs");
|
|
3
|
+
const require_shared_line_ending = require("../shared/line-ending.cjs");
|
|
3
4
|
//#region src/lower/front-matter.ts
|
|
4
5
|
const LEADING_DELIMITER_PATTERN = /^---[ \t]*$/;
|
|
5
6
|
const CLOSING_DELIMITER_PATTERN = /^(?:---|\.\.\.)[ \t]*$/;
|
|
6
7
|
const KEY_VALUE_LINE_PATTERN = /^([A-Za-z_][A-Za-z0-9_-]*):[ \t]*(.*)$/;
|
|
7
|
-
const LINE_ENDING_PATTERN = /\r\n|\n|\r/;
|
|
8
8
|
function parseScalar(raw) {
|
|
9
9
|
const trimmed = raw.trim();
|
|
10
10
|
const isDoubleQuoted = trimmed.length >= 2 && trimmed.startsWith("\"") && trimmed.endsWith("\"");
|
|
@@ -16,7 +16,7 @@ function parseKeywordList(raw) {
|
|
|
16
16
|
return (trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.slice(1, -1) : trimmed).split(",").map((item) => parseScalar(item)).filter((item) => item.length > 0);
|
|
17
17
|
}
|
|
18
18
|
function extractFrontMatter(source, sink = require_diagnostics_diagnostics.NOOP_MARKDOWN_DIAGNOSTIC_SINK) {
|
|
19
|
-
const lines = source.split(LINE_ENDING_PATTERN);
|
|
19
|
+
const lines = source.split(require_shared_line_ending.LINE_ENDING_PATTERN);
|
|
20
20
|
const firstLine = lines[0];
|
|
21
21
|
if (firstLine === void 0 || !LEADING_DELIMITER_PATTERN.test(firstLine)) return {
|
|
22
22
|
metadata: {},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
1
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.cjs";
|
|
2
2
|
import { LayoutMetadata } from "document-schema.js";
|
|
3
3
|
//#region src/lower/front-matter.d.ts
|
|
4
4
|
interface FrontMatterResult {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
1
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.js";
|
|
2
2
|
import { LayoutMetadata } from "document-schema.js";
|
|
3
3
|
//#region src/lower/front-matter.d.ts
|
|
4
4
|
interface FrontMatterResult {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { MarkdownDiagnosticCodes, NOOP_MARKDOWN_DIAGNOSTIC_SINK } from "../diagnostics/diagnostics.js";
|
|
2
|
+
import { LINE_ENDING_PATTERN } from "../shared/line-ending.js";
|
|
2
3
|
//#region src/lower/front-matter.ts
|
|
3
4
|
const LEADING_DELIMITER_PATTERN = /^---[ \t]*$/;
|
|
4
5
|
const CLOSING_DELIMITER_PATTERN = /^(?:---|\.\.\.)[ \t]*$/;
|
|
5
6
|
const KEY_VALUE_LINE_PATTERN = /^([A-Za-z_][A-Za-z0-9_-]*):[ \t]*(.*)$/;
|
|
6
|
-
const LINE_ENDING_PATTERN = /\r\n|\n|\r/;
|
|
7
7
|
function parseScalar(raw) {
|
|
8
8
|
const trimmed = raw.trim();
|
|
9
9
|
const isDoubleQuoted = trimmed.length >= 2 && trimmed.startsWith("\"") && trimmed.endsWith("\"");
|
package/dist/lower/inline.cjs
CHANGED
|
@@ -33,7 +33,13 @@ function lowerInlineNodeInto(node, style, context, runs, extents) {
|
|
|
33
33
|
if (node.value.length > 0) runs.push(buildRun(node.value, style));
|
|
34
34
|
return;
|
|
35
35
|
case "softBreak":
|
|
36
|
-
runs.push(
|
|
36
|
+
runs.push({
|
|
37
|
+
...buildRun(" ", style),
|
|
38
|
+
source: {
|
|
39
|
+
format: "markdown",
|
|
40
|
+
xml: "\n"
|
|
41
|
+
}
|
|
42
|
+
});
|
|
37
43
|
return;
|
|
38
44
|
case "hardBreak":
|
|
39
45
|
runs.push(buildRun("\n", style));
|
package/dist/lower/inline.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { v as MarkdownInlineNode } from "../ast-CNfTgS0N.cjs";
|
|
2
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
2
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.cjs";
|
|
3
3
|
import { ContentRun, RunConstructExtent } from "document-schema.js";
|
|
4
4
|
//#region src/lower/inline.d.ts
|
|
5
5
|
interface InlineLowerContext {
|
package/dist/lower/inline.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { v as MarkdownInlineNode } from "../ast-CNfTgS0N.js";
|
|
2
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
2
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.js";
|
|
3
3
|
import { ContentRun, RunConstructExtent } from "document-schema.js";
|
|
4
4
|
//#region src/lower/inline.d.ts
|
|
5
5
|
interface InlineLowerContext {
|
package/dist/lower/inline.js
CHANGED
|
@@ -32,7 +32,13 @@ function lowerInlineNodeInto(node, style, context, runs, extents) {
|
|
|
32
32
|
if (node.value.length > 0) runs.push(buildRun(node.value, style));
|
|
33
33
|
return;
|
|
34
34
|
case "softBreak":
|
|
35
|
-
runs.push(
|
|
35
|
+
runs.push({
|
|
36
|
+
...buildRun(" ", style),
|
|
37
|
+
source: {
|
|
38
|
+
format: "markdown",
|
|
39
|
+
xml: "\n"
|
|
40
|
+
}
|
|
41
|
+
});
|
|
36
42
|
return;
|
|
37
43
|
case "hardBreak":
|
|
38
44
|
runs.push(buildRun("\n", style));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as MarkdownDiagnosticSink } from "../diagnostics-
|
|
1
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.cjs";
|
|
2
2
|
import { n as MarkdownImageResolver } from "../image-B5L0HpAJ.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-
|
|
1
|
+
import { i as MarkdownDiagnosticSink } from "../diagnostics-CnamCy6I.js";
|
|
2
2
|
import { n as MarkdownImageResolver } from "../image-C390OIB3.js";
|
|
3
3
|
import { Margins, PageSize } from "document-schema.js";
|
|
4
4
|
//#region src/options/options.d.ts
|
package/dist/read.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as MarkdownDiagnostic } from "./diagnostics-
|
|
1
|
+
import { t as MarkdownDiagnostic } from "./diagnostics-CnamCy6I.cjs";
|
|
2
2
|
import { ReadMarkdownOptions } from "./options/options.cjs";
|
|
3
3
|
import { ContentDocument, DocumentTree } 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-
|
|
1
|
+
import { t as MarkdownDiagnostic } from "./diagnostics-CnamCy6I.js";
|
|
2
2
|
import { ReadMarkdownOptions } from "./options/options.js";
|
|
3
3
|
import { ContentDocument, DocumentTree } from "document-schema.js";
|
|
4
4
|
//#region src/read.d.ts
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/shared/line-ending.ts
|
|
3
|
+
const LINE_ENDING_PATTERN = /\r\n|\n|\r/;
|
|
4
|
+
const ESCAPED_HARD_BREAK_PATTERN = new RegExp(`\\\\(?:${LINE_ENDING_PATTERN.source})`, "g");
|
|
5
|
+
//#endregion
|
|
6
|
+
exports.ESCAPED_HARD_BREAK_PATTERN = ESCAPED_HARD_BREAK_PATTERN;
|
|
7
|
+
exports.LINE_ENDING_PATTERN = LINE_ENDING_PATTERN;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markdown-codec",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"description": "Hand-written CommonMark+GFM <-> DocumentTree codec, built on document-schema.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -62,6 +62,8 @@
|
|
|
62
62
|
"test:watch": "vitest --project unit",
|
|
63
63
|
"test:coverage": "turbo run _test:coverage",
|
|
64
64
|
"_test:coverage": "vitest run --project unit --coverage",
|
|
65
|
+
"test:mutation": "turbo run _test:mutation",
|
|
66
|
+
"_test:mutation": "stryker run stryker.config.mjs",
|
|
65
67
|
"test:corpus": "turbo run _test:corpus",
|
|
66
68
|
"_test:corpus": "vitest run --project corpus",
|
|
67
69
|
"test:smoke": "turbo run _test:smoke",
|
|
@@ -81,16 +83,20 @@
|
|
|
81
83
|
"license": "MIT",
|
|
82
84
|
"packageManager": "pnpm@11.6.0",
|
|
83
85
|
"dependencies": {
|
|
84
|
-
"document-schema.js": "^6.
|
|
86
|
+
"document-schema.js": "^6.2.0",
|
|
85
87
|
"zod": "^4.4.3"
|
|
86
88
|
},
|
|
87
89
|
"devDependencies": {
|
|
88
90
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
89
91
|
"@cloudflare/vitest-pool-workers": "^0.21.2",
|
|
92
|
+
"@stryker-mutator/core": "^10.0.0",
|
|
93
|
+
"@stryker-mutator/typescript-checker": "^10.0.0",
|
|
94
|
+
"@stryker-mutator/vitest-runner": "^10.0.0",
|
|
90
95
|
"@types/node": "^26.1.1",
|
|
91
96
|
"@vitest/coverage-v8": "^4.1.10",
|
|
92
97
|
"eslint": "^10.8.0",
|
|
93
98
|
"husky": "^9.1.7",
|
|
99
|
+
"jiti": "2.7.0",
|
|
94
100
|
"publint": "^0.3.21",
|
|
95
101
|
"semantic-release": "^25.0.8",
|
|
96
102
|
"tsdown": "^0.22.13",
|