formatferry 1.0.38 → 1.0.40
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/index.js +137 -19
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -58942,6 +58942,12 @@ h${level}. ${trimmed}
|
|
|
58942
58942
|
}
|
|
58943
58943
|
|
|
58944
58944
|
// ../../src/shared/conversion-engine.ts
|
|
58945
|
+
var TableMarkdownLimitError = class extends Error {
|
|
58946
|
+
constructor() {
|
|
58947
|
+
super("Table Markdown exceeds the conversion limit");
|
|
58948
|
+
this.name = "TableMarkdownLimitError";
|
|
58949
|
+
}
|
|
58950
|
+
};
|
|
58945
58951
|
var ConversionEngine = class {
|
|
58946
58952
|
githubService;
|
|
58947
58953
|
commonmarkService;
|
|
@@ -58953,6 +58959,10 @@ var ConversionEngine = class {
|
|
|
58953
58959
|
confluenceService;
|
|
58954
58960
|
dom;
|
|
58955
58961
|
domSanitizer;
|
|
58962
|
+
/** Scoped to one synchronous Turndown pass; cloned cells do not change while table rules read them. */
|
|
58963
|
+
tableCellCache;
|
|
58964
|
+
/** Table Markdown characters this conversion may still emit (maxTableMarkdownChars). */
|
|
58965
|
+
tableMarkdownBudget = Number.POSITIVE_INFINITY;
|
|
58956
58966
|
constructor(options = {}) {
|
|
58957
58967
|
this.dom = options.dom;
|
|
58958
58968
|
this.initializeServices();
|
|
@@ -58967,7 +58977,7 @@ var ConversionEngine = class {
|
|
|
58967
58977
|
this.slackService,
|
|
58968
58978
|
this.confluenceService
|
|
58969
58979
|
]) {
|
|
58970
|
-
this.parseWithInjectedDom(service, this.dom);
|
|
58980
|
+
this.parseWithInjectedDom(service, this.dom, service === this.githubService);
|
|
58971
58981
|
}
|
|
58972
58982
|
}
|
|
58973
58983
|
}
|
|
@@ -58978,7 +58988,7 @@ var ConversionEngine = class {
|
|
|
58978
58988
|
* passes the element, which Turndown accepts in place of a string. Covers
|
|
58979
58989
|
* the nested `service.turndown(el.outerHTML)` calls in the list rules too.
|
|
58980
58990
|
*/
|
|
58981
|
-
parseWithInjectedDom(service, dom) {
|
|
58991
|
+
parseWithInjectedDom(service, dom, batchParagraphs) {
|
|
58982
58992
|
const turndown = service.turndown.bind(service);
|
|
58983
58993
|
service.turndown = (input) => {
|
|
58984
58994
|
if (typeof input !== "string") return turndown(input);
|
|
@@ -58989,9 +58999,64 @@ var ConversionEngine = class {
|
|
|
58989
58999
|
const root = doc.getElementById("turndown-root");
|
|
58990
59000
|
root?.normalize();
|
|
58991
59001
|
if (!root) throw new Error("Injected DOM did not produce the turndown root element");
|
|
58992
|
-
|
|
59002
|
+
if (batchParagraphs) {
|
|
59003
|
+
this.batchParagraphSiblings(root);
|
|
59004
|
+
this.batchTableRows(root);
|
|
59005
|
+
}
|
|
59006
|
+
return turndown(this.ownedDomInput(root));
|
|
58993
59007
|
};
|
|
58994
59008
|
}
|
|
59009
|
+
/** Turndown consumes a fresh private tree synchronously; caller-owned DOM never uses this adapter. */
|
|
59010
|
+
ownedDomInput(root) {
|
|
59011
|
+
return { nodeType: 1, cloneNode: () => root };
|
|
59012
|
+
}
|
|
59013
|
+
/**
|
|
59014
|
+
* GFM paragraphs and generic divs both contribute two separating newlines. Group long runs in the
|
|
59015
|
+
* private parsed DOM so Turndown joins a few hundred outputs at a time, instead of flattening a growing
|
|
59016
|
+
* string tens of thousands of times (#180). Keep DOM-sensitive table/list/quote/pre rules untouched.
|
|
59017
|
+
*/
|
|
59018
|
+
batchParagraphSiblings(root) {
|
|
59019
|
+
const containers = [root, ...Array.from(root.querySelectorAll("body,main,article,section,div"))];
|
|
59020
|
+
for (const container of containers) {
|
|
59021
|
+
if (container.childNodes.length < 512 || container.closest("table,ul,ol,pre,blockquote")) continue;
|
|
59022
|
+
const children = Array.from(container.childNodes);
|
|
59023
|
+
if (!children.every((child) => child.nodeType === 1 ? child.nodeName === "P" : child.nodeType === 8 || child.nodeType === 3 && !child.textContent?.trim())) continue;
|
|
59024
|
+
let group;
|
|
59025
|
+
let count = 0;
|
|
59026
|
+
for (const child of children) {
|
|
59027
|
+
if (!group) {
|
|
59028
|
+
group = container.ownerDocument.createElement("div");
|
|
59029
|
+
container.insertBefore(group, child);
|
|
59030
|
+
}
|
|
59031
|
+
group.appendChild(child);
|
|
59032
|
+
if (child.nodeType === 1 && ++count === 256) {
|
|
59033
|
+
group = void 0;
|
|
59034
|
+
count = 0;
|
|
59035
|
+
}
|
|
59036
|
+
}
|
|
59037
|
+
}
|
|
59038
|
+
}
|
|
59039
|
+
/** The table rule discards preliminary row Markdown and queries all descendant rows itself. */
|
|
59040
|
+
batchTableRows(root) {
|
|
59041
|
+
for (const container of Array.from(root.querySelectorAll("table,thead,tbody,tfoot"))) {
|
|
59042
|
+
if (container.childNodes.length < 512) continue;
|
|
59043
|
+
const children = Array.from(container.childNodes);
|
|
59044
|
+
if (!children.every((child) => child.nodeType === 1 ? child.nodeName === "TR" : child.nodeType === 8 || child.nodeType === 3 && !child.textContent?.trim())) continue;
|
|
59045
|
+
let group;
|
|
59046
|
+
let count = 0;
|
|
59047
|
+
for (const child of children) {
|
|
59048
|
+
if (!group) {
|
|
59049
|
+
group = container.ownerDocument.createElement("tbody");
|
|
59050
|
+
container.insertBefore(group, child);
|
|
59051
|
+
}
|
|
59052
|
+
group.appendChild(child);
|
|
59053
|
+
if (child.nodeType === 1 && ++count === 256) {
|
|
59054
|
+
group = void 0;
|
|
59055
|
+
count = 0;
|
|
59056
|
+
}
|
|
59057
|
+
}
|
|
59058
|
+
}
|
|
59059
|
+
}
|
|
58995
59060
|
initializeServices() {
|
|
58996
59061
|
this.githubService = new import_turndown2.default({
|
|
58997
59062
|
headingStyle: "atx",
|
|
@@ -59627,10 +59692,22 @@ ${plainText}
|
|
|
59627
59692
|
if (rows.length === 0) return content;
|
|
59628
59693
|
let markdown = "\n";
|
|
59629
59694
|
let headerProcessed = false;
|
|
59695
|
+
let tableLength = 0;
|
|
59630
59696
|
rows.forEach((row, index) => {
|
|
59631
59697
|
const cells = Array.from(row.querySelectorAll("th, td"));
|
|
59632
|
-
const cellContents = cells.map((cell) =>
|
|
59698
|
+
const cellContents = cells.map((cell) => {
|
|
59699
|
+
let rendered = this.tableCellCache?.get(cell);
|
|
59700
|
+
if (rendered === void 0) {
|
|
59701
|
+
rendered = this.escapeTableCell(this.renderTableCell(cell));
|
|
59702
|
+
this.chargeTableMarkdown(rendered.length);
|
|
59703
|
+
this.tableCellCache?.set(cell, rendered);
|
|
59704
|
+
}
|
|
59705
|
+
return rendered;
|
|
59706
|
+
});
|
|
59633
59707
|
if (cellContents.length > 0) {
|
|
59708
|
+
tableLength += 1 + 3 * cellContents.length;
|
|
59709
|
+
for (const value of cellContents) tableLength += value.length;
|
|
59710
|
+
if (tableLength > this.tableMarkdownBudget) throw new TableMarkdownLimitError();
|
|
59634
59711
|
markdown += "| " + cellContents.join(" | ") + " |\n";
|
|
59635
59712
|
if (!headerProcessed && (row.querySelector("th") || index === 0)) {
|
|
59636
59713
|
const separator = cellContents.map(() => "---").join(" | ");
|
|
@@ -59643,6 +59720,11 @@ ${plainText}
|
|
|
59643
59720
|
}
|
|
59644
59721
|
});
|
|
59645
59722
|
}
|
|
59723
|
+
/** Deduct a rendered cell, which the per-conversion cache keeps alive until the conversion ends. */
|
|
59724
|
+
chargeTableMarkdown(chars) {
|
|
59725
|
+
this.tableMarkdownBudget -= chars;
|
|
59726
|
+
if (this.tableMarkdownBudget < 0) throw new TableMarkdownLimitError();
|
|
59727
|
+
}
|
|
59646
59728
|
renderTableCell(cell) {
|
|
59647
59729
|
const ELEMENT_NODE2 = 1;
|
|
59648
59730
|
const blocks = [];
|
|
@@ -59700,8 +59782,17 @@ ${plainText}
|
|
|
59700
59782
|
}
|
|
59701
59783
|
renderCodeSpan(content) {
|
|
59702
59784
|
if (!content.includes("`")) return `\`${content}\``;
|
|
59703
|
-
|
|
59704
|
-
|
|
59785
|
+
let longest = 0;
|
|
59786
|
+
let current = 0;
|
|
59787
|
+
for (let i = 0; i < content.length; i++) {
|
|
59788
|
+
if (content.charCodeAt(i) === 96) {
|
|
59789
|
+
current++;
|
|
59790
|
+
if (current > longest) longest = current;
|
|
59791
|
+
} else {
|
|
59792
|
+
current = 0;
|
|
59793
|
+
}
|
|
59794
|
+
}
|
|
59795
|
+
const delimiter = "`".repeat(longest + 1);
|
|
59705
59796
|
return `${delimiter} ${content} ${delimiter}`;
|
|
59706
59797
|
}
|
|
59707
59798
|
escapeMarkdownLinkText(text) {
|
|
@@ -59711,7 +59802,8 @@ ${plainText}
|
|
|
59711
59802
|
return href.replace(/</g, "%3C").replace(/>/g, "%3E");
|
|
59712
59803
|
}
|
|
59713
59804
|
escapeTableCell(content) {
|
|
59714
|
-
|
|
59805
|
+
const escaped = content.replace(/\|/g, "\\|");
|
|
59806
|
+
return escaped.includes("<br>") ? escaped.split("<br>").map((part) => part.trim()).join("<br>") : escaped.trim();
|
|
59715
59807
|
}
|
|
59716
59808
|
/** A space after a checkbox marker unless the label text already starts with one. */
|
|
59717
59809
|
checkboxSpacer(node) {
|
|
@@ -59766,6 +59858,12 @@ ${plainText}
|
|
|
59766
59858
|
});
|
|
59767
59859
|
}
|
|
59768
59860
|
addListRules(service) {
|
|
59861
|
+
if (this.dom && service === this.githubService) {
|
|
59862
|
+
service.addRule("discardPreliminaryListItems", {
|
|
59863
|
+
filter: (node) => node.nodeName === "LI" && (node.parentNode?.nodeName === "UL" || node.parentNode?.nodeName === "OL"),
|
|
59864
|
+
replacement: () => ""
|
|
59865
|
+
});
|
|
59866
|
+
}
|
|
59769
59867
|
service.addRule("enhancedList", {
|
|
59770
59868
|
filter: ["ul", "ol"],
|
|
59771
59869
|
replacement: (content, node) => {
|
|
@@ -59792,10 +59890,12 @@ ${plainText}
|
|
|
59792
59890
|
let markdown = "";
|
|
59793
59891
|
items.forEach((item, index) => {
|
|
59794
59892
|
const marker = isOrdered ? `${index + 1}.` : bullet;
|
|
59795
|
-
const indent = " ".repeat(marker.length + 1);
|
|
59796
59893
|
const body = this.processListItem(item, service);
|
|
59797
|
-
|
|
59798
|
-
|
|
59894
|
+
let indented = body;
|
|
59895
|
+
if (body.includes("\n")) {
|
|
59896
|
+
const indent = " ".repeat(marker.length + 1);
|
|
59897
|
+
indented = body.split("\n").map((line, i) => i === 0 || line === "" ? line : indent + line).join("\n");
|
|
59898
|
+
}
|
|
59799
59899
|
markdown += `${marker} ${indented}
|
|
59800
59900
|
`;
|
|
59801
59901
|
});
|
|
@@ -59808,13 +59908,21 @@ ${plainText}
|
|
|
59808
59908
|
* multiple paragraphs stay separated.
|
|
59809
59909
|
*/
|
|
59810
59910
|
processListItem(item, service) {
|
|
59911
|
+
if (this.dom && service === this.githubService && service.options.linkStyle !== "referenced") {
|
|
59912
|
+
const child = item.firstChild;
|
|
59913
|
+
if (child?.nodeType === 3 && child.nextSibling === null) {
|
|
59914
|
+
const text = child.textContent ?? "";
|
|
59915
|
+
if (!/\s/.test(text)) return service.escape(text).trim();
|
|
59916
|
+
}
|
|
59917
|
+
}
|
|
59811
59918
|
const parts = [];
|
|
59812
59919
|
const ELEMENT_NODE2 = 1;
|
|
59813
59920
|
const doc = item.ownerDocument;
|
|
59814
59921
|
let buffer = doc.createElement("div");
|
|
59815
59922
|
const flush = () => {
|
|
59816
59923
|
if (buffer.childNodes.length > 0) {
|
|
59817
|
-
const
|
|
59924
|
+
const input = this.dom && service === this.githubService ? this.ownedDomInput(buffer) : buffer;
|
|
59925
|
+
const md = service.turndown(input).trim();
|
|
59818
59926
|
if (md) parts.push(md);
|
|
59819
59927
|
}
|
|
59820
59928
|
buffer = doc.createElement("div");
|
|
@@ -59936,7 +60044,17 @@ ${plainText}
|
|
|
59936
60044
|
break;
|
|
59937
60045
|
}
|
|
59938
60046
|
const htmlForConversion = options.preserveTables ? sanitizedHtml : this.flattenTables(sanitizedHtml);
|
|
59939
|
-
|
|
60047
|
+
const previousCache = this.tableCellCache;
|
|
60048
|
+
const previousBudget = this.tableMarkdownBudget;
|
|
60049
|
+
this.tableCellCache = /* @__PURE__ */ new WeakMap();
|
|
60050
|
+
this.tableMarkdownBudget = options.maxTableMarkdownChars ?? Number.POSITIVE_INFINITY;
|
|
60051
|
+
let markdown;
|
|
60052
|
+
try {
|
|
60053
|
+
markdown = service.turndown(htmlForConversion);
|
|
60054
|
+
} finally {
|
|
60055
|
+
this.tableCellCache = previousCache;
|
|
60056
|
+
this.tableMarkdownBudget = previousBudget;
|
|
60057
|
+
}
|
|
59940
60058
|
markdown = this.applyFormatPostProcessing(markdown, options.format);
|
|
59941
60059
|
const endTime = performance.now();
|
|
59942
60060
|
const metadata = {
|
|
@@ -64297,7 +64415,7 @@ async function binaryToMarkdown(buffer, type, format) {
|
|
|
64297
64415
|
preserveLists: true,
|
|
64298
64416
|
customRules: []
|
|
64299
64417
|
});
|
|
64300
|
-
return { markdown: converted.markdown, warnings: result.warnings
|
|
64418
|
+
return { markdown: converted.markdown, warnings: result.warnings };
|
|
64301
64419
|
}
|
|
64302
64420
|
case "pdf": {
|
|
64303
64421
|
const result = await pdfAdapter.parseToText(toArrayBuffer());
|
|
@@ -64320,7 +64438,7 @@ async function binaryToMarkdown(buffer, type, format) {
|
|
|
64320
64438
|
preserveLists: true,
|
|
64321
64439
|
customRules: []
|
|
64322
64440
|
});
|
|
64323
|
-
return { markdown: converted.markdown, warnings: result.warnings
|
|
64441
|
+
return { markdown: converted.markdown, warnings: result.warnings };
|
|
64324
64442
|
}
|
|
64325
64443
|
case "json": {
|
|
64326
64444
|
const result = await dataAdapter.parseJsonToHtml(toArrayBuffer());
|
|
@@ -64331,7 +64449,7 @@ async function binaryToMarkdown(buffer, type, format) {
|
|
|
64331
64449
|
preserveLists: true,
|
|
64332
64450
|
customRules: []
|
|
64333
64451
|
});
|
|
64334
|
-
return { markdown: converted.markdown, warnings: result.warnings
|
|
64452
|
+
return { markdown: converted.markdown, warnings: result.warnings };
|
|
64335
64453
|
}
|
|
64336
64454
|
case "xml": {
|
|
64337
64455
|
const result = await dataAdapter.parseXmlToHtml(toArrayBuffer());
|
|
@@ -64342,7 +64460,7 @@ async function binaryToMarkdown(buffer, type, format) {
|
|
|
64342
64460
|
preserveLists: true,
|
|
64343
64461
|
customRules: []
|
|
64344
64462
|
});
|
|
64345
|
-
return { markdown: converted.markdown, warnings: result.warnings
|
|
64463
|
+
return { markdown: converted.markdown, warnings: result.warnings };
|
|
64346
64464
|
}
|
|
64347
64465
|
case "pptx": {
|
|
64348
64466
|
const result = await pptxAdapter.parseToHtml(toArrayBuffer());
|
|
@@ -64353,7 +64471,7 @@ async function binaryToMarkdown(buffer, type, format) {
|
|
|
64353
64471
|
preserveLists: true,
|
|
64354
64472
|
customRules: []
|
|
64355
64473
|
});
|
|
64356
|
-
return { markdown: converted.markdown, warnings: result.warnings
|
|
64474
|
+
return { markdown: converted.markdown, warnings: result.warnings };
|
|
64357
64475
|
}
|
|
64358
64476
|
}
|
|
64359
64477
|
}
|
|
@@ -64909,8 +65027,8 @@ import { readFileSync as readFileSync5 } from "fs";
|
|
|
64909
65027
|
import { resolve, dirname as dirname3 } from "path";
|
|
64910
65028
|
import { fileURLToPath } from "url";
|
|
64911
65029
|
var getVersion = () => {
|
|
64912
|
-
if ("1.0.
|
|
64913
|
-
return "1.0.
|
|
65030
|
+
if ("1.0.40") {
|
|
65031
|
+
return "1.0.40";
|
|
64914
65032
|
}
|
|
64915
65033
|
try {
|
|
64916
65034
|
const __dirname2 = dirname3(fileURLToPath(import.meta.url));
|