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

Commit c593e58

Browse files
committed
Fix handling of style in react, vdom
1 parent 34d01a0 commit c593e58

File tree

3 files changed

+88
-4
lines changed

3 files changed

+88
-4
lines changed

index.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
/* Dependencies. */
4+
var trim = require('trim');
45
var paramCase = require('kebab-case');
56
var information = require('property-information');
67
var spaces = require('space-separated-tokens');
@@ -68,6 +69,23 @@ function toH(h, node, ctx) {
6869
delete attributes.className;
6970
}
7071

72+
if (typeof attributes.style === 'string') {
73+
/* VDOM expects a `string` style in `attributes`
74+
* See https://github.com/Matt-Esch/virtual-dom/blob/947ecf9/
75+
* docs/vnode.md#propertiesstyle-vs-propertiesattributesstyle */
76+
if (ctx.vdom) {
77+
if (!attributes.attributes) {
78+
attributes.attributes = {};
79+
}
80+
81+
attributes.attributes.style = attributes.style;
82+
delete attributes.style;
83+
/* React only accepts `style` as object. */
84+
} else if (ctx.react) {
85+
attributes.style = parseStyle(attributes.style);
86+
}
87+
}
88+
7189
if (ctx.prefix) {
7290
ctx.key++;
7391
attributes.key = ctx.prefix + ctx.key;
@@ -168,3 +186,36 @@ function vdom(h) {
168186
/* istanbul ignore next */
169187
return false;
170188
}
189+
190+
function parseStyle(value) {
191+
var result = {};
192+
var declarations = value.split(';');
193+
var length = declarations.length;
194+
var index = -1;
195+
var declaration;
196+
var prop;
197+
var pos;
198+
199+
while (++index < length) {
200+
declaration = declarations[index];
201+
pos = declaration.indexOf(':');
202+
if (pos !== -1) {
203+
prop = camelCase(trim(declaration.slice(0, pos)));
204+
result[prop] = trim(declaration.slice(pos + 1));
205+
}
206+
}
207+
208+
return result;
209+
}
210+
211+
function camelCase(val) {
212+
if (val.slice(0, 4) === '-ms-') {
213+
val = 'ms-' + val.slice(4);
214+
}
215+
216+
return val.replace(/-([a-z])/g, replace);
217+
}
218+
219+
function replace($0, $1) {
220+
return $1.toUpperCase();
221+
}

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"kebab-case": "^1.0.0",
3232
"property-information": "^3.0.0",
3333
"space-separated-tokens": "^1.0.0",
34+
"trim": "0.0.1",
3435
"unist-util-is": "^2.0.0"
3536
},
3637
"devDependencies": {
@@ -70,6 +71,8 @@
7071
}
7172
},
7273
"remarkConfig": {
73-
"plugins": ["preset-wooorm"]
74+
"plugins": [
75+
"preset-wooorm"
76+
]
7477
}
7578
}

test.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,8 @@ test('hast-to-hyperscript', function (t) {
8686
'bravo ',
8787
v('strong', {
8888
key: 'h-2',
89-
style: 'color: red',
9089
accept: '.jpg, .jpeg',
91-
attributes: {'camel-case': 'on off'}
90+
attributes: {style: 'color: red', 'camel-case': 'on off'}
9291
}, 'charlie'),
9392
' delta'
9493
])),
@@ -109,7 +108,7 @@ test('hast-to-hyperscript', function (t) {
109108
'bravo ',
110109
r('strong', {
111110
key: 'h-2',
112-
style: 'color: red',
111+
style: {color: 'red'},
113112
'camel-case': 'on off',
114113
accept: '.jpg, .jpeg'
115114
}, ['charlie']),
@@ -143,6 +142,37 @@ test('hast-to-hyperscript', function (t) {
143142
'should patch `keys` on react'
144143
);
145144

145+
st.deepEqual(
146+
toH(v, u('element', {tagName: 'div', properties: {style: 'color: red'}})).properties.attributes.style,
147+
'color: red',
148+
'vdom: should patch a style declaration correctly'
149+
);
150+
151+
st.deepEqual(
152+
toH(r, u('element', {tagName: 'div', properties: {style: 'color: red'}})).props.style,
153+
{color: 'red'},
154+
'react: should parse a style declaration'
155+
);
156+
157+
st.deepEqual(
158+
toH(r, u('element', {tagName: 'div', properties: {
159+
style: 'color: red; background-color: blue; -moz-transition: initial; -ms-transition: unset'
160+
}})).props.style,
161+
{
162+
color: 'red',
163+
backgroundColor: 'blue',
164+
msTransition: 'unset',
165+
MozTransition: 'initial'
166+
},
167+
'react: should parse vendor prefixed in style declarations'
168+
);
169+
170+
st.deepEqual(
171+
toH(r, u('element', {tagName: 'div', properties: {style: '; color; border: 1;'}})).props.style,
172+
{border: '1'},
173+
'react: should parse an invalid style declaration'
174+
);
175+
146176
st.end();
147177
});
148178

0 commit comments

Comments
 (0)