Skip to content

Commit e0d66eb

Browse files
author
Gray Norton
committed
Add changes to support multiple apreads, case-sensitive props
1 parent b4204d2 commit e0d66eb

1 file changed

Lines changed: 28 additions & 15 deletions

File tree

‎src/index.mjs‎

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const CACHE = {};
1616
const TEMPLATE = document.createElement('template');
1717

1818
const reg = /(\$_h\[\d+\])/g;
19+
const nomExp = /([\w-]+)=/g;
1920

2021
export default function html(statics) {
2122
const tpl = CACHE[statics] || (CACHE[statics] = build(statics));
@@ -25,49 +26,61 @@ export default function html(statics) {
2526

2627
/** Create a template function given strings from a tagged template. */
2728
function build(statics) {
28-
let str = statics[0], i = 1;
29+
const noms = {};
30+
let str = '', i = 0;
2931
while (i < statics.length) {
30-
str += '$_h[' + i + ']' + statics[i++];
32+
getNoms(statics[i], noms);
33+
str += statics[i++] + (i < statics.length ? '$_h[' + i + ']' : '');
3134
}
3235
// Template string preprocessing:
3336
// - replace <${Foo}> with <c c@=${Foo}>
3437
// - replace <x /> with <x></x>
3538
// - replace <${Foo}>a<//>b with <c c@=${Foo}>a</c>b
3639
TEMPLATE.innerHTML = str.replace(/<(?:(\/)\/|(\/?)(\$_h\[\d+\]))/g, '<$1$2c c@=$3').replace(/<([\w:-]+)(\s[^<>]*?)?\/>/gi, '<$1$2></$1>').trim();
37-
return Function('h', '$_h', 'return ' + walk((TEMPLATE.content || TEMPLATE).firstChild));
40+
return Function('h', '$_h', 'return ' + walk((TEMPLATE.content || TEMPLATE).firstChild, noms));
3841
}
3942

4043
/** Traverse a DOM tree and serialize it to hyperscript function calls */
41-
function walk(n) {
44+
function walk(n, noms) {
4245
if (n.nodeType !== 1) {
4346
if (n.nodeType === 3 && n.data) return field(n.data, ',');
4447
return 'null';
4548
}
46-
let nodeName = `"${n.localName}"`, str = '{', sub='', end='}';
49+
let nodeName = `"${n.localName}"`, str = '', pre, it, prevSpread, anySpread;
4750
for (let i=0; i<n.attributes.length; i++) {
48-
const { name, value } = n.attributes[i];
51+
let { name } = n.attributes[i];
52+
const { value } = n.attributes[i];
53+
name = noms[name] || name;
4954
if (name=='c@') {
5055
nodeName = value;
5156
continue;
5257
}
5358
if (name.substring(0,3)==='...') {
54-
end = '})';
55-
str = 'Object.assign(' + str + '},' + name.substring(3) + ',{';
56-
sub = '';
57-
continue;
59+
it = name.substring(3);
60+
pre = str ? (prevSpread ? ',' : '},') : '';
61+
prevSpread = anySpread = true;
62+
}
63+
else {
64+
it = `"${name.replace(/:(\w)/g, upper)}":${value ? field(value, '+') : true}`;
65+
pre = str ? (prevSpread ? ',{' : ',') : '{';
66+
prevSpread = false;
5867
}
59-
str += `${sub}"${name.replace(/:(\w)/g, upper)}":${value ? field(value, '+') : true}`;
60-
sub = ',';
68+
str += pre + it;
6169
}
62-
str = 'h(' + nodeName + ',' + str + end;
70+
str = 'h(' + nodeName + ',' + (str ? (anySpread ? 'Object.assign({},' + str + (prevSpread ? '' : '}') + ')' : str + '}') : '{}');
6371
let child = n.firstChild;
6472
while (child) {
65-
str += ',' + walk(child);
73+
str += ',' + walk(child, noms);
6674
child = child.nextSibling;
6775
}
6876
return str + ')';
6977
}
7078

79+
function getNoms(str, noms) {
80+
let nom;
81+
while ((nom = nomExp.exec(str)) !== null) noms[nom[1].toLowerCase()] = nom[1];
82+
}
83+
7184
function upper (s, i) {
7285
return i.toUpperCase();
7386
}
@@ -82,4 +95,4 @@ function field(value, sep) {
8295
if (sep === ',') strValue = `[${strValue}]`;
8396
}
8497
return strValue;
85-
}
98+
}

0 commit comments

Comments
 (0)