Add sanitize
This commit is contained in:
@@ -1,12 +1,17 @@
|
|||||||
const isFn = (v) => typeof v === 'function';
|
const isFn = (v) => typeof v === 'function';
|
||||||
const isNode = (v) => v instanceof Node;
|
const isNode = (v) => v instanceof Node;
|
||||||
|
const DANGEROUS = /^(javascript|data|vbscript):/i;
|
||||||
|
const sanitize = v => DANGEROUS.test(String(v)) ? '#' : v;
|
||||||
|
|
||||||
let isScheduled = false, activeEffect = null, context = null;
|
let isScheduled = false, activeEffect = null, context = null;
|
||||||
const queue = new Set(), reactiveCache = new WeakMap();
|
const queue = new Set(), reactiveCache = new WeakMap();
|
||||||
|
|
||||||
const tick = () => {
|
const tick = () => {
|
||||||
queue.forEach(fn => fn());
|
while (queue.size) {
|
||||||
|
const runs = [...queue];
|
||||||
queue.clear();
|
queue.clear();
|
||||||
|
runs.forEach(fn => fn());
|
||||||
|
}
|
||||||
isScheduled = false;
|
isScheduled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,21 +165,28 @@ export const h = (tag, props = {}, ...children) => {
|
|||||||
else if (k === "ref") isFn(v) ? v(el) : v.value = el;
|
else if (k === "ref") isFn(v) ? v(el) : v.value = el;
|
||||||
else if (k === "on") el.$on = v;
|
else if (k === "on") el.$on = v;
|
||||||
else if (k === "off") el.$off = v;
|
else if (k === "off") el.$off = v;
|
||||||
else if (isFn(v) || v?._isSig) effect(() => el[k] = unwrap(v));
|
else if (isFn(v) || v?._isSig) effect(() => {
|
||||||
else el[k] = v;
|
const val = unwrap(v);
|
||||||
|
const attr = (k === 'href' || k === 'src') ? sanitize(val) : val;
|
||||||
|
el[k] = attr;
|
||||||
|
});
|
||||||
|
else {
|
||||||
|
const attr = (k === 'href' || k === 'src') ? sanitize(v) : v;
|
||||||
|
el[k] = attr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
children.forEach(c => append(el, c));
|
children.forEach(c => append(el, c));
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
const append = (p, c) => {
|
const append = (p, c) => {
|
||||||
if (c == null) return;
|
if (c == null || c === false || c === true) return;
|
||||||
if (isFn(c) || c?._isSig) {
|
if (isFn(c) || c?._isSig) {
|
||||||
const anchor = document.createTextNode('');
|
const anchor = document.createTextNode('');
|
||||||
p.appendChild(anchor);
|
p.appendChild(anchor);
|
||||||
let nodes = [];
|
let nodes = [];
|
||||||
effect(async () => {
|
effect(async () => {
|
||||||
const raw = [unwrap(c)].flat(Infinity).filter(n => n != null);
|
const raw = [unwrap(c)].flat(Infinity).filter(n => n != null && n !== false && n !== true);
|
||||||
const next = raw.map(n => isNode(n) ? n : document.createTextNode(String(n)));
|
const next = raw.map(n => isNode(n) ? n : document.createTextNode(String(n)));
|
||||||
for (const n of nodes) { if (!next.includes(n)) await remove(n); }
|
for (const n of nodes) { if (!next.includes(n)) await remove(n); }
|
||||||
next.forEach((n, i) => {
|
next.forEach((n, i) => {
|
||||||
@@ -243,7 +255,7 @@ export const Router = (routes, trans = {}) => {
|
|||||||
|
|
||||||
export const mount = (root, target, props = {}) => {
|
export const mount = (root, target, props = {}) => {
|
||||||
const container = typeof target === 'string' ? document.querySelector(target) : target;
|
const container = typeof target === 'string' ? document.querySelector(target) : target;
|
||||||
if (container.firstElementChild) remove(container.firstElementChild);
|
container.replaceChildren(); // Limpieza rápida moderna
|
||||||
const el = h(root, props);
|
const el = h(root, props);
|
||||||
container.appendChild(el);
|
container.appendChild(el);
|
||||||
if (el.$on) el.$on(el);
|
if (el.$on) el.$on(el);
|
||||||
|
|||||||
Reference in New Issue
Block a user