@vuer-ai/vuer-uikit 0.0.99 → 0.0.100

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.
Files changed (194) hide show
  1. package/dist/SyncScroll/SyncScroll.cjs +3 -3
  2. package/dist/SyncScroll/SyncScroll.mjs +3 -3
  3. package/dist/SyncScroll/index.cjs +3 -3
  4. package/dist/SyncScroll/index.mjs +3 -3
  5. package/dist/{chunk-WIGYDOHM.cjs → chunk-XBTBTLID.cjs} +2 -2
  6. package/dist/{chunk-XMFU7SDD.mjs → chunk-XGXWOY3U.mjs} +2 -2
  7. package/dist/dial/DialPanel.cjs +6 -6
  8. package/dist/dial/DialPanel.mjs +6 -6
  9. package/dist/dial/index.cjs +6 -6
  10. package/dist/dial/index.mjs +6 -6
  11. package/dist/dial/wrapped-inputs/ControlledInputs.cjs +6 -6
  12. package/dist/dial/wrapped-inputs/ControlledInputs.mjs +6 -6
  13. package/dist/dial/wrapped-inputs/DialInputs.cjs +6 -6
  14. package/dist/dial/wrapped-inputs/DialInputs.mjs +6 -6
  15. package/dist/dial/wrapped-inputs/DialVectorInput.cjs +6 -6
  16. package/dist/dial/wrapped-inputs/DialVectorInput.mjs +6 -6
  17. package/dist/dial/wrapped-inputs/index.cjs +6 -6
  18. package/dist/dial/wrapped-inputs/index.mjs +6 -6
  19. package/dist/highlight-cursor/enhanced-components.cjs +4 -4
  20. package/dist/highlight-cursor/enhanced-components.mjs +4 -4
  21. package/dist/highlight-cursor/index.cjs +8 -8
  22. package/dist/highlight-cursor/index.mjs +4 -4
  23. package/dist/hooks/index.cjs +12 -12
  24. package/dist/hooks/index.mjs +3 -3
  25. package/dist/hooks/useQueryParams.cjs +3 -3
  26. package/dist/hooks/useQueryParams.mjs +2 -2
  27. package/dist/index.cjs +47 -47
  28. package/dist/index.css +7 -1
  29. package/dist/index.mjs +6 -6
  30. package/dist/ui/DialBadge.cjs +3 -3
  31. package/dist/ui/DialBadge.mjs +3 -3
  32. package/dist/ui/UIKitBadge.cjs +8 -8
  33. package/dist/ui/UIKitBadge.mjs +4 -4
  34. package/dist/ui/avatar.cjs +3 -3
  35. package/dist/ui/avatar.mjs +3 -3
  36. package/dist/ui/badge.cjs +3 -3
  37. package/dist/ui/badge.mjs +3 -3
  38. package/dist/ui/button.cjs +3 -3
  39. package/dist/ui/button.mjs +3 -3
  40. package/dist/ui/card.cjs +3 -3
  41. package/dist/ui/card.mjs +3 -3
  42. package/dist/ui/checkbox.cjs +3 -3
  43. package/dist/ui/checkbox.mjs +3 -3
  44. package/dist/ui/collapsible.cjs +3 -3
  45. package/dist/ui/collapsible.mjs +3 -3
  46. package/dist/ui/drawer.cjs +3 -3
  47. package/dist/ui/drawer.mjs +3 -3
  48. package/dist/ui/dropdown.cjs +3 -3
  49. package/dist/ui/dropdown.mjs +3 -3
  50. package/dist/ui/index.cjs +33 -33
  51. package/dist/ui/index.mjs +5 -5
  52. package/dist/ui/inputs/color-input.cjs +3 -3
  53. package/dist/ui/inputs/color-input.mjs +3 -3
  54. package/dist/ui/inputs/index.cjs +3 -3
  55. package/dist/ui/inputs/index.mjs +3 -3
  56. package/dist/ui/inputs/input-numbers.cjs +3 -3
  57. package/dist/ui/inputs/input-numbers.mjs +3 -3
  58. package/dist/ui/inputs/input.cjs +3 -3
  59. package/dist/ui/inputs/input.mjs +3 -3
  60. package/dist/ui/inputs/number-inputs/CmInput.cjs +3 -3
  61. package/dist/ui/inputs/number-inputs/CmInput.mjs +3 -3
  62. package/dist/ui/inputs/number-inputs/DegInput.cjs +3 -3
  63. package/dist/ui/inputs/number-inputs/DegInput.mjs +3 -3
  64. package/dist/ui/inputs/number-inputs/EulerDegInput.cjs +3 -3
  65. package/dist/ui/inputs/number-inputs/EulerDegInput.mjs +3 -3
  66. package/dist/ui/inputs/number-inputs/EulerInput.cjs +3 -3
  67. package/dist/ui/inputs/number-inputs/EulerInput.mjs +3 -3
  68. package/dist/ui/inputs/number-inputs/EulerRadInput.cjs +3 -3
  69. package/dist/ui/inputs/number-inputs/EulerRadInput.mjs +3 -3
  70. package/dist/ui/inputs/number-inputs/InchInput.cjs +3 -3
  71. package/dist/ui/inputs/number-inputs/InchInput.mjs +3 -3
  72. package/dist/ui/inputs/number-inputs/IntInput.cjs +3 -3
  73. package/dist/ui/inputs/number-inputs/IntInput.mjs +3 -3
  74. package/dist/ui/inputs/number-inputs/KVectorInput.cjs +3 -3
  75. package/dist/ui/inputs/number-inputs/KVectorInput.mjs +3 -3
  76. package/dist/ui/inputs/number-inputs/QuaternionInput.cjs +3 -3
  77. package/dist/ui/inputs/number-inputs/QuaternionInput.mjs +3 -3
  78. package/dist/ui/inputs/number-inputs/RadInput.cjs +3 -3
  79. package/dist/ui/inputs/number-inputs/RadInput.mjs +3 -3
  80. package/dist/ui/inputs/number-inputs/TimeInput.cjs +3 -3
  81. package/dist/ui/inputs/number-inputs/TimeInput.mjs +3 -3
  82. package/dist/ui/inputs/number-inputs/Vec3Input.cjs +3 -3
  83. package/dist/ui/inputs/number-inputs/Vec3Input.mjs +3 -3
  84. package/dist/ui/inputs/number-inputs/VectorInput.cjs +3 -3
  85. package/dist/ui/inputs/number-inputs/VectorInput.mjs +3 -3
  86. package/dist/ui/inputs/number-inputs/index.cjs +3 -3
  87. package/dist/ui/inputs/number-inputs/index.mjs +3 -3
  88. package/dist/ui/inputs/presets-input.cjs +3 -3
  89. package/dist/ui/inputs/presets-input.mjs +3 -3
  90. package/dist/ui/label.cjs +3 -3
  91. package/dist/ui/label.mjs +3 -3
  92. package/dist/ui/layout.cjs +3 -3
  93. package/dist/ui/layout.mjs +3 -3
  94. package/dist/ui/layouts/dock-layout/DockLayoutView.cjs +3 -3
  95. package/dist/ui/layouts/dock-layout/DockLayoutView.mjs +3 -3
  96. package/dist/ui/layouts/dock-layout/LayoutSlots.cjs +3 -3
  97. package/dist/ui/layouts/dock-layout/LayoutSlots.mjs +3 -3
  98. package/dist/ui/layouts/dock-layout/index.cjs +3 -3
  99. package/dist/ui/layouts/dock-layout/index.mjs +3 -3
  100. package/dist/ui/layouts/index.cjs +3 -3
  101. package/dist/ui/layouts/index.mjs +3 -3
  102. package/dist/ui/layouts/liquid-layout/LayoutSlots.cjs +3 -3
  103. package/dist/ui/layouts/liquid-layout/LayoutSlots.mjs +3 -3
  104. package/dist/ui/layouts/liquid-layout/LiquidLayoutView.cjs +3 -3
  105. package/dist/ui/layouts/liquid-layout/LiquidLayoutView.mjs +3 -3
  106. package/dist/ui/layouts/liquid-layout/index.cjs +3 -3
  107. package/dist/ui/layouts/liquid-layout/index.mjs +3 -3
  108. package/dist/ui/modal.cjs +3 -3
  109. package/dist/ui/modal.mjs +3 -3
  110. package/dist/ui/navigation.cjs +3 -3
  111. package/dist/ui/navigation.mjs +3 -3
  112. package/dist/ui/pagination.cjs +3 -3
  113. package/dist/ui/pagination.mjs +3 -3
  114. package/dist/ui/panel.cjs +3 -3
  115. package/dist/ui/panel.mjs +3 -3
  116. package/dist/ui/popover.cjs +3 -3
  117. package/dist/ui/popover.mjs +3 -3
  118. package/dist/ui/radio-group.cjs +3 -3
  119. package/dist/ui/radio-group.mjs +3 -3
  120. package/dist/ui/resizable.cjs +3 -3
  121. package/dist/ui/resizable.mjs +3 -3
  122. package/dist/ui/select.cjs +3 -3
  123. package/dist/ui/select.mjs +3 -3
  124. package/dist/ui/separator.cjs +3 -3
  125. package/dist/ui/separator.mjs +3 -3
  126. package/dist/ui/sheet.cjs +3 -3
  127. package/dist/ui/sheet.mjs +3 -3
  128. package/dist/ui/sidebar.cjs +28 -28
  129. package/dist/ui/sidebar.mjs +4 -4
  130. package/dist/ui/simple-tree-view.cjs +3 -3
  131. package/dist/ui/simple-tree-view.mjs +3 -3
  132. package/dist/ui/skeleton.cjs +3 -3
  133. package/dist/ui/skeleton.mjs +3 -3
  134. package/dist/ui/slider.cjs +3 -3
  135. package/dist/ui/slider.mjs +3 -3
  136. package/dist/ui/switch.cjs +3 -3
  137. package/dist/ui/switch.mjs +3 -3
  138. package/dist/ui/table.cjs +3 -3
  139. package/dist/ui/table.mjs +3 -3
  140. package/dist/ui/tabs.cjs +3 -3
  141. package/dist/ui/tabs.mjs +3 -3
  142. package/dist/ui/textarea.cjs +3 -3
  143. package/dist/ui/textarea.mjs +3 -3
  144. package/dist/ui/theme/ThemeToggles.cjs +3 -3
  145. package/dist/ui/theme/ThemeToggles.mjs +3 -3
  146. package/dist/ui/theme/index.cjs +3 -3
  147. package/dist/ui/theme/index.mjs +3 -3
  148. package/dist/ui/toggle-buttons.cjs +3 -3
  149. package/dist/ui/toggle-buttons.mjs +3 -3
  150. package/dist/ui/toggle-group.cjs +3 -3
  151. package/dist/ui/toggle-group.mjs +3 -3
  152. package/dist/ui/toggle.cjs +3 -3
  153. package/dist/ui/toggle.mjs +3 -3
  154. package/dist/ui/toolbar.cjs +3 -3
  155. package/dist/ui/toolbar.mjs +3 -3
  156. package/dist/ui/tooltip.cjs +3 -3
  157. package/dist/ui/tooltip.mjs +3 -3
  158. package/dist/ui/tree-view/TreeSearchBar.cjs +3 -3
  159. package/dist/ui/tree-view/TreeSearchBar.mjs +3 -3
  160. package/dist/ui/tree-view/TreeView.cjs +3 -3
  161. package/dist/ui/tree-view/TreeView.mjs +3 -3
  162. package/dist/ui/tree-view/index.cjs +3 -3
  163. package/dist/ui/tree-view/index.mjs +3 -3
  164. package/dist/ui/tree-view-legacy.cjs +3 -3
  165. package/dist/ui/tree-view-legacy.mjs +3 -3
  166. package/dist/ui/waterfall/CursorOverlay.cjs +3 -3
  167. package/dist/ui/waterfall/CursorOverlay.mjs +3 -3
  168. package/dist/ui/waterfall/TimelineEvent.cjs +3 -3
  169. package/dist/ui/waterfall/TimelineEvent.mjs +3 -3
  170. package/dist/ui/waterfall/TimelineProcessBar.cjs +3 -3
  171. package/dist/ui/waterfall/TimelineProcessBar.mjs +3 -3
  172. package/dist/ui/waterfall/Wedges.cjs +3 -3
  173. package/dist/ui/waterfall/Wedges.mjs +3 -3
  174. package/dist/ui/waterfall/index.cjs +3 -3
  175. package/dist/ui/waterfall/index.mjs +3 -3
  176. package/package.json +1 -5
  177. package/dial-cli/README.md +0 -137
  178. package/dial-cli/dial-cli.ts +0 -1136
  179. package/dial-cli/dist/dial-cli.js +0 -838
  180. package/dial-cli/node_modules/.bin/api-extractor +0 -17
  181. package/dial-cli/node_modules/.bin/jiti +0 -17
  182. package/dial-cli/node_modules/.bin/tsc +0 -17
  183. package/dial-cli/node_modules/.bin/tsserver +0 -17
  184. package/dial-cli/node_modules/.bin/tsup +0 -17
  185. package/dial-cli/node_modules/.bin/tsup-node +0 -17
  186. package/dial-cli/node_modules/.bin/tsx +0 -17
  187. package/dial-cli/node_modules/.bin/yaml +0 -17
  188. package/dial-cli/package.json +0 -47
  189. package/dial-cli/tsconfig.json +0 -20
  190. package/dial-cli/tsup.config.ts +0 -18
  191. package/dist/{chunk-K4VD5PPY.mjs → chunk-BIUDC66P.mjs} +1 -1
  192. package/dist/{chunk-Q4XH2Z5M.cjs → chunk-LYZJNEOR.cjs} +1 -1
  193. package/dist/{chunk-U3LN5NB6.mjs → chunk-OEIF3JCH.mjs} +1 -1
  194. package/dist/{chunk-RKJR6RZU.cjs → chunk-OYNLQTHW.cjs} +1 -1
@@ -1,1136 +0,0 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
- import { basename, dirname, join, resolve } from "node:path";
3
- import { parseArgs } from "node:util";
4
- import { fileURLToPath } from "node:url";
5
- import { execSync } from "node:child_process";
6
- import * as docgen from "react-docgen-typescript";
7
- import * as ts from "typescript";
8
-
9
- // Get package version and git hash
10
- function getVersionInfo(): { version: string; gitHash?: string } {
11
- try {
12
- // Get the directory of this CLI file
13
- const __filename = fileURLToPath(import.meta.url);
14
- const __dirname = dirname(__filename);
15
-
16
- // Try multiple possible locations for package.json
17
- const possiblePaths = [
18
- resolve(__dirname, './package.json'), // Same directory (for standalone package)
19
- resolve(__dirname, '../package.json'), // Parent directory (built version)
20
- resolve(__dirname, '../../package.json'), // Two levels up (for development)
21
- ];
22
-
23
- let packageJson: any = null;
24
- for (const path of possiblePaths) {
25
- try {
26
- if (existsSync(path)) {
27
- const content = JSON.parse(readFileSync(path, 'utf-8'));
28
- // Check if this is the dial-cli package
29
- if (content.name === '@vuer-ai/dial-cli' || content.bin?.['dial-cli']) {
30
- packageJson = content;
31
- break;
32
- }
33
- }
34
- } catch {
35
- // Continue to next path
36
- }
37
- }
38
-
39
- const version = packageJson?.version || 'unknown';
40
-
41
- // Try to get git hash
42
- let gitHash: string | undefined;
43
- try {
44
- gitHash = execSync('git rev-parse --short HEAD', { encoding: 'utf-8', cwd: dirname(__dirname) }).trim();
45
- } catch {
46
- // Git not available or not a git repo
47
- gitHash = undefined;
48
- }
49
-
50
- return { version, gitHash };
51
- } catch (error) {
52
- // Fallback if we can't read package.json
53
- return { version: 'unknown' };
54
- }
55
- }
56
-
57
- interface DialTag {
58
- grouping?: string;
59
- min?: number;
60
- max?: number;
61
- step?: number;
62
- options?: unknown;
63
- icon?: string;
64
- placeholders?: string[];
65
- tooltips?: string[];
66
- dtypes?: string[];
67
- mins?: number[];
68
- maxs?: number[];
69
- steps?: number[];
70
- column?: boolean;
71
- rowCount?: number;
72
- colCount?: number;
73
- labelPosition?: string;
74
- dtype?: string;
75
- type?: string;
76
- default?: unknown;
77
- noWrap?: boolean;
78
- }
79
-
80
- interface ElementData {
81
- index: number;
82
- raw: string;
83
- name?: string;
84
- type?: string;
85
- comment?: string;
86
- min?: number;
87
- max?: number;
88
- step?: number;
89
- dtype?: string;
90
- dialTags?: DialTag;
91
- }
92
-
93
- interface TypeDefinition {
94
- name: string;
95
- kind: string;
96
- raw: string;
97
- dialTags?: DialTag;
98
- jsDoc?: string;
99
- type?: string;
100
- elements?: ElementData[];
101
- elementType?: string;
102
- typeNode?: string;
103
- }
104
-
105
- interface PropertySchema {
106
- name: string;
107
- dtype: string;
108
- min?: number;
109
- max?: number;
110
- step?: number;
111
- icon?: string;
112
- value?: unknown;
113
- options?: unknown;
114
- placeholders?: string[];
115
- tooltips?: string[];
116
- dtypes?: string[];
117
- mins?: number[];
118
- maxs?: number[];
119
- steps?: number[];
120
- tags?: Record<string, unknown>;
121
- typeDefinition?: TypeDefinition;
122
- }
123
-
124
- // Parse type alias definition from TypeScript source
125
- function parseTypeAlias(sourceFile: ts.SourceFile, typeName: string): TypeDefinition | null {
126
- let typeDefinition: TypeDefinition | null = null;
127
-
128
- function visit(node: ts.Node): void {
129
- if (ts.isTypeAliasDeclaration(node) && node.name.text === typeName) {
130
- typeDefinition = {
131
- name: typeName,
132
- kind: "typeAlias",
133
- raw: node.getFullText().trim(),
134
- };
135
-
136
- // Parse JSDoc comments for the type alias
137
- const fullText = node.getFullText();
138
- const jsDocMatch = fullText.match(/\/\*\*([\s\S]*?)\*\//);
139
- if (jsDocMatch) {
140
- const jsDocContent = jsDocMatch[1];
141
- typeDefinition.dialTags = parseDialTags(jsDocContent);
142
- typeDefinition.jsDoc = jsDocContent.trim();
143
- }
144
-
145
- if (ts.isTupleTypeNode(node.type)) {
146
- typeDefinition.type = "tuple";
147
- typeDefinition.elements = [];
148
-
149
- node.type.elements.forEach((element, index) => {
150
- const elementData: ElementData = {
151
- index,
152
- raw: element.getFullText().trim(),
153
- };
154
-
155
- if (ts.isNamedTupleMember(element)) {
156
- elementData.name = element.name?.getText();
157
- elementData.type = element.type?.getText();
158
-
159
- // Extract inline comment with @dial annotations
160
- const sourceText = element.getFullText();
161
- const commentMatch = sourceText.match(/\/\/(.+)/);
162
- if (commentMatch) {
163
- elementData.comment = commentMatch[1].trim();
164
-
165
- // Parse @dial annotations from the comment
166
- const dialTags: DialTag = {};
167
-
168
- // Parse @dial-min
169
- const minMatch = commentMatch[1].match(/@dial-min\s+([\d.]+)/);
170
- if (minMatch) {
171
- dialTags.min = parseFloat(minMatch[1]);
172
- elementData.min = dialTags.min;
173
- }
174
-
175
- // Parse @dial-max
176
- const maxMatch = commentMatch[1].match(/@dial-max\s+([\d.]+)/);
177
- if (maxMatch) {
178
- dialTags.max = parseFloat(maxMatch[1]);
179
- elementData.max = dialTags.max;
180
- }
181
-
182
- // Parse @dial-step
183
- const stepMatch = commentMatch[1].match(/@dial-step\s+([\d.]+)/);
184
- if (stepMatch) {
185
- dialTags.step = parseFloat(stepMatch[1]);
186
- elementData.step = dialTags.step;
187
- }
188
-
189
- // Parse @dial-dtype
190
- const dtypeMatch = commentMatch[1].match(/@dial-dtype\s+(\w+)/);
191
- if (dtypeMatch) {
192
- dialTags.dtype = dtypeMatch[1];
193
- elementData.dtype = dtypeMatch[1];
194
- } else {
195
- elementData.dtype = "number";
196
- }
197
-
198
- elementData.dialTags = dialTags;
199
- }
200
- }
201
-
202
- typeDefinition.elements!.push(elementData);
203
- });
204
- } else if (ts.isArrayTypeNode(node.type)) {
205
- typeDefinition!.type = "array";
206
- typeDefinition!.elementType = node.type.elementType?.getText();
207
- } else {
208
- typeDefinition.type = "other";
209
- typeDefinition.typeNode = node.type ? node.type.getText() : "unknown";
210
- }
211
- }
212
-
213
- ts.forEachChild(node, visit);
214
- }
215
-
216
- visit(sourceFile);
217
- return typeDefinition;
218
- }
219
-
220
- // Parse interface properties from TypeScript source
221
- function parseInterfaceProperties(
222
- sourceFile: ts.SourceFile,
223
- interfaceName: string,
224
- ): PropertySchema[] {
225
- const properties: PropertySchema[] = [];
226
- let interfaceDialTags: DialTag = {};
227
- const groupConfigs: Record<string, any> = {};
228
-
229
- function visit(node: ts.Node) {
230
- if (ts.isInterfaceDeclaration(node) && node.name.text === interfaceName) {
231
- // First, get JSDoc comments for the interface itself
232
- const interfaceJsDocNodes = ts.getJSDocCommentsAndTags(node);
233
- if (interfaceJsDocNodes && interfaceJsDocNodes.length > 0) {
234
- const interfaceFullText = interfaceJsDocNodes[0].getFullText();
235
- interfaceDialTags = parseDialTags(interfaceFullText);
236
-
237
- // Parse group-level configurations from interface JSDoc
238
- const lines = interfaceFullText.split('\n');
239
- lines.forEach(line => {
240
- // Match patterns like "@dial transform @dial-no-wrap"
241
- const groupMatch = line.match(/@dial\s+(\w+)(.*)/);
242
- if (groupMatch) {
243
- const groupName = groupMatch[1];
244
- const configStr = groupMatch[2];
245
- if (configStr.includes('@dial-no-wrap')) {
246
- groupConfigs[groupName] = { noWrap: true };
247
- }
248
- }
249
- });
250
- }
251
-
252
- node.members.forEach((member) => {
253
- if (ts.isPropertySignature(member) && member.name && ts.isIdentifier(member.name)) {
254
- const propName = member.name.text;
255
-
256
- // Get JSDoc comments for the property
257
- const jsDocNodes = ts.getJSDocCommentsAndTags(member);
258
- let propertyDialTags: DialTag = {};
259
-
260
- if (jsDocNodes && jsDocNodes.length > 0) {
261
- const fullText = jsDocNodes[0].getFullText();
262
- propertyDialTags = parseDialTags(fullText);
263
- }
264
-
265
- // Merge interface-level tags with property-level tags (property-level takes precedence)
266
- const mergedDialTags = { ...interfaceDialTags, ...propertyDialTags };
267
-
268
- // Build property schema
269
- const prop: PropertySchema = {
270
- name: propName,
271
- dtype: mergedDialTags.dtype || "number",
272
- };
273
-
274
- // Add numeric constraints
275
- if (mergedDialTags.min !== undefined) prop.min = mergedDialTags.min;
276
- if (mergedDialTags.max !== undefined) prop.max = mergedDialTags.max;
277
- if (mergedDialTags.step !== undefined) prop.step = mergedDialTags.step;
278
- if (mergedDialTags.icon) prop.icon = mergedDialTags.icon;
279
-
280
- // Add grouping and other tags
281
- if (mergedDialTags.grouping || mergedDialTags.column || mergedDialTags.rowCount ||
282
- mergedDialTags.colCount || mergedDialTags.labelPosition || mergedDialTags.noWrap) {
283
- prop.tags = {};
284
- if (mergedDialTags.grouping) {
285
- prop.tags.grouping = mergedDialTags.grouping;
286
- // Check if this group has noWrap configuration
287
- if (groupConfigs[mergedDialTags.grouping]?.noWrap) {
288
- prop.tags.noWrap = true;
289
- }
290
- }
291
- if (mergedDialTags.column) prop.tags.layout = "column";
292
- if (mergedDialTags.rowCount) prop.tags.row = mergedDialTags.rowCount;
293
- if (mergedDialTags.colCount) prop.tags.col = mergedDialTags.colCount;
294
- if (mergedDialTags.labelPosition) prop.tags.labelPosition = mergedDialTags.labelPosition;
295
- if (mergedDialTags.noWrap) prop.tags.noWrap = true;
296
- }
297
-
298
- properties.push(prop);
299
- }
300
- });
301
- }
302
-
303
- ts.forEachChild(node, visit);
304
- }
305
-
306
- visit(sourceFile);
307
- return properties;
308
- }
309
-
310
- // Parse @dial annotations from JSDoc comments
311
- function parseDialTags(description: string): DialTag & { ignore?: boolean } {
312
- const dialTags: DialTag & { ignore?: boolean } = {};
313
-
314
- if (!description) return dialTags;
315
-
316
- // Check for @dial-ignore first
317
- if (/@dial-ignore\b/i.test(description)) {
318
- dialTags.ignore = true;
319
- return dialTags; // Return early if ignore is set
320
- }
321
-
322
- // Extract @dial grouping tags (without hyphen)
323
- const groupingPattern = /@dial\s+(transform|visibility|geometry|segments)\b/gm;
324
- let match;
325
-
326
- while ((match = groupingPattern.exec(description)) !== null) {
327
- dialTags.grouping = match[1];
328
- }
329
-
330
- // Extract @dial-* property tags (with hyphen)
331
- const propertyPattern = /@dial-([\w-]+)(?:\s+([^\n@]+?))?(?:\n|@|$)/gm;
332
-
333
- while ((match = propertyPattern.exec(description)) !== null) {
334
- const [, key, value] = match;
335
-
336
- switch (key) {
337
- case "options":
338
- // Parse array-like values
339
- if (value) {
340
- try {
341
- dialTags.options = JSON.parse(value);
342
- } catch {
343
- dialTags.options = value;
344
- }
345
- }
346
- break;
347
-
348
- case "min":
349
- case "max":
350
- case "step":
351
- // Parse numeric values
352
- if (value) {
353
- dialTags[key] = parseFloat(value);
354
- }
355
- break;
356
-
357
- case "col":
358
- case "column":
359
- // Boolean flag for column layout
360
- dialTags.column = true;
361
- break;
362
-
363
- case "row":
364
- // Parse row layout
365
- if (value && /^\d+$/.test(value)) {
366
- dialTags.rowCount = parseInt(value, 10);
367
- }
368
- break;
369
-
370
- case "col-3":
371
- case "col-2":
372
- case "col-4": {
373
- // Parse column layout with number
374
- const colMatch = key.match(/col-(\d+)/);
375
- if (colMatch) {
376
- dialTags.colCount = parseInt(colMatch[1], 10);
377
- }
378
- break;
379
- }
380
-
381
- case "row-3":
382
- case "row-2":
383
- case "row-4": {
384
- // Parse row layout with number
385
- const rowMatch = key.match(/row-(\d+)/);
386
- if (rowMatch) {
387
- dialTags.rowCount = parseInt(rowMatch[1], 10);
388
- }
389
- break;
390
- }
391
-
392
- case "dtype":
393
- // Data type
394
- if (value) {
395
- dialTags.dtype = value.trim();
396
- }
397
- break;
398
-
399
- case "dtypes":
400
- // Comma-separated data types for vectors
401
- if (value) {
402
- dialTags.dtypes = value.split(",").map((s) => s.trim());
403
- }
404
- break;
405
-
406
- case "type":
407
- // Type reference
408
- if (value) {
409
- dialTags.type = value.trim();
410
- }
411
- break;
412
-
413
- case "icon":
414
- // Lucide icon name
415
- if (value) {
416
- dialTags.icon = value.trim();
417
- }
418
- break;
419
-
420
- case "default":
421
- // Default value for the property
422
- if (value) {
423
- try {
424
- // Try to parse as JSON first (for arrays, objects, booleans, numbers)
425
- dialTags.default = JSON.parse(value);
426
- } catch {
427
- // If not valid JSON, use as string
428
- dialTags.default = value.trim();
429
- }
430
- }
431
- break;
432
-
433
- case "placeholders":
434
- // Comma-separated placeholders for vector types
435
- if (value) {
436
- dialTags.placeholders = value.split(",").map((s) => s.trim());
437
- }
438
- break;
439
-
440
- case "tooltips":
441
- // Comma-separated tooltips for vector types
442
- if (value) {
443
- dialTags.tooltips = value.split(",").map((s) => s.trim());
444
- }
445
- break;
446
-
447
- case "mins":
448
- // Comma-separated min values
449
- if (value) {
450
- dialTags.mins = value.split(",").map((s) => parseFloat(s.trim()));
451
- }
452
- break;
453
-
454
- case "maxs":
455
- // Comma-separated max values
456
- if (value) {
457
- dialTags.maxs = value.split(",").map((s) => parseFloat(s.trim()));
458
- }
459
- break;
460
-
461
- case "steps":
462
- // Comma-separated step values
463
- if (value) {
464
- dialTags.steps = value.split(",").map((s) => parseFloat(s.trim()));
465
- }
466
- break;
467
-
468
- case "label-left":
469
- case "left":
470
- // Label position left
471
- dialTags.labelPosition = "left";
472
- break;
473
-
474
- case "label-right":
475
- case "right":
476
- // Label position right
477
- dialTags.labelPosition = "right";
478
- break;
479
-
480
- case "label-center":
481
- case "label-middle":
482
- case "center":
483
- case "middle":
484
- // Label position center
485
- dialTags.labelPosition = "center";
486
- break;
487
-
488
- case "label-top":
489
- case "top":
490
- // Label position top
491
- dialTags.labelPosition = "top";
492
- break;
493
-
494
- case "label-bottom":
495
- case "bottom":
496
- // Label position bottom
497
- dialTags.labelPosition = "bottom";
498
- break;
499
-
500
- case "label-inline":
501
- case "inline":
502
- // Label position inline
503
- dialTags.labelPosition = "inline";
504
- break;
505
-
506
- case "no-wrap":
507
- // No wrap flag for preventing line wrapping
508
- dialTags.noWrap = true;
509
- break;
510
-
511
- default:
512
- // Other key-value pairs could be handled here
513
- break;
514
- }
515
- }
516
-
517
- return dialTags;
518
- }
519
-
520
- // Convert prop data to dial schema format
521
- function propToDialSchema(propName: string, propData: Record<string, unknown>, groupConfigs?: Record<string, any>): PropertySchema | null {
522
- const description = (propData.description as string) || "";
523
- const dialTags = parseDialTags(description);
524
-
525
- // Skip properties with @dial-ignore
526
- if (dialTags.ignore) {
527
- return null;
528
- }
529
-
530
- // Determine dtype based on type or dial tags
531
- let dtype = dialTags.dtype;
532
- if (!dtype) {
533
- const type = propData.type as { name?: string } | undefined;
534
- const typeName = type?.name || "";
535
- if (typeName === "boolean") {
536
- dtype = "boolean";
537
- } else if (typeName === "number") {
538
- dtype = "number";
539
- } else if (typeName.includes("[]")) {
540
- dtype = "array";
541
- } else {
542
- dtype = "string";
543
- }
544
- }
545
-
546
- // Build schema object
547
- const schema: PropertySchema = {
548
- name: propName,
549
- dtype,
550
- };
551
-
552
- // Add default value
553
- // Priority: @dial-default annotation > component default > undefined
554
- if (dialTags.default !== undefined) {
555
- schema.value = dialTags.default;
556
- } else {
557
- const defaultValue = propData.defaultValue as { value?: string } | undefined;
558
- if (defaultValue?.value) {
559
- try {
560
- schema.value = JSON.parse(defaultValue.value);
561
- } catch {
562
- schema.value = defaultValue.value;
563
- }
564
- }
565
- }
566
-
567
- // Add dial tags
568
- if (dialTags.min !== undefined) schema.min = dialTags.min;
569
- if (dialTags.max !== undefined) schema.max = dialTags.max;
570
- if (dialTags.step !== undefined) schema.step = dialTags.step;
571
- if (dialTags.options) schema.options = dialTags.options;
572
- if (dialTags.icon) schema.icon = dialTags.icon;
573
-
574
- // Add vector-specific metadata
575
- if (dialTags.placeholders) schema.placeholders = dialTags.placeholders;
576
- if (dialTags.tooltips) schema.tooltips = dialTags.tooltips;
577
- if (dialTags.dtypes) schema.dtypes = dialTags.dtypes;
578
- if (dialTags.mins) schema.mins = dialTags.mins;
579
- if (dialTags.maxs) schema.maxs = dialTags.maxs;
580
- if (dialTags.steps) schema.steps = dialTags.steps;
581
-
582
- // Add tags for grouping and layout
583
- const tags: Record<string, unknown> = {};
584
- if (dialTags.grouping) {
585
- tags.grouping = dialTags.grouping;
586
-
587
- // Check if this group has noWrap configuration
588
- if (groupConfigs && groupConfigs[dialTags.grouping]?.noWrap) {
589
- tags.noWrap = true;
590
- }
591
- }
592
- if (dialTags.column) {
593
- tags.col = true;
594
- }
595
- if (dialTags.rowCount) {
596
- tags.row = dialTags.rowCount;
597
- tags.layout = "row";
598
- }
599
- if (dialTags.colCount) {
600
- tags.col = dialTags.colCount;
601
- tags.layout = "column";
602
- }
603
- if (dialTags.labelPosition) {
604
- tags.labelPosition = dialTags.labelPosition;
605
- }
606
-
607
- if (Object.keys(tags).length > 0) {
608
- schema.tags = tags;
609
- }
610
-
611
- return schema;
612
- }
613
-
614
- // Process a single file
615
- async function processFile(
616
- filePath: string,
617
- outputDir: string,
618
- options: docgen.ParserOptions,
619
- flags: { verbose?: boolean; quiet?: boolean; ignoreList?: string[] } = {},
620
- ): Promise<void> {
621
- if (!flags.quiet) {
622
- console.log(`\n📦 Processing ${filePath}...`);
623
- }
624
-
625
- // Parse with react-docgen-typescript
626
- const docs = docgen.parse(filePath, options);
627
-
628
- // Also parse the TypeScript source
629
- const sourceCode = readFileSync(filePath, "utf-8");
630
- const sourceFile = ts.createSourceFile(filePath, sourceCode, ts.ScriptTarget.Latest, true);
631
-
632
- // Process each component
633
- const enhancedMetadata = docs.map((doc) => {
634
- const dialSchema: PropertySchema[] = [];
635
-
636
- // Parse component-level dial configuration from description
637
- const groupConfigs: Record<string, any> = {};
638
- if (doc.description) {
639
- const componentTags = parseDialTags(doc.description);
640
- // Extract group-specific configuration
641
- const descLines = doc.description.split('\n');
642
- descLines.forEach(line => {
643
- // Match patterns like "@dial transform @dial-no-wrap"
644
- const groupMatch = line.match(/@dial\s+(\w+)(.*)/);
645
- if (groupMatch) {
646
- const groupName = groupMatch[1];
647
- const configStr = groupMatch[2];
648
- if (configStr.includes('@dial-no-wrap')) {
649
- groupConfigs[groupName] = { noWrap: true };
650
- }
651
- }
652
- });
653
- }
654
-
655
- // Also look for the Props interface and parse its JSDoc for group configurations
656
- // The props interface is typically named [ComponentName]Props
657
- const propsInterfaceName = doc.displayName + 'Props';
658
- function findInterfaceJSDoc(node: ts.Node): void {
659
- if (ts.isInterfaceDeclaration(node) && node.name.text === propsInterfaceName) {
660
- const interfaceJsDocNodes = ts.getJSDocCommentsAndTags(node);
661
- if (interfaceJsDocNodes && interfaceJsDocNodes.length > 0) {
662
- const interfaceFullText = interfaceJsDocNodes[0].getFullText();
663
- // Parse group-level configurations from interface JSDoc
664
- const lines = interfaceFullText.split('\n');
665
- lines.forEach(line => {
666
- // Match patterns like "@dial transform @dial-no-wrap"
667
- const groupMatch = line.match(/@dial\s+(\w+)(.*)/);
668
- if (groupMatch) {
669
- const groupName = groupMatch[1];
670
- const configStr = groupMatch[2];
671
- if (configStr.includes('@dial-no-wrap')) {
672
- groupConfigs[groupName] = { noWrap: true };
673
- }
674
- }
675
- });
676
- }
677
- }
678
- ts.forEachChild(node, findInterfaceJSDoc);
679
- }
680
- findInterfaceJSDoc(sourceFile);
681
-
682
- // Convert each prop to dial schema format
683
- for (const [propName, propData] of Object.entries(doc.props || {})) {
684
- const propDescription = (propData as { description?: string }).description || "";
685
- const propDialTags = parseDialTags(propDescription);
686
-
687
- // Skip properties with @dial-ignore
688
- if (propDialTags.ignore) {
689
- continue;
690
- }
691
-
692
- const propType = (propData as { type?: { name?: string } }).type;
693
- const referencedType = propDialTags.type || propType?.name;
694
-
695
- // Check if this prop references a type with dial annotations
696
- if (referencedType) {
697
- const typeDefinition = parseTypeAlias(sourceFile, referencedType);
698
-
699
- if (typeDefinition) {
700
- // Create schema with type definition
701
- const schema = propToDialSchema(propName, propData as unknown as Record<string, unknown>, groupConfigs);
702
-
703
- // Skip if the property is ignored
704
- if (!schema) {
705
- continue;
706
- }
707
-
708
- // Handle vector types with element annotations
709
- if (typeDefinition.elements && typeDefinition.elements.length > 0) {
710
- schema.dtype = "vector";
711
-
712
- // Build arrays from individual element annotations
713
- const mins: number[] = [];
714
- const maxs: number[] = [];
715
- const steps: number[] = [];
716
- const dtypes: string[] = [];
717
- const placeholders: string[] = [];
718
- const tooltips: string[] = [];
719
-
720
- typeDefinition.elements.forEach((element) => {
721
- if (element.name) {
722
- mins.push(element.min !== undefined ? element.min : 0);
723
- maxs.push(element.max !== undefined ? element.max : 100);
724
- steps.push(element.step !== undefined ? element.step : 1);
725
- dtypes.push(element.dtype || "number");
726
- placeholders.push(element.name);
727
-
728
- // Create descriptive tooltips
729
- const tooltip = element.name.includes("Segments")
730
- ? `${element.name.replace("Segments", " segments")}`
731
- : element.name.charAt(0).toUpperCase() + element.name.slice(1);
732
- tooltips.push(tooltip);
733
- }
734
- });
735
-
736
- if (mins.length > 0) schema.mins = mins;
737
- if (maxs.length > 0) schema.maxs = maxs;
738
- if (steps.length > 0) schema.steps = steps;
739
- if (dtypes.length > 0) schema.dtypes = dtypes;
740
- if (placeholders.length > 0) schema.placeholders = placeholders;
741
- if (tooltips.length > 0) schema.tooltips = tooltips;
742
-
743
- schema.typeDefinition = typeDefinition;
744
- }
745
-
746
- dialSchema.push(schema);
747
-
748
- // Also parse interface properties if it's an interface
749
- const interfaceProps = parseInterfaceProperties(sourceFile, referencedType);
750
- interfaceProps.forEach((prop) => {
751
- dialSchema.push({
752
- ...prop,
753
- name: `${propName}.${prop.name}`,
754
- tags: {
755
- grouping: "nested",
756
- parent: propName,
757
- hidden: true,
758
- metadata: true,
759
- },
760
- });
761
- });
762
- } else {
763
- // Regular prop without type definition
764
- const schema = propToDialSchema(propName, propData as unknown as Record<string, unknown>, groupConfigs);
765
- if (schema) {
766
- dialSchema.push(schema);
767
- }
768
- }
769
- } else {
770
- // Regular prop without type reference
771
- const schema = propToDialSchema(propName, propData as unknown as Record<string, unknown>, groupConfigs);
772
- if (schema) {
773
- dialSchema.push(schema);
774
- }
775
- }
776
- }
777
-
778
- return {
779
- displayName: doc.displayName,
780
- description: doc.description,
781
- dialSchema,
782
- groupConfigs,
783
- props: doc.props,
784
- };
785
- });
786
-
787
- // Create output directory if it doesn't exist
788
- if (!existsSync(outputDir)) {
789
- mkdirSync(outputDir, { recursive: true });
790
- }
791
-
792
- const baseName = basename(filePath, ".tsx").toLowerCase();
793
-
794
- // Write raw docgen output
795
- writeFileSync(join(outputDir, `${baseName}-raw.json`), JSON.stringify(docs, null, 2));
796
- if (!flags.quiet) {
797
- console.log(`📝 Wrote raw metadata to ${baseName}-raw.json`);
798
- }
799
-
800
- // Write enhanced metadata with dial schema
801
- writeFileSync(
802
- join(outputDir, `${baseName}-combined.json`),
803
- JSON.stringify(enhancedMetadata, null, 2),
804
- );
805
- if (!flags.quiet) {
806
- console.log(`📝 Wrote enhanced metadata to ${baseName}-combined.json`);
807
- }
808
-
809
- // Write just the dial schemas with groups
810
- const schemas = enhancedMetadata.map((c) => {
811
- // Convert groupConfigs to groups array
812
- const groups = Object.entries(c.groupConfigs || {}).map(([name, config]) => ({
813
- name,
814
- ...config
815
- }));
816
-
817
- return {
818
- component: c.displayName,
819
- schemas: c.dialSchema,
820
- groups: groups.length > 0 ? groups : undefined,
821
- config: c.dialConfig,
822
- };
823
- });
824
- writeFileSync(join(outputDir, `${baseName}-schemas.json`), JSON.stringify(schemas, null, 2));
825
- if (!flags.quiet) {
826
- console.log(`📝 Wrote dial schemas to ${baseName}-schemas.json`);
827
- }
828
-
829
- // Log sample output in verbose mode
830
- if (flags.verbose && enhancedMetadata.length > 0) {
831
- console.log("\n📊 Generated dial schemas:");
832
- enhancedMetadata.forEach((meta) => {
833
- console.log(`\n Component: ${meta.displayName}`);
834
- console.log(` Properties: ${meta.dialSchema.length}`);
835
- if (meta.dialSchema.length > 0) {
836
- console.log(` Sample schema:`);
837
- console.log(JSON.stringify(meta.dialSchema[0], null, 4).split('\n').map(line => ' ' + line).join('\n'));
838
- }
839
- });
840
- }
841
- }
842
-
843
- // Help text for the CLI (with dynamic version)
844
- function getHelpText(): string {
845
- const { version, gitHash } = getVersionInfo();
846
- const versionString = gitHash ? `v${version} (${gitHash})` : `v${version}`;
847
-
848
- return `
849
- dial-cli - Generate dial metadata from TypeScript/React components
850
-
851
- SYNOPSIS
852
- dial-cli [options] <file.tsx> [file2.tsx ...]
853
-
854
- DESCRIPTION
855
- The dial-cli tool parses TypeScript and React component files to extract
856
- @dial annotations from JSDoc comments and generates JSON metadata files
857
- that can be used to automatically create UI controls.
858
-
859
- The tool generates three types of output files for each input:
860
- • *-raw.json - Raw output from react-docgen-typescript
861
- • *-combined.json - Enhanced metadata with dial schema information
862
- • *-schemas.json - Just the dial schemas for UI generation
863
-
864
- OPTIONS
865
- -o, --output <dir>
866
- Output directory for generated metadata files (default: ./metadata)
867
-
868
- -i, --ignore <prop>
869
- Property names or patterns to exclude from dial schema generation
870
- Can be specified multiple times: -i prop1 -i prop2
871
- Or as a comma-separated list: -i prop1,prop2,prop3
872
- Supports glob patterns: -i "*Style" -i "on*" -i "_*"
873
-
874
- -h, --help
875
- Display this help message and exit
876
-
877
- -v, --version
878
- Display version information and exit
879
-
880
- --verbose
881
- Enable verbose output with detailed processing information
882
-
883
- --quiet
884
- Suppress all output except errors
885
-
886
- DIAL ANNOTATIONS
887
- The tool recognizes the following @dial annotations in JSDoc comments:
888
-
889
- Grouping:
890
- @dial <group> Group related properties (transform, visibility, etc.)
891
-
892
- Property Configuration:
893
- @dial-dtype <type> Data type (vector3, euler, boolean, int, etc.)
894
- @dial-min <number> Minimum value for numeric inputs
895
- @dial-max <number> Maximum value for numeric inputs
896
- @dial-step <number> Step increment for numeric inputs
897
- @dial-default <value> Default value (overrides component default)
898
- @dial-options [...] Array of preset values
899
- @dial-icon <name> Lucide icon name for the control
900
- @dial-ignore Exclude this property from dial schema generation
901
-
902
- FormLayout:
903
- @dial-col-<n> Display in column layout with n columns
904
- @dial-row-<n> Display in row layout with n items per row
905
- @dial-label-<pos> Label position (left, right, top, bottom, inline)
906
-
907
- Vector Types:
908
- @dial-mins <n,n,n> Comma-separated min values for vector elements
909
- @dial-maxs <n,n,n> Comma-separated max values for vector elements
910
- @dial-steps <n,n,n> Comma-separated step values for vector elements
911
- @dial-dtypes <t,t,t> Comma-separated data types for vector elements
912
-
913
- EXAMPLES
914
- Generate metadata for a single component:
915
- $ dial-cli MyComponent.tsx
916
-
917
- Specify a custom output directory:
918
- $ dial-cli -o ./docs/metadata MyComponent.tsx
919
-
920
- Process multiple files:
921
- $ dial-cli Component1.tsx Component2.tsx Component3.tsx
922
-
923
- Process all components in a directory:
924
- $ dial-cli src/components/*.tsx
925
-
926
- Generate metadata with verbose output:
927
- $ dial-cli --verbose MyComponent.tsx
928
-
929
- Exclude specific properties from schema generation:
930
- $ dial-cli -i className -i style -i children MyComponent.tsx
931
- $ dial-cli --ignore ref,key,id MyComponent.tsx
932
-
933
- EXAMPLE COMPONENT
934
- interface Props {
935
- /**
936
- * Position in 3D space
937
- * @dial transform
938
- * @dial-dtype vector3
939
- * @dial-mins -10,-10,-10
940
- * @dial-maxs 10,10,10
941
- * @dial-steps 0.1,0.1,0.1
942
- * @dial-icon Move3d
943
- */
944
- position: [number, number, number];
945
-
946
- /**
947
- * Visibility toggle
948
- * @dial visibility
949
- * @dial-dtype boolean
950
- * @dial-icon Eye
951
- */
952
- visible: boolean;
953
- }
954
-
955
- FILES
956
- The tool generates the following files in the output directory:
957
-
958
- <component>-raw.json
959
- Raw docgen output with all prop information
960
-
961
- <component>-combined.json
962
- Enhanced metadata including dial schemas and type definitions
963
-
964
- <component>-schemas.json
965
- Extracted dial schemas ready for UI generation
966
-
967
- ENVIRONMENT
968
- NODE_ENV
969
- Set to 'development' for debug output
970
-
971
- SEE ALSO
972
- Documentation: https://uikit.vuer.ai/dial
973
- GitHub: https://github.com/vuer-ai/vuer-uikit
974
-
975
- VERSION
976
- dial-cli ${versionString} (part of @vuer-ai/vuer-uikit)
977
-
978
- AUTHORS
979
- Vuer AI Team <team@vuer.ai>
980
- `;
981
- }
982
-
983
- // Main CLI function
984
- async function main() {
985
- const { values, positionals } = parseArgs({
986
- args: process.argv.slice(2),
987
- options: {
988
- output: {
989
- type: "string",
990
- short: "o",
991
- default: "./metadata",
992
- },
993
- ignore: {
994
- type: "string",
995
- short: "i",
996
- multiple: true,
997
- default: [],
998
- },
999
- help: {
1000
- type: "boolean",
1001
- short: "h",
1002
- },
1003
- version: {
1004
- type: "boolean",
1005
- short: "v",
1006
- },
1007
- verbose: {
1008
- type: "boolean",
1009
- },
1010
- quiet: {
1011
- type: "boolean",
1012
- },
1013
- },
1014
- allowPositionals: true,
1015
- });
1016
-
1017
- // Handle version flag
1018
- if (values.version) {
1019
- const { version, gitHash } = getVersionInfo();
1020
- const versionString = gitHash ? `v${version} (${gitHash})` : `v${version}`;
1021
- console.log(`dial-cli ${versionString} (part of @vuer-ai/vuer-uikit)`);
1022
- process.exit(0);
1023
- }
1024
-
1025
- // Handle help flag or no arguments
1026
- if (values.help || positionals.length === 0) {
1027
- console.log(getHelpText());
1028
- process.exit(0);
1029
- }
1030
-
1031
- // Check for man page style help requests
1032
- if (positionals.length === 1 && (positionals[0] === "man" || positionals[0] === "help")) {
1033
- console.log(getHelpText());
1034
- process.exit(0);
1035
- }
1036
-
1037
- const outputDir = resolve(process.cwd(), values.output as string);
1038
-
1039
- // Process ignore list - handle both multiple -i flags and comma-separated values
1040
- const ignoreList: string[] = [];
1041
- const ignoreValues = values.ignore as string | string[] | undefined;
1042
- if (ignoreValues) {
1043
- if (Array.isArray(ignoreValues)) {
1044
- ignoreValues.forEach(val => {
1045
- // Split by comma in case user provided comma-separated list
1046
- ignoreList.push(...val.split(',').map(s => s.trim()));
1047
- });
1048
- } else if (typeof ignoreValues === 'string') {
1049
- ignoreList.push(...ignoreValues.split(',').map(s => s.trim()));
1050
- }
1051
- }
1052
-
1053
- // Parser options for react-docgen-typescript
1054
- const options: docgen.ParserOptions = {
1055
- savePropValueAsString: true,
1056
- shouldExtractLiteralValuesFromEnum: true,
1057
- shouldRemoveUndefinedFromOptional: true,
1058
- propFilter: (prop) => {
1059
- // Include all props except React internals and ignored props
1060
- if (prop.name === "ref" || prop.name === "key") {
1061
- return false;
1062
- }
1063
- // Check if prop name matches any ignore pattern
1064
- // Support both exact matches and patterns with wildcards
1065
- for (const pattern of ignoreList) {
1066
- if (pattern.includes('*') || pattern.includes('?')) {
1067
- // Simple glob pattern matching
1068
- const regex = new RegExp('^' + pattern.replace(/\*/g, '.*').replace(/\?/g, '.') + '$');
1069
- if (regex.test(prop.name)) {
1070
- return false;
1071
- }
1072
- } else if (prop.name === pattern) {
1073
- // Exact match
1074
- return false;
1075
- }
1076
- }
1077
- return true;
1078
- },
1079
- };
1080
-
1081
- const flags = {
1082
- verbose: values.verbose as boolean | undefined,
1083
- quiet: values.quiet as boolean | undefined,
1084
- ignoreList,
1085
- };
1086
-
1087
- if (!flags.quiet) {
1088
- const { version, gitHash } = getVersionInfo();
1089
- const versionString = gitHash ? `v${version} (${gitHash})` : `v${version}`;
1090
- console.log(`🚀 Dial Documentation Generator ${versionString}`);
1091
- console.log(`📂 Output directory: ${outputDir}`);
1092
- if (flags.verbose && ignoreList.length > 0) {
1093
- console.log(`🚫 Ignoring properties: ${ignoreList.join(', ')}`);
1094
- }
1095
- }
1096
-
1097
- // Process each file
1098
- let filesProcessed = 0;
1099
- let filesErrored = 0;
1100
-
1101
- for (const file of positionals) {
1102
- const filePath = resolve(process.cwd(), file);
1103
-
1104
- if (!existsSync(filePath)) {
1105
- console.error(`❌ File not found: ${filePath}`);
1106
- filesErrored++;
1107
- continue;
1108
- }
1109
-
1110
- try {
1111
- await processFile(filePath, outputDir, options, flags);
1112
- filesProcessed++;
1113
- } catch (error) {
1114
- console.error(`❌ Error processing ${filePath}:`, error);
1115
- filesErrored++;
1116
- }
1117
- }
1118
-
1119
- if (!flags.quiet) {
1120
- console.log("\n✅ Documentation generation complete!");
1121
- if (flags.verbose) {
1122
- console.log(` Files processed: ${filesProcessed}`);
1123
- if (filesErrored > 0) {
1124
- console.log(` Files with errors: ${filesErrored}`);
1125
- }
1126
- }
1127
- }
1128
- }
1129
-
1130
- // Run the CLI - always run when this is the main module
1131
- main().catch((error) => {
1132
- console.error("Fatal error:", error);
1133
- process.exit(1);
1134
- });
1135
-
1136
- export { parseDialTags, propToDialSchema, parseTypeAlias, parseInterfaceProperties };