149 lines
4.2 KiB
JavaScript
149 lines
4.2 KiB
JavaScript
import { u as unpackMeta } from './unhead.DQc16pHI.mjs';
|
|
|
|
function defineHeadPlugin(plugin) {
|
|
return plugin;
|
|
}
|
|
|
|
const FlatMetaPlugin = /* @__PURE__ */ defineHeadPlugin({
|
|
key: "flatMeta",
|
|
hooks: {
|
|
"entries:normalize": (ctx) => {
|
|
const tagsToAdd = [];
|
|
ctx.tags = ctx.tags.map((t) => {
|
|
if (t.tag !== "_flatMeta") {
|
|
return t;
|
|
}
|
|
tagsToAdd.push(unpackMeta(t.props).map((p) => ({
|
|
...t,
|
|
tag: "meta",
|
|
props: p
|
|
})));
|
|
return false;
|
|
}).filter(Boolean).concat(...tagsToAdd);
|
|
}
|
|
}
|
|
});
|
|
|
|
const WhitelistAttributes = {
|
|
htmlAttrs: /* @__PURE__ */ new Set(["class", "style", "lang", "dir"]),
|
|
bodyAttrs: /* @__PURE__ */ new Set(["class", "style"]),
|
|
meta: /* @__PURE__ */ new Set(["name", "property", "charset", "content", "media"]),
|
|
noscript: /* @__PURE__ */ new Set(["textContent"]),
|
|
style: /* @__PURE__ */ new Set(["media", "textContent", "nonce", "title", "blocking"]),
|
|
script: /* @__PURE__ */ new Set(["type", "textContent", "nonce", "blocking"]),
|
|
link: /* @__PURE__ */ new Set(["color", "crossorigin", "fetchpriority", "href", "hreflang", "imagesrcset", "imagesizes", "integrity", "media", "referrerpolicy", "rel", "sizes", "type"])
|
|
};
|
|
function acceptDataAttrs(value) {
|
|
return Object.fromEntries(
|
|
Object.entries(value || {}).filter(([key]) => key === "id" || key.startsWith("data-"))
|
|
);
|
|
}
|
|
function makeTagSafe(tag) {
|
|
let next = {};
|
|
const { tag: type, props: prev } = tag;
|
|
switch (type) {
|
|
// always safe
|
|
case "title":
|
|
case "titleTemplate":
|
|
case "templateParams":
|
|
next = prev;
|
|
break;
|
|
case "htmlAttrs":
|
|
case "bodyAttrs":
|
|
WhitelistAttributes[type].forEach((attr) => {
|
|
if (prev[attr]) {
|
|
next[attr] = prev[attr];
|
|
}
|
|
});
|
|
break;
|
|
case "style":
|
|
next = acceptDataAttrs(prev);
|
|
WhitelistAttributes.style.forEach((key) => {
|
|
if (prev[key]) {
|
|
next[key] = prev[key];
|
|
}
|
|
});
|
|
break;
|
|
// meta is safe, except for http-equiv
|
|
case "meta":
|
|
WhitelistAttributes.meta.forEach((key) => {
|
|
if (prev[key]) {
|
|
next[key] = prev[key];
|
|
}
|
|
});
|
|
break;
|
|
// link tags we don't allow stylesheets, scripts, preloading, prerendering, prefetching, etc
|
|
case "link":
|
|
WhitelistAttributes.link.forEach((key) => {
|
|
const val = prev[key];
|
|
if (!val) {
|
|
return;
|
|
}
|
|
if (key === "rel" && (val === "canonical" || val === "modulepreload" || val === "prerender" || val === "preload" || val === "prefetch")) {
|
|
return;
|
|
}
|
|
if (key === "href") {
|
|
if (val.includes("javascript:") || val.includes("data:")) {
|
|
return;
|
|
}
|
|
next[key] = val;
|
|
} else if (val) {
|
|
next[key] = val;
|
|
}
|
|
});
|
|
if (!next.href && !next.imagesrcset || !next.rel) {
|
|
return false;
|
|
}
|
|
break;
|
|
case "noscript":
|
|
WhitelistAttributes.noscript.forEach((key) => {
|
|
if (prev[key]) {
|
|
next[key] = prev[key];
|
|
}
|
|
});
|
|
break;
|
|
// we only allow JSON in scripts
|
|
case "script":
|
|
if (!tag.textContent || !prev.type?.endsWith("json")) {
|
|
return false;
|
|
}
|
|
WhitelistAttributes.script.forEach((s) => {
|
|
if (prev[s] === "textContent") {
|
|
try {
|
|
const jsonVal = typeof prev[s] === "string" ? JSON.parse(prev[s]) : prev[s];
|
|
next[s] = JSON.stringify(jsonVal, null, 0);
|
|
} catch {
|
|
}
|
|
} else if (prev[s]) {
|
|
next[s] = prev[s];
|
|
}
|
|
});
|
|
break;
|
|
}
|
|
if (!Object.keys(next).length && !tag.tag.endsWith("Attrs")) {
|
|
return false;
|
|
}
|
|
tag.props = { ...acceptDataAttrs(prev), ...next };
|
|
return tag;
|
|
}
|
|
const SafeInputPlugin = (
|
|
/* @PURE */
|
|
defineHeadPlugin({
|
|
key: "safe",
|
|
hooks: {
|
|
"entries:normalize": (ctx) => {
|
|
if (ctx.entry.options?._safe) {
|
|
ctx.tags = ctx.tags.reduce((acc, tag) => {
|
|
const safeTag = makeTagSafe(tag);
|
|
if (safeTag)
|
|
acc.push(safeTag);
|
|
return acc;
|
|
}, []);
|
|
}
|
|
}
|
|
}
|
|
})
|
|
);
|
|
|
|
export { FlatMetaPlugin as F, SafeInputPlugin as S, defineHeadPlugin as d };
|