diff --git a/src/renderers/dom/shared/HTMLDOMPropertyConfig.js b/src/renderers/dom/shared/HTMLDOMPropertyConfig.js index cf567c1a689a1..ed3808c7f7dc7 100644 --- a/src/renderers/dom/shared/HTMLDOMPropertyConfig.js +++ b/src/renderers/dom/shared/HTMLDOMPropertyConfig.js @@ -22,6 +22,9 @@ var HAS_OVERLOADED_BOOLEAN_VALUE = DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE; var HTMLDOMPropertyConfig = { + // When adding attributes to this list, be sure to also add them to + // the `possibleStandardNames` module to ensure casing and incorrect + // name warnings. Properties: { allowFullScreen: HAS_BOOLEAN_VALUE, // specifies target context for links with `preload` type diff --git a/src/renderers/dom/shared/SVGDOMPropertyConfig.js b/src/renderers/dom/shared/SVGDOMPropertyConfig.js index 657e2f3a5ce18..46db12aa4250d 100644 --- a/src/renderers/dom/shared/SVGDOMPropertyConfig.js +++ b/src/renderers/dom/shared/SVGDOMPropertyConfig.js @@ -17,8 +17,12 @@ var NS = { }; /** - * This is a list of all SVG attributes that need special - * casing, namespacing, or boolean value assignment. + * This is a list of all SVG attributes that need special casing, + * namespacing, or boolean value assignment. + * + * When adding attributes to this list, be sure to also add them to + * the `possibleStandardNames` module to ensure casing and incorrect + * name warnings. * * SVG Attributes List: * https://www.w3.org/TR/SVG/attindex.html diff --git a/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js b/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js index b52588ef0d575..835a45c60826d 100644 --- a/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js +++ b/src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js @@ -2080,6 +2080,18 @@ describe('ReactDOMComponent', () => { 'Warning: Invalid prop `whatever` on
tag.', ); }); + + it('warns on bad casing of known HTML attributes', function() { + spyOn(console, 'error'); + + var el = ReactTestUtils.renderIntoDocument(
); + + expect(el.getAttribute('size')).toBe('30'); + + expectDev(console.error.calls.argsFor(0)[0]).toContain( + 'Warning: Invalid DOM property `SiZe`. Did you mean `size`?', + ); + }); }); describe('Object stringification', function() { diff --git a/src/renderers/dom/shared/hooks/possibleStandardNames.js b/src/renderers/dom/shared/hooks/possibleStandardNames.js index 1e7ef05597ad5..2d0a81771ece6 100644 --- a/src/renderers/dom/shared/hooks/possibleStandardNames.js +++ b/src/renderers/dom/shared/hooks/possibleStandardNames.js @@ -9,49 +9,82 @@ * @providesModule possibleStandardNames */ +// When adding attributes to the HTML or SVG whitelist, be sure to +// also add them to this module to ensure casing and incorrect name +// warnings. var possibleStandardNames = { // HTML + accept: 'accept', acceptcharset: 'acceptCharset', 'accept-charset': 'acceptCharset', accesskey: 'accessKey', + action: 'action', allowfullscreen: 'allowFullScreen', allowtransparency: 'allowTransparency', + alt: 'alt', + as: 'as', + async: 'async', autocapitalize: 'autoCapitalize', autocomplete: 'autoComplete', autocorrect: 'autoCorrect', autofocus: 'autoFocus', autoplay: 'autoPlay', autosave: 'autoSave', + capture: 'capture', cellpadding: 'cellPadding', cellspacing: 'cellSpacing', + challenge: 'challenge', charset: 'charSet', + checked: 'checked', + children: 'children', + cite: 'cite', class: 'className', classid: 'classID', classname: 'className', - children: 'children', + cols: 'cols', colspan: 'colSpan', + content: 'content', contenteditable: 'contentEditable', contextmenu: 'contextMenu', + controls: 'controls', controlslist: 'controlsList', + coords: 'coords', crossorigin: 'crossOrigin', dangerouslysetinnerhtml: 'dangerouslySetInnerHTML', + data: 'data', datetime: 'dateTime', - defaultvalue: 'defaultValue', + default: 'default', defaultchecked: 'defaultChecked', + defaultvalue: 'defaultValue', + defer: 'defer', + dir: 'dir', + disabled: 'disabled', + download: 'download', + draggable: 'draggable', enctype: 'encType', for: 'htmlFor', + form: 'form', formMethod: 'formMethod', formaction: 'formAction', formenctype: 'formEncType', formnovalidate: 'formNoValidate', formtarget: 'formTarget', frameborder: 'frameBorder', + headers: 'headers', + height: 'height', + hidden: 'hidden', + high: 'high', + href: 'href', hreflang: 'hrefLang', htmlfor: 'htmlFor', httpequiv: 'httpEquiv', 'http-equiv': 'httpEquiv', + icon: 'icon', + id: 'id', innerhtml: 'innerHTML', inputmode: 'inputMode', + integrity: 'integrity', + is: 'is', itemid: 'itemID', itemprop: 'itemProp', itemref: 'itemRef', @@ -59,253 +92,408 @@ var possibleStandardNames = { itemtype: 'itemType', keyparams: 'keyParams', keytype: 'keyType', + kind: 'kind', + label: 'label', + lang: 'lang', + list: 'list', + loop: 'loop', + low: 'low', + manifest: 'manifest', marginWidth: 'marginWidth', marginheight: 'marginHeight', + max: 'max', maxlength: 'maxLength', + media: 'media', mediagroup: 'mediaGroup', + method: 'method', + min: 'min', minLength: 'minlength', + multiple: 'multiple', + muted: 'muted', + name: 'name', + nonce: 'nonce', novalidate: 'noValidate', + open: 'open', + optimum: 'optimum', + pattern: 'pattern', + placeholder: 'placeholder', playsinline: 'playsInline', + poster: 'poster', + preload: 'preload', + profile: 'profile', radiogroup: 'radioGroup', readonly: 'readOnly', referrerpolicy: 'referrerPolicy', + rel: 'rel', + required: 'required', + reversed: 'reversed', + role: 'role', + rows: 'rows', rowspan: 'rowSpan', + sandbox: 'sandbox', + scope: 'scope', + scoped: 'scoped', + scrolling: 'scrolling', + seamless: 'seamless', + selected: 'selected', + shape: 'shape', + size: 'size', + sizes: 'sizes', + span: 'span', spellcheck: 'spellCheck', + src: 'src', srcdoc: 'srcDoc', srclang: 'srcLang', srcset: 'srcSet', + start: 'start', + step: 'step', + style: 'style', + summary: 'summary', tabindex: 'tabIndex', + target: 'target', + title: 'title', + type: 'type', usemap: 'useMap', + value: 'value', + width: 'width', + wmode: 'wmode', + wrap: 'wrap', // SVG + about: 'about', accentheight: 'accentHeight', 'accent-height': 'accentHeight', + accumulate: 'accumulate', + additive: 'additive', alignmentbaseline: 'alignmentBaseline', 'alignment-baseline': 'alignmentBaseline', allowreorder: 'allowReorder', - 'arabic-form': 'arabicForm', + alphabetic: 'alphabetic', + amplitude: 'amplitude', arabicform: 'arabicForm', + 'arabic-form': 'arabicForm', + ascent: 'ascent', attributename: 'attributeName', attributetype: 'attributeType', autoreverse: 'autoReverse', + azimuth: 'azimuth', basefrequency: 'baseFrequency', - baseprofile: 'baseProfile', - 'baseline-shift': 'baselineShift', baselineshift: 'baselineShift', + 'baseline-shift': 'baselineShift', + baseprofile: 'baseProfile', + bbox: 'bbox', + begin: 'begin', + bias: 'bias', + by: 'by', calcmode: 'calcMode', - 'cap-height': 'capHeight', capheight: 'capHeight', - 'clip-path': 'clipPath', + 'cap-height': 'capHeight', + clip: 'clip', clippath: 'clipPath', - 'clip-rule': 'clipRule', - cliprule: 'clipRule', + 'clip-path': 'clipPath', clippathunits: 'clipPathUnits', - 'color-interpolation': 'colorInterpolation', + cliprule: 'clipRule', + 'clip-rule': 'clipRule', + color: 'color', colorinterpolation: 'colorInterpolation', - 'color-interpolation-filters': 'colorInterpolationFilters', + 'color-interpolation': 'colorInterpolation', colorinterpolationfilters: 'colorInterpolationFilters', - 'color-profile': 'colorProfile', + 'color-interpolation-filters': 'colorInterpolationFilters', colorprofile: 'colorProfile', - 'color-rendering': 'colorRendering', + 'color-profile': 'colorProfile', colorrendering: 'colorRendering', + 'color-rendering': 'colorRendering', contentscripttype: 'contentScriptType', contentstyletype: 'contentStyleType', + cursor: 'cursor', + cx: 'cx', + cy: 'cy', + d: 'd', + datatype: 'datatype', + decelerate: 'decelerate', + descent: 'descent', diffuseconstant: 'diffuseConstant', - 'dominant-baseline': 'dominantBaseline', + direction: 'direction', + display: 'display', + divisor: 'divisor', dominantbaseline: 'dominantBaseline', + 'dominant-baseline': 'dominantBaseline', + dur: 'dur', + dx: 'dx', + dy: 'dy', edgemode: 'edgeMode', - 'enable-background': 'enableBackground', + elevation: 'elevation', enablebackground: 'enableBackground', + 'enable-background': 'enableBackground', + end: 'end', + exponent: 'exponent', externalresourcesrequired: 'externalResourcesRequired', - 'fill-opacity': 'fillOpacity', + fill: 'fill', fillopacity: 'fillOpacity', - 'fill-rule': 'fillRule', + 'fill-opacity': 'fillOpacity', fillrule: 'fillRule', + 'fill-rule': 'fillRule', + filter: 'filter', filterres: 'filterRes', filterunits: 'filterUnits', + floodOpacity: 'floodOpacity', + 'flood-opacity': 'floodOpacity', floodcolor: 'floodColor', 'flood-color': 'floodColor', - 'flood-opacity': 'floodOpacity', - floodOpacity: 'floodOpacity', - 'font-family': 'fontFamily', + focusable: 'focusable', fontfamily: 'fontFamily', - 'font-size': 'fontSize', + 'font-family': 'fontFamily', fontsize: 'fontSize', - 'font-size-adjust': 'fontSizeAdjust', + 'font-size': 'fontSize', fontsizeadjust: 'fontSizeAdjust', - 'font-stretch': 'fontStretch', + 'font-size-adjust': 'fontSizeAdjust', fontstretch: 'fontStretch', - 'font-style': 'fontStyle', + 'font-stretch': 'fontStretch', fontstyle: 'fontStyle', - 'font-variant': 'fontVariant', + 'font-style': 'fontStyle', fontvariant: 'fontVariant', - 'font-weight': 'fontWeight', + 'font-variant': 'fontVariant', fontweight: 'fontWeight', - 'glyph-name': 'glyphName', + 'font-weight': 'fontWeight', + format: 'format', + from: 'from', + fx: 'fx', + fy: 'fy', + g1: 'g1', + g2: 'g2', glyphname: 'glyphName', - 'glyph-orientation-horizontal': 'glyphOrientationHorizontal', + 'glyph-name': 'glyphName', glyphorientationhorizontal: 'glyphOrientationHorizontal', - 'glyph-orientation-vertical': 'glyphOrientationVertical', + 'glyph-orientation-horizontal': 'glyphOrientationHorizontal', glyphorientationvertical: 'glyphOrientationVertical', + 'glyph-orientation-vertical': 'glyphOrientationVertical', glyphref: 'glyphRef', gradienttransform: 'gradientTransform', gradientunits: 'gradientUnits', - 'horiz-adv-x': 'horizAdvX', + hanging: 'hanging', horizadvx: 'horizAdvX', - 'horiz-origin-x': 'horizOriginX', + 'horiz-adv-x': 'horizAdvX', horizoriginx: 'horizOriginX', - 'image-rendering': 'imageRendering', + 'horiz-origin-x': 'horizOriginX', + ideographic: 'ideographic', imagerendering: 'imageRendering', + 'image-rendering': 'imageRendering', + in2: 'in2', + in: 'in', + inlist: 'inlist', + intercept: 'intercept', + k1: 'k1', + k2: 'k2', + k3: 'k3', + k4: 'k4', + k: 'k', kernelmatrix: 'kernelMatrix', kernelunitlength: 'kernelUnitLength', + kerning: 'kerning', keypoints: 'keyPoints', keysplines: 'keySplines', keytimes: 'keyTimes', lengthadjust: 'lengthAdjust', - 'letter-spacing': 'letterSpacing', letterspacing: 'letterSpacing', - 'lighting-color': 'lightingColor', + 'letter-spacing': 'letterSpacing', lightingcolor: 'lightingColor', + 'lighting-color': 'lightingColor', limitingconeangle: 'limitingConeAngle', - 'marker-end': 'markerEnd', + local: 'local', markerend: 'markerEnd', - 'marker-mid': 'markerMid', + 'marker-end': 'markerEnd', + markerheight: 'markerHeight', markermid: 'markerMid', - 'marker-start': 'markerStart', + 'marker-mid': 'markerMid', markerstart: 'markerStart', - markerheight: 'markerHeight', + 'marker-start': 'markerStart', markerunits: 'markerUnits', markerwidth: 'markerWidth', + mask: 'mask', maskcontentunits: 'maskContentUnits', maskunits: 'maskUnits', + mathematical: 'mathematical', + mode: 'mode', numoctaves: 'numOctaves', - 'overline-position': 'overlinePosition', + offset: 'offset', + opacity: 'opacity', + operator: 'operator', + order: 'order', + orient: 'orient', + orientation: 'orientation', + origin: 'origin', + overflow: 'overflow', overlineposition: 'overlinePosition', - 'overline-thickness': 'overlineThickness', + 'overline-position': 'overlinePosition', overlinethickness: 'overlineThickness', - 'paint-order': 'paintOrder', + 'overline-thickness': 'overlineThickness', paintorder: 'paintOrder', + 'paint-order': 'paintOrder', + panose1: 'panose1', 'panose-1': 'panose1', pathlength: 'pathLength', patterncontentunits: 'patternContentUnits', patterntransform: 'patternTransform', patternunits: 'patternUnits', - 'pointer-events': 'pointerEvents', pointerevents: 'pointerEvents', + 'pointer-events': 'pointerEvents', + points: 'points', pointsatx: 'pointsAtX', pointsaty: 'pointsAtY', pointsatz: 'pointsAtZ', + prefix: 'prefix', preservealpha: 'preserveAlpha', preserveaspectratio: 'preserveAspectRatio', primitiveunits: 'primitiveUnits', + property: 'property', + r: 'r', + radius: 'radius', refx: 'refX', refy: 'refY', - 'rendering-intent': 'renderingIntent', renderingintent: 'renderingIntent', + 'rendering-intent': 'renderingIntent', repeatcount: 'repeatCount', repeatdur: 'repeatDur', requiredextensions: 'requiredExtensions', requiredfeatures: 'requiredFeatures', - 'shape-rendering': 'shapeRendering', + resource: 'resource', + restart: 'restart', + result: 'result', + results: 'results', + rotate: 'rotate', + rx: 'rx', + ry: 'ry', + scale: 'scale', + security: 'security', + seed: 'seed', shaperendering: 'shapeRendering', + 'shape-rendering': 'shapeRendering', + slope: 'slope', + spacing: 'spacing', specularconstant: 'specularConstant', specularexponent: 'specularExponent', + speed: 'speed', spreadmethod: 'spreadMethod', startoffset: 'startOffset', stddeviation: 'stdDeviation', + stemh: 'stemh', + stemv: 'stemv', stitchtiles: 'stitchTiles', - 'stop-color': 'stopColor', stopcolor: 'stopColor', + 'stop-color': 'stopColor', stopopacity: 'stopOpacity', 'stop-opacity': 'stopOpacity', - 'strikethrough-position': 'strikethroughPosition', strikethroughposition: 'strikethroughPosition', + 'strikethrough-position': 'strikethroughPosition', strikethroughthickness: 'strikethroughThickness', 'strikethrough-thickness': 'strikethroughThickness', - 'stroke-dasharray': 'strokeDasharray', + string: 'string', + stroke: 'stroke', strokedasharray: 'strokeDasharray', - 'stroke-dashoffset': 'strokeDashoffset', + 'stroke-dasharray': 'strokeDasharray', strokedashoffset: 'strokeDashoffset', - 'stroke-linecap': 'strokeLinecap', + 'stroke-dashoffset': 'strokeDashoffset', strokelinecap: 'strokeLinecap', - 'stroke-linejoin': 'strokeLinejoin', + 'stroke-linecap': 'strokeLinecap', strokelinejoin: 'strokeLinejoin', - 'stroke-miterlimit': 'strokeMiterlimit', + 'stroke-linejoin': 'strokeLinejoin', strokemiterlimit: 'strokeMiterlimit', - 'stroke-opacity': 'strokeOpacity', - strokeopacity: 'strokeOpacity', + 'stroke-miterlimit': 'strokeMiterlimit', + strokewidth: 'strokeWidth', 'stroke-width': 'strokeWidth', + strokeopacity: 'strokeOpacity', + 'stroke-opacity': 'strokeOpacity', suppresscontenteditablewarning: 'suppressContentEditableWarning', surfacescale: 'surfaceScale', systemlanguage: 'systemLanguage', tablevalues: 'tableValues', targetx: 'targetX', targety: 'targetY', - 'text-anchor': 'textAnchor', textanchor: 'textAnchor', - 'text-decoration': 'textDecoration', + 'text-anchor': 'textAnchor', textdecoration: 'textDecoration', - 'text-rendering': 'textRendering', - textrendering: 'textRendering', + 'text-decoration': 'textDecoration', textlength: 'textLength', - 'underline-position': 'underlinePosition', + textrendering: 'textRendering', + 'text-rendering': 'textRendering', + to: 'to', + transform: 'transform', + typeof: 'typeof', + u1: 'u1', + u2: 'u2', underlineposition: 'underlinePosition', - 'underline-thickness': 'underlineThickness', + 'underline-position': 'underlinePosition', underlinethickness: 'underlineThickness', - 'unicode-bidi': 'unicodeBidi', + 'underline-thickness': 'underlineThickness', + unicode: 'unicode', unicodebidi: 'unicodeBidi', - 'unicode-range': 'unicodeRange', + 'unicode-bidi': 'unicodeBidi', unicoderange: 'unicodeRange', - 'units-per-em': 'unitsPerEm', + 'unicode-range': 'unicodeRange', unitsperem: 'unitsPerEm', - 'v-alphabetic': 'vAlphabetic', + 'units-per-em': 'unitsPerEm', + unselectable: 'unselectable', valphabetic: 'vAlphabetic', - 'v-hanging': 'vHanging', - vhanging: 'vHanging', - 'v-ideographic': 'vIdeographic', - videographic: 'vIdeographic', - 'v-mathematical': 'vMathematical', - vmathematical: 'vMathematical', - 'vector-effect': 'vectorEffect', + 'v-alphabetic': 'vAlphabetic', + values: 'values', vectoreffect: 'vectorEffect', - 'vert-adv-y': 'vertAdvY', + 'vector-effect': 'vectorEffect', + version: 'version', vertadvy: 'vertAdvY', - 'vert-origin-x': 'vertOriginX', + 'vert-adv-y': 'vertAdvY', vertoriginx: 'vertOriginX', - 'vert-origin-y': 'vertOriginY', + 'vert-origin-x': 'vertOriginX', vertoriginy: 'vertOriginY', + 'vert-origin-y': 'vertOriginY', + vhanging: 'vHanging', + 'v-hanging': 'vHanging', + videographic: 'vIdeographic', + 'v-ideographic': 'vIdeographic', viewbox: 'viewBox', viewtarget: 'viewTarget', - 'word-spacing': 'wordSpacing', + visibility: 'visibility', + vmathematical: 'vMathematical', + 'v-mathematical': 'vMathematical', + vocab: 'vocab', + widths: 'widths', wordspacing: 'wordSpacing', - 'writing-mode': 'writingMode', + 'word-spacing': 'wordSpacing', writingmode: 'writingMode', - 'x-height': 'xHeight', - xheight: 'xHeight', + 'writing-mode': 'writingMode', + x1: 'x1', + x2: 'x2', + x: 'x', xchannelselector: 'xChannelSelector', - 'xlink:actuate': 'xlinkActuate', + xheight: 'xHeight', + 'x-height': 'xHeight', xlinkactuate: 'xlinkActuate', - 'xlink:arcrole': 'xlinkArcrole', + 'xlink:actuate': 'xlinkActuate', xlinkarcrole: 'xlinkArcrole', - 'xlink:href': 'xlinkHref', + 'xlink:arcrole': 'xlinkArcrole', xlinkhref: 'xlinkHref', - 'xlink:role': 'xlinkRole', + 'xlink:href': 'xlinkHref', xlinkrole: 'xlinkRole', - 'xlink:show': 'xlinkShow', + 'xlink:role': 'xlinkRole', xlinkshow: 'xlinkShow', - 'xlink:title': 'xlinkTitle', + 'xlink:show': 'xlinkShow', xlinktitle: 'xlinkTitle', - 'xlink:type': 'xlinkType', + 'xlink:title': 'xlinkTitle', xlinktype: 'xlinkType', - 'xml:base': 'xmlBase', + 'xlink:type': 'xlinkType', xmlbase: 'xmlBase', - 'xmlns:xlink': 'xmlnsXlink', - xmlnsxlink: 'xmlnsXlink', - 'xml:lang': 'xmlLang', + 'xml:base': 'xmlBase', xmllang: 'xmlLang', + 'xml:lang': 'xmlLang', + xmlns: 'xmlns', 'xml:space': 'xmlSpace', + xmlnsxlink: 'xmlnsXlink', + 'xmlns:xlink': 'xmlnsXlink', xmlspace: 'xmlSpace', + y1: 'y1', + y2: 'y2', + y: 'y', ychannelselector: 'yChannelSelector', + z: 'z', zoomandpan: 'zoomAndPan', };