dom-expressions 0.40.11 → 0.40.12
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/package.json +2 -2
- package/src/server.js +59 -12
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dom-expressions",
|
|
3
3
|
"description": "A Fine-Grained Runtime for Performant DOM Rendering",
|
|
4
|
-
"version": "0.40.
|
|
4
|
+
"version": "0.40.12",
|
|
5
5
|
"author": "Ryan Carniato",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"seroval": "~1.6.8",
|
|
30
30
|
"seroval-plugins": "~1.6.8"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "27a88bea8ffa97400bbcc66d380e40daed9e1cf1"
|
|
33
33
|
}
|
package/src/server.js
CHANGED
|
@@ -20,6 +20,39 @@ const VOID_ELEMENTS =
|
|
|
20
20
|
/^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i;
|
|
21
21
|
const REPLACE_SCRIPT = `function $df(e,n,o,t){if(n=document.getElementById(e),o=document.getElementById("pl-"+e)){for(;o&&8!==o.nodeType&&o.nodeValue!=="pl-"+e;)t=o.nextSibling,o.remove(),o=t;_$HY.done?o.remove():o.replaceWith(n.content)}n.remove(),_$HY.fe(e)}`;
|
|
22
22
|
|
|
23
|
+
// A name without these characters (and starting with an ASCII letter for a tag)
|
|
24
|
+
// is read back by the HTML parser as exactly that one name.
|
|
25
|
+
const INVALID_NAME = /[\0-\x20\x7F-\x9F"'<>/=]/;
|
|
26
|
+
const TAG_START = /^[a-zA-Z]/;
|
|
27
|
+
// Bounded: spread keys, style keys and dynamic tags can be any runtime string.
|
|
28
|
+
const validTags = new Set();
|
|
29
|
+
const attrNames = new Map();
|
|
30
|
+
const styleNames = new Map();
|
|
31
|
+
function checkTag(tag) {
|
|
32
|
+
if (validTags.has(tag)) return;
|
|
33
|
+
if (!TAG_START.test(tag) || INVALID_NAME.test(tag))
|
|
34
|
+
throw new Error(`"${tag}" is not a valid tag name`);
|
|
35
|
+
if (validTags.size < 512) validTags.add(tag);
|
|
36
|
+
}
|
|
37
|
+
// The attribute name written for a spread key, or "" when it is not a valid name.
|
|
38
|
+
function attrName(prop, prefixed) {
|
|
39
|
+
let name = attrNames.get(prop);
|
|
40
|
+
if (name !== undefined) return name;
|
|
41
|
+
const raw = prefixed ? prop.slice(5) : prop;
|
|
42
|
+
if (raw === "" || INVALID_NAME.test(raw)) return "";
|
|
43
|
+
name = (!prefixed && Aliases[raw]) || escape(raw);
|
|
44
|
+
if (attrNames.size < 512) attrNames.set(prop, name);
|
|
45
|
+
return name;
|
|
46
|
+
}
|
|
47
|
+
function styleName(name) {
|
|
48
|
+
let s = styleNames.get(name);
|
|
49
|
+
if (s === undefined) {
|
|
50
|
+
s = escape(name, true);
|
|
51
|
+
if (styleNames.size < 512) styleNames.set(name, s);
|
|
52
|
+
}
|
|
53
|
+
return s;
|
|
54
|
+
}
|
|
55
|
+
|
|
23
56
|
export function renderToString(code, options = {}) {
|
|
24
57
|
const { renderId } = options;
|
|
25
58
|
let scripts = "";
|
|
@@ -333,7 +366,7 @@ export function ssrClassList(value) {
|
|
|
333
366
|
classValue = !!value[key];
|
|
334
367
|
if (!key || key === "undefined" || !classValue) continue;
|
|
335
368
|
i && (result += " ");
|
|
336
|
-
result += escape(key);
|
|
369
|
+
result += escape(key, true);
|
|
337
370
|
}
|
|
338
371
|
return result;
|
|
339
372
|
}
|
|
@@ -351,16 +384,17 @@ export function ssrStyle(value) {
|
|
|
351
384
|
if (i) result += ";";
|
|
352
385
|
const r = escape(v, true);
|
|
353
386
|
if (r != undefined && r !== "undefined") {
|
|
354
|
-
result += `${s}:${r}`;
|
|
387
|
+
result += `${styleName(s)}:${r}`;
|
|
355
388
|
}
|
|
356
389
|
}
|
|
357
390
|
}
|
|
358
391
|
return result;
|
|
359
392
|
}
|
|
360
393
|
export function ssrStyleProperty(name, value) {
|
|
361
|
-
return value != null ? name + value : "";
|
|
394
|
+
return value != null ? styleName(name) + value : "";
|
|
362
395
|
}
|
|
363
396
|
export function ssrElement(tag, props, children, needsId) {
|
|
397
|
+
checkTag(tag);
|
|
364
398
|
if (props == null) props = {};
|
|
365
399
|
else if (typeof props === "function") props = props();
|
|
366
400
|
const skipChildren = VOID_ELEMENTS.test(tag);
|
|
@@ -400,11 +434,17 @@ export function ssrElement(tag, props, children, needsId) {
|
|
|
400
434
|
continue;
|
|
401
435
|
} else if (prop.slice(0, 5) === "bool:") {
|
|
402
436
|
if (!value) continue;
|
|
403
|
-
|
|
437
|
+
const name = attrName(prop, true);
|
|
438
|
+
if (!name) continue;
|
|
439
|
+
result += name;
|
|
404
440
|
} else if (prop.slice(0, 5) === "attr:") {
|
|
405
|
-
|
|
441
|
+
const name = attrName(prop, true);
|
|
442
|
+
if (!name) continue;
|
|
443
|
+
result += `${name}="${escape(value, true)}"`;
|
|
406
444
|
} else {
|
|
407
|
-
|
|
445
|
+
const name = attrName(prop, false);
|
|
446
|
+
if (!name) continue;
|
|
447
|
+
result += `${name}="${escape(value, true)}"`;
|
|
408
448
|
}
|
|
409
449
|
if (i !== keys.length - 1) result += " ";
|
|
410
450
|
}
|
|
@@ -691,9 +731,10 @@ export function ssrSpread(props, isSVG, skipChildren) {
|
|
|
691
731
|
} else if (prop === "class" || prop === "className" || prop === "classList") {
|
|
692
732
|
if (classResolved) continue;
|
|
693
733
|
let n;
|
|
694
|
-
result += `class="${
|
|
695
|
-
(n = props.className) ? n + " " : ""
|
|
696
|
-
|
|
734
|
+
result += `class="${
|
|
735
|
+
escape(((n = props.class) ? n + " " : "") + ((n = props.className) ? n + " " : ""), true) +
|
|
736
|
+
ssrClassList(props.classList)
|
|
737
|
+
}"`;
|
|
697
738
|
classResolved = true;
|
|
698
739
|
} else if (prop !== "value" && Properties.has(prop)) {
|
|
699
740
|
if (value) result += prop;
|
|
@@ -707,11 +748,17 @@ export function ssrSpread(props, isSVG, skipChildren) {
|
|
|
707
748
|
continue;
|
|
708
749
|
} else if (prop.slice(0, 5) === "bool:") {
|
|
709
750
|
if (!value) continue;
|
|
710
|
-
|
|
751
|
+
const name = attrName(prop, true);
|
|
752
|
+
if (!name) continue;
|
|
753
|
+
result += name;
|
|
711
754
|
} else if (prop.slice(0, 5) === "attr:") {
|
|
712
|
-
|
|
755
|
+
const name = attrName(prop, true);
|
|
756
|
+
if (!name) continue;
|
|
757
|
+
result += `${name}="${escape(value, true)}"`;
|
|
713
758
|
} else {
|
|
714
|
-
|
|
759
|
+
const name = attrName(prop, false);
|
|
760
|
+
if (!name) continue;
|
|
761
|
+
result += `${name}="${escape(value, true)}"`;
|
|
715
762
|
}
|
|
716
763
|
if (i !== keys.length - 1) result += " ";
|
|
717
764
|
}
|