Skip to content

Commit 2eb96be

Browse files
Merge pull request #308 from preactjs/attribute-casing
2 parents e02629e + a331699 commit 2eb96be

File tree

3 files changed

+462
-0
lines changed

3 files changed

+462
-0
lines changed

.changeset/fifty-chefs-mate.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'preact-render-to-string': patch
3+
---
4+
5+
Fix incorrect casing of HTML attributes and SVG attributes

src/index.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,12 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent) {
384384
v = styleObjToCss(v);
385385
}
386386
break;
387+
case 'acceptCharset':
388+
name = 'accept-charset';
389+
break;
390+
case 'httpEquiv':
391+
name = 'http-equiv';
392+
break;
387393

388394
default: {
389395
if (isSvgMode && XLINK.test(name)) {
@@ -395,6 +401,17 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent) {
395401
// `draggable` is an enumerated attribute and not Boolean. A value of `true` or `false` is mandatory
396402
// https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/draggable
397403
v += '';
404+
} else if (isSvgMode) {
405+
if (SVG_CAMEL_CASE.test(name)) {
406+
name =
407+
name === 'panose1'
408+
? 'panose-1'
409+
: name.replace(/([A-Z])/g, '-$1').toLowerCase();
410+
} else if (XML_REPLACE_REGEX.test(name)) {
411+
name = name.toLowerCase().replace(XML_REPLACE_REGEX, 'xml:');
412+
}
413+
} else if (HTML_LOWER_CASE.test(name)) {
414+
name = name.toLowerCase();
398415
}
399416
}
400417
}
@@ -439,6 +456,9 @@ function _renderToString(vnode, context, isSvgMode, selectValue, parent) {
439456
return s + '>' + html + '</' + type + '>';
440457
}
441458

459+
const HTML_LOWER_CASE = /^accessK|^auto[A-Z]|^ch|^col|cont|cross|dateT|encT|form[A-Z]|frame|hrefL|inputM|maxL|minL|noV|playsI|readO|rowS|spellC|src[A-Z]|tabI|item[A-Z]/;
460+
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/;
461+
const XML_REPLACE_REGEX = /^xml:?/;
442462
const XLINK_REPLACE_REGEX = /^xlink:?/;
443463
const SELF_CLOSING = new Set([
444464
'area',

0 commit comments

Comments
 (0)