@ai-matrx/print 0.8.7 → 0.8.9
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 +51 -0
- package/dist/document.cjs +256 -8
- package/dist/document.cjs.map +1 -1
- package/dist/document.d.cts +10 -2
- package/dist/document.d.ts +10 -2
- package/dist/document.js +256 -8
- package/dist/document.js.map +1 -1
- package/dist/markdown-html.cjs +4207 -0
- package/dist/markdown-html.cjs.map +1 -0
- package/dist/markdown-html.d.cts +87 -0
- package/dist/markdown-html.d.ts +87 -0
- package/dist/markdown-html.js +4176 -0
- package/dist/markdown-html.js.map +1 -0
- package/dist/markdown.cjs +146 -36
- package/dist/markdown.cjs.map +1 -1
- package/dist/markdown.js +146 -36
- package/dist/markdown.js.map +1 -1
- package/dist/safe-html.cjs +299 -0
- package/dist/safe-html.cjs.map +1 -0
- package/dist/safe-html.d.cts +56 -0
- package/dist/safe-html.d.ts +56 -0
- package/dist/safe-html.js +278 -0
- package/dist/safe-html.js.map +1 -0
- package/package.json +27 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.9
|
|
4
|
+
### Unreleased
|
|
5
|
+
|
|
6
|
+
- **New subpath `/markdown-html` — THE ONE Markdown→HTML engine** (Matrx
|
|
7
|
+
Alchemy CONTRACT §1.9, ALC-16). `createMarkdownHtmlEngine({ projectors })`
|
|
8
|
+
→ `parse` (content-ir marks every kind island, each becomes an atom
|
|
9
|
+
placeholder, the `/document` parse runs once), `fragment` (skins
|
|
10
|
+
`document` / `article` / `inline`; profiles `generic` / `google-docs` /
|
|
11
|
+
`word`), `document`, `plainText` (tables as TSV, TeX kept as `$…$`). Every
|
|
12
|
+
string ends in the allow-list. Optional asset resolver for private images
|
|
13
|
+
(an unresolved image becomes its description with a notice).
|
|
14
|
+
- **Security (LIST T26):** the display-math SVG the PDF writer draws is
|
|
15
|
+
allow-list sanitized (`MATH_SVG_SCHEMA`, `sanitizeMathSvg`) — TeX `\href`,
|
|
16
|
+
`\style`, `\class`, `\cssId`, `\bbox[…]`, `\mmlToken[…]` no longer reach it.
|
|
17
|
+
- `/safe-html`: `engineHtmlSchema`, `sanitizeEngineHtml`.
|
|
18
|
+
- `/document`: `documentToHtml` accepts `srcFor` and `transformBody`; an
|
|
19
|
+
image `srcFor` result now also passes the URL check (EPUB included).
|
|
20
|
+
|
|
21
|
+
- **Tables print by THE GFM rule** (`@ai-matrx/content-ir/source`, verify-RC-B4):
|
|
22
|
+
tables written without edge pipes print as tables; an escaped `\|` stays in
|
|
23
|
+
its cell by backslash parity and prints as `|`; a line that starts another
|
|
24
|
+
block (`- x`, `> y`) ends a pipe-less table; rows print at the header's width.
|
|
25
|
+
The private `splitTableRow` and the pipe-led-only table regex are gone.
|
|
26
|
+
Requires `@ai-matrx/content-ir` with `/source` table exports.
|
|
27
|
+
|
|
28
|
+
## 0.8.8
|
|
29
|
+
|
|
30
|
+
- **Security: every markdown→HTML path is allow-list sanitized.** The regex
|
|
31
|
+
converter (`markdownToHtml`, `markdownToArticleHtml`, and through them
|
|
32
|
+
`renderMarkdownDocument`, `markdownToHtmlForSkin`, `markdownToPdfBlob`) used a
|
|
33
|
+
block-list and let `<iframe>`, `<form>`, `<meta http-equiv=refresh>`,
|
|
34
|
+
`<object>`/`<embed>`, `<base>`, `<link>`, `<svg>`, `<textarea>`/`<select>` and
|
|
35
|
+
inline `style` through. Output now goes through `PRINT_HTML_SCHEMA`
|
|
36
|
+
(hast-util-sanitize's GitHub schema plus the converter's own `.matrx-*` /
|
|
37
|
+
`print-*` / `code-*` classes, table-cell `text-align`, the flashcard
|
|
38
|
+
checkbox + label, figures, page-break data/aria attributes). Sync, DOM-free.
|
|
39
|
+
- **Security (`/document`):** TeX `\href`, `\style`, `\class`, `\cssId`,
|
|
40
|
+
`\bbox[css]` and `\mmlToken[attrs]` no longer write `href`/`style` into the
|
|
41
|
+
exported MathML (`MATHML_SCHEMA`); a front-matter `header`/`footer` can no
|
|
42
|
+
longer close the document's `<style>` element.
|
|
43
|
+
- **New subpath `/safe-html`:** `sanitizeHtmlFragment`, `SAFE_HTML_SCHEMA`
|
|
44
|
+
(plain GitHub allow-list for email/CMS), `PRINT_HTML_SCHEMA`,
|
|
45
|
+
`sanitizePrintHtml`, `MATHML_SCHEMA`, `sanitizeMathml`.
|
|
46
|
+
- **Visible differences:** author raw-HTML classes outside the print
|
|
47
|
+
vocabulary are dropped (`<div class="note">` → `<div class="matrx-div">`);
|
|
48
|
+
author inline styles are dropped; HTML serialization is normalized (`<img …>`
|
|
49
|
+
not `<img … />`, text `>` and `"` literal instead of `>`/`"`) —
|
|
50
|
+
same rendered page.
|
|
51
|
+
- Consumer action: none — refresh to latest.
|
|
52
|
+
|
|
3
53
|
## 0.8.7
|
|
4
54
|
|
|
5
55
|
- **Fixed: hidden reasoning merged two paragraphs.** `removeThinkingContent`
|
|
@@ -583,3 +633,4 @@ originals die at the adoption swap):
|
|
|
583
633
|
defaults; the template registry is now immutable; the dev-time geometry
|
|
584
634
|
check no longer reads `process.env` bare (which would throw in browser
|
|
585
635
|
consumers).
|
|
636
|
+
|
package/dist/document.cjs
CHANGED
|
@@ -170,6 +170,249 @@ function contentColumnWidths(b, n, avail, measure, pad = 10) {
|
|
|
170
170
|
|
|
171
171
|
// src/document/math.ts
|
|
172
172
|
var import_source = require("@ai-matrx/content-ir/source");
|
|
173
|
+
|
|
174
|
+
// src/safe-html.ts
|
|
175
|
+
var import_hast_util_from_html = require("hast-util-from-html");
|
|
176
|
+
var import_hast_util_sanitize = require("hast-util-sanitize");
|
|
177
|
+
var import_hast_util_to_html = require("hast-util-to-html");
|
|
178
|
+
var STRIP_WITH_CONTENT = [
|
|
179
|
+
"script",
|
|
180
|
+
"style",
|
|
181
|
+
"noscript",
|
|
182
|
+
"template",
|
|
183
|
+
"iframe",
|
|
184
|
+
"object",
|
|
185
|
+
"embed",
|
|
186
|
+
"textarea",
|
|
187
|
+
"select",
|
|
188
|
+
"head",
|
|
189
|
+
"title"
|
|
190
|
+
];
|
|
191
|
+
var FORBIDDEN_TAGS = [
|
|
192
|
+
...STRIP_WITH_CONTENT,
|
|
193
|
+
"form",
|
|
194
|
+
"meta",
|
|
195
|
+
"base",
|
|
196
|
+
"link",
|
|
197
|
+
"frame",
|
|
198
|
+
"frameset",
|
|
199
|
+
"applet",
|
|
200
|
+
"button",
|
|
201
|
+
"svg",
|
|
202
|
+
"math"
|
|
203
|
+
];
|
|
204
|
+
var baseAttributes = import_hast_util_sanitize.defaultSchema.attributes ?? {};
|
|
205
|
+
var SAFE_HTML_SCHEMA = {
|
|
206
|
+
...import_hast_util_sanitize.defaultSchema,
|
|
207
|
+
tagNames: (import_hast_util_sanitize.defaultSchema.tagNames ?? []).filter((t) => !FORBIDDEN_TAGS.includes(t)),
|
|
208
|
+
strip: STRIP_WITH_CONTENT,
|
|
209
|
+
// Authored anchors keep their names; the GitHub `user-content-` rewrite
|
|
210
|
+
// would also break `<label for>` → `<input id>` pairs.
|
|
211
|
+
clobberPrefix: "",
|
|
212
|
+
clobber: []
|
|
213
|
+
};
|
|
214
|
+
var PRINT_CLASS = /^(?:(?:matrx|print|code|doc|language)-[\w-]*|inline-code|is-checked)$/;
|
|
215
|
+
function withPrintClasses(defs = []) {
|
|
216
|
+
let found = false;
|
|
217
|
+
const out = defs.map((d) => {
|
|
218
|
+
if (Array.isArray(d) && d[0] === "className") {
|
|
219
|
+
found = true;
|
|
220
|
+
return [...d, PRINT_CLASS];
|
|
221
|
+
}
|
|
222
|
+
return d;
|
|
223
|
+
});
|
|
224
|
+
return found ? out : [...out, ["className", PRINT_CLASS]];
|
|
225
|
+
}
|
|
226
|
+
var printAttributes = Object.fromEntries(
|
|
227
|
+
Object.entries(baseAttributes).map(([tag, defs]) => [tag, withPrintClasses(defs)])
|
|
228
|
+
);
|
|
229
|
+
var cellAlign = ["style", /^text-align:\s*(?:left|center|right);?$/];
|
|
230
|
+
var PRINT_HTML_SCHEMA = {
|
|
231
|
+
...SAFE_HTML_SCHEMA,
|
|
232
|
+
tagNames: [
|
|
233
|
+
.../* @__PURE__ */ new Set([...SAFE_HTML_SCHEMA.tagNames ?? [], "section", "figure", "figcaption", "label"])
|
|
234
|
+
],
|
|
235
|
+
attributes: {
|
|
236
|
+
...printAttributes,
|
|
237
|
+
"*": [
|
|
238
|
+
...baseAttributes["*"] ?? [],
|
|
239
|
+
["className", PRINT_CLASS],
|
|
240
|
+
"role",
|
|
241
|
+
"ariaLabel",
|
|
242
|
+
"ariaHidden",
|
|
243
|
+
"dataLabel",
|
|
244
|
+
"dataLanguage",
|
|
245
|
+
"dataArtifactType"
|
|
246
|
+
],
|
|
247
|
+
// Table-cell alignment is the one inline style the converter writes.
|
|
248
|
+
td: withPrintClasses([...baseAttributes["td"] ?? [], [...cellAlign]]),
|
|
249
|
+
th: withPrintClasses([...baseAttributes["th"] ?? [], [...cellAlign]]),
|
|
250
|
+
// The flashcard flip is a checkbox + label pair (GitHub forces `disabled`).
|
|
251
|
+
input: withPrintClasses([["type", "checkbox"], "checked"]),
|
|
252
|
+
label: withPrintClasses(["htmlFor"])
|
|
253
|
+
},
|
|
254
|
+
required: { input: { type: "checkbox" } },
|
|
255
|
+
protocols: {
|
|
256
|
+
...import_hast_util_sanitize.defaultSchema.protocols,
|
|
257
|
+
href: [...import_hast_util_sanitize.defaultSchema.protocols?.href ?? [], "tel"],
|
|
258
|
+
// Embedded images (`data:image/png;base64,…`) — an <img> never runs script.
|
|
259
|
+
src: [...import_hast_util_sanitize.defaultSchema.protocols?.src ?? [], "data"]
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
function sanitizeHtmlFragment(html, schema = SAFE_HTML_SCHEMA) {
|
|
263
|
+
if (!html) return "";
|
|
264
|
+
const tree = (0, import_hast_util_sanitize.sanitize)((0, import_hast_util_from_html.fromHtml)(html, { fragment: true }), schema);
|
|
265
|
+
return (0, import_hast_util_to_html.toHtml)(tree, { characterReferences: { useNamedReferences: true } });
|
|
266
|
+
}
|
|
267
|
+
var MATHML_TAGS = [
|
|
268
|
+
"math",
|
|
269
|
+
"maction",
|
|
270
|
+
"annotation",
|
|
271
|
+
"menclose",
|
|
272
|
+
"merror",
|
|
273
|
+
"mfrac",
|
|
274
|
+
"mglyph",
|
|
275
|
+
"mi",
|
|
276
|
+
"mlabeledtr",
|
|
277
|
+
"mmultiscripts",
|
|
278
|
+
"mn",
|
|
279
|
+
"mo",
|
|
280
|
+
"mover",
|
|
281
|
+
"mpadded",
|
|
282
|
+
"mphantom",
|
|
283
|
+
"mprescripts",
|
|
284
|
+
"none",
|
|
285
|
+
"mroot",
|
|
286
|
+
"mrow",
|
|
287
|
+
"ms",
|
|
288
|
+
"mspace",
|
|
289
|
+
"msqrt",
|
|
290
|
+
"mstyle",
|
|
291
|
+
"msub",
|
|
292
|
+
"msubsup",
|
|
293
|
+
"msup",
|
|
294
|
+
"mtable",
|
|
295
|
+
"mtd",
|
|
296
|
+
"mtext",
|
|
297
|
+
"mtr",
|
|
298
|
+
"munder",
|
|
299
|
+
"munderover",
|
|
300
|
+
"semantics"
|
|
301
|
+
];
|
|
302
|
+
var MATHML_ATTRIBUTES = [
|
|
303
|
+
"xmlns",
|
|
304
|
+
"display",
|
|
305
|
+
"displaystyle",
|
|
306
|
+
"mathvariant",
|
|
307
|
+
"mathsize",
|
|
308
|
+
"mathcolor",
|
|
309
|
+
"mathbackground",
|
|
310
|
+
"scriptlevel",
|
|
311
|
+
"dir",
|
|
312
|
+
"fence",
|
|
313
|
+
"form",
|
|
314
|
+
"largeop",
|
|
315
|
+
"lspace",
|
|
316
|
+
"rspace",
|
|
317
|
+
"movablelimits",
|
|
318
|
+
"separator",
|
|
319
|
+
"stretchy",
|
|
320
|
+
"symmetric",
|
|
321
|
+
"maxsize",
|
|
322
|
+
"minsize",
|
|
323
|
+
"accent",
|
|
324
|
+
"accentunder",
|
|
325
|
+
"align",
|
|
326
|
+
"columnalign",
|
|
327
|
+
"rowalign",
|
|
328
|
+
"columnspacing",
|
|
329
|
+
"rowspacing",
|
|
330
|
+
"columnlines",
|
|
331
|
+
"rowlines",
|
|
332
|
+
"frame",
|
|
333
|
+
"framespacing",
|
|
334
|
+
"equalrows",
|
|
335
|
+
"equalcolumns",
|
|
336
|
+
"linethickness",
|
|
337
|
+
"numalign",
|
|
338
|
+
"denomalign",
|
|
339
|
+
"bevelled",
|
|
340
|
+
"notation",
|
|
341
|
+
"width",
|
|
342
|
+
"height",
|
|
343
|
+
"depth",
|
|
344
|
+
"voffset",
|
|
345
|
+
"lquote",
|
|
346
|
+
"rquote",
|
|
347
|
+
"columnspan",
|
|
348
|
+
"rowspan",
|
|
349
|
+
"encoding",
|
|
350
|
+
"open",
|
|
351
|
+
"close",
|
|
352
|
+
"separators",
|
|
353
|
+
"actiontype",
|
|
354
|
+
"selection",
|
|
355
|
+
"mslinebreak",
|
|
356
|
+
"linebreak",
|
|
357
|
+
"indentalign",
|
|
358
|
+
"data*"
|
|
359
|
+
];
|
|
360
|
+
var MATHML_SCHEMA = {
|
|
361
|
+
tagNames: MATHML_TAGS,
|
|
362
|
+
attributes: { "*": MATHML_ATTRIBUTES },
|
|
363
|
+
strip: ["script", "style"],
|
|
364
|
+
clobberPrefix: "",
|
|
365
|
+
clobber: [],
|
|
366
|
+
protocols: {}
|
|
367
|
+
};
|
|
368
|
+
function sanitizeMathml(mathml) {
|
|
369
|
+
return sanitizeHtmlFragment(mathml, MATHML_SCHEMA);
|
|
370
|
+
}
|
|
371
|
+
var MATH_SVG_TAGS = ["svg", "g", "path", "rect", "line", "polyline", "polygon", "circle", "ellipse", "text", "title", "desc"];
|
|
372
|
+
var MATH_SVG_ATTRIBUTES = [
|
|
373
|
+
"xmlns",
|
|
374
|
+
"width",
|
|
375
|
+
"height",
|
|
376
|
+
"viewBox",
|
|
377
|
+
"role",
|
|
378
|
+
"focusable",
|
|
379
|
+
"ariaHidden",
|
|
380
|
+
"ariaLabel",
|
|
381
|
+
"stroke",
|
|
382
|
+
"fill",
|
|
383
|
+
"strokeWidth",
|
|
384
|
+
"strokeLinecap",
|
|
385
|
+
"strokeLinejoin",
|
|
386
|
+
"transform",
|
|
387
|
+
"d",
|
|
388
|
+
"x",
|
|
389
|
+
"y",
|
|
390
|
+
"x1",
|
|
391
|
+
"y1",
|
|
392
|
+
"x2",
|
|
393
|
+
"y2",
|
|
394
|
+
"points",
|
|
395
|
+
"cx",
|
|
396
|
+
"cy",
|
|
397
|
+
"r",
|
|
398
|
+
"rx",
|
|
399
|
+
"ry",
|
|
400
|
+
"dataMmlNode",
|
|
401
|
+
"dataC"
|
|
402
|
+
];
|
|
403
|
+
var MATH_SVG_SCHEMA = {
|
|
404
|
+
tagNames: MATH_SVG_TAGS,
|
|
405
|
+
attributes: { "*": MATH_SVG_ATTRIBUTES },
|
|
406
|
+
strip: ["script", "style", "foreignObject"],
|
|
407
|
+
clobberPrefix: "",
|
|
408
|
+
clobber: [],
|
|
409
|
+
protocols: {}
|
|
410
|
+
};
|
|
411
|
+
function sanitizeMathSvg(svg) {
|
|
412
|
+
return sanitizeHtmlFragment(svg, MATH_SVG_SCHEMA);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// src/document/math.ts
|
|
173
416
|
var MATH_OPEN = "\uE100";
|
|
174
417
|
var MATH_CLOSE = "\uE101";
|
|
175
418
|
var MATH_TOKEN_RE = /\uE100(\d+)\uE101/g;
|
|
@@ -236,12 +479,12 @@ async function typesetMathSpans(spans) {
|
|
|
236
479
|
const mathml = mj.mml(s.tex, s.display);
|
|
237
480
|
const err = /<merror[\s\S]*?<mtext[^>]*>([\s\S]*?)<\/mtext>/.exec(mathml);
|
|
238
481
|
if (err) {
|
|
239
|
-
out.set(key, { mathml, error: decodeXml(err[1]) });
|
|
482
|
+
out.set(key, { mathml: sanitizeMathml(mathml), error: decodeXml(err[1]) });
|
|
240
483
|
continue;
|
|
241
484
|
}
|
|
242
|
-
const entry = { mathml: mathml.replace(/\n\s*/g, "") };
|
|
485
|
+
const entry = { mathml: sanitizeMathml(mathml.replace(/\n\s*/g, "")) };
|
|
243
486
|
if (s.display) {
|
|
244
|
-
const svg = mj.svg(s.tex, true);
|
|
487
|
+
const svg = sanitizeMathSvg(mj.svg(s.tex, true));
|
|
245
488
|
entry.svg = svg;
|
|
246
489
|
entry.widthEx = Number(/width="([\d.]+)ex"/.exec(svg)?.[1] ?? 0);
|
|
247
490
|
entry.heightEx = Number(/height="([\d.]+)ex"/.exec(svg)?.[1] ?? 0);
|
|
@@ -3351,7 +3594,10 @@ function mathHtml(tex, display, x, inText = false) {
|
|
|
3351
3594
|
}
|
|
3352
3595
|
var href = (id, x) => x.hrefFor ? x.hrefFor(id) : `#${id}`;
|
|
3353
3596
|
function imageSrc(url, x) {
|
|
3354
|
-
if (x.srcFor)
|
|
3597
|
+
if (x.srcFor) {
|
|
3598
|
+
const src = x.srcFor(url);
|
|
3599
|
+
return src === null ? null : safeUrl(src);
|
|
3600
|
+
}
|
|
3355
3601
|
const resolved = x.images?.get(url);
|
|
3356
3602
|
if (resolved) return resolved.dataUrl;
|
|
3357
3603
|
return safeUrl(url);
|
|
@@ -3437,7 +3683,7 @@ function coverHtml(s, x) {
|
|
|
3437
3683
|
s.title ?? ""
|
|
3438
3684
|
)}</h1>${s.subtitle ? `<p class="doc-cover-subtitle">${(0, import_html_escape.escapeHtml)(s.subtitle)}</p>` : ""}${s.author ? `<p class="doc-cover-author">${(0, import_html_escape.escapeHtml)(s.author)}</p>` : ""}${s.date ? `<p class="doc-cover-date">${(0, import_html_escape.escapeHtml)(s.date)}</p>` : ""}</section>`;
|
|
3439
3685
|
}
|
|
3440
|
-
var cssString = (s) => `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, " ")}"`;
|
|
3686
|
+
var cssString = (s) => `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, " ").replace(/</g, "\\3C ").replace(/>/g, "\\3E ")}"`;
|
|
3441
3687
|
function marginContent(template, s) {
|
|
3442
3688
|
if (!template) return "none";
|
|
3443
3689
|
return templateParts(template, s).map((p) => "field" in p ? `counter(${p.field})` : cssString(p.text)).join(" ");
|
|
@@ -3532,7 +3778,7 @@ ${[2, 3, 4, 5, 6].map((l) => `.doc-toc .toc-l${l}{padding-left:${(l - 1) * 1.2}e
|
|
|
3532
3778
|
}
|
|
3533
3779
|
function documentToHtml(tree, options = {}) {
|
|
3534
3780
|
const s = tree.settings;
|
|
3535
|
-
const x = { tree, images: options.images };
|
|
3781
|
+
const x = { tree, images: options.images, ...options.srcFor ? { srcFor: options.srcFor } : {} };
|
|
3536
3782
|
const sections = tree.sections.map((sec) => {
|
|
3537
3783
|
const cls = [
|
|
3538
3784
|
"doc-section",
|
|
@@ -3555,8 +3801,8 @@ ${s.author ? `<meta name="author" content="${(0, import_html_escape.escapeHtml)(
|
|
|
3555
3801
|
</head>
|
|
3556
3802
|
<body>
|
|
3557
3803
|
<main class="doc">
|
|
3558
|
-
${s.cover ? coverHtml(s, x) : ""}
|
|
3559
|
-
${sections}
|
|
3804
|
+
${(options.transformBody ?? ((h) => h))(`${s.cover ? coverHtml(s, x) : ""}
|
|
3805
|
+
${sections}`)}
|
|
3560
3806
|
</main>
|
|
3561
3807
|
</body>
|
|
3562
3808
|
</html>`;
|
|
@@ -4895,6 +5141,7 @@ var import_micromark_extension_gfm = require("micromark-extension-gfm");
|
|
|
4895
5141
|
|
|
4896
5142
|
// src/markdown.ts
|
|
4897
5143
|
var import_html_escape3 = require("@ai-matrx/kit/html-escape");
|
|
5144
|
+
var import_source2 = require("@ai-matrx/content-ir/source");
|
|
4898
5145
|
function removeThinkingContent(content) {
|
|
4899
5146
|
if (!content) return "";
|
|
4900
5147
|
const hide = (_match, before, after) => before.length >= 2 || after.length >= 2 ? "\n\n" : "\n";
|
|
@@ -4967,6 +5214,7 @@ function looksLikeJson(body) {
|
|
|
4967
5214
|
return false;
|
|
4968
5215
|
}
|
|
4969
5216
|
}
|
|
5217
|
+
var ALLOWED_TAGS = new Set(PRINT_HTML_SCHEMA.tagNames ?? []);
|
|
4970
5218
|
var LINK_URL = String.raw`((?:[^()\s]|\([^()\s]*\))+)(?:\s+"[^"]*")?`;
|
|
4971
5219
|
var IMAGE_RE = new RegExp(String.raw`!\[([^\]]*)\]\(` + LINK_URL + String.raw`\)`, "g");
|
|
4972
5220
|
var LINK_RE = new RegExp(String.raw`\[([^\]]+)\]\(` + LINK_URL + String.raw`\)`, "g");
|