formatferry 1.0.21 → 1.0.23
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 +90 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19720,7 +19720,7 @@ var InputSanitizer = class {
|
|
|
19720
19720
|
],
|
|
19721
19721
|
// Include data-page-marker for PDF page break markers (Req 3.5)
|
|
19722
19722
|
// Include type and checked for task list checkbox support
|
|
19723
|
-
ALLOWED_ATTR: ["href", "src", "alt", "title", "style", "class", "data-page-marker", "type", "checked", "data-math"]
|
|
19723
|
+
ALLOWED_ATTR: ["href", "src", "alt", "title", "style", "class", "data-page-marker", "data-docx-table-kind", "type", "checked", "data-math"]
|
|
19724
19724
|
};
|
|
19725
19725
|
switch (this.config.level) {
|
|
19726
19726
|
case "strict":
|
|
@@ -20729,6 +20729,22 @@ ${plainText}
|
|
|
20729
20729
|
});
|
|
20730
20730
|
return lines.join("\n");
|
|
20731
20731
|
}
|
|
20732
|
+
flattenTables(html) {
|
|
20733
|
+
if (typeof DOMParser === "undefined") return html;
|
|
20734
|
+
const parser = new DOMParser();
|
|
20735
|
+
const doc = parser.parseFromString(`<div>${html}</div>`, "text/html");
|
|
20736
|
+
Array.from(doc.querySelectorAll("table")).forEach((table) => {
|
|
20737
|
+
const replacement = doc.createElement("div");
|
|
20738
|
+
const lines = this.tableToPlainText(table).split("\n").filter(Boolean);
|
|
20739
|
+
lines.forEach((line) => {
|
|
20740
|
+
const paragraph = doc.createElement("p");
|
|
20741
|
+
paragraph.textContent = line;
|
|
20742
|
+
replacement.appendChild(paragraph);
|
|
20743
|
+
});
|
|
20744
|
+
table.replaceWith(replacement);
|
|
20745
|
+
});
|
|
20746
|
+
return doc.body.firstElementChild?.innerHTML ?? html;
|
|
20747
|
+
}
|
|
20732
20748
|
addGoogleDocsRules(service) {
|
|
20733
20749
|
service.addRule("googleDocsBold", {
|
|
20734
20750
|
filter: (node) => {
|
|
@@ -20860,10 +20876,7 @@ ${plainText}
|
|
|
20860
20876
|
let headerProcessed = false;
|
|
20861
20877
|
rows.forEach((row, index) => {
|
|
20862
20878
|
const cells = Array.from(row.querySelectorAll("th, td"));
|
|
20863
|
-
const cellContents = cells.map((cell) =>
|
|
20864
|
-
const cellContent = cell.textContent || "";
|
|
20865
|
-
return cellContent.trim().replace(/\|/g, "\\|");
|
|
20866
|
-
});
|
|
20879
|
+
const cellContents = cells.map((cell) => this.escapeTableCell(this.renderTableCell(cell)));
|
|
20867
20880
|
if (cellContents.length > 0) {
|
|
20868
20881
|
markdown += "| " + cellContents.join(" | ") + " |\n";
|
|
20869
20882
|
if (!headerProcessed && (row.querySelector("th") || index === 0)) {
|
|
@@ -20877,6 +20890,73 @@ ${plainText}
|
|
|
20877
20890
|
}
|
|
20878
20891
|
});
|
|
20879
20892
|
}
|
|
20893
|
+
renderTableCell(cell) {
|
|
20894
|
+
const blocks = [];
|
|
20895
|
+
let inlineBuffer = "";
|
|
20896
|
+
cell.childNodes.forEach((child) => {
|
|
20897
|
+
if (child.nodeType === Node.ELEMENT_NODE && this.isTableCellBlock(child)) {
|
|
20898
|
+
if (inlineBuffer.trim()) {
|
|
20899
|
+
blocks.push(inlineBuffer.trim());
|
|
20900
|
+
inlineBuffer = "";
|
|
20901
|
+
}
|
|
20902
|
+
blocks.push(this.renderTableBlock(child));
|
|
20903
|
+
return;
|
|
20904
|
+
}
|
|
20905
|
+
inlineBuffer += this.renderInlineNode(child);
|
|
20906
|
+
});
|
|
20907
|
+
if (inlineBuffer.trim()) blocks.push(inlineBuffer.trim());
|
|
20908
|
+
if (blocks.length === 0) return (cell.textContent || "").trim();
|
|
20909
|
+
return blocks.filter(Boolean).join("<br>");
|
|
20910
|
+
}
|
|
20911
|
+
isTableCellBlock(element) {
|
|
20912
|
+
return ["P", "DIV", "UL", "OL", "H1", "H2", "H3", "H4", "H5", "H6", "BLOCKQUOTE", "PRE"].includes(element.nodeName);
|
|
20913
|
+
}
|
|
20914
|
+
renderTableBlock(element) {
|
|
20915
|
+
if (element.nodeName === "UL" || element.nodeName === "OL") {
|
|
20916
|
+
return Array.from(element.children).filter((child) => child.nodeName === "LI").map((child) => `- ${this.renderInlineNode(child).trim()}`).join("<br>");
|
|
20917
|
+
}
|
|
20918
|
+
return this.renderInlineNode(element).trim();
|
|
20919
|
+
}
|
|
20920
|
+
renderInlineNode(node) {
|
|
20921
|
+
if (node.nodeType === Node.TEXT_NODE) return node.textContent || "";
|
|
20922
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return "";
|
|
20923
|
+
const element = node;
|
|
20924
|
+
const content = Array.from(element.childNodes).map((child) => this.renderInlineNode(child)).join("");
|
|
20925
|
+
const trimmed = content.trim();
|
|
20926
|
+
switch (element.nodeName) {
|
|
20927
|
+
case "BR":
|
|
20928
|
+
return "<br>";
|
|
20929
|
+
case "STRONG":
|
|
20930
|
+
case "B":
|
|
20931
|
+
return trimmed ? `**${trimmed}**` : content;
|
|
20932
|
+
case "EM":
|
|
20933
|
+
case "I":
|
|
20934
|
+
return trimmed ? `_${trimmed}_` : content;
|
|
20935
|
+
case "CODE":
|
|
20936
|
+
return trimmed ? this.renderCodeSpan(trimmed) : content;
|
|
20937
|
+
case "A": {
|
|
20938
|
+
const href = element.getAttribute("href") || "";
|
|
20939
|
+
return href && trimmed ? `[${this.escapeMarkdownLinkText(trimmed)}](<${this.escapeMarkdownLinkHref(href)}>)` : content;
|
|
20940
|
+
}
|
|
20941
|
+
default:
|
|
20942
|
+
return content;
|
|
20943
|
+
}
|
|
20944
|
+
}
|
|
20945
|
+
renderCodeSpan(content) {
|
|
20946
|
+
if (!content.includes("`")) return `\`${content}\``;
|
|
20947
|
+
const runs = content.match(/`+/g) || ["`"];
|
|
20948
|
+
const delimiter = "`".repeat(Math.max(...runs.map((run) => run.length)) + 1);
|
|
20949
|
+
return `${delimiter} ${content} ${delimiter}`;
|
|
20950
|
+
}
|
|
20951
|
+
escapeMarkdownLinkText(text) {
|
|
20952
|
+
return text.replace(/\\/g, "\\\\").replace(/\[/g, "\\[").replace(/\]/g, "\\]");
|
|
20953
|
+
}
|
|
20954
|
+
escapeMarkdownLinkHref(href) {
|
|
20955
|
+
return href.replace(/</g, "%3C").replace(/>/g, "%3E");
|
|
20956
|
+
}
|
|
20957
|
+
escapeTableCell(content) {
|
|
20958
|
+
return content.replace(/\|/g, "\\|").replace(/\s*<br>\s*/g, "<br>").trim();
|
|
20959
|
+
}
|
|
20880
20960
|
addListRules(service) {
|
|
20881
20961
|
service.addRule("enhancedList", {
|
|
20882
20962
|
filter: ["ul", "ol"],
|
|
@@ -21025,7 +21105,8 @@ ${plainText}
|
|
|
21025
21105
|
service = this.githubService;
|
|
21026
21106
|
break;
|
|
21027
21107
|
}
|
|
21028
|
-
|
|
21108
|
+
const htmlForConversion = options.preserveTables ? sanitizedHtml : this.flattenTables(sanitizedHtml);
|
|
21109
|
+
let markdown = service.turndown(htmlForConversion);
|
|
21029
21110
|
markdown = this.applyFormatPostProcessing(markdown, options.format);
|
|
21030
21111
|
const endTime = performance.now();
|
|
21031
21112
|
const metadata = {
|
|
@@ -23089,7 +23170,7 @@ var PdfAdapter = class {
|
|
|
23089
23170
|
const hasMinimalTextWithImages = totalTextLength < MIN_TEXT_CHARS_THRESHOLD && hasAnyImages;
|
|
23090
23171
|
if (hasNoText || hasMinimalTextWithImages) {
|
|
23091
23172
|
throw new PdfParseError(
|
|
23092
|
-
"
|
|
23173
|
+
"PDF contains only images \u2014 no text layer available.",
|
|
23093
23174
|
"IMAGE_ONLY"
|
|
23094
23175
|
);
|
|
23095
23176
|
}
|
|
@@ -25419,8 +25500,8 @@ import { readFileSync as readFileSync4 } from "fs";
|
|
|
25419
25500
|
import { resolve, dirname as dirname3 } from "path";
|
|
25420
25501
|
import { fileURLToPath } from "url";
|
|
25421
25502
|
var getVersion = () => {
|
|
25422
|
-
if ("1.0.
|
|
25423
|
-
return "1.0.
|
|
25503
|
+
if ("1.0.23") {
|
|
25504
|
+
return "1.0.23";
|
|
25424
25505
|
}
|
|
25425
25506
|
try {
|
|
25426
25507
|
const __dirname = dirname3(fileURLToPath(import.meta.url));
|