|
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