diff --git a/.changeset/angry-chairs-marry.md b/.changeset/angry-chairs-marry.md new file mode 100644 index 00000000..445fac09 --- /dev/null +++ b/.changeset/angry-chairs-marry.md @@ -0,0 +1,5 @@ +--- +'preact-render-to-string': patch +--- + +Fix `spellcheck={false}` not rendering as `spellcheck="false"` diff --git a/package-lock.json b/package-lock.json index 7045b906..59389a18 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "preact-render-to-string", - "version": "6.5.7", + "version": "6.5.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "preact-render-to-string", - "version": "6.5.7", + "version": "6.5.10", "license": "MIT", "devDependencies": { "@babel/plugin-transform-react-jsx": "^7.12.12", @@ -14,7 +14,7 @@ "@babel/register": "^7.12.10", "@changesets/changelog-github": "^0.4.1", "@changesets/cli": "^2.18.0", - "baseline-rts": "npm:preact-render-to-string@6.5.7", + "baseline-rts": "npm:preact-render-to-string@latest", "benchmarkjs-pretty": "^2.0.1", "chai": "^4.2.0", "check-export-map": "^1.3.1", @@ -2567,10 +2567,11 @@ }, "node_modules/baseline-rts": { "name": "preact-render-to-string", - "version": "6.5.7", - "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.5.7.tgz", - "integrity": "sha512-nACZDdv/ZZciuldVYMcfGqr61DKJeaAfPx96hn6OXoBGhgtU2yGQkA0EpTzWH4SvnwF0syLsL4WK7AIp3Ruc1g==", + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.5.10.tgz", + "integrity": "sha512-BJdypTQaBA5UbTF9NKZS3zP93Sw33tZOxNXIfuHofqOZFoMdsquNkVebs/HkEw0in/Qbi6Ep/Anngnj+VsHeBQ==", "dev": true, + "license": "MIT", "peerDependencies": { "preact": ">=10" } diff --git a/src/index.js b/src/index.js index 19771717..c648b4fc 100644 --- a/src/index.js +++ b/src/index.js @@ -4,6 +4,7 @@ import { UNSAFE_NAME, NAMESPACE_REPLACE_REGEX, HTML_LOWER_CASE, + HTML_ENUMERATED, SVG_CAMEL_CASE, createComponent } from './lib/util.js'; @@ -623,10 +624,11 @@ function _renderToString( name = name.replace(NAMESPACE_REPLACE_REGEX, '$1:$2').toLowerCase(); } else if (UNSAFE_NAME.test(name)) { continue; - } else if ((name[4] === '-' || name === 'draggable') && v != null) { - // serialize boolean aria-xyz or draggable attribute values as strings - // `draggable` is an enumerated attribute and not Boolean. A value of `true` or `false` is mandatory - // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/draggable + } else if ( + (name[4] === '-' || HTML_ENUMERATED.has(name)) && + v != null + ) { + // serialize boolean aria-xyz or enumerated attribute values as strings v = v + EMPTY_STR; } else if (isSvgMode) { if (SVG_CAMEL_CASE.test(name)) { @@ -637,9 +639,6 @@ function _renderToString( } } else if (HTML_LOWER_CASE.test(name)) { name = name.toLowerCase(); - if (name === 'spellcheck') { - v = '' + v; - } } } } diff --git a/src/lib/util.js b/src/lib/util.js index 48c02a0b..84b348df 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -1,8 +1,11 @@ export const VOID_ELEMENTS = /^(?:area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/; export const UNSAFE_NAME = /[\s\n\\/='"\0<>]/; export const NAMESPACE_REPLACE_REGEX = /^(xlink|xmlns|xml)([A-Z])/; -export const HTML_LOWER_CASE = /^accessK|^auto[A-Z]|^cell|^ch|^col|cont|cross|dateT|encT|form[A-Z]|frame|hrefL|inputM|maxL|minL|noV|playsI|popoverT|readO|rowS|spellC|src[A-Z]|tabI|useM|item[A-Z]/; -export const SVG_CAMEL_CASE = /^ac|^ali|arabic|basel|cap|clipPath$|clipRule$|color|dominant|enable|fill|flood|font|glyph[^R]|horiz|image|letter|lighting|marker[^WUH]|overline|panose|pointe|paint|rendering|shape|stop|strikethrough|stroke|spel|text[^L]|transform|underline|unicode|units|^v[^i]|^w|^xH/; +export const HTML_LOWER_CASE = /^accessK|^auto[A-Z]|^cell|^ch|^col|cont|cross|dateT|encT|form[A-Z]|frame|hrefL|inputM|maxL|minL|noV|playsI|popoverT|readO|rowS|src[A-Z]|tabI|useM|item[A-Z]/; +export const SVG_CAMEL_CASE = /^ac|^ali|arabic|basel|cap|clipPath$|clipRule$|color|dominant|enable|fill|flood|font|glyph[^R]|horiz|image|letter|lighting|marker[^WUH]|overline|panose|pointe|paint|rendering|shape|stop|strikethrough|stroke|text[^L]|transform|underline|unicode|units|^v[^i]|^w|^xH/; + +// Boolean DOM properties that translate to enumerated ('true'/'false') attributes +export const HTML_ENUMERATED = new Set(['draggable', 'spellcheck']); // DOM properties that should NOT have "px" added when numeric const ENCODED_ENTITIES = /["&<]/; diff --git a/test/render.test.jsx b/test/render.test.jsx index ba8e0289..45915699 100644 --- a/test/render.test.jsx +++ b/test/render.test.jsx @@ -154,11 +154,11 @@ describe('render', () => { expect(rendered).to.equal(`
`); }); - it('should support spellCheck', () => { - let rendered = render(); + it('should support spellcheck', () => { + let rendered = render(); expect(rendered).to.equal(``); - rendered = render(); + rendered = render(); expect(rendered).to.equal(``); }); diff --git a/test/utils.jsx b/test/utils.jsx index 068a1149..631f02df 100644 --- a/test/utils.jsx +++ b/test/utils.jsx @@ -400,7 +400,6 @@ export const htmlAttributes = { slot: 'slot', span: 'span', spellcheck: 'spellcheck', - spellCheck: 'spellcheck', src: 'src', srcset: 'srcset', srcDoc: 'srcdoc',