@ryangarber/markitdown-ts 0.1.4 → 0.1.5
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 +1 -0
- package/dist/cli.mjs +101 -22
- package/dist/index.cjs +11506 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +100 -21
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
- Jupyter notebooks (`.ipynb`)
|
|
11
11
|
- Word documents (`.docx`)
|
|
12
12
|
- Excel workbooks (`.xlsx`)
|
|
13
|
+
- PowerPoint presentations (`.pptx`)
|
|
13
14
|
- PDF documents (`.pdf`)
|
|
14
15
|
- ZIP archives (`.zip`), with nested files converted recursively
|
|
15
16
|
- Wikipedia, YouTube metadata, and Bing result pages supplied as HTML
|
package/dist/cli.mjs
CHANGED
|
@@ -5,11 +5,12 @@ import TurndownService from "turndown";
|
|
|
5
5
|
import { parseHTML } from "linkedom";
|
|
6
6
|
import mammoth from "mammoth";
|
|
7
7
|
import { extractText, getDocumentProxy, getMeta } from "unpdf";
|
|
8
|
-
import
|
|
9
|
-
import { DOMParser } from "@xmldom/xmldom";
|
|
8
|
+
import { pptxToHtml } from "@jvmr/pptx-to-html";
|
|
9
|
+
import { DOMParser, Document, Element, Node } from "@xmldom/xmldom";
|
|
10
|
+
import readExcelFile from "read-excel-file/universal";
|
|
10
11
|
import { unzipSync } from "fflate";
|
|
11
12
|
//#region package.json
|
|
12
|
-
var version = "0.1.
|
|
13
|
+
var version = "0.1.5";
|
|
13
14
|
//#endregion
|
|
14
15
|
//#region src/bytes.ts
|
|
15
16
|
async function toUint8Array(source) {
|
|
@@ -220,6 +221,7 @@ const MIME_EXTENSIONS = {
|
|
|
220
221
|
"application/zip": ".zip",
|
|
221
222
|
"application/rss+xml": ".rss",
|
|
222
223
|
"application/x-pdf": ".pdf",
|
|
224
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation": ".pptx",
|
|
223
225
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": ".xlsx",
|
|
224
226
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
|
|
225
227
|
"application/xml": ".xml",
|
|
@@ -265,6 +267,85 @@ var PlainTextConverter = class {
|
|
|
265
267
|
}
|
|
266
268
|
};
|
|
267
269
|
//#endregion
|
|
270
|
+
//#region src/converters/pptx.ts
|
|
271
|
+
var PptxConverter = class extends HtmlConverter {
|
|
272
|
+
async convert(source, options) {
|
|
273
|
+
if (options.file_extension?.toLowerCase() !== ".pptx") return null;
|
|
274
|
+
const slides = await pptxToHtml(toArrayBuffer(source), { domParserFactory: createPptxDomParser });
|
|
275
|
+
const sections = [];
|
|
276
|
+
for (const [index, html] of slides.entries()) {
|
|
277
|
+
const result = await this.convertHtml(`<html><body>${html}</body></html>`);
|
|
278
|
+
sections.push(`<!-- Slide number: ${index + 1} -->\n${result?.markdown.trim() ?? ""}`);
|
|
279
|
+
}
|
|
280
|
+
const markdown = sections.join("\n\n");
|
|
281
|
+
return {
|
|
282
|
+
title: null,
|
|
283
|
+
markdown,
|
|
284
|
+
text_content: markdown
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
function createPptxDomParser() {
|
|
289
|
+
if (typeof globalThis.DOMParser === "function") return new globalThis.DOMParser();
|
|
290
|
+
patchXmlDom();
|
|
291
|
+
return new DOMParser();
|
|
292
|
+
}
|
|
293
|
+
let xmlDomPatched = false;
|
|
294
|
+
function patchXmlDom() {
|
|
295
|
+
if (xmlDomPatched) return;
|
|
296
|
+
xmlDomPatched = true;
|
|
297
|
+
defineMethod(Element.prototype, "querySelector", querySelector);
|
|
298
|
+
defineMethod(Element.prototype, "querySelectorAll", querySelectorAll);
|
|
299
|
+
defineMethod(Document.prototype, "querySelector", querySelector);
|
|
300
|
+
defineMethod(Document.prototype, "querySelectorAll", querySelectorAll);
|
|
301
|
+
defineGetter(Element.prototype, "children", function() {
|
|
302
|
+
return [...this.childNodes].filter((node) => node.nodeType === 1);
|
|
303
|
+
});
|
|
304
|
+
defineGetter(Node.prototype, "parentElement", function() {
|
|
305
|
+
const parent = this.parentNode;
|
|
306
|
+
return parent?.nodeType === 1 ? parent : null;
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
function querySelector(selector) {
|
|
310
|
+
for (const group of selector.split(",")) {
|
|
311
|
+
const match = queryByPath(this, group.trim());
|
|
312
|
+
if (match) return match;
|
|
313
|
+
}
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
function querySelectorAll() {
|
|
317
|
+
return [];
|
|
318
|
+
}
|
|
319
|
+
function queryByPath(root, selector) {
|
|
320
|
+
const tokens = selector.split(/\s+/).filter(Boolean);
|
|
321
|
+
let current = [root];
|
|
322
|
+
for (const token of tokens) {
|
|
323
|
+
const localName = selectorLocalName(token);
|
|
324
|
+
const next = [];
|
|
325
|
+
for (const node of current) next.push(...Array.from(node.getElementsByTagNameNS("*", localName)));
|
|
326
|
+
current = next;
|
|
327
|
+
}
|
|
328
|
+
return current[0] ?? null;
|
|
329
|
+
}
|
|
330
|
+
function selectorLocalName(token) {
|
|
331
|
+
if (token.includes("|")) return token.slice(token.lastIndexOf("|") + 1);
|
|
332
|
+
return token.replace(/\\:/g, ":").split(":").pop() ?? token;
|
|
333
|
+
}
|
|
334
|
+
function defineMethod(target, name, value) {
|
|
335
|
+
Object.defineProperty(target, name, {
|
|
336
|
+
configurable: true,
|
|
337
|
+
writable: true,
|
|
338
|
+
value
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
function defineGetter(target, name, get) {
|
|
342
|
+
if (Object.getOwnPropertyDescriptor(target, name)) return;
|
|
343
|
+
Object.defineProperty(target, name, {
|
|
344
|
+
configurable: true,
|
|
345
|
+
get
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
//#endregion
|
|
268
349
|
//#region src/converters/wikipedia.ts
|
|
269
350
|
const WIKIPEDIA_URL = /^https?:\/\/[a-z]{2,3}\.wikipedia\.org\//i;
|
|
270
351
|
var WikipediaConverter = class {
|
|
@@ -287,41 +368,38 @@ var WikipediaConverter = class {
|
|
|
287
368
|
};
|
|
288
369
|
//#endregion
|
|
289
370
|
//#region src/converters/xlsx.ts
|
|
290
|
-
const { Workbook } = ExcelJS;
|
|
291
371
|
var XlsxConverter = class extends HtmlConverter {
|
|
292
372
|
async convert(source, options) {
|
|
293
373
|
if (options.file_extension?.toLowerCase() !== ".xlsx") return null;
|
|
294
|
-
const
|
|
295
|
-
await workbook.xlsx.load(toArrayBuffer(source));
|
|
374
|
+
const sheets = await readExcelFile(toArrayBuffer(source));
|
|
296
375
|
const sections = [];
|
|
297
|
-
for (const
|
|
298
|
-
const html =
|
|
376
|
+
for (const { sheet, data } of sheets) {
|
|
377
|
+
const html = sheetToHtml(data);
|
|
299
378
|
if (!html) continue;
|
|
300
379
|
const result = await this.convertHtml(html);
|
|
301
|
-
sections.push(`## ${
|
|
380
|
+
sections.push(`## ${sheet}\n${result?.markdown.trim() ?? ""}`);
|
|
302
381
|
}
|
|
303
382
|
const markdown = sections.join("\n\n");
|
|
304
383
|
return {
|
|
305
|
-
title:
|
|
384
|
+
title: null,
|
|
306
385
|
markdown,
|
|
307
386
|
text_content: markdown
|
|
308
387
|
};
|
|
309
388
|
}
|
|
310
389
|
};
|
|
311
|
-
function
|
|
312
|
-
const columnCount =
|
|
313
|
-
if (!columnCount ||
|
|
314
|
-
|
|
315
|
-
worksheet.eachRow({ includeEmpty: true }, (row) => {
|
|
390
|
+
function sheetToHtml(rows) {
|
|
391
|
+
const columnCount = rows.reduce((max, row) => Math.max(max, row.length), 0);
|
|
392
|
+
if (!columnCount || rows.length === 0) return "";
|
|
393
|
+
return `<html><body><table>${rows.map((row) => {
|
|
316
394
|
const cells = [];
|
|
317
|
-
for (let column =
|
|
318
|
-
|
|
319
|
-
})
|
|
320
|
-
return `<html><body><table>${rows.join("")}</table></body></html>`;
|
|
395
|
+
for (let column = 0; column < columnCount; column++) cells.push(`<td>${escapeHtml(cellText(row[column]))}</td>`);
|
|
396
|
+
return `<tr>${cells.join("")}</tr>`;
|
|
397
|
+
}).join("")}</table></body></html>`;
|
|
321
398
|
}
|
|
322
|
-
function cellText(
|
|
323
|
-
if (
|
|
324
|
-
return
|
|
399
|
+
function cellText(value) {
|
|
400
|
+
if (value == null) return "";
|
|
401
|
+
if (value instanceof Date) return value.toISOString();
|
|
402
|
+
return String(value);
|
|
325
403
|
}
|
|
326
404
|
function escapeHtml(value) {
|
|
327
405
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
@@ -520,6 +598,7 @@ var MarkItDown = class {
|
|
|
520
598
|
this.registerConverter(new BingSerpConverter());
|
|
521
599
|
this.registerConverter(new DocxConverter());
|
|
522
600
|
this.registerConverter(new XlsxConverter());
|
|
601
|
+
this.registerConverter(new PptxConverter());
|
|
523
602
|
this.registerConverter(new PdfConverter());
|
|
524
603
|
this.registerConverter(new IpynbConverter());
|
|
525
604
|
}
|