@orkestrel/markdown 0.0.4 → 0.0.6
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/dist/src/core/index.cjs +803 -272
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +1459 -8
- package/dist/src/core/index.d.ts +1459 -8
- package/dist/src/core/index.js +803 -272
- package/dist/src/core/index.js.map +1 -1
- package/package.json +17 -13
- package/dist/src/core/Markdown.d.ts +0 -86
- package/dist/src/core/constants.d.ts +0 -17
- package/dist/src/core/factories.d.ts +0 -92
- package/dist/src/core/helpers.d.ts +0 -451
- package/dist/src/core/parsers.d.ts +0 -66
- package/dist/src/core/shapers.d.ts +0 -105
- package/dist/src/core/types.d.ts +0 -269
- package/dist/src/core/validators.d.ts +0 -287
package/dist/src/core/index.cjs
CHANGED
|
@@ -863,15 +863,6 @@ function scanInline(source, from, to, depth = 0) {
|
|
|
863
863
|
const nodes = [];
|
|
864
864
|
let index = from;
|
|
865
865
|
let pending = "";
|
|
866
|
-
const flush = () => {
|
|
867
|
-
if (pending.length > 0) {
|
|
868
|
-
nodes.push({
|
|
869
|
-
element: "text",
|
|
870
|
-
value: pending
|
|
871
|
-
});
|
|
872
|
-
pending = "";
|
|
873
|
-
}
|
|
874
|
-
};
|
|
875
866
|
while (index < to) {
|
|
876
867
|
const character = source[index] ?? "";
|
|
877
868
|
if (character === "\\" && index + 1 < to && isEscapable(source[index + 1] ?? "")) {
|
|
@@ -879,40 +870,51 @@ function scanInline(source, from, to, depth = 0) {
|
|
|
879
870
|
index += 2;
|
|
880
871
|
continue;
|
|
881
872
|
}
|
|
873
|
+
let scanned;
|
|
874
|
+
let end = index;
|
|
882
875
|
if (character === "`") {
|
|
883
876
|
const span = scanCode(source, index, to);
|
|
884
877
|
if (span) {
|
|
885
|
-
|
|
886
|
-
nodes.push({
|
|
878
|
+
scanned = {
|
|
887
879
|
element: "codeSpan",
|
|
888
880
|
value: span.value
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
continue;
|
|
881
|
+
};
|
|
882
|
+
end = span.end;
|
|
892
883
|
}
|
|
893
884
|
}
|
|
894
885
|
if (character === "[") {
|
|
895
886
|
const link = scanLink(source, index, to, depth);
|
|
896
887
|
if (link) {
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
index = link.end;
|
|
900
|
-
continue;
|
|
888
|
+
scanned = link.node;
|
|
889
|
+
end = link.end;
|
|
901
890
|
}
|
|
902
891
|
}
|
|
903
892
|
if (character === "*" || character === "_") {
|
|
904
893
|
const emphasis = scanEmphasis(source, index, to, depth);
|
|
905
894
|
if (emphasis) {
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
index = emphasis.end;
|
|
909
|
-
continue;
|
|
895
|
+
scanned = emphasis.node;
|
|
896
|
+
end = emphasis.end;
|
|
910
897
|
}
|
|
911
898
|
}
|
|
899
|
+
if (scanned !== void 0) {
|
|
900
|
+
if (pending.length > 0) {
|
|
901
|
+
nodes.push({
|
|
902
|
+
element: "text",
|
|
903
|
+
value: pending
|
|
904
|
+
});
|
|
905
|
+
pending = "";
|
|
906
|
+
}
|
|
907
|
+
nodes.push(scanned);
|
|
908
|
+
index = end;
|
|
909
|
+
continue;
|
|
910
|
+
}
|
|
912
911
|
pending += character;
|
|
913
912
|
index += 1;
|
|
914
913
|
}
|
|
915
|
-
|
|
914
|
+
if (pending.length > 0) nodes.push({
|
|
915
|
+
element: "text",
|
|
916
|
+
value: pending
|
|
917
|
+
});
|
|
916
918
|
return nodes;
|
|
917
919
|
}
|
|
918
920
|
/**
|
|
@@ -971,10 +973,7 @@ function sanitizeUrl(href) {
|
|
|
971
973
|
* @remarks
|
|
972
974
|
* Total: never throws. At {@link MAX_DEPTH} a value-bearing node (`text` / `codeSpan`)
|
|
973
975
|
* degrades to its escaped `value`; any other node degrades to `''` instead of
|
|
974
|
-
* recursing further, so pathologically deep input cannot exhaust the call stack.
|
|
975
|
-
* recursive engine and its per-shape sub-steps (inline concatenation, table cell,
|
|
976
|
-
* tight list-item) are nested inner functions - the only exported surface is
|
|
977
|
-
* `renderHTML` itself.
|
|
976
|
+
* recursing further, so pathologically deep input cannot exhaust the call stack.
|
|
978
977
|
*
|
|
979
978
|
* @param node - The AST node to render (a full document, or any sub-node)
|
|
980
979
|
* @returns The rendered, XSS-safe HTML string
|
|
@@ -988,47 +987,158 @@ function sanitizeUrl(href) {
|
|
|
988
987
|
* ```
|
|
989
988
|
*/
|
|
990
989
|
function renderHTML(node) {
|
|
991
|
-
|
|
992
|
-
|
|
990
|
+
const stack = [{
|
|
991
|
+
node,
|
|
992
|
+
depth: 0,
|
|
993
|
+
expanded: false,
|
|
994
|
+
count: 0
|
|
995
|
+
}];
|
|
996
|
+
const values = [];
|
|
997
|
+
while (stack.length > 0) {
|
|
998
|
+
const frame = stack.pop();
|
|
999
|
+
if (frame === void 0) continue;
|
|
1000
|
+
const current = frame.node;
|
|
1001
|
+
if (!frame.expanded) {
|
|
1002
|
+
if (frame.depth >= 64) {
|
|
1003
|
+
values.push("value" in current && typeof current.value === "string" ? escapeHtml(current.value) : "");
|
|
1004
|
+
continue;
|
|
1005
|
+
}
|
|
1006
|
+
const children = [];
|
|
1007
|
+
let depth = frame.depth + 1;
|
|
1008
|
+
switch (current.element) {
|
|
1009
|
+
case "document":
|
|
1010
|
+
case "heading":
|
|
1011
|
+
case "paragraph":
|
|
1012
|
+
case "blockquote":
|
|
1013
|
+
for (const child of current.children) if (child !== void 0) children.push(child);
|
|
1014
|
+
break;
|
|
1015
|
+
case "listItem": {
|
|
1016
|
+
const only = current.children[0];
|
|
1017
|
+
if (current.children.length === 1 && only !== void 0 && only.element === "paragraph") {
|
|
1018
|
+
for (const child of only.children) if (child !== void 0) children.push(child);
|
|
1019
|
+
} else for (const child of current.children) if (child !== void 0) children.push(child);
|
|
1020
|
+
break;
|
|
1021
|
+
}
|
|
1022
|
+
case "emphasis":
|
|
1023
|
+
case "link":
|
|
1024
|
+
for (const child of current.children) if (child !== void 0) children.push(child);
|
|
1025
|
+
depth += 1;
|
|
1026
|
+
break;
|
|
1027
|
+
case "list":
|
|
1028
|
+
for (const child of current.items) if (child !== void 0) children.push(child);
|
|
1029
|
+
break;
|
|
1030
|
+
case "table":
|
|
1031
|
+
for (const cell of current.header) if (cell !== void 0) {
|
|
1032
|
+
for (const child of cell) if (child !== void 0) children.push(child);
|
|
1033
|
+
}
|
|
1034
|
+
for (const row of current.rows) if (row !== void 0) {
|
|
1035
|
+
for (const cell of row) if (cell !== void 0) {
|
|
1036
|
+
for (const child of cell) if (child !== void 0) children.push(child);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
depth += 1;
|
|
1040
|
+
break;
|
|
1041
|
+
}
|
|
1042
|
+
stack.push({
|
|
1043
|
+
...frame,
|
|
1044
|
+
expanded: true,
|
|
1045
|
+
count: children.length
|
|
1046
|
+
});
|
|
1047
|
+
for (let index = children.length - 1; index >= 0; index -= 1) {
|
|
1048
|
+
const child = children[index];
|
|
1049
|
+
if (child !== void 0) stack.push({
|
|
1050
|
+
node: child,
|
|
1051
|
+
depth,
|
|
1052
|
+
expanded: false,
|
|
1053
|
+
count: 0
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
continue;
|
|
1057
|
+
}
|
|
1058
|
+
const children = frame.count === 0 ? [] : values.splice(values.length - frame.count, frame.count);
|
|
1059
|
+
let value = "";
|
|
993
1060
|
switch (current.element) {
|
|
994
|
-
case "document":
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
case "
|
|
998
|
-
|
|
999
|
-
|
|
1061
|
+
case "document":
|
|
1062
|
+
value = children.join("\n");
|
|
1063
|
+
break;
|
|
1064
|
+
case "heading":
|
|
1065
|
+
value = `<h${current.level}>${children.join("")}</h${current.level}>`;
|
|
1066
|
+
break;
|
|
1067
|
+
case "paragraph":
|
|
1068
|
+
value = `<p>${children.join("")}</p>`;
|
|
1069
|
+
break;
|
|
1070
|
+
case "thematicBreak":
|
|
1071
|
+
value = "<hr>";
|
|
1072
|
+
break;
|
|
1073
|
+
case "blockquote":
|
|
1074
|
+
value = `<blockquote>\n${children.join("\n")}\n</blockquote>`;
|
|
1075
|
+
break;
|
|
1076
|
+
case "codeBlock":
|
|
1077
|
+
value = `<pre>${current.lang === void 0 ? "<code>" : `<code class="language-${escapeHtml(current.lang)}">`}${escapeHtml(current.code)}</code></pre>`;
|
|
1078
|
+
break;
|
|
1000
1079
|
case "list": {
|
|
1001
|
-
const items =
|
|
1002
|
-
if (!current.ordered)
|
|
1003
|
-
|
|
1080
|
+
const items = children.join("\n");
|
|
1081
|
+
if (!current.ordered) {
|
|
1082
|
+
value = `<ul>\n${items}\n</ul>`;
|
|
1083
|
+
break;
|
|
1084
|
+
}
|
|
1085
|
+
value = `<ol${current.start !== 1 ? ` start="${current.start}"` : ""}>\n${items}\n</ol>`;
|
|
1086
|
+
break;
|
|
1004
1087
|
}
|
|
1005
|
-
case "listItem":
|
|
1088
|
+
case "listItem":
|
|
1089
|
+
value = `<li>${children.join(current.children.length === 1 && current.children[0]?.element === "paragraph" ? "" : "\n")}</li>`;
|
|
1090
|
+
break;
|
|
1006
1091
|
case "table": {
|
|
1007
|
-
|
|
1008
|
-
const
|
|
1009
|
-
|
|
1092
|
+
let offset = 0;
|
|
1093
|
+
const header = [];
|
|
1094
|
+
for (const [column, cell] of current.header.entries()) {
|
|
1095
|
+
if (cell === void 0) continue;
|
|
1096
|
+
const align = current.align[column];
|
|
1097
|
+
const style = align === "left" || align === "right" || align === "center" ? ` style="text-align:${align}"` : "";
|
|
1098
|
+
let count = 0;
|
|
1099
|
+
for (const child of cell) if (child !== void 0) count += 1;
|
|
1100
|
+
header.push(`<th${style}>${children.slice(offset, offset + count).join("")}</th>`);
|
|
1101
|
+
offset += count;
|
|
1102
|
+
}
|
|
1103
|
+
const rows = [];
|
|
1104
|
+
for (const row of current.rows) {
|
|
1105
|
+
const cells = [];
|
|
1106
|
+
for (const [column, cell] of row.entries()) {
|
|
1107
|
+
if (cell === void 0) continue;
|
|
1108
|
+
const align = current.align[column];
|
|
1109
|
+
const style = align === "left" || align === "right" || align === "center" ? ` style="text-align:${align}"` : "";
|
|
1110
|
+
let count = 0;
|
|
1111
|
+
for (const child of cell) if (child !== void 0) count += 1;
|
|
1112
|
+
cells.push(`<td${style}>${children.slice(offset, offset + count).join("")}</td>`);
|
|
1113
|
+
offset += count;
|
|
1114
|
+
}
|
|
1115
|
+
rows.push(`<tr>${cells.join("")}</tr>`);
|
|
1116
|
+
}
|
|
1117
|
+
const body = rows.join("\n");
|
|
1118
|
+
const bodyHtml = (0, _orkestrel_contract.isNonEmptyArray)(current.rows) ? `\n<tbody>\n${body}\n</tbody>` : "";
|
|
1119
|
+
value = `<table>\n<thead>\n<tr>${header.join("")}</tr>\n</thead>${bodyHtml}\n</table>`;
|
|
1120
|
+
break;
|
|
1010
1121
|
}
|
|
1011
|
-
case "text":
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
case "
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
const only = children[0];
|
|
1027
|
-
if (only !== void 0 && only.element === "paragraph") return renderInline(only.children, depth);
|
|
1122
|
+
case "text":
|
|
1123
|
+
value = escapeHtml(current.value);
|
|
1124
|
+
break;
|
|
1125
|
+
case "emphasis":
|
|
1126
|
+
value = current.strong ? `<strong>${children.join("")}</strong>` : `<em>${children.join("")}</em>`;
|
|
1127
|
+
break;
|
|
1128
|
+
case "codeSpan":
|
|
1129
|
+
value = `<code>${escapeHtml(current.value)}</code>`;
|
|
1130
|
+
break;
|
|
1131
|
+
case "link":
|
|
1132
|
+
value = `<a href="${sanitizeUrl(current.href)}">${children.join("")}</a>`;
|
|
1133
|
+
break;
|
|
1134
|
+
default:
|
|
1135
|
+
value = "";
|
|
1136
|
+
break;
|
|
1028
1137
|
}
|
|
1029
|
-
|
|
1138
|
+
if (stack.length === 0) return value;
|
|
1139
|
+
values.push(value);
|
|
1030
1140
|
}
|
|
1031
|
-
return
|
|
1141
|
+
return "";
|
|
1032
1142
|
}
|
|
1033
1143
|
/**
|
|
1034
1144
|
* Render a {@link MarkdownNode} to its CANONICAL markdown source - the inverse
|
|
@@ -1058,125 +1168,220 @@ function renderHTML(node) {
|
|
|
1058
1168
|
* ```
|
|
1059
1169
|
*/
|
|
1060
1170
|
function renderMarkdown(node) {
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1171
|
+
const stack = [{
|
|
1172
|
+
node,
|
|
1173
|
+
depth: 0,
|
|
1174
|
+
expanded: false,
|
|
1175
|
+
count: 0,
|
|
1176
|
+
escaped: ""
|
|
1177
|
+
}];
|
|
1178
|
+
const values = [];
|
|
1179
|
+
while (stack.length > 0) {
|
|
1180
|
+
const frame = stack.pop();
|
|
1181
|
+
if (frame === void 0) continue;
|
|
1182
|
+
const current = frame.node;
|
|
1183
|
+
if (!frame.expanded) {
|
|
1184
|
+
let escaped = "";
|
|
1185
|
+
if ((frame.depth >= 64 || current.element === "text") && "value" in current && typeof current.value === "string") for (let index = 0; index < current.value.length; index += 1) {
|
|
1186
|
+
const character = current.value[index] ?? "";
|
|
1187
|
+
const atLineStart = index === 0 || current.value[index - 1] === "\n";
|
|
1188
|
+
if (character === "\\" || character === "*" || character === "_" || character === "`" || character === "[" || character === "]") {
|
|
1189
|
+
escaped += `\\${character}`;
|
|
1073
1190
|
continue;
|
|
1074
1191
|
}
|
|
1075
|
-
if (
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
const marker = value[end];
|
|
1083
|
-
if ((marker === "." || marker === ")") && value[end + 1] === " ") {
|
|
1084
|
-
out += `${value.slice(index, end)}\\${marker}`;
|
|
1085
|
-
index = end;
|
|
1192
|
+
if (atLineStart) {
|
|
1193
|
+
if (character === "#" || character === ">") {
|
|
1194
|
+
escaped += `\\${character}`;
|
|
1195
|
+
continue;
|
|
1196
|
+
}
|
|
1197
|
+
if ((character === "-" || character === "+") && (current.value[index + 1] ?? " ") === " ") {
|
|
1198
|
+
escaped += `\\${character}`;
|
|
1086
1199
|
continue;
|
|
1087
1200
|
}
|
|
1201
|
+
if (/[0-9]/.test(character)) {
|
|
1202
|
+
let end = index;
|
|
1203
|
+
while (end < current.value.length && /[0-9]/.test(current.value[end] ?? "")) end += 1;
|
|
1204
|
+
const marker = current.value[end];
|
|
1205
|
+
if ((marker === "." || marker === ")") && current.value[end + 1] === " ") {
|
|
1206
|
+
escaped += `${current.value.slice(index, end)}\\${marker}`;
|
|
1207
|
+
index = end;
|
|
1208
|
+
continue;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1088
1211
|
}
|
|
1212
|
+
escaped += character;
|
|
1213
|
+
}
|
|
1214
|
+
if (frame.depth >= 64) {
|
|
1215
|
+
values.push(escaped);
|
|
1216
|
+
continue;
|
|
1217
|
+
}
|
|
1218
|
+
const children = [];
|
|
1219
|
+
let depth = frame.depth + 1;
|
|
1220
|
+
switch (current.element) {
|
|
1221
|
+
case "document":
|
|
1222
|
+
case "heading":
|
|
1223
|
+
case "paragraph":
|
|
1224
|
+
case "blockquote":
|
|
1225
|
+
case "listItem":
|
|
1226
|
+
case "emphasis":
|
|
1227
|
+
case "link":
|
|
1228
|
+
for (const child of current.children) if (child !== void 0) children.push(child);
|
|
1229
|
+
break;
|
|
1230
|
+
case "list":
|
|
1231
|
+
for (const child of current.items) if (child !== void 0) children.push(child);
|
|
1232
|
+
break;
|
|
1233
|
+
case "table":
|
|
1234
|
+
for (const cell of current.header) if (cell !== void 0) {
|
|
1235
|
+
for (const child of cell) if (child !== void 0) children.push(child);
|
|
1236
|
+
}
|
|
1237
|
+
for (const row of current.rows) {
|
|
1238
|
+
if (row === void 0) continue;
|
|
1239
|
+
for (let column = 0; column < current.header.length; column += 1) {
|
|
1240
|
+
const cell = row[column];
|
|
1241
|
+
if (cell !== void 0) {
|
|
1242
|
+
for (const child of cell) if (child !== void 0) children.push(child);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
depth += 1;
|
|
1247
|
+
break;
|
|
1248
|
+
}
|
|
1249
|
+
stack.push({
|
|
1250
|
+
...frame,
|
|
1251
|
+
expanded: true,
|
|
1252
|
+
count: children.length,
|
|
1253
|
+
escaped
|
|
1254
|
+
});
|
|
1255
|
+
for (let index = children.length - 1; index >= 0; index -= 1) {
|
|
1256
|
+
const child = children[index];
|
|
1257
|
+
if (child !== void 0) stack.push({
|
|
1258
|
+
node: child,
|
|
1259
|
+
depth,
|
|
1260
|
+
expanded: false,
|
|
1261
|
+
count: 0,
|
|
1262
|
+
escaped: ""
|
|
1263
|
+
});
|
|
1089
1264
|
}
|
|
1090
|
-
|
|
1265
|
+
continue;
|
|
1091
1266
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
function fenceFor(body, minimum) {
|
|
1095
|
-
let longest = 0;
|
|
1096
|
-
let run = 0;
|
|
1097
|
-
for (const character of body) if (character === "`") {
|
|
1098
|
-
run += 1;
|
|
1099
|
-
longest = Math.max(longest, run);
|
|
1100
|
-
} else run = 0;
|
|
1101
|
-
return "`".repeat(Math.max(minimum, longest + 1));
|
|
1102
|
-
}
|
|
1103
|
-
function renderInline(nodes, depth) {
|
|
1104
|
-
return nodes.map((child) => render(child, depth + 1)).join("");
|
|
1105
|
-
}
|
|
1106
|
-
function renderBlocks(blocks, depth) {
|
|
1107
|
-
return blocks.map((block) => render(block, depth + 1)).join("\n\n");
|
|
1108
|
-
}
|
|
1109
|
-
function renderItem(item, marker, depth) {
|
|
1110
|
-
const body = renderBlocks(item.children, depth + 1);
|
|
1111
|
-
const pad = " ".repeat(marker.length);
|
|
1112
|
-
return body.split("\n").map((line, index) => index === 0 ? marker + line : line === "" ? "" : pad + line).join("\n");
|
|
1113
|
-
}
|
|
1114
|
-
function renderCell(cell, depth) {
|
|
1115
|
-
return renderInline(cell, depth + 1).replace(/\|/g, "\\|");
|
|
1116
|
-
}
|
|
1117
|
-
function renderTable(current, depth) {
|
|
1118
|
-
const columns = current.header.length;
|
|
1119
|
-
return [
|
|
1120
|
-
`| ${current.header.map((cell) => renderCell(cell, depth)).join(" | ")} |`,
|
|
1121
|
-
`| ${current.align.map((align) => {
|
|
1122
|
-
if (align === "left") return ":--";
|
|
1123
|
-
if (align === "right") return "--:";
|
|
1124
|
-
if (align === "center") return ":-:";
|
|
1125
|
-
return "---";
|
|
1126
|
-
}).join(" | ")} |`,
|
|
1127
|
-
...current.rows.map((row) => {
|
|
1128
|
-
const cells = [];
|
|
1129
|
-
for (let column = 0; column < columns; column += 1) {
|
|
1130
|
-
const cell = row[column];
|
|
1131
|
-
cells.push(cell === void 0 ? "" : renderCell(cell, depth));
|
|
1132
|
-
}
|
|
1133
|
-
return `| ${cells.join(" | ")} |`;
|
|
1134
|
-
})
|
|
1135
|
-
].join("\n");
|
|
1136
|
-
}
|
|
1137
|
-
function render(current, depth) {
|
|
1138
|
-
if (depth >= 64) return "value" in current && typeof current.value === "string" ? escapeText(current.value) : "";
|
|
1267
|
+
const children = frame.count === 0 ? [] : values.splice(values.length - frame.count, frame.count);
|
|
1268
|
+
let value = "";
|
|
1139
1269
|
switch (current.element) {
|
|
1140
|
-
case "
|
|
1270
|
+
case "codeBlock":
|
|
1271
|
+
case "codeSpan": {
|
|
1272
|
+
const body = current.element === "codeBlock" ? current.code : current.value;
|
|
1273
|
+
let longest = 0;
|
|
1274
|
+
let run = 0;
|
|
1275
|
+
for (const character of body) if (character === "`") {
|
|
1276
|
+
run += 1;
|
|
1277
|
+
longest = Math.max(longest, run);
|
|
1278
|
+
} else run = 0;
|
|
1279
|
+
const fence = "`".repeat(Math.max(current.element === "codeBlock" ? 3 : 1, longest + 1));
|
|
1280
|
+
if (current.element === "codeBlock") {
|
|
1281
|
+
value = `${fence}${current.lang === void 0 ? "" : current.lang}\n${current.code}\n${fence}`;
|
|
1282
|
+
break;
|
|
1283
|
+
}
|
|
1284
|
+
const pad = current.value.startsWith("`") || current.value.endsWith("`") ? " " : "";
|
|
1285
|
+
value = `${fence}${pad}${current.value}${pad}${fence}`;
|
|
1286
|
+
break;
|
|
1287
|
+
}
|
|
1288
|
+
case "document":
|
|
1289
|
+
value = children.join("\n\n");
|
|
1290
|
+
break;
|
|
1141
1291
|
case "heading": {
|
|
1142
|
-
const escaped =
|
|
1143
|
-
return `${
|
|
1292
|
+
const escaped = children.join("").replace(/(^|[^\\])(#+)$/, (_match, before, hashes) => {
|
|
1293
|
+
return `${before}\\${hashes[0] ?? ""}${hashes.slice(1)}`;
|
|
1144
1294
|
});
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
case "paragraph": return renderInline(current.children, depth);
|
|
1148
|
-
case "thematicBreak": return "---";
|
|
1149
|
-
case "blockquote": return renderBlocks(current.children, depth).split("\n").map((line) => line === "" ? ">" : `> ${line}`).join("\n");
|
|
1150
|
-
case "codeBlock": {
|
|
1151
|
-
const fence = fenceFor(current.code, 3);
|
|
1152
|
-
return `${fence}${current.lang === void 0 ? "" : current.lang}\n${current.code}\n${fence}`;
|
|
1295
|
+
value = `${"#".repeat(current.level)} ${escaped}`;
|
|
1296
|
+
break;
|
|
1153
1297
|
}
|
|
1298
|
+
case "paragraph":
|
|
1299
|
+
value = children.join("");
|
|
1300
|
+
break;
|
|
1301
|
+
case "thematicBreak":
|
|
1302
|
+
value = "---";
|
|
1303
|
+
break;
|
|
1304
|
+
case "blockquote":
|
|
1305
|
+
value = children.join("\n\n").split("\n").map((line) => line === "" ? ">" : `> ${line}`).join("\n");
|
|
1306
|
+
break;
|
|
1154
1307
|
case "list": {
|
|
1308
|
+
const items = [];
|
|
1155
1309
|
let ordinal = current.start;
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1310
|
+
for (const body of children) {
|
|
1311
|
+
const marker = current.ordered ? `${ordinal}. ` : "- ";
|
|
1312
|
+
ordinal += 1;
|
|
1313
|
+
const pad = " ".repeat(marker.length);
|
|
1314
|
+
items.push(body.split("\n").map((line, index) => index === 0 ? marker + line : line === "" ? "" : pad + line).join("\n"));
|
|
1315
|
+
}
|
|
1316
|
+
value = items.join("\n");
|
|
1317
|
+
break;
|
|
1318
|
+
}
|
|
1319
|
+
case "listItem":
|
|
1320
|
+
value = children.join("\n\n");
|
|
1321
|
+
break;
|
|
1322
|
+
case "table": {
|
|
1323
|
+
let offset = 0;
|
|
1324
|
+
const header = [];
|
|
1325
|
+
for (const cell of current.header) {
|
|
1326
|
+
if (cell === void 0) {
|
|
1327
|
+
header.push("");
|
|
1328
|
+
continue;
|
|
1329
|
+
}
|
|
1330
|
+
let count = 0;
|
|
1331
|
+
for (const child of cell) if (child !== void 0) count += 1;
|
|
1332
|
+
header.push(children.slice(offset, offset + count).join("").replace(/\|/g, "\\|"));
|
|
1333
|
+
offset += count;
|
|
1334
|
+
}
|
|
1335
|
+
const delimiter = current.align.map((align) => {
|
|
1336
|
+
if (align === "left") return ":--";
|
|
1337
|
+
if (align === "right") return "--:";
|
|
1338
|
+
if (align === "center") return ":-:";
|
|
1339
|
+
return "---";
|
|
1340
|
+
});
|
|
1341
|
+
const rows = [];
|
|
1342
|
+
for (const row of current.rows) {
|
|
1343
|
+
const cells = [];
|
|
1344
|
+
for (let column = 0; column < current.header.length; column += 1) {
|
|
1345
|
+
const cell = row[column];
|
|
1346
|
+
if (cell === void 0) {
|
|
1347
|
+
cells.push("");
|
|
1348
|
+
continue;
|
|
1349
|
+
}
|
|
1350
|
+
let count = 0;
|
|
1351
|
+
for (const child of cell) if (child !== void 0) count += 1;
|
|
1352
|
+
cells.push(children.slice(offset, offset + count).join("").replace(/\|/g, "\\|"));
|
|
1353
|
+
offset += count;
|
|
1354
|
+
}
|
|
1355
|
+
rows.push(`| ${cells.join(" | ")} |`);
|
|
1356
|
+
}
|
|
1357
|
+
value = [
|
|
1358
|
+
`| ${header.join(" | ")} |`,
|
|
1359
|
+
`| ${delimiter.join(" | ")} |`,
|
|
1360
|
+
...rows
|
|
1361
|
+
].join("\n");
|
|
1362
|
+
break;
|
|
1159
1363
|
}
|
|
1160
|
-
case "
|
|
1161
|
-
|
|
1162
|
-
|
|
1364
|
+
case "text":
|
|
1365
|
+
value = frame.escaped;
|
|
1366
|
+
break;
|
|
1163
1367
|
case "emphasis": {
|
|
1164
1368
|
const marker = current.strong ? "**" : "*";
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
case "codeSpan": {
|
|
1168
|
-
const fence = fenceFor(current.value, 1);
|
|
1169
|
-
const pad = current.value.startsWith("`") || current.value.endsWith("`") ? " " : "";
|
|
1170
|
-
return `${fence}${pad}${current.value}${pad}${fence}`;
|
|
1369
|
+
value = `${marker}${children.join("")}${marker}`;
|
|
1370
|
+
break;
|
|
1171
1371
|
}
|
|
1172
1372
|
case "link": {
|
|
1173
1373
|
const href = current.href.replace(/[\\()]/g, (character) => `\\${character}`);
|
|
1174
|
-
|
|
1374
|
+
value = `[${children.join("")}](${href})`;
|
|
1375
|
+
break;
|
|
1175
1376
|
}
|
|
1176
|
-
default:
|
|
1377
|
+
default:
|
|
1378
|
+
value = "";
|
|
1379
|
+
break;
|
|
1177
1380
|
}
|
|
1381
|
+
if (stack.length === 0) return value;
|
|
1382
|
+
values.push(value);
|
|
1178
1383
|
}
|
|
1179
|
-
return
|
|
1384
|
+
return "";
|
|
1180
1385
|
}
|
|
1181
1386
|
/**
|
|
1182
1387
|
* Depth-first, pre-order, root-inclusive traversal of a {@link MarkdownNode} - yields
|
|
@@ -1198,10 +1403,17 @@ function renderMarkdown(node) {
|
|
|
1198
1403
|
* ```
|
|
1199
1404
|
*/
|
|
1200
1405
|
function* walkNodes(node) {
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1406
|
+
const stack = [{
|
|
1407
|
+
node,
|
|
1408
|
+
depth: 0
|
|
1409
|
+
}];
|
|
1410
|
+
while (stack.length > 0) {
|
|
1411
|
+
const frame = stack.pop();
|
|
1412
|
+
if (frame === void 0) continue;
|
|
1413
|
+
yield frame.node;
|
|
1414
|
+
if (frame.depth >= 64) continue;
|
|
1415
|
+
const children = [];
|
|
1416
|
+
switch (frame.node.element) {
|
|
1205
1417
|
case "document":
|
|
1206
1418
|
case "heading":
|
|
1207
1419
|
case "paragraph":
|
|
@@ -1209,19 +1421,30 @@ function* walkNodes(node) {
|
|
|
1209
1421
|
case "listItem":
|
|
1210
1422
|
case "emphasis":
|
|
1211
1423
|
case "link":
|
|
1212
|
-
for (const child of
|
|
1213
|
-
|
|
1424
|
+
for (const child of frame.node.children) if (child !== void 0) children.push(child);
|
|
1425
|
+
break;
|
|
1214
1426
|
case "list":
|
|
1215
|
-
for (const
|
|
1216
|
-
|
|
1427
|
+
for (const child of frame.node.items) if (child !== void 0) children.push(child);
|
|
1428
|
+
break;
|
|
1217
1429
|
case "table":
|
|
1218
|
-
for (const cell of
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1430
|
+
for (const cell of frame.node.header) if (cell !== void 0) {
|
|
1431
|
+
for (const child of cell) if (child !== void 0) children.push(child);
|
|
1432
|
+
}
|
|
1433
|
+
for (const row of frame.node.rows) if (row !== void 0) {
|
|
1434
|
+
for (const cell of row) if (cell !== void 0) {
|
|
1435
|
+
for (const child of cell) if (child !== void 0) children.push(child);
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
break;
|
|
1439
|
+
}
|
|
1440
|
+
for (let index = children.length - 1; index >= 0; index -= 1) {
|
|
1441
|
+
const child = children[index];
|
|
1442
|
+
if (child !== void 0) stack.push({
|
|
1443
|
+
node: child,
|
|
1444
|
+
depth: frame.depth + 1
|
|
1445
|
+
});
|
|
1222
1446
|
}
|
|
1223
1447
|
}
|
|
1224
|
-
yield* walk(node, 0);
|
|
1225
1448
|
}
|
|
1226
1449
|
/**
|
|
1227
1450
|
* Fold a {@link MarkdownNode} into a `T` via a total catamorphism - children are
|
|
@@ -1255,46 +1478,119 @@ function* walkNodes(node) {
|
|
|
1255
1478
|
* ```
|
|
1256
1479
|
*/
|
|
1257
1480
|
function foldNode(node, handlers, depth) {
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1481
|
+
const stack = [{
|
|
1482
|
+
node,
|
|
1483
|
+
depth,
|
|
1484
|
+
expanded: false,
|
|
1485
|
+
count: 0
|
|
1486
|
+
}];
|
|
1487
|
+
const values = [];
|
|
1488
|
+
while (stack.length > 0) {
|
|
1489
|
+
const frame = stack.pop();
|
|
1490
|
+
if (frame === void 0) continue;
|
|
1491
|
+
if (!frame.expanded) {
|
|
1492
|
+
const children = [];
|
|
1493
|
+
if (frame.depth < 64) switch (frame.node.element) {
|
|
1494
|
+
case "document":
|
|
1495
|
+
case "heading":
|
|
1496
|
+
case "paragraph":
|
|
1497
|
+
case "blockquote":
|
|
1498
|
+
case "listItem":
|
|
1499
|
+
case "emphasis":
|
|
1500
|
+
case "link":
|
|
1501
|
+
for (const child of frame.node.children) if (child !== void 0) children.push(child);
|
|
1502
|
+
break;
|
|
1503
|
+
case "list":
|
|
1504
|
+
for (const child of frame.node.items) if (child !== void 0) children.push(child);
|
|
1505
|
+
break;
|
|
1506
|
+
case "table":
|
|
1507
|
+
for (const cell of frame.node.header) if (cell !== void 0) {
|
|
1508
|
+
for (const child of cell) if (child !== void 0) children.push(child);
|
|
1509
|
+
}
|
|
1510
|
+
for (const row of frame.node.rows) if (row !== void 0) {
|
|
1511
|
+
for (const cell of row) if (cell !== void 0) {
|
|
1512
|
+
for (const child of cell) if (child !== void 0) children.push(child);
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
break;
|
|
1516
|
+
}
|
|
1517
|
+
stack.push({
|
|
1518
|
+
...frame,
|
|
1519
|
+
expanded: true,
|
|
1520
|
+
count: children.length
|
|
1521
|
+
});
|
|
1522
|
+
for (let index = children.length - 1; index >= 0; index -= 1) {
|
|
1523
|
+
const child = children[index];
|
|
1524
|
+
if (child !== void 0) stack.push({
|
|
1525
|
+
node: child,
|
|
1526
|
+
depth: frame.depth + 1,
|
|
1527
|
+
expanded: false,
|
|
1528
|
+
count: 0
|
|
1529
|
+
});
|
|
1530
|
+
}
|
|
1531
|
+
continue;
|
|
1273
1532
|
}
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
switch (
|
|
1533
|
+
const children = frame.count === 0 ? [] : values.splice(values.length - frame.count, frame.count);
|
|
1534
|
+
let value;
|
|
1535
|
+
switch (frame.node.element) {
|
|
1277
1536
|
case "document":
|
|
1537
|
+
value = handlers.document(frame.node, children);
|
|
1538
|
+
break;
|
|
1278
1539
|
case "heading":
|
|
1540
|
+
value = handlers.heading(frame.node, children);
|
|
1541
|
+
break;
|
|
1279
1542
|
case "paragraph":
|
|
1543
|
+
value = handlers.paragraph(frame.node, children);
|
|
1544
|
+
break;
|
|
1545
|
+
case "thematicBreak":
|
|
1546
|
+
value = handlers.thematicBreak(frame.node, children);
|
|
1547
|
+
break;
|
|
1280
1548
|
case "blockquote":
|
|
1549
|
+
value = handlers.blockquote(frame.node, children);
|
|
1550
|
+
break;
|
|
1551
|
+
case "codeBlock":
|
|
1552
|
+
value = handlers.codeBlock(frame.node, children);
|
|
1553
|
+
break;
|
|
1554
|
+
case "list":
|
|
1555
|
+
value = handlers.list(frame.node, children);
|
|
1556
|
+
break;
|
|
1281
1557
|
case "listItem":
|
|
1558
|
+
value = handlers.listItem(frame.node, children);
|
|
1559
|
+
break;
|
|
1560
|
+
case "table":
|
|
1561
|
+
value = handlers.table(frame.node, children);
|
|
1562
|
+
break;
|
|
1563
|
+
case "text":
|
|
1564
|
+
value = handlers.text(frame.node, children);
|
|
1565
|
+
break;
|
|
1282
1566
|
case "emphasis":
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
case "
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1567
|
+
value = handlers.emphasis(frame.node, children);
|
|
1568
|
+
break;
|
|
1569
|
+
case "codeSpan":
|
|
1570
|
+
value = handlers.codeSpan(frame.node, children);
|
|
1571
|
+
break;
|
|
1572
|
+
case "link":
|
|
1573
|
+
value = handlers.link(frame.node, children);
|
|
1574
|
+
break;
|
|
1291
1575
|
}
|
|
1576
|
+
if (stack.length === 0) return value;
|
|
1577
|
+
values.push(value);
|
|
1292
1578
|
}
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
return
|
|
1579
|
+
switch (node.element) {
|
|
1580
|
+
case "document": return handlers.document(node, []);
|
|
1581
|
+
case "heading": return handlers.heading(node, []);
|
|
1582
|
+
case "paragraph": return handlers.paragraph(node, []);
|
|
1583
|
+
case "thematicBreak": return handlers.thematicBreak(node, []);
|
|
1584
|
+
case "blockquote": return handlers.blockquote(node, []);
|
|
1585
|
+
case "codeBlock": return handlers.codeBlock(node, []);
|
|
1586
|
+
case "list": return handlers.list(node, []);
|
|
1587
|
+
case "listItem": return handlers.listItem(node, []);
|
|
1588
|
+
case "table": return handlers.table(node, []);
|
|
1589
|
+
case "text": return handlers.text(node, []);
|
|
1590
|
+
case "emphasis": return handlers.emphasis(node, []);
|
|
1591
|
+
case "codeSpan": return handlers.codeSpan(node, []);
|
|
1592
|
+
case "link": return handlers.link(node, []);
|
|
1296
1593
|
}
|
|
1297
|
-
return fold(node, depth);
|
|
1298
1594
|
}
|
|
1299
1595
|
/**
|
|
1300
1596
|
* Rewrite a {@link MarkdownDocument} bottom-up (copy-on-write) - each node's children
|
|
@@ -1329,71 +1625,227 @@ function foldNode(node, handlers, depth) {
|
|
|
1329
1625
|
* ```
|
|
1330
1626
|
*/
|
|
1331
1627
|
function rewriteDocument(document, rewrite) {
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
const
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1628
|
+
const stack = [{
|
|
1629
|
+
node: document,
|
|
1630
|
+
depth: -1,
|
|
1631
|
+
expanded: false,
|
|
1632
|
+
count: 0
|
|
1633
|
+
}];
|
|
1634
|
+
const values = [];
|
|
1635
|
+
while (stack.length > 0) {
|
|
1636
|
+
const frame = stack.pop();
|
|
1637
|
+
if (frame === void 0) continue;
|
|
1638
|
+
const current = frame.node;
|
|
1639
|
+
if (!frame.expanded) {
|
|
1640
|
+
if (current.element !== "document" && frame.depth >= 64) {
|
|
1641
|
+
values.push(current);
|
|
1642
|
+
continue;
|
|
1643
|
+
}
|
|
1644
|
+
const children = [];
|
|
1645
|
+
switch (current.element) {
|
|
1646
|
+
case "document":
|
|
1647
|
+
case "heading":
|
|
1648
|
+
case "paragraph":
|
|
1649
|
+
case "blockquote":
|
|
1650
|
+
case "listItem":
|
|
1651
|
+
case "emphasis":
|
|
1652
|
+
case "link":
|
|
1653
|
+
for (const child of current.children) if (child !== void 0) children.push(child);
|
|
1654
|
+
break;
|
|
1655
|
+
case "list":
|
|
1656
|
+
for (const child of current.items) if (child !== void 0) children.push(child);
|
|
1657
|
+
break;
|
|
1658
|
+
case "table":
|
|
1659
|
+
for (const cell of current.header) if (cell !== void 0) {
|
|
1660
|
+
for (const child of cell) if (child !== void 0) children.push(child);
|
|
1661
|
+
}
|
|
1662
|
+
for (const row of current.rows) if (row !== void 0) {
|
|
1663
|
+
for (const cell of row) if (cell !== void 0) {
|
|
1664
|
+
for (const child of cell) if (child !== void 0) children.push(child);
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
break;
|
|
1668
|
+
}
|
|
1669
|
+
stack.push({
|
|
1670
|
+
...frame,
|
|
1671
|
+
expanded: true,
|
|
1672
|
+
count: children.length
|
|
1673
|
+
});
|
|
1674
|
+
const depth = current.element === "document" ? 0 : frame.depth + 1;
|
|
1675
|
+
for (let index = children.length - 1; index >= 0; index -= 1) {
|
|
1676
|
+
const child = children[index];
|
|
1677
|
+
if (child !== void 0) stack.push({
|
|
1678
|
+
node: child,
|
|
1679
|
+
depth,
|
|
1680
|
+
expanded: false,
|
|
1681
|
+
count: 0
|
|
1682
|
+
});
|
|
1683
|
+
}
|
|
1684
|
+
continue;
|
|
1685
|
+
}
|
|
1686
|
+
const children = frame.count === 0 ? [] : values.splice(values.length - frame.count, frame.count);
|
|
1687
|
+
let rebuilt = current;
|
|
1688
|
+
switch (current.element) {
|
|
1689
|
+
case "document": {
|
|
1690
|
+
const blocks = [];
|
|
1691
|
+
let offset = 0;
|
|
1692
|
+
for (const block of current.children) {
|
|
1693
|
+
if (block === void 0) continue;
|
|
1694
|
+
const child = children[offset];
|
|
1695
|
+
blocks.push(child !== void 0 && isBlockNode(child) ? child : block);
|
|
1696
|
+
offset += 1;
|
|
1697
|
+
}
|
|
1698
|
+
const result = {
|
|
1699
|
+
element: "document",
|
|
1700
|
+
children: blocks
|
|
1701
|
+
};
|
|
1702
|
+
if (stack.length === 0) return result;
|
|
1703
|
+
values.push(result);
|
|
1704
|
+
continue;
|
|
1705
|
+
}
|
|
1706
|
+
case "heading":
|
|
1707
|
+
case "paragraph": {
|
|
1708
|
+
const inlines = [];
|
|
1709
|
+
let offset = 0;
|
|
1710
|
+
for (const inline of current.children) {
|
|
1711
|
+
if (inline === void 0) continue;
|
|
1712
|
+
const child = children[offset];
|
|
1713
|
+
inlines.push(child !== void 0 && isInlineNode(child) ? child : inline);
|
|
1714
|
+
offset += 1;
|
|
1715
|
+
}
|
|
1716
|
+
rebuilt = {
|
|
1717
|
+
...current,
|
|
1718
|
+
children: inlines
|
|
1719
|
+
};
|
|
1720
|
+
break;
|
|
1721
|
+
}
|
|
1722
|
+
case "blockquote": {
|
|
1723
|
+
const blocks = [];
|
|
1724
|
+
let offset = 0;
|
|
1725
|
+
for (const block of current.children) {
|
|
1726
|
+
if (block === void 0) continue;
|
|
1727
|
+
const child = children[offset];
|
|
1728
|
+
blocks.push(child !== void 0 && isBlockNode(child) ? child : block);
|
|
1729
|
+
offset += 1;
|
|
1730
|
+
}
|
|
1731
|
+
rebuilt = {
|
|
1732
|
+
...current,
|
|
1733
|
+
children: blocks
|
|
1734
|
+
};
|
|
1735
|
+
break;
|
|
1736
|
+
}
|
|
1737
|
+
case "listItem": {
|
|
1738
|
+
const blocks = [];
|
|
1739
|
+
let offset = 0;
|
|
1740
|
+
for (const block of current.children) {
|
|
1741
|
+
if (block === void 0) continue;
|
|
1742
|
+
const child = children[offset];
|
|
1743
|
+
blocks.push(child !== void 0 && isBlockNode(child) ? child : block);
|
|
1744
|
+
offset += 1;
|
|
1745
|
+
}
|
|
1746
|
+
rebuilt = {
|
|
1747
|
+
element: "listItem",
|
|
1748
|
+
children: blocks
|
|
1749
|
+
};
|
|
1750
|
+
break;
|
|
1751
|
+
}
|
|
1752
|
+
case "emphasis":
|
|
1753
|
+
case "link": {
|
|
1754
|
+
const inlines = [];
|
|
1755
|
+
let offset = 0;
|
|
1756
|
+
for (const inline of current.children) {
|
|
1757
|
+
if (inline === void 0) continue;
|
|
1758
|
+
const child = children[offset];
|
|
1759
|
+
inlines.push(child !== void 0 && isInlineNode(child) ? child : inline);
|
|
1760
|
+
offset += 1;
|
|
1761
|
+
}
|
|
1762
|
+
rebuilt = {
|
|
1763
|
+
...current,
|
|
1764
|
+
children: inlines
|
|
1765
|
+
};
|
|
1766
|
+
break;
|
|
1767
|
+
}
|
|
1768
|
+
case "list": {
|
|
1769
|
+
const items = [];
|
|
1770
|
+
let offset = 0;
|
|
1771
|
+
for (const item of current.items) {
|
|
1772
|
+
if (item === void 0) continue;
|
|
1773
|
+
const child = children[offset];
|
|
1774
|
+
items.push(child?.element === "listItem" ? child : item);
|
|
1775
|
+
offset += 1;
|
|
1776
|
+
}
|
|
1777
|
+
rebuilt = {
|
|
1778
|
+
...current,
|
|
1779
|
+
items
|
|
1780
|
+
};
|
|
1781
|
+
break;
|
|
1782
|
+
}
|
|
1783
|
+
case "table": {
|
|
1784
|
+
let offset = 0;
|
|
1785
|
+
const header = [];
|
|
1786
|
+
for (const cell of current.header) {
|
|
1787
|
+
if (cell === void 0) continue;
|
|
1788
|
+
const inlines = [];
|
|
1789
|
+
for (const inline of cell) {
|
|
1790
|
+
if (inline === void 0) continue;
|
|
1791
|
+
const child = children[offset];
|
|
1792
|
+
inlines.push(child !== void 0 && isInlineNode(child) ? child : inline);
|
|
1793
|
+
offset += 1;
|
|
1794
|
+
}
|
|
1795
|
+
header.push(inlines);
|
|
1796
|
+
}
|
|
1797
|
+
const rows = [];
|
|
1798
|
+
for (const row of current.rows) {
|
|
1799
|
+
if (row === void 0) continue;
|
|
1800
|
+
const cells = [];
|
|
1801
|
+
for (const cell of row) {
|
|
1802
|
+
if (cell === void 0) continue;
|
|
1803
|
+
const inlines = [];
|
|
1804
|
+
for (const inline of cell) {
|
|
1805
|
+
if (inline === void 0) continue;
|
|
1806
|
+
const child = children[offset];
|
|
1807
|
+
inlines.push(child !== void 0 && isInlineNode(child) ? child : inline);
|
|
1808
|
+
offset += 1;
|
|
1809
|
+
}
|
|
1810
|
+
cells.push(inlines);
|
|
1811
|
+
}
|
|
1812
|
+
rows.push(cells);
|
|
1813
|
+
}
|
|
1814
|
+
rebuilt = {
|
|
1815
|
+
...current,
|
|
1816
|
+
header,
|
|
1817
|
+
rows
|
|
1818
|
+
};
|
|
1819
|
+
break;
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1350
1822
|
const result = rewrite(rebuilt);
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
function rebuildInline(node, depth) {
|
|
1354
|
-
switch (node.element) {
|
|
1355
|
-
case "emphasis": return {
|
|
1356
|
-
...node,
|
|
1357
|
-
children: node.children.map((child) => rewriteInline(child, depth + 1))
|
|
1358
|
-
};
|
|
1359
|
-
case "link": return {
|
|
1360
|
-
...node,
|
|
1361
|
-
children: node.children.map((child) => rewriteInline(child, depth + 1))
|
|
1362
|
-
};
|
|
1823
|
+
let accepted = rebuilt;
|
|
1824
|
+
switch (current.element) {
|
|
1363
1825
|
case "text":
|
|
1364
|
-
case "
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
case "heading":
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
case "paragraph": return {
|
|
1374
|
-
...node,
|
|
1375
|
-
children: node.children.map((child) => rewriteInline(child, depth + 1))
|
|
1376
|
-
};
|
|
1377
|
-
case "blockquote": return {
|
|
1378
|
-
...node,
|
|
1379
|
-
children: node.children.map((child) => rewriteBlock(child, depth + 1))
|
|
1380
|
-
};
|
|
1381
|
-
case "list": return {
|
|
1382
|
-
...node,
|
|
1383
|
-
items: node.items.map((item) => rewriteItem(item, depth + 1))
|
|
1384
|
-
};
|
|
1385
|
-
case "table": return {
|
|
1386
|
-
...node,
|
|
1387
|
-
header: node.header.map((cell) => cell.map((inline) => rewriteInline(inline, depth + 1))),
|
|
1388
|
-
rows: node.rows.map((row) => row.map((cell) => cell.map((inline) => rewriteInline(inline, depth + 1))))
|
|
1389
|
-
};
|
|
1826
|
+
case "emphasis":
|
|
1827
|
+
case "codeSpan":
|
|
1828
|
+
case "link":
|
|
1829
|
+
if (isInlineNode(result)) accepted = result;
|
|
1830
|
+
break;
|
|
1831
|
+
case "heading":
|
|
1832
|
+
case "paragraph":
|
|
1833
|
+
case "list":
|
|
1834
|
+
case "table":
|
|
1390
1835
|
case "codeBlock":
|
|
1391
|
-
case "
|
|
1836
|
+
case "blockquote":
|
|
1837
|
+
case "thematicBreak":
|
|
1838
|
+
if (isBlockNode(result)) accepted = result;
|
|
1839
|
+
break;
|
|
1840
|
+
case "listItem":
|
|
1841
|
+
if (result.element === "listItem") accepted = result;
|
|
1842
|
+
break;
|
|
1392
1843
|
}
|
|
1844
|
+
values.push(accepted);
|
|
1393
1845
|
}
|
|
1394
1846
|
return {
|
|
1395
1847
|
element: "document",
|
|
1396
|
-
children: document.children
|
|
1848
|
+
children: [...document.children]
|
|
1397
1849
|
};
|
|
1398
1850
|
}
|
|
1399
1851
|
/**
|
|
@@ -1418,26 +1870,55 @@ function rewriteDocument(document, rewrite) {
|
|
|
1418
1870
|
* ```
|
|
1419
1871
|
*/
|
|
1420
1872
|
function flattenText(node) {
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1873
|
+
const stack = [{
|
|
1874
|
+
node,
|
|
1875
|
+
depth: 0
|
|
1876
|
+
}];
|
|
1877
|
+
let value = "";
|
|
1878
|
+
while (stack.length > 0) {
|
|
1879
|
+
const frame = stack.pop();
|
|
1880
|
+
if (frame === void 0 || frame.depth >= 64) continue;
|
|
1881
|
+
const children = [];
|
|
1882
|
+
switch (frame.node.element) {
|
|
1883
|
+
case "text":
|
|
1884
|
+
case "codeSpan":
|
|
1885
|
+
value += frame.node.value;
|
|
1886
|
+
break;
|
|
1887
|
+
case "codeBlock":
|
|
1888
|
+
value += frame.node.code;
|
|
1889
|
+
break;
|
|
1427
1890
|
case "document":
|
|
1428
1891
|
case "heading":
|
|
1429
1892
|
case "paragraph":
|
|
1430
1893
|
case "blockquote":
|
|
1431
1894
|
case "listItem":
|
|
1432
1895
|
case "emphasis":
|
|
1433
|
-
case "link":
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
case "
|
|
1437
|
-
|
|
1896
|
+
case "link":
|
|
1897
|
+
for (const child of frame.node.children) if (child !== void 0) children.push(child);
|
|
1898
|
+
break;
|
|
1899
|
+
case "list":
|
|
1900
|
+
for (const child of frame.node.items) if (child !== void 0) children.push(child);
|
|
1901
|
+
break;
|
|
1902
|
+
case "table":
|
|
1903
|
+
for (const cell of frame.node.header) if (cell !== void 0) {
|
|
1904
|
+
for (const child of cell) if (child !== void 0) children.push(child);
|
|
1905
|
+
}
|
|
1906
|
+
for (const row of frame.node.rows) if (row !== void 0) {
|
|
1907
|
+
for (const cell of row) if (cell !== void 0) {
|
|
1908
|
+
for (const child of cell) if (child !== void 0) children.push(child);
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
break;
|
|
1912
|
+
}
|
|
1913
|
+
for (let index = children.length - 1; index >= 0; index -= 1) {
|
|
1914
|
+
const child = children[index];
|
|
1915
|
+
if (child !== void 0) stack.push({
|
|
1916
|
+
node: child,
|
|
1917
|
+
depth: frame.depth + 1
|
|
1918
|
+
});
|
|
1438
1919
|
}
|
|
1439
1920
|
}
|
|
1440
|
-
return
|
|
1921
|
+
return value;
|
|
1441
1922
|
}
|
|
1442
1923
|
//#endregion
|
|
1443
1924
|
//#region src/core/parsers.ts
|
|
@@ -1596,6 +2077,51 @@ function collectList(lines, start, depth) {
|
|
|
1596
2077
|
const startOrdinal = first?.start ?? 1;
|
|
1597
2078
|
const topIndent = first?.indent ?? 0;
|
|
1598
2079
|
const items = [];
|
|
2080
|
+
const chain = [];
|
|
2081
|
+
let nested = true;
|
|
2082
|
+
for (let cursor = start; cursor < lines.length; cursor += 1) {
|
|
2083
|
+
const parsed = extractListItem(lines[cursor] ?? "");
|
|
2084
|
+
const previous = chain[chain.length - 1];
|
|
2085
|
+
if (parsed === void 0 || previous !== void 0 && (previous.content.length > 0 || parsed.indent !== previous.marker)) {
|
|
2086
|
+
nested = false;
|
|
2087
|
+
break;
|
|
2088
|
+
}
|
|
2089
|
+
chain.push(parsed);
|
|
2090
|
+
}
|
|
2091
|
+
const remaining = 64 - depth;
|
|
2092
|
+
if (nested && remaining > 0 && chain.length > remaining) {
|
|
2093
|
+
const terminal = chain[remaining - 1];
|
|
2094
|
+
if (terminal !== void 0) {
|
|
2095
|
+
const source = [terminal.content];
|
|
2096
|
+
for (let cursor = start + remaining; cursor < lines.length; cursor += 1) source.push((lines[cursor] ?? "").slice(terminal.marker));
|
|
2097
|
+
let children = [{
|
|
2098
|
+
element: "paragraph",
|
|
2099
|
+
children: [{
|
|
2100
|
+
element: "text",
|
|
2101
|
+
value: source.join("\n")
|
|
2102
|
+
}]
|
|
2103
|
+
}];
|
|
2104
|
+
let node;
|
|
2105
|
+
for (let cursor = remaining - 1; cursor >= 0; cursor -= 1) {
|
|
2106
|
+
const parsed = chain[cursor];
|
|
2107
|
+
if (parsed === void 0) continue;
|
|
2108
|
+
node = {
|
|
2109
|
+
element: "list",
|
|
2110
|
+
ordered: parsed.ordered,
|
|
2111
|
+
start: parsed.start,
|
|
2112
|
+
items: [{
|
|
2113
|
+
element: "listItem",
|
|
2114
|
+
children
|
|
2115
|
+
}]
|
|
2116
|
+
};
|
|
2117
|
+
children = [node];
|
|
2118
|
+
}
|
|
2119
|
+
if (node !== void 0) return {
|
|
2120
|
+
node,
|
|
2121
|
+
next: lines.length
|
|
2122
|
+
};
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
1599
2125
|
let index = start;
|
|
1600
2126
|
while (index < lines.length) {
|
|
1601
2127
|
const parsed = extractListItem(lines[index] ?? "");
|
|
@@ -1878,7 +2404,12 @@ var Markdown = class Markdown {
|
|
|
1878
2404
|
let index = 0;
|
|
1879
2405
|
return new ReadableStream({ pull(controller) {
|
|
1880
2406
|
if (index < blocks.length) {
|
|
1881
|
-
|
|
2407
|
+
const block = blocks[index];
|
|
2408
|
+
if (block === void 0) {
|
|
2409
|
+
controller.close();
|
|
2410
|
+
return;
|
|
2411
|
+
}
|
|
2412
|
+
controller.enqueue(block);
|
|
1882
2413
|
index += 1;
|
|
1883
2414
|
} else controller.close();
|
|
1884
2415
|
} });
|