Skip to content

Commit 859dff5

Browse files
committed
Decamelize html attributes
1 parent c9bd4bb commit 859dff5

File tree

3 files changed

+23
-6
lines changed

3 files changed

+23
-6
lines changed

src/index.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ const UNNAMED = [];
1717

1818
const VOID_ELEMENTS = /^(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/;
1919

20+
const DASHED_ATTRS = /^(acceptC|httpE)/;
21+
const CAMEL_ATTRS = /^(viewB)/;
22+
2023
const UNSAFE_NAME = /[\s\n\\/='"\0<>]/;
2124

2225
const noop = () => {};
@@ -250,9 +253,13 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
250253
name = 'class';
251254
} else if (isSvgMode && name.match(/^xlink:?./)) {
252255
name = name.toLowerCase().replace(/^xlink:?/, 'xlink:');
256+
} else if (DASHED_ATTRS.test(name)) {
257+
name = name.replace(/([A-Z])/g, (l) => '-' + l.toLowerCase());
258+
} else if (!CAMEL_ATTRS.test(name)) {
259+
name = name.toLowerCase();
253260
}
254261

255-
if (name === 'htmlFor') {
262+
if (name === 'htmlfor') {
256263
if (props.for) continue;
257264
name = 'for';
258265
}
@@ -275,7 +282,7 @@ function _renderToString(vnode, context, opts, inner, isSvgMode, selectValue) {
275282
continue;
276283
}
277284

278-
if (name === 'dangerouslySetInnerHTML') {
285+
if (name === 'dangerouslysetinnerhtml') {
279286
html = v && v.__html;
280287
} else if (nodeName === 'textarea' && name === 'value') {
281288
// <textarea value="a&b"> --> <textarea>a&amp;b</textarea>

test/jsx.test.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,16 @@ describe('jsx', () => {
7474
`);
7575
});
7676

77+
it('should decamelize attributes', () => {
78+
expect(renderJsx(<img srcSet="foo.png, foo2.png 2x" />)).to.equal(
79+
`<img srcset="foo.png, foo2.png 2x" />`
80+
);
81+
});
82+
83+
it('should dasherize certain attributes', () => {
84+
expect(renderJsx(<meta httpEquiv="" />)).to.equal(`<meta http-equiv="" />`);
85+
});
86+
7787
it('should skip null and undefined attributes', () => {
7888
expect(renderJsx(<a b={null}>bar</a>)).to.equal(`<a>bar</a>`);
7989

@@ -151,11 +161,11 @@ describe('jsx', () => {
151161
it('should skip function names if functionNames=false', () => {
152162
expect(
153163
renderJsx(<div onClick={() => {}} />, { functionNames: false })
154-
).to.equal('<div onClick={Function}></div>');
164+
).to.equal('<div onclick={Function}></div>');
155165

156166
expect(
157167
renderJsx(<div onClick={function foo() {}} />, { functionNames: false })
158-
).to.equal('<div onClick={Function}></div>');
168+
).to.equal('<div onclick={Function}></div>');
159169
});
160170

161171
it('should render self-closing elements', () => {

test/render.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ describe('render', () => {
265265

266266
it('should render SVG elements', () => {
267267
let rendered = render(
268-
<svg>
268+
<svg viewBox="0 0 100 100">
269269
<image xlinkHref="#" />
270270
<foreignObject>
271271
<div xlinkHref="#" />
@@ -277,7 +277,7 @@ describe('render', () => {
277277
);
278278

279279
expect(rendered).to.equal(
280-
`<svg><image xlink:href="#"></image><foreignObject><div xlinkHref="#"></div></foreignObject><g><image xlink:href="#"></image></g></svg>`
280+
`<svg viewBox="0 0 100 100"><image xlink:href="#"></image><foreignObject><div xlinkhref="#"></div></foreignObject><g><image xlink:href="#"></image></g></svg>`
281281
);
282282
});
283283
});

0 commit comments

Comments
 (0)