Skip to content

Commit bae093b

Browse files
Update attributes to props helper to handle SVG props
The property config originally only had the HTML DOM property config. Updated the property config with the SVG property config as well. Then update `attributesToProps` to try setting both HTML and SVG properties when iterating through the attributes. The only difference between the HTML and SVG config is that the HTML property keys are lowercased whereas the SVG property keys are not because there are certain keys that are camel cased. Add tests to check that the SVG attributes and properties are handled correctly by the helper. React's SVGDOMPropertyConfig source: https://github.com/facebook/react/blob/master/src/renderers/dom/shared/SVGDOMPropertyConfig.js
1 parent 8b1c50e commit bae093b

File tree

3 files changed

+95
-9
lines changed

3 files changed

+95
-9
lines changed

lib/attributes-to-props.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,15 @@ function attributesToProps(attributes) {
2929
continue;
3030
}
3131

32-
// make DOM attribute/property consistent with React attribute/property
33-
reactProperty = propertyConfig[propertyName.toLowerCase()]
32+
// make HTML DOM attribute/property consistent with React attribute/property
33+
reactProperty = propertyConfig.html[propertyName.toLowerCase()];
34+
if (reactProperty) {
35+
props[reactProperty] = propertyValue;
36+
continue;
37+
}
38+
39+
// make SVG DOM attribute/property consistent with React attribute/property
40+
reactProperty = propertyConfig.svg[propertyName];
3441
if (reactProperty) {
3542
props[reactProperty] = propertyValue;
3643
}

lib/property-config.js

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,53 @@
33
/**
44
* Module dependencies.
55
*/
6-
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
76
var utilities = require('./utilities');
7+
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
8+
var SVGDOMPropertyConfig = require('react/lib/SVGDOMPropertyConfig');
9+
10+
var config = {
11+
html: {},
12+
svg: {}
13+
};
14+
15+
var propertyName;
816

9-
// first map out the DOM attribute names
10-
// e.g., { className: 'class' } => { class: 'className' }
17+
/**
18+
* HTML DOM property config.
19+
*/
20+
21+
// first map out the HTML DOM attribute names
22+
// e.g., { className: 'class' } => { 'class': 'className' }
1123
// https://github.com/facebook/react/blob/master/src/renderers/dom/shared/HTMLDOMPropertyConfig.js#L204
12-
var config = utilities.invertObject(
24+
config.html = utilities.invertObject(
1325
HTMLDOMPropertyConfig.DOMAttributeNames
1426
);
1527

16-
// then map out the rest of the DOM properties
28+
// then map out the rest of the HTML DOM properties
1729
// e.g., { charSet: 0 } => { charset: 'charSet' }
1830
// https://github.com/facebook/react/blob/master/src/renderers/dom/shared/HTMLDOMPropertyConfig.js#L28
19-
for (var key in HTMLDOMPropertyConfig.Properties) {
20-
config[key.toLowerCase()] = key;
31+
for (propertyName in HTMLDOMPropertyConfig.Properties) {
32+
// lowercase to make matching property names easier
33+
config.html[propertyName.toLowerCase()] = propertyName;
34+
}
35+
36+
/**
37+
* SVG DOM property config.
38+
*/
39+
40+
// first map out the SVG DOM attribute names
41+
// e.g., { fontSize: 'font-size' } => { 'font-size': 'fontSize' }
42+
// https://github.com/facebook/react/blob/master/src/renderers/dom/shared/SVGDOMPropertyConfig.js#L36
43+
config.svg = utilities.invertObject(
44+
SVGDOMPropertyConfig.DOMAttributeNames
45+
);
46+
47+
// then map out the rest of the SVG DOM properties
48+
// e.g., { preserveAlpha: 0 } => { preserveAlpha: 'preserveAlpha' }
49+
// https://github.com/facebook/react/blob/master/src/renderers/dom/shared/HTMLDOMPropertyConfig.js#L28
50+
for (propertyName in SVGDOMPropertyConfig.Properties) {
51+
// do not lowercase as some svg properties are camel cased
52+
config.html[propertyName] = propertyName;
2153
}
2254

2355
/**

test/attributes-to-props.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,53 @@ describe('attributes to props helper', function() {
104104

105105
});
106106

107+
/**
108+
* SVG DOM property to React prop.
109+
*/
110+
describe('SVG DOM properties', function() {
111+
112+
it('converts attributes/properties to React props', function() {
113+
assert.deepEqual(
114+
attributesToProps({
115+
edgeMode: 'edgeMode',
116+
'fill-opacity': '0.42',
117+
'fill-rule': 'evenodd',
118+
'glyph-orientation-vertical': 'auto',
119+
'horiz-adv-x': '9001',
120+
stroke: 'none',
121+
'xml:base': 'http://example.org'
122+
}),
123+
{
124+
edgeMode: 'edgeMode',
125+
fillOpacity: '0.42',
126+
fillRule: 'evenodd',
127+
glyphOrientationVertical: 'auto',
128+
horizAdvX: '9001',
129+
stroke: 'none',
130+
xmlBase: 'http://example.org'
131+
}
132+
);
133+
});
134+
135+
it('does not convert incorrectly capitalized properties', function() {
136+
assert.deepEqual(
137+
attributesToProps({
138+
'XLINK:HREF': '#',
139+
ychannelselector: 'G',
140+
ZoomAndPan: 'disable'
141+
}),
142+
{
143+
/*
144+
xlinkHref: '#',
145+
yChannelSelector: 'G',
146+
zoomAndPan: 'disable'
147+
*/
148+
}
149+
);
150+
});
151+
152+
});
153+
107154
/**
108155
* Style string to object.
109156
*/

0 commit comments

Comments
 (0)