@hubspot/ui-extensions-sdk-api-metadata 0.12.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__generated__/component-props.js +502 -22
- package/dist/__tests__/component-props-docs.spec.js +287 -6
- package/dist/__tests__/jsx-utils.spec.d.ts +1 -0
- package/dist/__tests__/jsx-utils.spec.js +162 -0
- package/dist/__tests__/markdown-utils.spec.d.ts +1 -0
- package/dist/__tests__/markdown-utils.spec.js +13 -0
- package/dist/component-props-docs.js +15 -19
- package/dist/internal/get-type-source.js +372 -0
- package/dist/internal/render-prop-type.d.ts +4 -4
- package/dist/internal/render-prop-type.js +161 -49
- package/dist/internal/utils/jsx-utils.d.ts +32 -0
- package/dist/internal/utils/jsx-utils.js +77 -0
- package/dist/internal/utils/markdown-utils.d.ts +8 -3
- package/dist/internal/utils/markdown-utils.js +11 -4
- package/dist/types.d.ts +94 -1
- package/dist/types.js +93 -0
- package/package.json +6 -5
- package/dist/internal/utils/html-utils.d.ts +0 -7
- package/dist/internal/utils/html-utils.js +0 -18
|
@@ -8,6 +8,378 @@ const componentSourceLookup = {
|
|
|
8
8
|
exportName: 'AccordionProps',
|
|
9
9
|
exportPath: '.',
|
|
10
10
|
},
|
|
11
|
+
Alert: {
|
|
12
|
+
exportName: 'AlertProps',
|
|
13
|
+
exportPath: '.',
|
|
14
|
+
},
|
|
15
|
+
AutoGrid: {
|
|
16
|
+
exportName: 'AutoGridProps',
|
|
17
|
+
exportPath: '.',
|
|
18
|
+
},
|
|
19
|
+
BarChart: {
|
|
20
|
+
exportName: 'BarChartProps',
|
|
21
|
+
exportPath: '.',
|
|
22
|
+
},
|
|
23
|
+
Box: {
|
|
24
|
+
exportName: 'BoxProps',
|
|
25
|
+
exportPath: '.',
|
|
26
|
+
},
|
|
27
|
+
Button: {
|
|
28
|
+
exportName: 'ButtonProps',
|
|
29
|
+
exportPath: '.',
|
|
30
|
+
},
|
|
31
|
+
ButtonRow: {
|
|
32
|
+
exportName: 'ButtonRowProps',
|
|
33
|
+
exportPath: '.',
|
|
34
|
+
},
|
|
35
|
+
Card: {
|
|
36
|
+
exportName: 'CardProps',
|
|
37
|
+
exportPath: '.',
|
|
38
|
+
},
|
|
39
|
+
Center: {
|
|
40
|
+
exportName: 'CenterProps',
|
|
41
|
+
exportPath: './experimental',
|
|
42
|
+
},
|
|
43
|
+
Checkbox: {
|
|
44
|
+
exportName: 'CheckboxProps',
|
|
45
|
+
exportPath: '.',
|
|
46
|
+
},
|
|
47
|
+
CrmActionButton: {
|
|
48
|
+
exportName: 'CrmActionButtonProps',
|
|
49
|
+
exportPath: './crm',
|
|
50
|
+
},
|
|
51
|
+
CrmActionLink: {
|
|
52
|
+
exportName: 'CrmActionLinkProps',
|
|
53
|
+
exportPath: './crm',
|
|
54
|
+
},
|
|
55
|
+
CrmAssociationPivot: {
|
|
56
|
+
exportName: 'CrmAssociationPivotProps',
|
|
57
|
+
exportPath: './crm',
|
|
58
|
+
},
|
|
59
|
+
CrmAssociationPropertyList: {
|
|
60
|
+
exportName: 'CrmAssociationPropertyListProps',
|
|
61
|
+
exportPath: './crm',
|
|
62
|
+
},
|
|
63
|
+
CrmAssociationStageTracker: {
|
|
64
|
+
exportName: 'CrmAssociationStageTrackerProps',
|
|
65
|
+
exportPath: './crm',
|
|
66
|
+
},
|
|
67
|
+
CrmAssociationTable: {
|
|
68
|
+
exportName: 'CrmAssociationTableProps',
|
|
69
|
+
exportPath: './crm',
|
|
70
|
+
},
|
|
71
|
+
CrmCardActions: {
|
|
72
|
+
exportName: 'CrmCardActionsProps',
|
|
73
|
+
exportPath: './crm',
|
|
74
|
+
},
|
|
75
|
+
CrmDataHighlight: {
|
|
76
|
+
exportName: 'CrmDataHighlightProps',
|
|
77
|
+
exportPath: './crm',
|
|
78
|
+
},
|
|
79
|
+
CrmPropertyList: {
|
|
80
|
+
exportName: 'CrmPropertyListProps',
|
|
81
|
+
exportPath: './crm',
|
|
82
|
+
},
|
|
83
|
+
CrmReport: {
|
|
84
|
+
exportName: 'CrmReportProps',
|
|
85
|
+
exportPath: './crm',
|
|
86
|
+
},
|
|
87
|
+
CrmSimpleDeadline: {
|
|
88
|
+
exportName: 'CrmSimpleDeadlineProps',
|
|
89
|
+
exportPath: './crm',
|
|
90
|
+
},
|
|
91
|
+
CrmStageTracker: {
|
|
92
|
+
exportName: 'CrmStageTrackerProps',
|
|
93
|
+
exportPath: './crm',
|
|
94
|
+
},
|
|
95
|
+
CrmStatistics: {
|
|
96
|
+
exportName: 'CrmStatisticsProps',
|
|
97
|
+
exportPath: './crm',
|
|
98
|
+
},
|
|
99
|
+
CurrencyInput: {
|
|
100
|
+
exportName: 'CurrencyInputProps',
|
|
101
|
+
exportPath: '.',
|
|
102
|
+
},
|
|
103
|
+
DateInput: {
|
|
104
|
+
exportName: 'DateInputProps',
|
|
105
|
+
exportPath: '.',
|
|
106
|
+
},
|
|
107
|
+
DescriptionList: {
|
|
108
|
+
exportName: 'DescriptionListProps',
|
|
109
|
+
exportPath: '.',
|
|
110
|
+
},
|
|
111
|
+
DescriptionListItem: {
|
|
112
|
+
exportName: 'DescriptionListItemProps',
|
|
113
|
+
exportPath: '.',
|
|
114
|
+
},
|
|
115
|
+
Divider: {
|
|
116
|
+
exportName: 'DividerProps',
|
|
117
|
+
exportPath: '.',
|
|
118
|
+
},
|
|
119
|
+
Dropdown: {
|
|
120
|
+
exportName: 'DropdownProps',
|
|
121
|
+
exportPath: '.',
|
|
122
|
+
},
|
|
123
|
+
DropdownButtonItem: {
|
|
124
|
+
exportName: 'DropdownButtonItemProps',
|
|
125
|
+
exportPath: '.',
|
|
126
|
+
},
|
|
127
|
+
EmptyState: {
|
|
128
|
+
exportName: 'EmptyStateProps',
|
|
129
|
+
exportPath: '.',
|
|
130
|
+
},
|
|
131
|
+
ErrorState: {
|
|
132
|
+
exportName: 'ErrorStateProps',
|
|
133
|
+
exportPath: '.',
|
|
134
|
+
},
|
|
135
|
+
ExpandableText: {
|
|
136
|
+
exportName: 'ExpandableTextProps',
|
|
137
|
+
exportPath: './experimental',
|
|
138
|
+
},
|
|
139
|
+
FileInput: {
|
|
140
|
+
exportName: 'FileInputProps',
|
|
141
|
+
exportPath: './experimental',
|
|
142
|
+
},
|
|
143
|
+
Flex: {
|
|
144
|
+
exportName: 'FlexProps',
|
|
145
|
+
exportPath: '.',
|
|
146
|
+
},
|
|
147
|
+
Form: {
|
|
148
|
+
exportName: 'FormProps',
|
|
149
|
+
exportPath: '.',
|
|
150
|
+
},
|
|
151
|
+
Grid: {
|
|
152
|
+
exportName: 'GridProps',
|
|
153
|
+
exportPath: './experimental',
|
|
154
|
+
},
|
|
155
|
+
GridItem: {
|
|
156
|
+
exportName: 'GridItemProps',
|
|
157
|
+
exportPath: './experimental',
|
|
158
|
+
},
|
|
159
|
+
HeaderActions: {
|
|
160
|
+
exportName: 'HeaderActionsProps',
|
|
161
|
+
exportPath: '.',
|
|
162
|
+
},
|
|
163
|
+
Heading: {
|
|
164
|
+
exportName: 'HeadingProps',
|
|
165
|
+
exportPath: '.',
|
|
166
|
+
},
|
|
167
|
+
Icon: {
|
|
168
|
+
exportName: 'IconProps',
|
|
169
|
+
exportPath: '.',
|
|
170
|
+
},
|
|
171
|
+
Iframe: {
|
|
172
|
+
exportName: 'IframeProps',
|
|
173
|
+
exportPath: '.',
|
|
174
|
+
},
|
|
175
|
+
Illustration: {
|
|
176
|
+
exportName: 'IllustrationProps',
|
|
177
|
+
exportPath: '.',
|
|
178
|
+
},
|
|
179
|
+
Image: {
|
|
180
|
+
exportName: 'ImageProps',
|
|
181
|
+
exportPath: '.',
|
|
182
|
+
},
|
|
183
|
+
Inline: {
|
|
184
|
+
exportName: 'InlineProps',
|
|
185
|
+
exportPath: '.',
|
|
186
|
+
},
|
|
187
|
+
Input: {
|
|
188
|
+
exportName: 'InputProps',
|
|
189
|
+
exportPath: '.',
|
|
190
|
+
},
|
|
191
|
+
LineChart: {
|
|
192
|
+
exportName: 'LineChartProps',
|
|
193
|
+
exportPath: '.',
|
|
194
|
+
},
|
|
195
|
+
Link: {
|
|
196
|
+
exportName: 'LinkProps',
|
|
197
|
+
exportPath: '.',
|
|
198
|
+
},
|
|
199
|
+
List: {
|
|
200
|
+
exportName: 'ListProps',
|
|
201
|
+
exportPath: '.',
|
|
202
|
+
},
|
|
203
|
+
LoadingButton: {
|
|
204
|
+
exportName: 'LoadingButtonProps',
|
|
205
|
+
exportPath: '.',
|
|
206
|
+
},
|
|
207
|
+
LoadingSpinner: {
|
|
208
|
+
exportName: 'LoadingSpinnerProps',
|
|
209
|
+
exportPath: '.',
|
|
210
|
+
},
|
|
211
|
+
MediaObject: {
|
|
212
|
+
exportName: 'MediaObjectProps',
|
|
213
|
+
exportPath: './experimental',
|
|
214
|
+
},
|
|
215
|
+
Modal: {
|
|
216
|
+
exportName: 'ModalProps',
|
|
217
|
+
exportPath: '.',
|
|
218
|
+
},
|
|
219
|
+
ModalBody: {
|
|
220
|
+
exportName: 'ModalBodyProps',
|
|
221
|
+
exportPath: '.',
|
|
222
|
+
},
|
|
223
|
+
ModalFooter: {
|
|
224
|
+
exportName: 'ModalFooterProps',
|
|
225
|
+
exportPath: '.',
|
|
226
|
+
},
|
|
227
|
+
MultiSelect: {
|
|
228
|
+
exportName: 'MultiSelectProps',
|
|
229
|
+
exportPath: '.',
|
|
230
|
+
},
|
|
231
|
+
NumberInput: {
|
|
232
|
+
exportName: 'NumberInputProps',
|
|
233
|
+
exportPath: '.',
|
|
234
|
+
},
|
|
235
|
+
Panel: {
|
|
236
|
+
exportName: 'PanelProps',
|
|
237
|
+
exportPath: '.',
|
|
238
|
+
},
|
|
239
|
+
PanelBody: {
|
|
240
|
+
exportName: 'PanelBodyProps',
|
|
241
|
+
exportPath: '.',
|
|
242
|
+
},
|
|
243
|
+
PanelFooter: {
|
|
244
|
+
exportName: 'PanelFooterProps',
|
|
245
|
+
exportPath: '.',
|
|
246
|
+
},
|
|
247
|
+
PanelSection: {
|
|
248
|
+
exportName: 'PanelSectionProps',
|
|
249
|
+
exportPath: '.',
|
|
250
|
+
},
|
|
251
|
+
Popover: {
|
|
252
|
+
exportName: 'PopoverProps',
|
|
253
|
+
exportPath: './experimental',
|
|
254
|
+
},
|
|
255
|
+
PrimaryHeaderActionButton: {
|
|
256
|
+
exportName: 'HeaderActionButtonProps',
|
|
257
|
+
exportPath: '.',
|
|
258
|
+
},
|
|
259
|
+
ProgressBar: {
|
|
260
|
+
exportName: 'ProgressBarProps',
|
|
261
|
+
exportPath: '.',
|
|
262
|
+
},
|
|
263
|
+
RadioButton: {
|
|
264
|
+
exportName: 'RadioButtonProps',
|
|
265
|
+
exportPath: '.',
|
|
266
|
+
},
|
|
267
|
+
ScoreCircle: {
|
|
268
|
+
exportName: 'ScoreProps',
|
|
269
|
+
exportPath: '.',
|
|
270
|
+
},
|
|
271
|
+
SearchInput: {
|
|
272
|
+
exportName: 'SearchInputProps',
|
|
273
|
+
exportPath: '.',
|
|
274
|
+
},
|
|
275
|
+
SecondaryHeaderActionButton: {
|
|
276
|
+
exportName: 'HeaderActionButtonProps',
|
|
277
|
+
exportPath: '.',
|
|
278
|
+
},
|
|
279
|
+
Select: {
|
|
280
|
+
exportName: 'SelectProps',
|
|
281
|
+
exportPath: '.',
|
|
282
|
+
},
|
|
283
|
+
SettingsView: {
|
|
284
|
+
exportName: 'SettingsViewProps',
|
|
285
|
+
exportPath: './experimental',
|
|
286
|
+
},
|
|
287
|
+
Stack2: {
|
|
288
|
+
exportName: 'Stack2Props',
|
|
289
|
+
exportPath: './experimental',
|
|
290
|
+
},
|
|
291
|
+
Statistics: {
|
|
292
|
+
exportName: 'StatisticsProps',
|
|
293
|
+
exportPath: '.',
|
|
294
|
+
},
|
|
295
|
+
StatisticsItem: {
|
|
296
|
+
exportName: 'StatisticsItemProps',
|
|
297
|
+
exportPath: '.',
|
|
298
|
+
},
|
|
299
|
+
StatisticsTrend: {
|
|
300
|
+
exportName: 'StatisticsTrendProps',
|
|
301
|
+
exportPath: '.',
|
|
302
|
+
},
|
|
303
|
+
StatusTag: {
|
|
304
|
+
exportName: 'StatusTagProps',
|
|
305
|
+
exportPath: '.',
|
|
306
|
+
},
|
|
307
|
+
StepIndicator: {
|
|
308
|
+
exportName: 'StepIndicatorProps',
|
|
309
|
+
exportPath: '.',
|
|
310
|
+
},
|
|
311
|
+
StepperInput: {
|
|
312
|
+
exportName: 'StepperInputProps',
|
|
313
|
+
exportPath: '.',
|
|
314
|
+
},
|
|
315
|
+
Tab: {
|
|
316
|
+
exportName: 'TabProps',
|
|
317
|
+
exportPath: '.',
|
|
318
|
+
},
|
|
319
|
+
Table: {
|
|
320
|
+
exportName: 'TableProps',
|
|
321
|
+
exportPath: '.',
|
|
322
|
+
},
|
|
323
|
+
TableBody: {
|
|
324
|
+
exportName: 'TableElementProps',
|
|
325
|
+
exportPath: '.',
|
|
326
|
+
},
|
|
327
|
+
TableCell: {
|
|
328
|
+
exportName: 'TableCellProps',
|
|
329
|
+
exportPath: '.',
|
|
330
|
+
},
|
|
331
|
+
TableFooter: {
|
|
332
|
+
exportName: 'TableElementProps',
|
|
333
|
+
exportPath: '.',
|
|
334
|
+
},
|
|
335
|
+
TableHead: {
|
|
336
|
+
exportName: 'TableElementProps',
|
|
337
|
+
exportPath: '.',
|
|
338
|
+
},
|
|
339
|
+
TableHeader: {
|
|
340
|
+
exportName: 'TableHeaderProps',
|
|
341
|
+
exportPath: '.',
|
|
342
|
+
},
|
|
343
|
+
TableRow: {
|
|
344
|
+
exportName: 'TableElementProps',
|
|
345
|
+
exportPath: '.',
|
|
346
|
+
},
|
|
347
|
+
Tabs: {
|
|
348
|
+
exportName: 'TabsProps',
|
|
349
|
+
exportPath: '.',
|
|
350
|
+
},
|
|
351
|
+
Tag: {
|
|
352
|
+
exportName: 'TagProps',
|
|
353
|
+
exportPath: '.',
|
|
354
|
+
},
|
|
355
|
+
Text: {
|
|
356
|
+
exportName: 'TextProps',
|
|
357
|
+
exportPath: '.',
|
|
358
|
+
},
|
|
359
|
+
TextArea: {
|
|
360
|
+
exportName: 'TextAreaProps',
|
|
361
|
+
exportPath: '.',
|
|
362
|
+
},
|
|
363
|
+
Tile: {
|
|
364
|
+
exportName: 'TileProps',
|
|
365
|
+
exportPath: '.',
|
|
366
|
+
},
|
|
367
|
+
TimeInput: {
|
|
368
|
+
exportName: 'TimeInputProps',
|
|
369
|
+
exportPath: '.',
|
|
370
|
+
},
|
|
371
|
+
Toggle: {
|
|
372
|
+
exportName: 'ToggleProps',
|
|
373
|
+
exportPath: '.',
|
|
374
|
+
},
|
|
375
|
+
ToggleGroup: {
|
|
376
|
+
exportName: 'ToggleGroupProps',
|
|
377
|
+
exportPath: '.',
|
|
378
|
+
},
|
|
379
|
+
Tooltip: {
|
|
380
|
+
exportName: 'TooltipProps',
|
|
381
|
+
exportPath: '.',
|
|
382
|
+
},
|
|
11
383
|
};
|
|
12
384
|
/**
|
|
13
385
|
* Gets the type source for a component.
|
|
@@ -4,12 +4,12 @@ import { AnalyzeResultReader, ApiNode } from '@hubspot/ts-export-types-reader';
|
|
|
4
4
|
*
|
|
5
5
|
* This context maintains state needed for rendering types correctly:
|
|
6
6
|
* - typesReader: The reader for looking up referenced types
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
7
|
+
* - typePath: An array tracking the current path of type nodes being rendered,
|
|
8
|
+
* used to detect actual circular references (not just repeated types)
|
|
9
9
|
*/
|
|
10
10
|
export interface RenderTypeContext {
|
|
11
11
|
typesReader: AnalyzeResultReader;
|
|
12
|
-
|
|
12
|
+
typePath: ApiNode[];
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* Renders a prop's type as an HTML string.
|
|
@@ -28,4 +28,4 @@ export interface RenderTypeContext {
|
|
|
28
28
|
* renderPropTypeToHtml(context, unionNode) // Returns: "<code>boolean</code> | <code>number</code> | <code>string</code>"
|
|
29
29
|
* ```
|
|
30
30
|
*/
|
|
31
|
-
export declare const
|
|
31
|
+
export declare const renderPropTypeToJsx: (context: RenderTypeContext, propType: ApiNode) => string;
|
|
@@ -1,10 +1,35 @@
|
|
|
1
|
-
import { isBuiltInTypeReferenceNode, isExternalTypeReferenceNode, isFunctionNode,
|
|
2
|
-
import { wrapCodeInHtmlCodeTags } from "./utils/
|
|
1
|
+
import { isArrayNode, isBuiltInTypeReferenceNode, isExternalTypeReferenceNode, isFunctionNode, isIntersectionNode, isLiteralNode, isObjectNode, isPrimitiveNode, isTupleNode, isTypeReferenceNode, isUnionNode, } from '@hubspot/ts-export-types-reader';
|
|
2
|
+
import { wrapCodeInHtmlCodeTags } from "./utils/jsx-utils.js";
|
|
3
|
+
/**
|
|
4
|
+
* Renders an index signature node as a string representation.
|
|
5
|
+
*
|
|
6
|
+
* Converts an IndexSignatureNode into a TypeScript-like index signature string, e.g.:
|
|
7
|
+
* `[key: string]: any` or `readonly [key: number]: string`
|
|
8
|
+
*
|
|
9
|
+
* @param context - The rendering context containing the types reader
|
|
10
|
+
* @param indexSignature - The index signature node to render
|
|
11
|
+
* @returns A string representation of the index signature
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* renderIndexSignature(context, indexSignatureNode)
|
|
16
|
+
* // Returns: "[key: string]: any"
|
|
17
|
+
* // Returns: "readonly [key: number]: string"
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
const renderIndexSignature = (context, indexSignature) => {
|
|
21
|
+
const readonly = indexSignature.isReadonly ? 'readonly ' : '';
|
|
22
|
+
const keyType = renderType(context, indexSignature.keyType);
|
|
23
|
+
const valueType = renderType(context, indexSignature.valueType);
|
|
24
|
+
return `${readonly}[key: ${keyType}]: ${valueType}`;
|
|
25
|
+
};
|
|
3
26
|
/**
|
|
4
27
|
* Renders an object type node as a string representation.
|
|
5
28
|
*
|
|
6
29
|
* Converts an ObjectNode into a TypeScript-like object type string, e.g.:
|
|
7
|
-
* `{ name: string, age: number }`
|
|
30
|
+
* `{ name: string, age: number }` or `{ [key: string]: any, name: string }`
|
|
31
|
+
*
|
|
32
|
+
* If the object has index signatures, they are rendered before regular properties.
|
|
8
33
|
*
|
|
9
34
|
* @param context - The rendering context containing the types reader
|
|
10
35
|
* @param objectTypeNode - The object type node to render
|
|
@@ -14,19 +39,97 @@ import { wrapCodeInHtmlCodeTags } from "./utils/html-utils.js";
|
|
|
14
39
|
* ```typescript
|
|
15
40
|
* renderObjectType(context, objectNode)
|
|
16
41
|
* // Returns: "{ name: string, age: number }"
|
|
42
|
+
* // Returns: "{ [key: string]: any }"
|
|
43
|
+
* // Returns: "{ readonly [key: number]: string, [name: string]: string, regularProperty: hello }"
|
|
17
44
|
* ```
|
|
18
45
|
*/
|
|
19
46
|
const renderObjectType = (context, objectTypeNode) => {
|
|
20
|
-
const { properties } = objectTypeNode;
|
|
47
|
+
const { properties, indexSignatures } = objectTypeNode;
|
|
48
|
+
const hasIndexSignatures = indexSignatures && indexSignatures.length > 0;
|
|
49
|
+
const hasProperties = properties.length > 0;
|
|
21
50
|
// Empty object types render as just {}
|
|
22
|
-
if (
|
|
51
|
+
if (!hasIndexSignatures && !hasProperties) {
|
|
23
52
|
return `{}`;
|
|
24
53
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
54
|
+
const parts = [];
|
|
55
|
+
// Render index signatures first
|
|
56
|
+
if (hasIndexSignatures) {
|
|
57
|
+
const indexParts = indexSignatures.map((indexSig) => renderIndexSignature(context, indexSig));
|
|
58
|
+
parts.push(...indexParts);
|
|
59
|
+
}
|
|
60
|
+
// Then render regular properties
|
|
61
|
+
if (hasProperties) {
|
|
62
|
+
const propertyParts = properties.map((property) => {
|
|
63
|
+
return `${property.name}: ${renderType(context, property.type)}`;
|
|
64
|
+
});
|
|
65
|
+
parts.push(...propertyParts);
|
|
66
|
+
}
|
|
67
|
+
return `{ ${parts.join(', ')} }`;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Renders an array type node as a string representation.
|
|
71
|
+
*
|
|
72
|
+
* Converts an ArrayNode into a TypeScript array type string, e.g.:
|
|
73
|
+
* `string[]` or `Array<string>`
|
|
74
|
+
*
|
|
75
|
+
* @param context - The rendering context containing the types reader
|
|
76
|
+
* @param arrayNode - The array type node to render
|
|
77
|
+
* @returns A string representation of the array type
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* renderArrayType(context, arrayNode)
|
|
82
|
+
* // Returns: "string[]" for simple types
|
|
83
|
+
* // Returns: "Array<"a" | "b">" for union types
|
|
84
|
+
* // Returns: "Array<A & B>" for intersection types
|
|
85
|
+
* // Returns: "Array<[string, number]>" for tuple types
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
const renderArrayType = (context, arrayNode) => {
|
|
89
|
+
const elementType = arrayNode.elementType;
|
|
90
|
+
const targetElementType = getTargetTypeNode(context, elementType);
|
|
91
|
+
// Use Array<T> syntax for union/intersection/tuple types to avoid ambiguity with operator precedence
|
|
92
|
+
// e.g., Array<"red" | "green" | "blue"> instead of ("red" | "green" | "blue")[]
|
|
93
|
+
// e.g., Array<A & B> instead of A & B[]
|
|
94
|
+
// e.g., Array<[string, number]> instead of [string, number][]
|
|
95
|
+
if (isUnionNode(targetElementType) ||
|
|
96
|
+
isIntersectionNode(targetElementType) ||
|
|
97
|
+
isTupleNode(targetElementType)) {
|
|
98
|
+
return `Array<${renderType(context, elementType)}>`;
|
|
99
|
+
}
|
|
100
|
+
// Use T[] syntax for simple types
|
|
101
|
+
return `${renderType(context, elementType)}[]`;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Renders a tuple type node as a string representation.
|
|
105
|
+
*
|
|
106
|
+
* Converts a TupleNode into a TypeScript tuple type string, e.g.:
|
|
107
|
+
* `[string, number]` or `[string, number, ...boolean[]]`
|
|
108
|
+
*
|
|
109
|
+
* @param context - The rendering context containing the types reader
|
|
110
|
+
* @param tupleNode - The tuple type node to render
|
|
111
|
+
* @returns A string representation of the tuple type
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* renderTupleType(context, tupleNode)
|
|
116
|
+
* // Returns: "[string, number]"
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
const renderTupleType = (context, tupleNode) => {
|
|
120
|
+
const elementParts = tupleNode.elements.map((element) => {
|
|
121
|
+
const renderedType = renderType(context, element.type);
|
|
122
|
+
// Handle rest elements (e.g., ...string[])
|
|
123
|
+
if (element.isRest) {
|
|
124
|
+
return `...${renderedType}`;
|
|
125
|
+
}
|
|
126
|
+
// Handle optional elements (e.g., string?)
|
|
127
|
+
if (element.isOptional) {
|
|
128
|
+
return `${renderedType}?`;
|
|
129
|
+
}
|
|
130
|
+
return renderedType;
|
|
28
131
|
});
|
|
29
|
-
return `
|
|
132
|
+
return `[${elementParts.join(', ')}]`;
|
|
30
133
|
};
|
|
31
134
|
/**
|
|
32
135
|
* Renders a function type node as a string representation.
|
|
@@ -67,10 +170,12 @@ const renderFunction = (context, functionNode) => {
|
|
|
67
170
|
* - Type references (aliases and interfaces)
|
|
68
171
|
* - Union types
|
|
69
172
|
*
|
|
70
|
-
* The function uses the context to track
|
|
71
|
-
*
|
|
173
|
+
* The function uses the context to track the current path of type nodes being rendered,
|
|
174
|
+
* which allows it to detect actual circular references (where a type references itself
|
|
175
|
+
* in its own definition) while still expanding types that appear multiple times in
|
|
176
|
+
* different parts of the type tree.
|
|
72
177
|
*
|
|
73
|
-
* @param context - The rendering context containing the types reader and
|
|
178
|
+
* @param context - The rendering context containing the types reader and current type path
|
|
74
179
|
* @param typeNode - The API node representing the type to render
|
|
75
180
|
* @returns A string representation of the type (e.g., "string", "Array<number>", "string | number")
|
|
76
181
|
*/
|
|
@@ -88,6 +193,14 @@ const renderType = (context, typeNode) => {
|
|
|
88
193
|
if (isExternalTypeReferenceNode(typeNode)) {
|
|
89
194
|
return typeNode.typeString;
|
|
90
195
|
}
|
|
196
|
+
// Handle array types
|
|
197
|
+
if (isArrayNode(typeNode)) {
|
|
198
|
+
return renderArrayType(context, typeNode);
|
|
199
|
+
}
|
|
200
|
+
// Handle tuple types
|
|
201
|
+
if (isTupleNode(typeNode)) {
|
|
202
|
+
return renderTupleType(context, typeNode);
|
|
203
|
+
}
|
|
91
204
|
// Handle function types
|
|
92
205
|
if (isFunctionNode(typeNode)) {
|
|
93
206
|
return renderFunction(context, typeNode);
|
|
@@ -96,10 +209,6 @@ const renderType = (context, typeNode) => {
|
|
|
96
209
|
if (isObjectNode(typeNode)) {
|
|
97
210
|
return renderObjectType(context, typeNode);
|
|
98
211
|
}
|
|
99
|
-
// Handle inlined type references - recursively render the inner type
|
|
100
|
-
if (isInlinedTypeReferenceNode(typeNode)) {
|
|
101
|
-
return renderType(context, typeNode.type);
|
|
102
|
-
}
|
|
103
212
|
// Handle built-in generic types (Array<T>, Promise<T>, etc.)
|
|
104
213
|
if (isBuiltInTypeReferenceNode(typeNode)) {
|
|
105
214
|
const { name, typeArguments } = typeNode;
|
|
@@ -113,24 +222,29 @@ const renderType = (context, typeNode) => {
|
|
|
113
222
|
}
|
|
114
223
|
// Handle type references (aliases, interfaces, etc.)
|
|
115
224
|
if (isTypeReferenceNode(typeNode)) {
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
if (
|
|
225
|
+
// Look up the referenced type definition
|
|
226
|
+
const referencedNode = context.typesReader.findReferencedTypeById(typeNode.typeId);
|
|
227
|
+
// Check if this type node is already in the current path (actual recursion)
|
|
228
|
+
// If yes, return the type string instead of expanding to prevent infinite loop
|
|
229
|
+
if (context.typePath.includes(referencedNode)) {
|
|
119
230
|
return typeNode.typeString;
|
|
120
231
|
}
|
|
121
|
-
//
|
|
122
|
-
context.
|
|
123
|
-
//
|
|
124
|
-
const
|
|
125
|
-
|
|
232
|
+
// Add to path before descending
|
|
233
|
+
context.typePath.push(referencedNode);
|
|
234
|
+
// Render the referenced type (may recurse through many paths)
|
|
235
|
+
const result = renderType(context, referencedNode);
|
|
236
|
+
// Remove from path after returning (ensures we pop even if renderType took complex paths)
|
|
237
|
+
context.typePath.pop();
|
|
238
|
+
return result;
|
|
126
239
|
}
|
|
127
|
-
// Handle union types (e.g., string | number | boolean)
|
|
128
|
-
if (isUnionNode(typeNode)) {
|
|
129
|
-
// Render each type in the union
|
|
130
|
-
const
|
|
131
|
-
// Sort
|
|
132
|
-
|
|
133
|
-
|
|
240
|
+
// Handle union and intersection types (e.g., (string | number | boolean) and (A & B & C))
|
|
241
|
+
if (isUnionNode(typeNode) || isIntersectionNode(typeNode)) {
|
|
242
|
+
// Render each type in the union or intersection
|
|
243
|
+
const renderedParts = typeNode.types.map((type) => renderType(context, type));
|
|
244
|
+
// Sort parts alphabetically for consistent output
|
|
245
|
+
renderedParts.sort((a, b) => a.localeCompare(b));
|
|
246
|
+
const separator = isUnionNode(typeNode) ? '|' : '&';
|
|
247
|
+
return renderedParts.join(` ${separator} `);
|
|
134
248
|
}
|
|
135
249
|
throw new Error(`Unsupported type node: ${typeNode.kind}`);
|
|
136
250
|
};
|
|
@@ -165,11 +279,6 @@ const hasTypeArgs = (typeNode) => isNonEmptyArray(typeNode.typeArguments);
|
|
|
165
279
|
* @returns The resolved target type node
|
|
166
280
|
*/
|
|
167
281
|
const getTargetTypeNode = (context, typeNode) => {
|
|
168
|
-
// For inlined type references, preserve the node if it has type args (generics)
|
|
169
|
-
// Otherwise, resolve to the inner type
|
|
170
|
-
if (isInlinedTypeReferenceNode(typeNode)) {
|
|
171
|
-
return hasTypeArgs(typeNode) ? typeNode : typeNode.type;
|
|
172
|
-
}
|
|
173
282
|
// For type references, preserve the node if it has type args (generics)
|
|
174
283
|
// Otherwise, look up and return the referenced type definition
|
|
175
284
|
if (isTypeReferenceNode(typeNode)) {
|
|
@@ -180,6 +289,20 @@ const getTargetTypeNode = (context, typeNode) => {
|
|
|
180
289
|
// For other node types, return as-is
|
|
181
290
|
return typeNode;
|
|
182
291
|
};
|
|
292
|
+
const renderPropTypeToJsxHelper = (context, propType) => {
|
|
293
|
+
// Resolve references to other types to the actual type node
|
|
294
|
+
// This handles type aliases and ensures generics are preserved
|
|
295
|
+
const targetPropType = getTargetTypeNode(context, propType);
|
|
296
|
+
// Special handling for union types: render each member recursively and sort
|
|
297
|
+
// This ensures nested unions are properly formatted
|
|
298
|
+
if (isUnionNode(targetPropType)) {
|
|
299
|
+
const renderedUnionTypes = targetPropType.types.map((currentType) => renderPropTypeToJsxHelper(context, currentType));
|
|
300
|
+
// Sort union parts alphabetically for consistent output
|
|
301
|
+
renderedUnionTypes.sort((a, b) => a.localeCompare(b));
|
|
302
|
+
return renderedUnionTypes.join(' | ');
|
|
303
|
+
}
|
|
304
|
+
return wrapCodeInHtmlCodeTags(renderType(context, targetPropType));
|
|
305
|
+
};
|
|
183
306
|
/**
|
|
184
307
|
* Renders a prop's type as an HTML string.
|
|
185
308
|
*
|
|
@@ -197,17 +320,6 @@ const getTargetTypeNode = (context, typeNode) => {
|
|
|
197
320
|
* renderPropTypeToHtml(context, unionNode) // Returns: "<code>boolean</code> | <code>number</code> | <code>string</code>"
|
|
198
321
|
* ```
|
|
199
322
|
*/
|
|
200
|
-
export const
|
|
201
|
-
|
|
202
|
-
// This handles type aliases and ensures generics are preserved
|
|
203
|
-
const targetPropType = getTargetTypeNode(context, propType);
|
|
204
|
-
// Special handling for union types: render each member recursively and sort
|
|
205
|
-
// This ensures nested unions are properly formatted
|
|
206
|
-
if (isUnionNode(targetPropType)) {
|
|
207
|
-
const renderedUnionTypes = targetPropType.types.map((currentType) => renderPropTypeToHtml(context, currentType));
|
|
208
|
-
// Sort union parts alphabetically for consistent output
|
|
209
|
-
renderedUnionTypes.sort((a, b) => a.localeCompare(b));
|
|
210
|
-
return renderedUnionTypes.join(' | ');
|
|
211
|
-
}
|
|
212
|
-
return wrapCodeInHtmlCodeTags(renderType(context, targetPropType));
|
|
323
|
+
export const renderPropTypeToJsx = (context, propType) => {
|
|
324
|
+
return `<>${renderPropTypeToJsxHelper(context, propType)}</>`;
|
|
213
325
|
};
|