@aiquants/markdown-explorer 0.1.0 → 0.2.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/CHANGELOG.md +30 -1
- package/README.md +31 -13
- package/dist/{ExplorerSplit-BESGFcu6.cjs → ExplorerSplit-D2plJRRe.cjs} +1 -1
- package/dist/{ExplorerSplit-DwEFmvQM.js → ExplorerSplit-DB37U7Kh.js} +3 -3
- package/dist/MultiLayout-DCPDu1-l.js +909 -0
- package/dist/MultiLayout-UyWxs6Xy.cjs +1 -0
- package/dist/TreeLayout-BoyFelK2.js +22 -0
- package/dist/TreeLayout-CLWbWjOc.cjs +1 -0
- package/dist/core/config.d.cts +6 -0
- package/dist/core/config.d.ts +6 -0
- package/dist/core/labels.d.cts +6 -1
- package/dist/core/labels.d.ts +6 -1
- package/dist/{index-BgkZ9ATV.js → index-BfuAu2GV.js} +947 -901
- package/dist/index-Cx3-jSna.cjs +3 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +2 -2
- package/dist/location-Oo21lTyV.cjs +1 -0
- package/dist/{location-Cb2Ak55B.js → location-fVl2R1ee.js} +154 -141
- package/dist/sanitizeWorker.cjs +1 -1
- package/dist/sanitizeWorker.js +196 -206
- package/dist/server.cjs +1 -1
- package/dist/server.js +1 -1
- package/dist/styles/markdown-explorer.css +1 -1
- package/docs/behavior/dom-hooks.md +4 -4
- package/docs/behavior/layout.md +21 -9
- package/docs/behavior/localization.md +4 -3
- package/docs/behavior/security.md +7 -3
- package/docs/behavior/url-contract.md +8 -2
- package/package.json +5 -5
- package/dist/MultiLayout-DxPiARsv.js +0 -896
- package/dist/MultiLayout-r_qx1Mfz.cjs +0 -1
- package/dist/TreeLayout-9-20bbSM.cjs +0 -1
- package/dist/TreeLayout-CW7lgV_e.js +0 -19
- package/dist/index-y9tVvDW7.cjs +0 -3
- package/dist/location-DWHQYntR.cjs +0 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NO_EMBEDS as Y, isEmbedProviderId as Q, EMBED_PROVIDER_IDS as ee, isLinkCardEndpoint as te } from "@aiquants/markdown/embeds";
|
|
2
|
+
import { CONTENT_ALIGNS as b, DEFAULT_MARKDOWN_STYLES as re } from "@aiquants/markdown/viewer-settings";
|
|
2
3
|
import { i as k } from "./dataRoute-Bkfwfp1R.js";
|
|
3
4
|
const F = (e) => {
|
|
4
5
|
if (e === null || typeof e != "object") return !1;
|
|
5
6
|
const t = Object.getPrototypeOf(e);
|
|
6
7
|
return t === Object.prototype || t === null;
|
|
7
|
-
},
|
|
8
|
+
}, v = new Intl.Collator("en", { numeric: !0, sensitivity: "variant" }), P = Object.freeze({
|
|
8
9
|
sortMode: "native",
|
|
9
10
|
directoriesFirst: !1,
|
|
10
11
|
selectionMode: "single",
|
|
@@ -16,7 +17,7 @@ const F = (e) => {
|
|
|
16
17
|
expandIcons: !0,
|
|
17
18
|
directoryIcons: !0,
|
|
18
19
|
fileIcons: !0
|
|
19
|
-
}),
|
|
20
|
+
}), ne = [!0, !1], oe = (e, t) => t ? e.settingOn : e.settingOff, g = (e, t) => ({ key: e, labelKey: t, values: ne, formatValue: oe, requiresItemSelection: !1 }), p = Object.freeze([
|
|
20
21
|
{
|
|
21
22
|
key: "sortMode",
|
|
22
23
|
labelKey: "settingSortMode",
|
|
@@ -24,7 +25,7 @@ const F = (e) => {
|
|
|
24
25
|
formatValue: (e, t) => t === "native" ? e.sortNative : t === "asc" ? e.sortAscending : e.sortDescending,
|
|
25
26
|
requiresItemSelection: !1
|
|
26
27
|
},
|
|
27
|
-
|
|
28
|
+
g("directoriesFirst", "settingDirectoriesFirst"),
|
|
28
29
|
{
|
|
29
30
|
key: "selectionMode",
|
|
30
31
|
labelKey: "settingSelectionMode",
|
|
@@ -46,91 +47,91 @@ const F = (e) => {
|
|
|
46
47
|
formatValue: (e, t) => e.expandIconSizeValue(t),
|
|
47
48
|
requiresItemSelection: !1
|
|
48
49
|
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
]),
|
|
50
|
+
g("alwaysExpanded", "settingAlwaysExpanded"),
|
|
51
|
+
g("removeRootIndent", "settingRemoveRootIndent"),
|
|
52
|
+
g("lines", "settingTreeLines"),
|
|
53
|
+
g("expandIcons", "settingExpandIcons"),
|
|
54
|
+
g("directoryIcons", "settingDirectoryIcons"),
|
|
55
|
+
g("fileIcons", "settingFileIcons")
|
|
56
|
+
]), Ge = (e) => e ? p : p.filter((t) => !t.requiresItemSelection), V = (e) => {
|
|
56
57
|
const t = p.find((r) => r.key === e);
|
|
57
58
|
if (t === void 0) throw new RangeError(`[markdown-explorer] no tree setting descriptor for ${e}`);
|
|
58
59
|
return t;
|
|
59
|
-
},
|
|
60
|
+
}, Je = (e, t) => {
|
|
60
61
|
const r = V(t).values, n = r[(r.indexOf(e[t]) + 1) % r.length];
|
|
61
62
|
return { ...e, [t]: n };
|
|
62
|
-
},
|
|
63
|
-
if (e === null || typeof e != "object" || Array.isArray(e)) return
|
|
63
|
+
}, Xe = (e, t, r) => V(r).formatValue(e, t[r]), U = 2, M = Object.freeze({}), $ = (e, t) => Object.freeze(Object.fromEntries(p.filter((r) => t(r, e[r.key])).map((r) => [r.key, e[r.key]]))), We = (e) => {
|
|
64
|
+
if (e === null || typeof e != "object" || Array.isArray(e)) return M;
|
|
64
65
|
const t = e;
|
|
65
|
-
return t.version !== U || t.settings === null || typeof t.settings != "object" || Array.isArray(t.settings) ?
|
|
66
|
-
},
|
|
66
|
+
return t.version !== U || t.settings === null || typeof t.settings != "object" || Array.isArray(t.settings) ? M : $(t.settings, (r, n) => r.values.includes(n));
|
|
67
|
+
}, He = (e, t) => {
|
|
67
68
|
const r = $(t, (n, o) => o !== void 0 && o !== e[n.key]);
|
|
68
69
|
return Object.keys(r).length === 0 ? e : Object.freeze({ ...e, ...r });
|
|
69
|
-
},
|
|
70
|
+
}, qe = (e, t, r, n) => $({ ...e, [t]: r }, (o, s) => s !== void 0 && !(o.key === t && s === n[t])), Be = (e) => JSON.stringify({ version: U, settings: e }), Ke = (e) => {
|
|
70
71
|
if (e.sortMode === "native" && !e.directoriesFirst) return;
|
|
71
72
|
const t = e.sortMode === "desc" ? -1 : 1;
|
|
72
73
|
return (r, n) => {
|
|
73
74
|
if (e.directoriesFirst && r.type !== n.type) return r.type === "directory" ? -1 : 1;
|
|
74
75
|
if (e.sortMode === "native") return 0;
|
|
75
|
-
const o =
|
|
76
|
-
return t * (o !== 0 ? o :
|
|
76
|
+
const o = v.compare(r.name, n.name);
|
|
77
|
+
return t * (o !== 0 ? o : v.compare(r.path, n.path));
|
|
77
78
|
};
|
|
78
|
-
}, w = (1 + Math.sqrt(5)) / 2,
|
|
79
|
+
}, w = (1 + Math.sqrt(5)) / 2, Ze = 100 / w ** 3, Ye = 100 / w ** 4, G = 100 / w ** 2, se = 13, Qe = 16, et = Object.freeze({ gripThickness: 5, gripLength: 34, barThickness: 2, barLength: 21 }), ie = Object.freeze([89, 144, 233, 377]), tt = 34, rt = 44, nt = 24, ot = 1 / w, st = 1 / w ** 3, it = "40ch", ae = (e) => {
|
|
79
80
|
if (!Number.isFinite(e) || e <= 0)
|
|
80
81
|
throw new RangeError(`[markdown-explorer] rootFontPixels must be a finite number > 0; got ${String(e)}`);
|
|
81
|
-
},
|
|
82
|
+
}, ce = (e) => (ae(e), se * e), at = (e) => ce(e) * w ** 2, ct = 233, lt = ie[0], L = (e, t) => {
|
|
82
83
|
if (!Number.isFinite(t) || t < 0)
|
|
83
84
|
throw new RangeError(`[markdown-explorer] ${e} must be a finite number >= 0; got ${String(t)}`);
|
|
84
|
-
},
|
|
85
|
-
if (
|
|
85
|
+
}, le = ({ trackInlineSize: e, gap: t, minColumnInlineSize: r, logicalColumns: n }) => {
|
|
86
|
+
if (L("trackInlineSize", e), L("gap", t), !Number.isFinite(r) || r <= 0)
|
|
86
87
|
throw new RangeError(`[markdown-explorer] minColumnInlineSize must be a finite number > 0; got ${String(r)}`);
|
|
87
88
|
if (!Number.isInteger(n) || n < 1)
|
|
88
89
|
throw new RangeError(`[markdown-explorer] logicalColumns must be a positive integer; got ${String(n)}`);
|
|
89
90
|
const o = Math.floor((e + t) / (r + t));
|
|
90
91
|
return Math.min(n, Math.max(1, o));
|
|
91
|
-
},
|
|
92
|
+
}, dt = (e, t) => {
|
|
92
93
|
const { trackInlineSize: r, gap: n, minColumnInlineSize: o, logicalColumns: s } = t;
|
|
93
94
|
if (!([r, n, o].every(Number.isFinite) && r > 0 && n >= 0 && o > 0)) return e;
|
|
94
|
-
const i =
|
|
95
|
+
const i = le(t);
|
|
95
96
|
if (e === null || i === e) return i;
|
|
96
97
|
const l = Math.min(s, Math.max(1, e));
|
|
97
98
|
if (i > l) {
|
|
98
|
-
const
|
|
99
|
-
return r >=
|
|
99
|
+
const _ = (l + 1) * o + l * n + n / w;
|
|
100
|
+
return r >= _ ? i : l;
|
|
100
101
|
}
|
|
101
102
|
return r >= l * o + (l - 1) * n ? l : i;
|
|
102
|
-
},
|
|
103
|
+
}, mt = (e, t) => {
|
|
103
104
|
if (!(Number.isInteger(e) && Number.isInteger(t)) || t < 1 || t > e)
|
|
104
105
|
throw new RangeError(`[markdown-explorer] visible columns must be an integer in 1..${String(e)}; got ${String(t)}`);
|
|
105
106
|
return Array.from({ length: t }, (r, n) => [Math.floor(n * e / t), Math.floor((n + 1) * e / t)]);
|
|
106
|
-
},
|
|
107
|
-
if (typeof e != "string" || !
|
|
107
|
+
}, de = 31536e3, me = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u, fe = (e) => {
|
|
108
|
+
if (typeof e != "string" || !me.test(e))
|
|
108
109
|
throw new RangeError(`[markdown-explorer] settingsCookie must be a cookie-name token; got ${JSON.stringify(e)}`);
|
|
109
|
-
}, z = (e) => typeof e == "number" && Number.isFinite(e) && e > 0 && e <= G,
|
|
110
|
+
}, z = (e) => typeof e == "number" && Number.isFinite(e) && e > 0 && e <= G, ue = (e, t) => {
|
|
110
111
|
if (e === null || typeof e != "object" || Array.isArray(e)) return {};
|
|
111
112
|
const r = e, { treeExplorer: n, multiExplorer: o, style: s, align: a } = r;
|
|
112
113
|
return {
|
|
113
114
|
...z(n) ? { treeExplorer: n } : {},
|
|
114
115
|
...z(o) ? { multiExplorer: o } : {},
|
|
115
116
|
...typeof s == "string" && t.includes(s) ? { style: s } : {},
|
|
116
|
-
...typeof a == "string" &&
|
|
117
|
+
...typeof a == "string" && b.includes(a) ? { align: a } : {}
|
|
117
118
|
};
|
|
118
|
-
},
|
|
119
|
+
}, ft = (e, t) => {
|
|
119
120
|
if (e !== null)
|
|
120
121
|
for (const r of e.split(";")) {
|
|
121
122
|
const n = r.indexOf("=");
|
|
122
123
|
if (!(n < 0) && r.slice(0, n).trim() === t)
|
|
123
124
|
return r.slice(n + 1).trim();
|
|
124
125
|
}
|
|
125
|
-
},
|
|
126
|
+
}, ut = (e, t) => {
|
|
126
127
|
if (e === void 0 || e === "") return {};
|
|
127
128
|
try {
|
|
128
|
-
return
|
|
129
|
+
return ue(JSON.parse(decodeURIComponent(e)), t);
|
|
129
130
|
} catch {
|
|
130
131
|
return {};
|
|
131
132
|
}
|
|
132
|
-
}, O = 100,
|
|
133
|
-
const t = (r) => Math.min(
|
|
133
|
+
}, O = 100, ge = Math.floor(G * O) / O, we = (e) => {
|
|
134
|
+
const t = (r) => Math.min(ge, Math.max(1, Math.round(r * O)) / O);
|
|
134
135
|
return encodeURIComponent(
|
|
135
136
|
JSON.stringify({
|
|
136
137
|
...e.treeExplorer === void 0 ? {} : { treeExplorer: t(e.treeExplorer) },
|
|
@@ -139,50 +140,61 @@ const F = (e) => {
|
|
|
139
140
|
...e.align === void 0 ? {} : { align: e.align }
|
|
140
141
|
})
|
|
141
142
|
);
|
|
142
|
-
},
|
|
143
|
+
}, gt = (e, t, r) => `${e}=${we(t)}; Path=/; Max-Age=${String(de)}; SameSite=Lax${r ? "; Secure" : ""}`, j = Object.freeze({ tree: "tree", multi: "multi", single: "single" }), pe = Object.freeze({ default: 12, min: 1, max: 64 }), he = Object.freeze({ default: 4, min: 1, max: 6 }), Ee = Object.freeze({ default: 500, min: 1, max: 1e4 }), Se = Object.freeze({ default: 16, min: 1, max: 64 }), ye = /^\/(?:[A-Za-z0-9._~-]+\/)*[A-Za-z0-9._~-]+$/u, xe = /^[A-Za-z0-9][A-Za-z0-9_-]*$/u, be = /^[a-z0-9][a-z0-9-]*$/u, Oe = /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/u, D = (e, t) => {
|
|
143
144
|
if (typeof t != "string") throw new TypeError(`[markdown-explorer] ${e} must be a string; got ${typeof t}`);
|
|
144
|
-
if (!
|
|
145
|
+
if (!ye.test(t) || t.split("/").some((r) => r === "." || r === ".."))
|
|
145
146
|
throw new RangeError(`[markdown-explorer] ${e} must start with "/", have no trailing "/", and use only letters, digits and "._~-" in each segment; got ${JSON.stringify(t)}`);
|
|
146
|
-
},
|
|
147
|
+
}, d = (e) => typeof e == "string" ? JSON.stringify(e) : typeof e == "bigint" ? `${String(e)}n` : Object.is(e, -0) ? "-0" : typeof e == "function" ? "a function" : Array.isArray(e) ? "an array" : e !== null && typeof e == "object" ? F(e) ? "a plain object" : `a non-plain object (${Object.prototype.toString.call(e)})` : String(e), S = (e, t, r) => {
|
|
147
148
|
if (t === void 0) return [];
|
|
148
|
-
if (!F(t)) throw new TypeError(`[markdown-explorer] ${e} must be a plain object; got ${
|
|
149
|
+
if (!F(t)) throw new TypeError(`[markdown-explorer] ${e} must be a plain object; got ${d(t)}`);
|
|
149
150
|
const n = Object.entries(t);
|
|
150
151
|
for (const [o] of n)
|
|
151
152
|
if (!r.includes(o)) throw new RangeError(`[markdown-explorer] ${e}.${o} is not an option; expected ${r.join(", ")}`);
|
|
152
153
|
return n.filter(([, o]) => o !== void 0);
|
|
153
|
-
},
|
|
154
|
+
}, _e = (e) => {
|
|
154
155
|
const t = { ...j };
|
|
155
|
-
for (const [r, n] of
|
|
156
|
+
for (const [r, n] of S("views", e, Object.keys(j))) t[r] = n;
|
|
156
157
|
for (const [r, n] of Object.entries(t))
|
|
157
|
-
if (typeof n != "string" || !
|
|
158
|
+
if (typeof n != "string" || !xe.test(n))
|
|
158
159
|
throw new RangeError(`[markdown-explorer] views.${r} must start with a letter or digit and use only letters, digits, "_" and "-"; got ${JSON.stringify(n)}`);
|
|
159
160
|
return Object.freeze(t);
|
|
160
|
-
},
|
|
161
|
+
}, x = (e, t, r) => {
|
|
161
162
|
if (t === void 0) return r.default;
|
|
162
163
|
if (typeof t != "number" || !Number.isInteger(t) || t < r.min || t > r.max)
|
|
163
|
-
throw new RangeError(`[markdown-explorer] ${e} must be an integer in ${String(r.min)}..${String(r.max)}; got ${
|
|
164
|
+
throw new RangeError(`[markdown-explorer] ${e} must be an integer in ${String(r.min)}..${String(r.max)}; got ${d(t)}`);
|
|
164
165
|
return t;
|
|
165
|
-
},
|
|
166
|
+
}, Re = (e) => {
|
|
167
|
+
const t = new Map(S("embeds", e, ["providers", "linkCardEndpoint"]));
|
|
168
|
+
if (t.size === 0) return Y;
|
|
169
|
+
const r = t.has("providers") ? t.get("providers") : [];
|
|
170
|
+
if (!Array.isArray(r)) throw new RangeError(`[markdown-explorer] embeds.providers must be an array of provider ids; got ${d(r)}`);
|
|
171
|
+
for (const o of r)
|
|
172
|
+
if (!Q(o)) throw new RangeError(`[markdown-explorer] embeds.providers must hold only ${ee.join(", ")}; got ${d(o)}`);
|
|
173
|
+
const n = t.has("linkCardEndpoint") ? t.get("linkCardEndpoint") : null;
|
|
174
|
+
if (n !== null && !te(n))
|
|
175
|
+
throw new RangeError(`[markdown-explorer] embeds.linkCardEndpoint must start with "/", have no trailing "/", and use only letters, digits and "._~-" in each segment; got ${d(n)}`);
|
|
176
|
+
return Object.freeze({ providers: Object.freeze([...new Set(r)]), linkCardEndpoint: n });
|
|
177
|
+
}, Te = (e) => {
|
|
166
178
|
const t = new Map(
|
|
167
|
-
|
|
179
|
+
S(
|
|
168
180
|
"defaultTreeSettings",
|
|
169
181
|
e,
|
|
170
182
|
p.map((n) => n.key)
|
|
171
183
|
)
|
|
172
184
|
);
|
|
173
|
-
if (t.size === 0) return
|
|
174
|
-
const r = { ...
|
|
185
|
+
if (t.size === 0) return P;
|
|
186
|
+
const r = { ...P };
|
|
175
187
|
for (const n of p) {
|
|
176
188
|
if (!t.has(n.key)) continue;
|
|
177
189
|
const o = t.get(n.key), s = n.values;
|
|
178
|
-
if (!s.includes(o)) throw new RangeError(`[markdown-explorer] defaultTreeSettings.${n.key} must be one of ${s.map(
|
|
190
|
+
if (!s.includes(o)) throw new RangeError(`[markdown-explorer] defaultTreeSettings.${n.key} must be one of ${s.map(d).join(", ")}; got ${d(o)}`);
|
|
179
191
|
r[n.key] = o;
|
|
180
192
|
}
|
|
181
193
|
return Object.freeze(r);
|
|
182
|
-
},
|
|
194
|
+
}, wt = (e) => {
|
|
183
195
|
if (e === null || typeof e != "object") throw new TypeError("[markdown-explorer] the explorer configuration must be an object");
|
|
184
196
|
D("basePath", e.basePath), D("dataPath", e.dataPath);
|
|
185
|
-
const t =
|
|
197
|
+
const t = _e(e.views);
|
|
186
198
|
if ((/* @__PURE__ */ new Set([t.tree, t.multi, t.single])).size !== 3)
|
|
187
199
|
throw new RangeError(`[markdown-explorer] the view slugs must differ; got ${JSON.stringify(t)}`);
|
|
188
200
|
if (e.dataPath === e.basePath) throw new RangeError("[markdown-explorer] dataPath must differ from basePath");
|
|
@@ -191,11 +203,11 @@ const F = (e) => {
|
|
|
191
203
|
if (i === t.tree || i === t.multi || i === t.single)
|
|
192
204
|
throw new RangeError(`[markdown-explorer] dataPath must not start with a view slug under basePath; got ${JSON.stringify(e.dataPath)}`);
|
|
193
205
|
}
|
|
194
|
-
|
|
206
|
+
fe(e.settingsCookie);
|
|
195
207
|
const r = e.iframeHosts ?? [];
|
|
196
|
-
if (!Array.isArray(r) || r.some((i) => typeof i != "string" || !
|
|
208
|
+
if (!Array.isArray(r) || r.some((i) => typeof i != "string" || !Oe.test(i)))
|
|
197
209
|
throw new RangeError(`[markdown-explorer] iframeHosts must be lowercase host names without scheme, port or path; got ${JSON.stringify(r)}`);
|
|
198
|
-
const n = Object.fromEntries(
|
|
210
|
+
const n = Object.fromEntries(S("multiView", e.multiView, ["maxPanels", "columns"])), o = Object.fromEntries(S("expandAll", e.expandAll, ["maxFolders", "maxDepth"])), s = e.documentStyles ?? re;
|
|
199
211
|
if (!Array.isArray(s) || s.length === 0) throw new RangeError("[markdown-explorer] documentStyles must be a non-empty array");
|
|
200
212
|
const a = /* @__PURE__ */ new Set();
|
|
201
213
|
for (const i of s) {
|
|
@@ -210,25 +222,26 @@ const F = (e) => {
|
|
|
210
222
|
settingsCookie: e.settingsCookie,
|
|
211
223
|
views: t,
|
|
212
224
|
multiView: Object.freeze({
|
|
213
|
-
maxPanels:
|
|
214
|
-
columns:
|
|
225
|
+
maxPanels: x("multiView.maxPanels", n.maxPanels, pe),
|
|
226
|
+
columns: x("multiView.columns", n.columns, he)
|
|
215
227
|
}),
|
|
216
228
|
expandAll: Object.freeze({
|
|
217
|
-
maxFolders:
|
|
218
|
-
maxDepth:
|
|
229
|
+
maxFolders: x("expandAll.maxFolders", o.maxFolders, Ee),
|
|
230
|
+
maxDepth: x("expandAll.maxDepth", o.maxDepth, Se)
|
|
219
231
|
}),
|
|
220
232
|
documentStyles: Object.freeze(s.map((i) => Object.freeze({ name: i.name, className: i.className }))),
|
|
221
233
|
iframeHosts: Object.freeze([...new Set(r)]),
|
|
222
|
-
|
|
234
|
+
embeds: Re(e.embeds),
|
|
235
|
+
defaultTreeSettings: Te(e.defaultTreeSettings)
|
|
223
236
|
});
|
|
224
|
-
},
|
|
225
|
-
if (e === null || typeof e != "object") throw new TypeError(`[markdown-explorer] withExplorerSources needs the configuration of defineExplorerConfig; got ${
|
|
226
|
-
if (!Array.isArray(t) || t.length === 0) throw new RangeError(`[markdown-explorer] sourceIds must be a non-empty array; got ${
|
|
237
|
+
}, Ne = (e) => typeof e == "string" && be.test(e), pt = (e, t) => {
|
|
238
|
+
if (e === null || typeof e != "object") throw new TypeError(`[markdown-explorer] withExplorerSources needs the configuration of defineExplorerConfig; got ${d(e)}`);
|
|
239
|
+
if (!Array.isArray(t) || t.length === 0) throw new RangeError(`[markdown-explorer] sourceIds must be a non-empty array; got ${d(t)}`);
|
|
227
240
|
for (const r of t)
|
|
228
|
-
if (!
|
|
241
|
+
if (!Ne(r)) throw new RangeError(`[markdown-explorer] each source id must use lowercase letters, digits and "-" and start with a letter or digit; got ${d(r)}`);
|
|
229
242
|
if (new Set(t).size !== t.length) throw new RangeError(`[markdown-explorer] source ids must be unique; got ${JSON.stringify(t)}`);
|
|
230
243
|
return Object.freeze({ ...e, sourceIds: Object.freeze([...t]) });
|
|
231
|
-
},
|
|
244
|
+
}, ht = (e) => e.documentStyles.map((t) => t.name), c = Object.freeze({
|
|
232
245
|
source: "source",
|
|
233
246
|
doc: "doc",
|
|
234
247
|
maximized: "maximized",
|
|
@@ -240,25 +253,25 @@ const F = (e) => {
|
|
|
240
253
|
padding: "padding",
|
|
241
254
|
width: "width",
|
|
242
255
|
maxWidth: "maxWidth"
|
|
243
|
-
}), C = ".data", J = 256, X = /^\d+(?:\.\d+)?$/u, I = /^\d+(?:\.\d+)?(?:px|rem|em|ch|vw|%)$/u, W = Object.freeze(["showToc", "showStyle", "showAlign"]),
|
|
256
|
+
}), C = ".data", J = 256, X = /^\d+(?:\.\d+)?$/u, I = /^\d+(?:\.\d+)?(?:px|rem|em|ch|vw|%)$/u, W = Object.freeze(["showToc", "showStyle", "showAlign"]), Ae = (e) => {
|
|
244
257
|
const t = encodeURIComponent(e.replaceAll("%", "%25"));
|
|
245
258
|
return t.endsWith(C) ? `${t.slice(0, -C.length)}%2Edata` : t;
|
|
246
|
-
},
|
|
259
|
+
}, Ie = (e) => e.replaceAll("%25", "%"), H = (e) => {
|
|
247
260
|
const { sourceIds: t } = e;
|
|
248
261
|
if (t === void 0) throw new TypeError("[markdown-explorer] the configuration has no source ids; join the server's sources with withExplorerSources(config, sourceIds)");
|
|
249
262
|
return t;
|
|
250
|
-
},
|
|
263
|
+
}, ke = (e, t, r) => {
|
|
251
264
|
const n = r.getAll(c.source);
|
|
252
265
|
if (n.length === 0) return t;
|
|
253
266
|
const [o] = n;
|
|
254
267
|
return n.length > 1 || o === void 0 || o === t || !e.includes(o) ? null : o;
|
|
255
|
-
},
|
|
268
|
+
}, $e = (e, t) => {
|
|
256
269
|
const r = t.get(c.style), n = t.get(c.align);
|
|
257
270
|
return {
|
|
258
271
|
...r !== null && e.documentStyles.some((o) => o.name === r) ? { style: r } : {},
|
|
259
|
-
...n !== null &&
|
|
272
|
+
...n !== null && b.includes(n) ? { align: n } : {}
|
|
260
273
|
};
|
|
261
|
-
}, q = (e) => Number.isFinite(e) && e >= 0 && e <= J && X.test(String(e)),
|
|
274
|
+
}, q = (e) => Number.isFinite(e) && e >= 0 && e <= J && X.test(String(e)), ve = (e) => {
|
|
262
275
|
const t = e.get(c.padding), r = t !== null && X.test(t) ? Number(t) : Number.NaN, n = e.get(c.width), o = e.get(c.maxWidth);
|
|
263
276
|
return {
|
|
264
277
|
...e.get(c.showToc) === "false" ? { showToc: !1 } : {},
|
|
@@ -268,20 +281,20 @@ const F = (e) => {
|
|
|
268
281
|
...n !== null && I.test(n) ? { width: n } : {},
|
|
269
282
|
...o !== null && I.test(o) ? { maxWidth: o } : {}
|
|
270
283
|
};
|
|
271
|
-
},
|
|
272
|
-
for (const n of t)
|
|
284
|
+
}, Pe = (e, t) => [...new Set(t.filter(k))].slice(0, e.multiView.maxPanels), Me = (e, t, r) => {
|
|
285
|
+
for (const n of t) B(n);
|
|
273
286
|
if (new Set(t).size !== t.length) throw new RangeError(`[markdown-explorer] multi-view documents must each appear once; got ${String(t.length)} with repeats`);
|
|
274
287
|
if (t.length > e.multiView.maxPanels) throw new RangeError(`[markdown-explorer] the multi view opens at most ${String(e.multiView.maxPanels)} documents; got ${String(t.length)}`);
|
|
275
288
|
if (r !== null && !t.includes(r)) throw new RangeError(`[markdown-explorer] the maximized document must be one of the open documents; got ${JSON.stringify(r.slice(0, 80))}`);
|
|
276
|
-
},
|
|
289
|
+
}, B = (e) => {
|
|
277
290
|
if (!k(e)) throw new RangeError(`[markdown-explorer] not an acceptable document path: ${JSON.stringify(String(e).slice(0, 80))}`);
|
|
278
291
|
return e;
|
|
279
|
-
},
|
|
292
|
+
}, Le = (e, t) => {
|
|
280
293
|
if (t.style !== void 0 && !e.documentStyles.some((r) => r.name === t.style))
|
|
281
294
|
throw new RangeError(`[markdown-explorer] overrides.style must name a configured document style (${e.documentStyles.map((r) => JSON.stringify(r.name)).join(", ")}); got ${JSON.stringify(t.style)}`);
|
|
282
|
-
if (t.align !== void 0 && !
|
|
283
|
-
throw new RangeError(`[markdown-explorer] overrides.align must be one of ${
|
|
284
|
-
},
|
|
295
|
+
if (t.align !== void 0 && !b.includes(t.align))
|
|
296
|
+
throw new RangeError(`[markdown-explorer] overrides.align must be one of ${b.join(", ")}; got ${JSON.stringify(t.align)}`);
|
|
297
|
+
}, ze = (e) => {
|
|
285
298
|
for (const t of W)
|
|
286
299
|
if (e[t] !== void 0 && typeof e[t] != "boolean") throw new RangeError(`[markdown-explorer] embed.${t} must be a boolean; got ${JSON.stringify(e[t])}`);
|
|
287
300
|
if (e.padding !== void 0 && !q(e.padding)) throw new RangeError(`[markdown-explorer] embed.padding must be 0..${String(J)} px in plain decimal digits; got ${String(e.padding)}`);
|
|
@@ -289,94 +302,94 @@ const F = (e) => {
|
|
|
289
302
|
const r = e[t];
|
|
290
303
|
if (r !== void 0 && !I.test(r)) throw new RangeError(`[markdown-explorer] embed.${t} must be a CSS length in px, rem, em, ch, vw or %; got ${JSON.stringify(r)}`);
|
|
291
304
|
}
|
|
292
|
-
},
|
|
305
|
+
}, je = (e, t) => {
|
|
293
306
|
const r = new URLSearchParams();
|
|
294
307
|
let n = `${e.basePath}/${e.views[t.view]}`;
|
|
295
308
|
if (t.view === "multi") {
|
|
296
309
|
const s = t.docs ?? [], a = t.maximized ?? null;
|
|
297
|
-
|
|
310
|
+
Me(e, s, a);
|
|
298
311
|
for (const i of s) r.append(c.doc, i);
|
|
299
312
|
a !== null && r.set(c.maximized, a);
|
|
300
|
-
} else t.doc !== void 0 && t.doc !== null && (n += `/${
|
|
313
|
+
} else t.doc !== void 0 && t.doc !== null && (n += `/${Ae(B(t.doc))}`);
|
|
301
314
|
if (t.source !== void 0) {
|
|
302
315
|
const s = H(e);
|
|
303
316
|
if (!s.includes(t.source)) throw new RangeError(`[markdown-explorer] unknown source ${JSON.stringify(t.source)}; expected one of ${s.join(", ")}`);
|
|
304
317
|
t.source !== s[0] && r.set(c.source, t.source);
|
|
305
318
|
}
|
|
306
|
-
if (t.view !== "multi" && t.overrides !== void 0 && (
|
|
319
|
+
if (t.view !== "multi" && t.overrides !== void 0 && (Le(e, t.overrides), t.overrides.style !== void 0 && r.set(c.style, t.overrides.style), t.overrides.align !== void 0 && r.set(c.align, t.overrides.align)), t.view === "single" && t.embed !== void 0) {
|
|
307
320
|
const { embed: s } = t;
|
|
308
|
-
|
|
321
|
+
ze(s);
|
|
309
322
|
for (const a of W) s[a] === !1 && r.set(c[a], "false");
|
|
310
323
|
s.padding !== void 0 && r.set(c.padding, String(s.padding)), s.width !== void 0 && r.set(c.width, s.width), s.maxWidth !== void 0 && r.set(c.maxWidth, s.maxWidth);
|
|
311
324
|
}
|
|
312
325
|
const o = r.toString();
|
|
313
326
|
return o === "" ? n : `${n}?${o}`;
|
|
314
|
-
},
|
|
327
|
+
}, De = (e, t) => Object.keys(e.views).find((r) => e.views[r] === t), Et = (e, t, r) => {
|
|
315
328
|
const n = H(e), [o] = n;
|
|
316
329
|
if (o === void 0) throw new RangeError("[markdown-explorer] the configuration has no source");
|
|
317
|
-
const s =
|
|
330
|
+
const s = ke(n, o, r), a = s === null ? o : s, i = (m) => ({ kind: "redirect", href: je(e, m), location: m }), l = () => i({ view: "tree", source: a, doc: null, overrides: {} });
|
|
318
331
|
if (t === void 0 || t === "") return l();
|
|
319
|
-
const h = t.indexOf("/"),
|
|
320
|
-
if (
|
|
321
|
-
if (
|
|
322
|
-
const
|
|
323
|
-
return
|
|
332
|
+
const h = t.indexOf("/"), _ = h < 0 ? t : t.slice(0, h), R = h < 0 ? null : t.slice(h + 1), f = De(e, _);
|
|
333
|
+
if (f === void 0) return l();
|
|
334
|
+
if (f === "multi") {
|
|
335
|
+
const m = r.getAll(c.doc), E = Pe(e, m), T = r.getAll(c.maximized), [N] = T, A = T.length === 1 && N !== void 0 && E.includes(N) ? N : null;
|
|
336
|
+
return R === null && s !== null && E.length === m.length && E.every((K, Z) => K === m[Z]) && (T.length === 0 || A !== null) ? { kind: "location", location: { view: "multi", source: a, docs: E, maximized: A } } : i({ view: "multi", source: a, docs: E, maximized: A });
|
|
324
337
|
}
|
|
325
|
-
const
|
|
326
|
-
if (
|
|
327
|
-
const
|
|
328
|
-
if (
|
|
329
|
-
if (
|
|
330
|
-
const
|
|
331
|
-
return s === null ? i({ view:
|
|
338
|
+
const u = R === null ? null : Ie(R);
|
|
339
|
+
if (u !== null && !k(u)) return l();
|
|
340
|
+
const y = $e(e, r);
|
|
341
|
+
if (f === "single") {
|
|
342
|
+
if (u === null) return l();
|
|
343
|
+
const m = ve(r);
|
|
344
|
+
return s === null ? i({ view: f, source: a, doc: u, overrides: y, embed: m }) : { kind: "location", location: { view: f, source: a, doc: u, overrides: y, embed: m } };
|
|
332
345
|
}
|
|
333
|
-
return s === null ? i({ view:
|
|
346
|
+
return s === null ? i({ view: f, source: a, doc: u, overrides: y }) : { kind: "location", location: { view: f, source: a, doc: u, overrides: y } };
|
|
334
347
|
};
|
|
335
348
|
export {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
349
|
+
Qe as A,
|
|
350
|
+
Be as B,
|
|
351
|
+
tt as C,
|
|
352
|
+
M as D,
|
|
353
|
+
ct as E,
|
|
354
|
+
nt as F,
|
|
342
355
|
w as G,
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
356
|
+
We as H,
|
|
357
|
+
gt as I,
|
|
358
|
+
it as J,
|
|
359
|
+
P as K,
|
|
347
360
|
j as L,
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
+
Se as M,
|
|
362
|
+
v as N,
|
|
363
|
+
Ee as O,
|
|
364
|
+
ot as P,
|
|
365
|
+
se as Q,
|
|
366
|
+
he as R,
|
|
367
|
+
et as S,
|
|
368
|
+
pe as T,
|
|
369
|
+
wt as a,
|
|
370
|
+
ft as b,
|
|
371
|
+
Pe as c,
|
|
372
|
+
ht as d,
|
|
373
|
+
je as e,
|
|
361
374
|
F as f,
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
375
|
+
mt as g,
|
|
376
|
+
dt as h,
|
|
377
|
+
Ne as i,
|
|
378
|
+
st as j,
|
|
379
|
+
Ke as k,
|
|
380
|
+
Xe as l,
|
|
381
|
+
at as m,
|
|
382
|
+
ce as n,
|
|
370
383
|
G as o,
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
384
|
+
ut as p,
|
|
385
|
+
Ze as q,
|
|
386
|
+
Et as r,
|
|
387
|
+
Ye as s,
|
|
388
|
+
rt as t,
|
|
389
|
+
lt as u,
|
|
390
|
+
Ge as v,
|
|
391
|
+
pt as w,
|
|
392
|
+
qe as x,
|
|
393
|
+
Je as y,
|
|
394
|
+
He as z
|
|
382
395
|
};
|
package/dist/sanitizeWorker.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";const ee=require("node:worker_threads"),S=require("parse5"),w=require("isomorphic-dompurify"),B=require("./dataRoute-CKbdwkQ7.cjs"),F=512,te=4096,P=1024,G=Symbol("placement"),j=2,re=3,ne=new Set(["html","head","body"]),b=0,y=1,I=2,V=3,D=4,L=5,O=6,N=7,$=8,k=9,W=10,_=-1,se=0,oe=1,ae=2,ie=3,ce=4,le=5,q=6,ue=7,fe=t=>{switch(t){case 9:case 10:case 12:case 13:case 32:return se;case 47:return oe;case 62:return ae;case 61:return ie;case 34:return ce;case 39:return le;default:return q}},de=Uint8Array.from({length:128},(t,n)=>fe(n)),U=60,Q=47,pe=/[\t\n\f\r />="'<]/g,Ae=/["<]/g,Ee=/['<]/g,m=-1-I,he=Int8Array.from([[y,k,_,b,b,b,b],[y,k,_,m,m,m,m],[V,k,_,D,I,I,I],[V,k,_,D,m,m,m],[D,N,_,N,L,O,N],[L,L,L,L,$,L,L],[O,O,O,O,O,$,O],[y,N,_,N,N,N,N],[y,k,_,m,m,m,m],[y,k,_,m,m,m,m]].flat()),X=t=>t>=65&&t<=90||t>=97&&t<=122,me=(t,n)=>{let s=new Int32Array(W),l=new Int32Array(W),i=0,T=0,o=0;for(;o<t.length;){if(i===0){const r=t.indexOf("<",o);if(r<0)return!1;o=r+1,t.charCodeAt(o)===Q&&(o+=1),X(t.charCodeAt(o))&&(s[b]=0,i=1<<b,o+=1);continue}if((i&-230)===0&&o>=T){const r=i===1<<L?Ae:i===1<<O?Ee:pe;r.lastIndex=o;const d=r.exec(t);if(d===null)return!1;o=d.index,t.charCodeAt(o)===U&&(T=o+3)}const E=t.charCodeAt(o),g=E<128?de[E]:q;let h=0;for(let r=i;r!==0;r&=r-1){const d=31-Math.clz32(r&-r);let f=he[d*ue+g],A=s[d];if(f<_&&(f=-1-f,A+=1,A>n))return!0;if(f===_)continue;const R=1<<f;((h&R)===0||A>l[f])&&(l[f]=A),h|=R}X(E)&&(t.charCodeAt(o-1)===U||t.charCodeAt(o-1)===Q&&t.charCodeAt(o-2)===U)&&(h&1<<b)===0&&(l[b]=0,h|=1<<b);const u=s;s=l,l=u,i=h,o+=1}return!1};class C extends Error{status;constructor(n){super(`[markdown-explorer] the nesting guard stopped the parse: ${n}`),this.name="ParseStop",this.status=n}}const Te=(t,n,s,l)=>{if(!Number.isSafeInteger(n)||n<=0)throw new RangeError(`[markdown-explorer] the nesting guard's depth limit must be a positive safe integer; got ${String(n)}`);if(!Number.isSafeInteger(s)||s<=0)throw new RangeError(`[markdown-explorer] the nesting guard's node budget must be a positive safe integer; got ${String(s)}`);if(!Number.isSafeInteger(l)||l<=0)throw new RangeError(`[markdown-explorer] the nesting guard's attribute character budget must be a positive safe integer; got ${String(l)}`);if(me(t,P))return{status:"too-many-attributes"};const i=n+j,T=t.length+re;let o=null,E=0,g=0,h=0,u=0;const r=e=>{if(g+=e,g>s)throw new C("too-many-nodes")},d=e=>{for(const a of e)u+=a.name.length+a.value.length;if(u>l)throw new C("too-many-attribute-characters")},f=(e,a,c,p)=>{const v={node:e,above:null,levels:a,height:0,keepsChildren:c,attributes:p,first:null,next:null,previous:null},Z=e;return Z[G]=v,v},A=e=>{const c=e[G];if(c===void 0)throw new Error("[markdown-explorer] the nesting guard was handed a node it did not create");return c},R=(e,a)=>{let c=a;for(let p=e;p!==null&&c>p.height;p=p.above)p.height=c,c+=p.levels;if(o!==null&&o.height>i)throw new C("too-deep")},M=e=>{const a=e.above;a?.keepsChildren&&(e.previous===null?a.first=e.next:e.previous.next=e.next,e.next!==null&&(e.next.previous=e.previous)),e.above=null,e.next=null,e.previous=null},H=(e,a)=>{if(!S.defaultTreeAdapter.isElementNode(a))return;const c=A(a),p=A(e);M(c),c.above=p,p.keepsChildren&&(c.next=p.first,p.first!==null&&(p.first.previous=c),p.first=c),a.parentNode=e,R(p,c.height+c.levels)},K={...S.defaultTreeAdapter,createDocument:()=>{const e=S.defaultTreeAdapter.createDocument();return o=f(e,0,!1,0),e},createDocumentFragment:()=>{const e=S.defaultTreeAdapter.createDocumentFragment();return f(e,0,!1,0),e},createElement:(e,a,c)=>{if(E+=1,E>T)throw new C("too-many-elements");r(1+c.length),d(c);const p=S.defaultTreeAdapter.createElement(e,a,c);return f(p,1,!(a===S.html.NS.HTML&&ne.has(e)),c.length),p},createCommentNode:e=>{if(h+=1,h>te)throw new C("too-many-comments");return r(1),S.defaultTreeAdapter.createCommentNode(e)},setTemplateContent:(e,a)=>{S.defaultTreeAdapter.setTemplateContent(e,a);const c=A(a);c.above=A(e),R(c.above,c.height)},appendChild:H,insertBefore:(e,a)=>H(e,a),detachNode:e=>{S.defaultTreeAdapter.isElementNode(e)&&(M(A(e)),e.parentNode=null)},getFirstChild:e=>{const a=A(e);if(!a.keepsChildren)throw new Error("[markdown-explorer] the nesting guard was asked for the children of a node whose children it does not keep");return a.first===null?null:a.first.node},getChildNodes:()=>{throw new Error("[markdown-explorer] the nesting guard keeps no child lists for source locations")},onItemPop:e=>{const a=A(e);a.keepsChildren=!1,a.first=null},insertText:()=>{},insertTextBefore:()=>{},adoptAttributes:(e,a)=>{r(a.length),d(a);const c=A(e);if(c.attributes+=a.length,c.attributes>P)throw new C("too-many-attributes")}};let z;try{z=S.parse(t,{scriptingEnabled:!1,treeAdapter:K})}catch(e){if(e instanceof C)return{status:e.status};throw e}return{status:"within",depth:A(z).height-j,elements:E,nodes:g}};class J extends RangeError{constructor(n){super(`[markdown-explorer] the HTML nests deeper than ${String(n)} levels`),this.name="HtmlNestingLimitError"}}const ge=["script","style","noscript","template","form","button","textarea","select","option","object","embed","base","meta","link","frame","frameset"],Se=["srcdoc","formaction"],we=/^(?:(?:https?|mailto|tel):|[^a-z]|[a-z+.-]+(?:[^a-z+.:-]|$))/iu,_e=new Set(["left","right","center","justify","start","end"]),be=new Set(["h1","h2","h3","h4","h5","h6"]),x=1,Y=Object.freeze({a:Object.freeze(["target","data-link-kind","data-doc-path","data-doc-exists","data-footnote-ref","data-footnote-backref"]),area:Object.freeze(["target"]),img:Object.freeze(["data-asset-src","data-asset-exists"]),section:Object.freeze(["data-footnotes"]),iframe:Object.freeze(["allow","allowfullscreen","frameborder","referrerpolicy"])}),Ne=[...new Set(Object.values(Y).flatMap(t=>t.filter(n=>n.startsWith("data-"))))],Le=new Set(["no-referrer","origin","same-origin","strict-origin","strict-origin-when-cross-origin"]),Oe=new Set(["autoplay","clipboard-write","encrypted-media","fullscreen","picture-in-picture","web-share"]),Re=new Set(["src","href","xlink:href"]),Ce=/^data:/iu,ke=Object.freeze({FORBID_TAGS:ge,FORBID_ATTR:Se,ADD_TAGS:["iframe"],ADD_ATTR:(t,n)=>Y[n]?.includes(t)===!0,ADD_URI_SAFE_ATTR:Ne,ALLOWED_URI_REGEXP:we,ALLOW_DATA_ATTR:!1}),ye=t=>{let n=null;for(const s of t.split(";")){const l=s.indexOf(":");if(l<0||s.slice(0,l).trim().toLowerCase()!=="text-align")continue;const i=s.slice(l+1).trim().toLowerCase();_e.has(i)&&(n=i)}return n===null?null:`text-align: ${n}`},Ie=t=>{const n=new Set;for(const s of t.split(";")){const[l]=s.trim().toLowerCase().split(/\s+/u);l!==void 0&&Oe.has(l)&&n.add(l)}return n.size===0?null:[...n].join("; ")},De=(t,n)=>{if(t===null)return!1;let s;try{s=new URL(t.trim())}catch{return!1}return s.protocol==="https:"&&s.username===""&&s.password===""&&s.port===""&&n.has(s.hostname)},Ue=t=>{const n=t.getAttribute("type");return n!==null&&n.trim().toLowerCase()==="checkbox"&&t.hasAttribute("disabled")},xe=(t,n,s)=>{if(w.isSupported!==!0)throw new Error("[markdown-explorer] the HTML sanitizer cannot run in this environment");if(!Number.isSafeInteger(s)||s<=0)throw new RangeError(`[markdown-explorer] the HTML sanitizer's depth limit must be a positive integer; got ${String(s)}`);const l=new Set(t);let i=new WeakMap;const T=u=>{const r=u.parentNode===null?void 0:i.get(u.parentNode),d=r===void 0?0:r+1;if(i.set(u,d),u.nodeType===x&&d>s)throw new J(s)},o=(u,r)=>{if(u.nodeType!==x)return;const d=u;(r.tagName==="input"&&!Ue(d)||r.tagName==="iframe"&&!De(d.getAttribute("src"),l))&&d.parentNode?.removeChild(d)},E=(u,r)=>{const d=u.nodeName.toLowerCase();if(r.attrName==="style"){const f=ye(r.attrValue);f===null?r.keepAttr=!1:r.attrValue=f}else if(r.attrName==="allow"&&d==="iframe"){const f=Ie(r.attrValue);f===null?r.keepAttr=!1:r.attrValue=f}else if(r.attrName==="referrerpolicy"&&d==="iframe"){const f=r.attrValue.trim().toLowerCase();Le.has(f)?r.attrValue=f:r.keepAttr=!1}else Re.has(r.attrName)&&Ce.test(r.attrValue)?r.keepAttr=!1:r.attrName==="id"&&be.has(d)&&(r.forceKeepAttr=!0)},g=u=>{const r=u.getAttribute("data-asset-src");r!==null&&(u.getAttribute("data-asset-exists")!=="false"&&B.isAcceptableDocumentPath(r)?u.setAttribute("src",B.explorerAssetHref(n,r,null)):u.removeAttribute("src"))},h=u=>{if(u.nodeType!==x)return;const r=u;r.nodeName.toLowerCase()==="img"&&g(r);const d=r.getAttribute("target");if(d===null||d.trim().toLowerCase()==="_self")return;const f=r.getAttribute("rel"),A=new Set(f===null?[]:f.split(/\s+/u).filter(R=>R!==""));A.add("noopener"),A.add("noreferrer"),r.setAttribute("rel",[...A].join(" "))};return u=>{i=new WeakMap,w.addHook("beforeSanitizeElements",T),w.addHook("uponSanitizeElement",o),w.addHook("uponSanitizeAttribute",E),w.addHook("afterSanitizeAttributes",h);try{return w.sanitize(u,ke)}finally{w.removeHook("beforeSanitizeElements",T),w.removeHook("uponSanitizeElement",o),w.removeHook("uponSanitizeAttribute",E),w.removeHook("afterSanitizeAttributes",h)}}},Me=t=>{if(t===null||typeof t!="object")return!1;const{id:n,input:s}=t;if(typeof n!="number"||s===null||typeof s!="object")return!1;const{html:l,iframeHosts:i,dataPath:T,maxNodes:o,maxAttributeChars:E,maxSanitizedChars:g}=s;return typeof l=="string"&&Array.isArray(i)&&i.every(h=>typeof h=="string")&&typeof T=="string"&&T!==""&&[o,E,g].every(h=>Number.isSafeInteger(h)&&h>0)},He=()=>{const t=ee.parentPort;if(t===null)throw new Error("[markdown-explorer] the sanitizer worker must run in a worker thread");const n=new Map;t.on("message",s=>{if(!Me(s))throw new TypeError("[markdown-explorer] the sanitizer worker received a message that is not a job");const{id:l,input:i}=s;let T;try{if(Te(i.html,F,i.maxNodes,i.maxAttributeChars).status!=="within"){t.postMessage({id:l,output:{status:"too-large"}});return}const o=JSON.stringify([i.iframeHosts,i.dataPath]);let E=n.get(o);E===void 0&&(E=xe(i.iframeHosts,i.dataPath,F),n.set(o,E));const g=E(i.html);T=g.length>i.maxSanitizedChars?{status:"too-large"}:{status:"sanitized",html:g}}catch(o){T=o instanceof J?{status:"too-large"}:{status:"error",message:o instanceof Error?`${o.name}: ${o.message}`:String(o)}}t.postMessage({id:l,output:T})}),t.postMessage({ready:!0})};He();
|
|
1
|
+
"use strict";const te=require("node:worker_threads"),_=require("parse5"),R=require("@aiquants/markdown/embeds"),S=require("isomorphic-dompurify"),F=require("./dataRoute-CKbdwkQ7.cjs"),G=512,re=4096,j=1024,V=Symbol("placement"),$=2,ne=3,se=new Set(["html","head","body"]),b=0,M=1,U=2,W=3,z=4,O=5,k=6,N=7,Q=8,y=9,X=10,w=-1,oe=0,ae=1,ie=2,le=3,ce=4,ue=5,J=6,fe=7,de=t=>{switch(t){case 9:case 10:case 12:case 13:case 32:return oe;case 47:return ae;case 62:return ie;case 61:return le;case 34:return ce;case 39:return ue;default:return J}},Ee=Uint8Array.from({length:128},(t,i)=>de(i)),B=60,q=47,pe=/[\t\n\f\r />="'<]/g,Te=/["<]/g,Ae=/['<]/g,m=-1-U,he=Int8Array.from([[M,y,w,b,b,b,b],[M,y,w,m,m,m,m],[W,y,w,z,U,U,U],[W,y,w,z,m,m,m],[z,N,w,N,O,k,N],[O,O,O,O,Q,O,O],[k,k,k,k,k,Q,k],[M,N,w,N,N,N,N],[M,y,w,m,m,m,m],[M,y,w,m,m,m,m]].flat()),K=t=>t>=65&&t<=90||t>=97&&t<=122,me=(t,i)=>{let u=new Int32Array(X),f=new Int32Array(X),l=0,A=0,n=0;for(;n<t.length;){if(l===0){const E=t.indexOf("<",n);if(E<0)return!1;n=E+1,t.charCodeAt(n)===q&&(n+=1),K(t.charCodeAt(n))&&(u[b]=0,l=1<<b,n+=1);continue}if((l&-230)===0&&n>=A){const E=l===1<<O?Te:l===1<<k?Ae:pe;E.lastIndex=n;const a=E.exec(t);if(a===null)return!1;n=a.index,t.charCodeAt(n)===B&&(A=n+3)}const T=t.charCodeAt(n),g=T<128?Ee[T]:J;let h=0;for(let E=l;E!==0;E&=E-1){const a=31-Math.clz32(E&-E);let r=he[a*fe+g],s=u[a];if(r<w&&(r=-1-r,s+=1,s>i))return!0;if(r===w)continue;const p=1<<r;((h&p)===0||s>f[r])&&(f[r]=s),h|=p}K(T)&&(t.charCodeAt(n-1)===B||t.charCodeAt(n-1)===q&&t.charCodeAt(n-2)===B)&&(h&1<<b)===0&&(f[b]=0,h|=1<<b);const C=u;u=f,f=C,l=h,n+=1}return!1};class L extends Error{status;constructor(i){super(`[markdown-explorer] the nesting guard stopped the parse: ${i}`),this.name="ParseStop",this.status=i}}const ge=(t,i,u,f)=>{if(!Number.isSafeInteger(i)||i<=0)throw new RangeError(`[markdown-explorer] the nesting guard's depth limit must be a positive safe integer; got ${String(i)}`);if(!Number.isSafeInteger(u)||u<=0)throw new RangeError(`[markdown-explorer] the nesting guard's node budget must be a positive safe integer; got ${String(u)}`);if(!Number.isSafeInteger(f)||f<=0)throw new RangeError(`[markdown-explorer] the nesting guard's attribute character budget must be a positive safe integer; got ${String(f)}`);if(me(t,j))return{status:"too-many-attributes"};const l=i+$,A=t.length+ne;let n=null,T=0,g=0,h=0,C=0;const E=e=>{if(g+=e,g>u)throw new L("too-many-nodes")},a=e=>{for(const o of e)C+=o.name.length+o.value.length;if(C>f)throw new L("too-many-attribute-characters")},r=(e,o,c,d)=>{const P={node:e,above:null,levels:o,height:0,keepsChildren:c,attributes:d,first:null,next:null,previous:null},ee=e;return ee[V]=P,P},s=e=>{const c=e[V];if(c===void 0)throw new Error("[markdown-explorer] the nesting guard was handed a node it did not create");return c},p=(e,o)=>{let c=o;for(let d=e;d!==null&&c>d.height;d=d.above)d.height=c,c+=d.levels;if(n!==null&&n.height>l)throw new L("too-deep")},D=e=>{const o=e.above;o?.keepsChildren&&(e.previous===null?o.first=e.next:e.previous.next=e.next,e.next!==null&&(e.next.previous=e.previous)),e.above=null,e.next=null,e.previous=null},I=(e,o)=>{if(!_.defaultTreeAdapter.isElementNode(o))return;const c=s(o),d=s(e);D(c),c.above=d,d.keepsChildren&&(c.next=d.first,d.first!==null&&(d.first.previous=c),d.first=c),o.parentNode=e,p(d,c.height+c.levels)},H={..._.defaultTreeAdapter,createDocument:()=>{const e=_.defaultTreeAdapter.createDocument();return n=r(e,0,!1,0),e},createDocumentFragment:()=>{const e=_.defaultTreeAdapter.createDocumentFragment();return r(e,0,!1,0),e},createElement:(e,o,c)=>{if(T+=1,T>A)throw new L("too-many-elements");E(1+c.length),a(c);const d=_.defaultTreeAdapter.createElement(e,o,c);return r(d,1,!(o===_.html.NS.HTML&&se.has(e)),c.length),d},createCommentNode:e=>{if(h+=1,h>re)throw new L("too-many-comments");return E(1),_.defaultTreeAdapter.createCommentNode(e)},setTemplateContent:(e,o)=>{_.defaultTreeAdapter.setTemplateContent(e,o);const c=s(o);c.above=s(e),p(c.above,c.height)},appendChild:I,insertBefore:(e,o)=>I(e,o),detachNode:e=>{_.defaultTreeAdapter.isElementNode(e)&&(D(s(e)),e.parentNode=null)},getFirstChild:e=>{const o=s(e);if(!o.keepsChildren)throw new Error("[markdown-explorer] the nesting guard was asked for the children of a node whose children it does not keep");return o.first===null?null:o.first.node},getChildNodes:()=>{throw new Error("[markdown-explorer] the nesting guard keeps no child lists for source locations")},onItemPop:e=>{const o=s(e);o.keepsChildren=!1,o.first=null},insertText:()=>{},insertTextBefore:()=>{},adoptAttributes:(e,o)=>{E(o.length),a(o);const c=s(e);if(c.attributes+=o.length,c.attributes>j)throw new L("too-many-attributes")}};let v;try{v=_.parse(t,{scriptingEnabled:!1,treeAdapter:H})}catch(e){if(e instanceof L)return{status:e.status};throw e}return{status:"within",depth:s(v).height-$,elements:T,nodes:g}};class Y extends RangeError{constructor(i){super(`[markdown-explorer] the HTML nests deeper than ${String(i)} levels`),this.name="HtmlNestingLimitError"}}const _e=["script","style","noscript","template","form","button","textarea","select","option","object","embed","base","meta","link","frame","frameset"],Se=["srcdoc","formaction"],we=/^(?:(?:https?|mailto|tel):|[^a-z]|[a-z+.-]+(?:[^a-z+.:-]|$))/iu,be=new Set(["left","right","center","justify","start","end"]),Ne=new Set(["h1","h2","h3","h4","h5","h6"]),x=1,Oe=3,ke=7,Re=8,Z=Object.freeze({a:Object.freeze(["target","data-link-kind","data-doc-path","data-doc-exists","data-footnote-ref","data-footnote-backref"]),area:Object.freeze(["target"]),img:Object.freeze(["data-asset-src","data-asset-exists"]),section:Object.freeze(["data-footnotes"]),iframe:Object.freeze(["allow","allowfullscreen","frameborder","referrerpolicy"])}),Le=[...new Set(Object.values(Z).flatMap(t=>t.filter(i=>i.startsWith("data-"))))],Ce=new Set(["src","href","xlink:href"]),Ie=/^data:/iu,ye=Object.freeze({FORBID_TAGS:_e,FORBID_ATTR:Se,ADD_TAGS:["iframe"],ADD_ATTR:(t,i)=>Z[i]?.includes(t)===!0,ADD_URI_SAFE_ATTR:Le,ALLOWED_URI_REGEXP:we,ALLOW_DATA_ATTR:!1}),De=t=>{let i=null;for(const u of t.split(";")){const f=u.indexOf(":");if(f<0||u.slice(0,f).trim().toLowerCase()!=="text-align")continue;const l=u.slice(f+1).trim().toLowerCase();be.has(l)&&(i=l)}return i===null?null:`text-align: ${i}`},Me=t=>t.nodeType===Oe?{kind:"text",text:t.nodeValue??""}:t.nodeType===Re||t.nodeType===ke?{kind:"ignored"}:t.nodeType===x&&t.nodeName.toLowerCase()==="a"?{kind:"link",href:t.getAttribute("href")}:{kind:"element"},Ue=t=>{const i=t.getAttribute("type");return i!==null&&i.trim().toLowerCase()==="checkbox"&&t.hasAttribute("disabled")},xe=(t,i,u)=>{if(S.isSupported!==!0)throw new Error("[markdown-explorer] the HTML sanitizer cannot run in this environment");if(!Number.isSafeInteger(u)||u<=0)throw new RangeError(`[markdown-explorer] the HTML sanitizer's depth limit must be a positive integer; got ${String(u)}`);const f=Object.freeze([...t]);let l=new WeakMap,A=new WeakMap;const n=a=>{const r=a.parentNode===null?void 0:l.get(a.parentNode),s=r===void 0?0:r+1;if(l.set(a,s),a.nodeType===x&&s>u)throw new Y(u)},T=(a,r)=>{if(a.nodeType!==x)return;const s=a;(r.tagName==="input"&&!Ue(s)||r.tagName==="iframe"&&R.allowedFrameUrlOf(s.getAttribute("src")?.trim(),f)===null)&&s.parentNode?.removeChild(s)},g=(a,r)=>{const s=a.nodeName.toLowerCase();if(r.attrName==="style"){const p=De(r.attrValue);p===null?r.keepAttr=!1:r.attrValue=p}else if(r.attrName==="allow"&&s==="iframe"){const p=R.reduceFrameFeatures(r.attrValue);p===null?r.keepAttr=!1:r.attrValue=p}else if(r.attrName==="referrerpolicy"&&s==="iframe"){const p=r.attrValue.trim().toLowerCase();R.EMBED_FRAME_REFERRER_POLICIES.has(p)?r.attrValue=p:r.keepAttr=!1}else r.attrName===R.EMBED_LINK_ATTRIBUTE&&s==="p"?A.set(a,a.getAttribute(R.EMBED_LINK_ATTRIBUTE)):Ce.has(r.attrName)&&Ie.test(r.attrValue)?r.keepAttr=!1:r.attrName==="id"&&Ne.has(s)&&(r.forceKeepAttr=!0)},h=a=>{const r=a.getAttribute("data-asset-src");r!==null&&(a.getAttribute("data-asset-exists")!=="false"&&F.isAcceptableDocumentPath(r)?a.setAttribute("src",F.explorerAssetHref(i,r,null)):a.removeAttribute("src"))},C=a=>{const r=a.parentNode;if(r===null)return;const s=A.get(r);s!=null&&R.placeholderLinkOf(s,[...r.childNodes].map(Me))!==null&&r.setAttribute(R.EMBED_LINK_ATTRIBUTE,s)},E=a=>{if(a.nodeType!==x)return;const r=a,s=r.nodeName.toLowerCase();s==="img"?h(r):s==="a"&&C(r);const p=r.getAttribute("target");if(p===null||p.trim().toLowerCase()==="_self")return;const D=r.getAttribute("rel"),I=new Set(D===null?[]:D.split(/\s+/u).filter(H=>H!==""));I.add("noopener"),I.add("noreferrer"),r.setAttribute("rel",[...I].join(" "))};return a=>{l=new WeakMap,A=new WeakMap,S.addHook("beforeSanitizeElements",n),S.addHook("uponSanitizeElement",T),S.addHook("uponSanitizeAttribute",g),S.addHook("afterSanitizeAttributes",E);try{return S.sanitize(a,ye)}finally{S.removeHook("beforeSanitizeElements",n),S.removeHook("uponSanitizeElement",T),S.removeHook("uponSanitizeAttribute",g),S.removeHook("afterSanitizeAttributes",E)}}},He=t=>{if(t===null||typeof t!="object")return!1;const{id:i,input:u}=t;if(typeof i!="number"||u===null||typeof u!="object")return!1;const{html:f,iframeHosts:l,dataPath:A,maxNodes:n,maxAttributeChars:T,maxSanitizedChars:g}=u;return typeof f=="string"&&Array.isArray(l)&&l.every(h=>typeof h=="string")&&typeof A=="string"&&A!==""&&[n,T,g].every(h=>Number.isSafeInteger(h)&&h>0)},ze=()=>{const t=te.parentPort;if(t===null)throw new Error("[markdown-explorer] the sanitizer worker must run in a worker thread");const i=new Map;t.on("message",u=>{if(!He(u))throw new TypeError("[markdown-explorer] the sanitizer worker received a message that is not a job");const{id:f,input:l}=u;let A;try{if(ge(l.html,G,l.maxNodes,l.maxAttributeChars).status!=="within"){t.postMessage({id:f,output:{status:"too-large"}});return}const n=JSON.stringify([l.iframeHosts,l.dataPath]);let T=i.get(n);T===void 0&&(T=xe(l.iframeHosts,l.dataPath,G),i.set(n,T));const g=T(l.html);A=g.length>l.maxSanitizedChars?{status:"too-large"}:{status:"sanitized",html:g}}catch(n){A=n instanceof Y?{status:"too-large"}:{status:"error",message:n instanceof Error?`${n.name}: ${n.message}`:String(n)}}t.postMessage({id:f,output:A})}),t.postMessage({ready:!0})};ze();
|