diff --git a/docs/assets/css/chartifact-reset.css b/docs/dist/v1/chartifact-reset.css similarity index 100% rename from docs/assets/css/chartifact-reset.css rename to docs/dist/v1/chartifact-reset.css diff --git a/docs/dist/v1/chartifact.markdown.umd.js b/docs/dist/v1/chartifact.markdown.umd.js new file mode 100644 index 00000000..dd5d37f3 --- /dev/null +++ b/docs/dist/v1/chartifact.markdown.umd.js @@ -0,0 +1,2749 @@ +(function(global, factory) { + typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("vega"), require("vega-lite")) : typeof define === "function" && define.amd ? define(["exports", "vega", "vega-lite"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.Chartifact = global.Chartifact || {}, global.vega, global.vegaLite)); +})(this, (function(exports2, vega, vegaLite) { + "use strict";var __defProp = Object.defineProperty; +var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; +var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); + + const defaultCommonOptions = { + dataSignalPrefix: "data_signal:", + groupClassName: "group" + }; + function collectIdentifiers(ast) { + const identifiers = /* @__PURE__ */ new Set(); + function walk(node) { + if (!node || typeof node !== "object") + return; + switch (node.type) { + case "Identifier": + if (!VEGA_BUILTIN_FUNCTIONS.includes(node.name)) { + identifiers.add(node.name); + } + break; + case "CallExpression": + walk(node.callee); + (node.arguments || []).forEach(walk); + break; + case "MemberExpression": + walk(node.object); + break; + case "BinaryExpression": + case "LogicalExpression": + walk(node.left); + walk(node.right); + break; + case "ConditionalExpression": + walk(node.test); + walk(node.consequent); + walk(node.alternate); + break; + case "ArrayExpression": + (node.elements || []).forEach(walk); + break; + default: + for (const key in node) { + if (node.hasOwnProperty(key)) { + const value = node[key]; + if (Array.isArray(value)) + value.forEach(walk); + else if (typeof value === "object") + walk(value); + } + } + } + } + walk(ast); + return identifiers; + } + const VEGA_BUILTIN_FUNCTIONS = Object.freeze([ + // Built-ins from Vega Expression docs + "abs", + "acos", + "asin", + "atan", + "atan2", + "ceil", + "clamp", + "cos", + "exp", + "expm1", + "floor", + "hypot", + "log", + "log1p", + "max", + "min", + "pow", + "random", + "round", + "sign", + "sin", + "sqrt", + "tan", + "trunc", + "length", + "isNaN", + "isFinite", + "parseFloat", + "parseInt", + "Date", + "now", + "time", + "utc", + "timezoneOffset", + "quarter", + "month", + "day", + "hours", + "minutes", + "seconds", + "milliseconds", + "year" + ]); + function tokenizeTemplate(input) { + const allVars = /{{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g; + const tokens = []; + let lastIndex = 0; + input.replace(allVars, (match, varName, offset) => { + const staticPart = input.slice(lastIndex, offset); + if (staticPart) { + tokens.push({ type: "literal", value: staticPart }); + } + tokens.push({ type: "variable", name: varName }); + lastIndex = offset + match.length; + return match; + }); + const tail = input.slice(lastIndex); + if (tail) { + tokens.push({ type: "literal", value: tail }); + } + return tokens; + } + function renderVegaExpression(tokens, funcName = "encodeURIComponent") { + if (tokens.length === 1 && tokens[0].type === "variable") { + return tokens[0].name; + } + const escape = (str) => `'${str.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`; + return tokens.map((token) => token.type === "literal" ? escape(token.value) : `${funcName}(${token.name})`).join(" + "); + } + function encodeTemplateVariables(input) { + const tokens = tokenizeTemplate(input); + return renderVegaExpression(tokens); + } + const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ + __proto__: null, + VEGA_BUILTIN_FUNCTIONS, + collectIdentifiers, + defaultCommonOptions, + encodeTemplateVariables, + renderVegaExpression, + tokenizeTemplate + }, Symbol.toStringTag, { value: "Module" })); + const u = (e, t) => { + t && e.forEach(([s, n]) => { + switch (s) { + case "class": + t.attrJoin("class", n); + break; + case "css-module": + t.attrJoin("css-module", n); + break; + default: + t.attrPush([s, n]); + } + }); + }, _ = ".", x = "#", v = /[^\t\n\f />"'=]/, O = " ", E = "=", d = (e, t, { left: s, right: n, allowed: o }) => { + let i = "", l = "", r = true, c = false; + const f = []; + for (let h = t + s.length; h < e.length; h++) { + if (e.slice(h, h + n.length) === n) { + i !== "" && f.push([i, l]); + break; + } + const a = e.charAt(h); + if (a === E && r) { + r = false; + continue; + } + if (a === _ && i === "") { + e.charAt(h + 1) === _ ? (i = "css-module", h++) : i = "class", r = false; + continue; + } + if (a === x && i === "") { + i = "id", r = false; + continue; + } + if (a === '"' && l === "" && !c) { + c = true; + continue; + } + if (a === '"' && c) { + c = false; + continue; + } + if (a === O && !c) { + if (i === "") continue; + f.push([i, l]), i = "", l = "", r = true; + continue; + } + if (!(r && a.search(v) === -1)) { + if (r) { + i += a; + continue; + } + l += a; + } + } + return o.length ? f.filter(([h]) => o.some((a) => a instanceof RegExp ? a.test(h) : a === h)) : f; + }, y = ({ left: e, right: t }, s) => { + if (!["start", "end", "only"].includes(s)) throw new Error(`Invalid 'where' parameter: ${s}. Expected 'start', 'end', or 'only'.`); + return (n) => { + const o = e.length, i = t.length, l = o + 1 + i, r = o + 1; + if (!n || typeof n != "string" || n.length < l) return false; + const c = (p) => [_, x].includes(p.charAt(o)) ? p.length >= l + 1 : p.length >= l; + let f, h, a, m; + return s === "start" ? (a = n.slice(0, o), f = a === e ? 0 : -1, h = f === -1 ? -1 : n.indexOf(t, r), m = n.charAt(h + i), m && t.includes(m) && (h = -1)) : s === "end" ? (f = n.lastIndexOf(e), h = f === -1 ? -1 : n.indexOf(t, f + r), h = h === n.length - i ? h : -1) : (a = n.slice(0, o), f = a === e ? 0 : -1, a = n.slice(n.length - i), h = a === t ? n.length - i : -1), f !== -1 && h !== -1 && c(n.substring(f, h + i)); + }; + }, g = (e, t) => { + const s = e[t]; + if (s.type === "softbreak") return null; + if (s.nesting === 0) return s; + const n = s.level, o = s.type.replace("_close", "_open"); + for (; t >= 0; ) { + const i = e[t]; + if (i.type === o && i.level === n) return i; + t--; + } + /* istanbul ignore next -- @preserve */ + return null; + }, b = (e) => e.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"), w = (e, t, s) => { + const n = b(t), o = b(s), i = e.search(new RegExp(`[ \\n]?${n}[^${n}${o}]+${o}$`)); + return i !== -1 ? e.slice(0, i) : e; + }, $ = (e, t) => t >= 0 ? e[t] : e[e.length + t], C = (e) => Array.isArray(e) && !!e.length && e.every((t) => typeof t == "function"), I = (e) => Array.isArray(e) && !!e.length && e.every((t) => typeof t == "object"), k = (e, t, s) => { + var _a, _b; + const n = { match: false, position: null }, o = s.shift !== void 0 ? t + s.shift : s.position; + if (s.shift !== void 0 && o < 0) return n; + const i = $(e, o); + if (!i) return n; + for (const l of Object.keys(s)) { + if (l === "shift" || l === "position") continue; + if (i[l] === void 0) return n; + if (l === "children" && I(s.children)) { + if (((_a = i.children) == null ? void 0 : _a.length) === 0) return n; + let c; + const f = s.children, h = i.children; + if (f.every((a) => a.position !== void 0)) { + if (c = f.every((a) => k(h, a.position, a).match), c) { + const a = ((_b = f[f.length - 1]) == null ? void 0 : _b.position) ?? 0; + n.position = a >= 0 ? a : h.length + a; + } + } else for (let a = 0; a < h.length; a++) if (c = f.every((m) => k(h, a, m).match), c) { + n.position = a; + break; + } + if (c === false) return n; + continue; + } + const r = s[l]; + switch (typeof r) { + case "boolean": + case "number": + case "string": { + if (i[l] !== r) return n; + break; + } + case "function": { + if (!r(i[l])) return n; + break; + } + default: { + if (C(r)) { + if (!r.every((c) => c(i[l]))) return n; + break; + } + throw new Error(`Unknown type of pattern test (key: ${l}). Test should be of type boolean, number, string, function or array of functions.`); + } + } + } + return n.match = true, n; + }, S = (e) => ({ name: "end of block", tests: [{ shift: 0, type: "inline", children: [{ position: -1, content: y(e, "end"), type: (t) => t !== "code_inline" && t !== "math_inline" }] }], transform: (t, s, n) => { + const o = t[s].children[n], { content: i } = o, l = i.lastIndexOf(e.left), r = d(i, l, e); + let c = s + 1; + for (; t[c + 1] && t[c + 1].nesting === -1; ) c++; + const f = g(t, c); + u(r, f); + const h = i.slice(0, l), a = h[h.length - 1] === " "; + o.content = a ? h.slice(0, -1) : h; + } }), T = (e) => ({ name: "code-block", tests: [{ shift: 0, block: true, info: y(e, "end") }], transform: (t, s) => { + const n = t[s]; + let o = ""; + const i = /{(?:[\d,-]+)}/.exec(n.info); + i && (n.info = n.info.replace(i[0], ""), o = i[0]); + const l = n.info.lastIndexOf(e.left), r = d(n.info, l, e); + u(r, n); + const c = w(n.info, e.left, e.right); + n.info = `${c} ${o}`.trim(); + } }), D = (e) => [{ name: "inline nesting self-close", tests: [{ shift: 0, type: "inline", children: [{ shift: -1, type: (t) => t === "image" || t === "code_inline" }, { shift: 0, type: "text", content: y(e, "start") }] }], transform: (t, s, n) => { + const o = e.right.length, i = t[s].children[n], l = i.content.indexOf(e.right), r = t[s].children[n - 1], c = d(i.content, 0, e); + u(c, r), i.content.length === l + o ? t[s].children.splice(n, 1) : i.content = i.content.slice(l + o); + } }, { name: "inline attributes", tests: [{ shift: 0, type: "inline", children: [{ shift: -1, nesting: -1 }, { shift: 0, type: "text", content: y(e, "start") }] }], transform: (t, s, n) => { + const o = t[s].children[n], { content: i } = o, l = d(i, 0, e), r = g(t[s].children, n - 1); + u(l, r); + const c = i.indexOf(e.right) + e.right.length; + o.content = i.slice(c); + } }], K = (e) => [{ name: "list softbreak", tests: [{ shift: -2, type: "list_item_open" }, { shift: 0, type: "inline", children: [{ position: -2, type: "softbreak" }, { position: -1, type: "text", content: y(e, "only") }] }], transform: (t, s, n) => { + const o = t[s].children[n], i = d(o.content, 0, e); + let l = s - 2; + for (; t[l - 1] && t[l - 1].type !== "ordered_list_open" && t[l - 1].type !== "bullet_list_open"; ) l--; + u(i, t[l - 1]), t[s].children = t[s].children.slice(0, -2); + } }, { name: "list double softbreak", tests: [{ shift: 0, type: (t) => t === "bullet_list_close" || t === "ordered_list_close" }, { shift: 1, type: "paragraph_open" }, { shift: 2, type: "inline", content: y(e, "only"), children: (t) => t.length === 1 }, { shift: 3, type: "paragraph_close" }], transform: (t, s) => { + const n = t[s + 2], o = d(n.content, 0, e), i = g(t, s); + u(o, i), t.splice(s + 1, 3); + } }, { name: "list item end", tests: [{ shift: -2, type: "list_item_open" }, { shift: 0, type: "inline", children: [{ position: -1, type: "text", content: y(e, "end") }] }], transform: (t, s, n) => { + const o = t[s].children[n], { content: i } = o, l = i.lastIndexOf(e.left), r = d(i, l, e); + u(r, t[s - 2]); + const c = i.slice(0, l), f = c[c.length - 1] === " "; + o.content = f ? c.slice(0, -1) : c; + } }], L = (e) => ({ name: ` +{.a} softbreak then curly in start`, tests: [{ shift: 0, type: "inline", children: [{ position: -2, type: "softbreak" }, { position: -1, type: "text", content: y(e, "only") }] }], transform: (t, s, n) => { + const o = t[s].children[n], i = d(o.content, 0, e); + let l = s + 1; + for (; t[l + 1] && t[l + 1].nesting === -1; ) l++; + const r = g(t, l); + u(i, r), t[s].children = t[s].children.slice(0, -2); + } }), M = (e) => ({ name: "horizontal rule", tests: [{ shift: 0, type: "paragraph_open" }, { shift: 1, type: "inline", children: (t) => t.length === 1, content: (t) => new RegExp(`^ {0,3}[-*_]{3,} ?${b(e.left)}[^${b(e.right)}]`).test(t) }, { shift: 2, type: "paragraph_close" }], transform: (t, s) => { + const n = t[s]; + n.type = "hr", n.tag = "hr", n.nesting = 0; + const o = t[s + 1], { content: i } = o, l = i.lastIndexOf(e.left), r = d(i, l, e); + u(r, n), n.markup = i, t.splice(s + 1, 2); + } }), A = (e) => { + var _a; + e.hidden = true, (_a = e.children) == null ? void 0 : _a.forEach((t) => { + t.content = "", A(t); + }); + }, P = (e, t, s, n, o, i) => { + let l = n - (o > 0 ? o : 1); + for (let r = t, c = i; r < s && c > 1; r++) if (e[r].type === "tr_open") { + const f = e[r]; + f.meta ?? (f.meta = {}), f.meta.columnCount && (l -= 1), f.meta.columnCount = l, c--; + } + }, j = (e, t, s) => { + var _a; + const n = (_a = e[t].meta) == null ? void 0 : _a.columnCount; + if (n) for (let o = t, i = 0; o < s; o++) { + const l = e[o]; + if (l.type === "td_open") i += 1; + else if (l.type === "tr_close") break; + i > n && !l.hidden && A(l); + } + }, N = (e, t, s, n, o, i) => { + var _a; + const l = [], r = e[t]; + let c = t + 3, f = n; + for (let p = t; p > i; p--) if (e[p].type === "tr_open") { + f = ((_a = e[p].meta) == null ? void 0 : _a.columnCount) ?? f; + break; + } else e[p].type === "td_open" && l.unshift(p); + for (let p = t + 2; p < s; p++) if (e[p].type === "tr_close") { + c = p; + break; + } else e[p].type === "td_open" && l.push(p); + const h = l.indexOf(t), a = Math.min(o, f - h); + o > a && r.attrSet("colspan", a.toString()); + const m = l.slice(f + 1 - n - a)[0]; + for (let p = m; p < c; p++) e[p].hidden || A(e[p]); + }, B = (e) => [{ name: "table", tests: [{ shift: 0, type: "table_close" }, { shift: 1, type: "paragraph_open" }, { shift: 2, type: "inline", content: y(e, "only") }], transform: (t, s) => { + const n = t[s + 2], o = g(t, s), i = d(n.content, 0, e); + u(i, o), t.splice(s + 1, 3); + } }, { name: "table cell attributes", tests: [{ shift: -1, type: (t) => t === "td_open" || t === "th_open" }, { shift: 0, type: "inline", children: [{ shift: 0, type: "text", content: y(e, "end") }] }], transform: (t, s, n) => { + const o = t[s].children[n], i = t[s - 1], { content: l } = o, r = l.lastIndexOf(e.left), c = d(l, r, e); + u(c, i), o.content = l.substring(0, r).trim(); + } }, { name: "table thead metadata", tests: [{ shift: 0, type: "tr_close" }, { shift: 1, type: "thead_close" }, { shift: 2, type: "tbody_open" }], transform: (t, s) => { + const n = g(t, s), o = t[s - 1]; + let i = 0, l = s - 1; + for (; l > 0; ) { + const c = t[l]; + if (c === n) { + const f = t[l - 1]; + f.meta = { ...f.meta, columnCount: i }; + break; + } + c.level === o.level && c.type === o.type && i++, l--; + } + const r = t[s + 2]; + r.meta = { ...r.meta, columnCount: i }; + } }, { name: "table tbody calculate", tests: [{ shift: 0, type: "tbody_close", hidden: false }], transform: (t, s) => { + var _a; + let n = s - 2; + for (; n > 0 && (n--, t[n].type !== "tbody_open"); ) ; + const o = Number(((_a = t[n].meta) == null ? void 0 : _a.columnCount) ?? 0); + if (o < 2) return; + const i = t[s].level + 2; + for (let l = n; l < s; l++) { + if (t[l].level > i) continue; + const r = t[l], c = r.hidden ? 0 : Number(r.attrGet("rowspan")), f = r.hidden ? 0 : Number(r.attrGet("colspan")); + c > 1 && P(t, l, s, o, f, c), r.type === "tr_open" && j(t, l, s), f > 1 && N(t, l, s, o, f, n); + } + } }], R$1 = ["fence", "inline", "table", "list", "hr", "softbreak", "block"], F = (e) => { + const t = e.rule === false ? [] : Array.isArray(e.rule) ? e.rule.filter((n) => R$1.includes(n)) : R$1, s = []; + return t.includes("fence") && s.push(T(e)), t.includes("inline") && s.push(...D(e)), t.includes("table") && s.push(...B(e)), t.includes("list") && s.push(...K(e)), t.includes("softbreak") && s.push(L(e)), t.includes("hr") && s.push(M(e)), t.includes("block") && s.push(S(e)), s; + }, G = (e, { left: t = "{", right: s = "}", allowed: n = [], rule: o = "all" } = {}) => { + const i = F({ left: t, right: s, allowed: n, rule: o }), l = ({ tokens: r }) => { + for (let c = 0; c < r.length; c++) for (let f = 0; f < i.length; f++) { + const h = i[f]; + let a = null; + h.tests.every((m) => { + const p = k(r, c, m); + return p.position !== null && ({ position: a } = p), p.match; + }) && (h.transform(r, c, a), (h.name === "inline attributes" || h.name === "inline nesting self-close") && f--); + } + }; + e.core.ruler.before("linkify", "attrs", l); + }; + const R = (p, u2) => { + if (typeof u2 != "object" || !u2.name) throw new Error("[@mdit/plugin-container]: 'name' option is required."); + const { name: n, marker: c = ":", validate: $2 = (e) => e.trim().split(" ", 2)[0] === n, openRender: g2 = (e, t, l, k2, a) => (e[t].attrJoin("class", n), a.renderToken(e, t, l)), closeRender: C2 = (e, t, l, k2, a) => a.renderToken(e, t, l) } = u2, M2 = c[0], i = c.length, I2 = (e, t, l, k2) => { + const a = e.bMarks[t] + e.tShift[t], _2 = e.eMarks[t], d2 = e.sCount[t]; + if (M2 !== e.src[a]) return false; + let r = a + 1; + for (; r <= _2 && c[(r - a) % i] === e.src[r]; ) r++; + const b2 = Math.floor((r - a) / i); + if (b2 < 3) return false; + r -= (r - a) % i; + const m = c.repeat(b2), T2 = e.src.slice(r, _2); + if (!$2(T2, m)) return false; + if (k2) return true; + let o = t + 1, x2 = false; + for (; o < l; o++) { + const s = e.bMarks[o] + e.tShift[o], h = e.eMarks[o]; + if (s < h && e.sCount[o] < d2) break; + if (e.sCount[o] === d2 && M2 === e.src[s]) { + for (r = s + 1; r <= h && c[(r - s) % i] === e.src[r]; r++) ; + if (Math.floor((r - s) / i) >= b2 && (r -= (r - s) % i, r = e.skipSpaces(r), r >= h)) { + x2 = true; + break; + } + } + } + const S2 = e.parentType, v2 = e.lineMax, w2 = e.blkIndent; + e.parentType = "container", e.lineMax = o, e.blkIndent = d2; + const f = e.push(`container_${n}_open`, "div", 1); + f.markup = m, f.block = true, f.info = T2, f.map = [t, o], e.md.block.tokenize(e, t + 1, o); + const y2 = e.push(`container_${n}_close`, "div", -1); + return y2.markup = m, y2.block = true, e.parentType = S2, e.lineMax = v2, e.blkIndent = w2, e.line = o + (x2 ? 1 : 0), true; + }; + p.block.ruler.before("fence", `container_${n}`, I2, { alt: ["paragraph", "reference", "blockquote", "list"] }), p.renderer.rules[`container_${n}_open`] = g2, p.renderer.rules[`container_${n}_close`] = C2; + }; + const plugins = []; + function registerMarkdownPlugin(plugin) { + let insertIndex = plugins.length; + let minIndex = 0; + for (let i = 0; i < plugins.length; i++) { + if (plugins[i].hydratesBefore === plugin.name) { + minIndex = Math.max(minIndex, i + 1); + } + } + if (plugin.hydratesBefore) { + const targetIndex = plugins.findIndex((p) => p.name === plugin.hydratesBefore); + if (targetIndex !== -1) { + insertIndex = targetIndex; + } + } + insertIndex = Math.max(insertIndex, minIndex); + plugins.splice(insertIndex, 0, plugin); + return "register"; + } + function create() { + var _a; + const md = new markdownit(); + for (const plugin of plugins) { + (_a = plugin.initializePlugin) == null ? void 0 : _a.call(plugin, md); + } + md.use(G); + const containerOptions = { name: defaultCommonOptions.groupClassName }; + md.use(R, containerOptions); + const originalFence = md.renderer.rules.fence; + md.renderer.rules.fence = function(tokens, idx, options, env, slf) { + const token = tokens[idx]; + const info = token.info.trim(); + const findPlugin = (pluginName2) => { + const plugin = plugins.find((p) => p.name === pluginName2); + if (plugin && plugin.fence) { + return plugin.fence(token, idx); + } + }; + if (info.startsWith("#")) { + return findPlugin("#"); + } else { + const directPlugin = findPlugin(info); + if (directPlugin) { + return directPlugin; + } else if (info.startsWith("json ")) { + const jsonPluginName = info.slice(5).trim(); + const jsonPlugin = findPlugin(jsonPluginName); + if (jsonPlugin) { + return jsonPlugin; + } + } + } + if (originalFence) { + return originalFence(tokens, idx, options, env, slf); + } else { + return ""; + } + }; + return md; + } + function getJsonScriptTag(container, errorHandler) { + const scriptTag = container.previousElementSibling; + if ((scriptTag == null ? void 0 : scriptTag.tagName) !== "SCRIPT" || scriptTag.getAttribute("type") !== "application/json") { + errorHandler(new Error("Invalid JSON script tag")); + return null; + } + if (!scriptTag.textContent) { + errorHandler(new Error("Empty JSON script tag")); + return null; + } + try { + return JSON.parse(scriptTag.textContent); + } catch (error) { + errorHandler(error); + return null; + } + } + function pluginClassName(pluginName2) { + return `chartifact-plugin-${pluginName2}`; + } + const newId = () => [...Date.now().toString(36) + Math.random().toString(36).slice(2)].sort(() => 0.5 - Math.random()).join(""); + function sanitizedHTML(tagName, attributes, content, precedeWithScriptTag) { + const element = document.createElement(tagName); + Object.keys(attributes).forEach((key) => { + element.setAttribute(key, attributes[key]); + }); + if (precedeWithScriptTag) { + const scriptElement = document.createElement("script"); + scriptElement.setAttribute("type", "application/json"); + const safeContent = content.replace(/<\/script>/gi, "<\\/script>"); + scriptElement.innerHTML = safeContent; + return scriptElement.outerHTML + element.outerHTML; + } else { + element.textContent = content; + } + return element.outerHTML; + } + function sanitizeHtmlComment(content) { + const tempElement = document.createElement("div"); + tempElement.textContent = content; + const safeContent = tempElement.innerHTML; + const comment = document.createComment(safeContent); + const container = document.createElement("div"); + container.appendChild(comment); + return container.innerHTML; + } + function flaggableJsonPlugin(pluginName2, className2, flagger, attrs) { + const plugin = { + name: pluginName2, + fence: (token, index2) => { + let json = token.content.trim(); + let spec; + let flaggableSpec; + try { + spec = JSON.parse(json); + } catch (e) { + flaggableSpec = { + spec: null, + hasFlags: true, + reasons: [`malformed JSON`] + }; + } + if (spec) { + if (flagger) { + flaggableSpec = flagger(spec); + } else { + flaggableSpec = { spec }; + } + } + if (flaggableSpec) { + json = JSON.stringify(flaggableSpec); + } + return sanitizedHTML("div", { class: className2, id: `${pluginName2}-${index2}`, ...attrs }, json, true); + }, + hydrateSpecs: (renderer, errorHandler) => { + var _a; + const flagged = []; + const containers = renderer.element.querySelectorAll(`.${className2}`); + for (const [index2, container] of Array.from(containers).entries()) { + const flaggableSpec = getJsonScriptTag(container, (e) => errorHandler(e, pluginName2, index2, "parse", container)); + if (!flaggableSpec) continue; + const f = { approvedSpec: null, pluginName: pluginName2, containerId: container.id }; + if (flaggableSpec.hasFlags) { + f.blockedSpec = flaggableSpec.spec; + f.reason = ((_a = flaggableSpec.reasons) == null ? void 0 : _a.join(", ")) || "Unknown reason"; + } else { + f.approvedSpec = flaggableSpec.spec; + } + flagged.push(f); + } + return flagged; + } + }; + return plugin; + } + const pluginName$c = "checkbox"; + const className$a = pluginClassName(pluginName$c); + const checkboxPlugin = { + ...flaggableJsonPlugin(pluginName$c, className$a), + hydrateComponent: async (renderer, errorHandler, specs) => { + const checkboxInstances = []; + for (let index2 = 0; index2 < specs.length; index2++) { + const specReview = specs[index2]; + if (!specReview.approvedSpec) { + continue; + } + const container = renderer.element.querySelector(`#${specReview.containerId}`); + const spec = specReview.approvedSpec; + const html = `
`; + container.innerHTML = html; + const element = container.querySelector('input[type="checkbox"]'); + const checkboxInstance = { id: `${pluginName$c}-${index2}`, spec, element }; + checkboxInstances.push(checkboxInstance); + } + const instances = checkboxInstances.map((checkboxInstance) => { + const { element, spec } = checkboxInstance; + const initialSignals = [{ + name: spec.variableId, + value: spec.value || false, + priority: 1, + isData: false + }]; + return { + ...checkboxInstance, + initialSignals, + receiveBatch: async (batch) => { + if (batch[spec.variableId]) { + const value = batch[spec.variableId].value; + element.checked = value; + } + }, + beginListening() { + element.addEventListener("change", (e) => { + const value = e.target.checked; + const batch = { + [spec.variableId]: { + value, + isData: false + } + }; + renderer.signalBus.broadcast(checkboxInstance.id, batch); + }); + }, + getCurrentSignalValue: () => { + return element.checked; + }, + destroy: () => { + element.removeEventListener("change", checkboxInstance.element.onchange); + } + }; + }); + return instances; + } + }; + const pluginName$b = "#"; + const commentPlugin = { + name: pluginName$b, + fence: (token) => { + const content = token.content.trim(); + return sanitizeHtmlComment(content); + } + }; + function reconstituteAtRule(atRule) { + if (atRule.css) { + return atRule.flag ? `/* ${atRule.css} - BLOCKED: ${atRule.reason} */` : atRule.css; + } + if (!atRule.rules || atRule.rules.length === 0) return ""; + const reconstitutedRules = []; + for (const rule of atRule.rules) { + const validDeclarations = rule.declarations.map((decl) => decl.css).filter((css) => css.trim() !== ""); + if (validDeclarations.length > 0) { + reconstitutedRules.push(`${rule.selector} { + ${validDeclarations.join(";\n ")}; +}`); + } + } + if (reconstitutedRules.length === 0) return ""; + if (atRule.signature === "") { + return reconstitutedRules.join("\n\n"); + } else { + return `${atRule.signature} { +${reconstitutedRules.join("\n\n")} +}`; + } + } + function reconstituteCss(atRules) { + const cssBlocks = []; + for (const atRule of Object.values(atRules)) { + const reconstructed = reconstituteAtRule(atRule); + if (reconstructed.trim()) { + cssBlocks.push(reconstructed); + } + } + return cssBlocks.join("\n\n"); + } + function categorizeCss(cssContent) { + const spec = { + atRules: {} + }; + const result = { + spec, + hasFlags: false, + reasons: [] + }; + const completeBlockAtRules = [ + // Keyframes and variants + "keyframes", + "-webkit-keyframes", + "-moz-keyframes", + "-o-keyframes", + // Font-related at-rules + "font-face", + "font-feature-values", + "font-palette-values", + // Page and counter styling + "page", + "counter-style", + // CSS Houdini and newer features + "property", + "layer", + "container", + "scope", + "starting-style", + "position-try" + ]; + function checkSecurityIssues(node) { + if (node.type === "Function" && node.name === "expression") { + return { flag: "scriptExec", reason: "CSS expression() function detected" }; + } + if (node.type === "Url") { + const urlValue = node.value; + if (!urlValue) return null; + const url = urlValue.value || urlValue; + const urlStr = url.toLowerCase(); + if (urlStr.startsWith("javascript:") || urlStr.startsWith("vbscript:")) { + return { flag: "scriptExec", reason: `${urlStr.split(":")[0]} URL detected` }; + } + if (urlStr.startsWith("data:")) { + if (urlStr.includes("data:image/svg+xml")) { + if (urlStr.includes("