@@ -21,10 +21,11 @@ class _Token:
2121 expressions : tuple [tuple [int , int ], ...] = ()
2222 complete : bool = True
2323 uncertain : bool = False
24+ type_spans : tuple [tuple [int , int ], ...] = ()
2425
2526
2627_WORD = re .compile (r"[\w$]+" , re .UNICODE )
27- _JSX_OPENING = re .compile (r"<[a-zA-Z] [\w:.-]*(?=[\s/>])(?!\s*(?:=|extends\b))" )
28+ _JSX_OPENING = re .compile (r"<(?:[^\W\d]|\$) [\w$ :.-]*(?=[\s/>< ])(?!\s*(?:=|extends\b))" )
2829_JSX_CLOSING = re .compile (r"</(?:[\w$][\w$:.-]*\s*)?>" )
2930_CLASS_VALUE_OPERATORS = {":" , "=" , "+=" , "-=" , "*=" , "/=" , "%=" , "**=" , "&=" , "|=" , "^=" , "&&=" , "||=" , "??=" }
3031_PREFIX = {"keyof" , "readonly" , "unique" , "typeof" , "asserts" , "abstract" , "new" }
@@ -158,6 +159,7 @@ def _jsx_element(source: str, index: int, depth: int) -> _Token | None:
158159 return None
159160 start = index
160161 expressions = []
162+ type_spans = []
161163 uncertain = False
162164 if source .startswith ("<>" , index ):
163165 name = ""
@@ -168,10 +170,23 @@ def _jsx_element(source: str, index: int, depth: int) -> _Token | None:
168170 return None
169171 name = source [index + 1 : opening .end ()]
170172 index = opening .end ()
173+ if index < len (source ) and source [index ] == "<" :
174+ arguments = _RuntimeView (source [index :], jsx = False )
175+ end = arguments .angle_end (0 )
176+ if end is None :
177+ return None
178+ argument_end = index + arguments .tokens [end - 1 ].end
179+ type_spans .append ((index , argument_end ))
180+ index = argument_end
171181 while index < len (source ):
172182 if source .startswith ("/>" , index ):
173183 return _Token (
174- source [start : index + 2 ], start , index + 2 , expressions = tuple (expressions ), uncertain = uncertain
184+ source [start : index + 2 ],
185+ start ,
186+ index + 2 ,
187+ expressions = tuple (expressions ),
188+ uncertain = uncertain ,
189+ type_spans = tuple (type_spans ),
175190 )
176191 if source [index ] == ">" :
177192 index += 1
@@ -189,7 +204,7 @@ def _jsx_element(source: str, index: int, depth: int) -> _Token | None:
189204 uncertain |= nested_uncertain
190205 index = end + 1
191206 elif source [index ] == "<" :
192- return None # Generic JSX arguments retain the existing token path.
207+ return None
193208 else :
194209 index += 1
195210 else :
@@ -200,13 +215,19 @@ def _jsx_element(source: str, index: int, depth: int) -> _Token | None:
200215 if not closing or source [index + 2 : closing .end () - 1 ].strip () != name :
201216 return None
202217 return _Token (
203- source [start : closing .end ()], start , closing .end (), expressions = tuple (expressions ), uncertain = uncertain
218+ source [start : closing .end ()],
219+ start ,
220+ closing .end (),
221+ expressions = tuple (expressions ),
222+ uncertain = uncertain ,
223+ type_spans = tuple (type_spans ),
204224 )
205225 if source [index ] == "<" :
206226 child = _jsx_element (source , index , depth + 1 )
207227 if child is None :
208228 return None
209229 expressions .extend (child .expressions )
230+ type_spans .extend (child .type_spans )
210231 uncertain |= child .uncertain
211232 index = child .end
212233 elif source [index ] == "{" :
@@ -874,6 +895,11 @@ def render(self, path: str, depth: int) -> str:
874895 for token in self .tokens :
875896 for start , end in token .expressions :
876897 output [start :end ] = class_usage_source (self .source [start :end ], path , depth = depth + 1 )
898+ if path .endswith (".tsx" ):
899+ for start , end in token .type_spans :
900+ for index in range (start , end ):
901+ if output [index ] not in "\r \n " :
902+ output [index ] = " "
877903 merged = []
878904 for start , end in sorted (self .erased ):
879905 if merged and start <= merged [- 1 ][1 ]:
0 commit comments