@@ -222,24 +222,44 @@ export function removeSpecifier(
222
222
}
223
223
224
224
export function jsxPropName ( prop : T . JSXAttribute ) {
225
- if ( ! prop . type || prop . type !== "JSXAttribute" ) {
226
- throw new Error ( "The prop must be a JSXAttribute collected by the AST parser." ) ;
227
- }
228
-
229
225
if ( prop . name . type === "JSXNamespacedName" ) {
230
226
return `${ prop . name . namespace . name } :${ prop . name . name . name } ` ;
231
227
}
232
228
233
229
return prop . name . name ;
234
230
}
235
231
236
- export function jsxHasProp ( props : ( T . JSXAttribute | T . JSXSpreadAttribute ) [ ] , prop : string ) {
237
- return props . some (
238
- ( attribute ) => attribute . type !== "JSXSpreadAttribute" && prop === jsxPropName ( attribute )
239
- ) ;
232
+ type Props = T . JSXOpeningElement [ "attributes" ] ;
233
+
234
+ /** Iterate through both attributes and spread object props, yielding the name and the node. */
235
+ export function * jsxGetAllProps ( props : Props ) : Generator < [ string , T . Node ] > {
236
+ for ( const attr of props ) {
237
+ if ( attr . type === "JSXSpreadAttribute" && attr . argument . type === "ObjectExpression" ) {
238
+ for ( const property of attr . argument . properties ) {
239
+ if ( property . type === "Property" ) {
240
+ if ( property . key . type === "Identifier" ) {
241
+ yield [ property . key . name , property . key ] ;
242
+ } else if ( property . key . type === "Literal" ) {
243
+ yield [ String ( property . key . value ) , property . key ] ;
244
+ }
245
+ }
246
+ }
247
+ } else if ( attr . type === "JSXAttribute" ) {
248
+ yield [ jsxPropName ( attr ) , attr . name ] ;
249
+ }
250
+ }
251
+ }
252
+
253
+ /** Returns whether an element has a prop, checking spread object props. */
254
+ export function jsxHasProp ( props : Props , prop : string ) {
255
+ for ( const [ p ] of jsxGetAllProps ( props ) ) {
256
+ if ( p === prop ) return true ;
257
+ }
258
+ return false ;
240
259
}
241
260
242
- export function jsxGetProp ( props : ( T . JSXAttribute | T . JSXSpreadAttribute ) [ ] , prop : string ) {
261
+ /** Get a JSXAttribute, excluding spread props. */
262
+ export function jsxGetProp ( props : Props , prop : string ) {
243
263
return props . find (
244
264
( attribute ) => attribute . type !== "JSXSpreadAttribute" && prop === jsxPropName ( attribute )
245
265
) as T . JSXAttribute | undefined ;
0 commit comments