@@ -222,24 +222,44 @@ export function removeSpecifier(
222222}
223223
224224export 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-
229225 if ( prop . name . type === "JSXNamespacedName" ) {
230226 return `${ prop . name . namespace . name } :${ prop . name . name . name } ` ;
231227 }
232228
233229 return prop . name . name ;
234230}
235231
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 ;
240259}
241260
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 ) {
243263 return props . find (
244264 ( attribute ) => attribute . type !== "JSXSpreadAttribute" && prop === jsxPropName ( attribute )
245265 ) as T . JSXAttribute | undefined ;
0 commit comments