@aiquants/markdown-explorer 0.2.0 → 0.3.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 +23 -0
- package/README.md +26 -7
- package/dist/{ExplorerSplit-DB37U7Kh.js → ExplorerSplit-B7pmzR8t.js} +2 -2
- package/dist/{ExplorerSplit-D2plJRRe.cjs → ExplorerSplit-Bi3yU6NG.cjs} +1 -1
- package/dist/{MultiLayout-DCPDu1-l.js → MultiLayout-BxeXOLX1.js} +4 -4
- package/dist/{MultiLayout-UyWxs6Xy.cjs → MultiLayout-DtFrFRmS.cjs} +1 -1
- package/dist/{TreeLayout-CLWbWjOc.cjs → TreeLayout-BQUfVNlA.cjs} +1 -1
- package/dist/{TreeLayout-BoyFelK2.js → TreeLayout-D6hCSihW.js} +3 -3
- package/dist/core/config.d.cts +4 -2
- package/dist/core/config.d.ts +4 -2
- package/dist/{dataRoute-CKbdwkQ7.cjs → dataRoute-B9Wk-G7A.cjs} +1 -1
- package/dist/{dataRoute-Bkfwfp1R.js → dataRoute-zUX-oR9j.js} +39 -38
- package/dist/{index-BfuAu2GV.js → index-BJTmp0lR.js} +3 -3
- package/dist/{index-Cx3-jSna.cjs → index-DkiGlM7C.cjs} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +13 -13
- package/dist/location-DfYTzfFS.cjs +1 -0
- package/dist/{location-fVl2R1ee.js → location-V5BKeWNs.js} +178 -164
- package/dist/sanitizeWorker.cjs +1 -1
- package/dist/sanitizeWorker.js +1 -1
- package/dist/server/anonymous.d.cts +2 -2
- package/dist/server/anonymous.d.ts +2 -2
- package/dist/server/ports.d.cts +4 -1
- package/dist/server/ports.d.ts +4 -1
- package/dist/server.cjs +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +631 -603
- package/docs/behavior/security.md +16 -2
- package/package.json +3 -3
- package/dist/location-Oo21lTyV.cjs +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { NO_EMBEDS as Y, isEmbedProviderId as Q, EMBED_PROVIDER_IDS as ee,
|
|
2
|
-
import { CONTENT_ALIGNS as
|
|
3
|
-
import { i as
|
|
4
|
-
const
|
|
1
|
+
import { NO_EMBEDS as Y, isEmbedProviderId as Q, EMBED_PROVIDER_IDS as ee, isLinkCardSize as te, LINK_CARD_SIZES as re } from "@aiquants/markdown/embeds";
|
|
2
|
+
import { CONTENT_ALIGNS as x, DEFAULT_MARKDOWN_STYLES as ne } from "@aiquants/markdown/viewer-settings";
|
|
3
|
+
import { a as oe, i as I } from "./dataRoute-zUX-oR9j.js";
|
|
4
|
+
const $ = (e) => {
|
|
5
5
|
if (e === null || typeof e != "object") return !1;
|
|
6
6
|
const t = Object.getPrototypeOf(e);
|
|
7
7
|
return t === Object.prototype || t === null;
|
|
8
|
-
},
|
|
8
|
+
}, P = new Intl.Collator("en", { numeric: !0, sensitivity: "variant" }), C = Object.freeze({
|
|
9
9
|
sortMode: "native",
|
|
10
10
|
directoriesFirst: !1,
|
|
11
11
|
selectionMode: "single",
|
|
@@ -17,7 +17,7 @@ const F = (e) => {
|
|
|
17
17
|
expandIcons: !0,
|
|
18
18
|
directoryIcons: !0,
|
|
19
19
|
fileIcons: !0
|
|
20
|
-
}),
|
|
20
|
+
}), se = [!0, !1], ie = (e, t) => t ? e.settingOn : e.settingOff, g = (e, t) => ({ key: e, labelKey: t, values: se, formatValue: ie, requiresItemSelection: !1 }), p = Object.freeze([
|
|
21
21
|
{
|
|
22
22
|
key: "sortMode",
|
|
23
23
|
labelKey: "settingSortMode",
|
|
@@ -53,85 +53,85 @@ const F = (e) => {
|
|
|
53
53
|
g("expandIcons", "settingExpandIcons"),
|
|
54
54
|
g("directoryIcons", "settingDirectoryIcons"),
|
|
55
55
|
g("fileIcons", "settingFileIcons")
|
|
56
|
-
]),
|
|
56
|
+
]), We = (e) => e ? p : p.filter((t) => !t.requiresItemSelection), V = (e) => {
|
|
57
57
|
const t = p.find((r) => r.key === e);
|
|
58
58
|
if (t === void 0) throw new RangeError(`[markdown-explorer] no tree setting descriptor for ${e}`);
|
|
59
59
|
return t;
|
|
60
|
-
},
|
|
60
|
+
}, He = (e, t) => {
|
|
61
61
|
const r = V(t).values, n = r[(r.indexOf(e[t]) + 1) % r.length];
|
|
62
62
|
return { ...e, [t]: n };
|
|
63
|
-
},
|
|
64
|
-
if (e === null || typeof e != "object" || Array.isArray(e)) return
|
|
63
|
+
}, qe = (e, t, r) => V(r).formatValue(e, t[r]), U = 2, z = Object.freeze({}), v = (e, t) => Object.freeze(Object.fromEntries(p.filter((r) => t(r, e[r.key])).map((r) => [r.key, e[r.key]]))), Be = (e) => {
|
|
64
|
+
if (e === null || typeof e != "object" || Array.isArray(e)) return z;
|
|
65
65
|
const t = e;
|
|
66
|
-
return t.version !== U || t.settings === null || typeof t.settings != "object" || Array.isArray(t.settings) ?
|
|
67
|
-
},
|
|
68
|
-
const r =
|
|
66
|
+
return t.version !== U || t.settings === null || typeof t.settings != "object" || Array.isArray(t.settings) ? z : v(t.settings, (r, n) => r.values.includes(n));
|
|
67
|
+
}, Ke = (e, t) => {
|
|
68
|
+
const r = v(t, (n, o) => o !== void 0 && o !== e[n.key]);
|
|
69
69
|
return Object.keys(r).length === 0 ? e : Object.freeze({ ...e, ...r });
|
|
70
|
-
},
|
|
70
|
+
}, Ze = (e, t, r, n) => v({ ...e, [t]: r }, (o, s) => s !== void 0 && !(o.key === t && s === n[t])), Ye = (e) => JSON.stringify({ version: U, settings: e }), Qe = (e) => {
|
|
71
71
|
if (e.sortMode === "native" && !e.directoriesFirst) return;
|
|
72
72
|
const t = e.sortMode === "desc" ? -1 : 1;
|
|
73
73
|
return (r, n) => {
|
|
74
74
|
if (e.directoriesFirst && r.type !== n.type) return r.type === "directory" ? -1 : 1;
|
|
75
75
|
if (e.sortMode === "native") return 0;
|
|
76
|
-
const o =
|
|
77
|
-
return t * (o !== 0 ? o :
|
|
76
|
+
const o = P.compare(r.name, n.name);
|
|
77
|
+
return t * (o !== 0 ? o : P.compare(r.path, n.path));
|
|
78
78
|
};
|
|
79
|
-
}, w = (1 + Math.sqrt(5)) / 2,
|
|
79
|
+
}, w = (1 + Math.sqrt(5)) / 2, et = 100 / w ** 3, tt = 100 / w ** 4, G = 100 / w ** 2, ae = 13, rt = 16, nt = Object.freeze({ gripThickness: 5, gripLength: 34, barThickness: 2, barLength: 21 }), le = Object.freeze([89, 144, 233, 377]), ot = 34, st = 44, it = 24, at = 1 / w, lt = 1 / w ** 3, ct = "40ch", ce = (e) => {
|
|
80
80
|
if (!Number.isFinite(e) || e <= 0)
|
|
81
81
|
throw new RangeError(`[markdown-explorer] rootFontPixels must be a finite number > 0; got ${String(e)}`);
|
|
82
|
-
},
|
|
82
|
+
}, de = (e) => (ce(e), ae * e), dt = (e) => de(e) * w ** 2, mt = 233, ft = le[0], L = (e, t) => {
|
|
83
83
|
if (!Number.isFinite(t) || t < 0)
|
|
84
84
|
throw new RangeError(`[markdown-explorer] ${e} must be a finite number >= 0; got ${String(t)}`);
|
|
85
|
-
},
|
|
85
|
+
}, me = ({ trackInlineSize: e, gap: t, minColumnInlineSize: r, logicalColumns: n }) => {
|
|
86
86
|
if (L("trackInlineSize", e), L("gap", t), !Number.isFinite(r) || r <= 0)
|
|
87
87
|
throw new RangeError(`[markdown-explorer] minColumnInlineSize must be a finite number > 0; got ${String(r)}`);
|
|
88
88
|
if (!Number.isInteger(n) || n < 1)
|
|
89
89
|
throw new RangeError(`[markdown-explorer] logicalColumns must be a positive integer; got ${String(n)}`);
|
|
90
90
|
const o = Math.floor((e + t) / (r + t));
|
|
91
91
|
return Math.min(n, Math.max(1, o));
|
|
92
|
-
},
|
|
92
|
+
}, ut = (e, t) => {
|
|
93
93
|
const { trackInlineSize: r, gap: n, minColumnInlineSize: o, logicalColumns: s } = t;
|
|
94
94
|
if (!([r, n, o].every(Number.isFinite) && r > 0 && n >= 0 && o > 0)) return e;
|
|
95
|
-
const i =
|
|
95
|
+
const i = me(t);
|
|
96
96
|
if (e === null || i === e) return i;
|
|
97
|
-
const
|
|
98
|
-
if (i >
|
|
99
|
-
const
|
|
100
|
-
return r >=
|
|
97
|
+
const d = Math.min(s, Math.max(1, e));
|
|
98
|
+
if (i > d) {
|
|
99
|
+
const k = (d + 1) * o + d * n + n / w;
|
|
100
|
+
return r >= k ? i : d;
|
|
101
101
|
}
|
|
102
|
-
return r >=
|
|
103
|
-
},
|
|
102
|
+
return r >= d * o + (d - 1) * n ? d : i;
|
|
103
|
+
}, gt = (e, t) => {
|
|
104
104
|
if (!(Number.isInteger(e) && Number.isInteger(t)) || t < 1 || t > e)
|
|
105
105
|
throw new RangeError(`[markdown-explorer] visible columns must be an integer in 1..${String(e)}; got ${String(t)}`);
|
|
106
106
|
return Array.from({ length: t }, (r, n) => [Math.floor(n * e / t), Math.floor((n + 1) * e / t)]);
|
|
107
|
-
},
|
|
108
|
-
if (typeof e != "string" || !
|
|
107
|
+
}, fe = 31536e3, ue = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u, ge = (e) => {
|
|
108
|
+
if (typeof e != "string" || !ue.test(e))
|
|
109
109
|
throw new RangeError(`[markdown-explorer] settingsCookie must be a cookie-name token; got ${JSON.stringify(e)}`);
|
|
110
|
-
},
|
|
110
|
+
}, j = (e) => typeof e == "number" && Number.isFinite(e) && e > 0 && e <= G, we = (e, t) => {
|
|
111
111
|
if (e === null || typeof e != "object" || Array.isArray(e)) return {};
|
|
112
112
|
const r = e, { treeExplorer: n, multiExplorer: o, style: s, align: a } = r;
|
|
113
113
|
return {
|
|
114
|
-
...
|
|
115
|
-
...
|
|
114
|
+
...j(n) ? { treeExplorer: n } : {},
|
|
115
|
+
...j(o) ? { multiExplorer: o } : {},
|
|
116
116
|
...typeof s == "string" && t.includes(s) ? { style: s } : {},
|
|
117
|
-
...typeof a == "string" &&
|
|
117
|
+
...typeof a == "string" && x.includes(a) ? { align: a } : {}
|
|
118
118
|
};
|
|
119
|
-
},
|
|
119
|
+
}, wt = (e, t) => {
|
|
120
120
|
if (e !== null)
|
|
121
121
|
for (const r of e.split(";")) {
|
|
122
122
|
const n = r.indexOf("=");
|
|
123
123
|
if (!(n < 0) && r.slice(0, n).trim() === t)
|
|
124
124
|
return r.slice(n + 1).trim();
|
|
125
125
|
}
|
|
126
|
-
},
|
|
126
|
+
}, pt = (e, t) => {
|
|
127
127
|
if (e === void 0 || e === "") return {};
|
|
128
128
|
try {
|
|
129
|
-
return
|
|
129
|
+
return we(JSON.parse(decodeURIComponent(e)), t);
|
|
130
130
|
} catch {
|
|
131
131
|
return {};
|
|
132
132
|
}
|
|
133
|
-
}, O = 100,
|
|
134
|
-
const t = (r) => Math.min(
|
|
133
|
+
}, O = 100, pe = Math.floor(G * O) / O, he = (e) => {
|
|
134
|
+
const t = (r) => Math.min(pe, Math.max(1, Math.round(r * O)) / O);
|
|
135
135
|
return encodeURIComponent(
|
|
136
136
|
JSON.stringify({
|
|
137
137
|
...e.treeExplorer === void 0 ? {} : { treeExplorer: t(e.treeExplorer) },
|
|
@@ -140,41 +140,45 @@ const F = (e) => {
|
|
|
140
140
|
...e.align === void 0 ? {} : { align: e.align }
|
|
141
141
|
})
|
|
142
142
|
);
|
|
143
|
-
},
|
|
143
|
+
}, ht = (e, t, r) => `${e}=${he(t)}; Path=/; Max-Age=${String(fe)}; SameSite=Lax${r ? "; Secure" : ""}`, M = Object.freeze({ tree: "tree", multi: "multi", single: "single" }), Ee = Object.freeze({ default: 12, min: 1, max: 64 }), Se = Object.freeze({ default: 4, min: 1, max: 6 }), ye = Object.freeze({ default: 500, min: 1, max: 1e4 }), be = Object.freeze({ default: 16, min: 1, max: 64 }), xe = /^\/(?:[A-Za-z0-9._~-]+\/)*[A-Za-z0-9._~-]+$/u, Oe = /^[A-Za-z0-9][A-Za-z0-9_-]*$/u, ke = /^[a-z0-9][a-z0-9-]*$/u, Re = /^(?=.{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) => {
|
|
144
144
|
if (typeof t != "string") throw new TypeError(`[markdown-explorer] ${e} must be a string; got ${typeof t}`);
|
|
145
|
-
if (!
|
|
145
|
+
if (!xe.test(t) || t.split("/").some((r) => r === "." || r === ".."))
|
|
146
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)}`);
|
|
147
|
-
},
|
|
147
|
+
}, c = (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" ? $(e) ? "a plain object" : `a non-plain object (${Object.prototype.toString.call(e)})` : String(e), S = (e, t, r) => {
|
|
148
148
|
if (t === void 0) return [];
|
|
149
|
-
if (
|
|
149
|
+
if (!$(t)) throw new TypeError(`[markdown-explorer] ${e} must be a plain object; got ${c(t)}`);
|
|
150
150
|
const n = Object.entries(t);
|
|
151
151
|
for (const [o] of n)
|
|
152
152
|
if (!r.includes(o)) throw new RangeError(`[markdown-explorer] ${e}.${o} is not an option; expected ${r.join(", ")}`);
|
|
153
153
|
return n.filter(([, o]) => o !== void 0);
|
|
154
154
|
}, _e = (e) => {
|
|
155
|
-
const t = { ...
|
|
156
|
-
for (const [r, n] of S("views", e, Object.keys(
|
|
155
|
+
const t = { ...M };
|
|
156
|
+
for (const [r, n] of S("views", e, Object.keys(M))) t[r] = n;
|
|
157
157
|
for (const [r, n] of Object.entries(t))
|
|
158
|
-
if (typeof n != "string" || !
|
|
158
|
+
if (typeof n != "string" || !Oe.test(n))
|
|
159
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)}`);
|
|
160
160
|
return Object.freeze(t);
|
|
161
|
-
},
|
|
161
|
+
}, b = (e, t, r) => {
|
|
162
162
|
if (t === void 0) return r.default;
|
|
163
163
|
if (typeof t != "number" || !Number.isInteger(t) || t < r.min || t > r.max)
|
|
164
|
-
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 ${c(t)}`);
|
|
165
165
|
return t;
|
|
166
|
-
},
|
|
167
|
-
const
|
|
168
|
-
if (
|
|
169
|
-
const
|
|
170
|
-
if (!Array.isArray(
|
|
171
|
-
for (const
|
|
172
|
-
if (!Q(
|
|
173
|
-
const
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
166
|
+
}, Te = (e, t) => {
|
|
167
|
+
const r = new Map(S("embeds", e, ["providers", "linkCards", "linkCardSize"]));
|
|
168
|
+
if (r.size === 0) return Y;
|
|
169
|
+
const n = r.has("providers") ? r.get("providers") : [];
|
|
170
|
+
if (!Array.isArray(n)) throw new RangeError(`[markdown-explorer] embeds.providers must be an array of provider ids; got ${c(n)}`);
|
|
171
|
+
for (const i of n)
|
|
172
|
+
if (!Q(i)) throw new RangeError(`[markdown-explorer] embeds.providers must hold only ${ee.join(", ")}; got ${c(i)}`);
|
|
173
|
+
const o = r.has("linkCards") ? r.get("linkCards") : !1;
|
|
174
|
+
if (typeof o != "boolean") throw new RangeError(`[markdown-explorer] embeds.linkCards must be a boolean; got ${c(o)}`);
|
|
175
|
+
const s = { providers: Object.freeze([...new Set(n)]), linkCardEndpoint: o ? oe(t) : null };
|
|
176
|
+
if (!r.has("linkCardSize")) return Object.freeze(s);
|
|
177
|
+
const a = r.get("linkCardSize");
|
|
178
|
+
if (!te(a)) throw new RangeError(`[markdown-explorer] embeds.linkCardSize must be one of ${re.join(", ")}; got ${c(a)}`);
|
|
179
|
+
if (!o) throw new RangeError(`[markdown-explorer] embeds.linkCardSize needs embeds.linkCards: true; got linkCardSize ${c(a)} with linkCards ${c(o)}`);
|
|
180
|
+
return Object.freeze({ ...s, linkCardSize: a });
|
|
181
|
+
}, Ne = (e) => {
|
|
178
182
|
const t = new Map(
|
|
179
183
|
S(
|
|
180
184
|
"defaultTreeSettings",
|
|
@@ -182,16 +186,16 @@ const F = (e) => {
|
|
|
182
186
|
p.map((n) => n.key)
|
|
183
187
|
)
|
|
184
188
|
);
|
|
185
|
-
if (t.size === 0) return
|
|
186
|
-
const r = { ...
|
|
189
|
+
if (t.size === 0) return C;
|
|
190
|
+
const r = { ...C };
|
|
187
191
|
for (const n of p) {
|
|
188
192
|
if (!t.has(n.key)) continue;
|
|
189
193
|
const o = t.get(n.key), s = n.values;
|
|
190
|
-
if (!s.includes(o)) throw new RangeError(`[markdown-explorer] defaultTreeSettings.${n.key} must be one of ${s.map(
|
|
194
|
+
if (!s.includes(o)) throw new RangeError(`[markdown-explorer] defaultTreeSettings.${n.key} must be one of ${s.map(c).join(", ")}; got ${c(o)}`);
|
|
191
195
|
r[n.key] = o;
|
|
192
196
|
}
|
|
193
197
|
return Object.freeze(r);
|
|
194
|
-
},
|
|
198
|
+
}, Ae = (e) => {
|
|
195
199
|
if (e === null || typeof e != "object") throw new TypeError("[markdown-explorer] the explorer configuration must be an object");
|
|
196
200
|
D("basePath", e.basePath), D("dataPath", e.dataPath);
|
|
197
201
|
const t = _e(e.views);
|
|
@@ -203,11 +207,11 @@ const F = (e) => {
|
|
|
203
207
|
if (i === t.tree || i === t.multi || i === t.single)
|
|
204
208
|
throw new RangeError(`[markdown-explorer] dataPath must not start with a view slug under basePath; got ${JSON.stringify(e.dataPath)}`);
|
|
205
209
|
}
|
|
206
|
-
|
|
210
|
+
ge(e.settingsCookie);
|
|
207
211
|
const r = e.iframeHosts ?? [];
|
|
208
|
-
if (!Array.isArray(r) || r.some((i) => typeof i != "string" || !
|
|
212
|
+
if (!Array.isArray(r) || r.some((i) => typeof i != "string" || !Re.test(i)))
|
|
209
213
|
throw new RangeError(`[markdown-explorer] iframeHosts must be lowercase host names without scheme, port or path; got ${JSON.stringify(r)}`);
|
|
210
|
-
const n = Object.fromEntries(S("multiView", e.multiView, ["maxPanels", "columns"])), o = Object.fromEntries(S("expandAll", e.expandAll, ["maxFolders", "maxDepth"])), s = e.documentStyles ??
|
|
214
|
+
const n = Object.fromEntries(S("multiView", e.multiView, ["maxPanels", "columns"])), o = Object.fromEntries(S("expandAll", e.expandAll, ["maxFolders", "maxDepth"])), s = e.documentStyles ?? ne;
|
|
211
215
|
if (!Array.isArray(s) || s.length === 0) throw new RangeError("[markdown-explorer] documentStyles must be a non-empty array");
|
|
212
216
|
const a = /* @__PURE__ */ new Set();
|
|
213
217
|
for (const i of s) {
|
|
@@ -222,26 +226,35 @@ const F = (e) => {
|
|
|
222
226
|
settingsCookie: e.settingsCookie,
|
|
223
227
|
views: t,
|
|
224
228
|
multiView: Object.freeze({
|
|
225
|
-
maxPanels:
|
|
226
|
-
columns:
|
|
229
|
+
maxPanels: b("multiView.maxPanels", n.maxPanels, Ee),
|
|
230
|
+
columns: b("multiView.columns", n.columns, Se)
|
|
227
231
|
}),
|
|
228
232
|
expandAll: Object.freeze({
|
|
229
|
-
maxFolders:
|
|
230
|
-
maxDepth:
|
|
233
|
+
maxFolders: b("expandAll.maxFolders", o.maxFolders, ye),
|
|
234
|
+
maxDepth: b("expandAll.maxDepth", o.maxDepth, be)
|
|
231
235
|
}),
|
|
232
236
|
documentStyles: Object.freeze(s.map((i) => Object.freeze({ name: i.name, className: i.className }))),
|
|
233
237
|
iframeHosts: Object.freeze([...new Set(r)]),
|
|
234
|
-
embeds:
|
|
235
|
-
defaultTreeSettings:
|
|
238
|
+
embeds: Te(e.embeds, e.dataPath),
|
|
239
|
+
defaultTreeSettings: Ne(e.defaultTreeSettings)
|
|
236
240
|
});
|
|
237
|
-
},
|
|
238
|
-
|
|
239
|
-
if (
|
|
241
|
+
}, Et = (e) => {
|
|
242
|
+
const t = e.embeds;
|
|
243
|
+
if (!$(t)) throw new TypeError(`[markdown-explorer] config.embeds must be the embeds defineExplorerConfig resolved; got ${c(t)}`);
|
|
244
|
+
if (Object.hasOwn(t, "linkCards"))
|
|
245
|
+
throw new RangeError(`[markdown-explorer] config.embeds.linkCards is an option of defineExplorerConfig, not a key of the embeds it resolves; pass the option to defineExplorerConfig (got linkCards ${c(t.linkCards)})`);
|
|
246
|
+
const { linkCardEndpoint: r, ...n } = t, o = Ae({ ...e, embeds: { ...n, linkCards: r !== null } });
|
|
247
|
+
if (o.embeds.linkCardEndpoint !== r)
|
|
248
|
+
throw new RangeError(`[markdown-explorer] config.embeds.linkCardEndpoint must be ${c(o.embeds.linkCardEndpoint)} (the data route's link-card path) or null; got ${c(r)}`);
|
|
249
|
+
return o;
|
|
250
|
+
}, Ie = (e) => typeof e == "string" && ke.test(e), St = (e, t) => {
|
|
251
|
+
if (e === null || typeof e != "object") throw new TypeError(`[markdown-explorer] withExplorerSources needs the configuration of defineExplorerConfig; got ${c(e)}`);
|
|
252
|
+
if (!Array.isArray(t) || t.length === 0) throw new RangeError(`[markdown-explorer] sourceIds must be a non-empty array; got ${c(t)}`);
|
|
240
253
|
for (const r of t)
|
|
241
|
-
if (!
|
|
254
|
+
if (!Ie(r)) throw new RangeError(`[markdown-explorer] each source id must use lowercase letters, digits and "-" and start with a letter or digit; got ${c(r)}`);
|
|
242
255
|
if (new Set(t).size !== t.length) throw new RangeError(`[markdown-explorer] source ids must be unique; got ${JSON.stringify(t)}`);
|
|
243
256
|
return Object.freeze({ ...e, sourceIds: Object.freeze([...t]) });
|
|
244
|
-
},
|
|
257
|
+
}, yt = (e) => e.documentStyles.map((t) => t.name), l = Object.freeze({
|
|
245
258
|
source: "source",
|
|
246
259
|
doc: "doc",
|
|
247
260
|
maximized: "maximized",
|
|
@@ -253,143 +266,144 @@ const F = (e) => {
|
|
|
253
266
|
padding: "padding",
|
|
254
267
|
width: "width",
|
|
255
268
|
maxWidth: "maxWidth"
|
|
256
|
-
}),
|
|
269
|
+
}), F = ".data", J = 256, X = /^\d+(?:\.\d+)?$/u, A = /^\d+(?:\.\d+)?(?:px|rem|em|ch|vw|%)$/u, W = Object.freeze(["showToc", "showStyle", "showAlign"]), $e = (e) => {
|
|
257
270
|
const t = encodeURIComponent(e.replaceAll("%", "%25"));
|
|
258
|
-
return t.endsWith(
|
|
259
|
-
},
|
|
271
|
+
return t.endsWith(F) ? `${t.slice(0, -F.length)}%2Edata` : t;
|
|
272
|
+
}, ve = (e) => e.replaceAll("%25", "%"), H = (e) => {
|
|
260
273
|
const { sourceIds: t } = e;
|
|
261
274
|
if (t === void 0) throw new TypeError("[markdown-explorer] the configuration has no source ids; join the server's sources with withExplorerSources(config, sourceIds)");
|
|
262
275
|
return t;
|
|
263
|
-
},
|
|
264
|
-
const n = r.getAll(
|
|
276
|
+
}, Pe = (e, t, r) => {
|
|
277
|
+
const n = r.getAll(l.source);
|
|
265
278
|
if (n.length === 0) return t;
|
|
266
279
|
const [o] = n;
|
|
267
280
|
return n.length > 1 || o === void 0 || o === t || !e.includes(o) ? null : o;
|
|
268
|
-
},
|
|
269
|
-
const r = t.get(
|
|
281
|
+
}, Ce = (e, t) => {
|
|
282
|
+
const r = t.get(l.style), n = t.get(l.align);
|
|
270
283
|
return {
|
|
271
284
|
...r !== null && e.documentStyles.some((o) => o.name === r) ? { style: r } : {},
|
|
272
|
-
...n !== null &&
|
|
285
|
+
...n !== null && x.includes(n) ? { align: n } : {}
|
|
273
286
|
};
|
|
274
|
-
}, q = (e) => Number.isFinite(e) && e >= 0 && e <= J && X.test(String(e)),
|
|
275
|
-
const t = e.get(
|
|
287
|
+
}, q = (e) => Number.isFinite(e) && e >= 0 && e <= J && X.test(String(e)), ze = (e) => {
|
|
288
|
+
const t = e.get(l.padding), r = t !== null && X.test(t) ? Number(t) : Number.NaN, n = e.get(l.width), o = e.get(l.maxWidth);
|
|
276
289
|
return {
|
|
277
|
-
...e.get(
|
|
278
|
-
...e.get(
|
|
279
|
-
...e.get(
|
|
290
|
+
...e.get(l.showToc) === "false" ? { showToc: !1 } : {},
|
|
291
|
+
...e.get(l.showStyle) === "false" ? { showStyle: !1 } : {},
|
|
292
|
+
...e.get(l.showAlign) === "false" ? { showAlign: !1 } : {},
|
|
280
293
|
...q(r) ? { padding: r } : {},
|
|
281
|
-
...n !== null &&
|
|
282
|
-
...o !== null &&
|
|
294
|
+
...n !== null && A.test(n) ? { width: n } : {},
|
|
295
|
+
...o !== null && A.test(o) ? { maxWidth: o } : {}
|
|
283
296
|
};
|
|
284
|
-
},
|
|
297
|
+
}, Le = (e, t) => [...new Set(t.filter(I))].slice(0, e.multiView.maxPanels), je = (e, t, r) => {
|
|
285
298
|
for (const n of t) B(n);
|
|
286
299
|
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`);
|
|
287
300
|
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)}`);
|
|
288
301
|
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))}`);
|
|
289
302
|
}, B = (e) => {
|
|
290
|
-
if (!
|
|
303
|
+
if (!I(e)) throw new RangeError(`[markdown-explorer] not an acceptable document path: ${JSON.stringify(String(e).slice(0, 80))}`);
|
|
291
304
|
return e;
|
|
292
|
-
},
|
|
305
|
+
}, Me = (e, t) => {
|
|
293
306
|
if (t.style !== void 0 && !e.documentStyles.some((r) => r.name === t.style))
|
|
294
307
|
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)}`);
|
|
295
|
-
if (t.align !== void 0 && !
|
|
296
|
-
throw new RangeError(`[markdown-explorer] overrides.align must be one of ${
|
|
297
|
-
},
|
|
308
|
+
if (t.align !== void 0 && !x.includes(t.align))
|
|
309
|
+
throw new RangeError(`[markdown-explorer] overrides.align must be one of ${x.join(", ")}; got ${JSON.stringify(t.align)}`);
|
|
310
|
+
}, De = (e) => {
|
|
298
311
|
for (const t of W)
|
|
299
312
|
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])}`);
|
|
300
313
|
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)}`);
|
|
301
314
|
for (const t of ["width", "maxWidth"]) {
|
|
302
315
|
const r = e[t];
|
|
303
|
-
if (r !== void 0 && !
|
|
316
|
+
if (r !== void 0 && !A.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)}`);
|
|
304
317
|
}
|
|
305
|
-
},
|
|
318
|
+
}, Fe = (e, t) => {
|
|
306
319
|
const r = new URLSearchParams();
|
|
307
320
|
let n = `${e.basePath}/${e.views[t.view]}`;
|
|
308
321
|
if (t.view === "multi") {
|
|
309
322
|
const s = t.docs ?? [], a = t.maximized ?? null;
|
|
310
|
-
|
|
311
|
-
for (const i of s) r.append(
|
|
312
|
-
a !== null && r.set(
|
|
313
|
-
} else t.doc !== void 0 && t.doc !== null && (n += `/${
|
|
323
|
+
je(e, s, a);
|
|
324
|
+
for (const i of s) r.append(l.doc, i);
|
|
325
|
+
a !== null && r.set(l.maximized, a);
|
|
326
|
+
} else t.doc !== void 0 && t.doc !== null && (n += `/${$e(B(t.doc))}`);
|
|
314
327
|
if (t.source !== void 0) {
|
|
315
328
|
const s = H(e);
|
|
316
329
|
if (!s.includes(t.source)) throw new RangeError(`[markdown-explorer] unknown source ${JSON.stringify(t.source)}; expected one of ${s.join(", ")}`);
|
|
317
|
-
t.source !== s[0] && r.set(
|
|
330
|
+
t.source !== s[0] && r.set(l.source, t.source);
|
|
318
331
|
}
|
|
319
|
-
if (t.view !== "multi" && t.overrides !== void 0 && (
|
|
332
|
+
if (t.view !== "multi" && t.overrides !== void 0 && (Me(e, t.overrides), t.overrides.style !== void 0 && r.set(l.style, t.overrides.style), t.overrides.align !== void 0 && r.set(l.align, t.overrides.align)), t.view === "single" && t.embed !== void 0) {
|
|
320
333
|
const { embed: s } = t;
|
|
321
|
-
|
|
322
|
-
for (const a of W) s[a] === !1 && r.set(
|
|
323
|
-
s.padding !== void 0 && r.set(
|
|
334
|
+
De(s);
|
|
335
|
+
for (const a of W) s[a] === !1 && r.set(l[a], "false");
|
|
336
|
+
s.padding !== void 0 && r.set(l.padding, String(s.padding)), s.width !== void 0 && r.set(l.width, s.width), s.maxWidth !== void 0 && r.set(l.maxWidth, s.maxWidth);
|
|
324
337
|
}
|
|
325
338
|
const o = r.toString();
|
|
326
339
|
return o === "" ? n : `${n}?${o}`;
|
|
327
|
-
},
|
|
340
|
+
}, Ve = (e, t) => Object.keys(e.views).find((r) => e.views[r] === t), bt = (e, t, r) => {
|
|
328
341
|
const n = H(e), [o] = n;
|
|
329
342
|
if (o === void 0) throw new RangeError("[markdown-explorer] the configuration has no source");
|
|
330
|
-
const s =
|
|
331
|
-
if (t === void 0 || t === "") return
|
|
332
|
-
const h = t.indexOf("/"),
|
|
333
|
-
if (f === void 0) return
|
|
343
|
+
const s = Pe(n, o, r), a = s === null ? o : s, i = (m) => ({ kind: "redirect", href: Fe(e, m), location: m }), d = () => i({ view: "tree", source: a, doc: null, overrides: {} });
|
|
344
|
+
if (t === void 0 || t === "") return d();
|
|
345
|
+
const h = t.indexOf("/"), k = h < 0 ? t : t.slice(0, h), R = h < 0 ? null : t.slice(h + 1), f = Ve(e, k);
|
|
346
|
+
if (f === void 0) return d();
|
|
334
347
|
if (f === "multi") {
|
|
335
|
-
const m = r.getAll(
|
|
336
|
-
return R === null && s !== null && E.length === m.length && E.every((K, Z) => K === m[Z]) && (
|
|
348
|
+
const m = r.getAll(l.doc), E = Le(e, m), _ = r.getAll(l.maximized), [T] = _, N = _.length === 1 && T !== void 0 && E.includes(T) ? T : null;
|
|
349
|
+
return R === null && s !== null && E.length === m.length && E.every((K, Z) => K === m[Z]) && (_.length === 0 || N !== null) ? { kind: "location", location: { view: "multi", source: a, docs: E, maximized: N } } : i({ view: "multi", source: a, docs: E, maximized: N });
|
|
337
350
|
}
|
|
338
|
-
const u = R === null ? null :
|
|
339
|
-
if (u !== null && !
|
|
340
|
-
const y =
|
|
351
|
+
const u = R === null ? null : ve(R);
|
|
352
|
+
if (u !== null && !I(u)) return d();
|
|
353
|
+
const y = Ce(e, r);
|
|
341
354
|
if (f === "single") {
|
|
342
|
-
if (u === null) return
|
|
343
|
-
const m =
|
|
355
|
+
if (u === null) return d();
|
|
356
|
+
const m = ze(r);
|
|
344
357
|
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 } };
|
|
345
358
|
}
|
|
346
359
|
return s === null ? i({ view: f, source: a, doc: u, overrides: y }) : { kind: "location", location: { view: f, source: a, doc: u, overrides: y } };
|
|
347
360
|
};
|
|
348
361
|
export {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
362
|
+
rt as A,
|
|
363
|
+
Ye as B,
|
|
364
|
+
ot as C,
|
|
365
|
+
z as D,
|
|
366
|
+
mt as E,
|
|
367
|
+
it as F,
|
|
355
368
|
w as G,
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
369
|
+
Be as H,
|
|
370
|
+
ht as I,
|
|
371
|
+
ct as J,
|
|
372
|
+
C as K,
|
|
373
|
+
M as L,
|
|
374
|
+
be as M,
|
|
375
|
+
P as N,
|
|
376
|
+
ye as O,
|
|
377
|
+
at as P,
|
|
378
|
+
ae as Q,
|
|
379
|
+
Se as R,
|
|
380
|
+
nt as S,
|
|
381
|
+
Ee as T,
|
|
382
|
+
Ae as U,
|
|
383
|
+
bt as a,
|
|
384
|
+
wt as b,
|
|
385
|
+
Le as c,
|
|
386
|
+
yt as d,
|
|
387
|
+
Fe as e,
|
|
388
|
+
$ as f,
|
|
389
|
+
gt as g,
|
|
390
|
+
ut as h,
|
|
391
|
+
Ie as i,
|
|
392
|
+
lt as j,
|
|
393
|
+
Qe as k,
|
|
394
|
+
qe as l,
|
|
395
|
+
dt as m,
|
|
396
|
+
de as n,
|
|
383
397
|
G as o,
|
|
384
|
-
|
|
385
|
-
|
|
398
|
+
pt as p,
|
|
399
|
+
et as q,
|
|
386
400
|
Et as r,
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
401
|
+
tt as s,
|
|
402
|
+
st as t,
|
|
403
|
+
ft as u,
|
|
404
|
+
We as v,
|
|
405
|
+
St as w,
|
|
406
|
+
Ze as x,
|
|
407
|
+
He as y,
|
|
408
|
+
Ke as z
|
|
395
409
|
};
|
package/dist/sanitizeWorker.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
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();
|
|
1
|
+
"use strict";const te=require("node:worker_threads"),_=require("parse5"),R=require("@aiquants/markdown/embeds"),S=require("isomorphic-dompurify"),F=require("./dataRoute-B9Wk-G7A.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();
|
package/dist/sanitizeWorker.js
CHANGED
|
@@ -2,7 +2,7 @@ import { parentPort as ee } from "node:worker_threads";
|
|
|
2
2
|
import { defaultTreeAdapter as b, parse as te, html as re } from "parse5";
|
|
3
3
|
import { allowedFrameUrlOf as ne, reduceFrameFeatures as oe, EMBED_FRAME_REFERRER_POLICIES as se, EMBED_LINK_ATTRIBUTE as H, placeholderLinkOf as ae } from "@aiquants/markdown/embeds";
|
|
4
4
|
import S from "isomorphic-dompurify";
|
|
5
|
-
import { i as ie, e as ce } from "./dataRoute-
|
|
5
|
+
import { i as ie, e as ce } from "./dataRoute-zUX-oR9j.js";
|
|
6
6
|
const F = 512, le = 4096, G = 1024, j = /* @__PURE__ */ Symbol("placement"), V = 2, ue = 3, fe = /* @__PURE__ */ new Set(["html", "head", "body"]), w = 0, D = 1, M = 2, W = 3, z = 4, O = 5, k = 6, N = 7, Q = 8, I = 9, $ = 10, _ = -1, de = 0, pe = 1, Ee = 2, me = 3, he = 4, Te = 5, K = 6, Ae = 7, ge = (t) => {
|
|
7
7
|
switch (t) {
|
|
8
8
|
case 9:
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ExplorerAuthentication } from "./ports.cjs";
|
|
1
|
+
import { ExplorerAuthentication, ExplorerAuthenticationMode } from "./ports.cjs";
|
|
2
2
|
export type AnonymousPrincipal = {
|
|
3
3
|
readonly kind: "anonymous";
|
|
4
4
|
};
|
|
5
5
|
export type AnonymousAccess = {
|
|
6
|
-
readonly authenticate: (request: Request) => Promise<ExplorerAuthentication<AnonymousPrincipal>>;
|
|
6
|
+
readonly authenticate: (request: Request, mode: ExplorerAuthenticationMode) => Promise<ExplorerAuthentication<AnonymousPrincipal>>;
|
|
7
7
|
readonly principalKey: (principal: AnonymousPrincipal) => string;
|
|
8
8
|
readonly signedOutPage: (request: Request, headers: Headers) => Response;
|
|
9
9
|
};
|