@gmickel/gno 1.45.1 → 2.0.0
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 -1
- package/THIRD_PARTY_NOTICES.md +46 -0
- package/assets/skill/SKILL.md +7 -6
- package/assets/skill/cli-reference.md +14 -6
- package/assets/skill/mcp-reference.md +4 -1
- package/assets/spa-production.json.gz +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.0.0.zip +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.0.0.zip.sha256 +1 -0
- package/browser-extension/dist/chunk-4tc9v0ja.js +74 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/browser-extension/dist/preview.html +1 -1
- package/browser-extension/dist/service-worker.js +32 -33
- package/bunfig.toml +2 -0
- package/package.json +40 -26
- package/spec/cli.md +30 -11
- package/spec/db/schema.sql +146 -1
- package/spec/mcp.md +26 -0
- package/src/app/context-runtime-types.ts +3 -0
- package/src/app/context-runtime.ts +2 -0
- package/src/cli/commands/ask.ts +6 -1
- package/src/cli/commands/daemon.ts +21 -8
- package/src/cli/commands/embed.ts +77 -41
- package/src/cli/commands/mcp/install.ts +20 -0
- package/src/cli/commands/mcp/paths.ts +25 -0
- package/src/cli/commands/mcp/status.ts +6 -0
- package/src/cli/detach.ts +3 -2
- package/src/cli/program.ts +6 -0
- package/src/config/types.ts +3 -3
- package/src/converters/adapters/markitdownTs/adapter.ts +1 -2
- package/src/converters/adapters/officeparser/adapter.ts +1 -2
- package/src/converters/versions.ts +6 -8
- package/src/core/context-evidence.ts +8 -4
- package/src/core/job-manager.ts +95 -13
- package/src/core/network-boundary-inventory.ts +10 -0
- package/src/core/shutdown-budget.ts +45 -0
- package/src/embed/backlog.ts +107 -4
- package/src/embed/batch.ts +42 -2
- package/src/embed/fingerprint.ts +16 -0
- package/src/embed/retry.ts +113 -5
- package/src/embed/variant-backlog.ts +105 -0
- package/src/embed/variant-plan.ts +62 -0
- package/src/embed/variant-retry.ts +113 -0
- package/src/ingestion/graph-reconciliation.ts +327 -0
- package/src/ingestion/sync.ts +9 -272
- package/src/llm/http-inference.ts +6 -0
- package/src/llm/httpEmbedding.ts +37 -6
- package/src/llm/httpGeneration.ts +18 -3
- package/src/llm/httpRerank.ts +23 -5
- package/src/llm/inference-cancellation.ts +168 -0
- package/src/llm/inference-scope.ts +202 -0
- package/src/llm/lazy-ports.ts +115 -0
- package/src/llm/native-worker/client.ts +541 -0
- package/src/llm/native-worker/dispatcher.ts +228 -0
- package/src/llm/native-worker/embedding-identity.ts +33 -0
- package/src/llm/native-worker/entry.ts +173 -0
- package/src/llm/native-worker/errors.ts +32 -0
- package/src/llm/native-worker/evaluation.ts +16 -0
- package/src/llm/native-worker/owned-exit.ts +108 -0
- package/src/llm/native-worker/owner.ts +141 -0
- package/src/llm/native-worker/ports.ts +317 -0
- package/src/llm/native-worker/protocol.ts +442 -0
- package/src/llm/native-worker/runtime-config.ts +92 -0
- package/src/llm/nodeLlamaCpp/adapter.ts +77 -20
- package/src/llm/nodeLlamaCpp/embedding.ts +130 -46
- package/src/llm/nodeLlamaCpp/generation.ts +34 -5
- package/src/llm/nodeLlamaCpp/lifecycle-options.ts +99 -0
- package/src/llm/nodeLlamaCpp/lifecycle.ts +209 -204
- package/src/llm/nodeLlamaCpp/rerank-capacity.ts +111 -0
- package/src/llm/nodeLlamaCpp/rerank.ts +118 -27
- package/src/llm/nodeLlamaCpp/simulator-handle.ts +73 -0
- package/src/llm/nodeLlamaCpp/simulator-install.ts +124 -0
- package/src/llm/nodeLlamaCpp/simulator-session.ts +240 -0
- package/src/llm/nodeLlamaCpp/simulator-types.ts +80 -0
- package/src/llm/types.ts +35 -5
- package/src/mcp/context.ts +27 -0
- package/src/mcp/http-transport.ts +12 -10
- package/src/mcp/server.ts +3 -0
- package/src/mcp/tool-profile.ts +30 -8
- package/src/mcp/tools/context.ts +8 -11
- package/src/mcp/tools/embed.ts +1 -1
- package/src/mcp/tools/index-cmd.ts +1 -1
- package/src/mcp/tools/index.ts +10 -8
- package/src/mcp/tools/query.ts +14 -30
- package/src/mcp/tools/vsearch.ts +1 -1
- package/src/pipeline/answer.ts +23 -3
- package/src/pipeline/claim-verifier.ts +6 -0
- package/src/pipeline/expansion.ts +43 -40
- package/src/pipeline/explain.ts +6 -2
- package/src/pipeline/filters.ts +63 -0
- package/src/pipeline/fusion.ts +29 -9
- package/src/pipeline/graph-retrieval.ts +29 -9
- package/src/pipeline/hybrid.ts +198 -55
- package/src/pipeline/hydration.ts +161 -0
- package/src/pipeline/owner-fusion.ts +87 -0
- package/src/pipeline/rerank.ts +35 -11
- package/src/pipeline/search.ts +13 -2
- package/src/pipeline/types.ts +5 -3
- package/src/pipeline/vsearch.ts +87 -7
- package/src/sdk/client.ts +47 -3
- package/src/sdk/embed.ts +63 -39
- package/src/serve/background-runtime.ts +1 -1
- package/src/serve/context.ts +41 -56
- package/src/serve/embed-scheduler.ts +58 -35
- package/src/serve/public/components/IndexingProgress.tsx +46 -60
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/lib/shiki-language-ids.ts +14 -0
- package/src/serve/resident-admission.ts +36 -36
- package/src/serve/resident-background-work.ts +20 -2
- package/src/serve/resident-request.ts +11 -5
- package/src/serve/resident-runtime.ts +97 -61
- package/src/serve/resident-shutdown.ts +153 -0
- package/src/serve/routes/api.ts +3 -1
- package/src/serve/server.ts +47 -26
- package/src/store/migrations/028-vector-variants.ts +54 -0
- package/src/store/migrations/029-graph-reference-state.ts +77 -0
- package/src/store/migrations/index.ts +4 -0
- package/src/store/sqlite/adapter.ts +251 -183
- package/src/store/sqlite/eligibility.ts +174 -0
- package/src/store/sqlite/graph-edge-application.ts +66 -0
- package/src/store/sqlite/graph-reference-state.ts +194 -0
- package/src/store/sqlite/legacy-vector-ownership.ts +79 -0
- package/src/store/types.ts +80 -12
- package/src/store/vector/eligibility.ts +36 -0
- package/src/store/vector/freshness.ts +33 -6
- package/src/store/vector/lazy.ts +81 -0
- package/src/store/vector/sqlite-vec.ts +106 -54
- package/src/store/vector/stats.ts +14 -3
- package/src/store/vector/types.ts +35 -2
- package/src/store/vector/variant-search.ts +192 -0
- package/src/store/vector/variants.ts +451 -0
- package/vendor/converters/markitdown-ts/LICENSE +21 -0
- package/vendor/converters/markitdown-ts/dist/index.cjs +1180 -0
- package/vendor/converters/markitdown-ts/dist/index.d.cts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.d.mts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.d.ts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.mjs +1152 -0
- package/vendor/converters/markitdown-ts/package.json +77 -0
- package/vendor/converters/officeparser/LICENSE +21 -0
- package/vendor/converters/officeparser/dist/OfficeConverter.d.ts +47 -0
- package/vendor/converters/officeparser/dist/OfficeConverter.js +76 -0
- package/vendor/converters/officeparser/dist/OfficeGenerator.d.ts +23 -0
- package/vendor/converters/officeparser/dist/OfficeGenerator.js +73 -0
- package/vendor/converters/officeparser/dist/OfficeParser.d.ts +106 -0
- package/vendor/converters/officeparser/dist/OfficeParser.js +332 -0
- package/vendor/converters/officeparser/dist/cli.d.ts +28 -0
- package/vendor/converters/officeparser/dist/cli.js +381 -0
- package/vendor/converters/officeparser/dist/defaults.d.ts +41 -0
- package/vendor/converters/officeparser/dist/defaults.js +218 -0
- package/vendor/converters/officeparser/dist/generators/BaseGenerator.d.ts +107 -0
- package/vendor/converters/officeparser/dist/generators/BaseGenerator.js +248 -0
- package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.d.ts +82 -0
- package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.js +797 -0
- package/vendor/converters/officeparser/dist/generators/CsvGenerator.d.ts +38 -0
- package/vendor/converters/officeparser/dist/generators/CsvGenerator.js +245 -0
- package/vendor/converters/officeparser/dist/generators/EpubGenerator.d.ts +43 -0
- package/vendor/converters/officeparser/dist/generators/EpubGenerator.js +315 -0
- package/vendor/converters/officeparser/dist/generators/HtmlGenerator.d.ts +59 -0
- package/vendor/converters/officeparser/dist/generators/HtmlGenerator.js +1942 -0
- package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.d.ts +96 -0
- package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.js +1175 -0
- package/vendor/converters/officeparser/dist/generators/PdfGenerator.d.ts +22 -0
- package/vendor/converters/officeparser/dist/generators/PdfGenerator.js +194 -0
- package/vendor/converters/officeparser/dist/generators/RtfGenerator.d.ts +29 -0
- package/vendor/converters/officeparser/dist/generators/RtfGenerator.js +316 -0
- package/vendor/converters/officeparser/dist/generators/TextGenerator.d.ts +13 -0
- package/vendor/converters/officeparser/dist/generators/TextGenerator.js +201 -0
- package/vendor/converters/officeparser/dist/index.d.ts +60 -0
- package/vendor/converters/officeparser/dist/index.js +72 -0
- package/vendor/converters/officeparser/dist/index.mjs +18 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.d.ts +2621 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.iife.js +1336 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.mjs +1335 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.d.ts +2621 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.iife.js +1336 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.mjs +1335 -0
- package/vendor/converters/officeparser/dist/parsers/CsvParser.d.ts +9 -0
- package/vendor/converters/officeparser/dist/parsers/CsvParser.js +115 -0
- package/vendor/converters/officeparser/dist/parsers/EpubParser.d.ts +8 -0
- package/vendor/converters/officeparser/dist/parsers/EpubParser.js +217 -0
- package/vendor/converters/officeparser/dist/parsers/ExcelParser.d.ts +32 -0
- package/vendor/converters/officeparser/dist/parsers/ExcelParser.js +736 -0
- package/vendor/converters/officeparser/dist/parsers/HtmlParser.d.ts +2 -0
- package/vendor/converters/officeparser/dist/parsers/HtmlParser.js +1287 -0
- package/vendor/converters/officeparser/dist/parsers/MarkdownParser.d.ts +2 -0
- package/vendor/converters/officeparser/dist/parsers/MarkdownParser.js +1272 -0
- package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.d.ts +31 -0
- package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.js +1819 -0
- package/vendor/converters/officeparser/dist/parsers/PdfParser.d.ts +67 -0
- package/vendor/converters/officeparser/dist/parsers/PdfParser.js +848 -0
- package/vendor/converters/officeparser/dist/parsers/PowerPointParser.d.ts +32 -0
- package/vendor/converters/officeparser/dist/parsers/PowerPointParser.js +950 -0
- package/vendor/converters/officeparser/dist/parsers/RtfParser.d.ts +187 -0
- package/vendor/converters/officeparser/dist/parsers/RtfParser.js +1801 -0
- package/vendor/converters/officeparser/dist/parsers/WordParser.d.ts +79 -0
- package/vendor/converters/officeparser/dist/parsers/WordParser.js +1177 -0
- package/vendor/converters/officeparser/dist/sbom.cdx.json +1763 -0
- package/vendor/converters/officeparser/dist/types.d.ts +2507 -0
- package/vendor/converters/officeparser/dist/types.js +107 -0
- package/vendor/converters/officeparser/dist/utils/astUtils.d.ts +16 -0
- package/vendor/converters/officeparser/dist/utils/astUtils.js +33 -0
- package/vendor/converters/officeparser/dist/utils/chartUtils.d.ts +6 -0
- package/vendor/converters/officeparser/dist/utils/chartUtils.js +257 -0
- package/vendor/converters/officeparser/dist/utils/configUtils.d.ts +44 -0
- package/vendor/converters/officeparser/dist/utils/configUtils.js +315 -0
- package/vendor/converters/officeparser/dist/utils/dateUtils.d.ts +17 -0
- package/vendor/converters/officeparser/dist/utils/dateUtils.js +69 -0
- package/vendor/converters/officeparser/dist/utils/envUtils.d.ts +29 -0
- package/vendor/converters/officeparser/dist/utils/envUtils.js +152 -0
- package/vendor/converters/officeparser/dist/utils/errorUtils.d.ts +72 -0
- package/vendor/converters/officeparser/dist/utils/errorUtils.js +245 -0
- package/vendor/converters/officeparser/dist/utils/imageUtils.d.ts +66 -0
- package/vendor/converters/officeparser/dist/utils/imageUtils.js +133 -0
- package/vendor/converters/officeparser/dist/utils/mathUtils.d.ts +42 -0
- package/vendor/converters/officeparser/dist/utils/mathUtils.js +385 -0
- package/vendor/converters/officeparser/dist/utils/moduleLoader.d.ts +18 -0
- package/vendor/converters/officeparser/dist/utils/moduleLoader.js +106 -0
- package/vendor/converters/officeparser/dist/utils/ocrUtils.d.ts +42 -0
- package/vendor/converters/officeparser/dist/utils/ocrUtils.js +428 -0
- package/vendor/converters/officeparser/dist/utils/sanitize.d.ts +148 -0
- package/vendor/converters/officeparser/dist/utils/sanitize.js +344 -0
- package/vendor/converters/officeparser/dist/utils/sheetUtils.d.ts +7 -0
- package/vendor/converters/officeparser/dist/utils/sheetUtils.js +35 -0
- package/vendor/converters/officeparser/dist/utils/styleMapper.d.ts +36 -0
- package/vendor/converters/officeparser/dist/utils/styleMapper.js +224 -0
- package/vendor/converters/officeparser/dist/utils/xmlUtils.d.ts +163 -0
- package/vendor/converters/officeparser/dist/utils/xmlUtils.js +461 -0
- package/vendor/converters/officeparser/dist/utils/zipUtils.d.ts +134 -0
- package/vendor/converters/officeparser/dist/utils/zipUtils.js +337 -0
- package/vendor/converters/officeparser/package.json +147 -0
- package/vendor/converters/upstream-manifest.json +124 -0
- package/vendor/dependency-fixes/README.md +77 -0
- package/vendor/dependency-fixes/vendor-converters.py +83 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.45.1.zip +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.45.1.zip.sha256 +0 -1
- package/browser-extension/dist/chunk-627emwpj.js +0 -75
- /package/browser-extension/dist/{chunk-ydfx5d7p.css → chunk-z74y8n8c.css} +0 -0
|
@@ -0,0 +1,1180 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const mime = require('mime-types');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const jsdom = require('jsdom');
|
|
7
|
+
const TurndownService = require('turndown');
|
|
8
|
+
const turndownPluginGfm = require('@joplin/turndown-plugin-gfm');
|
|
9
|
+
const xmldom = require('@xmldom/xmldom');
|
|
10
|
+
const url = require('url');
|
|
11
|
+
const pdfParse = require('pdf-parse');
|
|
12
|
+
const Mammoth = require('mammoth');
|
|
13
|
+
const XLSX = require('xlsx');
|
|
14
|
+
const childProcess = require('child_process');
|
|
15
|
+
const util = require('util');
|
|
16
|
+
const fs$1 = require('fs/promises');
|
|
17
|
+
const os = require('os');
|
|
18
|
+
const ai = require('ai');
|
|
19
|
+
const stream = require('stream');
|
|
20
|
+
|
|
21
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
22
|
+
|
|
23
|
+
function _interopNamespaceCompat(e) {
|
|
24
|
+
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
25
|
+
const n = Object.create(null);
|
|
26
|
+
if (e) {
|
|
27
|
+
for (const k in e) {
|
|
28
|
+
n[k] = e[k];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
n.default = e;
|
|
32
|
+
return n;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const mime__namespace = /*#__PURE__*/_interopNamespaceCompat(mime);
|
|
36
|
+
const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
|
|
37
|
+
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
38
|
+
const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
39
|
+
const fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs);
|
|
40
|
+
const TurndownService__default = /*#__PURE__*/_interopDefaultCompat(TurndownService);
|
|
41
|
+
const turndownPluginGfm__default = /*#__PURE__*/_interopDefaultCompat(turndownPluginGfm);
|
|
42
|
+
const Mammoth__default = /*#__PURE__*/_interopDefaultCompat(Mammoth);
|
|
43
|
+
const XLSX__namespace = /*#__PURE__*/_interopNamespaceCompat(XLSX);
|
|
44
|
+
const childProcess__namespace = /*#__PURE__*/_interopNamespaceCompat(childProcess);
|
|
45
|
+
const util__namespace = /*#__PURE__*/_interopNamespaceCompat(util);
|
|
46
|
+
const fs__namespace$1 = /*#__PURE__*/_interopNamespaceCompat(fs$1);
|
|
47
|
+
const os__namespace = /*#__PURE__*/_interopNamespaceCompat(os);
|
|
48
|
+
|
|
49
|
+
class PlainTextConverter {
|
|
50
|
+
async convert(source, options = {}) {
|
|
51
|
+
const fileExtension = options.file_extension || "";
|
|
52
|
+
const contentType = mime__namespace.lookup(fileExtension);
|
|
53
|
+
if (!contentType) {
|
|
54
|
+
return null;
|
|
55
|
+
} else if (!contentType.toLowerCase().includes("text/")) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
let content;
|
|
59
|
+
if (typeof source === "string") {
|
|
60
|
+
content = fs__default.readFileSync(source, { encoding: "utf-8" });
|
|
61
|
+
} else {
|
|
62
|
+
content = Buffer.from(source).toString("utf-8");
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
title: null,
|
|
66
|
+
markdown: content,
|
|
67
|
+
text_content: content
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
class CustomTurnDown {
|
|
73
|
+
convert_soup(doc) {
|
|
74
|
+
let turnDownService = new TurndownService__default({
|
|
75
|
+
headingStyle: "atx"
|
|
76
|
+
});
|
|
77
|
+
turnDownService.use(turndownPluginGfm__default.gfm);
|
|
78
|
+
turnDownService.addRule("anchor tags", {
|
|
79
|
+
filter: ["a"],
|
|
80
|
+
replacement: function(content, node) {
|
|
81
|
+
if (content === "") {
|
|
82
|
+
return "";
|
|
83
|
+
}
|
|
84
|
+
let prefix = "";
|
|
85
|
+
let suffix = "";
|
|
86
|
+
if (content && content[0] === " ") {
|
|
87
|
+
prefix = " ";
|
|
88
|
+
}
|
|
89
|
+
if (content && content[content.length - 1] === " ") {
|
|
90
|
+
suffix = " ";
|
|
91
|
+
}
|
|
92
|
+
let text = content.trim().replace(/\n\n.*/g, "");
|
|
93
|
+
if (text === "") {
|
|
94
|
+
return "";
|
|
95
|
+
}
|
|
96
|
+
let href = node.getAttribute("href");
|
|
97
|
+
let title = node.title;
|
|
98
|
+
if (href) {
|
|
99
|
+
try {
|
|
100
|
+
let parsed_url = new URL(href);
|
|
101
|
+
if (!["https:", "http:", "file:"].includes(parsed_url.protocol)) {
|
|
102
|
+
return `${prefix}${text}${suffix}`;
|
|
103
|
+
}
|
|
104
|
+
} catch (e) {
|
|
105
|
+
if (!/^https?:|^file:/.test(href)) {
|
|
106
|
+
return `${prefix}[${text}](${href} "${title}")${suffix}`;
|
|
107
|
+
}
|
|
108
|
+
return `${prefix}${text}${suffix}`;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (text.replace(/\\_/g, "_") === href && !title) {
|
|
112
|
+
return `<${href}>`;
|
|
113
|
+
}
|
|
114
|
+
if (!title && href) {
|
|
115
|
+
title = href;
|
|
116
|
+
}
|
|
117
|
+
let title_part = title ? ` "${title}"` : "";
|
|
118
|
+
return `${prefix}[${text}](${href}${title_part})${suffix}`;
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
turnDownService.addRule("img tags", {
|
|
122
|
+
filter: ["img"],
|
|
123
|
+
replacement: function(_, node) {
|
|
124
|
+
if (!node || node.nodeName !== "IMG") {
|
|
125
|
+
return "";
|
|
126
|
+
}
|
|
127
|
+
let alt = node.getAttribute("alt") || "";
|
|
128
|
+
let src = node.getAttribute("src") || "";
|
|
129
|
+
let title = node.getAttribute("title") || "";
|
|
130
|
+
let titlePart = title ? ` "${title}"` : "";
|
|
131
|
+
if (src.startsWith("data:")) {
|
|
132
|
+
src = src.split(",")[0] + "...";
|
|
133
|
+
}
|
|
134
|
+
return ``;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
let markdown = turnDownService.turndown(doc);
|
|
138
|
+
return markdown;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
class HtmlConverter {
|
|
143
|
+
async convert(source, options) {
|
|
144
|
+
const extension = options.file_extension || "";
|
|
145
|
+
if (![".html", ".htm"].includes(extension.toLowerCase())) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
let content;
|
|
150
|
+
if (typeof source === "string") {
|
|
151
|
+
let exists = fs__namespace.existsSync(source);
|
|
152
|
+
if (!exists) {
|
|
153
|
+
throw new Error("File does'nt exists");
|
|
154
|
+
}
|
|
155
|
+
content = fs__namespace.readFileSync(source, { encoding: "utf-8" });
|
|
156
|
+
} else {
|
|
157
|
+
content = source.toString("utf-8");
|
|
158
|
+
}
|
|
159
|
+
return await this._convert(content);
|
|
160
|
+
} catch (e) {
|
|
161
|
+
console.error(e);
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async _convert(htmlContent) {
|
|
166
|
+
const soup = new jsdom.JSDOM(htmlContent);
|
|
167
|
+
const doc = soup.window.document;
|
|
168
|
+
doc.querySelectorAll("script, style").forEach((script) => {
|
|
169
|
+
script.remove();
|
|
170
|
+
});
|
|
171
|
+
const bodyElm = doc.querySelector("body");
|
|
172
|
+
let webpageText = "";
|
|
173
|
+
if (bodyElm) {
|
|
174
|
+
webpageText = new CustomTurnDown().convert_soup(bodyElm);
|
|
175
|
+
} else {
|
|
176
|
+
webpageText = new CustomTurnDown().convert_soup(doc);
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
title: doc.title,
|
|
180
|
+
markdown: webpageText,
|
|
181
|
+
text_content: webpageText
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
class RSSConverter {
|
|
187
|
+
async convert(source, options = {}) {
|
|
188
|
+
const fileExtension = options.file_extension || "";
|
|
189
|
+
if (![".xml", ".rss", ".atom"].includes(fileExtension.toLowerCase())) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
try {
|
|
193
|
+
const xmlString = typeof source === "string" ? fs__namespace.readFileSync(source, { encoding: "utf-8" }) : source.toString("utf-8");
|
|
194
|
+
const doc = new xmldom.DOMParser().parseFromString(xmlString, "text/xml");
|
|
195
|
+
let result;
|
|
196
|
+
if (doc.getElementsByTagName("rss").length > 0) {
|
|
197
|
+
result = this._parseRssType(doc);
|
|
198
|
+
} else if (doc.getElementsByTagName("feed").length > 0) {
|
|
199
|
+
const root = doc.getElementsByTagName("feed")[0];
|
|
200
|
+
if (root.getElementsByTagName("entry").length > 0) {
|
|
201
|
+
result = this._parseAtomType(doc);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return result;
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error("RSS Parsing Error:", error);
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
_parseAtomType(doc) {
|
|
211
|
+
try {
|
|
212
|
+
const root = doc.getElementsByTagName("feed")[0];
|
|
213
|
+
const title = this._getDataByTagName(root, "title");
|
|
214
|
+
const subtitle = this._getDataByTagName(root, "subtitle");
|
|
215
|
+
const entries = root.getElementsByTagName("entry");
|
|
216
|
+
let mdText = `# ${title}
|
|
217
|
+
`;
|
|
218
|
+
if (subtitle) {
|
|
219
|
+
mdText += `${subtitle}
|
|
220
|
+
`;
|
|
221
|
+
}
|
|
222
|
+
for (let i = 0; i < entries.length; i++) {
|
|
223
|
+
const entry = entries[i];
|
|
224
|
+
const entryTitle = this._getDataByTagName(entry, "title");
|
|
225
|
+
const entrySummary = this._getDataByTagName(entry, "summary");
|
|
226
|
+
const entryUpdated = this._getDataByTagName(entry, "updated");
|
|
227
|
+
const entryContent = this._getDataByTagName(entry, "content");
|
|
228
|
+
if (entryTitle) {
|
|
229
|
+
mdText += `
|
|
230
|
+
## ${entryTitle}
|
|
231
|
+
`;
|
|
232
|
+
}
|
|
233
|
+
if (entryUpdated) {
|
|
234
|
+
mdText += `Updated on: ${entryUpdated}
|
|
235
|
+
`;
|
|
236
|
+
}
|
|
237
|
+
if (entrySummary) {
|
|
238
|
+
mdText += this._parseContent(entrySummary);
|
|
239
|
+
}
|
|
240
|
+
if (entryContent) {
|
|
241
|
+
mdText += this._parseContent(entryContent);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return { title, markdown: mdText, text_content: mdText };
|
|
245
|
+
} catch (error) {
|
|
246
|
+
console.error("Atom Parsing Error:", error);
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
_parseRssType(doc) {
|
|
251
|
+
try {
|
|
252
|
+
const root = doc.getElementsByTagName("rss")[0];
|
|
253
|
+
const channel = root.getElementsByTagName("channel");
|
|
254
|
+
if (!channel || channel.length === 0) {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
const channelElement = channel[0];
|
|
258
|
+
const channelTitle = this._getDataByTagName(channelElement, "title");
|
|
259
|
+
const channelDescription = this._getDataByTagName(channelElement, "description");
|
|
260
|
+
const items = channelElement.getElementsByTagName("item");
|
|
261
|
+
let mdText = "";
|
|
262
|
+
if (channelTitle) {
|
|
263
|
+
mdText = `# ${channelTitle}
|
|
264
|
+
`;
|
|
265
|
+
}
|
|
266
|
+
if (channelDescription) {
|
|
267
|
+
mdText += `${channelDescription}
|
|
268
|
+
`;
|
|
269
|
+
}
|
|
270
|
+
for (let i = 0; i < items.length; i++) {
|
|
271
|
+
const item = items[i];
|
|
272
|
+
const title = this._getDataByTagName(item, "title");
|
|
273
|
+
const description = this._getDataByTagName(item, "description");
|
|
274
|
+
const pubDate = this._getDataByTagName(item, "pubDate");
|
|
275
|
+
const content = this._getDataByTagName(item, "content:encoded");
|
|
276
|
+
if (title) {
|
|
277
|
+
mdText += `
|
|
278
|
+
## ${title}
|
|
279
|
+
`;
|
|
280
|
+
}
|
|
281
|
+
if (pubDate) {
|
|
282
|
+
mdText += `Published on: ${pubDate}
|
|
283
|
+
`;
|
|
284
|
+
}
|
|
285
|
+
if (description) {
|
|
286
|
+
mdText += this._parseContent(description);
|
|
287
|
+
}
|
|
288
|
+
if (content) {
|
|
289
|
+
mdText += this._parseContent(content);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return { title: channelTitle, markdown: mdText, text_content: mdText };
|
|
293
|
+
} catch (error) {
|
|
294
|
+
console.error("RSS Parsing Error:", error);
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
_parseContent(content) {
|
|
299
|
+
try {
|
|
300
|
+
const dom = new jsdom.JSDOM(content);
|
|
301
|
+
const document = dom.window.document;
|
|
302
|
+
return new CustomTurnDown().convert_soup(document);
|
|
303
|
+
} catch (error) {
|
|
304
|
+
console.warn("Parsing content error", error);
|
|
305
|
+
return content;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
_getDataByTagName(element, tagName) {
|
|
309
|
+
const nodes = element.getElementsByTagName(tagName);
|
|
310
|
+
if (!nodes || nodes.length === 0) {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
const fc = nodes[0].firstChild;
|
|
314
|
+
if (fc && fc.nodeValue) {
|
|
315
|
+
return fc.nodeValue;
|
|
316
|
+
}
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const WIKIPEDIA_REGEX = /^https?:\/\/[a-zA-Z]{2,3}\.wikipedia\.org\//;
|
|
322
|
+
const BODY_SELECTOR_QUERY = "div#mw-content-text";
|
|
323
|
+
const TITLE_SELECTOR_QUERY = "span.mw-page-title-main";
|
|
324
|
+
class WikipediaConverter {
|
|
325
|
+
async convert(source, options = {}) {
|
|
326
|
+
const fileExtension = options.file_extension || "";
|
|
327
|
+
if (![".html", ".htm"].includes(fileExtension.toLowerCase())) {
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
const url = options.url || "";
|
|
331
|
+
if (!WIKIPEDIA_REGEX.test(url)) {
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
try {
|
|
335
|
+
const htmlContent = typeof source === "string" ? fs__namespace.readFileSync(source, { encoding: "utf-8" }) : source.toString("utf-8");
|
|
336
|
+
return this._convert(htmlContent);
|
|
337
|
+
} catch (error) {
|
|
338
|
+
console.error("Wikipedia Parsing Error:", error);
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
_convert(htmlContent) {
|
|
343
|
+
const dom = new jsdom.JSDOM(htmlContent);
|
|
344
|
+
const doc = dom.window.document;
|
|
345
|
+
doc.querySelectorAll("script, style").forEach((script) => {
|
|
346
|
+
script.remove();
|
|
347
|
+
});
|
|
348
|
+
const bodyElm = doc.querySelector(BODY_SELECTOR_QUERY);
|
|
349
|
+
const titleElm = doc.querySelector(TITLE_SELECTOR_QUERY);
|
|
350
|
+
let webpageText = "";
|
|
351
|
+
let mainTitle = doc.title;
|
|
352
|
+
if (bodyElm) {
|
|
353
|
+
if (titleElm && titleElm.textContent) {
|
|
354
|
+
mainTitle = titleElm.textContent;
|
|
355
|
+
}
|
|
356
|
+
webpageText = `# ${mainTitle}
|
|
357
|
+
|
|
358
|
+
` + new CustomTurnDown().convert_soup(bodyElm);
|
|
359
|
+
} else {
|
|
360
|
+
webpageText = new CustomTurnDown().convert_soup(doc);
|
|
361
|
+
}
|
|
362
|
+
return { title: mainTitle, markdown: webpageText, text_content: webpageText };
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
class YouTubeConverter {
|
|
367
|
+
async convert(source, options = {}) {
|
|
368
|
+
const fileExtension = options.file_extension || "";
|
|
369
|
+
if (![".html", ".htm"].includes(fileExtension.toLowerCase())) {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
const url = options.url || "";
|
|
373
|
+
if (!url.startsWith("https://www.youtube.com/watch?")) {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
try {
|
|
377
|
+
const htmlContent = typeof source === "string" ? fs__namespace.readFileSync(source, { encoding: "utf-8" }) : source.toString("utf-8");
|
|
378
|
+
return this._convert(htmlContent, url, options);
|
|
379
|
+
} catch (error) {
|
|
380
|
+
console.error("YouTube Parsing Error:", error);
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
async _convert(htmlContent, url$1, options) {
|
|
385
|
+
const dom = new jsdom.JSDOM(htmlContent);
|
|
386
|
+
const doc = dom.window.document;
|
|
387
|
+
const metadata = {
|
|
388
|
+
title: doc.title
|
|
389
|
+
};
|
|
390
|
+
doc.querySelectorAll("meta").forEach((meta) => {
|
|
391
|
+
for (const a of meta.attributes) {
|
|
392
|
+
const attributeContent = meta.getAttribute("content");
|
|
393
|
+
if (["itemprop", "property", "name"].includes(a.name) && attributeContent) {
|
|
394
|
+
metadata[a.value] = attributeContent;
|
|
395
|
+
break;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
try {
|
|
400
|
+
for (const script of doc.querySelectorAll("script")) {
|
|
401
|
+
const content = script.textContent || "";
|
|
402
|
+
if (content.includes("ytInitialData")) {
|
|
403
|
+
const lines = content.split(/\r?\n/);
|
|
404
|
+
const objStart = lines[0].indexOf("{");
|
|
405
|
+
const objEnd = lines[0].lastIndexOf("}");
|
|
406
|
+
if (objStart >= 0 && objEnd >= 0) {
|
|
407
|
+
const data = JSON.parse(lines[0].substring(objStart, objEnd + 1));
|
|
408
|
+
const attrdesc = this._findKey(data, "attributedDescriptionBodyText");
|
|
409
|
+
if (attrdesc) {
|
|
410
|
+
metadata["description"] = attrdesc["content"];
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
} catch (e) {
|
|
417
|
+
console.warn("Error while parsing Youtube description");
|
|
418
|
+
}
|
|
419
|
+
let webpageText = "# YouTube\n";
|
|
420
|
+
const title = this._get(metadata, ["title", "og:title", "name"]);
|
|
421
|
+
if (title) {
|
|
422
|
+
webpageText += `
|
|
423
|
+
## ${title}
|
|
424
|
+
`;
|
|
425
|
+
}
|
|
426
|
+
let stats = "";
|
|
427
|
+
const views = this._get(metadata, ["interactionCount"]);
|
|
428
|
+
if (views) {
|
|
429
|
+
stats += `- **Views:** ${views}
|
|
430
|
+
`;
|
|
431
|
+
}
|
|
432
|
+
const keywords = this._get(metadata, ["keywords"]);
|
|
433
|
+
if (keywords) {
|
|
434
|
+
stats += `- **Keywords:** ${keywords}
|
|
435
|
+
`;
|
|
436
|
+
}
|
|
437
|
+
const runtime = this._get(metadata, ["duration"]);
|
|
438
|
+
if (runtime) {
|
|
439
|
+
stats += `- **Runtime:** ${runtime}
|
|
440
|
+
`;
|
|
441
|
+
}
|
|
442
|
+
if (stats.length > 0) {
|
|
443
|
+
webpageText += `
|
|
444
|
+
### Video Metadata
|
|
445
|
+
${stats}
|
|
446
|
+
`;
|
|
447
|
+
}
|
|
448
|
+
const description = this._get(metadata, ["description", "og:description"]);
|
|
449
|
+
if (description) {
|
|
450
|
+
webpageText += `
|
|
451
|
+
### Description
|
|
452
|
+
${description}
|
|
453
|
+
`;
|
|
454
|
+
}
|
|
455
|
+
if (options.enableYoutubeTranscript) {
|
|
456
|
+
let transcriptText = "";
|
|
457
|
+
const parsedUrl = new url.URL(url$1);
|
|
458
|
+
const params = parsedUrl.searchParams;
|
|
459
|
+
const videoId = params.get("v");
|
|
460
|
+
let ytTranscript;
|
|
461
|
+
try {
|
|
462
|
+
ytTranscript = await import('youtube-transcript').then((mod) => mod.YoutubeTranscript);
|
|
463
|
+
} catch (error) {
|
|
464
|
+
console.warn(
|
|
465
|
+
"Optional dependency 'youtube-transcript' is not installed. Run `npm install youtube-transcript` to enable this feature."
|
|
466
|
+
);
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
if (videoId) {
|
|
470
|
+
try {
|
|
471
|
+
const youtubeTranscriptLanguage = options.youtubeTranscriptLanguage || "en";
|
|
472
|
+
const transcript = await ytTranscript.fetchTranscript(videoId, {
|
|
473
|
+
lang: youtubeTranscriptLanguage
|
|
474
|
+
});
|
|
475
|
+
transcriptText = transcript.map((part) => part.text).join(" ");
|
|
476
|
+
} catch (error) {
|
|
477
|
+
console.warn("Error while extracting the Youtube Transcript", error);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
if (transcriptText) {
|
|
481
|
+
webpageText += `
|
|
482
|
+
### Transcript
|
|
483
|
+
${transcriptText}
|
|
484
|
+
`;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
const finalTitle = title ? title : doc.title;
|
|
488
|
+
return { title: finalTitle, markdown: webpageText, text_content: webpageText };
|
|
489
|
+
}
|
|
490
|
+
_get(metadata, keys, default_value) {
|
|
491
|
+
for (const k of keys) {
|
|
492
|
+
if (metadata[k]) {
|
|
493
|
+
return metadata[k];
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return default_value || null;
|
|
497
|
+
}
|
|
498
|
+
_findKey(json, key) {
|
|
499
|
+
if (Array.isArray(json)) {
|
|
500
|
+
for (const elm of json) {
|
|
501
|
+
const ret = this._findKey(elm, key);
|
|
502
|
+
if (ret) {
|
|
503
|
+
return ret;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
} else if (typeof json === "object" && json !== null) {
|
|
507
|
+
for (const k in json) {
|
|
508
|
+
if (k === key) {
|
|
509
|
+
return json[k];
|
|
510
|
+
} else {
|
|
511
|
+
const ret = this._findKey(json[k], key);
|
|
512
|
+
if (ret) {
|
|
513
|
+
return ret;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return null;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
class IpynbConverter {
|
|
523
|
+
async convert(source, options = {}) {
|
|
524
|
+
const fileExtension = options.file_extension || "";
|
|
525
|
+
if (fileExtension.toLowerCase() !== ".ipynb") {
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
528
|
+
try {
|
|
529
|
+
const contentStirng = typeof source === "string" ? fs__namespace.readFileSync(source, { encoding: "utf-8" }) : source.toString("utf-8");
|
|
530
|
+
const notebookContent = JSON.parse(contentStirng);
|
|
531
|
+
return this._convert(notebookContent);
|
|
532
|
+
} catch (error) {
|
|
533
|
+
console.error("Error converting .ipynb file:", error);
|
|
534
|
+
return null;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
_convert(notebookContent) {
|
|
538
|
+
try {
|
|
539
|
+
const mdOutput = [];
|
|
540
|
+
let title = null;
|
|
541
|
+
for (const cell of notebookContent.cells || []) {
|
|
542
|
+
const cellType = cell.cell_type || "";
|
|
543
|
+
const sourceLines = cell.source || [];
|
|
544
|
+
if (cellType === "markdown") {
|
|
545
|
+
mdOutput.push(sourceLines.join(""));
|
|
546
|
+
if (!title) {
|
|
547
|
+
for (const line of sourceLines) {
|
|
548
|
+
if (line.startsWith("# ")) {
|
|
549
|
+
title = line.substring(line.indexOf("# ") + 2).trim();
|
|
550
|
+
break;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
} else if (cellType === "code") {
|
|
555
|
+
mdOutput.push(`\`\`\`python
|
|
556
|
+
${sourceLines.join("")}
|
|
557
|
+
\`\`\``);
|
|
558
|
+
} else if (cellType === "raw") {
|
|
559
|
+
mdOutput.push(`\`\`\`
|
|
560
|
+
${sourceLines.join("")}
|
|
561
|
+
\`\`\``);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
const mdText = mdOutput.join("\n\n");
|
|
565
|
+
title = notebookContent.metadata?.title || title;
|
|
566
|
+
return { title, markdown: mdText, text_content: mdText };
|
|
567
|
+
} catch (e) {
|
|
568
|
+
console.error("Error converting .ipynb file:", e);
|
|
569
|
+
throw new Error(`Error converting .ipynb file: ${e}`);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
class BingSerpConverter {
|
|
575
|
+
async convert(source, options = {}) {
|
|
576
|
+
const fileExtension = options.file_extension || "";
|
|
577
|
+
if (![".html", ".htm"].includes(fileExtension.toLowerCase())) {
|
|
578
|
+
return null;
|
|
579
|
+
}
|
|
580
|
+
const url = options.url || "";
|
|
581
|
+
if (!/^https:\/\/www\.bing\.com\/search\?q=/.test(url)) {
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
try {
|
|
585
|
+
const htmlContent = typeof source === "string" ? fs__namespace.readFileSync(source, { encoding: "utf-8" }) : Buffer.from(source).toString("utf-8");
|
|
586
|
+
return this._convert(htmlContent, url);
|
|
587
|
+
} catch (error) {
|
|
588
|
+
console.error("Bing SERP Parsing Error:", error);
|
|
589
|
+
return null;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
_convert(htmlContent, url$1) {
|
|
593
|
+
const dom = new jsdom.JSDOM(htmlContent);
|
|
594
|
+
const doc = dom.window.document;
|
|
595
|
+
const parsedParams = new url.URL(url$1).searchParams;
|
|
596
|
+
const query = parsedParams.get("q") || "";
|
|
597
|
+
doc.querySelectorAll(".tptt").forEach((tptt) => {
|
|
598
|
+
if (tptt.textContent) {
|
|
599
|
+
tptt.textContent += " ";
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
doc.querySelectorAll(".algoSlug_icon").forEach((slug) => {
|
|
603
|
+
slug.remove();
|
|
604
|
+
});
|
|
605
|
+
const markdownify = new CustomTurnDown();
|
|
606
|
+
const results = [];
|
|
607
|
+
doc.querySelectorAll(".b_algo").forEach((result) => {
|
|
608
|
+
result.querySelectorAll("a[href]").forEach((a) => {
|
|
609
|
+
try {
|
|
610
|
+
const parsedHref = new url.URL(a.getAttribute("href"));
|
|
611
|
+
const params = parsedHref.searchParams;
|
|
612
|
+
const u = params.get("u");
|
|
613
|
+
if (u) {
|
|
614
|
+
const decoded = this._decodeBase64Url(u);
|
|
615
|
+
a.setAttribute("href", decoded);
|
|
616
|
+
}
|
|
617
|
+
} catch (e) {
|
|
618
|
+
}
|
|
619
|
+
});
|
|
620
|
+
const mdResult = markdownify.convert_soup(result).trim();
|
|
621
|
+
const lines = mdResult.split(/\n+/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
622
|
+
results.push(lines.join("\n"));
|
|
623
|
+
});
|
|
624
|
+
const webpageText = `## A Bing search for '${query}' found the following results:
|
|
625
|
+
|
|
626
|
+
${results.join("\n\n")}`;
|
|
627
|
+
return { title: doc.title, markdown: webpageText, text_content: webpageText };
|
|
628
|
+
}
|
|
629
|
+
_decodeBase64Url(encodedUrl) {
|
|
630
|
+
let u = encodedUrl.slice(2).trim() + "==";
|
|
631
|
+
try {
|
|
632
|
+
const decoded = Buffer.from(u, "base64").toString("utf-8");
|
|
633
|
+
return decoded;
|
|
634
|
+
} catch (error) {
|
|
635
|
+
console.error("Error decoding Base64URL:", error);
|
|
636
|
+
return encodedUrl;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
class PdfConverter {
|
|
642
|
+
async convert(source, options = {}) {
|
|
643
|
+
const fileExtension = options.file_extension || "";
|
|
644
|
+
if (![".pdf"].includes(fileExtension.toLowerCase())) {
|
|
645
|
+
return null;
|
|
646
|
+
}
|
|
647
|
+
try {
|
|
648
|
+
const pdfContent = typeof source === "string" ? fs__default.readFileSync(source) : Buffer.from(source);
|
|
649
|
+
return this._convert(pdfContent);
|
|
650
|
+
} catch (error) {
|
|
651
|
+
console.error("PDF Parsing Error:", error);
|
|
652
|
+
return null;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
async _convert(pdfContent) {
|
|
656
|
+
try {
|
|
657
|
+
const parser = new pdfParse.PDFParse({ data: pdfContent });
|
|
658
|
+
const result = await parser.getText();
|
|
659
|
+
await parser.destroy();
|
|
660
|
+
return { title: null, markdown: result.text, text_content: result.text };
|
|
661
|
+
} catch (error) {
|
|
662
|
+
console.error("PDF Parsing Error:", error);
|
|
663
|
+
return null;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
class DocxConverter extends HtmlConverter {
|
|
669
|
+
async convert(source, options) {
|
|
670
|
+
const fileExtension = options.file_extension || "";
|
|
671
|
+
if (![".docx"].includes(fileExtension.toLowerCase())) {
|
|
672
|
+
return null;
|
|
673
|
+
}
|
|
674
|
+
try {
|
|
675
|
+
let mammothInput;
|
|
676
|
+
if (typeof source === "string") {
|
|
677
|
+
if (!fs__namespace.existsSync(source)) {
|
|
678
|
+
throw new Error("File does'nt exists");
|
|
679
|
+
}
|
|
680
|
+
mammothInput = { path: source };
|
|
681
|
+
} else {
|
|
682
|
+
mammothInput = { buffer: Buffer.from(source) };
|
|
683
|
+
}
|
|
684
|
+
let htmlContent = await Mammoth__default.convertToHtml(mammothInput, {
|
|
685
|
+
...options
|
|
686
|
+
});
|
|
687
|
+
return await this._convert(htmlContent.value);
|
|
688
|
+
} catch (e) {
|
|
689
|
+
console.error(e);
|
|
690
|
+
return null;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
class XlsxConverter extends HtmlConverter {
|
|
696
|
+
async convert(source, options) {
|
|
697
|
+
const extension = options.file_extension || "";
|
|
698
|
+
if (![".xlsx"].includes(extension.toLowerCase())) {
|
|
699
|
+
return null;
|
|
700
|
+
}
|
|
701
|
+
try {
|
|
702
|
+
let workbook;
|
|
703
|
+
if (typeof source === "string") {
|
|
704
|
+
if (!fs__namespace.existsSync(source)) {
|
|
705
|
+
throw new Error("File does'nt exists");
|
|
706
|
+
}
|
|
707
|
+
workbook = XLSX__namespace.readFile(source);
|
|
708
|
+
} else {
|
|
709
|
+
workbook = XLSX__namespace.read(source, { type: "buffer" });
|
|
710
|
+
}
|
|
711
|
+
let mdContent = "";
|
|
712
|
+
for (const sheetName of workbook.SheetNames) {
|
|
713
|
+
const sheet = workbook.Sheets[sheetName];
|
|
714
|
+
if (sheet["!ref"]) {
|
|
715
|
+
mdContent += `## ${sheetName}
|
|
716
|
+
`;
|
|
717
|
+
let htmlContent = XLSX__namespace.utils.sheet_to_html(sheet);
|
|
718
|
+
mdContent += (await this._convert(htmlContent))?.markdown.trim() + "\n\n";
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return { title: workbook?.Props?.Title || "Untitled", markdown: mdContent, text_content: mdContent };
|
|
722
|
+
} catch (e) {
|
|
723
|
+
console.error(e);
|
|
724
|
+
return null;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
const exec = util__namespace.promisify(childProcess__namespace.exec);
|
|
730
|
+
class MediaConverter {
|
|
731
|
+
async _getMetadata(local_path) {
|
|
732
|
+
const exiftool = await this._which("exiftool");
|
|
733
|
+
if (!exiftool) {
|
|
734
|
+
console.error("exiftool is not found on this system so metadata cannot be extracted");
|
|
735
|
+
return null;
|
|
736
|
+
}
|
|
737
|
+
try {
|
|
738
|
+
const result = await exec(`"${exiftool}" -json "${local_path}"`);
|
|
739
|
+
return JSON.parse(result.stdout)[0];
|
|
740
|
+
} catch (error) {
|
|
741
|
+
console.error("Exiftool error:", error);
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
async _which(command) {
|
|
746
|
+
try {
|
|
747
|
+
const result = await exec(`which ${command}`);
|
|
748
|
+
return result.stdout.trim();
|
|
749
|
+
} catch (error) {
|
|
750
|
+
console.warn("Which command error:", error);
|
|
751
|
+
return null;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
class WavConverter extends MediaConverter {
|
|
757
|
+
async convert(source, options = {}) {
|
|
758
|
+
const fileExtension = options.file_extension || "";
|
|
759
|
+
if (fileExtension.toLowerCase() !== ".wav") {
|
|
760
|
+
return null;
|
|
761
|
+
}
|
|
762
|
+
try {
|
|
763
|
+
return this._convert(source, options);
|
|
764
|
+
} catch (error) {
|
|
765
|
+
console.error("WAV Conversion Error:", error);
|
|
766
|
+
return null;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
async _convert(source, _) {
|
|
770
|
+
let mdContent = "";
|
|
771
|
+
if (typeof source === "string") {
|
|
772
|
+
const metadata = await this._getMetadata(source);
|
|
773
|
+
if (metadata) {
|
|
774
|
+
for (const f of [
|
|
775
|
+
"Title",
|
|
776
|
+
"Artist",
|
|
777
|
+
"Author",
|
|
778
|
+
"Band",
|
|
779
|
+
"Album",
|
|
780
|
+
"Genre",
|
|
781
|
+
"Track",
|
|
782
|
+
"DateTimeOriginal",
|
|
783
|
+
"CreateDate",
|
|
784
|
+
"Duration"
|
|
785
|
+
]) {
|
|
786
|
+
if (metadata[f]) {
|
|
787
|
+
mdContent += `${f}: ${metadata[f]}
|
|
788
|
+
`;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
} else {
|
|
793
|
+
console.warn(
|
|
794
|
+
"Metadata extraction is skipped for Buffer inputs as it requires a file path for exiftool."
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
if (typeof source === "string") {
|
|
798
|
+
try {
|
|
799
|
+
const transcript = await this._transcribeAudio(source);
|
|
800
|
+
mdContent += `
|
|
801
|
+
|
|
802
|
+
### Audio Transcript:
|
|
803
|
+
${transcript === "" ? "[No speech detected]" : transcript}`;
|
|
804
|
+
} catch (error) {
|
|
805
|
+
console.error("Error loading speech recognition module:", error);
|
|
806
|
+
mdContent += "\n\n### Audio Transcript:\nError. Could not transcribe this audio.";
|
|
807
|
+
}
|
|
808
|
+
} else {
|
|
809
|
+
mdContent += "\n\n### Audio Transcript:\n[Audio transcription is not supported for Buffer inputs in this version.]";
|
|
810
|
+
}
|
|
811
|
+
return { title: null, markdown: mdContent.trim(), text_content: mdContent.trim() };
|
|
812
|
+
}
|
|
813
|
+
// TODO: Add speech to text
|
|
814
|
+
async _transcribeAudio(_) {
|
|
815
|
+
throw new Error("TODO: Audio transcription not implemented yet");
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
class Mp3Converter extends WavConverter {
|
|
820
|
+
async convert(source, options = {}) {
|
|
821
|
+
const fileExtension = options.file_extension || "";
|
|
822
|
+
if (fileExtension.toLowerCase() !== ".mp3") {
|
|
823
|
+
return null;
|
|
824
|
+
}
|
|
825
|
+
try {
|
|
826
|
+
return await this._convert$(source, options);
|
|
827
|
+
} catch (error) {
|
|
828
|
+
console.error("MP3 Conversion Error:", error);
|
|
829
|
+
return null;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
async _convert$(source, options) {
|
|
833
|
+
let mdContent = "";
|
|
834
|
+
if (typeof source === "string") {
|
|
835
|
+
const metadata = await this._getMetadata(source);
|
|
836
|
+
if (metadata) {
|
|
837
|
+
for (const f of [
|
|
838
|
+
"Title",
|
|
839
|
+
"Artist",
|
|
840
|
+
"Author",
|
|
841
|
+
"Band",
|
|
842
|
+
"Album",
|
|
843
|
+
"Genre",
|
|
844
|
+
"Track",
|
|
845
|
+
"DateTimeOriginal",
|
|
846
|
+
"CreateDate",
|
|
847
|
+
"Duration"
|
|
848
|
+
]) {
|
|
849
|
+
if (metadata[f]) {
|
|
850
|
+
mdContent += `${f}: ${metadata[f]}
|
|
851
|
+
`;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
} else {
|
|
856
|
+
console.warn(
|
|
857
|
+
"Metadata extraction is skipped for Buffer inputs as it requires a file path for exiftool."
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
if (typeof source === "string") {
|
|
861
|
+
const tempPath = await fs__namespace$1.mkdtemp(path__namespace.join(os__namespace.tmpdir(), "temp_"));
|
|
862
|
+
const wavPath = path__namespace.join(tempPath, "audio.wav");
|
|
863
|
+
try {
|
|
864
|
+
const transcript = await super._transcribeAudio(wavPath);
|
|
865
|
+
mdContent += `
|
|
866
|
+
|
|
867
|
+
### Audio Transcript:
|
|
868
|
+
${transcript == "" ? "[No speech detected]" : transcript}`;
|
|
869
|
+
} catch (e) {
|
|
870
|
+
mdContent += "\n\n### Audio Transcript:\nError. Could not transcribe this audio.";
|
|
871
|
+
} finally {
|
|
872
|
+
await fs__namespace$1.unlink(wavPath);
|
|
873
|
+
await fs__namespace$1.rmdir(tempPath);
|
|
874
|
+
}
|
|
875
|
+
} else {
|
|
876
|
+
mdContent += "\n\n### Audio Transcript:\n[Audio conversion and transcription are not supported for Buffer inputs.]";
|
|
877
|
+
}
|
|
878
|
+
return { title: null, markdown: mdContent.trim(), text_content: mdContent.trim() };
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
class ImageConverter extends MediaConverter {
|
|
883
|
+
async convert(source, options = {}) {
|
|
884
|
+
const fileExtension = options.file_extension || "";
|
|
885
|
+
if (![".jpg", ".jpeg", ".png"].includes(fileExtension.toLowerCase())) {
|
|
886
|
+
return null;
|
|
887
|
+
}
|
|
888
|
+
try {
|
|
889
|
+
return this._convert(source, options);
|
|
890
|
+
} catch (error) {
|
|
891
|
+
console.error("Image Conversion Error:", error);
|
|
892
|
+
return null;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
async _convert(source, options) {
|
|
896
|
+
let mdContent = "";
|
|
897
|
+
if (typeof source === "string") {
|
|
898
|
+
const metadata = await this._getMetadata(source);
|
|
899
|
+
if (metadata) {
|
|
900
|
+
for (const f of [
|
|
901
|
+
"ImageSize",
|
|
902
|
+
"Title",
|
|
903
|
+
"Caption",
|
|
904
|
+
"Description",
|
|
905
|
+
"Keywords",
|
|
906
|
+
"Artist",
|
|
907
|
+
"Author",
|
|
908
|
+
"DateTimeOriginal",
|
|
909
|
+
"CreateDate",
|
|
910
|
+
"GPSPosition"
|
|
911
|
+
]) {
|
|
912
|
+
if (metadata[f]) {
|
|
913
|
+
mdContent += `${f}: ${metadata[f]}
|
|
914
|
+
`;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
} else {
|
|
919
|
+
console.warn(
|
|
920
|
+
"Metadata extraction is skipped for Buffer inputs as it requires a file path for exiftool."
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
if (options.llmModel) {
|
|
924
|
+
const imageBuffer = typeof source === "string" ? fs__namespace.readFileSync(source) : Buffer.from(source);
|
|
925
|
+
mdContent += `
|
|
926
|
+
# Description:
|
|
927
|
+
${(await this._getLLMDescription(imageBuffer, options)).trim()}
|
|
928
|
+
`;
|
|
929
|
+
}
|
|
930
|
+
return { title: null, markdown: mdContent.trim(), text_content: mdContent.trim() };
|
|
931
|
+
}
|
|
932
|
+
async _getLLMDescription(imageBuffer, options) {
|
|
933
|
+
if (!options.llmPrompt || options.llmPrompt.trim() === "") {
|
|
934
|
+
options.llmPrompt = "Write a detailed caption for this image.";
|
|
935
|
+
}
|
|
936
|
+
const imageFileAsBase64 = imageBuffer.toString("base64");
|
|
937
|
+
const result = await ai.generateText({
|
|
938
|
+
model: options.llmModel,
|
|
939
|
+
messages: [
|
|
940
|
+
{
|
|
941
|
+
role: "user",
|
|
942
|
+
content: [
|
|
943
|
+
{ type: "text", text: options.llmPrompt },
|
|
944
|
+
{
|
|
945
|
+
type: "image",
|
|
946
|
+
image: imageFileAsBase64
|
|
947
|
+
}
|
|
948
|
+
]
|
|
949
|
+
}
|
|
950
|
+
]
|
|
951
|
+
});
|
|
952
|
+
return result.text.trim();
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
class ZipConverter {
|
|
957
|
+
async convert(source, options = {}) {
|
|
958
|
+
const fileExtension = options.file_extension || "";
|
|
959
|
+
if (fileExtension.toLowerCase() !== ".zip") {
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
const parentConverters = options._parent_converters || [];
|
|
963
|
+
if (!parentConverters) {
|
|
964
|
+
return {
|
|
965
|
+
title: null,
|
|
966
|
+
markdown: `[ERROR] No converters available to process zip contents from: ${source}`,
|
|
967
|
+
text_content: `[ERROR] No converters available to process zip contents from: ${source}`
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
let unzipper2;
|
|
971
|
+
try {
|
|
972
|
+
unzipper2 = await import('unzipper').then((mod) => mod.default);
|
|
973
|
+
} catch (error) {
|
|
974
|
+
console.error(
|
|
975
|
+
"Optional dependency 'unzipper' is not installed. Run `npm install unzipper` to enable this feature."
|
|
976
|
+
);
|
|
977
|
+
return null;
|
|
978
|
+
}
|
|
979
|
+
try {
|
|
980
|
+
const zipFileName = typeof source === "string" ? path__namespace.basename(source) : "archive.zip";
|
|
981
|
+
let mdContent = `Content from the zip file \`${zipFileName}\`:
|
|
982
|
+
|
|
983
|
+
`;
|
|
984
|
+
const mdResults = [];
|
|
985
|
+
const processEntry = async (entry) => {
|
|
986
|
+
const relativePath = entry.path;
|
|
987
|
+
if (entry.type === "File") {
|
|
988
|
+
const entryExtension = path__namespace.extname(relativePath);
|
|
989
|
+
const entryBuffer = await entry.buffer();
|
|
990
|
+
const fileOptions = {
|
|
991
|
+
...options,
|
|
992
|
+
file_extension: entryExtension,
|
|
993
|
+
_parent_converters: parentConverters
|
|
994
|
+
};
|
|
995
|
+
for (const converter of parentConverters) {
|
|
996
|
+
if (converter instanceof ZipConverter) {
|
|
997
|
+
continue;
|
|
998
|
+
}
|
|
999
|
+
const result = await converter.convert(entryBuffer, fileOptions);
|
|
1000
|
+
if (result) {
|
|
1001
|
+
mdResults.push(`
|
|
1002
|
+
## File: ${relativePath}
|
|
1003
|
+
|
|
1004
|
+
${result.markdown}
|
|
1005
|
+
|
|
1006
|
+
`);
|
|
1007
|
+
break;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
} else {
|
|
1011
|
+
entry.autodrain();
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
const inputStream = typeof source === "string" ? fs__namespace.createReadStream(source) : new stream.PassThrough().end(source);
|
|
1015
|
+
await new Promise((res, rej) => {
|
|
1016
|
+
const parser = unzipper2.Parse();
|
|
1017
|
+
parser.on("entry", (entry) => {
|
|
1018
|
+
processEntry(entry).catch((err) => {
|
|
1019
|
+
parser.destroy(err);
|
|
1020
|
+
rej(err);
|
|
1021
|
+
});
|
|
1022
|
+
});
|
|
1023
|
+
parser.on("finish", res);
|
|
1024
|
+
parser.on("error", rej);
|
|
1025
|
+
inputStream.pipe(parser);
|
|
1026
|
+
});
|
|
1027
|
+
mdContent += mdResults.join("");
|
|
1028
|
+
return { title: null, markdown: mdContent.trim(), text_content: mdContent.trim() };
|
|
1029
|
+
} catch (error) {
|
|
1030
|
+
if (error.message.includes("invalid signature")) {
|
|
1031
|
+
return {
|
|
1032
|
+
title: null,
|
|
1033
|
+
markdown: `[ERROR] Invalid or corrupted zip file: ${source}`,
|
|
1034
|
+
text_content: `[ERROR] Invalid or corrupted zip file: ${source}`
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
return {
|
|
1038
|
+
title: null,
|
|
1039
|
+
markdown: `[ERROR] Failed to process zip file ${source}: ${String(error)}`,
|
|
1040
|
+
text_content: `[ERROR] Failed to process zip file ${source}: ${String(error)}`
|
|
1041
|
+
};
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
class MarkItDown {
|
|
1047
|
+
converters = [];
|
|
1048
|
+
constructor() {
|
|
1049
|
+
this.register_converter(new PlainTextConverter());
|
|
1050
|
+
this.register_converter(new HtmlConverter());
|
|
1051
|
+
this.register_converter(new RSSConverter());
|
|
1052
|
+
this.register_converter(new WikipediaConverter());
|
|
1053
|
+
this.register_converter(new YouTubeConverter());
|
|
1054
|
+
this.register_converter(new BingSerpConverter());
|
|
1055
|
+
this.register_converter(new DocxConverter());
|
|
1056
|
+
this.register_converter(new XlsxConverter());
|
|
1057
|
+
this.register_converter(new WavConverter());
|
|
1058
|
+
this.register_converter(new Mp3Converter());
|
|
1059
|
+
this.register_converter(new ImageConverter());
|
|
1060
|
+
this.register_converter(new IpynbConverter());
|
|
1061
|
+
this.register_converter(new PdfConverter());
|
|
1062
|
+
this.register_converter(new ZipConverter());
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Converts a source from a file path, URL, or Response object.
|
|
1066
|
+
*/
|
|
1067
|
+
async convert(source, options = {}) {
|
|
1068
|
+
if (source instanceof Response) {
|
|
1069
|
+
return await this.convert_response(source, options);
|
|
1070
|
+
} else {
|
|
1071
|
+
if (source.startsWith("http://") || source.startsWith("https://") || source.startsWith("file://")) {
|
|
1072
|
+
return await this.convert_url(source, options);
|
|
1073
|
+
} else {
|
|
1074
|
+
return this.convert_local(source, options);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Converts a source from an in-memory Buffer.
|
|
1080
|
+
*/
|
|
1081
|
+
async convertBuffer(source, options) {
|
|
1082
|
+
const extensions = /* @__PURE__ */ new Set([options.file_extension]);
|
|
1083
|
+
return this._convert(source, extensions, options);
|
|
1084
|
+
}
|
|
1085
|
+
async convert_url(source, { fetch = globalThis.fetch, ...options }) {
|
|
1086
|
+
let response = await fetch(source);
|
|
1087
|
+
if (!response.ok) {
|
|
1088
|
+
throw new Error(`Failed to fetch URL: ${source}, status: ${response.status}`);
|
|
1089
|
+
}
|
|
1090
|
+
return await this.convert_response(response, options);
|
|
1091
|
+
}
|
|
1092
|
+
async convert_response(response, options) {
|
|
1093
|
+
const ext = options.file_extension;
|
|
1094
|
+
const extensions = ext ? /* @__PURE__ */ new Set([ext]) : /* @__PURE__ */ new Set();
|
|
1095
|
+
const contentType = response.headers?.get("content-type")?.split(";")[0];
|
|
1096
|
+
if (!contentType) {
|
|
1097
|
+
throw new Error("Response Content-Type header is missing");
|
|
1098
|
+
}
|
|
1099
|
+
const mimeExtension = mime__namespace.extension(contentType);
|
|
1100
|
+
if (mimeExtension) {
|
|
1101
|
+
extensions.add(`.${mimeExtension}`);
|
|
1102
|
+
}
|
|
1103
|
+
const content_disposition = response.headers?.get("content-disposition") || "";
|
|
1104
|
+
const fname = content_disposition.match(/filename="([^;]+)"/);
|
|
1105
|
+
if (fname) {
|
|
1106
|
+
extensions.add(path__default.extname(fname[1]));
|
|
1107
|
+
}
|
|
1108
|
+
if (response.url) {
|
|
1109
|
+
const url_ext = path__default.extname(new URL(response.url).pathname);
|
|
1110
|
+
extensions.add(url_ext);
|
|
1111
|
+
}
|
|
1112
|
+
if (extensions.size === 0) {
|
|
1113
|
+
throw new Error(
|
|
1114
|
+
"Could not determine file type. Please provide a `file_extension` in the options."
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
if (response.body == null) {
|
|
1118
|
+
throw new Error("Response body is empty");
|
|
1119
|
+
}
|
|
1120
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
1121
|
+
return await this._convert(buffer, extensions, {
|
|
1122
|
+
...options,
|
|
1123
|
+
url: response.url
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
async convert_local(source, options) {
|
|
1127
|
+
const ext = options.file_extension;
|
|
1128
|
+
const extensions = ext ? new Set(ext) : /* @__PURE__ */ new Set();
|
|
1129
|
+
if (!fs__namespace.existsSync(source)) {
|
|
1130
|
+
throw new Error(`File not found: ${source}`);
|
|
1131
|
+
}
|
|
1132
|
+
const extname = path__default.extname(source);
|
|
1133
|
+
if (extname === "") {
|
|
1134
|
+
throw new Error(`File extension not found: ${source}`);
|
|
1135
|
+
}
|
|
1136
|
+
if (!extensions.has(extname)) {
|
|
1137
|
+
extensions.add(extname);
|
|
1138
|
+
}
|
|
1139
|
+
return await this._convert(source, extensions, options);
|
|
1140
|
+
}
|
|
1141
|
+
async _convert(source, extensions, options = {}) {
|
|
1142
|
+
let error;
|
|
1143
|
+
for (const ext of extensions) {
|
|
1144
|
+
for (const converter of this.converters) {
|
|
1145
|
+
let res;
|
|
1146
|
+
try {
|
|
1147
|
+
const op = {
|
|
1148
|
+
...options,
|
|
1149
|
+
file_extension: ext,
|
|
1150
|
+
_parent_converters: this.converters
|
|
1151
|
+
};
|
|
1152
|
+
res = await converter.convert(source, op);
|
|
1153
|
+
} catch (e) {
|
|
1154
|
+
error = e;
|
|
1155
|
+
}
|
|
1156
|
+
if (res != null) {
|
|
1157
|
+
res.markdown = res.markdown.replace(/(?:\r\n|\r|\n)/g, "\n").trim();
|
|
1158
|
+
res.markdown = res.markdown.replace(/\n{3,}/g, "\n\n");
|
|
1159
|
+
return res;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
if (error) {
|
|
1164
|
+
throw new Error(
|
|
1165
|
+
`Could not convert ${source} to markdown. While converting the following error occurred: ${error}`
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
throw new Error(
|
|
1169
|
+
`Could not convert ${source} to markdown format. The ${Array.from(extensions).join(
|
|
1170
|
+
", "
|
|
1171
|
+
)} are not supported.`
|
|
1172
|
+
);
|
|
1173
|
+
}
|
|
1174
|
+
// NOTE: Inserts the converter at the beginning of the list
|
|
1175
|
+
register_converter(converter) {
|
|
1176
|
+
this.converters.unshift(converter);
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
exports.MarkItDown = MarkItDown;
|