diff --git a/lib/attributes-to-props.js b/lib/attributes-to-props.js index e2a52ab4..186db4b7 100644 --- a/lib/attributes-to-props.js +++ b/lib/attributes-to-props.js @@ -1,21 +1,20 @@ var reactProperty = require('react-property'); var utilities = require('./utilities'); -var hasOwnProperty = Object.prototype.hasOwnProperty; - /** * Converts HTML/SVG DOM attributes to React props. * * @param {object} [attributes={}] - HTML/SVG DOM attributes. * @return {object} - React props. */ -function attributesToProps(attributes) { +module.exports = function attributesToProps(attributes) { attributes = attributes || {}; var attributeName; var attributeNameLowerCased; var attributeValue; - var property; + var propName; + var propertyInfo; var props = {}; for (attributeName in attributes) { @@ -27,22 +26,23 @@ function attributesToProps(attributes) { continue; } - // convert HTML attribute to React prop + // convert HTML/SVG attribute to React prop attributeNameLowerCased = attributeName.toLowerCase(); - if (hasOwnProperty.call(reactProperty.html, attributeNameLowerCased)) { - property = reactProperty.html[attributeNameLowerCased]; - props[property.propertyName] = - property.hasBooleanValue || - (property.hasOverloadedBooleanValue && !attributeValue) - ? true - : attributeValue; - continue; - } - - // convert SVG attribute to React prop - if (hasOwnProperty.call(reactProperty.svg, attributeName)) { - property = reactProperty.svg[attributeName]; - props[property.propertyName] = attributeValue; + propName = reactProperty.possibleStandardNames[attributeNameLowerCased]; + + if (propName) { + props[propName] = attributeValue; + propertyInfo = reactProperty.getPropertyInfo(propName); + switch (propertyInfo && propertyInfo.type) { + case reactProperty.BOOLEAN: + props[propName] = true; + break; + case reactProperty.OVERLOADED_BOOLEAN: + if (attributeValue === '') { + props[propName] = true; + } + break; + } continue; } @@ -56,6 +56,4 @@ function attributesToProps(attributes) { utilities.setStyleProp(attributes.style, props); return props; -} - -module.exports = attributesToProps; +}; diff --git a/package.json b/package.json index 39576f00..e38a2988 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "dependencies": { "domhandler": "4.2.2", "html-dom-parser": "1.0.2", - "react-property": "1.0.2", + "react-property": "2.0.0", "style-to-js": "1.1.0" }, "devDependencies": { diff --git a/test/__snapshots__/attributes-to-props.test.js.snap b/test/__snapshots__/attributes-to-props.test.js.snap index ab7cdc34..95363523 100644 --- a/test/__snapshots__/attributes-to-props.test.js.snap +++ b/test/__snapshots__/attributes-to-props.test.js.snap @@ -35,6 +35,7 @@ Object { "controls": true, "default": true, "disabled": true, + "draggable": "false", "formNoValidate": true, "hidden": true, "ismap": "", @@ -42,8 +43,8 @@ Object { "loop": true, "multiple": true, "muted": true, + "noModule": true, "noValidate": true, - "nomodule": "", "open": true, "playsInline": true, "readOnly": true, @@ -88,21 +89,12 @@ Object { } `; -exports[`attributesToProps with SVG attribute keeps incorrectly capitalized attributes 1`] = ` -Object { - "XLINK:HREF": "#", - "YChannelSelector": "G", - "ZoomAndPan": "disable", -} -`; - exports[`attributesToProps with custom attribute converts attributes named after Object properties 1`] = ` Object { "__defineGetter__": "", "__defineSetter__": "", "__lookupGetter__": "", "__lookupSetter__": "", - "constructor": "", "hasOwnProperty": "", "isPrototypeOf": "", "propertyIsEnumerable": "", diff --git a/test/attributes-to-props.test.js b/test/attributes-to-props.test.js index 648d5931..7ac762ce 100644 --- a/test/attributes-to-props.test.js +++ b/test/attributes-to-props.test.js @@ -75,6 +75,7 @@ describe('attributesToProps with HTML attribute', () => { checked: 'true', controls: '', default: '', + draggable: 'false', disabled: 'disabled', formnovalidate: 'true', hidden: 'true', @@ -118,13 +119,22 @@ describe('attributesToProps with SVG attribute', () => { expect(attributesToProps(attributes)).toMatchSnapshot(); }); - it('keeps incorrectly capitalized attributes', () => { + /** + * SVG elements and attributes should all be entered in the case shown here since XML is case-sensitive (unlike HTML). + * + * @see {@link https://developer.mozilla.org/docs/Web/SVG/Tutorial/Introduction#before_you_start} + */ + it('fixes incorrectly capitalized attributes', () => { const attributes = { 'XLINK:HREF': '#', YChannelSelector: 'G', ZoomAndPan: 'disable' }; - expect(attributesToProps(attributes)).toMatchSnapshot(); + expect(attributesToProps(attributes)).toEqual({ + xlinkHref: '#', + yChannelSelector: 'G', + zoomAndPan: 'disable' + }); }); }); @@ -164,7 +174,6 @@ describe('attributesToProps with custom attribute', () => { __lookupGetter__: '', __lookupSetter__: '', __proto__: '', - constructor: '', hasOwnProperty: '', isPrototypeOf: '', propertyIsEnumerable: '', @@ -194,13 +203,4 @@ describe('utilities.PRESERVE_CUSTOM_ATTRIBUTES=false', () => { }; expect(attributesToProps(attributes)).toEqual(emptyProps); }); - - it('omits incorrectly capitalized attributes', () => { - const attributes = { - 'XLINK:HREF': '#', - YChannelSelector: 'G', - ZoomAndPan: 'disable' - }; - expect(attributesToProps(attributes)).toEqual(emptyProps); - }); });