diff --git a/Helpers/DocumentHelper.ts b/Helpers/DocumentHelper.ts index 4a01b13..39e6bd1 100644 --- a/Helpers/DocumentHelper.ts +++ b/Helpers/DocumentHelper.ts @@ -1,18 +1,26 @@ -import { extractText, getDocumentProxy } from 'unpdf'; +import { loadPdfJs } from 'obsidian'; +import { unzipSync, strFromU8 } from 'fflate'; +import mammoth from 'mammoth/mammoth.browser.js'; import type { IPageText } from '../Types/SearchTypes'; import { Exception } from './Exception'; -import { parseOffice } from 'officeparser'; -// Handles PDF format +// Uses Obsidian's own bundled PDF.js via loadPdfJs() rather than shipping our own export async function readPDF(arrayBuffer: ArrayBuffer): Promise { try { - const pdf = await getDocumentProxy(new Uint8Array(arrayBuffer), { isEvalSupported: false }); - const pages = (await extractText(pdf, { mergePages: false })).text; + const pdfjs = await loadPdfJs(); + const pdf = await pdfjs.getDocument({ data: new Uint8Array(arrayBuffer) }).promise; - const pageTexts: IPageText[] = pages.map((pageText, index) => ({ - text: pageText, - pageNumber: index + 1 - })); + const pageTexts: IPageText[] = []; + for (let i = 1; i <= pdf.numPages; i++) { + const page = await pdf.getPage(i); + const content = await page.getTextContent(); + const text = content.items + .map((item: { str?: string }) => item.str ?? '') + .join(' '); + pageTexts.push({ text, pageNumber: i }); + page.cleanup?.(); + } + await pdf.destroy?.(); return pageTexts; } catch (error) { @@ -31,18 +39,137 @@ export async function readPDF(arrayBuffer: ArrayBuffer): Promise { } } -// Handles document formats: DOCX, PPTX, XLSX, ODT, ODP, ODS -export async function readDocument(arrayBuffer: ArrayBuffer): Promise { +// Handles document formats: DOCX, PPTX, XLSX, ODT, ODP, ODS. +// +// DOCX goes through mammoth (battle-tested: tables, lists, footnotes). The remaining +// formats are ZIP-of-XML containers we read with fflate + the platform DOMParser, so +// no heavy parser is bundled. We only extract plain text (no OCR, no images) — the LLM +// can read files directly and use its own vision engine when it needs to. +export async function readDocument(arrayBuffer: ArrayBuffer, extension: string): Promise { try { - const ast = await parseOffice(arrayBuffer, { - extractAttachments: true, - ocr: true, - ocrLanguage: "eng+esp" - }); + let text: string; + switch (extension.toLowerCase()) { + case 'docx': + text = (await mammoth.extractRawText({ arrayBuffer })).value; + break; + case 'xlsx': + text = extractXlsx(arrayBuffer); + break; + case 'pptx': + text = extractPptx(arrayBuffer); + break; + case 'odt': + case 'odp': + case 'ods': + text = extractOdf(arrayBuffer); + break; + default: + throw Exception.new(`Unsupported document type: .${extension}`); + } - // OfficeParser doesn't currently expose page data (page number etc) - return [{ text: (await ast.to('text')).value, pageNumber: 1 }] as IPageText[]; + // These formats expose no page structure, so we return a single page + return [{ text, pageNumber: 1 }] as IPageText[]; } catch (error) { return [{ text: `Failed to read document: ${Exception.messageFrom(error)}`, pageNumber: 1 }] as IPageText[]; } -} \ No newline at end of file +} + +// --- Shared helpers for the ZIP-of-XML formats (xlsx / pptx / odf) --- + +// Throws on legacy OLE2 binaries (.xls/.ppt/.doc) — they aren't ZIPs. Callers wrap +// this so the failure surfaces as a clean "failed to read" message. +function unzip(arrayBuffer: ArrayBuffer): Record { + return unzipSync(new Uint8Array(arrayBuffer)); +} + +function parseXml(bytes: Uint8Array): Document { + return new DOMParser().parseFromString(strFromU8(bytes), 'application/xml'); +} + +/** Numeric sort key from a path like "ppt/slides/slide12.xml" -> 12. */ +function ordinal(path: string): number { + const match = path.match(/(\d+)\.xml$/); + return match ? Number(match[1]) : 0; +} + +// --- XLSX: values live as indices into a shared-strings table --- +function extractXlsx(arrayBuffer: ArrayBuffer): string { + const files = unzip(arrayBuffer); + + // Resolve the shared-strings table (cells of type "s" point into this). + let shared: string[] = []; + if (files['xl/sharedStrings.xml']) { + const dom = parseXml(files['xl/sharedStrings.xml']); + shared = Array.from(dom.getElementsByTagName('si')).map((si) => + Array.from(si.getElementsByTagName('t')) + .map((t) => t.textContent ?? '') + .join('') + ); + } + + const sheets = Object.keys(files) + .filter((name) => /^xl\/worksheets\/sheet\d+\.xml$/.test(name)) + .sort((a, b) => ordinal(a) - ordinal(b)); + + const rows: string[] = []; + for (const name of sheets) { + const dom = parseXml(files[name]); + for (const row of Array.from(dom.getElementsByTagName('row'))) { + const cells = Array.from(row.getElementsByTagName('c')).map((cell) => { + const type = cell.getAttribute('t'); + if (type === 'inlineStr') { + // Text stored directly in the cell: + return Array.from(cell.getElementsByTagName('t')) + .map((t) => t.textContent ?? '') + .join(''); + } + const value = cell.getElementsByTagName('v')[0]; + if (!value) return ''; + return type === 's' + ? shared[Number(value.textContent)] ?? '' + : value.textContent ?? ''; + }); + rows.push(cells.join('\t')); + } + } + return rows.join('\n'); +} + +// --- PPTX: one XML per slide; sort numerically so output is in slide order --- +function extractPptx(arrayBuffer: ArrayBuffer): string { + const files = unzip(arrayBuffer); + + const slides = Object.keys(files) + .filter((name) => /^ppt\/slides\/slide\d+\.xml$/.test(name)) + .sort((a, b) => ordinal(a) - ordinal(b)); + + return slides + .map((name) => { + const dom = parseXml(files[name]); + return Array.from(dom.getElementsByTagName('a:t')) + .map((t) => t.textContent ?? '') + .join(' '); + }) + .join('\n\n'); +} + +// --- ODF (odt / ods / odp): everything lives in a single content.xml --- +function extractOdf(arrayBuffer: ArrayBuffer): string { + const files = unzip(arrayBuffer); + if (!files['content.xml']) return ''; + + const dom = parseXml(files['content.xml']); + + // Single document-order pass over paragraphs (text:p) and headings (text:h). + // getElementsByTagName("*") preserves order, keeping body text, spreadsheet cells, + // and slide text in the sequence they appear. + const out: string[] = []; + const all = dom.getElementsByTagName('*'); + for (let i = 0; i < all.length; i++) { + const tag = all[i].tagName; // prefixed, e.g. "text:p" + if (tag === 'text:p' || tag === 'text:h') { + out.push(all[i].textContent ?? ''); + } + } + return out.join('\n'); +} diff --git a/README.md b/README.md index 33bc890..96751b9 100644 --- a/README.md +++ b/README.md @@ -410,8 +410,9 @@ This plugin is built on the shoulders of many excellent projects: - Official SDKs: [@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript), [@google/genai](https://github.com/google/generative-ai-js), [openai](https://github.com/openai/openai-node) **Document Processing** -- [unpdf](https://github.com/unjs/unpdf) - PDF parsing and text extraction -- [officeparser](https://github.com/nicktomlin/officeparser) - Office document parsing (DOCX, PPTX, XLSX, ODT, ODP, ODS) +- [mammoth](https://github.com/mwilliamson/mammoth.js) - DOCX text extraction +- [fflate](https://github.com/101arrowz/fflate) - Unzipping Office Open XML / OpenDocument files (PPTX, XLSX, ODT, ODP, ODS) +- PDF text extraction via Obsidian's bundled [PDF.js](https://mozilla.github.io/pdf.js/) (`loadPdfJs()`) **UI Framework** - [Svelte](https://svelte.dev) - Reactive UI components diff --git a/Services/InputService.ts b/Services/InputService.ts index 6294849..c6557d7 100644 --- a/Services/InputService.ts +++ b/Services/InputService.ts @@ -48,7 +48,7 @@ export class InputService { } if (isDocumentFile(fileType)) { - const content = await readDocument(await file.arrayBuffer()); + const content = await readDocument(await file.arrayBuffer(), fileType); attachments.push(new Attachment( file.name, MimeType.TEXT_PLAIN, diff --git a/Services/VaultService.ts b/Services/VaultService.ts index 7e01c69..dcf87dd 100644 --- a/Services/VaultService.ts +++ b/Services/VaultService.ts @@ -98,7 +98,7 @@ export class VaultService { if (isDocumentFile(fileExtension)) { const arrayBuffer = await this.readBinaryData(file, allowAccessToPluginRoot); if (arrayBuffer) { - return (await readDocument(arrayBuffer))[0].text; + return (await readDocument(arrayBuffer, fileExtension))[0].text; } } @@ -418,7 +418,7 @@ export class VaultService { content = await readPDF(arrayBuffer); } else if (isDocumentFile(fileExtension)) { const arrayBuffer = await this.vault.readBinary(file); - content = await readDocument(arrayBuffer); + content = await readDocument(arrayBuffer, fileExtension); } else { content = [{ text: await this.vault.cachedRead(file), pageNumber: 1 }] as IPageText[]; } diff --git a/esbuild.config.mjs b/esbuild.config.mjs index 2d94720..343f244 100644 --- a/esbuild.config.mjs +++ b/esbuild.config.mjs @@ -41,26 +41,23 @@ function copyDir(src, dest) { // Neutralises `new Function(...)` literals in the bundled output. // -// All such literals come from dependencies, never from our own source: -// - unpdf/PDF.js: 3x feature-detection probes `new Function("")` wrapped in -// try/catch (a throw makes them return `false` = "eval not supported", the -// safe answer), plus 1x PostScript JIT compiler gated behind -// `isEvalSupported` (we pass `false`, so it is never entered). +// All such literals come from dependencies, never from our own source, and every +// one is dead code in our usage: +// - bluebird (transitive via mammoth): 7x promise-method JIT compilers, ALL +// gated behind `canEvaluate = typeof navigator == "undefined"`. Obsidian always +// defines `navigator`, so `canEvaluate` is false and bluebird takes its pure-JS +// fallbacks — the `new Function` branches are never entered. (call_get.js x2, +// join.js x3, promisify.js x2.) // - diff2html/@profoundlogic/hogan: 2x template compilers reachable only via // Hogan.compile(), which diff2html invokes only for runtime `rawTemplates`. // We use diff2html's precompiled defaults, so these never run. // -// Every occurrence is therefore dead code in our usage. We rewrite them to a -// throwing stub so the bundle contains no `new Function(` literal, which clears -// the Obsidian scanner's "Dynamic Code Execution" warning. The build FAILS if -// the count drifts from EXPECTED_NEW_FUNCTION_COUNT, so a dependency change can -// never silently reintroduce a live (or un-neutralised) dynamic-eval path. -// 9 = 5 PDF.js feature-detection probes (`new Function(""),!0}catch{return!1}`) -// + 2 PDF.js PostScript JIT compilers (gated behind `isEvalSupported`, which -// DocumentHelper passes as `false`) + 2 Hogan template compilers (reachable -// only via Hogan.compile(), unused with diff2html's precompiled templates). -// unpdf >=1.6 vendors PDF.js twice (main + worker/legacy), so the PDF.js probe -// and JIT sites each appear in duplicate; the Hogan pair is unchanged. +// We rewrite them to a throwing stub so the bundle contains no `new Function(` +// literal, which clears the Obsidian scanner's "Dynamic Code Execution" warning. The +// build FAILS if the count drifts from EXPECTED_NEW_FUNCTION_COUNT, so a dependency +// change can never silently reintroduce a live (or un-neutralised) dynamic-eval path. +// +// 9 = 7 bluebird (canEvaluate-gated) + 2 Hogan. const EXPECTED_NEW_FUNCTION_COUNT = 9; const NEW_FUNCTION_STUB = "VKBlockedDynamicFn"; function neutraliseDynamicEval(outfile) { @@ -94,98 +91,15 @@ function neutraliseDynamicEval(outfile) { ); } -// Neutralises the `.wasm` filename literals in the bundled output. -// -// Every reference comes from unpdf's vendored PDF.js, which loads optional -// WebAssembly modules only when *rendering/decoding image streams*: -// - qcms_bg.wasm — colour management (ICC profile transforms) -// - jbig2.wasm — JBIG2 decoder (scanned bilevel images) -// - openjpeg.wasm — OpenJPEG decoder (JPEG2000 images) -// Our PDF code (Helpers/DocumentHelper.ts) only calls extractText for text and -// never renders, so none of these loaders is entered. Each is also gated behind -// private-field checks and resolves its file via a relative URL we do not ship, -// so even if reached it falls back to PDF.js's pure-JS path. (unpdf >=1.6 -// vendors PDF.js twice, so qcms_bg.wasm appears in duplicate.) -// -// The literals are therefore dead, but their `.wasm` filenames trip Obsidian's -// "unrecognised .wasm" scanner (native binary that can't be statically -// reviewed). We rewrite each `*.wasm` filename to a non-`.wasm` name so no -// `.wasm` literal remains; the surrounding (unreachable) code stays intact. The -// build FAILS if an unexpected `.wasm` literal appears (or an expected one -// vanishes), so a dependency change can never silently reintroduce an -// undocumented .wasm reference. -// -// Keyed by literal filename → number of occurrences expected in the bundle. -const EXPECTED_WASM_REFS = { - "qcms_bg.wasm": 2, - "jbig2.wasm": 1, - "openjpeg.wasm": 1, -}; -const WASM_REF_SUFFIX_FROM = ".wasm"; -const WASM_REF_SUFFIX_TO = ".disabled-wasm"; -function neutraliseWasmRef(outfile) { - if (!existsSync(outfile)) return; - let contents = readFileSync(outfile, "utf-8"); - // Match the whole quoted/templated literal ending in `.wasm`, anchored on the - // quote/backtick. The negated class `[^'"`]` cannot overlap the delimiters, so - // this matches linearly — a `[\w.-]*\.wasm` form instead backtracks - // catastrophically on the megabytes of base64 in the dev inline sourcemap and - // hangs the watcher at 100% CPU. - const wasmLiterals = contents.match(/['"`][^'"`]*\.wasm['"`]/g) || []; - // Extract just the `.wasm` basename from each literal: drop the quotes, - // and for template literals drop any `${...}` interpolation prefix (qcms refs - // look like `` `${...}qcms_bg.wasm` ``). The basename is the trailing run of - // filename characters ending in `.wasm`. - const found = {}; - for (const lit of wasmLiterals) { - const inner = lit.slice(1, -1); - const name = (inner.match(/[\w.-]+\.wasm$/) || [inner])[0]; - found[name] = (found[name] || 0) + 1; - } - // Any literal we don't recognise → fail loudly (new undocumented .wasm). - const unknown = Object.keys(found).filter((n) => !(n in EXPECTED_WASM_REFS)); - if (unknown.length) { - throw new Error( - `neutraliseWasmRef: unexpected \`.wasm\` literal(s) in ${outfile}: ` + - `${unknown.join(", ")}. A dependency introduced a new .wasm reference — ` + - `re-audit that it is unreachable, then add it to EXPECTED_WASM_REFS.`, - ); - } - // Each expected filename must be present with the expected count. - for (const [name, count] of Object.entries(EXPECTED_WASM_REFS)) { - if ((found[name] || 0) !== count) { - throw new Error( - `neutraliseWasmRef: expected ${count} \`${name}\` literal(s) in ` + - `${outfile} but found ${found[name] || 0}. The .wasm references ` + - `changed shape — re-audit before shipping, then update ` + - `EXPECTED_WASM_REFS.`, - ); - } - } - // Rewrite only the `.wasm` extension on the literals we've vetted, so no - // `.wasm` string remains for the scanner to flag. - for (const name of Object.keys(EXPECTED_WASM_REFS)) { - contents = contents.split(name).join( - name.slice(0, -WASM_REF_SUFFIX_FROM.length) + WASM_REF_SUFFIX_TO, - ); - } - writeFileSync(outfile, contents); - console.log( - `🛡️ Neutralised ${wasmLiterals.length} \`.wasm\` reference(s) ` + - `(${Object.keys(EXPECTED_WASM_REFS).join(", ")}) in ${outfile}`, - ); -} - -// Runs the dynamic-eval and .wasm neutralisation on every build and rebuild, for -// both dev and production, so the dev bundle matches what ships and the post-build -// step is exercised continuously rather than only at release time. Registered last -// so it transforms the finalised main.js. +// Runs the dynamic-eval neutralisation on every build and rebuild, for both dev and +// production, so the dev bundle matches what ships and the post-build step is +// exercised continuously rather than only at release time. Registered last so it +// transforms the finalised main.js. const dynamicEvalPlugin = { name: "neutralise-dynamic-eval", setup(build) { build.onEnd(() => { neutraliseDynamicEval(build.initialOptions.outfile); - neutraliseWasmRef(build.initialOptions.outfile); }); }, }; @@ -253,64 +167,8 @@ const cssMergerPlugin = { } }; -// officeparser's browser bundle is an IIFE (var officeParser = (()=> { ... })()) that doesn't -// set module.exports, so esbuild can't resolve its exports. This plugin intercepts the resolve -// and appends a CJS export line so imports work correctly. -// -// The browser bundle contains a dynamic-require shim (from its own esbuild bundling) that our -// esbuild would otherwise resolve against the `external` list, emitting require("fs") etc. in -// the final output. On Obsidian mobile there is no "fs" module, so we replace that shim with a -// stub that always throws, keeping the bundle self-contained. -// -// Every identifier in the shim is minified and churns between releases — not just the outer -// variable name (Au in v5, Vm in v6, Gs in v7.1.0, dl in v7.2.1) but also the closure params -// (r/t/e in v7.1.0 became n/e/t in v7.2.1). So the regex captures whatever identifiers appear -// rather than hardcoding any of them. If the shim's *shape* changes such that nothing matches, -// the build FAILS loudly — a silent no-op here previously let the stale v6 `Vm` regex match -// nothing on v7, and the hardcoded v7.1.0 param names broke against v7.2.1. -const officeParserPlugin = { - name: "officeparser-cjs-shim", - setup(build) { - build.onResolve({ filter: /^officeparser$/ }, () => ({ - path: join(process.cwd(), 'node_modules', 'officeparser', 'dist', 'officeparser.browser.iife.js'), - namespace: 'officeparser-shim', - })); - build.onLoad({ filter: /.*/, namespace: 'officeparser-shim' }, async (args) => { - let contents = readFileSync(args.path, 'utf-8'); - // Capture the (minified) outer var in group 1 and every other minified identifier in its - // own group, reusing the captures via backreferences so we match regardless of which letters - // esbuild chose this release. Group map: 1=outer var, 2=arrow param, 3/4=getter params, - // 5=function param. - const id = "[A-Za-z_$][\\w$]*"; - const shimPattern = new RegExp( - `var (${id})=\\((${id})=>typeof require<"u"\\?require:typeof Proxy<"u"\\?` + - `new Proxy\\(\\2,\\{get:\\((${id}),(${id})\\)=>\\(typeof require<"u"\\?require:\\3\\)` + - `\\[\\4\\]\\}\\):\\2\\)\\(function\\((${id})\\)\\{if\\(typeof require<"u"\\)` + - `return require\\.apply\\(this,arguments\\);` + - `throw Error\\('Dynamic require of "'\\+\\5\\+'" is not supported'\\)\\}\\)`, - ); - if (!shimPattern.test(contents)) { - throw new Error( - "officeparser-cjs-shim: dynamic-require shim not found in officeparser browser bundle. " + - "officeparser's bundling likely changed shape — re-audit the IIFE and update shimPattern " + - "before shipping, or require(\"fs\") may leak into the mobile bundle.", - ); - } - contents = contents.replace( - shimPattern, - 'var $1=(function(r){throw Error(\'Dynamic require of "\'+r+\'" is not supported\')})', - ); - return { - contents: contents + '\nmodule.exports = officeParser;\n', - loader: 'js', - }; - }); - }, -}; - const buildOptions = { plugins: [ - officeParserPlugin, esbuildSvelte({ compilerOptions: { css: "injected" }, preprocess: sveltePreprocess(), diff --git a/global.d.ts b/global.d.ts index 595f21b..be39c8f 100644 --- a/global.d.ts +++ b/global.d.ts @@ -12,3 +12,11 @@ declare module '*.png' { const content: string; export default content; } + +// mammoth ships type declarations for its default entry but not for the browser +// build we import (mammoth/mammoth.browser.js) for mobile safety. The browser build +// exposes the same public API, so we re-use mammoth's own types. +declare module 'mammoth/mammoth.browser.js' { + import mammoth from 'mammoth'; + export = mammoth; +} diff --git a/package-lock.json b/package-lock.json index dbdc62f..213bf40 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,15 +16,15 @@ "diff": "^9.0.0", "diff2html": "^3.4.56", "express": "^5.2.1", + "fflate": "^0.8.3", "fuzzysort": "^3.1.0", "highlight.js": "^11.11.1", "katex": "^0.17.0", "lowlight": "^3.3.0", - "officeparser": "^7.2.2", + "mammoth": "^1.12.0", "openai": "^6.45.0", "path-browserify": "^1.0.1", "regex-parser": "^2.3.1", - "unpdf": "^1.6.2", "uuid": "^14.0.1", "zod": "^4.4.3" }, @@ -109,16 +109,6 @@ "node": ">=6.9.0" } }, - "node_modules/@borewit/text-codec": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz", - "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/@codemirror/state": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.0.tgz", @@ -1065,271 +1055,6 @@ "license": "MIT", "peer": true }, - "node_modules/@napi-rs/canvas": { - "version": "0.1.100", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.100.tgz", - "integrity": "sha512-xglYA6q3XO5P3BNJYxVZ1IV7DLVjp1Py6nwag88YntrS+3vKHyYcMqXVS4ZztJmwz2uGvz1FWhI/4LgbR5uQDA==", - "license": "MIT", - "optional": true, - "workspaces": [ - "e2e/*" - ], - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "optionalDependencies": { - "@napi-rs/canvas-android-arm64": "0.1.100", - "@napi-rs/canvas-darwin-arm64": "0.1.100", - "@napi-rs/canvas-darwin-x64": "0.1.100", - "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.100", - "@napi-rs/canvas-linux-arm64-gnu": "0.1.100", - "@napi-rs/canvas-linux-arm64-musl": "0.1.100", - "@napi-rs/canvas-linux-riscv64-gnu": "0.1.100", - "@napi-rs/canvas-linux-x64-gnu": "0.1.100", - "@napi-rs/canvas-linux-x64-musl": "0.1.100", - "@napi-rs/canvas-win32-arm64-msvc": "0.1.100", - "@napi-rs/canvas-win32-x64-msvc": "0.1.100" - } - }, - "node_modules/@napi-rs/canvas-android-arm64": { - "version": "0.1.100", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.100.tgz", - "integrity": "sha512-hjhCKhntPv9+t4ckHymdx0phYNcVW+GKQR6Lzw2zE+pOVjOplSmtx9nNNknTjbEDLcuLZqA1y8ufKg1XfgftzQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - }, - "node_modules/@napi-rs/canvas-darwin-arm64": { - "version": "0.1.100", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.100.tgz", - "integrity": "sha512-2PcswRaC7Ly645DGt88///zuFDhJxJYdKAs1uU3mfk1atYkXufgcgLfBpk6Tm12nCQBaNt1wpybuPZ4qOhTo8A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - }, - "node_modules/@napi-rs/canvas-darwin-x64": { - "version": "0.1.100", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.100.tgz", - "integrity": "sha512-ePNZtj7pNIva/siZMg+HmbeozkIjqUIYdoymH8HaA3qK7LfzFN4WMBM8G6HQ9ZC+H3+Dnn5pqtiXpgLykaPOhw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - }, - "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { - "version": "0.1.100", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.100.tgz", - "integrity": "sha512-d5cDB48oWFGU8/XPhUOFAlySgb/VAu7D+s8fi55K1Pcfg8aPplHWqMgibhVLU8ky7Pyg/fuiVLz4Nf3JrSTuUA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - }, - "node_modules/@napi-rs/canvas-linux-arm64-gnu": { - "version": "0.1.100", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.100.tgz", - "integrity": "sha512-rDxgxRu69RvDlX/bh9o22DxLsGr8EqsNgotL9+RwQE1S0b0cqeatqsw6aW45mukm0B42DIAaAacKaYQ8cqS1nw==", - "cpu": [ - "arm64" - ], - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - }, - "node_modules/@napi-rs/canvas-linux-arm64-musl": { - "version": "0.1.100", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.100.tgz", - "integrity": "sha512-K3mDW66N+xT2/V439u1alFANiBUjdEx2gLiNYnCmUsva5jZMxWTjafBYwTzYK+EMFMHrUoabuU+T1BIP5CgbYQ==", - "cpu": [ - "arm64" - ], - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - }, - "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { - "version": "0.1.100", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.100.tgz", - "integrity": "sha512-mooqUBTIsccZpnoQC4NgrC1v6C1vof39etLNMnBwCY+p0gajWJvAHLGQ6g/gGyS5YrpDW+GefSN4+Cvcr08UWw==", - "cpu": [ - "riscv64" - ], - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - }, - "node_modules/@napi-rs/canvas-linux-x64-gnu": { - "version": "0.1.100", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.100.tgz", - "integrity": "sha512-1eCvkDCazm7FFhsT7DfGOdSaHgZVK3bt/dSBl5EWHOWmnz+I7j8tPseJqqD81NF+MH21jKUK4wQSDjN0mdhnTg==", - "cpu": [ - "x64" - ], - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - }, - "node_modules/@napi-rs/canvas-linux-x64-musl": { - "version": "0.1.100", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.100.tgz", - "integrity": "sha512-20arT6lnI19S68qNlii73TSEDbECNgzMz2EpldC1V3mZFuRkeujXkcebRk0LRJe9SEUAooYiLokfMViY8IX7yA==", - "cpu": [ - "x64" - ], - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - }, - "node_modules/@napi-rs/canvas-win32-arm64-msvc": { - "version": "0.1.100", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-0.1.100.tgz", - "integrity": "sha512-DZFFT1wIAg37LJw37yhMRFfjATd3vTQzjZ1Yki8u2vhO6Hi5VE6BVaGQ1aaDu7xb4iMErz+9EOwjpS7xcxFeBw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - }, - "node_modules/@napi-rs/canvas-win32-x64-msvc": { - "version": "0.1.100", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.100.tgz", - "integrity": "sha512-MyT1j3mHC2+Lu4pBi9mKyMJhtP6U7k7EldY7sj/uS5gJA65gTXt8MefJQXLJo5d/vZbuWmfxzkEUNc/urV3pHA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - } - }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", @@ -1947,29 +1672,6 @@ "svelte": "^3 || ^4 || ^5 || ^5.0.0-next.0" } }, - "node_modules/@tokenizer/inflate": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz", - "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.3", - "token-types": "^6.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "license": "MIT" - }, "node_modules/@tybys/wasm-util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", @@ -2598,12 +2300,12 @@ } }, "node_modules/@xmldom/xmldom": { - "version": "0.9.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz", - "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==", + "version": "0.8.13", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.13.tgz", + "integrity": "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==", "license": "MIT", "engines": { - "node": ">=14.6" + "node": ">=10.0.0" } }, "node_modules/abbrev": { @@ -2969,10 +2671,10 @@ "node": "*" } }, - "node_modules/bmp-js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", - "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==", + "node_modules/bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", "license": "MIT" }, "node_modules/body-parser": { @@ -3314,6 +3016,12 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, "node_modules/crelt": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.7.tgz", @@ -3542,6 +3250,12 @@ "node": ">=0.3.1" } }, + "node_modules/dingbat-to-unicode": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dingbat-to-unicode/-/dingbat-to-unicode-1.0.1.tgz", + "integrity": "sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w==", + "license": "BSD-2-Clause" + }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -3562,6 +3276,15 @@ "dev": true, "license": "MIT" }, + "node_modules/duck": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/duck/-/duck-0.1.12.tgz", + "integrity": "sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==", + "license": "BSD", + "dependencies": { + "underscore": "^1.13.1" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -5066,24 +4789,6 @@ "node": ">=16.0.0" } }, - "node_modules/file-type": { - "version": "22.0.1", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-22.0.1.tgz", - "integrity": "sha512-ww5Mhre0EE+jmBvOXTmXAbEMuZE7uX4a3+oRCQFNj8w++g3ev913N6tXQz0XTXbueQ5TWQfm6BdaViEHHn8bhA==", - "license": "MIT", - "dependencies": { - "@tokenizer/inflate": "^0.4.1", - "strtok3": "^10.3.5", - "token-types": "^6.1.2", - "uint8array-extras": "^1.5.0" - }, - "engines": { - "node": ">=22" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, "node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", @@ -5675,32 +5380,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/idb-keyval": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.5.tgz", - "integrity": "sha512-eKQkTnS0relYsSOYomx8ozIbmdsQCKUdhyuIaQ2DZgKuaxtyQQMkyD/wlnQN32pO3yutN1b1L8uqwcDKaJd7/Q==", - "license": "Apache-2.0" - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/ignore": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", @@ -5711,6 +5390,12 @@ "node": ">= 4" } }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -6148,12 +5833,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "license": "MIT" - }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -6405,6 +6084,18 @@ "node": ">=4.0" } }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, "node_modules/jwa": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", @@ -6466,6 +6157,15 @@ "node": ">= 0.8.0" } }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, "node_modules/lightningcss": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", @@ -6788,6 +6488,17 @@ "loose-envify": "cli.js" } }, + "node_modules/lop": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/lop/-/lop-0.4.2.tgz", + "integrity": "sha512-RefILVDQ4DKoRZsJ4Pj22TxE3omDO47yFpkIBoDKzkqPRISs5U1cnAdg/5583YPkWPaLIYHOKRMQSvjFsO26cw==", + "license": "BSD-2-Clause", + "dependencies": { + "duck": "^0.1.12", + "option": "~0.2.1", + "underscore": "^1.13.1" + } + }, "node_modules/lowlight": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-3.3.0.tgz", @@ -6823,6 +6534,39 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/mammoth": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/mammoth/-/mammoth-1.12.0.tgz", + "integrity": "sha512-cwnK1RIcRdDMi2HRx2EXGYlxqIEh0Oo3bLhorgnsVJi2UkbX1+jKxuBNR9PC5+JaX7EkmJxFPmo6mjLpqShI2w==", + "license": "BSD-2-Clause", + "dependencies": { + "@xmldom/xmldom": "^0.8.6", + "argparse": "~1.0.3", + "base64-js": "^1.5.1", + "bluebird": "~3.4.0", + "dingbat-to-unicode": "^1.0.1", + "jszip": "^3.7.1", + "lop": "^0.4.2", + "path-is-absolute": "^1.0.0", + "underscore": "^1.13.1", + "xmlbuilder": "^10.0.0" + }, + "bin": { + "mammoth": "bin/mammoth" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/mammoth/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -7159,13 +6903,6 @@ "url": "https://opencollective.com/node-fetch" } }, - "node_modules/node-readable-to-web-readable-stream": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/node-readable-to-web-readable-stream/-/node-readable-to-web-readable-stream-0.4.2.tgz", - "integrity": "sha512-/cMZNI34v//jUTrI+UIo4ieHAB5EZRY/+7OmXZgBxaWBMcW2tGdceIw06RFxWxrKZ5Jp3sI2i5TsRo+CBhtVLQ==", - "license": "MIT", - "optional": true - }, "node_modules/nopt": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", @@ -7332,33 +7069,6 @@ "node": ">=12.20.0" } }, - "node_modules/officeparser": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/officeparser/-/officeparser-7.2.2.tgz", - "integrity": "sha512-W49PyMsOebNsEVEh6jYerNDakK+Se0YdUMwfTjTRQD7qFJqrEuSB7oEagLSnB7YOmZmvpKKz7wJEgeUeJzw5vg==", - "license": "MIT", - "dependencies": { - "@xmldom/xmldom": "^0.9.10", - "fflate": "^0.8.2", - "file-type": "^22.0.1", - "pdfjs-dist": "5.6.205", - "tesseract.js": "^7.0.0" - }, - "bin": { - "officeparser": "dist/cli.js" - }, - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/harshankur" - }, - "peerDependenciesMeta": { - "puppeteer": { - "optional": true - } - } - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -7427,14 +7137,11 @@ } } }, - "node_modules/opencollective-postinstall": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", - "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", - "license": "MIT", - "bin": { - "opencollective-postinstall": "index.js" - } + "node_modules/option": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/option/-/option-0.2.4.tgz", + "integrity": "sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A==", + "license": "BSD-2-Clause" }, "node_modules/optionator": { "version": "0.9.4", @@ -7517,6 +7224,12 @@ "node": ">=8" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -7555,6 +7268,15 @@ "node": ">=8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -7589,19 +7311,6 @@ "dev": true, "license": "MIT" }, - "node_modules/pdfjs-dist": { - "version": "5.6.205", - "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.6.205.tgz", - "integrity": "sha512-tlUj+2IDa7G1SbvBNN74UHRLJybZDWYom+k6p5KIZl7huBvsA4APi6mKL+zCxd3tLjN5hOOEE9Tv7VdzO88pfg==", - "license": "Apache-2.0", - "engines": { - "node": ">=20.19.0 || >=22.13.0 || >=24" - }, - "optionalDependencies": { - "@napi-rs/canvas": "^0.1.96", - "node-readable-to-web-readable-stream": "^0.4.2" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -7686,6 +7395,12 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -7812,6 +7527,33 @@ "dev": true, "license": "MIT" }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -7849,12 +7591,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "license": "MIT" - }, "node_modules/regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", @@ -8250,6 +7986,12 @@ "node": ">= 0.4" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -8412,6 +8154,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -8459,6 +8207,21 @@ "node": ">= 0.4" } }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/string.prototype.matchall": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", @@ -8595,22 +8358,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strtok3": { - "version": "10.3.5", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.5.tgz", - "integrity": "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==", - "license": "MIT", - "dependencies": { - "@tokenizer/token": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/style-mod": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", @@ -8795,50 +8542,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/tesseract.js": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-7.0.0.tgz", - "integrity": "sha512-exPBkd+z+wM1BuMkx/Bjv43OeLBxhL5kKWsz/9JY+DXcXdiBjiAch0V49QR3oAJqCaL5qURE0vx9Eo+G5YE7mA==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "bmp-js": "^0.1.0", - "idb-keyval": "^6.2.0", - "is-url": "^1.2.4", - "node-fetch": "^2.6.9", - "opencollective-postinstall": "^2.0.3", - "regenerator-runtime": "^0.13.3", - "tesseract.js-core": "^7.0.0", - "wasm-feature-detect": "^1.8.0", - "zlibjs": "^0.3.1" - } - }, - "node_modules/tesseract.js-core": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-7.0.0.tgz", - "integrity": "sha512-WnNH518NzmbSq9zgTPeoF8c+xmilS8rFIl1YKbk/ptuuc7p6cLNELNuPAzcmsYw450ca6bLa8j3t0VAtq435Vw==", - "license": "Apache-2.0" - }, - "node_modules/tesseract.js/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -8892,24 +8595,6 @@ "node": ">=0.6" } }, - "node_modules/token-types": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz", - "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", - "license": "MIT", - "dependencies": { - "@borewit/text-codec": "^0.2.1", - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/toml-eslint-parser": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/toml-eslint-parser/-/toml-eslint-parser-0.9.3.tgz", @@ -8936,12 +8621,6 @@ "node": ">=6" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -9174,18 +8853,6 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/uint8array-extras": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", - "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -9205,6 +8872,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "license": "MIT" + }, "node_modules/undici-types": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", @@ -9298,20 +8971,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unpdf": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/unpdf/-/unpdf-1.6.2.tgz", - "integrity": "sha512-zQ80ySoPuPHOsvIoRp/nJyQt8TOUoTh1+WBCGcBvlddQNgKDLRwm0AY3x8Q35I7+kIiRSgqMx+Ma2pl9McIp7A==", - "license": "MIT", - "peerDependencies": { - "@napi-rs/canvas": "^0.1.69" - }, - "peerDependenciesMeta": { - "@napi-rs/canvas": { - "optional": true - } - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -9331,6 +8990,12 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/uuid": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz", @@ -9557,12 +9222,6 @@ "license": "MIT", "peer": true }, - "node_modules/wasm-feature-detect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz", - "integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==", - "license": "Apache-2.0" - }, "node_modules/web-streams-polyfill": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", @@ -9572,12 +9231,6 @@ "node": ">= 8" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, "node_modules/whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", @@ -9588,16 +9241,6 @@ "node": ">=12" } }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -9757,6 +9400,15 @@ } } }, + "node_modules/xmlbuilder": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz", + "integrity": "sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, "node_modules/yaml": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", @@ -9810,15 +9462,6 @@ "dev": true, "license": "MIT" }, - "node_modules/zlibjs": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/zlibjs/-/zlibjs-0.3.1.tgz", - "integrity": "sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/zod": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", diff --git a/package.json b/package.json index 5f06a58..9c01213 100644 --- a/package.json +++ b/package.json @@ -52,15 +52,15 @@ "diff": "^9.0.0", "diff2html": "^3.4.56", "express": "^5.2.1", + "fflate": "^0.8.3", "fuzzysort": "^3.1.0", "highlight.js": "^11.11.1", "katex": "^0.17.0", "lowlight": "^3.3.0", - "officeparser": "^7.2.2", + "mammoth": "^1.12.0", "openai": "^6.45.0", "path-browserify": "^1.0.1", "regex-parser": "^2.3.1", - "unpdf": "^1.6.2", "uuid": "^14.0.1", "zod": "^4.4.3" }