formatferry 1.0.33 → 1.0.35
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 +2 -0
- package/dist/index.js +338 -96
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -103,6 +103,8 @@ formatferry [options]
|
|
|
103
103
|
| `-o, --output <path>` | Output file path (defaults to stdout) |
|
|
104
104
|
| `-f, --format <format>` | Markdown format (default: `github`) |
|
|
105
105
|
| `--url <url>` | Fetch and convert a web article (requires API key) |
|
|
106
|
+
|
|
107
|
+
`--url` asks the proxy for the page HTML and converts it locally, so `--format` chooses the Markdown flavour exactly as it does for a local file. The proxy also offers the finished Markdown directly: `POST /v1/extract` with `{ "format": "markdown" }` (see the root README).
|
|
106
108
|
| `--batch <glob>` | Batch convert files matching a glob pattern (Premium) |
|
|
107
109
|
| `--output-dir <dir>` | Output directory for batch mode |
|
|
108
110
|
| `--strict` | Exit with code 1 if the conversion produced any warnings (including advisory ones) |
|
package/dist/index.js
CHANGED
|
@@ -948,14 +948,14 @@ var require_Node = __commonJS({
|
|
|
948
948
|
this._nextSibling = this._previousSibling = this;
|
|
949
949
|
this._index = void 0;
|
|
950
950
|
}
|
|
951
|
-
var
|
|
951
|
+
var ELEMENT_NODE2 = Node2.ELEMENT_NODE = 1;
|
|
952
952
|
var ATTRIBUTE_NODE = Node2.ATTRIBUTE_NODE = 2;
|
|
953
953
|
var TEXT_NODE = Node2.TEXT_NODE = 3;
|
|
954
954
|
var CDATA_SECTION_NODE = Node2.CDATA_SECTION_NODE = 4;
|
|
955
955
|
var ENTITY_REFERENCE_NODE = Node2.ENTITY_REFERENCE_NODE = 5;
|
|
956
956
|
var ENTITY_NODE = Node2.ENTITY_NODE = 6;
|
|
957
957
|
var PROCESSING_INSTRUCTION_NODE = Node2.PROCESSING_INSTRUCTION_NODE = 7;
|
|
958
|
-
var
|
|
958
|
+
var COMMENT_NODE2 = Node2.COMMENT_NODE = 8;
|
|
959
959
|
var DOCUMENT_NODE = Node2.DOCUMENT_NODE = 9;
|
|
960
960
|
var DOCUMENT_TYPE_NODE = Node2.DOCUMENT_TYPE_NODE = 10;
|
|
961
961
|
var DOCUMENT_FRAGMENT_NODE = Node2.DOCUMENT_FRAGMENT_NODE = 11;
|
|
@@ -973,7 +973,7 @@ var require_Node = __commonJS({
|
|
|
973
973
|
// we'll come back to this later.
|
|
974
974
|
baseURI: { get: utils2.nyi },
|
|
975
975
|
parentElement: { get: function() {
|
|
976
|
-
return this.parentNode && this.parentNode.nodeType ===
|
|
976
|
+
return this.parentNode && this.parentNode.nodeType === ELEMENT_NODE2 ? this.parentNode : null;
|
|
977
977
|
} },
|
|
978
978
|
hasChildNodes: { value: utils2.shouldOverride },
|
|
979
979
|
firstChild: { get: utils2.shouldOverride },
|
|
@@ -1034,7 +1034,7 @@ var require_Node = __commonJS({
|
|
|
1034
1034
|
switch (parent.nodeType) {
|
|
1035
1035
|
case DOCUMENT_NODE:
|
|
1036
1036
|
case DOCUMENT_FRAGMENT_NODE:
|
|
1037
|
-
case
|
|
1037
|
+
case ELEMENT_NODE2:
|
|
1038
1038
|
break;
|
|
1039
1039
|
default:
|
|
1040
1040
|
utils2.HierarchyRequestError();
|
|
@@ -1046,10 +1046,10 @@ var require_Node = __commonJS({
|
|
|
1046
1046
|
switch (node.nodeType) {
|
|
1047
1047
|
case DOCUMENT_FRAGMENT_NODE:
|
|
1048
1048
|
case DOCUMENT_TYPE_NODE:
|
|
1049
|
-
case
|
|
1049
|
+
case ELEMENT_NODE2:
|
|
1050
1050
|
case TEXT_NODE:
|
|
1051
1051
|
case PROCESSING_INSTRUCTION_NODE:
|
|
1052
|
-
case
|
|
1052
|
+
case COMMENT_NODE2:
|
|
1053
1053
|
break;
|
|
1054
1054
|
default:
|
|
1055
1055
|
utils2.HierarchyRequestError();
|
|
@@ -1062,7 +1062,7 @@ var require_Node = __commonJS({
|
|
|
1062
1062
|
case DOCUMENT_FRAGMENT_NODE:
|
|
1063
1063
|
if (node._countChildrenOfType(TEXT_NODE) > 0)
|
|
1064
1064
|
utils2.HierarchyRequestError();
|
|
1065
|
-
switch (node._countChildrenOfType(
|
|
1065
|
+
switch (node._countChildrenOfType(ELEMENT_NODE2)) {
|
|
1066
1066
|
case 0:
|
|
1067
1067
|
break;
|
|
1068
1068
|
case 1:
|
|
@@ -1074,12 +1074,12 @@ var require_Node = __commonJS({
|
|
|
1074
1074
|
utils2.HierarchyRequestError();
|
|
1075
1075
|
}
|
|
1076
1076
|
}
|
|
1077
|
-
i = parent._countChildrenOfType(
|
|
1077
|
+
i = parent._countChildrenOfType(ELEMENT_NODE2);
|
|
1078
1078
|
if (isPreinsert) {
|
|
1079
1079
|
if (i > 0)
|
|
1080
1080
|
utils2.HierarchyRequestError();
|
|
1081
1081
|
} else {
|
|
1082
|
-
if (i > 1 || i === 1 && child.nodeType !==
|
|
1082
|
+
if (i > 1 || i === 1 && child.nodeType !== ELEMENT_NODE2)
|
|
1083
1083
|
utils2.HierarchyRequestError();
|
|
1084
1084
|
}
|
|
1085
1085
|
break;
|
|
@@ -1087,7 +1087,7 @@ var require_Node = __commonJS({
|
|
|
1087
1087
|
utils2.HierarchyRequestError();
|
|
1088
1088
|
}
|
|
1089
1089
|
break;
|
|
1090
|
-
case
|
|
1090
|
+
case ELEMENT_NODE2:
|
|
1091
1091
|
if (child !== null) {
|
|
1092
1092
|
if (isPreinsert && child.nodeType === DOCUMENT_TYPE_NODE)
|
|
1093
1093
|
utils2.HierarchyRequestError();
|
|
@@ -1096,23 +1096,23 @@ var require_Node = __commonJS({
|
|
|
1096
1096
|
utils2.HierarchyRequestError();
|
|
1097
1097
|
}
|
|
1098
1098
|
}
|
|
1099
|
-
i = parent._countChildrenOfType(
|
|
1099
|
+
i = parent._countChildrenOfType(ELEMENT_NODE2);
|
|
1100
1100
|
if (isPreinsert) {
|
|
1101
1101
|
if (i > 0)
|
|
1102
1102
|
utils2.HierarchyRequestError();
|
|
1103
1103
|
} else {
|
|
1104
|
-
if (i > 1 || i === 1 && child.nodeType !==
|
|
1104
|
+
if (i > 1 || i === 1 && child.nodeType !== ELEMENT_NODE2)
|
|
1105
1105
|
utils2.HierarchyRequestError();
|
|
1106
1106
|
}
|
|
1107
1107
|
break;
|
|
1108
1108
|
case DOCUMENT_TYPE_NODE:
|
|
1109
1109
|
if (child === null) {
|
|
1110
|
-
if (parent._countChildrenOfType(
|
|
1110
|
+
if (parent._countChildrenOfType(ELEMENT_NODE2))
|
|
1111
1111
|
utils2.HierarchyRequestError();
|
|
1112
1112
|
} else {
|
|
1113
1113
|
for (kid = parent.firstChild; kid !== null; kid = kid.nextSibling) {
|
|
1114
1114
|
if (kid === child) break;
|
|
1115
|
-
if (kid.nodeType ===
|
|
1115
|
+
if (kid.nodeType === ELEMENT_NODE2)
|
|
1116
1116
|
utils2.HierarchyRequestError();
|
|
1117
1117
|
}
|
|
1118
1118
|
}
|
|
@@ -1229,7 +1229,7 @@ var require_Node = __commonJS({
|
|
|
1229
1229
|
var e;
|
|
1230
1230
|
if (ns === "" || ns === null || ns === void 0) return null;
|
|
1231
1231
|
switch (this.nodeType) {
|
|
1232
|
-
case
|
|
1232
|
+
case ELEMENT_NODE2:
|
|
1233
1233
|
return this._lookupNamespacePrefix(ns, this);
|
|
1234
1234
|
case DOCUMENT_NODE:
|
|
1235
1235
|
e = this.documentElement;
|
|
@@ -1253,7 +1253,7 @@ var require_Node = __commonJS({
|
|
|
1253
1253
|
}
|
|
1254
1254
|
var e;
|
|
1255
1255
|
switch (this.nodeType) {
|
|
1256
|
-
case
|
|
1256
|
+
case ELEMENT_NODE2:
|
|
1257
1257
|
return utils2.shouldOverride();
|
|
1258
1258
|
case DOCUMENT_NODE:
|
|
1259
1259
|
e = this.documentElement;
|
|
@@ -1511,14 +1511,14 @@ var require_Node = __commonJS({
|
|
|
1511
1511
|
},
|
|
1512
1512
|
// mirror node type properties in the prototype, so they are present
|
|
1513
1513
|
// in instances of Node (and subclasses)
|
|
1514
|
-
ELEMENT_NODE: { value:
|
|
1514
|
+
ELEMENT_NODE: { value: ELEMENT_NODE2 },
|
|
1515
1515
|
ATTRIBUTE_NODE: { value: ATTRIBUTE_NODE },
|
|
1516
1516
|
TEXT_NODE: { value: TEXT_NODE },
|
|
1517
1517
|
CDATA_SECTION_NODE: { value: CDATA_SECTION_NODE },
|
|
1518
1518
|
ENTITY_REFERENCE_NODE: { value: ENTITY_REFERENCE_NODE },
|
|
1519
1519
|
ENTITY_NODE: { value: ENTITY_NODE },
|
|
1520
1520
|
PROCESSING_INSTRUCTION_NODE: { value: PROCESSING_INSTRUCTION_NODE },
|
|
1521
|
-
COMMENT_NODE: { value:
|
|
1521
|
+
COMMENT_NODE: { value: COMMENT_NODE2 },
|
|
1522
1522
|
DOCUMENT_NODE: { value: DOCUMENT_NODE },
|
|
1523
1523
|
DOCUMENT_TYPE_NODE: { value: DOCUMENT_TYPE_NODE },
|
|
1524
1524
|
DOCUMENT_FRAGMENT_NODE: { value: DOCUMENT_FRAGMENT_NODE },
|
|
@@ -58046,20 +58046,29 @@ var InputSanitizer = class {
|
|
|
58046
58046
|
this.purifyConfig = this.createPurifyConfig();
|
|
58047
58047
|
}
|
|
58048
58048
|
/**
|
|
58049
|
-
*
|
|
58049
|
+
* Like sanitizeHTML, but a sanitiser failure is thrown instead of being
|
|
58050
|
+
* turned into an empty string. Use it wherever an empty result would be
|
|
58051
|
+
* read as "the page had no content" (the ConversionEngine on an injected
|
|
58052
|
+
* DOM: the Worker's server-side Markdown and the CLI), so a failure is
|
|
58053
|
+
* reported as a failure (#170).
|
|
58050
58054
|
*/
|
|
58051
|
-
|
|
58055
|
+
sanitizeHTMLOrThrow(html) {
|
|
58052
58056
|
if (!html || typeof html !== "string") {
|
|
58053
58057
|
return "";
|
|
58054
58058
|
}
|
|
58059
|
+
return this.domEnv.DOMPurify.sanitize(html, {
|
|
58060
|
+
ALLOWED_TAGS: this.purifyConfig.ALLOWED_TAGS,
|
|
58061
|
+
ALLOWED_ATTR: this.purifyConfig.ALLOWED_ATTR,
|
|
58062
|
+
FORBID_TAGS: this.purifyConfig.FORBID_TAGS,
|
|
58063
|
+
FORBID_ATTR: this.purifyConfig.FORBID_ATTR
|
|
58064
|
+
});
|
|
58065
|
+
}
|
|
58066
|
+
/**
|
|
58067
|
+
* Sanitize HTML content to prevent XSS attacks
|
|
58068
|
+
*/
|
|
58069
|
+
sanitizeHTML(html) {
|
|
58055
58070
|
try {
|
|
58056
|
-
|
|
58057
|
-
ALLOWED_TAGS: this.purifyConfig.ALLOWED_TAGS,
|
|
58058
|
-
ALLOWED_ATTR: this.purifyConfig.ALLOWED_ATTR,
|
|
58059
|
-
FORBID_TAGS: this.purifyConfig.FORBID_TAGS,
|
|
58060
|
-
FORBID_ATTR: this.purifyConfig.FORBID_ATTR
|
|
58061
|
-
});
|
|
58062
|
-
return sanitized;
|
|
58071
|
+
return this.sanitizeHTMLOrThrow(html);
|
|
58063
58072
|
} catch (error) {
|
|
58064
58073
|
console.warn("HTML sanitization failed:", error);
|
|
58065
58074
|
return "";
|
|
@@ -58196,6 +58205,7 @@ var InputSanitizer = class {
|
|
|
58196
58205
|
ALLOWED_TAGS: [
|
|
58197
58206
|
"p",
|
|
58198
58207
|
"br",
|
|
58208
|
+
"hr",
|
|
58199
58209
|
"div",
|
|
58200
58210
|
"span",
|
|
58201
58211
|
"h1",
|
|
@@ -58246,6 +58256,7 @@ var InputSanitizer = class {
|
|
|
58246
58256
|
ALLOWED_TAGS: [
|
|
58247
58257
|
"p",
|
|
58248
58258
|
"br",
|
|
58259
|
+
"hr",
|
|
58249
58260
|
"div",
|
|
58250
58261
|
"span",
|
|
58251
58262
|
"h1",
|
|
@@ -58312,7 +58323,11 @@ var InputSanitizer = class {
|
|
|
58312
58323
|
return { ...this.config };
|
|
58313
58324
|
}
|
|
58314
58325
|
};
|
|
58315
|
-
var
|
|
58326
|
+
var defaultSanitizerInstance;
|
|
58327
|
+
function getDefaultSanitizer() {
|
|
58328
|
+
defaultSanitizerInstance ??= new InputSanitizer();
|
|
58329
|
+
return defaultSanitizerInstance;
|
|
58330
|
+
}
|
|
58316
58331
|
function normalizeSlackHTML(html, domParser) {
|
|
58317
58332
|
if (!html || !html.includes("indent=")) return html;
|
|
58318
58333
|
const doc = (domParser ?? new globalThis.DOMParser()).parseFromString(html, "text/html");
|
|
@@ -58343,7 +58358,7 @@ function normalizeSlackHTML(html, domParser) {
|
|
|
58343
58358
|
}
|
|
58344
58359
|
return root;
|
|
58345
58360
|
};
|
|
58346
|
-
const isListEl = (n) => n.nodeType ===
|
|
58361
|
+
const isListEl = (n) => n.nodeType === 1 && (n.nodeName === "UL" || n.nodeName === "OL");
|
|
58347
58362
|
const snapshot = Array.from(body.childNodes);
|
|
58348
58363
|
let runStart = -1;
|
|
58349
58364
|
const flushRun = (endIdx) => {
|
|
@@ -58377,7 +58392,7 @@ function sanitizeHTML(html, config) {
|
|
|
58377
58392
|
const sanitizer = new InputSanitizer(config);
|
|
58378
58393
|
return sanitizer.sanitizeHTML(html);
|
|
58379
58394
|
}
|
|
58380
|
-
return
|
|
58395
|
+
return getDefaultSanitizer().sanitizeHTML(html);
|
|
58381
58396
|
}
|
|
58382
58397
|
var PANEL_EMOJI = {
|
|
58383
58398
|
info: "\u2139\uFE0F Info:",
|
|
@@ -58463,11 +58478,11 @@ function normalizeAtlassianTables(doc) {
|
|
|
58463
58478
|
}
|
|
58464
58479
|
}
|
|
58465
58480
|
function stripUnrecognizedMacros(node) {
|
|
58466
|
-
const
|
|
58481
|
+
const ELEMENT_NODE2 = 1;
|
|
58467
58482
|
let i = 0;
|
|
58468
58483
|
while (i < node.childNodes.length) {
|
|
58469
58484
|
const child = node.childNodes[i];
|
|
58470
|
-
if (child.nodeType ===
|
|
58485
|
+
if (child.nodeType === ELEMENT_NODE2) {
|
|
58471
58486
|
const el = child;
|
|
58472
58487
|
const tagName = el.tagName.toLowerCase();
|
|
58473
58488
|
if (tagName.startsWith("ac:") || tagName.startsWith("ri:")) {
|
|
@@ -58682,11 +58697,11 @@ function processConfluenceList(list, service, depth) {
|
|
|
58682
58697
|
function processConfluenceListItem(item, service, depth) {
|
|
58683
58698
|
let content = "";
|
|
58684
58699
|
const TEXT_NODE = 3;
|
|
58685
|
-
const
|
|
58700
|
+
const ELEMENT_NODE2 = 1;
|
|
58686
58701
|
Array.from(item.childNodes).forEach((child) => {
|
|
58687
58702
|
if (child.nodeType === TEXT_NODE) {
|
|
58688
58703
|
content += child.textContent || "";
|
|
58689
|
-
} else if (child.nodeType ===
|
|
58704
|
+
} else if (child.nodeType === ELEMENT_NODE2) {
|
|
58690
58705
|
const el = child;
|
|
58691
58706
|
if (el.nodeName === "UL" || el.nodeName === "OL") {
|
|
58692
58707
|
content += "\n" + processConfluenceList(el, service, depth + 1);
|
|
@@ -58904,8 +58919,46 @@ var ConversionEngine = class {
|
|
|
58904
58919
|
rmarkdownService;
|
|
58905
58920
|
slackService;
|
|
58906
58921
|
confluenceService;
|
|
58907
|
-
|
|
58922
|
+
dom;
|
|
58923
|
+
domSanitizer;
|
|
58924
|
+
constructor(options = {}) {
|
|
58925
|
+
this.dom = options.dom;
|
|
58908
58926
|
this.initializeServices();
|
|
58927
|
+
if (this.dom) {
|
|
58928
|
+
for (const service of [
|
|
58929
|
+
this.githubService,
|
|
58930
|
+
this.commonmarkService,
|
|
58931
|
+
this.customService,
|
|
58932
|
+
this.discordService,
|
|
58933
|
+
this.redditService,
|
|
58934
|
+
this.rmarkdownService,
|
|
58935
|
+
this.slackService,
|
|
58936
|
+
this.confluenceService
|
|
58937
|
+
]) {
|
|
58938
|
+
this.parseWithInjectedDom(service, this.dom);
|
|
58939
|
+
}
|
|
58940
|
+
}
|
|
58941
|
+
}
|
|
58942
|
+
/**
|
|
58943
|
+
* Make `service.turndown(html)` parse with the injected DOM. Turndown parses
|
|
58944
|
+
* a string by wrapping it in `<x-turndown id="turndown-root">` and handing
|
|
58945
|
+
* that element to its converter; this does the same with `dom.DOMParser` and
|
|
58946
|
+
* passes the element, which Turndown accepts in place of a string. Covers
|
|
58947
|
+
* the nested `service.turndown(el.outerHTML)` calls in the list rules too.
|
|
58948
|
+
*/
|
|
58949
|
+
parseWithInjectedDom(service, dom) {
|
|
58950
|
+
const turndown = service.turndown.bind(service);
|
|
58951
|
+
service.turndown = (input) => {
|
|
58952
|
+
if (typeof input !== "string") return turndown(input);
|
|
58953
|
+
const doc = new dom.DOMParser().parseFromString(
|
|
58954
|
+
'<x-turndown id="turndown-root">' + input + "</x-turndown>",
|
|
58955
|
+
"text/html"
|
|
58956
|
+
);
|
|
58957
|
+
const root = doc.getElementById("turndown-root");
|
|
58958
|
+
root?.normalize();
|
|
58959
|
+
if (!root) throw new Error("Injected DOM did not produce the turndown root element");
|
|
58960
|
+
return turndown(root);
|
|
58961
|
+
};
|
|
58909
58962
|
}
|
|
58910
58963
|
initializeServices() {
|
|
58911
58964
|
this.githubService = new import_turndown2.default({
|
|
@@ -58962,6 +59015,37 @@ var ConversionEngine = class {
|
|
|
58962
59015
|
this.confluenceService = createConfluenceService(deps);
|
|
58963
59016
|
this.addSlideMarkerRules(this.slackService);
|
|
58964
59017
|
this.addSlideMarkerRules(this.confluenceService);
|
|
59018
|
+
[
|
|
59019
|
+
this.githubService,
|
|
59020
|
+
this.commonmarkService,
|
|
59021
|
+
this.customService,
|
|
59022
|
+
this.discordService,
|
|
59023
|
+
this.redditService,
|
|
59024
|
+
this.rmarkdownService,
|
|
59025
|
+
this.slackService,
|
|
59026
|
+
this.confluenceService
|
|
59027
|
+
].forEach((service) => this.addGoogleDocsWrapperRule(service));
|
|
59028
|
+
}
|
|
59029
|
+
/**
|
|
59030
|
+
* Google Docs wraps every copied selection in
|
|
59031
|
+
* <b style="font-weight:normal" id="docs-internal-guid-...">. Treating that
|
|
59032
|
+
* as bold puts a stray pair of bold markers around the whole document, so a
|
|
59033
|
+
* <b>/<strong> whose inline style explicitly sets a non-bold weight is
|
|
59034
|
+
* rendered as its plain content.
|
|
59035
|
+
*/
|
|
59036
|
+
addGoogleDocsWrapperRule(service) {
|
|
59037
|
+
service.addRule("googleDocsNonBoldWrapper", {
|
|
59038
|
+
filter: (node) => {
|
|
59039
|
+
if (node.nodeName !== "B" && node.nodeName !== "STRONG") return false;
|
|
59040
|
+
const style = (node.getAttribute("style") || "").toLowerCase();
|
|
59041
|
+
const matches = [...style.matchAll(/font-weight\s*:\s*([a-z0-9]+)/g)];
|
|
59042
|
+
if (matches.length === 0) return false;
|
|
59043
|
+
const weight = matches[matches.length - 1][1];
|
|
59044
|
+
if (weight === "normal" || weight === "lighter") return true;
|
|
59045
|
+
return /^\d+$/.test(weight) && parseInt(weight, 10) < 600;
|
|
59046
|
+
},
|
|
59047
|
+
replacement: (content) => content
|
|
59048
|
+
});
|
|
58965
59049
|
}
|
|
58966
59050
|
/**
|
|
58967
59051
|
* Create Discord-optimized Turndown service
|
|
@@ -59017,8 +59101,8 @@ ${plainText}
|
|
|
59017
59101
|
return node.nodeName === "INPUT" && node.type === "checkbox";
|
|
59018
59102
|
},
|
|
59019
59103
|
replacement: (_content, node) => {
|
|
59020
|
-
const checked = node.checked;
|
|
59021
|
-
return checked ? "\u2611
|
|
59104
|
+
const checked = node.checked || node.hasAttribute("checked");
|
|
59105
|
+
return (checked ? "\u2611" : "\u2610") + this.checkboxSpacer(node);
|
|
59022
59106
|
}
|
|
59023
59107
|
});
|
|
59024
59108
|
return service;
|
|
@@ -59046,9 +59130,9 @@ ${plainText}
|
|
|
59046
59130
|
* Converts Unicode checkboxes to [x] and [ ]
|
|
59047
59131
|
*/
|
|
59048
59132
|
normalizeGitHubCheckboxes(markdown) {
|
|
59049
|
-
let result = markdown;
|
|
59050
|
-
result = result.replace(/^([
|
|
59051
|
-
result = result.replace(/^([
|
|
59133
|
+
let result = markdown.replace(/^([ \t]*(?:[-*+]|\d+[.)])[ \t]+)\\\[([ xX])\\\]/gm, "$1[$2]");
|
|
59134
|
+
result = result.replace(/^([ \t]*(?:[-*+]|\d+[.)])[ \t]+)[☑✓✔■⬛]/gm, "$1[x]");
|
|
59135
|
+
result = result.replace(/^([ \t]*(?:[-*+]|\d+[.)])[ \t]+)[☐✗✘□⬜]/gm, "$1[ ]");
|
|
59052
59136
|
return result;
|
|
59053
59137
|
}
|
|
59054
59138
|
/**
|
|
@@ -59056,10 +59140,10 @@ ${plainText}
|
|
|
59056
59140
|
* Converts [x], [ ], and other checkbox patterns to emoji
|
|
59057
59141
|
*/
|
|
59058
59142
|
normalizeDiscordCheckboxes(markdown) {
|
|
59059
|
-
let result = markdown.replace(/^([
|
|
59060
|
-
result = result.replace(/^([
|
|
59061
|
-
result = result.replace(/^([
|
|
59062
|
-
result = result.replace(/^([
|
|
59143
|
+
let result = markdown.replace(/^([ \t]*(?:[-*+]|\d+[.)])[ \t]+)\\?\[x\\?\]/gmi, "$1\u2611");
|
|
59144
|
+
result = result.replace(/^([ \t]*(?:[-*+]|\d+[.)])[ \t]+)[✓✔■⬛]/gm, "$1\u2611");
|
|
59145
|
+
result = result.replace(/^([ \t]*(?:[-*+]|\d+[.)])[ \t]+)\\?\[\s?\\?\]/gm, "$1\u2610");
|
|
59146
|
+
result = result.replace(/^([ \t]*(?:[-*+]|\d+[.)])[ \t]+)[✗✘□⬜]/gm, "$1\u2610");
|
|
59063
59147
|
return result;
|
|
59064
59148
|
}
|
|
59065
59149
|
/**
|
|
@@ -59298,8 +59382,9 @@ ${plainText}
|
|
|
59298
59382
|
return lines.join("\n");
|
|
59299
59383
|
}
|
|
59300
59384
|
flattenTables(html) {
|
|
59301
|
-
|
|
59302
|
-
|
|
59385
|
+
const Parser = this.dom?.DOMParser ?? (typeof DOMParser === "undefined" ? void 0 : DOMParser);
|
|
59386
|
+
if (!Parser) return html;
|
|
59387
|
+
const parser = new Parser();
|
|
59303
59388
|
const doc = parser.parseFromString(`<div>${html}</div>`, "text/html");
|
|
59304
59389
|
Array.from(doc.querySelectorAll("table")).forEach((table) => {
|
|
59305
59390
|
const replacement = doc.createElement("div");
|
|
@@ -59459,10 +59544,11 @@ ${plainText}
|
|
|
59459
59544
|
});
|
|
59460
59545
|
}
|
|
59461
59546
|
renderTableCell(cell) {
|
|
59547
|
+
const ELEMENT_NODE2 = 1;
|
|
59462
59548
|
const blocks = [];
|
|
59463
59549
|
let inlineBuffer = "";
|
|
59464
59550
|
cell.childNodes.forEach((child) => {
|
|
59465
|
-
if (child.nodeType ===
|
|
59551
|
+
if (child.nodeType === ELEMENT_NODE2 && this.isTableCellBlock(child)) {
|
|
59466
59552
|
if (inlineBuffer.trim()) {
|
|
59467
59553
|
blocks.push(inlineBuffer.trim());
|
|
59468
59554
|
inlineBuffer = "";
|
|
@@ -59486,8 +59572,10 @@ ${plainText}
|
|
|
59486
59572
|
return this.renderInlineNode(element).trim();
|
|
59487
59573
|
}
|
|
59488
59574
|
renderInlineNode(node) {
|
|
59489
|
-
|
|
59490
|
-
|
|
59575
|
+
const TEXT_NODE = 3;
|
|
59576
|
+
const ELEMENT_NODE2 = 1;
|
|
59577
|
+
if (node.nodeType === TEXT_NODE) return node.textContent || "";
|
|
59578
|
+
if (node.nodeType !== ELEMENT_NODE2) return "";
|
|
59491
59579
|
const element = node;
|
|
59492
59580
|
const content = Array.from(element.childNodes).map((child) => this.renderInlineNode(child)).join("");
|
|
59493
59581
|
const trimmed = content.trim();
|
|
@@ -59525,6 +59613,11 @@ ${plainText}
|
|
|
59525
59613
|
escapeTableCell(content) {
|
|
59526
59614
|
return content.replace(/\|/g, "\\|").replace(/\s*<br>\s*/g, "<br>").trim();
|
|
59527
59615
|
}
|
|
59616
|
+
/** A space after a checkbox marker unless the label text already starts with one. */
|
|
59617
|
+
checkboxSpacer(node) {
|
|
59618
|
+
const next = node.nextSibling;
|
|
59619
|
+
return next && /^\s/.test(next.textContent || "") ? "" : " ";
|
|
59620
|
+
}
|
|
59528
59621
|
addTaskListRules(service) {
|
|
59529
59622
|
service.addRule("gfmTaskListCheckbox", {
|
|
59530
59623
|
filter: (node) => {
|
|
@@ -59532,7 +59625,7 @@ ${plainText}
|
|
|
59532
59625
|
},
|
|
59533
59626
|
replacement: (_content, node) => {
|
|
59534
59627
|
const checked = node.checked || node.hasAttribute("checked");
|
|
59535
|
-
return checked ? "[x]
|
|
59628
|
+
return (checked ? "[x]" : "[ ]") + this.checkboxSpacer(node);
|
|
59536
59629
|
}
|
|
59537
59630
|
});
|
|
59538
59631
|
}
|
|
@@ -59598,60 +59691,78 @@ ${plainText}
|
|
|
59598
59691
|
service.addRule("enhancedList", {
|
|
59599
59692
|
filter: ["ul", "ol"],
|
|
59600
59693
|
replacement: (content, node) => {
|
|
59601
|
-
const listType = node?.nodeName.toLowerCase();
|
|
59602
59694
|
const items = Array.from(node.children).filter(
|
|
59603
59695
|
(child) => child.nodeName.toLowerCase() === "li"
|
|
59604
59696
|
);
|
|
59605
59697
|
if (items.length === 0) return content;
|
|
59606
|
-
|
|
59607
|
-
const isOrdered = listType === "ol";
|
|
59608
|
-
const marker = isOrdered ? "1." : service.options.bulletListMarker || "-";
|
|
59609
|
-
items.forEach((item, index) => {
|
|
59610
|
-
const itemContent = this.processListItem(item, service);
|
|
59611
|
-
const actualMarker = isOrdered ? `${index + 1}.` : marker;
|
|
59612
|
-
markdown += `${actualMarker} ${itemContent}
|
|
59613
|
-
`;
|
|
59614
|
-
});
|
|
59615
|
-
return markdown + "\n";
|
|
59616
|
-
}
|
|
59617
|
-
});
|
|
59618
|
-
}
|
|
59619
|
-
processListItem(item, service, depth = 0) {
|
|
59620
|
-
let content = "";
|
|
59621
|
-
const TEXT_NODE = 3;
|
|
59622
|
-
const ELEMENT_NODE = 1;
|
|
59623
|
-
Array.from(item.childNodes).forEach((child) => {
|
|
59624
|
-
if (child.nodeType === TEXT_NODE) {
|
|
59625
|
-
content += child.textContent || "";
|
|
59626
|
-
} else if (child.nodeType === ELEMENT_NODE) {
|
|
59627
|
-
const element = child;
|
|
59628
|
-
if (element.nodeName.toLowerCase() === "ul" || element.nodeName.toLowerCase() === "ol") {
|
|
59629
|
-
const nestedContent = this.processNestedList(element, service, depth + 1);
|
|
59630
|
-
content += "\n" + nestedContent;
|
|
59631
|
-
} else {
|
|
59632
|
-
content += service.turndown(element.outerHTML);
|
|
59633
|
-
}
|
|
59698
|
+
return "\n" + this.renderList(node, service) + "\n";
|
|
59634
59699
|
}
|
|
59635
59700
|
});
|
|
59636
|
-
return content.trim();
|
|
59637
59701
|
}
|
|
59638
|
-
|
|
59702
|
+
/**
|
|
59703
|
+
* Render a list with markers at column 0. Continuation lines of each item
|
|
59704
|
+
* (extra paragraphs, nested lists) are indented to the item's content
|
|
59705
|
+
* column (marker width + 1), which is what CommonMark/GFM require for them
|
|
59706
|
+
* to stay inside the item: 2 spaces under "- ", 3 under "1. ", 4 under "10. ".
|
|
59707
|
+
*/
|
|
59708
|
+
renderList(list, service) {
|
|
59639
59709
|
const items = Array.from(list.children).filter(
|
|
59640
59710
|
(child) => child.nodeName.toLowerCase() === "li"
|
|
59641
59711
|
);
|
|
59642
|
-
if (items.length === 0) return "";
|
|
59643
|
-
let markdown = "";
|
|
59644
59712
|
const isOrdered = list.nodeName.toLowerCase() === "ol";
|
|
59645
|
-
const
|
|
59646
|
-
|
|
59713
|
+
const bullet = service.options.bulletListMarker || "-";
|
|
59714
|
+
let markdown = "";
|
|
59647
59715
|
items.forEach((item, index) => {
|
|
59648
|
-
const
|
|
59649
|
-
const
|
|
59650
|
-
|
|
59716
|
+
const marker = isOrdered ? `${index + 1}.` : bullet;
|
|
59717
|
+
const indent = " ".repeat(marker.length + 1);
|
|
59718
|
+
const body = this.processListItem(item, service);
|
|
59719
|
+
const lines = body.split("\n");
|
|
59720
|
+
const indented = lines.map((line, i) => i === 0 || line === "" ? line : indent + line).join("\n");
|
|
59721
|
+
markdown += `${marker} ${indented}
|
|
59651
59722
|
`;
|
|
59652
59723
|
});
|
|
59653
59724
|
return markdown;
|
|
59654
59725
|
}
|
|
59726
|
+
/**
|
|
59727
|
+
* Render one list item's content relative to its own content column.
|
|
59728
|
+
* Inline runs and block children are converted together, so whitespace
|
|
59729
|
+
* between sibling spans survives (Google Docs emits one span per run) and
|
|
59730
|
+
* multiple paragraphs stay separated.
|
|
59731
|
+
*/
|
|
59732
|
+
processListItem(item, service) {
|
|
59733
|
+
const parts = [];
|
|
59734
|
+
const ELEMENT_NODE2 = 1;
|
|
59735
|
+
const doc = item.ownerDocument;
|
|
59736
|
+
let buffer = doc.createElement("div");
|
|
59737
|
+
const flush = () => {
|
|
59738
|
+
if (buffer.childNodes.length > 0) {
|
|
59739
|
+
const md = service.turndown(buffer).trim();
|
|
59740
|
+
if (md) parts.push(md);
|
|
59741
|
+
}
|
|
59742
|
+
buffer = doc.createElement("div");
|
|
59743
|
+
};
|
|
59744
|
+
Array.from(item.childNodes).forEach((child) => {
|
|
59745
|
+
const name = child.nodeType === ELEMENT_NODE2 ? child.nodeName.toLowerCase() : "";
|
|
59746
|
+
if (name === "ul" || name === "ol") {
|
|
59747
|
+
flush();
|
|
59748
|
+
const nested = this.renderList(child, service).replace(/\n+$/, "");
|
|
59749
|
+
if (nested) parts.push(nested);
|
|
59750
|
+
} else {
|
|
59751
|
+
buffer.appendChild(child.cloneNode(true));
|
|
59752
|
+
}
|
|
59753
|
+
});
|
|
59754
|
+
flush();
|
|
59755
|
+
let content = "";
|
|
59756
|
+
parts.forEach((part, i) => {
|
|
59757
|
+
if (i === 0) {
|
|
59758
|
+
content = part;
|
|
59759
|
+
return;
|
|
59760
|
+
}
|
|
59761
|
+
const isList = /^(?:[-*+]|\d+\.) /.test(part);
|
|
59762
|
+
content += (isList ? "\n" : "\n\n") + part;
|
|
59763
|
+
});
|
|
59764
|
+
return content;
|
|
59765
|
+
}
|
|
59655
59766
|
addSlideMarkerRules(service) {
|
|
59656
59767
|
service.addRule("pptxSlideMarker", {
|
|
59657
59768
|
filter: (node) => node.nodeName === "DIV" && node.hasAttribute("data-slide-marker"),
|
|
@@ -59764,6 +59875,10 @@ ${plainText}
|
|
|
59764
59875
|
};
|
|
59765
59876
|
}
|
|
59766
59877
|
sanitize(html) {
|
|
59878
|
+
if (this.dom) {
|
|
59879
|
+
this.domSanitizer ??= new InputSanitizer({ level: "moderate" }, this.dom);
|
|
59880
|
+
return this.domSanitizer.sanitizeHTMLOrThrow(html);
|
|
59881
|
+
}
|
|
59767
59882
|
return sanitizeHTML(html, {
|
|
59768
59883
|
level: "moderate"
|
|
59769
59884
|
// Use moderate level for conversion
|
|
@@ -63205,7 +63320,7 @@ var PptxAdapter = class {
|
|
|
63205
63320
|
};
|
|
63206
63321
|
var pptxAdapter = new PptxAdapter();
|
|
63207
63322
|
|
|
63208
|
-
// ../../src/shared/readability-
|
|
63323
|
+
// ../../src/shared/readability-core.ts
|
|
63209
63324
|
var import_readability = __toESM(require_readability(), 1);
|
|
63210
63325
|
var LinkedomProvider = class {
|
|
63211
63326
|
createDocument(html) {
|
|
@@ -63503,6 +63618,118 @@ function buildCachedProvider(config, lastValidated) {
|
|
|
63503
63618
|
return new CachedEntitlementProvider(cachedState);
|
|
63504
63619
|
}
|
|
63505
63620
|
|
|
63621
|
+
// ../../src/shared/linkedom-sanitizer.ts
|
|
63622
|
+
var FORBID_CONTENTS = /* @__PURE__ */ new Set([
|
|
63623
|
+
"annotation-xml",
|
|
63624
|
+
"audio",
|
|
63625
|
+
"colgroup",
|
|
63626
|
+
"desc",
|
|
63627
|
+
"foreignobject",
|
|
63628
|
+
"head",
|
|
63629
|
+
"iframe",
|
|
63630
|
+
"math",
|
|
63631
|
+
"mi",
|
|
63632
|
+
"mn",
|
|
63633
|
+
"mo",
|
|
63634
|
+
"ms",
|
|
63635
|
+
"mtext",
|
|
63636
|
+
"noembed",
|
|
63637
|
+
"noframes",
|
|
63638
|
+
"noscript",
|
|
63639
|
+
"plaintext",
|
|
63640
|
+
"script",
|
|
63641
|
+
"selectedcontent",
|
|
63642
|
+
"style",
|
|
63643
|
+
"svg",
|
|
63644
|
+
"template",
|
|
63645
|
+
"thead",
|
|
63646
|
+
"title",
|
|
63647
|
+
"video",
|
|
63648
|
+
"xmp"
|
|
63649
|
+
]);
|
|
63650
|
+
var DATA_URI_TAGS = /* @__PURE__ */ new Set(["audio", "video", "img", "source", "image", "track"]);
|
|
63651
|
+
var URI_SAFE_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
63652
|
+
"alt",
|
|
63653
|
+
"class",
|
|
63654
|
+
"for",
|
|
63655
|
+
"id",
|
|
63656
|
+
"label",
|
|
63657
|
+
"name",
|
|
63658
|
+
"pattern",
|
|
63659
|
+
"placeholder",
|
|
63660
|
+
"role",
|
|
63661
|
+
"summary",
|
|
63662
|
+
"title",
|
|
63663
|
+
"value",
|
|
63664
|
+
"style",
|
|
63665
|
+
"xmlns"
|
|
63666
|
+
]);
|
|
63667
|
+
var IS_ALLOWED_URI = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
|
|
63668
|
+
var ATTR_WHITESPACE = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g;
|
|
63669
|
+
var ELEMENT_NODE = 1;
|
|
63670
|
+
var COMMENT_NODE = 8;
|
|
63671
|
+
function toSet(list) {
|
|
63672
|
+
return new Set((list ?? []).map((s) => s.toLowerCase()));
|
|
63673
|
+
}
|
|
63674
|
+
function attrAllowed(name, allowed, wildcards) {
|
|
63675
|
+
return allowed.has(name) || wildcards.some((prefix) => name.startsWith(prefix));
|
|
63676
|
+
}
|
|
63677
|
+
function isSafeValue(tag, name, value) {
|
|
63678
|
+
if (URI_SAFE_ATTRIBUTES.has(name) || !value) return true;
|
|
63679
|
+
if (IS_ALLOWED_URI.test(value.replace(ATTR_WHITESPACE, ""))) return true;
|
|
63680
|
+
return (name === "src" || name === "href" || name === "xlink:href") && value.startsWith("data:") && DATA_URI_TAGS.has(tag);
|
|
63681
|
+
}
|
|
63682
|
+
function sanitizeWithLinkedom(html, config, parse) {
|
|
63683
|
+
if (!html) return "";
|
|
63684
|
+
const allowedTags = toSet(config.ALLOWED_TAGS);
|
|
63685
|
+
const forbidTags = toSet(config.FORBID_TAGS);
|
|
63686
|
+
const allowedAttrList = (config.ALLOWED_ATTR ?? []).map((s) => s.toLowerCase());
|
|
63687
|
+
const allowedAttrs = new Set(allowedAttrList.filter((a) => !a.endsWith("*")));
|
|
63688
|
+
const attrWildcards = allowedAttrList.filter((a) => a.endsWith("*")).map((a) => a.slice(0, -1));
|
|
63689
|
+
const forbidAttrs = toSet(config.FORBID_ATTR);
|
|
63690
|
+
const doc = parse(`<!DOCTYPE html><html><head></head><body>${html}</body></html>`);
|
|
63691
|
+
const body = doc.body;
|
|
63692
|
+
if (!body) return "";
|
|
63693
|
+
const toUnwrap = [];
|
|
63694
|
+
const stack = [body];
|
|
63695
|
+
while (stack.length > 0) {
|
|
63696
|
+
const parent = stack.pop();
|
|
63697
|
+
for (const child of Array.from(parent.childNodes)) {
|
|
63698
|
+
if (child.nodeType === COMMENT_NODE) {
|
|
63699
|
+
parent.removeChild(child);
|
|
63700
|
+
continue;
|
|
63701
|
+
}
|
|
63702
|
+
if (child.nodeType !== ELEMENT_NODE) continue;
|
|
63703
|
+
const el = child;
|
|
63704
|
+
const tag = el.nodeName.toLowerCase();
|
|
63705
|
+
if (!allowedTags.has(tag) || forbidTags.has(tag)) {
|
|
63706
|
+
if (FORBID_CONTENTS.has(tag)) {
|
|
63707
|
+
parent.removeChild(el);
|
|
63708
|
+
} else {
|
|
63709
|
+
toUnwrap.push(el);
|
|
63710
|
+
stack.push(el);
|
|
63711
|
+
}
|
|
63712
|
+
continue;
|
|
63713
|
+
}
|
|
63714
|
+
for (const attr of Array.from(el.attributes)) {
|
|
63715
|
+
const name = attr.name.toLowerCase();
|
|
63716
|
+
if (name.startsWith("on") || forbidAttrs.has(name) || !attrAllowed(name, allowedAttrs, attrWildcards) || !isSafeValue(tag, name, attr.value)) {
|
|
63717
|
+
el.removeAttribute(attr.name);
|
|
63718
|
+
}
|
|
63719
|
+
}
|
|
63720
|
+
stack.push(el);
|
|
63721
|
+
}
|
|
63722
|
+
}
|
|
63723
|
+
for (let i = toUnwrap.length - 1; i >= 0; i--) {
|
|
63724
|
+
const el = toUnwrap[i];
|
|
63725
|
+
const parent = el.parentNode;
|
|
63726
|
+
if (!parent) continue;
|
|
63727
|
+
while (el.firstChild) parent.insertBefore(el.firstChild, el);
|
|
63728
|
+
parent.removeChild(el);
|
|
63729
|
+
}
|
|
63730
|
+
return body.innerHTML;
|
|
63731
|
+
}
|
|
63732
|
+
|
|
63506
63733
|
// ../../src/shared/token-estimator.ts
|
|
63507
63734
|
var CJK_REGEX3 = /[\u4e00-\u9fff\u3400-\u4dbf\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/g;
|
|
63508
63735
|
var MAX_INPUT_LENGTH = 1e6;
|
|
@@ -64052,6 +64279,18 @@ async function binaryToMarkdown(buffer, type, format) {
|
|
|
64052
64279
|
}
|
|
64053
64280
|
}
|
|
64054
64281
|
}
|
|
64282
|
+
function linkedomDomEnvironment() {
|
|
64283
|
+
const parseHTML2 = globalThis.__FF_parseHTML;
|
|
64284
|
+
if (!parseHTML2) throw new Error("The CLI shim must be loaded before converting a URL");
|
|
64285
|
+
const parseDocument = (html) => parseHTML2(html).document;
|
|
64286
|
+
const { window: window3 } = parseHTML2("<!DOCTYPE html><html><head></head><body></body></html>");
|
|
64287
|
+
return {
|
|
64288
|
+
DOMParser: window3.DOMParser,
|
|
64289
|
+
DOMPurify: {
|
|
64290
|
+
sanitize: (html, config) => sanitizeWithLinkedom(html, config ?? {}, parseDocument)
|
|
64291
|
+
}
|
|
64292
|
+
};
|
|
64293
|
+
}
|
|
64055
64294
|
var DEFAULT_PROXY_URL = "https://formatferry.vibingfun.com";
|
|
64056
64295
|
async function urlToMarkdown(url, apiKey, format, proxyBaseUrl = process.env.FORMATFERRY_PROXY_URL ?? DEFAULT_PROXY_URL) {
|
|
64057
64296
|
const extractEndpoint = `${proxyBaseUrl}/v1/extract`;
|
|
@@ -64063,7 +64302,9 @@ async function urlToMarkdown(url, apiKey, format, proxyBaseUrl = process.env.FOR
|
|
|
64063
64302
|
"Content-Type": "application/json",
|
|
64064
64303
|
"X-API-Key": apiKey
|
|
64065
64304
|
},
|
|
64066
|
-
|
|
64305
|
+
// Readability and the chosen flavour run locally, so ask for the page's
|
|
64306
|
+
// HTML (the API's default is Markdown).
|
|
64307
|
+
body: JSON.stringify({ url, format: "html" })
|
|
64067
64308
|
});
|
|
64068
64309
|
} catch (err) {
|
|
64069
64310
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -64074,18 +64315,19 @@ async function urlToMarkdown(url, apiKey, format, proxyBaseUrl = process.env.FOR
|
|
|
64074
64315
|
if (!response.ok) {
|
|
64075
64316
|
let errorMessage = `Proxy returned ${response.status}`;
|
|
64076
64317
|
try {
|
|
64077
|
-
const
|
|
64078
|
-
errorMessage =
|
|
64318
|
+
const body2 = await response.json();
|
|
64319
|
+
errorMessage = body2.error ?? body2.message ?? errorMessage;
|
|
64079
64320
|
} catch {
|
|
64080
64321
|
}
|
|
64081
64322
|
process.stderr.write(`Error: ${errorMessage}
|
|
64082
64323
|
`);
|
|
64083
64324
|
process.exit(1);
|
|
64084
64325
|
}
|
|
64085
|
-
const
|
|
64326
|
+
const body = await response.json();
|
|
64327
|
+
const html = body.content ?? body.html ?? "";
|
|
64086
64328
|
const domProvider = new LinkedomProvider();
|
|
64087
64329
|
const article = extractArticle(html, domProvider);
|
|
64088
|
-
const engine = new ConversionEngine();
|
|
64330
|
+
const engine = new ConversionEngine({ dom: linkedomDomEnvironment() });
|
|
64089
64331
|
const result = await engine.convert(article.content, {
|
|
64090
64332
|
format,
|
|
64091
64333
|
preserveTables: true,
|
|
@@ -64589,8 +64831,8 @@ import { readFileSync as readFileSync5 } from "fs";
|
|
|
64589
64831
|
import { resolve, dirname as dirname3 } from "path";
|
|
64590
64832
|
import { fileURLToPath } from "url";
|
|
64591
64833
|
var getVersion = () => {
|
|
64592
|
-
if ("1.0.
|
|
64593
|
-
return "1.0.
|
|
64834
|
+
if ("1.0.35") {
|
|
64835
|
+
return "1.0.35";
|
|
64594
64836
|
}
|
|
64595
64837
|
try {
|
|
64596
64838
|
const __dirname2 = dirname3(fileURLToPath(import.meta.url));
|