@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
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
// src/safe-html.ts
|
|
2
|
+
import { fromHtml } from "hast-util-from-html";
|
|
3
|
+
import { defaultSchema, sanitize } from "hast-util-sanitize";
|
|
4
|
+
import { toHtml } from "hast-util-to-html";
|
|
5
|
+
var STRIP_WITH_CONTENT = [
|
|
6
|
+
"script",
|
|
7
|
+
"style",
|
|
8
|
+
"noscript",
|
|
9
|
+
"template",
|
|
10
|
+
"iframe",
|
|
11
|
+
"object",
|
|
12
|
+
"embed",
|
|
13
|
+
"textarea",
|
|
14
|
+
"select",
|
|
15
|
+
"head",
|
|
16
|
+
"title"
|
|
17
|
+
];
|
|
18
|
+
var FORBIDDEN_TAGS = [
|
|
19
|
+
...STRIP_WITH_CONTENT,
|
|
20
|
+
"form",
|
|
21
|
+
"meta",
|
|
22
|
+
"base",
|
|
23
|
+
"link",
|
|
24
|
+
"frame",
|
|
25
|
+
"frameset",
|
|
26
|
+
"applet",
|
|
27
|
+
"button",
|
|
28
|
+
"svg",
|
|
29
|
+
"math"
|
|
30
|
+
];
|
|
31
|
+
var baseAttributes = defaultSchema.attributes ?? {};
|
|
32
|
+
var SAFE_HTML_SCHEMA = {
|
|
33
|
+
...defaultSchema,
|
|
34
|
+
tagNames: (defaultSchema.tagNames ?? []).filter((t) => !FORBIDDEN_TAGS.includes(t)),
|
|
35
|
+
strip: STRIP_WITH_CONTENT,
|
|
36
|
+
// Authored anchors keep their names; the GitHub `user-content-` rewrite
|
|
37
|
+
// would also break `<label for>` → `<input id>` pairs.
|
|
38
|
+
clobberPrefix: "",
|
|
39
|
+
clobber: []
|
|
40
|
+
};
|
|
41
|
+
var PRINT_CLASS = /^(?:(?:matrx|print|code|doc|language)-[\w-]*|inline-code|is-checked)$/;
|
|
42
|
+
function withPrintClasses(defs = []) {
|
|
43
|
+
let found = false;
|
|
44
|
+
const out = defs.map((d) => {
|
|
45
|
+
if (Array.isArray(d) && d[0] === "className") {
|
|
46
|
+
found = true;
|
|
47
|
+
return [...d, PRINT_CLASS];
|
|
48
|
+
}
|
|
49
|
+
return d;
|
|
50
|
+
});
|
|
51
|
+
return found ? out : [...out, ["className", PRINT_CLASS]];
|
|
52
|
+
}
|
|
53
|
+
var printAttributes = Object.fromEntries(
|
|
54
|
+
Object.entries(baseAttributes).map(([tag, defs]) => [tag, withPrintClasses(defs)])
|
|
55
|
+
);
|
|
56
|
+
var cellAlign = ["style", /^text-align:\s*(?:left|center|right);?$/];
|
|
57
|
+
var PRINT_HTML_SCHEMA = {
|
|
58
|
+
...SAFE_HTML_SCHEMA,
|
|
59
|
+
tagNames: [
|
|
60
|
+
.../* @__PURE__ */ new Set([...SAFE_HTML_SCHEMA.tagNames ?? [], "section", "figure", "figcaption", "label"])
|
|
61
|
+
],
|
|
62
|
+
attributes: {
|
|
63
|
+
...printAttributes,
|
|
64
|
+
"*": [
|
|
65
|
+
...baseAttributes["*"] ?? [],
|
|
66
|
+
["className", PRINT_CLASS],
|
|
67
|
+
"role",
|
|
68
|
+
"ariaLabel",
|
|
69
|
+
"ariaHidden",
|
|
70
|
+
"dataLabel",
|
|
71
|
+
"dataLanguage",
|
|
72
|
+
"dataArtifactType"
|
|
73
|
+
],
|
|
74
|
+
// Table-cell alignment is the one inline style the converter writes.
|
|
75
|
+
td: withPrintClasses([...baseAttributes["td"] ?? [], [...cellAlign]]),
|
|
76
|
+
th: withPrintClasses([...baseAttributes["th"] ?? [], [...cellAlign]]),
|
|
77
|
+
// The flashcard flip is a checkbox + label pair (GitHub forces `disabled`).
|
|
78
|
+
input: withPrintClasses([["type", "checkbox"], "checked"]),
|
|
79
|
+
label: withPrintClasses(["htmlFor"])
|
|
80
|
+
},
|
|
81
|
+
required: { input: { type: "checkbox" } },
|
|
82
|
+
protocols: {
|
|
83
|
+
...defaultSchema.protocols,
|
|
84
|
+
href: [...defaultSchema.protocols?.href ?? [], "tel"],
|
|
85
|
+
// Embedded images (`data:image/png;base64,…`) — an <img> never runs script.
|
|
86
|
+
src: [...defaultSchema.protocols?.src ?? [], "data"]
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
function sanitizeHtmlFragment(html, schema = SAFE_HTML_SCHEMA) {
|
|
90
|
+
if (!html) return "";
|
|
91
|
+
const tree = sanitize(fromHtml(html, { fragment: true }), schema);
|
|
92
|
+
return toHtml(tree, { characterReferences: { useNamedReferences: true } });
|
|
93
|
+
}
|
|
94
|
+
function sanitizePrintHtml(html) {
|
|
95
|
+
return sanitizeHtmlFragment(html, PRINT_HTML_SCHEMA);
|
|
96
|
+
}
|
|
97
|
+
var MATHML_TAGS = [
|
|
98
|
+
"math",
|
|
99
|
+
"maction",
|
|
100
|
+
"annotation",
|
|
101
|
+
"menclose",
|
|
102
|
+
"merror",
|
|
103
|
+
"mfrac",
|
|
104
|
+
"mglyph",
|
|
105
|
+
"mi",
|
|
106
|
+
"mlabeledtr",
|
|
107
|
+
"mmultiscripts",
|
|
108
|
+
"mn",
|
|
109
|
+
"mo",
|
|
110
|
+
"mover",
|
|
111
|
+
"mpadded",
|
|
112
|
+
"mphantom",
|
|
113
|
+
"mprescripts",
|
|
114
|
+
"none",
|
|
115
|
+
"mroot",
|
|
116
|
+
"mrow",
|
|
117
|
+
"ms",
|
|
118
|
+
"mspace",
|
|
119
|
+
"msqrt",
|
|
120
|
+
"mstyle",
|
|
121
|
+
"msub",
|
|
122
|
+
"msubsup",
|
|
123
|
+
"msup",
|
|
124
|
+
"mtable",
|
|
125
|
+
"mtd",
|
|
126
|
+
"mtext",
|
|
127
|
+
"mtr",
|
|
128
|
+
"munder",
|
|
129
|
+
"munderover",
|
|
130
|
+
"semantics"
|
|
131
|
+
];
|
|
132
|
+
var MATHML_ATTRIBUTES = [
|
|
133
|
+
"xmlns",
|
|
134
|
+
"display",
|
|
135
|
+
"displaystyle",
|
|
136
|
+
"mathvariant",
|
|
137
|
+
"mathsize",
|
|
138
|
+
"mathcolor",
|
|
139
|
+
"mathbackground",
|
|
140
|
+
"scriptlevel",
|
|
141
|
+
"dir",
|
|
142
|
+
"fence",
|
|
143
|
+
"form",
|
|
144
|
+
"largeop",
|
|
145
|
+
"lspace",
|
|
146
|
+
"rspace",
|
|
147
|
+
"movablelimits",
|
|
148
|
+
"separator",
|
|
149
|
+
"stretchy",
|
|
150
|
+
"symmetric",
|
|
151
|
+
"maxsize",
|
|
152
|
+
"minsize",
|
|
153
|
+
"accent",
|
|
154
|
+
"accentunder",
|
|
155
|
+
"align",
|
|
156
|
+
"columnalign",
|
|
157
|
+
"rowalign",
|
|
158
|
+
"columnspacing",
|
|
159
|
+
"rowspacing",
|
|
160
|
+
"columnlines",
|
|
161
|
+
"rowlines",
|
|
162
|
+
"frame",
|
|
163
|
+
"framespacing",
|
|
164
|
+
"equalrows",
|
|
165
|
+
"equalcolumns",
|
|
166
|
+
"linethickness",
|
|
167
|
+
"numalign",
|
|
168
|
+
"denomalign",
|
|
169
|
+
"bevelled",
|
|
170
|
+
"notation",
|
|
171
|
+
"width",
|
|
172
|
+
"height",
|
|
173
|
+
"depth",
|
|
174
|
+
"voffset",
|
|
175
|
+
"lquote",
|
|
176
|
+
"rquote",
|
|
177
|
+
"columnspan",
|
|
178
|
+
"rowspan",
|
|
179
|
+
"encoding",
|
|
180
|
+
"open",
|
|
181
|
+
"close",
|
|
182
|
+
"separators",
|
|
183
|
+
"actiontype",
|
|
184
|
+
"selection",
|
|
185
|
+
"mslinebreak",
|
|
186
|
+
"linebreak",
|
|
187
|
+
"indentalign",
|
|
188
|
+
"data*"
|
|
189
|
+
];
|
|
190
|
+
var MATHML_SCHEMA = {
|
|
191
|
+
tagNames: MATHML_TAGS,
|
|
192
|
+
attributes: { "*": MATHML_ATTRIBUTES },
|
|
193
|
+
strip: ["script", "style"],
|
|
194
|
+
clobberPrefix: "",
|
|
195
|
+
clobber: [],
|
|
196
|
+
protocols: {}
|
|
197
|
+
};
|
|
198
|
+
function sanitizeMathml(mathml) {
|
|
199
|
+
return sanitizeHtmlFragment(mathml, MATHML_SCHEMA);
|
|
200
|
+
}
|
|
201
|
+
var MATH_SVG_TAGS = ["svg", "g", "path", "rect", "line", "polyline", "polygon", "circle", "ellipse", "text", "title", "desc"];
|
|
202
|
+
var MATH_SVG_ATTRIBUTES = [
|
|
203
|
+
"xmlns",
|
|
204
|
+
"width",
|
|
205
|
+
"height",
|
|
206
|
+
"viewBox",
|
|
207
|
+
"role",
|
|
208
|
+
"focusable",
|
|
209
|
+
"ariaHidden",
|
|
210
|
+
"ariaLabel",
|
|
211
|
+
"stroke",
|
|
212
|
+
"fill",
|
|
213
|
+
"strokeWidth",
|
|
214
|
+
"strokeLinecap",
|
|
215
|
+
"strokeLinejoin",
|
|
216
|
+
"transform",
|
|
217
|
+
"d",
|
|
218
|
+
"x",
|
|
219
|
+
"y",
|
|
220
|
+
"x1",
|
|
221
|
+
"y1",
|
|
222
|
+
"x2",
|
|
223
|
+
"y2",
|
|
224
|
+
"points",
|
|
225
|
+
"cx",
|
|
226
|
+
"cy",
|
|
227
|
+
"r",
|
|
228
|
+
"rx",
|
|
229
|
+
"ry",
|
|
230
|
+
"dataMmlNode",
|
|
231
|
+
"dataC"
|
|
232
|
+
];
|
|
233
|
+
var MATH_SVG_SCHEMA = {
|
|
234
|
+
tagNames: MATH_SVG_TAGS,
|
|
235
|
+
attributes: { "*": MATH_SVG_ATTRIBUTES },
|
|
236
|
+
strip: ["script", "style", "foreignObject"],
|
|
237
|
+
clobberPrefix: "",
|
|
238
|
+
clobber: [],
|
|
239
|
+
protocols: {}
|
|
240
|
+
};
|
|
241
|
+
function sanitizeMathSvg(svg) {
|
|
242
|
+
return sanitizeHtmlFragment(svg, MATH_SVG_SCHEMA);
|
|
243
|
+
}
|
|
244
|
+
function engineHtmlSchema(inlineStyles = []) {
|
|
245
|
+
const exact = inlineStyles.length ? [new RegExp(`^(?:${[...new Set(inlineStyles)].map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})$`)] : [];
|
|
246
|
+
const mathAttributes = Object.fromEntries(MATHML_TAGS.map((tag) => [tag, MATHML_ATTRIBUTES]));
|
|
247
|
+
const printAttrs = PRINT_HTML_SCHEMA.attributes ?? {};
|
|
248
|
+
const styled = (defs = []) => exact.length ? [...defs.filter((d) => !(Array.isArray(d) && d[0] === "style")), ["style", ...exact]] : defs;
|
|
249
|
+
const attributes = { ...printAttrs, ...mathAttributes };
|
|
250
|
+
if (exact.length) {
|
|
251
|
+
for (const tag of /* @__PURE__ */ new Set([...PRINT_HTML_SCHEMA.tagNames ?? [], "div", "span"])) {
|
|
252
|
+
if (MATHML_TAGS.includes(tag)) continue;
|
|
253
|
+
attributes[tag] = styled(printAttrs[tag] ?? []);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
...PRINT_HTML_SCHEMA,
|
|
258
|
+
tagNames: [.../* @__PURE__ */ new Set([...PRINT_HTML_SCHEMA.tagNames ?? [], ...MATHML_TAGS])],
|
|
259
|
+
attributes
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function sanitizeEngineHtml(html, inlineStyles = []) {
|
|
263
|
+
return sanitizeHtmlFragment(html, engineHtmlSchema(inlineStyles));
|
|
264
|
+
}
|
|
265
|
+
export {
|
|
266
|
+
FORBIDDEN_TAGS,
|
|
267
|
+
MATHML_SCHEMA,
|
|
268
|
+
MATH_SVG_SCHEMA,
|
|
269
|
+
PRINT_HTML_SCHEMA,
|
|
270
|
+
SAFE_HTML_SCHEMA,
|
|
271
|
+
engineHtmlSchema,
|
|
272
|
+
sanitizeEngineHtml,
|
|
273
|
+
sanitizeHtmlFragment,
|
|
274
|
+
sanitizeMathSvg,
|
|
275
|
+
sanitizeMathml,
|
|
276
|
+
sanitizePrintHtml
|
|
277
|
+
};
|
|
278
|
+
//# sourceMappingURL=safe-html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/safe-html.ts"],"sourcesContent":["/**\n * @ai-matrx/print/safe-html — THE allow-list every Markdown→HTML string this\n * package hands out goes through.\n *\n * Why an allow-list: the regex converter (`markdownToHtml` /\n * `markdownToArticleHtml`) lets author raw HTML through so a document can feed\n * WordPress. Its old guard was a block-list (script, style, on… handlers,\n * javascript: URLs) and everything nobody listed — `<iframe>`, `<form>`,\n * `<meta http-equiv=refresh>`, `<object>`/`<embed>`, `<base>`, `<link>`,\n * inline `style` — reached the clipboard, the downloaded page and the preview.\n * Now a tag or attribute survives only when it is listed here.\n *\n * Sync and DOM-free (parse5 via hast), so it runs in Node, workers, the\n * extension service worker and Tauri alike.\n *\n * Two schemas:\n * • `SAFE_HTML_SCHEMA` — GitHub's rendering rules (hast-util-sanitize's\n * default schema) with no id clobber-prefixing and the \"drop the element\n * AND its text\" list for elements whose text is not prose. For any host\n * that renders plain semantic HTML (email bodies, CMS drafts).\n * • `PRINT_HTML_SCHEMA` — the same, plus exactly the vocabulary print's own\n * converters emit: `matrx-*` / `print-*` / `code-*` / `doc-*` classes,\n * table-cell alignment, the flashcard checkbox + label, figures, and the\n * page-break separator's data/aria attributes.\n */\n\nimport { fromHtml } from \"hast-util-from-html\";\nimport { defaultSchema, sanitize, type Schema } from \"hast-util-sanitize\";\nimport { toHtml } from \"hast-util-to-html\";\nimport type { Root } from \"hast\";\n\ntype Attributes = NonNullable<Schema[\"attributes\"]>;\ntype AttributeList = Attributes[string];\n\n/** Elements removed together with their content (their text is not prose). */\nconst STRIP_WITH_CONTENT = [\n \"script\",\n \"style\",\n \"noscript\",\n \"template\",\n \"iframe\",\n \"object\",\n \"embed\",\n \"textarea\",\n \"select\",\n \"head\",\n \"title\",\n];\n\n/** Never allowed, whatever a schema extension adds. */\nexport const FORBIDDEN_TAGS: readonly string[] = [\n ...STRIP_WITH_CONTENT,\n \"form\",\n \"meta\",\n \"base\",\n \"link\",\n \"frame\",\n \"frameset\",\n \"applet\",\n \"button\",\n \"svg\",\n \"math\",\n];\n\nconst baseAttributes = defaultSchema.attributes ?? {};\n\nexport const SAFE_HTML_SCHEMA: Schema = {\n ...defaultSchema,\n tagNames: (defaultSchema.tagNames ?? []).filter((t) => !FORBIDDEN_TAGS.includes(t)),\n strip: STRIP_WITH_CONTENT,\n // Authored anchors keep their names; the GitHub `user-content-` rewrite\n // would also break `<label for>` → `<input id>` pairs.\n clobberPrefix: \"\",\n clobber: [],\n};\n\n/** Class tokens print's converters emit. Author classes outside these are dropped. */\nconst PRINT_CLASS = /^(?:(?:matrx|print|code|doc|language)-[\\w-]*|inline-code|is-checked)$/;\n\n/**\n * A tag's own `className` definition wins over `'*'` (and returns an empty\n * list rather than falling through), so the print class pattern is merged into\n * every definition that names `className`, and added where none does.\n */\nfunction withPrintClasses(defs: AttributeList = []): AttributeList {\n let found = false;\n const out = defs.map((d) => {\n if (Array.isArray(d) && d[0] === \"className\") {\n found = true;\n return [...d, PRINT_CLASS] as unknown as typeof d;\n }\n return d;\n });\n return found ? out : [...out, [\"className\", PRINT_CLASS]];\n}\n\nconst printAttributes: Attributes = Object.fromEntries(\n Object.entries(baseAttributes).map(([tag, defs]) => [tag, withPrintClasses(defs)]),\n);\n\nconst cellAlign = [\"style\", /^text-align:\\s*(?:left|center|right);?$/] as const;\n\nexport const PRINT_HTML_SCHEMA: Schema = {\n ...SAFE_HTML_SCHEMA,\n tagNames: [\n ...new Set([...(SAFE_HTML_SCHEMA.tagNames ?? []), \"section\", \"figure\", \"figcaption\", \"label\"]),\n ],\n attributes: {\n ...printAttributes,\n \"*\": [\n ...(baseAttributes[\"*\"] ?? []),\n [\"className\", PRINT_CLASS],\n \"role\",\n \"ariaLabel\",\n \"ariaHidden\",\n \"dataLabel\",\n \"dataLanguage\",\n \"dataArtifactType\",\n ],\n // Table-cell alignment is the one inline style the converter writes.\n td: withPrintClasses([...(baseAttributes[\"td\"] ?? []), [...cellAlign]]),\n th: withPrintClasses([...(baseAttributes[\"th\"] ?? []), [...cellAlign]]),\n // The flashcard flip is a checkbox + label pair (GitHub forces `disabled`).\n input: withPrintClasses([[\"type\", \"checkbox\"], \"checked\"]),\n label: withPrintClasses([\"htmlFor\"]),\n },\n required: { input: { type: \"checkbox\" } },\n protocols: {\n ...defaultSchema.protocols,\n href: [...(defaultSchema.protocols?.href ?? []), \"tel\"],\n // Embedded images (`data:image/png;base64,…`) — an <img> never runs script.\n src: [...(defaultSchema.protocols?.src ?? []), \"data\"],\n },\n};\n\n/** Sanitize an HTML fragment against an allow-list (default: `SAFE_HTML_SCHEMA`). */\nexport function sanitizeHtmlFragment(html: string, schema: Schema = SAFE_HTML_SCHEMA): string {\n if (!html) return \"\";\n const tree = sanitize(fromHtml(html, { fragment: true }), schema) as Root;\n return toHtml(tree, { characterReferences: { useNamedReferences: true } });\n}\n\n/** Sanitize the output of print's own converters (keeps the `.matrx-*` vocabulary). */\nexport function sanitizePrintHtml(html: string): string {\n return sanitizeHtmlFragment(html, PRINT_HTML_SCHEMA);\n}\n\nexport type { Schema as SafeHtmlSchema };\n\n/**\n * MathML from the TeX typesetter. TeX is author input, and MathJax's `html`,\n * `bbox` and `\\mmlToken` commands turn it into attributes (`\\href{javascript:…}`\n * → `href`, `\\style{position:fixed…}` / `\\bbox[position:fixed]` → `style`).\n * Only presentation MathML elements and their layout attributes survive.\n */\nconst MATHML_TAGS = [\n \"math\", \"maction\", \"annotation\", \"menclose\", \"merror\", \"mfrac\", \"mglyph\", \"mi\",\n \"mlabeledtr\", \"mmultiscripts\", \"mn\", \"mo\", \"mover\", \"mpadded\", \"mphantom\", \"mprescripts\", \"none\",\n \"mroot\", \"mrow\", \"ms\", \"mspace\", \"msqrt\", \"mstyle\", \"msub\", \"msubsup\", \"msup\", \"mtable\", \"mtd\",\n \"mtext\", \"mtr\", \"munder\", \"munderover\", \"semantics\",\n];\n\nconst MATHML_ATTRIBUTES = [\n \"xmlns\", \"display\", \"displaystyle\", \"mathvariant\", \"mathsize\", \"mathcolor\", \"mathbackground\",\n \"scriptlevel\", \"dir\", \"fence\", \"form\", \"largeop\", \"lspace\", \"rspace\", \"movablelimits\",\n \"separator\", \"stretchy\", \"symmetric\", \"maxsize\", \"minsize\", \"accent\", \"accentunder\", \"align\",\n \"columnalign\", \"rowalign\", \"columnspacing\", \"rowspacing\", \"columnlines\", \"rowlines\", \"frame\",\n \"framespacing\", \"equalrows\", \"equalcolumns\", \"linethickness\", \"numalign\", \"denomalign\",\n \"bevelled\", \"notation\", \"width\", \"height\", \"depth\", \"voffset\", \"lquote\", \"rquote\", \"columnspan\",\n \"rowspan\", \"encoding\", \"open\", \"close\", \"separators\", \"actiontype\", \"selection\", \"mslinebreak\",\n \"linebreak\", \"indentalign\", \"data*\",\n];\n\nexport const MATHML_SCHEMA: Schema = {\n tagNames: MATHML_TAGS,\n attributes: { \"*\": MATHML_ATTRIBUTES },\n strip: [\"script\", \"style\"],\n clobberPrefix: \"\",\n clobber: [],\n protocols: {},\n};\n\n/** Sanitize a typeset MathML string (keeps layout, drops links and styles). */\nexport function sanitizeMathml(mathml: string): string {\n return sanitizeHtmlFragment(mathml, MATHML_SCHEMA);\n}\n\n/**\n * SVG from the TeX typesetter (PDF display math, LIST T26). MathJax's `\\href`,\n * `\\style`, `\\class`, `\\cssId`, `\\bbox[…]` and `\\mmlToken[…]` reach the SVG as\n * `<a href=\"javascript:…\">`, `style=\"position:fixed…\"`, `class`, `id`. The PDF\n * writer draws this SVG, and any host that shows it would too, so only the\n * drawing vocabulary survives: shapes, paths, text, transforms and paint. A\n * link wrapper is unwrapped (its glyphs stay), everything else is dropped.\n */\nconst MATH_SVG_TAGS = [\"svg\", \"g\", \"path\", \"rect\", \"line\", \"polyline\", \"polygon\", \"circle\", \"ellipse\", \"text\", \"title\", \"desc\"];\n\nconst MATH_SVG_ATTRIBUTES = [\n \"xmlns\", \"width\", \"height\", \"viewBox\", \"role\", \"focusable\", \"ariaHidden\", \"ariaLabel\",\n \"stroke\", \"fill\", \"strokeWidth\", \"strokeLinecap\", \"strokeLinejoin\", \"transform\", \"d\",\n \"x\", \"y\", \"x1\", \"y1\", \"x2\", \"y2\", \"points\", \"cx\", \"cy\", \"r\", \"rx\", \"ry\",\n \"dataMmlNode\", \"dataC\",\n];\n\nexport const MATH_SVG_SCHEMA: Schema = {\n tagNames: MATH_SVG_TAGS,\n attributes: { \"*\": MATH_SVG_ATTRIBUTES },\n strip: [\"script\", \"style\", \"foreignObject\"],\n clobberPrefix: \"\",\n clobber: [],\n protocols: {},\n};\n\n/** Sanitize a typeset math SVG (keeps the drawing, drops links, styles, classes and ids). */\nexport function sanitizeMathSvg(svg: string): string {\n return sanitizeHtmlFragment(svg, MATH_SVG_SCHEMA);\n}\n\n/**\n * THE final allow-list of the one Markdown→HTML engine (`@ai-matrx/print/\n * markdown-html`, CONTRACT §1.9): print's own vocabulary plus typeset MathML\n * (MathML elements carry only the MathML layout attributes), and — for the\n * inline clipboard skin only — `style` attributes whose value is EXACTLY one\n * the engine itself wrote (`inlineStyles`). An author can never reach a style.\n */\nexport function engineHtmlSchema(inlineStyles: readonly string[] = []): Schema {\n const exact = inlineStyles.length\n ? [new RegExp(`^(?:${[...new Set(inlineStyles)].map((s) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")).join(\"|\")})$`)]\n : [];\n const mathAttributes = Object.fromEntries(MATHML_TAGS.map((tag) => [tag, MATHML_ATTRIBUTES]));\n const printAttrs = PRINT_HTML_SCHEMA.attributes ?? {};\n const styled = (defs: AttributeList = []): AttributeList =>\n exact.length ? [...defs.filter((d) => !(Array.isArray(d) && d[0] === \"style\")), [\"style\", ...exact]] : defs;\n const attributes: Attributes = { ...printAttrs, ...mathAttributes };\n if (exact.length) {\n for (const tag of new Set([...(PRINT_HTML_SCHEMA.tagNames ?? []), \"div\", \"span\"])) {\n if (MATHML_TAGS.includes(tag)) continue;\n attributes[tag] = styled(printAttrs[tag] ?? []);\n }\n // Table cells keep their alignment AND the skin's cell style (the skin writes both into one value).\n }\n return {\n ...PRINT_HTML_SCHEMA,\n tagNames: [...new Set([...(PRINT_HTML_SCHEMA.tagNames ?? []), ...MATHML_TAGS])],\n attributes,\n };\n}\n\n/** Sanitize the engine's output (see `engineHtmlSchema`). */\nexport function sanitizeEngineHtml(html: string, inlineStyles: readonly string[] = []): string {\n return sanitizeHtmlFragment(html, engineHtmlSchema(inlineStyles));\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-matrx/print",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.9",
|
|
4
4
|
"description": "The AI Matrx print system: the BlockPrinter contract and print-window composition, the flashcards deck printer (duplex-mirrored cut sheets, Avery 5388, study sheets), QR generation with spec quiet zones and e-commerce payload builders, label-sheet printing on Avery and roll stock with custom label formats, and a complete markdown pipeline: a shipped markdown converter, two default print stylesheets, print windows, and markdown/DOM to PDF, and print-grade documents (cover, TOC, captions, cross-references, citations, sections) exported to PDF, DOCX, EPUB and HTML from one parsed tree.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -215,6 +215,26 @@
|
|
|
215
215
|
"types": "./dist/document.d.cts",
|
|
216
216
|
"default": "./dist/document.cjs"
|
|
217
217
|
}
|
|
218
|
+
},
|
|
219
|
+
"./safe-html": {
|
|
220
|
+
"import": {
|
|
221
|
+
"types": "./dist/safe-html.d.ts",
|
|
222
|
+
"default": "./dist/safe-html.js"
|
|
223
|
+
},
|
|
224
|
+
"require": {
|
|
225
|
+
"types": "./dist/safe-html.d.cts",
|
|
226
|
+
"default": "./dist/safe-html.cjs"
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
"./markdown-html": {
|
|
230
|
+
"import": {
|
|
231
|
+
"types": "./dist/markdown-html.d.ts",
|
|
232
|
+
"default": "./dist/markdown-html.js"
|
|
233
|
+
},
|
|
234
|
+
"require": {
|
|
235
|
+
"types": "./dist/markdown-html.d.cts",
|
|
236
|
+
"default": "./dist/markdown-html.cjs"
|
|
237
|
+
}
|
|
218
238
|
}
|
|
219
239
|
},
|
|
220
240
|
"dependencies": {
|
|
@@ -224,6 +244,9 @@
|
|
|
224
244
|
"citeproc": "^2.4.63",
|
|
225
245
|
"docx": "^9.7.2",
|
|
226
246
|
"fontkit": "^2.0.4",
|
|
247
|
+
"hast-util-from-html": "^2.0.3",
|
|
248
|
+
"hast-util-sanitize": "^5.0.2",
|
|
249
|
+
"hast-util-to-html": "^9.0.5",
|
|
227
250
|
"html2canvas": "^1.4.1",
|
|
228
251
|
"hyphen": "^1.14.1",
|
|
229
252
|
"jspdf": "^4.2.1",
|
|
@@ -238,8 +261,8 @@
|
|
|
238
261
|
"tailwind-merge": "^3.7.0",
|
|
239
262
|
"vaul": "^1.1.2",
|
|
240
263
|
"yaml": "^2.9.1",
|
|
241
|
-
"@ai-matrx/
|
|
242
|
-
"@ai-matrx/
|
|
264
|
+
"@ai-matrx/content-ir": "latest",
|
|
265
|
+
"@ai-matrx/kit": "latest"
|
|
243
266
|
},
|
|
244
267
|
"peerDependencies": {
|
|
245
268
|
"react": ">=18.0.0",
|
|
@@ -259,6 +282,7 @@
|
|
|
259
282
|
"@fontsource/noto-sans-math": "^5.3.0",
|
|
260
283
|
"@testing-library/react": "^16.3.3",
|
|
261
284
|
"@types/fontkit": "^2.0.9",
|
|
285
|
+
"@types/hast": "^3.0.5",
|
|
262
286
|
"@types/hyphen": "^1.14.0",
|
|
263
287
|
"@types/mdast": "^4.0.4",
|
|
264
288
|
"@types/node": "^26.6.2",
|