@ai-matrx/print 0.8.6 → 0.8.8
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 +35 -0
- package/dist/document.cjs +206 -4
- package/dist/document.cjs.map +1 -1
- package/dist/document.js +206 -4
- package/dist/document.js.map +1 -1
- package/dist/markdown.cjs +115 -7
- package/dist/markdown.cjs.map +1 -1
- package/dist/markdown.js +115 -7
- package/dist/markdown.js.map +1 -1
- package/dist/safe-html.cjs +231 -0
- package/dist/safe-html.cjs.map +1 -0
- package/dist/safe-html.d.cts +43 -0
- package/dist/safe-html.d.ts +43 -0
- package/dist/safe-html.js +210 -0
- package/dist/safe-html.js.map +1 -0
- package/package.json +15 -1
package/dist/document.js
CHANGED
|
@@ -87,6 +87,206 @@ function contentColumnWidths(b, n, avail, measure, pad = 10) {
|
|
|
87
87
|
|
|
88
88
|
// src/document/math.ts
|
|
89
89
|
import { listIslands, tokenizeSource } from "@ai-matrx/content-ir/source";
|
|
90
|
+
|
|
91
|
+
// src/safe-html.ts
|
|
92
|
+
import { fromHtml } from "hast-util-from-html";
|
|
93
|
+
import { defaultSchema, sanitize } from "hast-util-sanitize";
|
|
94
|
+
import { toHtml } from "hast-util-to-html";
|
|
95
|
+
var STRIP_WITH_CONTENT = [
|
|
96
|
+
"script",
|
|
97
|
+
"style",
|
|
98
|
+
"noscript",
|
|
99
|
+
"template",
|
|
100
|
+
"iframe",
|
|
101
|
+
"object",
|
|
102
|
+
"embed",
|
|
103
|
+
"textarea",
|
|
104
|
+
"select",
|
|
105
|
+
"head",
|
|
106
|
+
"title"
|
|
107
|
+
];
|
|
108
|
+
var FORBIDDEN_TAGS = [
|
|
109
|
+
...STRIP_WITH_CONTENT,
|
|
110
|
+
"form",
|
|
111
|
+
"meta",
|
|
112
|
+
"base",
|
|
113
|
+
"link",
|
|
114
|
+
"frame",
|
|
115
|
+
"frameset",
|
|
116
|
+
"applet",
|
|
117
|
+
"button",
|
|
118
|
+
"svg",
|
|
119
|
+
"math"
|
|
120
|
+
];
|
|
121
|
+
var baseAttributes = defaultSchema.attributes ?? {};
|
|
122
|
+
var SAFE_HTML_SCHEMA = {
|
|
123
|
+
...defaultSchema,
|
|
124
|
+
tagNames: (defaultSchema.tagNames ?? []).filter((t) => !FORBIDDEN_TAGS.includes(t)),
|
|
125
|
+
strip: STRIP_WITH_CONTENT,
|
|
126
|
+
// Authored anchors keep their names; the GitHub `user-content-` rewrite
|
|
127
|
+
// would also break `<label for>` → `<input id>` pairs.
|
|
128
|
+
clobberPrefix: "",
|
|
129
|
+
clobber: []
|
|
130
|
+
};
|
|
131
|
+
var PRINT_CLASS = /^(?:(?:matrx|print|code|doc|language)-[\w-]*|inline-code|is-checked)$/;
|
|
132
|
+
function withPrintClasses(defs = []) {
|
|
133
|
+
let found = false;
|
|
134
|
+
const out = defs.map((d) => {
|
|
135
|
+
if (Array.isArray(d) && d[0] === "className") {
|
|
136
|
+
found = true;
|
|
137
|
+
return [...d, PRINT_CLASS];
|
|
138
|
+
}
|
|
139
|
+
return d;
|
|
140
|
+
});
|
|
141
|
+
return found ? out : [...out, ["className", PRINT_CLASS]];
|
|
142
|
+
}
|
|
143
|
+
var printAttributes = Object.fromEntries(
|
|
144
|
+
Object.entries(baseAttributes).map(([tag, defs]) => [tag, withPrintClasses(defs)])
|
|
145
|
+
);
|
|
146
|
+
var cellAlign = ["style", /^text-align:\s*(?:left|center|right);?$/];
|
|
147
|
+
var PRINT_HTML_SCHEMA = {
|
|
148
|
+
...SAFE_HTML_SCHEMA,
|
|
149
|
+
tagNames: [
|
|
150
|
+
.../* @__PURE__ */ new Set([...SAFE_HTML_SCHEMA.tagNames ?? [], "section", "figure", "figcaption", "label"])
|
|
151
|
+
],
|
|
152
|
+
attributes: {
|
|
153
|
+
...printAttributes,
|
|
154
|
+
"*": [
|
|
155
|
+
...baseAttributes["*"] ?? [],
|
|
156
|
+
["className", PRINT_CLASS],
|
|
157
|
+
"role",
|
|
158
|
+
"ariaLabel",
|
|
159
|
+
"ariaHidden",
|
|
160
|
+
"dataLabel",
|
|
161
|
+
"dataLanguage",
|
|
162
|
+
"dataArtifactType"
|
|
163
|
+
],
|
|
164
|
+
// Table-cell alignment is the one inline style the converter writes.
|
|
165
|
+
td: withPrintClasses([...baseAttributes["td"] ?? [], [...cellAlign]]),
|
|
166
|
+
th: withPrintClasses([...baseAttributes["th"] ?? [], [...cellAlign]]),
|
|
167
|
+
// The flashcard flip is a checkbox + label pair (GitHub forces `disabled`).
|
|
168
|
+
input: withPrintClasses([["type", "checkbox"], "checked"]),
|
|
169
|
+
label: withPrintClasses(["htmlFor"])
|
|
170
|
+
},
|
|
171
|
+
required: { input: { type: "checkbox" } },
|
|
172
|
+
protocols: {
|
|
173
|
+
...defaultSchema.protocols,
|
|
174
|
+
href: [...defaultSchema.protocols?.href ?? [], "tel"],
|
|
175
|
+
// Embedded images (`data:image/png;base64,…`) — an <img> never runs script.
|
|
176
|
+
src: [...defaultSchema.protocols?.src ?? [], "data"]
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
function sanitizeHtmlFragment(html, schema = SAFE_HTML_SCHEMA) {
|
|
180
|
+
if (!html) return "";
|
|
181
|
+
const tree = sanitize(fromHtml(html, { fragment: true }), schema);
|
|
182
|
+
return toHtml(tree, { characterReferences: { useNamedReferences: true } });
|
|
183
|
+
}
|
|
184
|
+
var MATHML_TAGS = [
|
|
185
|
+
"math",
|
|
186
|
+
"maction",
|
|
187
|
+
"annotation",
|
|
188
|
+
"menclose",
|
|
189
|
+
"merror",
|
|
190
|
+
"mfrac",
|
|
191
|
+
"mglyph",
|
|
192
|
+
"mi",
|
|
193
|
+
"mlabeledtr",
|
|
194
|
+
"mmultiscripts",
|
|
195
|
+
"mn",
|
|
196
|
+
"mo",
|
|
197
|
+
"mover",
|
|
198
|
+
"mpadded",
|
|
199
|
+
"mphantom",
|
|
200
|
+
"mprescripts",
|
|
201
|
+
"none",
|
|
202
|
+
"mroot",
|
|
203
|
+
"mrow",
|
|
204
|
+
"ms",
|
|
205
|
+
"mspace",
|
|
206
|
+
"msqrt",
|
|
207
|
+
"mstyle",
|
|
208
|
+
"msub",
|
|
209
|
+
"msubsup",
|
|
210
|
+
"msup",
|
|
211
|
+
"mtable",
|
|
212
|
+
"mtd",
|
|
213
|
+
"mtext",
|
|
214
|
+
"mtr",
|
|
215
|
+
"munder",
|
|
216
|
+
"munderover",
|
|
217
|
+
"semantics"
|
|
218
|
+
];
|
|
219
|
+
var MATHML_ATTRIBUTES = [
|
|
220
|
+
"xmlns",
|
|
221
|
+
"display",
|
|
222
|
+
"displaystyle",
|
|
223
|
+
"mathvariant",
|
|
224
|
+
"mathsize",
|
|
225
|
+
"mathcolor",
|
|
226
|
+
"mathbackground",
|
|
227
|
+
"scriptlevel",
|
|
228
|
+
"dir",
|
|
229
|
+
"fence",
|
|
230
|
+
"form",
|
|
231
|
+
"largeop",
|
|
232
|
+
"lspace",
|
|
233
|
+
"rspace",
|
|
234
|
+
"movablelimits",
|
|
235
|
+
"separator",
|
|
236
|
+
"stretchy",
|
|
237
|
+
"symmetric",
|
|
238
|
+
"maxsize",
|
|
239
|
+
"minsize",
|
|
240
|
+
"accent",
|
|
241
|
+
"accentunder",
|
|
242
|
+
"align",
|
|
243
|
+
"columnalign",
|
|
244
|
+
"rowalign",
|
|
245
|
+
"columnspacing",
|
|
246
|
+
"rowspacing",
|
|
247
|
+
"columnlines",
|
|
248
|
+
"rowlines",
|
|
249
|
+
"frame",
|
|
250
|
+
"framespacing",
|
|
251
|
+
"equalrows",
|
|
252
|
+
"equalcolumns",
|
|
253
|
+
"linethickness",
|
|
254
|
+
"numalign",
|
|
255
|
+
"denomalign",
|
|
256
|
+
"bevelled",
|
|
257
|
+
"notation",
|
|
258
|
+
"width",
|
|
259
|
+
"height",
|
|
260
|
+
"depth",
|
|
261
|
+
"voffset",
|
|
262
|
+
"lquote",
|
|
263
|
+
"rquote",
|
|
264
|
+
"columnspan",
|
|
265
|
+
"rowspan",
|
|
266
|
+
"encoding",
|
|
267
|
+
"open",
|
|
268
|
+
"close",
|
|
269
|
+
"separators",
|
|
270
|
+
"actiontype",
|
|
271
|
+
"selection",
|
|
272
|
+
"mslinebreak",
|
|
273
|
+
"linebreak",
|
|
274
|
+
"indentalign",
|
|
275
|
+
"data*"
|
|
276
|
+
];
|
|
277
|
+
var MATHML_SCHEMA = {
|
|
278
|
+
tagNames: MATHML_TAGS,
|
|
279
|
+
attributes: { "*": MATHML_ATTRIBUTES },
|
|
280
|
+
strip: ["script", "style"],
|
|
281
|
+
clobberPrefix: "",
|
|
282
|
+
clobber: [],
|
|
283
|
+
protocols: {}
|
|
284
|
+
};
|
|
285
|
+
function sanitizeMathml(mathml) {
|
|
286
|
+
return sanitizeHtmlFragment(mathml, MATHML_SCHEMA);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/document/math.ts
|
|
90
290
|
var MATH_OPEN = "\uE100";
|
|
91
291
|
var MATH_CLOSE = "\uE101";
|
|
92
292
|
var MATH_TOKEN_RE = /\uE100(\d+)\uE101/g;
|
|
@@ -153,10 +353,10 @@ async function typesetMathSpans(spans) {
|
|
|
153
353
|
const mathml = mj.mml(s.tex, s.display);
|
|
154
354
|
const err = /<merror[\s\S]*?<mtext[^>]*>([\s\S]*?)<\/mtext>/.exec(mathml);
|
|
155
355
|
if (err) {
|
|
156
|
-
out.set(key, { mathml, error: decodeXml(err[1]) });
|
|
356
|
+
out.set(key, { mathml: sanitizeMathml(mathml), error: decodeXml(err[1]) });
|
|
157
357
|
continue;
|
|
158
358
|
}
|
|
159
|
-
const entry = { mathml: mathml.replace(/\n\s*/g, "") };
|
|
359
|
+
const entry = { mathml: sanitizeMathml(mathml.replace(/\n\s*/g, "")) };
|
|
160
360
|
if (s.display) {
|
|
161
361
|
const svg = mj.svg(s.tex, true);
|
|
162
362
|
entry.svg = svg;
|
|
@@ -3354,7 +3554,7 @@ function coverHtml(s, x) {
|
|
|
3354
3554
|
s.title ?? ""
|
|
3355
3555
|
)}</h1>${s.subtitle ? `<p class="doc-cover-subtitle">${escapeHtml(s.subtitle)}</p>` : ""}${s.author ? `<p class="doc-cover-author">${escapeHtml(s.author)}</p>` : ""}${s.date ? `<p class="doc-cover-date">${escapeHtml(s.date)}</p>` : ""}</section>`;
|
|
3356
3556
|
}
|
|
3357
|
-
var cssString = (s) => `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, " ")}"`;
|
|
3557
|
+
var cssString = (s) => `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, " ").replace(/</g, "\\3C ").replace(/>/g, "\\3E ")}"`;
|
|
3358
3558
|
function marginContent(template, s) {
|
|
3359
3559
|
if (!template) return "none";
|
|
3360
3560
|
return templateParts(template, s).map((p) => "field" in p ? `counter(${p.field})` : cssString(p.text)).join(" ");
|
|
@@ -4814,7 +5014,8 @@ import { gfm } from "micromark-extension-gfm";
|
|
|
4814
5014
|
import { escapeHtml as escapeHtml3 } from "@ai-matrx/kit/html-escape";
|
|
4815
5015
|
function removeThinkingContent(content) {
|
|
4816
5016
|
if (!content) return "";
|
|
4817
|
-
|
|
5017
|
+
const hide = (_match, before, after) => before.length >= 2 || after.length >= 2 ? "\n\n" : "\n";
|
|
5018
|
+
let result = content.replace(/(\n*)<thinking>[\s\S]*?<\/thinking>(\n*)/gi, hide).replace(/(\n*)<think>[\s\S]*?<\/think>(\n*)/gi, hide).replace(/(\n*)<reasoning>[\s\S]*?<\/reasoning>(\n*)/gi, hide);
|
|
4818
5019
|
result = result.replace(/\n{3,}/g, "\n\n");
|
|
4819
5020
|
return result.trim();
|
|
4820
5021
|
}
|
|
@@ -4883,6 +5084,7 @@ function looksLikeJson(body) {
|
|
|
4883
5084
|
return false;
|
|
4884
5085
|
}
|
|
4885
5086
|
}
|
|
5087
|
+
var ALLOWED_TAGS = new Set(PRINT_HTML_SCHEMA.tagNames ?? []);
|
|
4886
5088
|
var LINK_URL = String.raw`((?:[^()\s]|\([^()\s]*\))+)(?:\s+"[^"]*")?`;
|
|
4887
5089
|
var IMAGE_RE = new RegExp(String.raw`!\[([^\]]*)\]\(` + LINK_URL + String.raw`\)`, "g");
|
|
4888
5090
|
var LINK_RE = new RegExp(String.raw`\[([^\]]+)\]\(` + LINK_URL + String.raw`\)`, "g");
|