Skip to content

Commit

Permalink
feat: preserve id and class with g container
Browse files Browse the repository at this point in the history
  • Loading branch information
JacobLinCool committed Nov 13, 2024
1 parent 11575c9 commit 58a9183
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 3 deletions.
10 changes: 9 additions & 1 deletion src/builder/rect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export default async function rect(
isInheritingTransform,
src,
debug,
className,
htmlId,
}: {
id: string
left: number
Expand All @@ -29,6 +31,8 @@ export default async function rect(
isInheritingTransform: boolean
src?: string
debug?: boolean
className?: string
htmlId?: string
},
style: Record<string, number | string>,
inheritableStyle: Record<string, number | string>
Expand Down Expand Up @@ -293,6 +297,9 @@ export default async function rect(
)

return (
`<g${className ? ` class="${className}"` : ''}${
htmlId ? ` id="${htmlId}"` : ''
}>` +
(defs ? buildXMLString('defs', {}, defs) : '') +
(shadow ? shadow[0] : '') +
(imageBorderRadius ? imageBorderRadius[0] : '') +
Expand All @@ -307,6 +314,7 @@ export default async function rect(
(style.transform && (currentClipPath || maskId) ? '</g>' : '') +
(opacity !== 1 ? `</g>` : '') +
(shadow ? shadow[1] : '') +
extra
extra +
'</g>'
)
}
29 changes: 27 additions & 2 deletions src/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export interface SatoriNode {
key?: string | number
props: Record<string, any>
textContent?: string
className?: string
htmlId?: string
}

export default async function* layout(
Expand Down Expand Up @@ -110,7 +112,14 @@ export default async function* layout(
'dangerouslySetInnerHTML property is not supported. See documentation for more information https://github.com/vercel/satori#jsx.'
)
}
let { style, children, tw, lang: _newLocale = locale } = props || {}
let {
style,
children,
tw,
lang: _newLocale = locale,
className,
id: htmlId,
} = props || {}
const newLocale = normalizeLocale(_newLocale)

// Extend Tailwind styles.
Expand Down Expand Up @@ -217,6 +226,8 @@ export default async function* layout(
props: restProps,
key: element.key,
textContent: isReactElement(childrenNode) ? undefined : childrenNode,
className,
htmlId,
})

// Generate the rendered markup for the current node.
Expand All @@ -232,6 +243,8 @@ export default async function* layout(
src,
isInheritingTransform,
debug,
className,
htmlId,
},
computedStyle,
newInheritableStyle
Expand All @@ -251,6 +264,8 @@ export default async function* layout(
src,
isInheritingTransform,
debug,
className,
htmlId,
},
computedStyle,
newInheritableStyle
Expand All @@ -269,7 +284,17 @@ export default async function* layout(
)
}
baseRenderResult = await rect(
{ id, left, top, width, height, isInheritingTransform, debug },
{
id,
left,
top,
width,
height,
isInheritingTransform,
debug,
className,
htmlId,
},
computedStyle,
newInheritableStyle
)
Expand Down
6 changes: 6 additions & 0 deletions test/event.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ describe('Event', () => {
expect(nodes).toMatchInlineSnapshot(`
[
{
"className": undefined,
"height": 50,
"htmlId": undefined,
"key": null,
"left": 0,
"props": {
Expand All @@ -42,7 +44,9 @@ describe('Event', () => {
"width": 100,
},
{
"className": undefined,
"height": 50,
"htmlId": undefined,
"key": null,
"left": 0,
"props": {},
Expand All @@ -52,7 +56,9 @@ describe('Event', () => {
"width": 37,
},
{
"className": undefined,
"height": 50,
"htmlId": undefined,
"key": null,
"left": 37,
"props": {},
Expand Down
23 changes: 23 additions & 0 deletions test/id-and-class.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { it, describe, expect } from 'vitest'

import { initFonts } from './utils.js'
import satori from '../src/index.js'

describe('Id and Class', () => {
let fonts
initFonts((f) => (fonts = f))

it('should preserve id and class attributes', async () => {
const svg = await satori(
<div id='test-element' className='class1 class2'></div>,
{
width: 100,
height: 100,
fonts,
}
)
expect(svg).toMatchInlineSnapshot(
'"<svg width=\\"100\\" height=\\"100\\" viewBox=\\"0 0 100 100\\" xmlns=\\"http://www.w3.org/2000/svg\\"><g class=\\"class1 class2\\" id=\\"test-element\\"><mask id=\\"satori_om-id\\"><rect x=\\"0\\" y=\\"0\\" width=\\"0\\" height=\\"0\\" fill=\\"#fff\\"/></mask></g></svg>"'
)
})
})

0 comments on commit 58a9183

Please sign in to comment.