Skip to content
This repository was archived by the owner on Aug 9, 2023. It is now read-only.

Commit d22f2b4

Browse files
committed
Refactor to improve bundle size
1 parent a387936 commit d22f2b4

File tree

3 files changed

+97
-111
lines changed

3 files changed

+97
-111
lines changed

index.js

Lines changed: 54 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,14 @@ var root = convert('root')
1414
var element = convert('element')
1515
var text = convert('text')
1616

17-
var dashes = /-([a-z])/g
18-
1917
module.exports = wrapper
2018

2119
function wrapper(h, node, options) {
2220
var settings = options || {}
21+
var r = react(h)
22+
var v = vue(h)
23+
var vd = vdom(h)
2324
var prefix
24-
var r
25-
var v
26-
var vd
2725

2826
if (typeof h !== 'function') {
2927
throw new Error('h is not a function')
@@ -36,14 +34,6 @@ function wrapper(h, node, options) {
3634
prefix = settings.prefix
3735
}
3836

39-
r = react(h)
40-
v = vue(h)
41-
vd = vdom(h)
42-
43-
if (prefix === null || prefix === undefined) {
44-
prefix = r === true || v === true || vd === true ? 'h-' : false
45-
}
46-
4737
if (root(node)) {
4838
node =
4939
node.children.length === 1 && element(node.children[0])
@@ -62,7 +52,7 @@ function wrapper(h, node, options) {
6252

6353
return toH(h, node, {
6454
schema: settings.space === 'svg' ? svg : html,
65-
prefix: prefix,
55+
prefix: prefix == null ? (r || v || vd ? 'h-' : null) : prefix,
6656
key: 0,
6757
react: r,
6858
vue: v,
@@ -76,125 +66,105 @@ function toH(h, node, ctx) {
7666
var parentSchema = ctx.schema
7767
var schema = parentSchema
7868
var name = node.tagName
79-
var properties
80-
var attributes
81-
var children
82-
var property
83-
var elements
84-
var length
85-
var index
69+
var attributes = {}
70+
var nodes = []
71+
var index = -1
72+
var key
8673
var value
87-
var result
8874

8975
if (parentSchema.space === 'html' && name.toLowerCase() === 'svg') {
9076
schema = svg
9177
ctx.schema = schema
9278
}
9379

94-
if (ctx.vdom === true && schema.space === 'html') {
95-
name = name.toUpperCase()
80+
for (key in node.properties) {
81+
addAttribute(attributes, key, node.properties[key], ctx, name)
9682
}
9783

98-
properties = node.properties
99-
attributes = {}
100-
101-
for (property in properties) {
102-
addAttribute(attributes, property, properties[property], ctx)
103-
}
104-
105-
if (
106-
typeof attributes.style === 'string' &&
107-
(ctx.vdom === true || ctx.vue === true || ctx.react === true)
108-
) {
109-
// VDOM, Vue, and React accept `style` as object.
110-
attributes.style = parseStyle(attributes.style, name)
84+
if (ctx.vdom) {
85+
if (schema.space === 'html') {
86+
name = name.toUpperCase()
87+
} else {
88+
attributes.namespace = ns[schema.space]
89+
}
11190
}
11291

11392
if (ctx.prefix) {
11493
ctx.key++
11594
attributes.key = ctx.prefix + ctx.key
11695
}
11796

118-
if (ctx.vdom && schema.space !== 'html') {
119-
attributes.namespace = ns[schema.space]
120-
}
121-
122-
elements = []
123-
children = node.children
124-
length = children ? children.length : 0
125-
index = -1
97+
if (node.children) {
98+
while (++index < node.children.length) {
99+
value = node.children[index]
126100

127-
while (++index < length) {
128-
value = children[index]
129-
130-
if (element(value)) {
131-
elements.push(toH(h, value, ctx))
132-
} else if (text(value)) {
133-
elements.push(value.value)
101+
if (element(value)) {
102+
nodes.push(toH(h, value, ctx))
103+
} else if (text(value)) {
104+
nodes.push(value.value)
105+
}
134106
}
135107
}
136108

137-
// Ensure no React warnings are triggered for void elements having children
138-
// passed in.
139-
result =
140-
elements.length === 0
141-
? h.call(node, name, attributes)
142-
: h.call(node, name, attributes, elements)
143-
144109
// Restore parent schema.
145110
ctx.schema = parentSchema
146111

147-
return result
112+
// Ensure no React warnings are triggered for void elements having children
113+
// passed in.
114+
return nodes.length
115+
? h.call(node, name, attributes, nodes)
116+
: h.call(node, name, attributes)
148117
}
149118

150-
function addAttribute(props, prop, value, ctx) {
151-
var hyperlike = ctx.hyperscript || ctx.vdom || ctx.vue
152-
var schema = ctx.schema
153-
var info = find(schema, prop)
119+
function addAttribute(props, prop, value, ctx, name) {
120+
var info = find(ctx.schema, prop)
154121
var subprop
155122

156123
// Ignore nullish and `NaN` values.
157124
// Ignore `false` and falsey known booleans for hyperlike DSLs.
158125
if (
159-
value === null ||
160-
value === undefined ||
126+
value == null ||
161127
value !== value ||
162-
(hyperlike && value === false) ||
163-
(hyperlike && info.boolean && !value)
128+
(value === false && (ctx.vue || ctx.vdom || ctx.hyperscript)) ||
129+
(!value && info.boolean && (ctx.vue || ctx.vdom || ctx.hyperscript))
164130
) {
165131
return
166132
}
167133

168-
if (value !== null && typeof value === 'object' && 'length' in value) {
134+
if (value && typeof value === 'object' && 'length' in value) {
169135
// Accept `array`.
170136
// Most props are space-separated.
171137
value = (info.commaSeparated ? commas : spaces).stringify(value)
172138
}
173139

174140
// Treat `true` and truthy known booleans.
175-
if (info.boolean && ctx.hyperscript === true) {
141+
if (info.boolean && ctx.hyperscript) {
176142
value = ''
177143
}
178144

145+
// VDOM, Vue, and React accept `style` as object.
146+
if (
147+
info.property === 'style' &&
148+
typeof value === 'string' &&
149+
(ctx.react || ctx.vue || ctx.vdom)
150+
) {
151+
value = parseStyle(value, name)
152+
}
153+
179154
if (ctx.vue) {
180-
if (prop !== 'style') {
181-
subprop = 'attrs'
182-
}
155+
if (info.property !== 'style') subprop = 'attrs'
183156
} else if (!info.mustUseProperty) {
184-
if (ctx.vdom === true) {
185-
subprop = 'attributes'
186-
} else if (ctx.hyperscript === true) {
157+
if (ctx.vdom) {
158+
if (info.property !== 'style') subprop = 'attributes'
159+
} else if (ctx.hyperscript) {
187160
subprop = 'attrs'
188161
}
189162
}
190163

191164
if (subprop) {
192-
if (props[subprop] === undefined) {
193-
props[subprop] = {}
194-
}
195-
165+
if (!props[subprop]) props[subprop] = {}
196166
props[subprop][info.attribute] = value
197-
} else if (ctx.react && info.space) {
167+
} else if (info.space && ctx.react) {
198168
props[hastToReact[info.property] || info.property] = value
199169
} else {
200170
props[info.attribute] = value
@@ -205,7 +175,7 @@ function addAttribute(props, prop, value, ctx) {
205175
function react(h) {
206176
var node = h && h('div')
207177
return Boolean(
208-
node && ('_owner' in node || '_store' in node) && node.key === null
178+
node && ('_owner' in node || '_store' in node) && node.key == null
209179
)
210180
}
211181

@@ -238,18 +208,11 @@ function parseStyle(value, tagName) {
238208
return result
239209

240210
function iterator(name, value) {
241-
result[styleCase(name)] = value
211+
if (name.slice(0, 4) === '-ms-') name = 'ms-' + name.slice(4)
212+
result[name.replace(/-([a-z])/g, styleReplacer)] = value
242213
}
243214
}
244215

245-
function styleCase(value) {
246-
if (value.slice(0, 4) === '-ms-') {
247-
value = 'ms-' + value.slice(4)
248-
}
249-
250-
return value.replace(dashes, styleReplacer)
251-
}
252-
253216
function styleReplacer($0, $1) {
254217
return $1.toUpperCase()
255218
}

package.json

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,21 @@
9797
"prettier": true,
9898
"esnext": false,
9999
"rules": {
100-
"unicorn/no-fn-reference-in-iterator": "off",
101-
"unicorn/prefer-type-error": "off",
102-
"@typescript-eslint/prefer-readonly-parameter-types": "off",
100+
"complexity": "off",
101+
"eqeqeq": [
102+
"error",
103+
"always",
104+
{
105+
"null": "ignore"
106+
}
107+
],
103108
"guard-for-in": "off",
109+
"max-params": "off",
110+
"no-eq-null": "off",
104111
"no-self-compare": "off",
105-
"complexity": "off"
112+
"unicorn/explicit-length-check": "off",
113+
"unicorn/no-fn-reference-in-iterator": "off",
114+
"unicorn/prefer-type-error": "off"
106115
}
107116
},
108117
"remarkConfig": {

test.js

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ test('hast-to-hyperscript', function (t) {
186186
})
187187

188188
t.test('should support `virtual-dom/h`', function (t) {
189-
var baseline = doc.replace(/color:red;/, 'color: red')
189+
var baseline = doc.replace(/color:red;/, 'color: red;')
190190
var actual = toH(v, hast)
191191
var expected = v('div', {key: 'h-1'}, [
192192
v(
@@ -201,13 +201,15 @@ test('hast-to-hyperscript', function (t) {
201201
'strong',
202202
{
203203
key: 'h-3',
204+
style: {
205+
color: 'red'
206+
},
204207
attributes: {
205208
'aria-valuenow': '1',
206209
foo: 'bar',
207210
camelCase: 'on off',
208211
'data-123': '456',
209-
'data-some': 'yes',
210-
style: 'color: red'
212+
'data-some': 'yes'
211213
}
212214
},
213215
'charlie'
@@ -478,16 +480,6 @@ test('hast-to-hyperscript', function (t) {
478480
return expected
479481
}
480482

481-
function identity(value) {
482-
return value
483-
}
484-
485-
function vueToString(render) {
486-
return VueSSR.createRenderer({template: identity}).renderToString(
487-
new Vue({render: render}).$mount()
488-
)
489-
}
490-
491483
function clean(node) {
492484
remove(node)
493485
return json(node)
@@ -526,13 +518,25 @@ test('hast-to-hyperscript', function (t) {
526518
'should patch `keys` on react'
527519
)
528520

521+
t.end()
522+
})
523+
524+
t.test('should support style and other funky props', function (t) {
529525
t.deepEqual(
530-
toH(v, u('element', {tagName: 'div', properties: {style: 'color: red'}}))
531-
.properties.attributes.style,
532-
'color: red',
526+
vToString(
527+
toH(v, u('element', {tagName: 'div', properties: {style: 'color:red'}}))
528+
),
529+
'<div style="color: red;"></div>',
533530
'vdom: should patch a style declaration correctly'
534531
)
535532

533+
t.deepEqual(
534+
toH(h, u('element', {tagName: 'div', properties: {style: 'color: red'}}))
535+
.outerHTML,
536+
'<div style="color:red;"></div>',
537+
'hyperscript: should parse a style declaration'
538+
)
539+
536540
t.deepEqual(
537541
toH(r, u('element', {tagName: 'div', properties: {style: 'color: red'}}))
538542
.props.style,
@@ -743,3 +747,13 @@ function html(doc) {
743747
function json(value) {
744748
return JSON.parse(JSON.stringify(value))
745749
}
750+
751+
function vueToString(render) {
752+
return VueSSR.createRenderer({template: identity}).renderToString(
753+
new Vue({render: render}).$mount()
754+
)
755+
}
756+
757+
function identity(value) {
758+
return value
759+
}

0 commit comments

Comments
 (0)