From bfb7d3f68eeaeca938eace08799c41af5b5a1abe Mon Sep 17 00:00:00 2001 From: Ryan Christian Date: Sat, 21 Sep 2024 21:24:11 -0500 Subject: [PATCH 1/3] refactor: Switch `VOID_ELEMENTS` over --- src/lib/util.js | 19 ++++++++++++++++++- src/pretty.js | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/lib/util.js b/src/lib/util.js index 84b348df..e40c457f 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -1,4 +1,21 @@ -export const VOID_ELEMENTS = /^(?:area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)$/; +export const VOID_ELEMENTS = new Set([ + 'area', + 'base', + 'br', + 'col', + 'command', + 'embed', + 'hr', + 'img', + 'input', + 'keygen', + '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|src[A-Z]|tabI|useM|item[A-Z]/; diff --git a/src/pretty.js b/src/pretty.js index 59df0e4c..7395da7b 100644 --- a/src/pretty.js +++ b/src/pretty.js @@ -332,7 +332,7 @@ function _renderToStringPretty( throw new Error(`${nodeName} is not a valid HTML tag name in ${s}`); let isVoid = - VOID_ELEMENTS.test(nodeName) || + VOID_ELEMENTS.has(nodeName) || (opts.voidElements && opts.voidElements.test(nodeName)); let pieces = []; From 8e49cc21efa0998649b7bea5fa89f555e1b540cf Mon Sep 17 00:00:00 2001 From: Ryan Christian Date: Sat, 21 Sep 2024 21:24:59 -0500 Subject: [PATCH 2/3] refactor: Switch `HTML_LOWER_CASE` over --- src/index.js | 2 +- src/lib/util.js | 48 +++++++++++++++++++++++++++++++++++++++++++++++- src/pretty.js | 2 +- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index c648b4fc..46c709af 100644 --- a/src/index.js +++ b/src/index.js @@ -637,7 +637,7 @@ function _renderToString( ? 'panose-1' : name.replace(/([A-Z])/g, '-$1').toLowerCase(); } - } else if (HTML_LOWER_CASE.test(name)) { + } else if (HTML_LOWER_CASE.has(name)) { name = name.toLowerCase(); } } diff --git a/src/lib/util.js b/src/lib/util.js index e40c457f..ff0e4b01 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -18,7 +18,53 @@ export const VOID_ELEMENTS = new Set([ ]); 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|src[A-Z]|tabI|useM|item[A-Z]/; + +export const HTML_LOWER_CASE = new Set([ + 'accessKey', + 'accessKeyLabel', + 'autoComplete', + 'autoCorrect', + 'autoFocus', + 'autoPlay', + 'autoCapitalize', + 'cellPadding', + 'cellSpacing', + 'charSet', + 'colSpan', + 'contentEditable', + 'contextMenu', + 'controlsList', + 'crossOrigin', + 'dateTime', + 'encType', + 'formAction', + 'formEncType', + 'formMethod', + 'formNoValidate', + 'formTarget', + 'frameBorder', + 'hrefLang', + 'inputMode', + 'maxLength', + 'minLength', + 'noValidate', + 'playsInline', + 'popoverTarget', + 'popoverTargetAction', + 'readOnly', + 'rowSpan', + 'srcSet', + 'srcDoc', + 'srcLang', + 'tabIndex', + 'useMap', + 'itemProp', + 'itemScope', + 'itemType', + 'itemID', + 'itemRef' +]); + 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 diff --git a/src/pretty.js b/src/pretty.js index 7395da7b..67847a8e 100644 --- a/src/pretty.js +++ b/src/pretty.js @@ -258,7 +258,7 @@ function _renderToStringPretty( ? 'panose-1' : name.replace(/([A-Z])/g, '-$1').toLowerCase(); } - } else if (HTML_LOWER_CASE.test(name)) { + } else if (HTML_LOWER_CASE.has(name)) { name = name.toLowerCase(); } From c12a3b500bcccf20a5cd70f0d86dac4a161a0699 Mon Sep 17 00:00:00 2001 From: Ryan Christian Date: Sat, 21 Sep 2024 22:07:28 -0500 Subject: [PATCH 3/3] refactor: Switch `SVG_KEBAB_CASE` over --- src/index.js | 4 +-- src/lib/util.js | 79 +++++++++++++++++++++++++++++++++++++++++++++++-- src/pretty.js | 4 +-- 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/index.js b/src/index.js index 46c709af..8dcffee5 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,7 @@ import { NAMESPACE_REPLACE_REGEX, HTML_LOWER_CASE, HTML_ENUMERATED, - SVG_CAMEL_CASE, + SVG_KEBAB_CASE, createComponent } from './lib/util.js'; import { options, h, Fragment } from 'preact'; @@ -631,7 +631,7 @@ function _renderToString( // serialize boolean aria-xyz or enumerated attribute values as strings v = v + EMPTY_STR; } else if (isSvgMode) { - if (SVG_CAMEL_CASE.test(name)) { + if (SVG_KEBAB_CASE.has(name)) { name = name === 'panose1' ? 'panose-1' diff --git a/src/lib/util.js b/src/lib/util.js index ff0e4b01..3ad443ab 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -18,7 +18,6 @@ export const VOID_ELEMENTS = new Set([ ]); export const UNSAFE_NAME = /[\s\n\\/='"\0<>]/; export const NAMESPACE_REPLACE_REGEX = /^(xlink|xmlns|xml)([A-Z])/; - export const HTML_LOWER_CASE = new Set([ 'accessKey', 'accessKeyLabel', @@ -64,8 +63,82 @@ export const HTML_LOWER_CASE = new Set([ 'itemID', 'itemRef' ]); - -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/; +export const SVG_KEBAB_CASE = new Set([ + 'accentHeight', + 'accumulate', + 'alignmentBaseline', + 'arabicForm', + 'baselineShift', + 'capHeight', + 'clipPath', + 'clipRule', + 'colorInterpolation', + 'colorInterpolationFilters', + 'colorProfile', + 'colorRendering', + 'dominantBaseline', + 'enableBackground', + 'fillOpacity', + 'fillRule', + 'floodColor', + 'floodOpacity', + 'fontFamily', + 'fontSize', + 'fontSizeAdjust', + 'fontStretch', + 'fontStyle', + 'fontVariant', + 'fontWeight', + 'glyphName', + 'glyphOrientationHorizontal', + 'glyphOrientationVertical', + 'horizAdvX', + 'horizOriginX', + 'imageRendering', + 'letterSpacing', + 'lightingColor', + 'markerEnd', + 'markerMid', + 'markerStart', + 'overlinePosition', + 'overlineThickness', + 'paintOrder', + 'panose1', + 'pointerEvents', + 'renderingIntent', + 'shapeRendering', + 'stopColor', + 'stopOpacity', + 'strikethroughPosition', + 'strikethroughThickness', + 'strokeDasharray', + 'strokeDashoffset', + 'strokeLinecap', + 'strokeLinejoin', + 'strokeMiterlimit', + 'strokeOpacity', + 'strokeWidth', + 'textAnchor', + 'textDecoration', + 'textRendering', + 'transformOrigin', + 'underlinePosition', + 'underlineThickness', + 'unicodeBidi', + 'unicodeRange', + 'unitsPerEm', + 'vAlphabetic', + 'vectorEffect', + 'vertAdvY', + 'vertOriginX', + 'vertOriginY', + 'vHanging', + 'vIdeographic', + 'vMathematical', + 'wordSpacing', + 'writingMode', + 'xHeight' +]); // Boolean DOM properties that translate to enumerated ('true'/'false') attributes export const HTML_ENUMERATED = new Set(['draggable', 'spellcheck']); diff --git a/src/pretty.js b/src/pretty.js index 67847a8e..3bd351d9 100644 --- a/src/pretty.js +++ b/src/pretty.js @@ -8,7 +8,7 @@ import { UNSAFE_NAME, VOID_ELEMENTS, NAMESPACE_REPLACE_REGEX, - SVG_CAMEL_CASE, + SVG_KEBAB_CASE, HTML_LOWER_CASE, getContext } from './lib/util.js'; @@ -252,7 +252,7 @@ function _renderToStringPretty( } else if (NAMESPACE_REPLACE_REGEX.test(name)) { name = name.replace(NAMESPACE_REPLACE_REGEX, '$1:$2').toLowerCase(); } else if (isSvgMode) { - if (SVG_CAMEL_CASE.test(name)) { + if (SVG_KEBAB_CASE.has(name)) { name = name === 'panose1' ? 'panose-1'