markdown-codec 6.1.6 → 6.2.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 +2 -2
- package/dist/codec.d.cts +78 -9
- package/dist/codec.d.ts +78 -9
- package/dist/emit/emit.cjs +176 -33
- package/dist/emit/emit.js +176 -33
- package/dist/lower/lower.cjs +2 -1
- package/dist/lower/lower.js +2 -1
- package/dist/shared/list-id.cjs +5 -3
- package/dist/shared/list-id.d.cts +2 -0
- package/dist/shared/list-id.d.ts +2 -0
- package/dist/shared/list-id.js +5 -3
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -228,9 +228,9 @@ Emission is the inverse and validates first: a section's markers must pair as ba
|
|
|
228
228
|
|
|
229
229
|
| Corpus | Examples | Passing round trip | Rate |
|
|
230
230
|
| ------------------------------------------------------------------------------------- | -------- | ------------------ | ----- |
|
|
231
|
-
| CommonMark 0.31.2 (`assets/commonmark/spec.json`) | 652 |
|
|
231
|
+
| CommonMark 0.31.2 (`assets/commonmark/spec.json`) | 652 | 516 | 79.1% |
|
|
232
232
|
| GFM tagged extensions (table/strikethrough/autolink/task-list, `assets/gfm/spec.txt`) | 23 | 22 | 95.7% |
|
|
233
|
-
| Combined | 675 |
|
|
233
|
+
| Combined | 675 | 538 | 79.7% |
|
|
234
234
|
|
|
235
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 a soft line break collapsing to a space, a nested/unresolved image title, an emphasis-span collision, or a blockquote whose heading content skips its container pair.
|
|
236
236
|
|
package/dist/codec.d.cts
CHANGED
|
@@ -595,7 +595,7 @@ declare const markdownCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uin
|
|
|
595
595
|
kind: z.ZodLiteral<"drawing">;
|
|
596
596
|
}, z.core.$strip>, z.ZodObject<{
|
|
597
597
|
children: z.ZodArray<z.ZodObject<{
|
|
598
|
-
mathml: z.ZodArray<z.
|
|
598
|
+
mathml: z.ZodArray<z.ZodType<import("document-schema.js").MathMlNode, import("document-schema.js").MathMlNode, z.core.$ZodTypeInternals<import("document-schema.js").MathMlNode, import("document-schema.js").MathMlNode>>>;
|
|
599
599
|
starMath: z.ZodOptional<z.ZodString>;
|
|
600
600
|
presentation: z.ZodOptional<z.ZodObject<{
|
|
601
601
|
latex: z.ZodString;
|
|
@@ -1113,11 +1113,80 @@ declare const markdownContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffe
|
|
|
1113
1113
|
}, z.core.$strip>>>;
|
|
1114
1114
|
colSpan: z.ZodOptional<z.ZodNumber>;
|
|
1115
1115
|
rowSpan: z.ZodOptional<z.ZodNumber>;
|
|
1116
|
-
background: z.ZodOptional<z.ZodObject<{
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1116
|
+
background: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1117
|
+
kind: z.ZodLiteral<"solid">;
|
|
1118
|
+
color: z.ZodObject<{
|
|
1119
|
+
r: z.ZodNumber;
|
|
1120
|
+
g: z.ZodNumber;
|
|
1121
|
+
b: z.ZodNumber;
|
|
1122
|
+
}, z.core.$strip>;
|
|
1123
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1124
|
+
kind: z.ZodLiteral<"pattern">;
|
|
1125
|
+
patternType: z.ZodEnum<{
|
|
1126
|
+
percent5: "percent5";
|
|
1127
|
+
percent10: "percent10";
|
|
1128
|
+
percent12: "percent12";
|
|
1129
|
+
percent15: "percent15";
|
|
1130
|
+
percent20: "percent20";
|
|
1131
|
+
percent25: "percent25";
|
|
1132
|
+
percent30: "percent30";
|
|
1133
|
+
percent35: "percent35";
|
|
1134
|
+
percent37: "percent37";
|
|
1135
|
+
percent40: "percent40";
|
|
1136
|
+
percent45: "percent45";
|
|
1137
|
+
percent50: "percent50";
|
|
1138
|
+
percent55: "percent55";
|
|
1139
|
+
percent60: "percent60";
|
|
1140
|
+
percent62: "percent62";
|
|
1141
|
+
percent65: "percent65";
|
|
1142
|
+
percent70: "percent70";
|
|
1143
|
+
percent75: "percent75";
|
|
1144
|
+
percent80: "percent80";
|
|
1145
|
+
percent85: "percent85";
|
|
1146
|
+
percent87: "percent87";
|
|
1147
|
+
percent90: "percent90";
|
|
1148
|
+
percent95: "percent95";
|
|
1149
|
+
horizontalStripe: "horizontalStripe";
|
|
1150
|
+
verticalStripe: "verticalStripe";
|
|
1151
|
+
diagonalStripe: "diagonalStripe";
|
|
1152
|
+
reverseDiagonalStripe: "reverseDiagonalStripe";
|
|
1153
|
+
horizontalCross: "horizontalCross";
|
|
1154
|
+
diagonalCross: "diagonalCross";
|
|
1155
|
+
thinHorizontalStripe: "thinHorizontalStripe";
|
|
1156
|
+
thinVerticalStripe: "thinVerticalStripe";
|
|
1157
|
+
thinDiagonalStripe: "thinDiagonalStripe";
|
|
1158
|
+
thinReverseDiagonalStripe: "thinReverseDiagonalStripe";
|
|
1159
|
+
thinHorizontalCross: "thinHorizontalCross";
|
|
1160
|
+
thinDiagonalCross: "thinDiagonalCross";
|
|
1161
|
+
mediumGray: "mediumGray";
|
|
1162
|
+
darkGray: "darkGray";
|
|
1163
|
+
lightGray: "lightGray";
|
|
1164
|
+
darkHorizontal: "darkHorizontal";
|
|
1165
|
+
darkVertical: "darkVertical";
|
|
1166
|
+
darkDown: "darkDown";
|
|
1167
|
+
darkUp: "darkUp";
|
|
1168
|
+
darkGrid: "darkGrid";
|
|
1169
|
+
darkTrellis: "darkTrellis";
|
|
1170
|
+
lightHorizontal: "lightHorizontal";
|
|
1171
|
+
lightVertical: "lightVertical";
|
|
1172
|
+
lightDown: "lightDown";
|
|
1173
|
+
lightUp: "lightUp";
|
|
1174
|
+
lightGrid: "lightGrid";
|
|
1175
|
+
lightTrellis: "lightTrellis";
|
|
1176
|
+
gray125: "gray125";
|
|
1177
|
+
gray0625: "gray0625";
|
|
1178
|
+
}>;
|
|
1179
|
+
foregroundColor: z.ZodOptional<z.ZodObject<{
|
|
1180
|
+
r: z.ZodNumber;
|
|
1181
|
+
g: z.ZodNumber;
|
|
1182
|
+
b: z.ZodNumber;
|
|
1183
|
+
}, z.core.$strip>>;
|
|
1184
|
+
backgroundColor: z.ZodOptional<z.ZodObject<{
|
|
1185
|
+
r: z.ZodNumber;
|
|
1186
|
+
g: z.ZodNumber;
|
|
1187
|
+
b: z.ZodNumber;
|
|
1188
|
+
}, z.core.$strip>>;
|
|
1189
|
+
}, z.core.$strip>], "kind">>;
|
|
1121
1190
|
borders: z.ZodOptional<z.ZodObject<{
|
|
1122
1191
|
left: z.ZodOptional<z.ZodObject<{
|
|
1123
1192
|
color: z.ZodObject<{
|
|
@@ -1356,10 +1425,10 @@ declare const markdownContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffe
|
|
|
1356
1425
|
endColumn: z.ZodNumber;
|
|
1357
1426
|
}, z.core.$strip>>;
|
|
1358
1427
|
type: z.ZodEnum<{
|
|
1359
|
-
decimal: "decimal";
|
|
1360
|
-
list: "list";
|
|
1361
1428
|
date: "date";
|
|
1362
1429
|
custom: "custom";
|
|
1430
|
+
decimal: "decimal";
|
|
1431
|
+
list: "list";
|
|
1363
1432
|
time: "time";
|
|
1364
1433
|
whole: "whole";
|
|
1365
1434
|
textLength: "textLength";
|
|
@@ -2439,7 +2508,7 @@ declare const markdownContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffe
|
|
|
2439
2508
|
}, z.core.$strip>;
|
|
2440
2509
|
}, z.core.$strip>, z.ZodObject<{
|
|
2441
2510
|
formula: z.ZodObject<{
|
|
2442
|
-
mathml: z.ZodArray<z.
|
|
2511
|
+
mathml: z.ZodArray<z.ZodType<import("document-schema.js").MathMlNode, import("document-schema.js").MathMlNode, z.core.$ZodTypeInternals<import("document-schema.js").MathMlNode, import("document-schema.js").MathMlNode>>>;
|
|
2443
2512
|
starMath: z.ZodOptional<z.ZodString>;
|
|
2444
2513
|
presentation: z.ZodOptional<z.ZodObject<{
|
|
2445
2514
|
latex: z.ZodString;
|
package/dist/codec.d.ts
CHANGED
|
@@ -595,7 +595,7 @@ declare const markdownCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uin
|
|
|
595
595
|
kind: z.ZodLiteral<"drawing">;
|
|
596
596
|
}, z.core.$strip>, z.ZodObject<{
|
|
597
597
|
children: z.ZodArray<z.ZodObject<{
|
|
598
|
-
mathml: z.ZodArray<z.
|
|
598
|
+
mathml: z.ZodArray<z.ZodType<import("document-schema.js").MathMlNode, import("document-schema.js").MathMlNode, z.core.$ZodTypeInternals<import("document-schema.js").MathMlNode, import("document-schema.js").MathMlNode>>>;
|
|
599
599
|
starMath: z.ZodOptional<z.ZodString>;
|
|
600
600
|
presentation: z.ZodOptional<z.ZodObject<{
|
|
601
601
|
latex: z.ZodString;
|
|
@@ -1113,11 +1113,80 @@ declare const markdownContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffe
|
|
|
1113
1113
|
}, z.core.$strip>>>;
|
|
1114
1114
|
colSpan: z.ZodOptional<z.ZodNumber>;
|
|
1115
1115
|
rowSpan: z.ZodOptional<z.ZodNumber>;
|
|
1116
|
-
background: z.ZodOptional<z.ZodObject<{
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1116
|
+
background: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1117
|
+
kind: z.ZodLiteral<"solid">;
|
|
1118
|
+
color: z.ZodObject<{
|
|
1119
|
+
r: z.ZodNumber;
|
|
1120
|
+
g: z.ZodNumber;
|
|
1121
|
+
b: z.ZodNumber;
|
|
1122
|
+
}, z.core.$strip>;
|
|
1123
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
1124
|
+
kind: z.ZodLiteral<"pattern">;
|
|
1125
|
+
patternType: z.ZodEnum<{
|
|
1126
|
+
percent5: "percent5";
|
|
1127
|
+
percent10: "percent10";
|
|
1128
|
+
percent12: "percent12";
|
|
1129
|
+
percent15: "percent15";
|
|
1130
|
+
percent20: "percent20";
|
|
1131
|
+
percent25: "percent25";
|
|
1132
|
+
percent30: "percent30";
|
|
1133
|
+
percent35: "percent35";
|
|
1134
|
+
percent37: "percent37";
|
|
1135
|
+
percent40: "percent40";
|
|
1136
|
+
percent45: "percent45";
|
|
1137
|
+
percent50: "percent50";
|
|
1138
|
+
percent55: "percent55";
|
|
1139
|
+
percent60: "percent60";
|
|
1140
|
+
percent62: "percent62";
|
|
1141
|
+
percent65: "percent65";
|
|
1142
|
+
percent70: "percent70";
|
|
1143
|
+
percent75: "percent75";
|
|
1144
|
+
percent80: "percent80";
|
|
1145
|
+
percent85: "percent85";
|
|
1146
|
+
percent87: "percent87";
|
|
1147
|
+
percent90: "percent90";
|
|
1148
|
+
percent95: "percent95";
|
|
1149
|
+
horizontalStripe: "horizontalStripe";
|
|
1150
|
+
verticalStripe: "verticalStripe";
|
|
1151
|
+
diagonalStripe: "diagonalStripe";
|
|
1152
|
+
reverseDiagonalStripe: "reverseDiagonalStripe";
|
|
1153
|
+
horizontalCross: "horizontalCross";
|
|
1154
|
+
diagonalCross: "diagonalCross";
|
|
1155
|
+
thinHorizontalStripe: "thinHorizontalStripe";
|
|
1156
|
+
thinVerticalStripe: "thinVerticalStripe";
|
|
1157
|
+
thinDiagonalStripe: "thinDiagonalStripe";
|
|
1158
|
+
thinReverseDiagonalStripe: "thinReverseDiagonalStripe";
|
|
1159
|
+
thinHorizontalCross: "thinHorizontalCross";
|
|
1160
|
+
thinDiagonalCross: "thinDiagonalCross";
|
|
1161
|
+
mediumGray: "mediumGray";
|
|
1162
|
+
darkGray: "darkGray";
|
|
1163
|
+
lightGray: "lightGray";
|
|
1164
|
+
darkHorizontal: "darkHorizontal";
|
|
1165
|
+
darkVertical: "darkVertical";
|
|
1166
|
+
darkDown: "darkDown";
|
|
1167
|
+
darkUp: "darkUp";
|
|
1168
|
+
darkGrid: "darkGrid";
|
|
1169
|
+
darkTrellis: "darkTrellis";
|
|
1170
|
+
lightHorizontal: "lightHorizontal";
|
|
1171
|
+
lightVertical: "lightVertical";
|
|
1172
|
+
lightDown: "lightDown";
|
|
1173
|
+
lightUp: "lightUp";
|
|
1174
|
+
lightGrid: "lightGrid";
|
|
1175
|
+
lightTrellis: "lightTrellis";
|
|
1176
|
+
gray125: "gray125";
|
|
1177
|
+
gray0625: "gray0625";
|
|
1178
|
+
}>;
|
|
1179
|
+
foregroundColor: z.ZodOptional<z.ZodObject<{
|
|
1180
|
+
r: z.ZodNumber;
|
|
1181
|
+
g: z.ZodNumber;
|
|
1182
|
+
b: z.ZodNumber;
|
|
1183
|
+
}, z.core.$strip>>;
|
|
1184
|
+
backgroundColor: z.ZodOptional<z.ZodObject<{
|
|
1185
|
+
r: z.ZodNumber;
|
|
1186
|
+
g: z.ZodNumber;
|
|
1187
|
+
b: z.ZodNumber;
|
|
1188
|
+
}, z.core.$strip>>;
|
|
1189
|
+
}, z.core.$strip>], "kind">>;
|
|
1121
1190
|
borders: z.ZodOptional<z.ZodObject<{
|
|
1122
1191
|
left: z.ZodOptional<z.ZodObject<{
|
|
1123
1192
|
color: z.ZodObject<{
|
|
@@ -1356,10 +1425,10 @@ declare const markdownContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffe
|
|
|
1356
1425
|
endColumn: z.ZodNumber;
|
|
1357
1426
|
}, z.core.$strip>>;
|
|
1358
1427
|
type: z.ZodEnum<{
|
|
1359
|
-
decimal: "decimal";
|
|
1360
|
-
list: "list";
|
|
1361
1428
|
date: "date";
|
|
1362
1429
|
custom: "custom";
|
|
1430
|
+
decimal: "decimal";
|
|
1431
|
+
list: "list";
|
|
1363
1432
|
time: "time";
|
|
1364
1433
|
whole: "whole";
|
|
1365
1434
|
textLength: "textLength";
|
|
@@ -2439,7 +2508,7 @@ declare const markdownContentCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffe
|
|
|
2439
2508
|
}, z.core.$strip>;
|
|
2440
2509
|
}, z.core.$strip>, z.ZodObject<{
|
|
2441
2510
|
formula: z.ZodObject<{
|
|
2442
|
-
mathml: z.ZodArray<z.
|
|
2511
|
+
mathml: z.ZodArray<z.ZodType<import("document-schema.js").MathMlNode, import("document-schema.js").MathMlNode, z.core.$ZodTypeInternals<import("document-schema.js").MathMlNode, import("document-schema.js").MathMlNode>>>;
|
|
2443
2512
|
starMath: z.ZodOptional<z.ZodString>;
|
|
2444
2513
|
presentation: z.ZodOptional<z.ZodObject<{
|
|
2445
2514
|
latex: z.ZodString;
|
package/dist/emit/emit.cjs
CHANGED
|
@@ -46,6 +46,18 @@ function isQuotableStyle(styleId) {
|
|
|
46
46
|
if (styleId === void 0) return false;
|
|
47
47
|
return QUOTABLE_STYLE_IDS.has(styleId) || require_shared_style_constants.parseHeadingStyleId(styleId) !== void 0;
|
|
48
48
|
}
|
|
49
|
+
function terminatesCleanly(styleId) {
|
|
50
|
+
if (styleId === void 0 || styleId === "Quote" || styleId === "HTMLPreformatted") return false;
|
|
51
|
+
return styleId === "CodeBlock" || styleId === "MathBlock" || styleId === "HorizontalRule" || require_shared_style_constants.parseHeadingStyleId(styleId) !== void 0;
|
|
52
|
+
}
|
|
53
|
+
function canInterruptOpenParagraph(styleId, context) {
|
|
54
|
+
if (styleId === void 0 || styleId === "Quote" || styleId === "HTMLPreformatted") return false;
|
|
55
|
+
if (styleId === "CodeBlock" || styleId === "MathBlock") return true;
|
|
56
|
+
if (styleId === "HorizontalRule") return context.thematicBreakChar !== SETEXT_LEVEL_2_CHAR;
|
|
57
|
+
const headingLevel = require_shared_style_constants.parseHeadingStyleId(styleId);
|
|
58
|
+
if (headingLevel !== void 0) return !(context.headingStyle === "setext" && headingLevel <= MAX_SETEXT_LEVEL);
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
49
61
|
function quoteDepthOf(paragraph) {
|
|
50
62
|
if (paragraph.indentLeftPt === void 0 || paragraph.indentLeftPt <= 0) return 0;
|
|
51
63
|
return Math.max(1, Math.round(paragraph.indentLeftPt / 36));
|
|
@@ -142,16 +154,19 @@ function stripCheckboxRun(item) {
|
|
|
142
154
|
runs
|
|
143
155
|
};
|
|
144
156
|
}
|
|
157
|
+
function toEmitItem(item) {
|
|
158
|
+
return item.kind === "paragraph" ? { block: item.block } : item.item;
|
|
159
|
+
}
|
|
145
160
|
function firstBlockCheckbox(first, taskNumId) {
|
|
146
|
-
if (first.list
|
|
161
|
+
if (first.list.checked !== void 0) return {
|
|
147
162
|
checkboxText: first.list.checked ? "[x] " : "[ ] ",
|
|
148
163
|
stripGlyph: false
|
|
149
164
|
};
|
|
150
|
-
if (!taskNumId) return {
|
|
165
|
+
if (!taskNumId || first.kind !== "paragraph") return {
|
|
151
166
|
checkboxText: "",
|
|
152
167
|
stripGlyph: false
|
|
153
168
|
};
|
|
154
|
-
const leading = first.runs[0]?.text ?? "";
|
|
169
|
+
const leading = first.block.runs[0]?.text ?? "";
|
|
155
170
|
if (leading.startsWith(`☒ `)) return {
|
|
156
171
|
checkboxText: "[x] ",
|
|
157
172
|
stripGlyph: true
|
|
@@ -181,44 +196,127 @@ function renderListItemMarker(numId, info, checkboxText, context) {
|
|
|
181
196
|
bareLength: bare.length
|
|
182
197
|
};
|
|
183
198
|
}
|
|
199
|
+
function consumeSameItemRun(items, from, level, itemId) {
|
|
200
|
+
let end = from;
|
|
201
|
+
while (end < items.length) {
|
|
202
|
+
const candidate = items[end];
|
|
203
|
+
if (candidate?.list.level !== level || candidate.list.itemId !== itemId) break;
|
|
204
|
+
end += 1;
|
|
205
|
+
}
|
|
206
|
+
return end;
|
|
207
|
+
}
|
|
208
|
+
function collectListItem(items, start, level, itemId) {
|
|
209
|
+
const segments = [];
|
|
210
|
+
let index = start;
|
|
211
|
+
const ownEnd = itemId === void 0 ? index + 1 : consumeSameItemRun(items, index, level, itemId);
|
|
212
|
+
segments.push({
|
|
213
|
+
kind: "own",
|
|
214
|
+
blocks: items.slice(index, ownEnd)
|
|
215
|
+
});
|
|
216
|
+
index = ownEnd;
|
|
217
|
+
for (;;) {
|
|
218
|
+
let nestedEnd = index;
|
|
219
|
+
while (nestedEnd < items.length) {
|
|
220
|
+
const candidateLevel = items[nestedEnd]?.list.level;
|
|
221
|
+
if (candidateLevel === void 0 || candidateLevel <= level) break;
|
|
222
|
+
nestedEnd += 1;
|
|
223
|
+
}
|
|
224
|
+
if (nestedEnd === index) break;
|
|
225
|
+
segments.push({
|
|
226
|
+
kind: "nested",
|
|
227
|
+
blocks: items.slice(index, nestedEnd)
|
|
228
|
+
});
|
|
229
|
+
index = nestedEnd;
|
|
230
|
+
if (itemId === void 0) break;
|
|
231
|
+
const resumedEnd = consumeSameItemRun(items, index, level, itemId);
|
|
232
|
+
if (resumedEnd === index) break;
|
|
233
|
+
segments.push({
|
|
234
|
+
kind: "own",
|
|
235
|
+
blocks: items.slice(index, resumedEnd)
|
|
236
|
+
});
|
|
237
|
+
index = resumedEnd;
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
segments,
|
|
241
|
+
next: index
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function emitItemCanInterrupt(item, context) {
|
|
245
|
+
if (!isConstructItem(item)) return item.block.kind === "paragraph" ? canInterruptOpenParagraph(item.block.styleId, context) : true;
|
|
246
|
+
if (isMaterialisedDivision(item)) return true;
|
|
247
|
+
const first = item.children[0];
|
|
248
|
+
return first === void 0 ? true : emitItemCanInterrupt(first, context);
|
|
249
|
+
}
|
|
250
|
+
function lastStyleIdOf(item) {
|
|
251
|
+
if (isConstructItem(item)) {
|
|
252
|
+
const last = item.children[item.children.length - 1];
|
|
253
|
+
return last === void 0 ? void 0 : lastStyleIdOf(last);
|
|
254
|
+
}
|
|
255
|
+
return item.block.kind === "paragraph" ? item.block.styleId : void 0;
|
|
256
|
+
}
|
|
257
|
+
function regionItemCanInterrupt(item, context) {
|
|
258
|
+
return emitItemCanInterrupt(toEmitItem(item), context);
|
|
259
|
+
}
|
|
260
|
+
function lastStyleIdOfRegionItem(item) {
|
|
261
|
+
return lastStyleIdOf(toEmitItem(item));
|
|
262
|
+
}
|
|
263
|
+
function listRegionItemBody(item, context, stripGlyph) {
|
|
264
|
+
if (item.kind === "paragraph") return renderParagraphBody(stripGlyph ? stripCheckboxRun(item.block) : item.block, context);
|
|
265
|
+
const previousEnclosingItemId = context.enclosingItemId;
|
|
266
|
+
context.enclosingItemId = item.list.itemId;
|
|
267
|
+
const body = renderConstruct(item.item, context);
|
|
268
|
+
context.enclosingItemId = previousEnclosingItemId;
|
|
269
|
+
return body;
|
|
270
|
+
}
|
|
271
|
+
function requiresBlankLineBefore(next, previousStyleId, context) {
|
|
272
|
+
if (previousStyleId === "HTMLPreformatted") return true;
|
|
273
|
+
return !terminatesCleanly(previousStyleId) && !regionItemCanInterrupt(next, context);
|
|
274
|
+
}
|
|
184
275
|
function renderListRegion(items, context) {
|
|
185
276
|
const parts = [];
|
|
186
277
|
let index = 0;
|
|
187
278
|
while (index < items.length) {
|
|
188
279
|
const item = items[index];
|
|
189
|
-
if (item
|
|
280
|
+
if (item === void 0) break;
|
|
190
281
|
const { numId, level, itemId } = item.list;
|
|
191
282
|
const info = listInfoFor(numId, context);
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (candidate?.list?.level !== level || candidate.list.itemId !== itemId) break;
|
|
196
|
-
ownEnd += 1;
|
|
197
|
-
}
|
|
198
|
-
const ownBlocks = items.slice(index, ownEnd);
|
|
199
|
-
let lookahead = ownEnd;
|
|
200
|
-
while (lookahead < items.length && (items[lookahead]?.list?.level ?? -1) > level) lookahead += 1;
|
|
201
|
-
const nestedItems = items.slice(ownEnd, lookahead);
|
|
202
|
-
const first = ownBlocks[0];
|
|
283
|
+
const loose = info?.loose === true;
|
|
284
|
+
const { segments, next } = collectListItem(items, index, level, itemId);
|
|
285
|
+
const first = segments[0]?.blocks[0];
|
|
203
286
|
if (first === void 0) break;
|
|
204
287
|
const { checkboxText, stripGlyph } = firstBlockCheckbox(first, info?.task === true);
|
|
205
288
|
const marker = renderListItemMarker(numId, info, checkboxText, context);
|
|
206
289
|
const indent = " ".repeat(marker.bareLength);
|
|
207
|
-
|
|
208
|
-
let
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
290
|
+
let text = "";
|
|
291
|
+
let renderedFirstLine = false;
|
|
292
|
+
let previousStyleId;
|
|
293
|
+
for (const segment of segments) {
|
|
294
|
+
if (segment.kind === "nested") {
|
|
295
|
+
const nested = renderListRegion(segment.blocks, context).split("\n").map((line) => line.length === 0 ? line : `${indent}${line}`).join("\n");
|
|
296
|
+
text += `\n${nested}`;
|
|
297
|
+
const lastNested = segment.blocks[segment.blocks.length - 1];
|
|
298
|
+
previousStyleId = lastNested === void 0 ? void 0 : lastStyleIdOfRegionItem(lastNested);
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
for (const block of segment.blocks) {
|
|
302
|
+
if (!renderedFirstLine) {
|
|
303
|
+
const [firstLine = "", ...restLines] = listRegionItemBody(block, context, stripGlyph).split("\n");
|
|
304
|
+
text = [`${marker.full}${firstLine}`, ...restLines.map((line) => `${indent}${line}`)].join("\n");
|
|
305
|
+
renderedFirstLine = true;
|
|
306
|
+
previousStyleId = lastStyleIdOfRegionItem(block);
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
const rendered = listRegionItemBody(block, context, false).split("\n").map((line) => line.length === 0 ? line : `${indent}${line}`).join("\n");
|
|
310
|
+
const blank = loose || requiresBlankLineBefore(block, previousStyleId, context);
|
|
311
|
+
text += blank ? `\n\n${rendered}` : `\n${rendered}`;
|
|
312
|
+
previousStyleId = lastStyleIdOfRegionItem(block);
|
|
313
|
+
}
|
|
216
314
|
}
|
|
217
315
|
parts.push({
|
|
218
316
|
numId,
|
|
219
317
|
text
|
|
220
318
|
});
|
|
221
|
-
index =
|
|
319
|
+
index = next;
|
|
222
320
|
}
|
|
223
321
|
let out = "";
|
|
224
322
|
for (const [partIndex, part] of parts.entries()) {
|
|
@@ -235,6 +333,12 @@ function renderListRegion(items, context) {
|
|
|
235
333
|
function isConstructItem(item) {
|
|
236
334
|
return "descriptor" in item;
|
|
237
335
|
}
|
|
336
|
+
function isMaterialisedDivision(item) {
|
|
337
|
+
return item.descriptor.kind === "division" && item.children.every((child) => {
|
|
338
|
+
if (isConstructItem(child)) return true;
|
|
339
|
+
return child.block.kind !== "paragraph" || child.block.indentLeftPt !== void 0 && child.block.indentLeftPt >= 36;
|
|
340
|
+
});
|
|
341
|
+
}
|
|
238
342
|
function groupConstructItems(blocks, start) {
|
|
239
343
|
const items = [];
|
|
240
344
|
let index = start;
|
|
@@ -283,10 +387,7 @@ function renderConstruct(item, context) {
|
|
|
283
387
|
return body;
|
|
284
388
|
}
|
|
285
389
|
if (descriptor.kind === "division") {
|
|
286
|
-
if (item
|
|
287
|
-
if (isConstructItem(child)) return true;
|
|
288
|
-
return child.block.kind !== "paragraph" || child.block.indentLeftPt !== void 0 && child.block.indentLeftPt >= 36;
|
|
289
|
-
})) {
|
|
390
|
+
if (isMaterialisedDivision(item)) {
|
|
290
391
|
context.divisionDepth += 1;
|
|
291
392
|
const body = renderItems(item.children, context);
|
|
292
393
|
context.divisionDepth -= 1;
|
|
@@ -307,6 +408,18 @@ function renderConstruct(item, context) {
|
|
|
307
408
|
});
|
|
308
409
|
return body;
|
|
309
410
|
}
|
|
411
|
+
function constructCarriesListItemId(item, itemId) {
|
|
412
|
+
return item.children.some((child) => {
|
|
413
|
+
if (isConstructItem(child)) return constructCarriesListItemId(child, itemId);
|
|
414
|
+
if (child.block.kind !== "paragraph") return false;
|
|
415
|
+
const list = child.block.list;
|
|
416
|
+
if (list?.itemId === itemId) return true;
|
|
417
|
+
return list?.numId !== void 0 && require_shared_list_id.parseListNumId(list.numId)?.ownerItemId === itemId;
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
function isInheritedListMembership(list, context) {
|
|
421
|
+
return list.itemId !== void 0 && list.itemId === context.enclosingItemId;
|
|
422
|
+
}
|
|
310
423
|
function renderItems(items, context) {
|
|
311
424
|
const parts = [];
|
|
312
425
|
let index = 0;
|
|
@@ -319,11 +432,40 @@ function renderItems(items, context) {
|
|
|
319
432
|
index += 1;
|
|
320
433
|
continue;
|
|
321
434
|
}
|
|
322
|
-
if (item.block.kind === "paragraph" && item.block.list !== void 0) {
|
|
435
|
+
if (item.block.kind === "paragraph" && item.block.list !== void 0 && !isInheritedListMembership(item.block.list, context)) {
|
|
323
436
|
const region = [];
|
|
324
437
|
let end = index;
|
|
325
|
-
|
|
326
|
-
|
|
438
|
+
const openMemberships = [];
|
|
439
|
+
for (;;) {
|
|
440
|
+
const candidate = items[end];
|
|
441
|
+
if (candidate === void 0) break;
|
|
442
|
+
if (isConstructItem(candidate)) {
|
|
443
|
+
let matched;
|
|
444
|
+
for (let i = openMemberships.length - 1; i >= 0; i -= 1) {
|
|
445
|
+
const membership = openMemberships[i];
|
|
446
|
+
if (membership.itemId !== void 0 && constructCarriesListItemId(candidate, membership.itemId)) {
|
|
447
|
+
matched = membership;
|
|
448
|
+
break;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (matched === void 0) break;
|
|
452
|
+
region.push({
|
|
453
|
+
kind: "construct",
|
|
454
|
+
item: candidate,
|
|
455
|
+
list: matched
|
|
456
|
+
});
|
|
457
|
+
end += 1;
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
if (candidate.block.kind !== "paragraph" || candidate.block.list === void 0 || isInheritedListMembership(candidate.block.list, context)) break;
|
|
461
|
+
const list = candidate.block.list;
|
|
462
|
+
while (openMemberships.length > 0 && openMemberships[openMemberships.length - 1].level >= list.level) openMemberships.pop();
|
|
463
|
+
openMemberships.push(list);
|
|
464
|
+
region.push({
|
|
465
|
+
kind: "paragraph",
|
|
466
|
+
block: candidate.block,
|
|
467
|
+
list
|
|
468
|
+
});
|
|
327
469
|
end += 1;
|
|
328
470
|
}
|
|
329
471
|
parts.push(renderListRegion(region, context));
|
|
@@ -365,7 +507,8 @@ function emitMarkdown(document, options = {}) {
|
|
|
365
507
|
orderedCounters: /* @__PURE__ */ new Map(),
|
|
366
508
|
reportedFallbackNumIds: /* @__PURE__ */ new Set(),
|
|
367
509
|
reportedAbsentNumIdFallback: false,
|
|
368
|
-
divisionDepth: 0
|
|
510
|
+
divisionDepth: 0,
|
|
511
|
+
enclosingItemId: void 0
|
|
369
512
|
};
|
|
370
513
|
const body = document.sections.map((section) => emitBlocks(section.blocks, context)).join("\n\n");
|
|
371
514
|
const frontMatter = options.frontMatter === true ? require_emit_front_matter.emitFrontMatter(document.metadata) : void 0;
|
package/dist/emit/emit.js
CHANGED
|
@@ -45,6 +45,18 @@ function isQuotableStyle(styleId) {
|
|
|
45
45
|
if (styleId === void 0) return false;
|
|
46
46
|
return QUOTABLE_STYLE_IDS.has(styleId) || parseHeadingStyleId(styleId) !== void 0;
|
|
47
47
|
}
|
|
48
|
+
function terminatesCleanly(styleId) {
|
|
49
|
+
if (styleId === void 0 || styleId === "Quote" || styleId === "HTMLPreformatted") return false;
|
|
50
|
+
return styleId === "CodeBlock" || styleId === "MathBlock" || styleId === "HorizontalRule" || parseHeadingStyleId(styleId) !== void 0;
|
|
51
|
+
}
|
|
52
|
+
function canInterruptOpenParagraph(styleId, context) {
|
|
53
|
+
if (styleId === void 0 || styleId === "Quote" || styleId === "HTMLPreformatted") return false;
|
|
54
|
+
if (styleId === "CodeBlock" || styleId === "MathBlock") return true;
|
|
55
|
+
if (styleId === "HorizontalRule") return context.thematicBreakChar !== SETEXT_LEVEL_2_CHAR;
|
|
56
|
+
const headingLevel = parseHeadingStyleId(styleId);
|
|
57
|
+
if (headingLevel !== void 0) return !(context.headingStyle === "setext" && headingLevel <= MAX_SETEXT_LEVEL);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
48
60
|
function quoteDepthOf(paragraph) {
|
|
49
61
|
if (paragraph.indentLeftPt === void 0 || paragraph.indentLeftPt <= 0) return 0;
|
|
50
62
|
return Math.max(1, Math.round(paragraph.indentLeftPt / 36));
|
|
@@ -141,16 +153,19 @@ function stripCheckboxRun(item) {
|
|
|
141
153
|
runs
|
|
142
154
|
};
|
|
143
155
|
}
|
|
156
|
+
function toEmitItem(item) {
|
|
157
|
+
return item.kind === "paragraph" ? { block: item.block } : item.item;
|
|
158
|
+
}
|
|
144
159
|
function firstBlockCheckbox(first, taskNumId) {
|
|
145
|
-
if (first.list
|
|
160
|
+
if (first.list.checked !== void 0) return {
|
|
146
161
|
checkboxText: first.list.checked ? "[x] " : "[ ] ",
|
|
147
162
|
stripGlyph: false
|
|
148
163
|
};
|
|
149
|
-
if (!taskNumId) return {
|
|
164
|
+
if (!taskNumId || first.kind !== "paragraph") return {
|
|
150
165
|
checkboxText: "",
|
|
151
166
|
stripGlyph: false
|
|
152
167
|
};
|
|
153
|
-
const leading = first.runs[0]?.text ?? "";
|
|
168
|
+
const leading = first.block.runs[0]?.text ?? "";
|
|
154
169
|
if (leading.startsWith(`☒ `)) return {
|
|
155
170
|
checkboxText: "[x] ",
|
|
156
171
|
stripGlyph: true
|
|
@@ -180,44 +195,127 @@ function renderListItemMarker(numId, info, checkboxText, context) {
|
|
|
180
195
|
bareLength: bare.length
|
|
181
196
|
};
|
|
182
197
|
}
|
|
198
|
+
function consumeSameItemRun(items, from, level, itemId) {
|
|
199
|
+
let end = from;
|
|
200
|
+
while (end < items.length) {
|
|
201
|
+
const candidate = items[end];
|
|
202
|
+
if (candidate?.list.level !== level || candidate.list.itemId !== itemId) break;
|
|
203
|
+
end += 1;
|
|
204
|
+
}
|
|
205
|
+
return end;
|
|
206
|
+
}
|
|
207
|
+
function collectListItem(items, start, level, itemId) {
|
|
208
|
+
const segments = [];
|
|
209
|
+
let index = start;
|
|
210
|
+
const ownEnd = itemId === void 0 ? index + 1 : consumeSameItemRun(items, index, level, itemId);
|
|
211
|
+
segments.push({
|
|
212
|
+
kind: "own",
|
|
213
|
+
blocks: items.slice(index, ownEnd)
|
|
214
|
+
});
|
|
215
|
+
index = ownEnd;
|
|
216
|
+
for (;;) {
|
|
217
|
+
let nestedEnd = index;
|
|
218
|
+
while (nestedEnd < items.length) {
|
|
219
|
+
const candidateLevel = items[nestedEnd]?.list.level;
|
|
220
|
+
if (candidateLevel === void 0 || candidateLevel <= level) break;
|
|
221
|
+
nestedEnd += 1;
|
|
222
|
+
}
|
|
223
|
+
if (nestedEnd === index) break;
|
|
224
|
+
segments.push({
|
|
225
|
+
kind: "nested",
|
|
226
|
+
blocks: items.slice(index, nestedEnd)
|
|
227
|
+
});
|
|
228
|
+
index = nestedEnd;
|
|
229
|
+
if (itemId === void 0) break;
|
|
230
|
+
const resumedEnd = consumeSameItemRun(items, index, level, itemId);
|
|
231
|
+
if (resumedEnd === index) break;
|
|
232
|
+
segments.push({
|
|
233
|
+
kind: "own",
|
|
234
|
+
blocks: items.slice(index, resumedEnd)
|
|
235
|
+
});
|
|
236
|
+
index = resumedEnd;
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
segments,
|
|
240
|
+
next: index
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function emitItemCanInterrupt(item, context) {
|
|
244
|
+
if (!isConstructItem(item)) return item.block.kind === "paragraph" ? canInterruptOpenParagraph(item.block.styleId, context) : true;
|
|
245
|
+
if (isMaterialisedDivision(item)) return true;
|
|
246
|
+
const first = item.children[0];
|
|
247
|
+
return first === void 0 ? true : emitItemCanInterrupt(first, context);
|
|
248
|
+
}
|
|
249
|
+
function lastStyleIdOf(item) {
|
|
250
|
+
if (isConstructItem(item)) {
|
|
251
|
+
const last = item.children[item.children.length - 1];
|
|
252
|
+
return last === void 0 ? void 0 : lastStyleIdOf(last);
|
|
253
|
+
}
|
|
254
|
+
return item.block.kind === "paragraph" ? item.block.styleId : void 0;
|
|
255
|
+
}
|
|
256
|
+
function regionItemCanInterrupt(item, context) {
|
|
257
|
+
return emitItemCanInterrupt(toEmitItem(item), context);
|
|
258
|
+
}
|
|
259
|
+
function lastStyleIdOfRegionItem(item) {
|
|
260
|
+
return lastStyleIdOf(toEmitItem(item));
|
|
261
|
+
}
|
|
262
|
+
function listRegionItemBody(item, context, stripGlyph) {
|
|
263
|
+
if (item.kind === "paragraph") return renderParagraphBody(stripGlyph ? stripCheckboxRun(item.block) : item.block, context);
|
|
264
|
+
const previousEnclosingItemId = context.enclosingItemId;
|
|
265
|
+
context.enclosingItemId = item.list.itemId;
|
|
266
|
+
const body = renderConstruct(item.item, context);
|
|
267
|
+
context.enclosingItemId = previousEnclosingItemId;
|
|
268
|
+
return body;
|
|
269
|
+
}
|
|
270
|
+
function requiresBlankLineBefore(next, previousStyleId, context) {
|
|
271
|
+
if (previousStyleId === "HTMLPreformatted") return true;
|
|
272
|
+
return !terminatesCleanly(previousStyleId) && !regionItemCanInterrupt(next, context);
|
|
273
|
+
}
|
|
183
274
|
function renderListRegion(items, context) {
|
|
184
275
|
const parts = [];
|
|
185
276
|
let index = 0;
|
|
186
277
|
while (index < items.length) {
|
|
187
278
|
const item = items[index];
|
|
188
|
-
if (item
|
|
279
|
+
if (item === void 0) break;
|
|
189
280
|
const { numId, level, itemId } = item.list;
|
|
190
281
|
const info = listInfoFor(numId, context);
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (candidate?.list?.level !== level || candidate.list.itemId !== itemId) break;
|
|
195
|
-
ownEnd += 1;
|
|
196
|
-
}
|
|
197
|
-
const ownBlocks = items.slice(index, ownEnd);
|
|
198
|
-
let lookahead = ownEnd;
|
|
199
|
-
while (lookahead < items.length && (items[lookahead]?.list?.level ?? -1) > level) lookahead += 1;
|
|
200
|
-
const nestedItems = items.slice(ownEnd, lookahead);
|
|
201
|
-
const first = ownBlocks[0];
|
|
282
|
+
const loose = info?.loose === true;
|
|
283
|
+
const { segments, next } = collectListItem(items, index, level, itemId);
|
|
284
|
+
const first = segments[0]?.blocks[0];
|
|
202
285
|
if (first === void 0) break;
|
|
203
286
|
const { checkboxText, stripGlyph } = firstBlockCheckbox(first, info?.task === true);
|
|
204
287
|
const marker = renderListItemMarker(numId, info, checkboxText, context);
|
|
205
288
|
const indent = " ".repeat(marker.bareLength);
|
|
206
|
-
|
|
207
|
-
let
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
289
|
+
let text = "";
|
|
290
|
+
let renderedFirstLine = false;
|
|
291
|
+
let previousStyleId;
|
|
292
|
+
for (const segment of segments) {
|
|
293
|
+
if (segment.kind === "nested") {
|
|
294
|
+
const nested = renderListRegion(segment.blocks, context).split("\n").map((line) => line.length === 0 ? line : `${indent}${line}`).join("\n");
|
|
295
|
+
text += `\n${nested}`;
|
|
296
|
+
const lastNested = segment.blocks[segment.blocks.length - 1];
|
|
297
|
+
previousStyleId = lastNested === void 0 ? void 0 : lastStyleIdOfRegionItem(lastNested);
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
for (const block of segment.blocks) {
|
|
301
|
+
if (!renderedFirstLine) {
|
|
302
|
+
const [firstLine = "", ...restLines] = listRegionItemBody(block, context, stripGlyph).split("\n");
|
|
303
|
+
text = [`${marker.full}${firstLine}`, ...restLines.map((line) => `${indent}${line}`)].join("\n");
|
|
304
|
+
renderedFirstLine = true;
|
|
305
|
+
previousStyleId = lastStyleIdOfRegionItem(block);
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const rendered = listRegionItemBody(block, context, false).split("\n").map((line) => line.length === 0 ? line : `${indent}${line}`).join("\n");
|
|
309
|
+
const blank = loose || requiresBlankLineBefore(block, previousStyleId, context);
|
|
310
|
+
text += blank ? `\n\n${rendered}` : `\n${rendered}`;
|
|
311
|
+
previousStyleId = lastStyleIdOfRegionItem(block);
|
|
312
|
+
}
|
|
215
313
|
}
|
|
216
314
|
parts.push({
|
|
217
315
|
numId,
|
|
218
316
|
text
|
|
219
317
|
});
|
|
220
|
-
index =
|
|
318
|
+
index = next;
|
|
221
319
|
}
|
|
222
320
|
let out = "";
|
|
223
321
|
for (const [partIndex, part] of parts.entries()) {
|
|
@@ -234,6 +332,12 @@ function renderListRegion(items, context) {
|
|
|
234
332
|
function isConstructItem(item) {
|
|
235
333
|
return "descriptor" in item;
|
|
236
334
|
}
|
|
335
|
+
function isMaterialisedDivision(item) {
|
|
336
|
+
return item.descriptor.kind === "division" && item.children.every((child) => {
|
|
337
|
+
if (isConstructItem(child)) return true;
|
|
338
|
+
return child.block.kind !== "paragraph" || child.block.indentLeftPt !== void 0 && child.block.indentLeftPt >= 36;
|
|
339
|
+
});
|
|
340
|
+
}
|
|
237
341
|
function groupConstructItems(blocks, start) {
|
|
238
342
|
const items = [];
|
|
239
343
|
let index = start;
|
|
@@ -282,10 +386,7 @@ function renderConstruct(item, context) {
|
|
|
282
386
|
return body;
|
|
283
387
|
}
|
|
284
388
|
if (descriptor.kind === "division") {
|
|
285
|
-
if (item
|
|
286
|
-
if (isConstructItem(child)) return true;
|
|
287
|
-
return child.block.kind !== "paragraph" || child.block.indentLeftPt !== void 0 && child.block.indentLeftPt >= 36;
|
|
288
|
-
})) {
|
|
389
|
+
if (isMaterialisedDivision(item)) {
|
|
289
390
|
context.divisionDepth += 1;
|
|
290
391
|
const body = renderItems(item.children, context);
|
|
291
392
|
context.divisionDepth -= 1;
|
|
@@ -306,6 +407,18 @@ function renderConstruct(item, context) {
|
|
|
306
407
|
});
|
|
307
408
|
return body;
|
|
308
409
|
}
|
|
410
|
+
function constructCarriesListItemId(item, itemId) {
|
|
411
|
+
return item.children.some((child) => {
|
|
412
|
+
if (isConstructItem(child)) return constructCarriesListItemId(child, itemId);
|
|
413
|
+
if (child.block.kind !== "paragraph") return false;
|
|
414
|
+
const list = child.block.list;
|
|
415
|
+
if (list?.itemId === itemId) return true;
|
|
416
|
+
return list?.numId !== void 0 && parseListNumId(list.numId)?.ownerItemId === itemId;
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
function isInheritedListMembership(list, context) {
|
|
420
|
+
return list.itemId !== void 0 && list.itemId === context.enclosingItemId;
|
|
421
|
+
}
|
|
309
422
|
function renderItems(items, context) {
|
|
310
423
|
const parts = [];
|
|
311
424
|
let index = 0;
|
|
@@ -318,11 +431,40 @@ function renderItems(items, context) {
|
|
|
318
431
|
index += 1;
|
|
319
432
|
continue;
|
|
320
433
|
}
|
|
321
|
-
if (item.block.kind === "paragraph" && item.block.list !== void 0) {
|
|
434
|
+
if (item.block.kind === "paragraph" && item.block.list !== void 0 && !isInheritedListMembership(item.block.list, context)) {
|
|
322
435
|
const region = [];
|
|
323
436
|
let end = index;
|
|
324
|
-
|
|
325
|
-
|
|
437
|
+
const openMemberships = [];
|
|
438
|
+
for (;;) {
|
|
439
|
+
const candidate = items[end];
|
|
440
|
+
if (candidate === void 0) break;
|
|
441
|
+
if (isConstructItem(candidate)) {
|
|
442
|
+
let matched;
|
|
443
|
+
for (let i = openMemberships.length - 1; i >= 0; i -= 1) {
|
|
444
|
+
const membership = openMemberships[i];
|
|
445
|
+
if (membership.itemId !== void 0 && constructCarriesListItemId(candidate, membership.itemId)) {
|
|
446
|
+
matched = membership;
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if (matched === void 0) break;
|
|
451
|
+
region.push({
|
|
452
|
+
kind: "construct",
|
|
453
|
+
item: candidate,
|
|
454
|
+
list: matched
|
|
455
|
+
});
|
|
456
|
+
end += 1;
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
if (candidate.block.kind !== "paragraph" || candidate.block.list === void 0 || isInheritedListMembership(candidate.block.list, context)) break;
|
|
460
|
+
const list = candidate.block.list;
|
|
461
|
+
while (openMemberships.length > 0 && openMemberships[openMemberships.length - 1].level >= list.level) openMemberships.pop();
|
|
462
|
+
openMemberships.push(list);
|
|
463
|
+
region.push({
|
|
464
|
+
kind: "paragraph",
|
|
465
|
+
block: candidate.block,
|
|
466
|
+
list
|
|
467
|
+
});
|
|
326
468
|
end += 1;
|
|
327
469
|
}
|
|
328
470
|
parts.push(renderListRegion(region, context));
|
|
@@ -364,7 +506,8 @@ function emitMarkdown(document, options = {}) {
|
|
|
364
506
|
orderedCounters: /* @__PURE__ */ new Map(),
|
|
365
507
|
reportedFallbackNumIds: /* @__PURE__ */ new Set(),
|
|
366
508
|
reportedAbsentNumIdFallback: false,
|
|
367
|
-
divisionDepth: 0
|
|
509
|
+
divisionDepth: 0,
|
|
510
|
+
enclosingItemId: void 0
|
|
368
511
|
};
|
|
369
512
|
const body = document.sections.map((section) => emitBlocks(section.blocks, context)).join("\n\n");
|
|
370
513
|
const frontMatter = options.frontMatter === true ? emitFrontMatter(document.metadata) : void 0;
|
package/dist/lower/lower.cjs
CHANGED
|
@@ -276,7 +276,8 @@ function lowerList(node, ancestorNumId, level, context, contentWidthPt) {
|
|
|
276
276
|
type: node.markerType,
|
|
277
277
|
start: node.start,
|
|
278
278
|
task,
|
|
279
|
-
loose: !node.tight
|
|
279
|
+
loose: !node.tight,
|
|
280
|
+
ownerItemId: context.list?.itemId
|
|
280
281
|
});
|
|
281
282
|
} else {
|
|
282
283
|
numId = ancestorNumId;
|
package/dist/lower/lower.js
CHANGED
|
@@ -275,7 +275,8 @@ function lowerList(node, ancestorNumId, level, context, contentWidthPt) {
|
|
|
275
275
|
type: node.markerType,
|
|
276
276
|
start: node.start,
|
|
277
277
|
task,
|
|
278
|
-
loose: !node.tight
|
|
278
|
+
loose: !node.tight,
|
|
279
|
+
ownerItemId: context.list?.itemId
|
|
279
280
|
});
|
|
280
281
|
} else {
|
|
281
282
|
numId = ancestorNumId;
|
package/dist/shared/list-id.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
//#region src/shared/list-id.ts
|
|
3
|
-
const NUMID_PATTERN = /^md(\d+):(bullet|ordered)(?:@(\d+))?(\+task)?(\+loose)?$/;
|
|
3
|
+
const NUMID_PATTERN = /^md(\d+):(bullet|ordered)(?:@(\d+))?(\+task)?(\+loose)?(?:\+owner=(md-i\d+))?$/;
|
|
4
4
|
const DEFAULT_ORDERED_START = 1;
|
|
5
5
|
function createNumIdMintState() {
|
|
6
6
|
return { next: 1 };
|
|
@@ -11,7 +11,8 @@ function mintListNumId(state, options) {
|
|
|
11
11
|
const startSuffix = options.type === "ordered" && options.start !== void 0 && options.start !== DEFAULT_ORDERED_START ? `@${String(options.start)}` : "";
|
|
12
12
|
const taskSuffix = options.task ? "+task" : "";
|
|
13
13
|
const looseSuffix = options.loose ? "+loose" : "";
|
|
14
|
-
|
|
14
|
+
const ownerSuffix = options.ownerItemId !== void 0 ? `+owner=${options.ownerItemId}` : "";
|
|
15
|
+
return `md${String(id)}:${options.type}${startSuffix}${taskSuffix}${looseSuffix}${ownerSuffix}`;
|
|
15
16
|
}
|
|
16
17
|
function parseListNumId(numId) {
|
|
17
18
|
const match = NUMID_PATTERN.exec(numId);
|
|
@@ -23,7 +24,8 @@ function parseListNumId(numId) {
|
|
|
23
24
|
type,
|
|
24
25
|
start: type === "ordered" && startText !== void 0 ? Number.parseInt(startText, 10) : void 0,
|
|
25
26
|
task: match[4] !== void 0,
|
|
26
|
-
loose: match[5] !== void 0
|
|
27
|
+
loose: match[5] !== void 0,
|
|
28
|
+
ownerItemId: match[6]
|
|
27
29
|
};
|
|
28
30
|
}
|
|
29
31
|
function mintedListType(numId) {
|
|
@@ -4,12 +4,14 @@ interface ListNumIdInfo {
|
|
|
4
4
|
readonly start?: number;
|
|
5
5
|
readonly task: boolean;
|
|
6
6
|
readonly loose: boolean;
|
|
7
|
+
readonly ownerItemId?: string;
|
|
7
8
|
}
|
|
8
9
|
interface ListNumIdMintOptions {
|
|
9
10
|
readonly type: "bullet" | "ordered";
|
|
10
11
|
readonly start?: number;
|
|
11
12
|
readonly task: boolean;
|
|
12
13
|
readonly loose: boolean;
|
|
14
|
+
readonly ownerItemId?: string;
|
|
13
15
|
}
|
|
14
16
|
interface NumIdMintState {
|
|
15
17
|
next: number;
|
package/dist/shared/list-id.d.ts
CHANGED
|
@@ -4,12 +4,14 @@ interface ListNumIdInfo {
|
|
|
4
4
|
readonly start?: number;
|
|
5
5
|
readonly task: boolean;
|
|
6
6
|
readonly loose: boolean;
|
|
7
|
+
readonly ownerItemId?: string;
|
|
7
8
|
}
|
|
8
9
|
interface ListNumIdMintOptions {
|
|
9
10
|
readonly type: "bullet" | "ordered";
|
|
10
11
|
readonly start?: number;
|
|
11
12
|
readonly task: boolean;
|
|
12
13
|
readonly loose: boolean;
|
|
14
|
+
readonly ownerItemId?: string;
|
|
13
15
|
}
|
|
14
16
|
interface NumIdMintState {
|
|
15
17
|
next: number;
|
package/dist/shared/list-id.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/shared/list-id.ts
|
|
2
|
-
const NUMID_PATTERN = /^md(\d+):(bullet|ordered)(?:@(\d+))?(\+task)?(\+loose)?$/;
|
|
2
|
+
const NUMID_PATTERN = /^md(\d+):(bullet|ordered)(?:@(\d+))?(\+task)?(\+loose)?(?:\+owner=(md-i\d+))?$/;
|
|
3
3
|
const DEFAULT_ORDERED_START = 1;
|
|
4
4
|
function createNumIdMintState() {
|
|
5
5
|
return { next: 1 };
|
|
@@ -10,7 +10,8 @@ function mintListNumId(state, options) {
|
|
|
10
10
|
const startSuffix = options.type === "ordered" && options.start !== void 0 && options.start !== DEFAULT_ORDERED_START ? `@${String(options.start)}` : "";
|
|
11
11
|
const taskSuffix = options.task ? "+task" : "";
|
|
12
12
|
const looseSuffix = options.loose ? "+loose" : "";
|
|
13
|
-
|
|
13
|
+
const ownerSuffix = options.ownerItemId !== void 0 ? `+owner=${options.ownerItemId}` : "";
|
|
14
|
+
return `md${String(id)}:${options.type}${startSuffix}${taskSuffix}${looseSuffix}${ownerSuffix}`;
|
|
14
15
|
}
|
|
15
16
|
function parseListNumId(numId) {
|
|
16
17
|
const match = NUMID_PATTERN.exec(numId);
|
|
@@ -22,7 +23,8 @@ function parseListNumId(numId) {
|
|
|
22
23
|
type,
|
|
23
24
|
start: type === "ordered" && startText !== void 0 ? Number.parseInt(startText, 10) : void 0,
|
|
24
25
|
task: match[4] !== void 0,
|
|
25
|
-
loose: match[5] !== void 0
|
|
26
|
+
loose: match[5] !== void 0,
|
|
27
|
+
ownerItemId: match[6]
|
|
26
28
|
};
|
|
27
29
|
}
|
|
28
30
|
function mintedListType(numId) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markdown-codec",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.2.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": "^
|
|
86
|
+
"document-schema.js": "^6.1.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",
|