@bendyline/squisq-formats 1.3.1 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +180 -43
- package/dist/{chunk-33YRFXZZ.js → chunk-46FMDOWZ.js} +260 -14
- package/dist/chunk-46FMDOWZ.js.map +1 -0
- package/dist/{chunk-ERZ627GR.js → chunk-5LSSWZPU.js} +12 -27
- package/dist/chunk-5LSSWZPU.js.map +1 -0
- package/dist/chunk-6M7Z25LA.js +46 -0
- package/dist/chunk-6M7Z25LA.js.map +1 -0
- package/dist/{chunk-S3Y7H2BK.js → chunk-D7IFPWNZ.js} +95 -50
- package/dist/chunk-D7IFPWNZ.js.map +1 -0
- package/dist/chunk-DQAZR57U.js +33 -0
- package/dist/chunk-DQAZR57U.js.map +1 -0
- package/dist/chunk-EHLGMSTE.js +273 -0
- package/dist/chunk-EHLGMSTE.js.map +1 -0
- package/dist/{chunk-A3FHLTY5.js → chunk-MJGRI6XR.js} +6 -19
- package/dist/chunk-MJGRI6XR.js.map +1 -0
- package/dist/chunk-PN52A5AA.js +32 -0
- package/dist/chunk-PN52A5AA.js.map +1 -0
- package/dist/chunk-RFAPOKHJ.js +123 -0
- package/dist/chunk-RFAPOKHJ.js.map +1 -0
- package/dist/chunk-RTS5XBZ7.js +526 -0
- package/dist/chunk-RTS5XBZ7.js.map +1 -0
- package/dist/{chunk-7DEUGIOO.js → chunk-SHLPSADL.js} +120 -2
- package/dist/chunk-SHLPSADL.js.map +1 -0
- package/dist/chunk-SSUPBUF5.js +15 -0
- package/dist/chunk-SSUPBUF5.js.map +1 -0
- package/dist/{chunk-UDS45KUJ.js → chunk-WWBIKRNP.js} +40 -80
- package/dist/chunk-WWBIKRNP.js.map +1 -0
- package/dist/{chunk-VN2KEOYB.js → chunk-YESS7VY3.js} +379 -87
- package/dist/chunk-YESS7VY3.js.map +1 -0
- package/dist/csv/index.d.ts +50 -0
- package/dist/csv/index.js +13 -0
- package/dist/csv/index.js.map +1 -0
- package/dist/docx/index.js +6 -3
- package/dist/epub/index.js +4 -2
- package/dist/html/index.d.ts +42 -2
- package/dist/html/index.js +9 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.js +47 -14
- package/dist/ooxml/index.d.ts +5 -1
- package/dist/ooxml/index.js +13 -9
- package/dist/pdf/index.js +2 -1
- package/dist/pptx/index.d.ts +36 -19
- package/dist/pptx/index.js +9 -2
- package/dist/registry/index.d.ts +167 -0
- package/dist/registry/index.js +17 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/xlsx/index.d.ts +60 -29
- package/dist/xlsx/index.js +4 -1
- package/package.json +12 -2
- package/src/__tests__/convert.test.ts +186 -0
- package/src/__tests__/csvImport.test.ts +84 -0
- package/src/__tests__/exportThemeReconciliation.test.ts +87 -0
- package/src/__tests__/formatRegistry.test.ts +174 -0
- package/src/__tests__/htmlImport.test.ts +57 -0
- package/src/__tests__/lossyWarnings.test.ts +105 -0
- package/src/__tests__/pdfImport.test.ts +95 -1
- package/src/__tests__/plainHtml.test.ts +31 -0
- package/src/__tests__/pptxExport.test.ts +138 -0
- package/src/__tests__/pptxImport.test.ts +115 -0
- package/src/__tests__/roundTripAssets.test.ts +50 -0
- package/src/__tests__/roundTripMatrix.fixtures.ts +86 -0
- package/src/__tests__/roundTripMatrix.helpers.ts +154 -0
- package/src/__tests__/roundTripMatrix.test.ts +142 -0
- package/src/__tests__/sharedContainer.test.ts +41 -0
- package/src/__tests__/sharedImages.test.ts +61 -0
- package/src/__tests__/xlsxExport.test.ts +164 -0
- package/src/__tests__/xlsxImport.test.ts +80 -0
- package/src/csv/index.ts +188 -0
- package/src/docx/export.ts +27 -44
- package/src/docx/import.ts +7 -39
- package/src/epub/export.ts +10 -27
- package/src/html/imageUtils.ts +5 -19
- package/src/html/import.ts +297 -0
- package/src/html/index.ts +4 -0
- package/src/html/plainHtml.ts +66 -16
- package/src/index.ts +36 -5
- package/src/ooxml/index.ts +3 -0
- package/src/ooxml/namespaces.ts +13 -0
- package/src/pdf/export.ts +10 -5
- package/src/pdf/import.ts +146 -51
- package/src/pptx/export.ts +225 -85
- package/src/pptx/import.ts +273 -0
- package/src/pptx/index.ts +10 -28
- package/src/registry/convert.ts +318 -0
- package/src/registry/defaultFormats.ts +323 -0
- package/src/registry/errors.ts +46 -0
- package/src/registry/index.ts +38 -0
- package/src/registry/registry.ts +48 -0
- package/src/registry/types.ts +107 -0
- package/src/shared/container.ts +28 -0
- package/src/shared/images.ts +44 -0
- package/src/shared/inlineRuns.ts +99 -0
- package/src/shared/text.ts +41 -0
- package/src/xlsx/export.ts +253 -0
- package/src/xlsx/import.ts +159 -0
- package/src/xlsx/index.ts +18 -61
- package/dist/chunk-33YRFXZZ.js.map +0 -1
- package/dist/chunk-67KIJHV2.js +0 -21
- package/dist/chunk-67KIJHV2.js.map +0 -1
- package/dist/chunk-7DEUGIOO.js.map +0 -1
- package/dist/chunk-A3FHLTY5.js.map +0 -1
- package/dist/chunk-ERZ627GR.js.map +0 -1
- package/dist/chunk-S3Y7H2BK.js.map +0 -1
- package/dist/chunk-UDS45KUJ.js.map +0 -1
- package/dist/chunk-VN2KEOYB.js.map +0 -1
- package/dist/chunk-YN5HFCEW.js +0 -120
- package/dist/chunk-YN5HFCEW.js.map +0 -1
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
arrayBufferToBase64DataUrl,
|
|
3
3
|
extractFilename,
|
|
4
4
|
inferMimeType
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-MJGRI6XR.js";
|
|
6
6
|
|
|
7
7
|
// src/html/index.ts
|
|
8
8
|
import JSZip3 from "jszip";
|
|
@@ -222,11 +222,18 @@ function escapeHtml(str) {
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
// src/html/plainHtml.ts
|
|
225
|
-
import {
|
|
225
|
+
import {
|
|
226
|
+
sanitizeHtmlNodes,
|
|
227
|
+
sanitizeUrl,
|
|
228
|
+
readFrontmatterThemeId
|
|
229
|
+
} from "@bendyline/squisq/markdown";
|
|
230
|
+
import { resolveFontFamily, buildGoogleFontsUrl } from "@bendyline/squisq/schemas";
|
|
231
|
+
import { resolveThemeForDoc } from "@bendyline/squisq/doc";
|
|
226
232
|
function markdownDocToPlainHtml(doc, options = {}) {
|
|
227
|
-
const { title = "Document", images, links, themeId, iconsCss } = options;
|
|
228
|
-
const
|
|
229
|
-
const
|
|
233
|
+
const { title = "Document", images, links, themeId, iconsCss, htmlPolicy = "sanitize" } = options;
|
|
234
|
+
const resolveId = themeId ?? readFrontmatterThemeId(doc.frontmatter);
|
|
235
|
+
const theme = options.theme ?? (resolveId ? resolveThemeForDoc(doc, resolveId) : void 0);
|
|
236
|
+
const ctx = { images, links, htmlPolicy };
|
|
230
237
|
const body = renderTopLevel(doc.children, ctx);
|
|
231
238
|
const fontsLink = theme ? renderFontsLink(theme) : "";
|
|
232
239
|
const usesIcons = docUsesIcons(doc);
|
|
@@ -310,7 +317,9 @@ ${textHtml}
|
|
|
310
317
|
}
|
|
311
318
|
function renderFeatureImage(img, ctx) {
|
|
312
319
|
const resolved = ctx?.images?.get(img.src) ?? img.src;
|
|
313
|
-
const
|
|
320
|
+
const safeSrc = sanitizeUrl(resolved, "media");
|
|
321
|
+
if (!safeSrc) return '<div class="squisq-feature__media squisq-feature__media--empty"></div>';
|
|
322
|
+
const attrs = [`src="${escapeAttr(safeSrc)}"`, `alt="${escapeAttr(img.alt)}"`];
|
|
314
323
|
if (typeof img.width === "number") attrs.push(`width="${img.width}"`);
|
|
315
324
|
if (typeof img.height === "number") attrs.push(`height="${img.height}"`);
|
|
316
325
|
const sizedClass = typeof img.width === "number" || typeof img.height === "number" ? " squisq-feature__media--sized" : "";
|
|
@@ -593,12 +602,16 @@ function nodeToHtml(node, ctx) {
|
|
|
593
602
|
case "link": {
|
|
594
603
|
const original = node.url ?? "";
|
|
595
604
|
const rewritten = ctx?.links?.get(original) ?? original;
|
|
596
|
-
|
|
605
|
+
const safeHref = sanitizeUrl(rewritten, "link");
|
|
606
|
+
if (!safeHref) return childrenToHtml(node, ctx);
|
|
607
|
+
return `<a href="${escapeAttr(safeHref)}">${childrenToHtml(node, ctx)}</a>`;
|
|
597
608
|
}
|
|
598
609
|
case "image": {
|
|
599
610
|
const original = node.url ?? "";
|
|
600
611
|
const resolved = ctx?.images?.get(original) ?? original;
|
|
601
|
-
|
|
612
|
+
const safeSrc = sanitizeUrl(resolved, "media");
|
|
613
|
+
if (!safeSrc) return escapeHtml2(node.alt ?? "");
|
|
614
|
+
return `<img src="${escapeAttr(safeSrc)}" alt="${escapeAttr(node.alt ?? "")}" />`;
|
|
602
615
|
}
|
|
603
616
|
case "thematicBreak":
|
|
604
617
|
return "<hr />";
|
|
@@ -612,7 +625,8 @@ function nodeToHtml(node, ctx) {
|
|
|
612
625
|
}
|
|
613
626
|
case "htmlBlock":
|
|
614
627
|
case "htmlInline":
|
|
615
|
-
|
|
628
|
+
if (resolveHtmlPolicy(ctx) === "strip") return "";
|
|
629
|
+
return htmlChildrenToHtml(resolveHtmlNodes(node.htmlChildren, ctx), ctx);
|
|
616
630
|
default: {
|
|
617
631
|
const withChildren = node;
|
|
618
632
|
if (Array.isArray(withChildren.children)) {
|
|
@@ -653,16 +667,24 @@ function tableToHtml(node, ctx) {
|
|
|
653
667
|
parts.push("</table>");
|
|
654
668
|
return parts.join("");
|
|
655
669
|
}
|
|
670
|
+
function resolveHtmlPolicy(ctx) {
|
|
671
|
+
return ctx?.htmlPolicy ?? "sanitize";
|
|
672
|
+
}
|
|
673
|
+
function resolveHtmlNodes(nodes, ctx) {
|
|
674
|
+
if (!nodes || nodes.length === 0) return [];
|
|
675
|
+
return resolveHtmlPolicy(ctx) === "trusted" ? nodes : sanitizeHtmlNodes(nodes);
|
|
676
|
+
}
|
|
656
677
|
function htmlChildrenToHtml(nodes, ctx) {
|
|
657
678
|
if (!nodes || nodes.length === 0) return "";
|
|
679
|
+
const trusted = resolveHtmlPolicy(ctx) === "trusted";
|
|
658
680
|
const out = [];
|
|
659
681
|
for (const node of nodes) {
|
|
660
682
|
if (node.type === "htmlText") {
|
|
661
|
-
out.push(node.value);
|
|
683
|
+
out.push(trusted ? node.value : escapeHtml2(node.value));
|
|
662
684
|
continue;
|
|
663
685
|
}
|
|
664
686
|
if (node.type === "htmlComment") {
|
|
665
|
-
out.push(`<!--${node.value}-->`);
|
|
687
|
+
if (trusted) out.push(`<!--${node.value}-->`);
|
|
666
688
|
continue;
|
|
667
689
|
}
|
|
668
690
|
const tag = node.tagName.toLowerCase();
|
|
@@ -673,6 +695,23 @@ function htmlChildrenToHtml(nodes, ctx) {
|
|
|
673
695
|
if ((tag === "video" || tag === "audio") && typeof attrs.poster === "string") {
|
|
674
696
|
attrs.poster = ctx?.images?.get(attrs.poster) ?? attrs.poster;
|
|
675
697
|
}
|
|
698
|
+
if (!trusted) {
|
|
699
|
+
if (typeof attrs.src === "string") {
|
|
700
|
+
const safeSrc = sanitizeUrl(attrs.src, "media");
|
|
701
|
+
if (!safeSrc) delete attrs.src;
|
|
702
|
+
else attrs.src = safeSrc;
|
|
703
|
+
}
|
|
704
|
+
if (typeof attrs.poster === "string") {
|
|
705
|
+
const safePoster = sanitizeUrl(attrs.poster, "media");
|
|
706
|
+
if (!safePoster) delete attrs.poster;
|
|
707
|
+
else attrs.poster = safePoster;
|
|
708
|
+
}
|
|
709
|
+
if (typeof attrs.href === "string") {
|
|
710
|
+
const safeHref = sanitizeUrl(attrs.href, "link");
|
|
711
|
+
if (!safeHref) delete attrs.href;
|
|
712
|
+
else attrs.href = safeHref;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
676
715
|
const attrStr = Object.entries(attrs).map(([k, v]) => ` ${k}="${escapeAttr(v)}"`).join("");
|
|
677
716
|
if (node.selfClosing) {
|
|
678
717
|
out.push(`<${tag}${attrStr} />`);
|
|
@@ -692,7 +731,7 @@ function escapeAttr(s) {
|
|
|
692
731
|
// src/html/plainHtmlBundle.ts
|
|
693
732
|
import JSZip from "jszip";
|
|
694
733
|
import { parseMarkdown, inferDocumentTitle } from "@bendyline/squisq/markdown";
|
|
695
|
-
import { resolveTheme
|
|
734
|
+
import { resolveTheme } from "@bendyline/squisq/schemas";
|
|
696
735
|
async function markdownDocsToPlainHtmlBundle(options) {
|
|
697
736
|
const {
|
|
698
737
|
entryPath,
|
|
@@ -704,7 +743,7 @@ async function markdownDocsToPlainHtmlBundle(options) {
|
|
|
704
743
|
maxDepth = Infinity,
|
|
705
744
|
entryAsIndex = false
|
|
706
745
|
} = options;
|
|
707
|
-
const resolvedTheme = theme ?? (themeId ?
|
|
746
|
+
const resolvedTheme = theme ?? (themeId ? resolveTheme(themeId) : void 0);
|
|
708
747
|
const entry = normalizePath(entryPath);
|
|
709
748
|
if (!entry) {
|
|
710
749
|
throw new Error("markdownDocsToPlainHtmlBundle: entryPath is required");
|
|
@@ -1126,6 +1165,210 @@ function titleForDoc(path, mdDoc) {
|
|
|
1126
1165
|
return base.replace(/\.md$/i, "");
|
|
1127
1166
|
}
|
|
1128
1167
|
|
|
1168
|
+
// src/html/import.ts
|
|
1169
|
+
import {
|
|
1170
|
+
parseHtmlToNodes,
|
|
1171
|
+
sanitizeHtmlNodes as sanitizeHtmlNodes2,
|
|
1172
|
+
stringifyMarkdown
|
|
1173
|
+
} from "@bendyline/squisq/markdown";
|
|
1174
|
+
var HEADINGS = {
|
|
1175
|
+
h1: 1,
|
|
1176
|
+
h2: 2,
|
|
1177
|
+
h3: 3,
|
|
1178
|
+
h4: 4,
|
|
1179
|
+
h5: 5,
|
|
1180
|
+
h6: 6
|
|
1181
|
+
};
|
|
1182
|
+
var TRANSPARENT_BLOCK = /* @__PURE__ */ new Set([
|
|
1183
|
+
"div",
|
|
1184
|
+
"section",
|
|
1185
|
+
"article",
|
|
1186
|
+
"header",
|
|
1187
|
+
"footer",
|
|
1188
|
+
"main",
|
|
1189
|
+
"aside",
|
|
1190
|
+
"nav",
|
|
1191
|
+
"figure",
|
|
1192
|
+
"figcaption",
|
|
1193
|
+
"form",
|
|
1194
|
+
"fieldset",
|
|
1195
|
+
"body",
|
|
1196
|
+
"html",
|
|
1197
|
+
"center"
|
|
1198
|
+
]);
|
|
1199
|
+
var DROP = /* @__PURE__ */ new Set(["script", "style", "head", "title", "noscript", "template", "svg"]);
|
|
1200
|
+
var INLINE_STRONG = /* @__PURE__ */ new Set(["strong", "b"]);
|
|
1201
|
+
var INLINE_EM = /* @__PURE__ */ new Set(["em", "i"]);
|
|
1202
|
+
var INLINE_DEL = /* @__PURE__ */ new Set(["del", "s", "strike"]);
|
|
1203
|
+
var INLINE_TRANSPARENT = /* @__PURE__ */ new Set(["span", "font", "abbr", "mark", "small", "sub", "sup", "u"]);
|
|
1204
|
+
var isElement = (n) => n.type === "htmlElement";
|
|
1205
|
+
var isText = (n) => n.type === "htmlText";
|
|
1206
|
+
var collapseWs = (s) => s.replace(/\s+/g, " ");
|
|
1207
|
+
function inlinesFromNodes(nodes) {
|
|
1208
|
+
const out = [];
|
|
1209
|
+
for (const node of nodes) {
|
|
1210
|
+
if (isText(node)) {
|
|
1211
|
+
const value = collapseWs(node.value);
|
|
1212
|
+
if (value) out.push({ type: "text", value });
|
|
1213
|
+
continue;
|
|
1214
|
+
}
|
|
1215
|
+
if (!isElement(node)) continue;
|
|
1216
|
+
const tag = node.tagName.toLowerCase();
|
|
1217
|
+
if (DROP.has(tag)) continue;
|
|
1218
|
+
if (tag === "br") {
|
|
1219
|
+
out.push({ type: "break" });
|
|
1220
|
+
} else if (INLINE_STRONG.has(tag)) {
|
|
1221
|
+
out.push({ type: "strong", children: inlinesFromNodes(node.children) });
|
|
1222
|
+
} else if (INLINE_EM.has(tag)) {
|
|
1223
|
+
out.push({ type: "emphasis", children: inlinesFromNodes(node.children) });
|
|
1224
|
+
} else if (INLINE_DEL.has(tag)) {
|
|
1225
|
+
out.push({ type: "delete", children: inlinesFromNodes(node.children) });
|
|
1226
|
+
} else if (tag === "code" || tag === "kbd" || tag === "samp" || tag === "tt") {
|
|
1227
|
+
out.push({ type: "inlineCode", value: textContent(node) });
|
|
1228
|
+
} else if (tag === "a") {
|
|
1229
|
+
const url = node.attributes.href ?? "";
|
|
1230
|
+
const children = inlinesFromNodes(node.children);
|
|
1231
|
+
out.push({
|
|
1232
|
+
type: "link",
|
|
1233
|
+
url,
|
|
1234
|
+
children: children.length > 0 ? children : [{ type: "text", value: url }]
|
|
1235
|
+
});
|
|
1236
|
+
} else if (tag === "img") {
|
|
1237
|
+
const url = node.attributes.src ?? "";
|
|
1238
|
+
const alt = node.attributes.alt;
|
|
1239
|
+
if (url) out.push({ type: "image", url, ...alt ? { alt } : {} });
|
|
1240
|
+
} else {
|
|
1241
|
+
out.push(...inlinesFromNodes(node.children));
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
return out;
|
|
1245
|
+
}
|
|
1246
|
+
function textContent(node) {
|
|
1247
|
+
if (isText(node)) return node.value;
|
|
1248
|
+
if (isElement(node)) return node.children.map(textContent).join("");
|
|
1249
|
+
return "";
|
|
1250
|
+
}
|
|
1251
|
+
var onlyWhitespace = (inlines) => inlines.every((n) => n.type === "text" && n.value.trim() === "");
|
|
1252
|
+
function blocksFromNodes(nodes) {
|
|
1253
|
+
const out = [];
|
|
1254
|
+
let inlineBuffer = [];
|
|
1255
|
+
const flush = () => {
|
|
1256
|
+
if (inlineBuffer.length === 0) return;
|
|
1257
|
+
const inlines = inlinesFromNodes(inlineBuffer);
|
|
1258
|
+
inlineBuffer = [];
|
|
1259
|
+
if (inlines.length > 0 && !onlyWhitespace(inlines)) {
|
|
1260
|
+
out.push({ type: "paragraph", children: inlines });
|
|
1261
|
+
}
|
|
1262
|
+
};
|
|
1263
|
+
for (const node of nodes) {
|
|
1264
|
+
if (isText(node)) {
|
|
1265
|
+
inlineBuffer.push(node);
|
|
1266
|
+
continue;
|
|
1267
|
+
}
|
|
1268
|
+
if (!isElement(node)) continue;
|
|
1269
|
+
const tag = node.tagName.toLowerCase();
|
|
1270
|
+
if (DROP.has(tag)) continue;
|
|
1271
|
+
const block = blockForElement(node, tag);
|
|
1272
|
+
if (block === "inline") {
|
|
1273
|
+
inlineBuffer.push(node);
|
|
1274
|
+
} else if (block) {
|
|
1275
|
+
flush();
|
|
1276
|
+
out.push(...block);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
flush();
|
|
1280
|
+
return out;
|
|
1281
|
+
}
|
|
1282
|
+
function blockForElement(node, tag) {
|
|
1283
|
+
if (tag in HEADINGS) {
|
|
1284
|
+
const children = inlinesFromNodes(node.children);
|
|
1285
|
+
return [{ type: "heading", depth: HEADINGS[tag], children }];
|
|
1286
|
+
}
|
|
1287
|
+
if (tag === "p") {
|
|
1288
|
+
const children = inlinesFromNodes(node.children);
|
|
1289
|
+
return children.length > 0 && !onlyWhitespace(children) ? [{ type: "paragraph", children }] : [];
|
|
1290
|
+
}
|
|
1291
|
+
if (tag === "br") return "inline";
|
|
1292
|
+
if (tag === "hr") return [{ type: "thematicBreak" }];
|
|
1293
|
+
if (tag === "blockquote") {
|
|
1294
|
+
return [{ type: "blockquote", children: blocksFromNodes(node.children) }];
|
|
1295
|
+
}
|
|
1296
|
+
if (tag === "pre") {
|
|
1297
|
+
return [{ type: "code", value: stripTrailingNewline(textContent(node)) }];
|
|
1298
|
+
}
|
|
1299
|
+
if (tag === "ul" || tag === "ol") {
|
|
1300
|
+
return [listFromElement(node, tag === "ol")];
|
|
1301
|
+
}
|
|
1302
|
+
if (tag === "table") {
|
|
1303
|
+
const table = tableFromElement(node);
|
|
1304
|
+
return table ? [table] : [];
|
|
1305
|
+
}
|
|
1306
|
+
if (TRANSPARENT_BLOCK.has(tag)) {
|
|
1307
|
+
return blocksFromNodes(node.children);
|
|
1308
|
+
}
|
|
1309
|
+
if (INLINE_STRONG.has(tag) || INLINE_EM.has(tag) || INLINE_DEL.has(tag) || INLINE_TRANSPARENT.has(tag) || tag === "a" || tag === "img" || tag === "code" || tag === "kbd" || tag === "samp") {
|
|
1310
|
+
return "inline";
|
|
1311
|
+
}
|
|
1312
|
+
return blocksFromNodes(node.children);
|
|
1313
|
+
}
|
|
1314
|
+
function listFromElement(node, ordered) {
|
|
1315
|
+
const items = [];
|
|
1316
|
+
for (const child of node.children) {
|
|
1317
|
+
if (isElement(child) && child.tagName.toLowerCase() === "li") {
|
|
1318
|
+
const blocks = blocksFromNodes(child.children);
|
|
1319
|
+
items.push({ type: "listItem", children: blocks });
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
const startAttr = node.attributes.start;
|
|
1323
|
+
const start = ordered && startAttr ? Number.parseInt(startAttr, 10) : void 0;
|
|
1324
|
+
return {
|
|
1325
|
+
type: "list",
|
|
1326
|
+
ordered,
|
|
1327
|
+
...start !== void 0 && Number.isFinite(start) ? { start } : {},
|
|
1328
|
+
children: items
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
function tableFromElement(node) {
|
|
1332
|
+
const rows = [];
|
|
1333
|
+
const collectRows = (n) => {
|
|
1334
|
+
for (const child of n.children) {
|
|
1335
|
+
if (!isElement(child)) continue;
|
|
1336
|
+
const t = child.tagName.toLowerCase();
|
|
1337
|
+
if (t === "tr") {
|
|
1338
|
+
const cells = [];
|
|
1339
|
+
for (const cell of child.children) {
|
|
1340
|
+
if (isElement(cell) && (cell.tagName.toLowerCase() === "td" || cell.tagName.toLowerCase() === "th")) {
|
|
1341
|
+
cells.push({ type: "tableCell", children: inlinesFromNodes(cell.children) });
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
if (cells.length > 0) rows.push({ type: "tableRow", children: cells });
|
|
1345
|
+
} else if (t === "thead" || t === "tbody" || t === "tfoot") {
|
|
1346
|
+
collectRows(child);
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
};
|
|
1350
|
+
collectRows(node);
|
|
1351
|
+
if (rows.length === 0) return null;
|
|
1352
|
+
return { type: "table", children: rows };
|
|
1353
|
+
}
|
|
1354
|
+
var stripTrailingNewline = (s) => s.replace(/\n+$/, "");
|
|
1355
|
+
function toHtmlString(data) {
|
|
1356
|
+
if (typeof data === "string") return data;
|
|
1357
|
+
const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
1358
|
+
return new TextDecoder("utf-8").decode(bytes);
|
|
1359
|
+
}
|
|
1360
|
+
function htmlToMarkdownDocSync(html, options = {}) {
|
|
1361
|
+
let nodes = parseHtmlToNodes(html);
|
|
1362
|
+
if (options.sanitize !== false) nodes = sanitizeHtmlNodes2(nodes);
|
|
1363
|
+
return { type: "document", children: blocksFromNodes(nodes) };
|
|
1364
|
+
}
|
|
1365
|
+
async function htmlToMarkdownDoc(data, options = {}) {
|
|
1366
|
+
return htmlToMarkdownDocSync(toHtmlString(data), options);
|
|
1367
|
+
}
|
|
1368
|
+
function htmlToMarkdown(html, options = {}) {
|
|
1369
|
+
return stringifyMarkdown(htmlToMarkdownDocSync(html, options));
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1129
1372
|
// src/html/index.ts
|
|
1130
1373
|
function sanitizeZipPath3(path) {
|
|
1131
1374
|
const normalized = path.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
@@ -1181,7 +1424,10 @@ export {
|
|
|
1181
1424
|
markdownDocsToPlainHtmlBundle,
|
|
1182
1425
|
collectLinkRefs,
|
|
1183
1426
|
markdownDocsToHtmlBundle,
|
|
1427
|
+
htmlToMarkdownDocSync,
|
|
1428
|
+
htmlToMarkdownDoc,
|
|
1429
|
+
htmlToMarkdown,
|
|
1184
1430
|
docToHtml,
|
|
1185
1431
|
docToHtmlZip
|
|
1186
1432
|
};
|
|
1187
|
-
//# sourceMappingURL=chunk-
|
|
1433
|
+
//# sourceMappingURL=chunk-46FMDOWZ.js.map
|