Files
console-dev/app/lib/sanitize.js
T
2026-11-06 00:04:38 +08:00

123 lines
3.4 KiB
JavaScript

var e = new Set(
`a.p.br.hr.div.span.h1.h2.h3.h4.h5.h6.b.strong.i.em.u.s.del.ins.sub.sup.small.mark.blockquote.pre.code.kbd.ul.ol.li.dl.dt.dd.table.thead.tbody.tfoot.tr.th.td.caption.colgroup.col.img.figure.figcaption`.split(
`.`,
),
),
t = new Set([
`script`,
`style`,
`iframe`,
`object`,
`embed`,
`link`,
`meta`,
`base`,
`form`,
`input`,
`button`,
`textarea`,
`select`,
`option`,
`template`,
`noscript`,
`noembed`,
`noframes`,
`xmp`,
`plaintext`,
`svg`,
`math`,
`audio`,
`video`,
`source`,
]);
function n(e, t = !1) {
if (!e || /[\u0000-\u001f\u007f]/.test(e)) return !1;
if (
t &&
/^data:image\/(?:png|jpeg|gif|webp|avif);base64,[a-z\d+/]+={0,2}$/i.test(e)
)
return !0;
try {
let n = new URL(e, `https://sanitizer.invalid/`).protocol;
return (
n === `https:` ||
n === `http:` ||
(!t && (n === `mailto:` || n === `tel:`))
);
} catch {
return !1;
}
}
function r(r) {
if (!r) return ``;
let i = new DOMParser().parseFromString(r, `text/html`),
a = i.createElement(`div`);
function o(r, a) {
if (r.nodeType === 3) {
a.appendChild(i.createTextNode(r.textContent ?? ``));
return;
}
if (r.nodeType !== 1) return;
let s = r,
c = s.localName;
if (s.namespaceURI !== `http://www.w3.org/1999/xhtml` || t.has(c)) return;
let l = a;
if (e.has(c)) {
let e = i.createElement(c);
for (let t of Array.from(s.attributes)) {
let r = t.name.toLowerCase(),
i = t.value.trim();
t.namespaceURI === null &&
(r === `title` || (r === `alt` && c === `img`)
? e.setAttribute(r, t.value)
: r === `style` &&
/^(p|div|h[1-6])$/.test(c) &&
/^text-align:\s*(left|center|right|justify);?$/i.test(i)
? e.setAttribute(`style`, i.toLowerCase())
: ((r === `dir` && /^(ltr|rtl|auto)$/.test(i)) ||
(r === `href` && c === `a` && n(i)) ||
(r === `src` && c === `img` && n(i, !0)) ||
(r === `target` &&
c === `a` &&
/^(?:_blank|_self)$/.test(i)) ||
(r === `scope` &&
c === `th` &&
/^(?:row|col|rowgroup|colgroup)$/.test(i)) ||
((((r === `colspan` || r === `rowspan`) &&
(c === `td` || c === `th`)) ||
((r === `width` || r === `height`) && c === `img`) ||
(r === `span` && (c === `col` || c === `colgroup`)) ||
(r === `start` && c === `ol`)) &&
/^\d{1,4}$/.test(i) &&
Number(i) > 0)) &&
e.setAttribute(r, i));
}
(c === `a` &&
e.getAttribute(`target`) === `_blank` &&
e.setAttribute(`rel`, `noopener noreferrer`),
a.appendChild(e),
(l = e));
}
for (let e of Array.from(r.childNodes)) o(e, l);
}
for (let e of Array.from(i.body.childNodes)) o(e, a);
return a.innerHTML;
}
function i(e) {
if (!e) return ``;
let t = e;
for (
let e = 0;
e < 2 && /&(?:amp|lt|gt|quot|#\d+|#x[0-9a-f]+);/i.test(t);
e++
) {
let e =
new DOMParser().parseFromString(t, `text/html`).documentElement
.textContent ?? t;
if (e === t) break;
t = e;
}
return t;
}
export { r as n, i as t };