Skip to content

Commit

Permalink
feat(jsx/dom): support SVG kebab-case attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
usualoma committed May 21, 2024
1 parent d3550bd commit a036181
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/jsx/dom/css.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ describe('Style and css for jsx/dom', () => {
})
global.document = dom.window.document
global.HTMLElement = dom.window.HTMLElement
global.SVGElement = dom.window.SVGElement
global.Text = dom.window.Text
root = document.getElementById('root') as HTMLElement
})
Expand Down
1 change: 1 addition & 0 deletions src/jsx/dom/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ describe('DOM', () => {
})
global.document = dom.window.document
global.HTMLElement = dom.window.HTMLElement
global.SVGElement = dom.window.SVGElement
global.Text = dom.window.Text
root = document.getElementById('root') as HTMLElement
})
Expand Down
20 changes: 15 additions & 5 deletions src/jsx/dom/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ const getEventSpec = (key: string): [string, boolean] | undefined => {
return undefined
}

const toAttributeName = (element: SupportedElement, key: string): string =>
element instanceof SVGElement &&
/[A-Z]/.test(key) &&
(key in element.style || // Presentation attributes are findable in style object. "clip-path", "font-size", "stroke-width", etc.
key.match(/^(?:o|pai|str|u|ve)/)) // Other un-deprecated kebab-case attributes. "overline-position", "paint-order", "strikethrough-position", etc.
? key.replace(/([A-Z])/g, '-$1').toLowerCase()
: key

const applyProps = (container: SupportedElement, attributes: Props, oldAttributes?: Props) => {
attributes ||= {}
for (const [key, value] of Object.entries(attributes)) {
Expand Down Expand Up @@ -164,14 +172,16 @@ const applyProps = (container: SupportedElement, attributes: Props, oldAttribute
;(container as any)[key] = value
}

const k = toAttributeName(container, key)

if (value === null || value === undefined || value === false) {
container.removeAttribute(key)
container.removeAttribute(k)
} else if (value === true) {
container.setAttribute(key, '')
container.setAttribute(k, '')
} else if (typeof value === 'string' || typeof value === 'number') {
container.setAttribute(key, value as string)
container.setAttribute(k, value as string)
} else {
container.setAttribute(key, value.toString())
container.setAttribute(k, value.toString())
}
}
}
Expand All @@ -189,7 +199,7 @@ const applyProps = (container: SupportedElement, attributes: Props, oldAttribute
value.current = null
}
} else {
container.removeAttribute(key)
container.removeAttribute(toAttributeName(container, key))
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/jsx/hooks/dom.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe('Hooks', () => {
})
global.document = dom.window.document
global.HTMLElement = dom.window.HTMLElement
global.SVGElement = dom.window.SVGElement
global.Text = dom.window.Text
root = document.getElementById('root') as HTMLElement
})
Expand Down

0 comments on commit a036181

Please sign in to comment.