@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 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 ExcelJS from "exceljs";
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.4";
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 workbook = new Workbook();
295
- await workbook.xlsx.load(toArrayBuffer(source));
374
+ const sheets = await readExcelFile(toArrayBuffer(source));
296
375
  const sections = [];
297
- for (const worksheet of workbook.worksheets) {
298
- const html = worksheetToHtml(worksheet);
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(`## ${worksheet.name}\n${result?.markdown.trim() ?? ""}`);
380
+ sections.push(`## ${sheet}\n${result?.markdown.trim() ?? ""}`);
302
381
  }
303
382
  const markdown = sections.join("\n\n");
304
383
  return {
305
- title: workbook.title || "Untitled",
384
+ title: null,
306
385
  markdown,
307
386
  text_content: markdown
308
387
  };
309
388
  }
310
389
  };
311
- function worksheetToHtml(worksheet) {
312
- const columnCount = worksheet.columnCount;
313
- if (!columnCount || !worksheet.actualRowCount) return "";
314
- const rows = [];
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 = 1; column <= columnCount; column++) cells.push(`<td>${escapeHtml(cellText(row.getCell(column)))}</td>`);
318
- rows.push(`<tr>${cells.join("")}</tr>`);
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(cell) {
323
- if (cell.isMerged && cell.master !== cell) return "";
324
- return cell.text;
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -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
  }