markdown-codec 6.7.5 → 6.7.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/block/block.cjs +19 -37
- package/dist/block/block.js +20 -38
- package/dist/block/node.cjs +3 -3
- package/dist/block/node.d.cts +2 -2
- package/dist/block/node.d.ts +2 -2
- package/dist/block/node.js +3 -3
- package/dist/codec.d.cts +28 -28
- package/dist/codec.d.ts +28 -28
- package/dist/emit/emit.cjs +24 -26
- package/dist/emit/emit.js +24 -26
- package/dist/emit/inline.cjs +18 -12
- package/dist/emit/inline.js +18 -12
- package/dist/html/html-table.cjs +14 -22
- package/dist/html/html-table.js +14 -22
- package/dist/image/image.cjs +8 -8
- package/dist/image/image.js +8 -8
- package/dist/inline/delimiter.cjs +0 -4
- package/dist/inline/delimiter.d.cts +1 -2
- package/dist/inline/delimiter.d.ts +1 -2
- package/dist/inline/delimiter.js +1 -4
- package/dist/inline/gfm-autolink.cjs +20 -19
- package/dist/inline/gfm-autolink.js +20 -19
- package/dist/inline/inline.cjs +29 -39
- package/dist/inline/inline.js +30 -40
- package/dist/lower/lower.cjs +7 -10
- package/dist/lower/lower.js +7 -10
- package/package.json +1 -1
package/dist/emit/emit.js
CHANGED
|
@@ -31,6 +31,10 @@ function renderSetextHeading(level, text) {
|
|
|
31
31
|
const [firstLine] = splitLines(text, LINE_ENDING_PATTERN);
|
|
32
32
|
return `${text}\n${underlineChar.repeat(Math.max(MIN_SETEXT_UNDERLINE_LENGTH, firstLine.length))}`;
|
|
33
33
|
}
|
|
34
|
+
function renderAtxHeading(level, text) {
|
|
35
|
+
const collapsed = text.replace(ESCAPED_HARD_BREAK_PATTERN, " ").split(LINE_ENDING_PATTERN).join(" ");
|
|
36
|
+
return `${"#".repeat(level)} ${collapsed}`;
|
|
37
|
+
}
|
|
34
38
|
const MIN_CODE_FENCE_LENGTH = 3;
|
|
35
39
|
function longestRunLength(text, char) {
|
|
36
40
|
let longest = 0;
|
|
@@ -64,7 +68,7 @@ function firstContentLineIndex(text) {
|
|
|
64
68
|
}
|
|
65
69
|
function leadingIndentReachesCodeThreshold(line) {
|
|
66
70
|
let column = 0;
|
|
67
|
-
while (
|
|
71
|
+
while (line[column] === " ") column += 1;
|
|
68
72
|
if (column >= 4) return true;
|
|
69
73
|
return line[column] === " ";
|
|
70
74
|
}
|
|
@@ -83,18 +87,16 @@ function tableDelimiterRowPromotesPrecedingLine(line, precedingLine) {
|
|
|
83
87
|
return parseTableDelimiterRow(cursor.restFromNextNonspace())?.length === splitTableRow(precedingLine).length;
|
|
84
88
|
}
|
|
85
89
|
function unsafeSetextBreakReason(text) {
|
|
86
|
-
let sawContentLine = false;
|
|
87
90
|
let leadingBlankLines = 0;
|
|
88
|
-
let precedingLine
|
|
91
|
+
let precedingLine;
|
|
89
92
|
for (const line of text.split(LINE_ENDING_PATTERN)) {
|
|
90
93
|
const isBlank = BLANK_OR_WHITESPACE_ONLY_LINE.test(line);
|
|
91
|
-
if (
|
|
94
|
+
if (precedingLine === void 0) {
|
|
92
95
|
if (isBlank) {
|
|
93
96
|
leadingBlankLines += 1;
|
|
94
97
|
if (leadingBlankLines > MAX_LEADING_BLANK_LINES_FOR_SETEXT) return "blank-line";
|
|
95
98
|
continue;
|
|
96
99
|
}
|
|
97
|
-
sawContentLine = true;
|
|
98
100
|
if (leadingIndentReachesCodeThreshold(line)) return "leading-indentation";
|
|
99
101
|
if (interruptsSetextParagraph(line, true)) return "interrupting-line";
|
|
100
102
|
precedingLine = line;
|
|
@@ -104,7 +106,7 @@ function unsafeSetextBreakReason(text) {
|
|
|
104
106
|
if (interruptsSetextParagraph(line, false) || tableDelimiterRowPromotesPrecedingLine(line, precedingLine)) return "interrupting-line";
|
|
105
107
|
precedingLine = line;
|
|
106
108
|
}
|
|
107
|
-
return
|
|
109
|
+
return precedingLine === void 0 ? "blank-line" : void 0;
|
|
108
110
|
}
|
|
109
111
|
function embedsUnsafeBreakForSetext(text) {
|
|
110
112
|
return unsafeSetextBreakReason(text) !== void 0;
|
|
@@ -177,18 +179,14 @@ function renderParagraphBody(paragraph, context) {
|
|
|
177
179
|
severity: "info",
|
|
178
180
|
message: unsafeSetextDiagnosticMessage(level, unsafeSetextReason, embedsLineBreak)
|
|
179
181
|
});
|
|
180
|
-
|
|
181
|
-
return `${"#".repeat(level)} ${text}`;
|
|
182
|
+
return renderAtxHeading(level, text);
|
|
182
183
|
}
|
|
183
|
-
if (embedsLineBreak) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return `${"#".repeat(level)} ${text.replace(ESCAPED_HARD_BREAK_PATTERN, " ").split(LINE_ENDING_PATTERN).join(" ")}`;
|
|
190
|
-
}
|
|
191
|
-
return `${"#".repeat(level)} ${text}`;
|
|
184
|
+
if (embedsLineBreak) context.sink({
|
|
185
|
+
code: 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 renderAtxHeading(level, text);
|
|
192
190
|
}
|
|
193
191
|
return emitRuns(paragraph.runs, context, paragraph.constructs);
|
|
194
192
|
}
|
|
@@ -270,12 +268,12 @@ function firstBlockCheckbox(first, taskNumId) {
|
|
|
270
268
|
checkboxText: "",
|
|
271
269
|
strippedFirstBlock: void 0
|
|
272
270
|
};
|
|
273
|
-
const leading = first.block.runs[0]?.text
|
|
274
|
-
if (leading
|
|
271
|
+
const leading = first.block.runs[0]?.text;
|
|
272
|
+
if (leading?.startsWith(`☒ `) === true) return {
|
|
275
273
|
checkboxText: "[x] ",
|
|
276
274
|
strippedFirstBlock: stripCheckboxRun(first.block)
|
|
277
275
|
};
|
|
278
|
-
if (leading
|
|
276
|
+
if (leading?.startsWith(`☐ `) === true) return {
|
|
279
277
|
checkboxText: "[ ] ",
|
|
280
278
|
strippedFirstBlock: stripCheckboxRun(first.block)
|
|
281
279
|
};
|
|
@@ -412,7 +410,7 @@ function renderListRegion(items, context) {
|
|
|
412
410
|
const { checkboxText, strippedFirstBlock } = firstBlockCheckbox(first, info?.task === true);
|
|
413
411
|
const marker = renderListItemMarker(numId, info, glyph, checkboxText, context);
|
|
414
412
|
const indent = " ".repeat(marker.bareLength);
|
|
415
|
-
let text =
|
|
413
|
+
let text = marker.full;
|
|
416
414
|
let renderedFirstLine = false;
|
|
417
415
|
let previousStyleId;
|
|
418
416
|
for (const segment of segments) {
|
|
@@ -426,7 +424,7 @@ function renderListRegion(items, context) {
|
|
|
426
424
|
for (const block of segment.blocks) {
|
|
427
425
|
if (!renderedFirstLine) {
|
|
428
426
|
const [firstLine, ...restLines] = splitLines(listRegionItemBody(block, context, strippedFirstBlock), "\n");
|
|
429
|
-
text
|
|
427
|
+
text += [firstLine, ...restLines.map((line) => `${indent}${line}`)].join("\n");
|
|
430
428
|
renderedFirstLine = true;
|
|
431
429
|
previousStyleId = lastStyleIdOfRegionItem(block);
|
|
432
430
|
continue;
|
|
@@ -447,9 +445,8 @@ function renderListRegion(items, context) {
|
|
|
447
445
|
for (const [partIndex, part] of parts.entries()) {
|
|
448
446
|
if (partIndex > 0) {
|
|
449
447
|
const previous = parts[partIndex - 1];
|
|
450
|
-
const
|
|
451
|
-
|
|
452
|
-
out += sameList && !loose ? "\n" : "\n\n";
|
|
448
|
+
const continuesTightly = previous.numId === part.numId && (previous.numId === void 0 || parseListNumId(previous.numId)?.loose !== true);
|
|
449
|
+
out += continuesTightly ? "\n" : "\n\n";
|
|
453
450
|
}
|
|
454
451
|
out += part.text;
|
|
455
452
|
}
|
|
@@ -458,10 +455,11 @@ function renderListRegion(items, context) {
|
|
|
458
455
|
function isConstructItem(item) {
|
|
459
456
|
return "descriptor" in item;
|
|
460
457
|
}
|
|
458
|
+
const UNINDENTED_PT = 0;
|
|
461
459
|
function isMaterialisedDivision(item) {
|
|
462
460
|
return item.descriptor.kind === "division" && item.children.every((child) => {
|
|
463
461
|
if (isConstructItem(child)) return true;
|
|
464
|
-
return child.block.kind !== "paragraph" || child.block.indentLeftPt
|
|
462
|
+
return child.block.kind !== "paragraph" || (child.block.indentLeftPt ?? UNINDENTED_PT) >= 36;
|
|
465
463
|
});
|
|
466
464
|
}
|
|
467
465
|
function groupConstructItems(blocks, start) {
|
package/dist/emit/inline.cjs
CHANGED
|
@@ -39,11 +39,12 @@ const ESCAPE_CHARS = /* @__PURE__ */ new Set([
|
|
|
39
39
|
function escapeMarkdownText(text) {
|
|
40
40
|
let out = "";
|
|
41
41
|
let index = 0;
|
|
42
|
-
|
|
43
|
-
const char = text
|
|
42
|
+
for (;;) {
|
|
43
|
+
const char = text[index];
|
|
44
|
+
if (char === void 0) break;
|
|
44
45
|
if (char === "\n" || char === "\r") {
|
|
45
46
|
out += "\\\n";
|
|
46
|
-
index += char === "\r" && text
|
|
47
|
+
index += char === "\r" && text[index + 1] === "\n" ? 2 : 1;
|
|
47
48
|
continue;
|
|
48
49
|
}
|
|
49
50
|
if (ESCAPE_CHARS.has(char)) {
|
|
@@ -64,9 +65,8 @@ function renderCodeSpan(text) {
|
|
|
64
65
|
longestBacktickRun = Math.max(longestBacktickRun, current);
|
|
65
66
|
} else current = 0;
|
|
66
67
|
const fence = "`".repeat(longestBacktickRun + 1);
|
|
67
|
-
const isAllSpaces = text.length > 0 && text.trim().length === 0;
|
|
68
68
|
const risksFenceCollision = text.startsWith("`") || text.endsWith("`");
|
|
69
|
-
const wouldBeStrippedOnReparse =
|
|
69
|
+
const wouldBeStrippedOnReparse = text.startsWith(" ") && text.endsWith(" ") && text.trim().length > 0;
|
|
70
70
|
return risksFenceCollision || wouldBeStrippedOnReparse ? `${fence} ${text} ${fence}` : `${fence}${text}${fence}`;
|
|
71
71
|
}
|
|
72
72
|
function footnoteReferenceAt(constructs, index) {
|
|
@@ -102,12 +102,11 @@ function styleActive(run, key) {
|
|
|
102
102
|
}
|
|
103
103
|
const WORD_CHAR_PATTERN = /[\p{L}\p{N}]/u;
|
|
104
104
|
function isIntrawordRisk(body) {
|
|
105
|
-
if (body.length === 0) return false;
|
|
106
105
|
return WORD_CHAR_PATTERN.test(body.charAt(0)) || WORD_CHAR_PATTERN.test(body.charAt(body.length - 1));
|
|
107
106
|
}
|
|
108
107
|
function hasMarkerConflict(body, candidate, precedingText) {
|
|
109
108
|
if (candidate === "_" && isIntrawordRisk(body)) return true;
|
|
110
|
-
if (body.
|
|
109
|
+
if (body.startsWith(candidate) || body.endsWith(candidate)) return true;
|
|
111
110
|
return precedingText.endsWith(candidate);
|
|
112
111
|
}
|
|
113
112
|
function pickEmphasisMarker(body, configured, precedingText) {
|
|
@@ -135,7 +134,7 @@ function groupCount(runs, key) {
|
|
|
135
134
|
function pickSplitKey(runs, remaining) {
|
|
136
135
|
let best = remaining[0];
|
|
137
136
|
let bestCount = groupCount(runs, best);
|
|
138
|
-
for (const key of remaining
|
|
137
|
+
for (const key of remaining) {
|
|
139
138
|
const count = groupCount(runs, key);
|
|
140
139
|
if (count < bestCount) {
|
|
141
140
|
best = key;
|
|
@@ -150,7 +149,7 @@ function renderNestedStyles(runs, remainingKeys, context, base, constructs) {
|
|
|
150
149
|
const rest = remainingKeys.filter((candidate) => candidate !== key);
|
|
151
150
|
let out = "";
|
|
152
151
|
let index = 0;
|
|
153
|
-
|
|
152
|
+
for (;;) {
|
|
154
153
|
const current = runs[index];
|
|
155
154
|
if (current === void 0) break;
|
|
156
155
|
const active = styleActive(current, key);
|
|
@@ -186,19 +185,26 @@ function linkTitleCovering(constructs, start, end) {
|
|
|
186
185
|
function emitRuns(runs, context, constructs) {
|
|
187
186
|
let out = "";
|
|
188
187
|
let index = 0;
|
|
189
|
-
|
|
188
|
+
for (;;) {
|
|
190
189
|
const run = runs[index];
|
|
191
190
|
if (run === void 0) break;
|
|
192
191
|
if (run.hyperlink === void 0) {
|
|
193
192
|
let end = index + 1;
|
|
194
|
-
|
|
193
|
+
for (;;) {
|
|
194
|
+
const next = runs[end];
|
|
195
|
+
if (next === void 0 || next.hyperlink !== void 0) break;
|
|
196
|
+
end += 1;
|
|
197
|
+
}
|
|
195
198
|
out += renderNestedStyles(runs.slice(index, end), STYLE_KEYS, context, index, constructs);
|
|
196
199
|
index = end;
|
|
197
200
|
continue;
|
|
198
201
|
}
|
|
199
202
|
const hyperlink = run.hyperlink;
|
|
200
203
|
let groupEnd = index + 1;
|
|
201
|
-
|
|
204
|
+
for (;;) {
|
|
205
|
+
if (runs[groupEnd]?.hyperlink !== hyperlink) break;
|
|
206
|
+
groupEnd += 1;
|
|
207
|
+
}
|
|
202
208
|
const group = runs.slice(index, groupEnd);
|
|
203
209
|
if (group.length > 1) context.sink({
|
|
204
210
|
code: require_diagnostics_diagnostics.MarkdownDiagnosticCodes.ADJACENT_LINKS_MERGED,
|
package/dist/emit/inline.js
CHANGED
|
@@ -38,11 +38,12 @@ const ESCAPE_CHARS = /* @__PURE__ */ new Set([
|
|
|
38
38
|
function escapeMarkdownText(text) {
|
|
39
39
|
let out = "";
|
|
40
40
|
let index = 0;
|
|
41
|
-
|
|
42
|
-
const char = text
|
|
41
|
+
for (;;) {
|
|
42
|
+
const char = text[index];
|
|
43
|
+
if (char === void 0) break;
|
|
43
44
|
if (char === "\n" || char === "\r") {
|
|
44
45
|
out += "\\\n";
|
|
45
|
-
index += char === "\r" && text
|
|
46
|
+
index += char === "\r" && text[index + 1] === "\n" ? 2 : 1;
|
|
46
47
|
continue;
|
|
47
48
|
}
|
|
48
49
|
if (ESCAPE_CHARS.has(char)) {
|
|
@@ -63,9 +64,8 @@ function renderCodeSpan(text) {
|
|
|
63
64
|
longestBacktickRun = Math.max(longestBacktickRun, current);
|
|
64
65
|
} else current = 0;
|
|
65
66
|
const fence = "`".repeat(longestBacktickRun + 1);
|
|
66
|
-
const isAllSpaces = text.length > 0 && text.trim().length === 0;
|
|
67
67
|
const risksFenceCollision = text.startsWith("`") || text.endsWith("`");
|
|
68
|
-
const wouldBeStrippedOnReparse =
|
|
68
|
+
const wouldBeStrippedOnReparse = text.startsWith(" ") && text.endsWith(" ") && text.trim().length > 0;
|
|
69
69
|
return risksFenceCollision || wouldBeStrippedOnReparse ? `${fence} ${text} ${fence}` : `${fence}${text}${fence}`;
|
|
70
70
|
}
|
|
71
71
|
function footnoteReferenceAt(constructs, index) {
|
|
@@ -101,12 +101,11 @@ function styleActive(run, key) {
|
|
|
101
101
|
}
|
|
102
102
|
const WORD_CHAR_PATTERN = /[\p{L}\p{N}]/u;
|
|
103
103
|
function isIntrawordRisk(body) {
|
|
104
|
-
if (body.length === 0) return false;
|
|
105
104
|
return WORD_CHAR_PATTERN.test(body.charAt(0)) || WORD_CHAR_PATTERN.test(body.charAt(body.length - 1));
|
|
106
105
|
}
|
|
107
106
|
function hasMarkerConflict(body, candidate, precedingText) {
|
|
108
107
|
if (candidate === "_" && isIntrawordRisk(body)) return true;
|
|
109
|
-
if (body.
|
|
108
|
+
if (body.startsWith(candidate) || body.endsWith(candidate)) return true;
|
|
110
109
|
return precedingText.endsWith(candidate);
|
|
111
110
|
}
|
|
112
111
|
function pickEmphasisMarker(body, configured, precedingText) {
|
|
@@ -134,7 +133,7 @@ function groupCount(runs, key) {
|
|
|
134
133
|
function pickSplitKey(runs, remaining) {
|
|
135
134
|
let best = remaining[0];
|
|
136
135
|
let bestCount = groupCount(runs, best);
|
|
137
|
-
for (const key of remaining
|
|
136
|
+
for (const key of remaining) {
|
|
138
137
|
const count = groupCount(runs, key);
|
|
139
138
|
if (count < bestCount) {
|
|
140
139
|
best = key;
|
|
@@ -149,7 +148,7 @@ function renderNestedStyles(runs, remainingKeys, context, base, constructs) {
|
|
|
149
148
|
const rest = remainingKeys.filter((candidate) => candidate !== key);
|
|
150
149
|
let out = "";
|
|
151
150
|
let index = 0;
|
|
152
|
-
|
|
151
|
+
for (;;) {
|
|
153
152
|
const current = runs[index];
|
|
154
153
|
if (current === void 0) break;
|
|
155
154
|
const active = styleActive(current, key);
|
|
@@ -185,19 +184,26 @@ function linkTitleCovering(constructs, start, end) {
|
|
|
185
184
|
function emitRuns(runs, context, constructs) {
|
|
186
185
|
let out = "";
|
|
187
186
|
let index = 0;
|
|
188
|
-
|
|
187
|
+
for (;;) {
|
|
189
188
|
const run = runs[index];
|
|
190
189
|
if (run === void 0) break;
|
|
191
190
|
if (run.hyperlink === void 0) {
|
|
192
191
|
let end = index + 1;
|
|
193
|
-
|
|
192
|
+
for (;;) {
|
|
193
|
+
const next = runs[end];
|
|
194
|
+
if (next === void 0 || next.hyperlink !== void 0) break;
|
|
195
|
+
end += 1;
|
|
196
|
+
}
|
|
194
197
|
out += renderNestedStyles(runs.slice(index, end), STYLE_KEYS, context, index, constructs);
|
|
195
198
|
index = end;
|
|
196
199
|
continue;
|
|
197
200
|
}
|
|
198
201
|
const hyperlink = run.hyperlink;
|
|
199
202
|
let groupEnd = index + 1;
|
|
200
|
-
|
|
203
|
+
for (;;) {
|
|
204
|
+
if (runs[groupEnd]?.hyperlink !== hyperlink) break;
|
|
205
|
+
groupEnd += 1;
|
|
206
|
+
}
|
|
201
207
|
const group = runs.slice(index, groupEnd);
|
|
202
208
|
if (group.length > 1) context.sink({
|
|
203
209
|
code: MarkdownDiagnosticCodes.ADJACENT_LINKS_MERGED,
|
package/dist/html/html-table.cjs
CHANGED
|
@@ -5,25 +5,21 @@ let document_schema_js = require("document-schema.js");
|
|
|
5
5
|
//#region src/html/html-table.ts
|
|
6
6
|
function findBalancedClose(text, openEnd, tagNames) {
|
|
7
7
|
const names = tagNames.join("|");
|
|
8
|
-
const
|
|
9
|
-
const closePattern = new RegExp(`</(?:${names})\\s*>`, "gi");
|
|
8
|
+
const tagPattern = new RegExp(`</(?:${names})\\s*>|<(?:${names})(?=[\\s/>])`, "gi");
|
|
10
9
|
let depth = 1;
|
|
11
10
|
let pos = openEnd;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (
|
|
18
|
-
if (openMatch !== null && openMatch.index < closeMatch.index) {
|
|
11
|
+
for (;;) {
|
|
12
|
+
tagPattern.lastIndex = pos;
|
|
13
|
+
const match = tagPattern.exec(text);
|
|
14
|
+
if (match === null) return;
|
|
15
|
+
pos = match.index + match[0].length;
|
|
16
|
+
if (!match[0].startsWith("</")) {
|
|
19
17
|
depth += 1;
|
|
20
|
-
pos = openMatch.index + openMatch[0].length;
|
|
21
18
|
continue;
|
|
22
19
|
}
|
|
23
20
|
depth -= 1;
|
|
24
|
-
pos = closeMatch.index + closeMatch[0].length;
|
|
25
21
|
if (depth === 0) return {
|
|
26
|
-
start:
|
|
22
|
+
start: match.index,
|
|
27
23
|
end: pos
|
|
28
24
|
};
|
|
29
25
|
}
|
|
@@ -37,7 +33,7 @@ function extractTopLevelElements(text, tagNames) {
|
|
|
37
33
|
const match = openPattern.exec(text);
|
|
38
34
|
if (match === null) break;
|
|
39
35
|
if (text.slice(pos, match.index).trim().length > 0) return;
|
|
40
|
-
const attrs = match[1]
|
|
36
|
+
const attrs = match[1];
|
|
41
37
|
const openEnd = match.index + match[0].length;
|
|
42
38
|
const close = findBalancedClose(text, openEnd, tagNames);
|
|
43
39
|
if (close === void 0) return;
|
|
@@ -136,15 +132,15 @@ function parseInlineHtml(text, style) {
|
|
|
136
132
|
pushPlainRun(runs, rest, style);
|
|
137
133
|
return runs;
|
|
138
134
|
}
|
|
139
|
-
pushPlainRun(runs, rest.slice(0, match.index), style);
|
|
140
135
|
const tagName = match[1].toLowerCase();
|
|
141
|
-
const attrs = match[2]
|
|
136
|
+
const attrs = match[2];
|
|
142
137
|
const openEnd = pos + match.index + match[0].length;
|
|
143
138
|
const close = findBalancedClose(text, openEnd, [tagName]);
|
|
144
139
|
if (close === void 0) {
|
|
145
140
|
pushPlainRun(runs, rest, style);
|
|
146
141
|
return runs;
|
|
147
142
|
}
|
|
143
|
+
pushPlainRun(runs, rest.slice(0, match.index), style);
|
|
148
144
|
runs.push(...parseInlineHtml(text.slice(openEnd, close.start), applyTagStyle(style, tagName, attrs)));
|
|
149
145
|
pos = close.end;
|
|
150
146
|
}
|
|
@@ -168,12 +164,10 @@ function parseHtmlImage(piece) {
|
|
|
168
164
|
};
|
|
169
165
|
}
|
|
170
166
|
function parseCellBlocks(inner, contentWidthPt) {
|
|
171
|
-
const
|
|
172
|
-
if (trimmed.length === 0) return [];
|
|
173
|
-
const nestedTable = parseWholeTable(trimmed, contentWidthPt);
|
|
167
|
+
const nestedTable = parseWholeTable(inner, contentWidthPt);
|
|
174
168
|
if (nestedTable !== void 0) return [nestedTable];
|
|
175
169
|
const blocks = [];
|
|
176
|
-
for (const segment of
|
|
170
|
+
for (const segment of inner.split(/<br\s*\/?>/i)) {
|
|
177
171
|
const piece = segment.trim();
|
|
178
172
|
if (piece.length === 0) continue;
|
|
179
173
|
const image = parseHtmlImage(piece);
|
|
@@ -235,9 +229,7 @@ function parseWholeTable(text, contentWidthPt) {
|
|
|
235
229
|
return rows === void 0 ? void 0 : buildContentTable(rows, contentWidthPt);
|
|
236
230
|
}
|
|
237
231
|
function parseHtmlTable(literal, contentWidthPt) {
|
|
238
|
-
|
|
239
|
-
if (!/^<table\b/i.test(trimmed)) return;
|
|
240
|
-
return parseWholeTable(trimmed, contentWidthPt);
|
|
232
|
+
return parseWholeTable(literal, contentWidthPt);
|
|
241
233
|
}
|
|
242
234
|
//#endregion
|
|
243
235
|
exports.parseHtmlTable = parseHtmlTable;
|
package/dist/html/html-table.js
CHANGED
|
@@ -4,25 +4,21 @@ import { rgbHexToColor } from "document-schema.js";
|
|
|
4
4
|
//#region src/html/html-table.ts
|
|
5
5
|
function findBalancedClose(text, openEnd, tagNames) {
|
|
6
6
|
const names = tagNames.join("|");
|
|
7
|
-
const
|
|
8
|
-
const closePattern = new RegExp(`</(?:${names})\\s*>`, "gi");
|
|
7
|
+
const tagPattern = new RegExp(`</(?:${names})\\s*>|<(?:${names})(?=[\\s/>])`, "gi");
|
|
9
8
|
let depth = 1;
|
|
10
9
|
let pos = openEnd;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (
|
|
17
|
-
if (openMatch !== null && openMatch.index < closeMatch.index) {
|
|
10
|
+
for (;;) {
|
|
11
|
+
tagPattern.lastIndex = pos;
|
|
12
|
+
const match = tagPattern.exec(text);
|
|
13
|
+
if (match === null) return;
|
|
14
|
+
pos = match.index + match[0].length;
|
|
15
|
+
if (!match[0].startsWith("</")) {
|
|
18
16
|
depth += 1;
|
|
19
|
-
pos = openMatch.index + openMatch[0].length;
|
|
20
17
|
continue;
|
|
21
18
|
}
|
|
22
19
|
depth -= 1;
|
|
23
|
-
pos = closeMatch.index + closeMatch[0].length;
|
|
24
20
|
if (depth === 0) return {
|
|
25
|
-
start:
|
|
21
|
+
start: match.index,
|
|
26
22
|
end: pos
|
|
27
23
|
};
|
|
28
24
|
}
|
|
@@ -36,7 +32,7 @@ function extractTopLevelElements(text, tagNames) {
|
|
|
36
32
|
const match = openPattern.exec(text);
|
|
37
33
|
if (match === null) break;
|
|
38
34
|
if (text.slice(pos, match.index).trim().length > 0) return;
|
|
39
|
-
const attrs = match[1]
|
|
35
|
+
const attrs = match[1];
|
|
40
36
|
const openEnd = match.index + match[0].length;
|
|
41
37
|
const close = findBalancedClose(text, openEnd, tagNames);
|
|
42
38
|
if (close === void 0) return;
|
|
@@ -135,15 +131,15 @@ function parseInlineHtml(text, style) {
|
|
|
135
131
|
pushPlainRun(runs, rest, style);
|
|
136
132
|
return runs;
|
|
137
133
|
}
|
|
138
|
-
pushPlainRun(runs, rest.slice(0, match.index), style);
|
|
139
134
|
const tagName = match[1].toLowerCase();
|
|
140
|
-
const attrs = match[2]
|
|
135
|
+
const attrs = match[2];
|
|
141
136
|
const openEnd = pos + match.index + match[0].length;
|
|
142
137
|
const close = findBalancedClose(text, openEnd, [tagName]);
|
|
143
138
|
if (close === void 0) {
|
|
144
139
|
pushPlainRun(runs, rest, style);
|
|
145
140
|
return runs;
|
|
146
141
|
}
|
|
142
|
+
pushPlainRun(runs, rest.slice(0, match.index), style);
|
|
147
143
|
runs.push(...parseInlineHtml(text.slice(openEnd, close.start), applyTagStyle(style, tagName, attrs)));
|
|
148
144
|
pos = close.end;
|
|
149
145
|
}
|
|
@@ -167,12 +163,10 @@ function parseHtmlImage(piece) {
|
|
|
167
163
|
};
|
|
168
164
|
}
|
|
169
165
|
function parseCellBlocks(inner, contentWidthPt) {
|
|
170
|
-
const
|
|
171
|
-
if (trimmed.length === 0) return [];
|
|
172
|
-
const nestedTable = parseWholeTable(trimmed, contentWidthPt);
|
|
166
|
+
const nestedTable = parseWholeTable(inner, contentWidthPt);
|
|
173
167
|
if (nestedTable !== void 0) return [nestedTable];
|
|
174
168
|
const blocks = [];
|
|
175
|
-
for (const segment of
|
|
169
|
+
for (const segment of inner.split(/<br\s*\/?>/i)) {
|
|
176
170
|
const piece = segment.trim();
|
|
177
171
|
if (piece.length === 0) continue;
|
|
178
172
|
const image = parseHtmlImage(piece);
|
|
@@ -234,9 +228,7 @@ function parseWholeTable(text, contentWidthPt) {
|
|
|
234
228
|
return rows === void 0 ? void 0 : buildContentTable(rows, contentWidthPt);
|
|
235
229
|
}
|
|
236
230
|
function parseHtmlTable(literal, contentWidthPt) {
|
|
237
|
-
|
|
238
|
-
if (!/^<table\b/i.test(trimmed)) return;
|
|
239
|
-
return parseWholeTable(trimmed, contentWidthPt);
|
|
231
|
+
return parseWholeTable(literal, contentWidthPt);
|
|
240
232
|
}
|
|
241
233
|
//#endregion
|
|
242
234
|
export { parseHtmlTable };
|
package/dist/image/image.cjs
CHANGED
|
@@ -18,9 +18,11 @@ const PNG_SIGNATURE = [
|
|
|
18
18
|
];
|
|
19
19
|
const PNG_HEADER_BYTES = 24;
|
|
20
20
|
function isPng(bytes) {
|
|
21
|
-
if (bytes.length < PNG_SIGNATURE.length) return false;
|
|
22
21
|
return PNG_SIGNATURE.every((byte, index) => bytes[index] === byte);
|
|
23
22
|
}
|
|
23
|
+
function isJpeg(bytes) {
|
|
24
|
+
return bytes[0] === 255 && bytes[1] === 216;
|
|
25
|
+
}
|
|
24
26
|
function readPngDimensions(bytes) {
|
|
25
27
|
if (bytes.length < PNG_HEADER_BYTES) return;
|
|
26
28
|
if (bytes[12] !== 73 || bytes[13] !== 72 || bytes[14] !== 68 || bytes[15] !== 82) return;
|
|
@@ -37,10 +39,12 @@ function hasNoLengthField(marker) {
|
|
|
37
39
|
return marker === 216 || marker === 217 || marker === 1 || marker >= 208 && marker <= 215;
|
|
38
40
|
}
|
|
39
41
|
function readJpegDimensions(bytes) {
|
|
40
|
-
if (bytes
|
|
42
|
+
if (!isJpeg(bytes)) return;
|
|
41
43
|
let offset = 2;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
for (;;) {
|
|
45
|
+
const byte = bytes[offset];
|
|
46
|
+
if (byte === void 0) return;
|
|
47
|
+
if (byte !== 255) {
|
|
44
48
|
offset += 1;
|
|
45
49
|
continue;
|
|
46
50
|
}
|
|
@@ -50,7 +54,6 @@ function readJpegDimensions(bytes) {
|
|
|
50
54
|
if (marker === void 0) return;
|
|
51
55
|
offset = markerOffset + 1;
|
|
52
56
|
if (hasNoLengthField(marker)) continue;
|
|
53
|
-
if (offset + 2 > bytes.length) return;
|
|
54
57
|
const length = readUint16BE(bytes, offset);
|
|
55
58
|
if (isStartOfFrameMarker(marker)) {
|
|
56
59
|
if (offset + 7 > bytes.length) return;
|
|
@@ -64,9 +67,6 @@ function readJpegDimensions(bytes) {
|
|
|
64
67
|
offset += length;
|
|
65
68
|
}
|
|
66
69
|
}
|
|
67
|
-
function isJpeg(bytes) {
|
|
68
|
-
return bytes.length >= 2 && bytes[0] === 255 && bytes[1] === 216;
|
|
69
|
-
}
|
|
70
70
|
function detectImageFormat(bytes) {
|
|
71
71
|
if (isPng(bytes)) return "png";
|
|
72
72
|
return isJpeg(bytes) ? "jpeg" : void 0;
|
package/dist/image/image.js
CHANGED
|
@@ -17,9 +17,11 @@ const PNG_SIGNATURE = [
|
|
|
17
17
|
];
|
|
18
18
|
const PNG_HEADER_BYTES = 24;
|
|
19
19
|
function isPng(bytes) {
|
|
20
|
-
if (bytes.length < PNG_SIGNATURE.length) return false;
|
|
21
20
|
return PNG_SIGNATURE.every((byte, index) => bytes[index] === byte);
|
|
22
21
|
}
|
|
22
|
+
function isJpeg(bytes) {
|
|
23
|
+
return bytes[0] === 255 && bytes[1] === 216;
|
|
24
|
+
}
|
|
23
25
|
function readPngDimensions(bytes) {
|
|
24
26
|
if (bytes.length < PNG_HEADER_BYTES) return;
|
|
25
27
|
if (bytes[12] !== 73 || bytes[13] !== 72 || bytes[14] !== 68 || bytes[15] !== 82) return;
|
|
@@ -36,10 +38,12 @@ function hasNoLengthField(marker) {
|
|
|
36
38
|
return marker === 216 || marker === 217 || marker === 1 || marker >= 208 && marker <= 215;
|
|
37
39
|
}
|
|
38
40
|
function readJpegDimensions(bytes) {
|
|
39
|
-
if (bytes
|
|
41
|
+
if (!isJpeg(bytes)) return;
|
|
40
42
|
let offset = 2;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
for (;;) {
|
|
44
|
+
const byte = bytes[offset];
|
|
45
|
+
if (byte === void 0) return;
|
|
46
|
+
if (byte !== 255) {
|
|
43
47
|
offset += 1;
|
|
44
48
|
continue;
|
|
45
49
|
}
|
|
@@ -49,7 +53,6 @@ function readJpegDimensions(bytes) {
|
|
|
49
53
|
if (marker === void 0) return;
|
|
50
54
|
offset = markerOffset + 1;
|
|
51
55
|
if (hasNoLengthField(marker)) continue;
|
|
52
|
-
if (offset + 2 > bytes.length) return;
|
|
53
56
|
const length = readUint16BE(bytes, offset);
|
|
54
57
|
if (isStartOfFrameMarker(marker)) {
|
|
55
58
|
if (offset + 7 > bytes.length) return;
|
|
@@ -63,9 +66,6 @@ function readJpegDimensions(bytes) {
|
|
|
63
66
|
offset += length;
|
|
64
67
|
}
|
|
65
68
|
}
|
|
66
|
-
function isJpeg(bytes) {
|
|
67
|
-
return bytes.length >= 2 && bytes[0] === 255 && bytes[1] === 216;
|
|
68
|
-
}
|
|
69
69
|
function detectImageFormat(bytes) {
|
|
70
70
|
if (isPng(bytes)) return "png";
|
|
71
71
|
return isJpeg(bytes) ? "jpeg" : void 0;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_inline_chars = require("./chars.cjs");
|
|
3
3
|
//#region src/inline/delimiter.ts
|
|
4
|
-
function isDelimiterChar(char) {
|
|
5
|
-
return char === "*" || char === "_" || char === "~";
|
|
6
|
-
}
|
|
7
4
|
const MAX_STRIKETHROUGH_RUN = 2;
|
|
8
5
|
function scanDelimiterRun(text, start, char) {
|
|
9
6
|
let count = 0;
|
|
@@ -124,6 +121,5 @@ function processEmphasis(stack, stackBottom, createWrapper) {
|
|
|
124
121
|
//#endregion
|
|
125
122
|
exports.DelimiterStack = DelimiterStack;
|
|
126
123
|
exports.closerSignature = closerSignature;
|
|
127
|
-
exports.isDelimiterChar = isDelimiterChar;
|
|
128
124
|
exports.processEmphasis = processEmphasis;
|
|
129
125
|
exports.scanDelimiterRun = scanDelimiterRun;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { InlineNode } from "./node.cjs";
|
|
2
2
|
//#region src/inline/delimiter.d.ts
|
|
3
3
|
type DelimiterChar = "*" | "_" | "~";
|
|
4
|
-
declare function isDelimiterChar(char: string): char is DelimiterChar;
|
|
5
4
|
interface Delimiter {
|
|
6
5
|
readonly char: DelimiterChar;
|
|
7
6
|
count: number;
|
|
@@ -27,4 +26,4 @@ declare function closerSignature(closer: Delimiter): string;
|
|
|
27
26
|
type EmphasisWrapperFactory = (kind: "emphasis" | "strong" | "strikethrough", marker: DelimiterChar) => InlineNode;
|
|
28
27
|
declare function processEmphasis(stack: DelimiterStack, stackBottom: Delimiter | undefined, createWrapper: EmphasisWrapperFactory): void;
|
|
29
28
|
//#endregion
|
|
30
|
-
export { Delimiter, DelimiterChar, DelimiterRun, DelimiterStack, EmphasisWrapperFactory, closerSignature,
|
|
29
|
+
export { Delimiter, DelimiterChar, DelimiterRun, DelimiterStack, EmphasisWrapperFactory, closerSignature, processEmphasis, scanDelimiterRun };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { InlineNode } from "./node.js";
|
|
2
2
|
//#region src/inline/delimiter.d.ts
|
|
3
3
|
type DelimiterChar = "*" | "_" | "~";
|
|
4
|
-
declare function isDelimiterChar(char: string): char is DelimiterChar;
|
|
5
4
|
interface Delimiter {
|
|
6
5
|
readonly char: DelimiterChar;
|
|
7
6
|
count: number;
|
|
@@ -27,4 +26,4 @@ declare function closerSignature(closer: Delimiter): string;
|
|
|
27
26
|
type EmphasisWrapperFactory = (kind: "emphasis" | "strong" | "strikethrough", marker: DelimiterChar) => InlineNode;
|
|
28
27
|
declare function processEmphasis(stack: DelimiterStack, stackBottom: Delimiter | undefined, createWrapper: EmphasisWrapperFactory): void;
|
|
29
28
|
//#endregion
|
|
30
|
-
export { Delimiter, DelimiterChar, DelimiterRun, DelimiterStack, EmphasisWrapperFactory, closerSignature,
|
|
29
|
+
export { Delimiter, DelimiterChar, DelimiterRun, DelimiterStack, EmphasisWrapperFactory, closerSignature, processEmphasis, scanDelimiterRun };
|
package/dist/inline/delimiter.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { codePointAt, codePointBefore, isUnicodePunctuation, isUnicodeWhitespace } from "./chars.js";
|
|
2
2
|
//#region src/inline/delimiter.ts
|
|
3
|
-
function isDelimiterChar(char) {
|
|
4
|
-
return char === "*" || char === "_" || char === "~";
|
|
5
|
-
}
|
|
6
3
|
const MAX_STRIKETHROUGH_RUN = 2;
|
|
7
4
|
function scanDelimiterRun(text, start, char) {
|
|
8
5
|
let count = 0;
|
|
@@ -121,4 +118,4 @@ function processEmphasis(stack, stackBottom, createWrapper) {
|
|
|
121
118
|
while (stack.top !== void 0 && stack.top !== stackBottom) stack.remove(stack.top);
|
|
122
119
|
}
|
|
123
120
|
//#endregion
|
|
124
|
-
export { DelimiterStack, closerSignature,
|
|
121
|
+
export { DelimiterStack, closerSignature, processEmphasis, scanDelimiterRun };
|