|
21 | 21 | * Element type: `Fragment` symbol, tag name (`string`), component.
|
22 | 22 | * @param {Props} props
|
23 | 23 | * Element props, `children`, and maybe `node`.
|
24 |
| - * @param {string | undefined} key |
| 24 | + * @param {string | undefined} [key] |
25 | 25 | * Dynamicly generated key to use.
|
26 | 26 | * @returns {JSX.Element}
|
27 | 27 | * An element from your framework.
|
|
101 | 101 | * File path.
|
102 | 102 | * @property {Partial<Components>} components
|
103 | 103 | * Components to swap.
|
| 104 | + * @property {boolean} passKeys |
| 105 | + * Generate keys to optimize frameworks that support them. |
104 | 106 | * @property {boolean} passNode
|
105 | 107 | * Pass `node` to components.
|
106 | 108 | * @property {ElementAttributeNameCase} elementAttributeNameCase
|
|
126 | 128 | *
|
127 | 129 | * Passed in source info to `jsxDEV` when using the automatic runtime with
|
128 | 130 | * `development: true`.
|
| 131 | + * @property {boolean | null | undefined} [passKeys=true] |
| 132 | + * Generate keys to optimize frameworks that support them. |
| 133 | + * |
| 134 | + * > 👉 **Note**: Solid currently fails if keys are passed. |
129 | 135 | * @property {boolean | null | undefined} [passNode=false]
|
130 | 136 | * Pass the hast element node to components.
|
131 | 137 | * @property {ElementAttributeNameCase | null | undefined} [elementAttributeNameCase='react']
|
@@ -205,6 +211,9 @@ import {whitespace} from 'hast-util-whitespace'
|
205 | 211 |
|
206 | 212 | const own = {}.hasOwnProperty
|
207 | 213 |
|
| 214 | +/** @type {Map<string, number>} */ |
| 215 | +const emptyMap = new Map() |
| 216 | + |
208 | 217 | const cap = /[A-Z]/g
|
209 | 218 | const dashSomething = /-([a-z])/g
|
210 | 219 |
|
@@ -266,6 +275,7 @@ export function toJsxRuntime(tree, options) {
|
266 | 275 | const state = {
|
267 | 276 | Fragment: options.Fragment,
|
268 | 277 | schema: options.space === 'svg' ? svg : html,
|
| 278 | + passKeys: options.passKeys !== false, |
269 | 279 | passNode: options.passNode || false,
|
270 | 280 | elementAttributeNameCase: options.elementAttributeNameCase || 'react',
|
271 | 281 | stylePropertyNameCase: options.stylePropertyNameCase || 'dom',
|
@@ -367,7 +377,7 @@ function productionCreate(_, jsx, jsxs) {
|
367 | 377 | function create(_, type, props, key) {
|
368 | 378 | const isStaticChildren = props.children ? props.children.length > 1 : false
|
369 | 379 | const fn = isStaticChildren ? jsxs : jsx
|
370 |
| - return fn(type, props, key) |
| 380 | + return key ? fn(type, props, key) : fn(type, props) |
371 | 381 | }
|
372 | 382 | }
|
373 | 383 |
|
@@ -415,14 +425,16 @@ function createChildren(state, node) {
|
415 | 425 | const children = []
|
416 | 426 | let index = -1
|
417 | 427 | /** @type {Map<string, number>} */
|
418 |
| - const countsByTagName = new Map() |
| 428 | + // Note: test this when Solid doesn’t want to merge my upcoming PR. |
| 429 | + /* c8 ignore next */ |
| 430 | + const countsByTagName = state.passKeys ? new Map() : emptyMap |
419 | 431 |
|
420 | 432 | while (++index < node.children.length) {
|
421 | 433 | const child = node.children[index]
|
422 | 434 | /** @type {string | undefined} */
|
423 | 435 | let key
|
424 | 436 |
|
425 |
| - if (child.type === 'element') { |
| 437 | + if (state.passKeys && child.type === 'element') { |
426 | 438 | const count = countsByTagName.get(child.tagName) || 0
|
427 | 439 | key = child.tagName + '-' + count
|
428 | 440 | countsByTagName.set(child.tagName, count + 1)
|
|
0 commit comments