Skip to content

Commit c9889fc

Browse files
committed
Add support for passing props as HTML attributes
Previously, all properties were passed using React casing. This does not work, particularly for complex cases such as SVG and XML, in any other JSX runtime. Instead, all other JSX runtimes converge on allowing HTML casing. This adds an option for that.
1 parent cc05806 commit c9889fc

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

index.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/**
22
* @typedef {import('./lib/components.js').Components} Components
3+
* @typedef {import('./lib/index.js').ElementAttributeNameCase} ElementAttributeNameCase
34
* @typedef {import('./lib/index.js').Fragment} Fragment
45
* @typedef {import('./lib/index.js').Jsx} Jsx
56
* @typedef {import('./lib/index.js').JsxDev} JsxDev

lib/index.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@
4646
* @typedef {'html' | 'svg'} Space
4747
* Namespace.
4848
*
49+
* @typedef {'react' | 'html'} ElementAttributeNameCase
50+
* Specify casing to use for attribute names.
51+
*
52+
* React casing is for example `className`, `strokeLinecap`, `xmlLang`.
53+
* HTML casing is for example `class`, `stroke-linecap`, `xml:lang`.
54+
*
4955
* @typedef Source
5056
* Info about source.
5157
* @property {string | undefined} fileName
@@ -91,6 +97,8 @@
9197
* Components to swap.
9298
* @property {boolean} passNode
9399
* Pass `node` to components.
100+
* @property {ElementAttributeNameCase} elementAttributeNameCase
101+
* Casing to use for attribute names.
94102
* @property {Schema} schema
95103
* Current schema.
96104
* @property {unknown} Fragment
@@ -112,6 +120,8 @@
112120
* `development: true`.
113121
* @property {boolean | null | undefined} [passNode=false]
114122
* Pass the hast element node to components.
123+
* @property {ElementAttributeNameCase | null | undefined} [elementAttributeNameCase='react']
124+
* Specify casing to use for attribute names.
115125
* @property {Space | null | undefined} [space='html']
116126
* Whether `tree` is in the `'html'` or `'svg'` space.
117127
*
@@ -244,6 +254,7 @@ export function toJsxRuntime(tree, options) {
244254
Fragment: options.Fragment,
245255
schema: options.space === 'svg' ? svg : html,
246256
passNode: options.passNode || false,
257+
elementAttributeNameCase: options.elementAttributeNameCase || 'react',
247258
components: options.components || {},
248259
filePath,
249260
create
@@ -479,7 +490,9 @@ function createProperty(state, node, prop, value) {
479490
}
480491

481492
return [
482-
info.space ? hastToReact[info.property] || info.property : info.attribute,
493+
state.elementAttributeNameCase === 'react' && info.space
494+
? hastToReact[info.property] || info.property
495+
: info.attribute,
483496
value
484497
]
485498
}

readme.md

+23-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ with an automatic JSX runtime.
2121
* [`toJsxRuntime(tree, options)`](#tojsxruntimetree-options)
2222
* [`Options`](#options)
2323
* [`Components`](#components-1)
24+
* [`ElementAttributeNameCase`](#elementattributenamecase-1)
2425
* [`Fragment`](#fragment-1)
2526
* [`Jsx`](#jsx-1)
2627
* [`JsxDev`](#jsxdev-1)
@@ -163,6 +164,11 @@ File path to the original source file (`string`, optional).
163164
Passed in source info to `jsxDEV` when using the automatic runtime with
164165
`development: true`.
165166

167+
###### `elementAttributeNameCase`
168+
169+
Specify casing to use for attribute names
170+
([`ElementAttributeNameCase`][elementattributenamecase], default: `'react'`).
171+
166172
###### `passNode`
167173

168174
Pass the hast element node to components (`boolean`, default: `false`).
@@ -213,6 +219,19 @@ type Component<ComponentProps> =
213219
| (new (props: ComponentProps) => JSX.ElementClass)
214220
```
215221
222+
### `ElementAttributeNameCase`
223+
224+
Specify casing to use for attribute names (TypeScript type).
225+
226+
React casing is for example `className`, `strokeLinecap`, `xmlLang`.
227+
HTML casing is for example `class`, `stroke-linecap`, `xml:lang`.
228+
229+
###### Type
230+
231+
```ts
232+
type ElementAttributeNameCase = 'react' | 'html'
233+
```
234+
216235
### `Fragment`
217236
218237
Represent the children, typically a symbol (TypeScript type).
@@ -281,7 +300,7 @@ type Props = {
281300
| number
282301
| boolean
283302
| undefined
284-
children: Array<JSX.Element | string | null | undefined>
303+
children: Array<JSX.Element | string | null | undefined> | undefined
285304
node?: Element | undefined
286305
}
287306
```
@@ -397,6 +416,7 @@ followed by browsers such as Chrome, Firefox, and Safari.
397416

398417
This package is fully typed with [TypeScript][].
399418
It exports the additional types [`Components`][components],
419+
[`ElementAttributeNameCase`][elementattributenamecase],
400420
[`Fragment`][fragment], [`Jsx`][jsx], [`JsxDev`][jsxdev], [`Options`][options],
401421
[`Props`][props], [`Source`][source], and [`Space`][Space].
402422

@@ -513,3 +533,5 @@ abide by its terms.
513533
[space]: #space-1
514534

515535
[components]: #components-1
536+
537+
[elementattributenamecase]: #elementattributenamecase-1

0 commit comments

Comments
 (0)