hyperx
Advanced tools
Comparing version 2.5.4 to 3.0.0
215
index.js
var attrToProp = require('hyperscript-attribute-to-property') | ||
var VAR = 0, TEXT = 1, OPEN = 2, CLOSE = 3, ATTR = 4 | ||
@@ -10,13 +11,17 @@ var ATTR_KEY = 5, ATTR_KEY_W = 6 | ||
module.exports = function (h, opts) { | ||
if (!opts) opts = {} | ||
if (!opts) opts = { } | ||
var concat = opts.concat || function (a, b) { | ||
return String(a) + String(b) | ||
} | ||
if (opts.attrToProp !== false) { | ||
if (opts.attrToProp !== false) | ||
h = attrToProp(h) | ||
} | ||
return function (strings) { | ||
var state = TEXT, reg = '' | ||
var state = TEXT, reg = '', isSelfClosing = false | ||
var arglen = arguments.length | ||
@@ -26,2 +31,3 @@ var parts = [] | ||
for (var i = 0; i < strings.length; i++) { | ||
if (i < arglen - 1) { | ||
@@ -48,23 +54,27 @@ var arg = arguments[i+1] | ||
parts.push.apply(parts, p) | ||
} else parts.push.apply(parts, parse(strings[i])) | ||
} else { | ||
parts.push.apply(parts, parse(strings[i])) | ||
} | ||
} | ||
var tree = [null,{},[]] | ||
var stack = [[tree,-1]] | ||
var tree = [ null, {}, [] ] | ||
var stack = [ [ tree, -1 ] ] | ||
for (var i = 0; i < parts.length; i++) { | ||
var cur = stack[stack.length-1][0] | ||
var p = parts[i], s = p[0] | ||
if (s === OPEN && /^\//.test(p[1])) { | ||
var p = parts[i], state = p[0] | ||
if (state === OPEN && /^\//.test(p[1])) { | ||
var ix = stack[stack.length-1][1] | ||
if (stack.length > 1) { | ||
stack.pop() | ||
stack[stack.length-1][0][2][ix] = h( | ||
cur[0], cur[1], cur[2].length ? cur[2] : undefined | ||
) | ||
stack[stack.length-1][0][2][ix] = h(cur[0], cur[1], cur[2].length ? cur[2] : undefined) | ||
} | ||
} else if (s === OPEN) { | ||
} else if (state === OPEN) { | ||
var c = [p[1],{},[]] | ||
cur[2].push(c) | ||
stack.push([c,cur[2].length-1]) | ||
} else if (s === ATTR_KEY || (s === VAR && p[1] === ATTR_KEY)) { | ||
} else if (state === ATTR_KEY || (state === VAR && p[1] === ATTR_KEY)) { | ||
var key = '' | ||
@@ -75,27 +85,38 @@ var copyKey | ||
key = concat(key, parts[i][1]) | ||
} else if (parts[i][0] === VAR && parts[i][1] === ATTR_KEY) { | ||
if (typeof parts[i][2] === 'object' && !key) { | ||
for (copyKey in parts[i][2]) { | ||
if (parts[i][2].hasOwnProperty(copyKey) && !cur[1][copyKey]) { | ||
for (copyKey in parts[i][2]) | ||
if (parts[i][2].hasOwnProperty(copyKey) && !cur[1][copyKey]) | ||
cur[1][copyKey] = parts[i][2][copyKey] | ||
} | ||
} | ||
} else { | ||
key = concat(key, parts[i][2]) | ||
} | ||
} else break | ||
} else { | ||
break | ||
} | ||
} | ||
if (parts[i][0] === ATTR_EQ) i++ | ||
if (parts[i][0] === ATTR_EQ) | ||
i++ | ||
var j = i | ||
for (; i < parts.length; i++) { | ||
if (parts[i][0] === ATTR_VALUE || parts[i][0] === ATTR_KEY) { | ||
if (!cur[1][key]) cur[1][key] = strfn(parts[i][1]) | ||
else parts[i][1]==="" || (cur[1][key] = concat(cur[1][key], parts[i][1])); | ||
} else if (parts[i][0] === VAR | ||
&& (parts[i][1] === ATTR_VALUE || parts[i][1] === ATTR_KEY)) { | ||
if (!cur[1][key]) cur[1][key] = strfn(parts[i][2]) | ||
else parts[i][2]==="" || (cur[1][key] = concat(cur[1][key], parts[i][2])); | ||
if (!cur[1][key]) | ||
cur[1][key] = strfn(parts[i][1]) | ||
else | ||
parts[i][1]==="" || (cur[1][key] = concat(cur[1][key], parts[i][1])); | ||
} else if (parts[i][0] === VAR && (parts[i][1] === ATTR_VALUE || parts[i][1] === ATTR_KEY)) { | ||
if (!cur[1][key]) | ||
cur[1][key] = strfn(parts[i][2]) | ||
else | ||
parts[i][2]==="" || (cur[1][key] = concat(cur[1][key], parts[i][2])); | ||
} else { | ||
if (key.length && !cur[1][key] && i === j | ||
&& (parts[i][0] === CLOSE || parts[i][0] === ATTR_BREAK)) { | ||
if (key.length && !cur[1][key] && i === j && (parts[i][0] === CLOSE || parts[i][0] === ATTR_BREAK)) { | ||
// https://html.spec.whatwg.org/multipage/infrastructure.html#boolean-attributes | ||
@@ -105,44 +126,56 @@ // empty string is falsy, not well behaved value in browser | ||
} | ||
if (parts[i][0] === CLOSE) { | ||
if (parts[i][0] === CLOSE) | ||
i-- | ||
} | ||
break | ||
} | ||
} | ||
} else if (s === ATTR_KEY) { | ||
} else if (state === ATTR_KEY) { | ||
cur[1][p[1]] = true | ||
} else if (s === VAR && p[1] === ATTR_KEY) { | ||
} else if (state === VAR && p[1] === ATTR_KEY) { | ||
cur[1][p[2]] = true | ||
} else if (s === CLOSE) { | ||
if (selfClosing(cur[0]) && stack.length) { | ||
} else if (state === CLOSE) { | ||
const isSelfClosing = p[1] || selfClosingVoid(cur[0]) | ||
//if (selfClosing(cur[0]) && stack.length) { | ||
if (isSelfClosing && stack.length) { | ||
var ix = stack[stack.length-1][1] | ||
stack.pop() | ||
stack[stack.length-1][0][2][ix] = h( | ||
cur[0], cur[1], cur[2].length ? cur[2] : undefined | ||
) | ||
stack[stack.length-1][0][2][ix] = h(cur[0], cur[1], cur[2].length ? cur[2] : undefined) | ||
} | ||
} else if (s === VAR && p[1] === TEXT) { | ||
if (p[2] === undefined || p[2] === null) p[2] = '' | ||
else if (!p[2]) p[2] = concat('', p[2]) | ||
if (Array.isArray(p[2][0])) { | ||
} else if (state === VAR && p[1] === TEXT) { | ||
if (p[2] === undefined || p[2] === null) | ||
p[2] = '' | ||
else if (!p[2]) | ||
p[2] = concat('', p[2]) | ||
if (Array.isArray(p[2][0])) | ||
cur[2].push.apply(cur[2], p[2]) | ||
} else { | ||
else | ||
cur[2].push(p[2]) | ||
} | ||
} else if (s === TEXT) { | ||
} else if (state === TEXT) { | ||
cur[2].push(p[1]) | ||
} else if (s === ATTR_EQ || s === ATTR_BREAK) { | ||
} else if (state === ATTR_EQ || state === ATTR_BREAK) { | ||
// no-op | ||
} else { | ||
throw new Error('unhandled: ' + s) | ||
throw new Error('unhandled: ' + state) | ||
} | ||
} | ||
if (tree[2].length > 1 && /^\s*$/.test(tree[2][0])) { | ||
if (tree[2].length > 1 && /^\s*$/.test(tree[2][0])) | ||
tree[2].shift() | ||
} | ||
if (tree[2].length > 2 | ||
|| (tree[2].length === 2 && /\S/.test(tree[2][1]))) { | ||
if (opts.createFragment) return opts.createFragment(tree[2]) | ||
if (tree[2].length > 2 || (tree[2].length === 2 && /\S/.test(tree[2][1]))) { | ||
if (opts.createFragment) | ||
return opts.createFragment(tree[2]) | ||
throw new Error( | ||
@@ -152,20 +185,35 @@ 'multiple root elements must be wrapped in an enclosing tag' | ||
} | ||
if (Array.isArray(tree[2][0]) && typeof tree[2][0][0] === 'string' | ||
&& Array.isArray(tree[2][0][2])) { | ||
if (Array.isArray(tree[2][0]) && typeof tree[2][0][0] === 'string' && Array.isArray(tree[2][0][2])) | ||
tree[2][0] = h(tree[2][0][0], tree[2][0][1], tree[2][0][2]) | ||
} | ||
return tree[2][0] | ||
function parse (str) { | ||
var res = [] | ||
if (state === ATTR_VALUE_W) state = ATTR | ||
var res = [ ] | ||
var isInStyleTag = false | ||
if (state === ATTR_VALUE_W) | ||
state = ATTR | ||
for (var i = 0; i < str.length; i++) { | ||
var c = str.charAt(i) | ||
if (state === TEXT && c === '<') { | ||
if (reg.length) res.push([TEXT, reg]) | ||
if (reg.length) | ||
res.push([TEXT, reg]) | ||
reg = '' | ||
state = OPEN | ||
isInStyleTag = false | ||
} else if (c === '>' && !quot(state) && state !== COMMENT) { | ||
if (state === OPEN && reg.length) { | ||
res.push([OPEN,reg]) | ||
if (reg === 'style') | ||
isInStyleTag = true | ||
else if (reg === '/style') | ||
isInStyleTag = false | ||
} else if (state === ATTR_KEY) { | ||
@@ -176,5 +224,15 @@ res.push([ATTR_KEY,reg]) | ||
} | ||
res.push([CLOSE]) | ||
reg = '' | ||
if (state === TEXT && isInStyleTag) { | ||
// the css descendant selector within <style> tags shouldn't close | ||
// e.g., <style> ul > .test { color: blue }</style> | ||
reg += c | ||
} else { | ||
res.push([CLOSE, isSelfClosing]) | ||
isSelfClosing = false | ||
reg = '' | ||
} | ||
state = TEXT | ||
} else if (state === COMMENT && /-$/.test(reg) && c === '-') { | ||
@@ -185,2 +243,3 @@ if (opts.comments) { | ||
reg = '' | ||
isSelfClosing = true | ||
state = TEXT | ||
@@ -196,7 +255,14 @@ } else if (state === OPEN && /^!--$/.test(reg)) { | ||
} else if (state === OPEN && c === '/' && reg.length) { | ||
// no-op, self closing tag without a space <br/> | ||
// self closing tag without a space <br/> | ||
isSelfClosing = true | ||
} else if (state === OPEN && /\s/.test(c)) { | ||
if (reg.length) { | ||
if (reg.length) | ||
res.push([OPEN, reg]) | ||
} | ||
if (reg === 'style') | ||
isInStyleTag = true | ||
else if (reg === '/style') | ||
isInStyleTag = false | ||
reg = '' | ||
@@ -210,3 +276,4 @@ state = ATTR | ||
} else if (state === ATTR && /\s/.test(c)) { | ||
if (reg.length) res.push([ATTR_KEY,reg]) | ||
if (reg.length) | ||
res.push([ATTR_KEY,reg]) | ||
res.push([ATTR_BREAK]) | ||
@@ -221,2 +288,6 @@ } else if (state === ATTR_KEY && /\s/.test(c)) { | ||
state = ATTR_VALUE_W | ||
} else if (state === ATTR_KEY && c === '/') { | ||
isSelfClosing = true | ||
reg='' | ||
state = ATTR | ||
} else if (state === ATTR_KEY) { | ||
@@ -232,3 +303,7 @@ reg += c | ||
state = ATTR_KEY | ||
} else state = ATTR | ||
} else if (c === '/') { | ||
isSelfClosing = true | ||
} else { | ||
state = ATTR | ||
} | ||
} else if (state === ATTR_VALUE_W && c === '"') { | ||
@@ -291,2 +366,12 @@ state = ATTR_VALUE_DQ | ||
//area, base, br, col, command, embed, hr, img, input, keygen, link, meta, param, source, track, wbr | ||
var voidCloseRE = RegExp('^(' + [ | ||
'area', 'base', 'br', 'col', 'command', 'embed', | ||
'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', | ||
'source', 'track', 'wbr' | ||
].join('|') + ')(?:[\.#][a-zA-Z0-9\u007F-\uFFFF_:-]+)*$') | ||
function selfClosingVoid (tag) { return voidCloseRE.test(tag) } | ||
/* | ||
var closeRE = RegExp('^(' + [ | ||
@@ -308,2 +393,4 @@ 'area', 'base', 'basefont', 'bgsound', 'br', 'col', 'command', 'embed', | ||
].join('|') + ')(?:[\.#][a-zA-Z0-9\u007F-\uFFFF_:-]+)*$') | ||
function selfClosing (tag) { return closeRE.test(tag) } | ||
*/ |
{ | ||
"name": "hyperx", | ||
"version": "2.5.4", | ||
"version": "3.0.0", | ||
"description": "tagged template string virtual dom builder", | ||
@@ -24,4 +24,4 @@ "main": "index.js", | ||
"covert": "^1.1.0", | ||
"hyperscript": "^1.4.7", | ||
"tape": "^4.4.0", | ||
"hyperscript": "^2.0.2", | ||
"tape": "^5.4.0", | ||
"virtual-dom": "^2.1.1" | ||
@@ -38,8 +38,8 @@ }, | ||
"type": "git", | ||
"url": "git+https://github.com/substack/hyperx.git" | ||
"url": "git+https://github.com/mreinstein/hyperx.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/substack/hyperx/issues" | ||
"url": "https://github.com/mreinstein/hyperx/issues" | ||
}, | ||
"homepage": "https://github.com/substack/hyperx#readme" | ||
"homepage": "https://github.com/mreinstein/hyperx#readme" | ||
} |
@@ -18,1 +18,40 @@ var test = require('tape') | ||
}) | ||
test('embedded style', function (t) { | ||
var key = 'type' | ||
var value = 'text' | ||
var tree = hx`<style> | ||
.test > ul { | ||
background-color: red; | ||
} | ||
</style>` | ||
t.equal( | ||
vdom.create(tree).toString(), | ||
`<style> | ||
.test > ul { | ||
background-color: red; | ||
} | ||
</style>` | ||
) | ||
t.end() | ||
}) | ||
test('embedded style with attributes', function (t) { | ||
var key = 'type' | ||
var value = 'text' | ||
var tree = hx`<style id="test1"> | ||
.test > ul { | ||
background-color: red; | ||
} | ||
</style>` | ||
t.equal( | ||
vdom.create(tree).toString(), | ||
`<style id="test1"> | ||
.test > ul { | ||
background-color: red; | ||
} | ||
</style>` | ||
) | ||
t.end() | ||
}) |
@@ -22,1 +22,26 @@ var test = require('tape') | ||
}) | ||
test('svg mixed with html and close / self-closing tags', function (t) { | ||
var expected = `<div> | ||
<h3>test</h3> | ||
<svg width="150" height="100" viewBox="0 0 3 2"> | ||
<use id="test"></use> | ||
<rect width="1" height="2" x="0" fill="#008d46"></rect> | ||
<use id="test"></use> | ||
<rect width="1" height="2" x="0" fill="#008d46"></rect> | ||
<use id="test"></use> | ||
</svg> | ||
</div>` | ||
var tree = hx`<div> | ||
<h3>test</h3> | ||
<svg width="150" height="100" viewBox="0 0 3 2"> | ||
<use id="test"></use> | ||
<rect width="1" height="2" x="0" fill="#008d46"></rect> | ||
<use id="test"/> | ||
<rect width="1" height="2" x="0" fill="#008d46"/> | ||
<use id="test"></use> | ||
</svg> | ||
</div>` | ||
t.equal(vdom.create(tree).toString(), expected) | ||
t.end() | ||
}) |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
42907
1122
1
1
2