@urbicon-ui/docs-gen 6.1.4

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 (263) hide show
  1. package/README.md +92 -0
  2. package/dist/cli/CLI.d.ts +10 -0
  3. package/dist/cli/CLI.d.ts.map +1 -0
  4. package/dist/cli/CLI.js +340 -0
  5. package/dist/cli/CLI.js.map +1 -0
  6. package/dist/cli/index.d.ts +2 -0
  7. package/dist/cli/index.d.ts.map +1 -0
  8. package/dist/cli/index.js +7 -0
  9. package/dist/cli/index.js.map +1 -0
  10. package/dist/core/discovery/ComponentFinder.d.ts +43 -0
  11. package/dist/core/discovery/ComponentFinder.d.ts.map +1 -0
  12. package/dist/core/discovery/ComponentFinder.js +421 -0
  13. package/dist/core/discovery/ComponentFinder.js.map +1 -0
  14. package/dist/core/discovery/FileStructureAnalyzer.d.ts +15 -0
  15. package/dist/core/discovery/FileStructureAnalyzer.d.ts.map +1 -0
  16. package/dist/core/discovery/FileStructureAnalyzer.js +35 -0
  17. package/dist/core/discovery/FileStructureAnalyzer.js.map +1 -0
  18. package/dist/core/discovery/MetadataExtractor.d.ts +15 -0
  19. package/dist/core/discovery/MetadataExtractor.d.ts.map +1 -0
  20. package/dist/core/discovery/MetadataExtractor.js +47 -0
  21. package/dist/core/discovery/MetadataExtractor.js.map +1 -0
  22. package/dist/core/discovery/index.d.ts +2 -0
  23. package/dist/core/discovery/index.d.ts.map +1 -0
  24. package/dist/core/discovery/index.js +2 -0
  25. package/dist/core/discovery/index.js.map +1 -0
  26. package/dist/core/enrichment/APIDataGenerator.d.ts +77 -0
  27. package/dist/core/enrichment/APIDataGenerator.d.ts.map +1 -0
  28. package/dist/core/enrichment/APIDataGenerator.js +663 -0
  29. package/dist/core/enrichment/APIDataGenerator.js.map +1 -0
  30. package/dist/core/enrichment/index.d.ts +2 -0
  31. package/dist/core/enrichment/index.d.ts.map +1 -0
  32. package/dist/core/enrichment/index.js +6 -0
  33. package/dist/core/enrichment/index.js.map +1 -0
  34. package/dist/core/extraction/ExtractionCoordinator.d.ts +53 -0
  35. package/dist/core/extraction/ExtractionCoordinator.d.ts.map +1 -0
  36. package/dist/core/extraction/ExtractionCoordinator.js +352 -0
  37. package/dist/core/extraction/ExtractionCoordinator.js.map +1 -0
  38. package/dist/core/extraction/index.d.ts +2 -0
  39. package/dist/core/extraction/index.d.ts.map +1 -0
  40. package/dist/core/extraction/index.js +2 -0
  41. package/dist/core/extraction/index.js.map +1 -0
  42. package/dist/core/generation/GenerationCoordinator.d.ts +51 -0
  43. package/dist/core/generation/GenerationCoordinator.d.ts.map +1 -0
  44. package/dist/core/generation/GenerationCoordinator.js +206 -0
  45. package/dist/core/generation/GenerationCoordinator.js.map +1 -0
  46. package/dist/core/generation/index.d.ts +2 -0
  47. package/dist/core/generation/index.d.ts.map +1 -0
  48. package/dist/core/generation/index.js +2 -0
  49. package/dist/core/generation/index.js.map +1 -0
  50. package/dist/core/index.d.ts +7 -0
  51. package/dist/core/index.d.ts.map +1 -0
  52. package/dist/core/index.js +16 -0
  53. package/dist/core/index.js.map +1 -0
  54. package/dist/core/pipeline/ErrorHandler.d.ts +129 -0
  55. package/dist/core/pipeline/ErrorHandler.d.ts.map +1 -0
  56. package/dist/core/pipeline/ErrorHandler.js +321 -0
  57. package/dist/core/pipeline/ErrorHandler.js.map +1 -0
  58. package/dist/core/pipeline/PipelineOrchestrator.d.ts +45 -0
  59. package/dist/core/pipeline/PipelineOrchestrator.d.ts.map +1 -0
  60. package/dist/core/pipeline/PipelineOrchestrator.js +216 -0
  61. package/dist/core/pipeline/PipelineOrchestrator.js.map +1 -0
  62. package/dist/core/pipeline/index.d.ts +1 -0
  63. package/dist/core/pipeline/index.d.ts.map +1 -0
  64. package/dist/core/pipeline/index.js +2 -0
  65. package/dist/core/pipeline/index.js.map +1 -0
  66. package/dist/extractors/BaseExtractor.d.ts +33 -0
  67. package/dist/extractors/BaseExtractor.d.ts.map +1 -0
  68. package/dist/extractors/BaseExtractor.js +68 -0
  69. package/dist/extractors/BaseExtractor.js.map +1 -0
  70. package/dist/extractors/ExtractorFactory.d.ts +35 -0
  71. package/dist/extractors/ExtractorFactory.d.ts.map +1 -0
  72. package/dist/extractors/ExtractorFactory.js +88 -0
  73. package/dist/extractors/ExtractorFactory.js.map +1 -0
  74. package/dist/extractors/documentation/index.d.ts +1 -0
  75. package/dist/extractors/documentation/index.d.ts.map +1 -0
  76. package/dist/extractors/documentation/index.js +2 -0
  77. package/dist/extractors/documentation/index.js.map +1 -0
  78. package/dist/extractors/index.d.ts +1 -0
  79. package/dist/extractors/index.d.ts.map +1 -0
  80. package/dist/extractors/index.js +2 -0
  81. package/dist/extractors/index.js.map +1 -0
  82. package/dist/extractors/typescript/ExamplesExtractor.d.ts +32 -0
  83. package/dist/extractors/typescript/ExamplesExtractor.d.ts.map +1 -0
  84. package/dist/extractors/typescript/ExamplesExtractor.js +209 -0
  85. package/dist/extractors/typescript/ExamplesExtractor.js.map +1 -0
  86. package/dist/extractors/typescript/InheritanceExtractor.d.ts +45 -0
  87. package/dist/extractors/typescript/InheritanceExtractor.d.ts.map +1 -0
  88. package/dist/extractors/typescript/InheritanceExtractor.js +368 -0
  89. package/dist/extractors/typescript/InheritanceExtractor.js.map +1 -0
  90. package/dist/extractors/typescript/LocalTypesExtractor.d.ts +20 -0
  91. package/dist/extractors/typescript/LocalTypesExtractor.d.ts.map +1 -0
  92. package/dist/extractors/typescript/LocalTypesExtractor.js +100 -0
  93. package/dist/extractors/typescript/LocalTypesExtractor.js.map +1 -0
  94. package/dist/extractors/typescript/PropsExtractor.d.ts +142 -0
  95. package/dist/extractors/typescript/PropsExtractor.d.ts.map +1 -0
  96. package/dist/extractors/typescript/PropsExtractor.js +709 -0
  97. package/dist/extractors/typescript/PropsExtractor.js.map +1 -0
  98. package/dist/extractors/typescript/TypeScriptBaseExtractor.d.ts +74 -0
  99. package/dist/extractors/typescript/TypeScriptBaseExtractor.d.ts.map +1 -0
  100. package/dist/extractors/typescript/TypeScriptBaseExtractor.js +249 -0
  101. package/dist/extractors/typescript/TypeScriptBaseExtractor.js.map +1 -0
  102. package/dist/extractors/typescript/index.d.ts +1 -0
  103. package/dist/extractors/typescript/index.d.ts.map +1 -0
  104. package/dist/extractors/typescript/index.js +2 -0
  105. package/dist/extractors/typescript/index.js.map +1 -0
  106. package/dist/extractors/variants/TailwindVariantsParser.d.ts +16 -0
  107. package/dist/extractors/variants/TailwindVariantsParser.d.ts.map +1 -0
  108. package/dist/extractors/variants/TailwindVariantsParser.js +53 -0
  109. package/dist/extractors/variants/TailwindVariantsParser.js.map +1 -0
  110. package/dist/extractors/variants/VariantsExtractor.d.ts +45 -0
  111. package/dist/extractors/variants/VariantsExtractor.d.ts.map +1 -0
  112. package/dist/extractors/variants/VariantsExtractor.js +340 -0
  113. package/dist/extractors/variants/VariantsExtractor.js.map +1 -0
  114. package/dist/extractors/variants/index.d.ts +2 -0
  115. package/dist/extractors/variants/index.d.ts.map +1 -0
  116. package/dist/extractors/variants/index.js +2 -0
  117. package/dist/extractors/variants/index.js.map +1 -0
  118. package/dist/generators/api/APIFileGenerator.d.ts +32 -0
  119. package/dist/generators/api/APIFileGenerator.d.ts.map +1 -0
  120. package/dist/generators/api/APIFileGenerator.js +450 -0
  121. package/dist/generators/api/APIFileGenerator.js.map +1 -0
  122. package/dist/generators/api/TypeDefinitionGenerator.d.ts +1 -0
  123. package/dist/generators/api/TypeDefinitionGenerator.d.ts.map +1 -0
  124. package/dist/generators/api/TypeDefinitionGenerator.js +2 -0
  125. package/dist/generators/api/TypeDefinitionGenerator.js.map +1 -0
  126. package/dist/generators/api/index.d.ts +2 -0
  127. package/dist/generators/api/index.d.ts.map +1 -0
  128. package/dist/generators/api/index.js +2 -0
  129. package/dist/generators/api/index.js.map +1 -0
  130. package/dist/generators/index.d.ts +5 -0
  131. package/dist/generators/index.d.ts.map +1 -0
  132. package/dist/generators/index.js +4 -0
  133. package/dist/generators/index.js.map +1 -0
  134. package/dist/generators/llm/LLMDocumentationGenerator.d.ts +34 -0
  135. package/dist/generators/llm/LLMDocumentationGenerator.d.ts.map +1 -0
  136. package/dist/generators/llm/LLMDocumentationGenerator.js +480 -0
  137. package/dist/generators/llm/LLMDocumentationGenerator.js.map +1 -0
  138. package/dist/generators/llm/LLMFormatter.d.ts +4 -0
  139. package/dist/generators/llm/LLMFormatter.d.ts.map +1 -0
  140. package/dist/generators/llm/LLMFormatter.js +8 -0
  141. package/dist/generators/llm/LLMFormatter.js.map +1 -0
  142. package/dist/generators/llm/LlmsFullAssembler.d.ts +20 -0
  143. package/dist/generators/llm/LlmsFullAssembler.d.ts.map +1 -0
  144. package/dist/generators/llm/LlmsFullAssembler.js +63 -0
  145. package/dist/generators/llm/LlmsFullAssembler.js.map +1 -0
  146. package/dist/generators/llm/index.d.ts +1 -0
  147. package/dist/generators/llm/index.d.ts.map +1 -0
  148. package/dist/generators/llm/index.js +2 -0
  149. package/dist/generators/llm/index.js.map +1 -0
  150. package/dist/generators/mcp/MCPCatalogAssembler.d.ts +27 -0
  151. package/dist/generators/mcp/MCPCatalogAssembler.d.ts.map +1 -0
  152. package/dist/generators/mcp/MCPCatalogAssembler.js +147 -0
  153. package/dist/generators/mcp/MCPCatalogAssembler.js.map +1 -0
  154. package/dist/generators/mcp/MCPCatalogGenerator.d.ts +55 -0
  155. package/dist/generators/mcp/MCPCatalogGenerator.d.ts.map +1 -0
  156. package/dist/generators/mcp/MCPCatalogGenerator.js +153 -0
  157. package/dist/generators/mcp/MCPCatalogGenerator.js.map +1 -0
  158. package/dist/generators/svelte/PageGenerator.d.ts +82 -0
  159. package/dist/generators/svelte/PageGenerator.d.ts.map +1 -0
  160. package/dist/generators/svelte/PageGenerator.js +557 -0
  161. package/dist/generators/svelte/PageGenerator.js.map +1 -0
  162. package/dist/generators/svelte/PlaygroundPresets.d.ts +2 -0
  163. package/dist/generators/svelte/PlaygroundPresets.d.ts.map +1 -0
  164. package/dist/generators/svelte/PlaygroundPresets.js +4 -0
  165. package/dist/generators/svelte/PlaygroundPresets.js.map +1 -0
  166. package/dist/generators/svelte/SectionMerger.d.ts +38 -0
  167. package/dist/generators/svelte/SectionMerger.d.ts.map +1 -0
  168. package/dist/generators/svelte/SectionMerger.js +154 -0
  169. package/dist/generators/svelte/SectionMerger.js.map +1 -0
  170. package/dist/generators/svelte/TemplateEngine.d.ts +91 -0
  171. package/dist/generators/svelte/TemplateEngine.d.ts.map +1 -0
  172. package/dist/generators/svelte/TemplateEngine.js +500 -0
  173. package/dist/generators/svelte/TemplateEngine.js.map +1 -0
  174. package/dist/generators/svelte/index.d.ts +8 -0
  175. package/dist/generators/svelte/index.d.ts.map +1 -0
  176. package/dist/generators/svelte/index.js +11 -0
  177. package/dist/generators/svelte/index.js.map +1 -0
  178. package/dist/generators/svelte/renderers/ApiRenderer.d.ts +17 -0
  179. package/dist/generators/svelte/renderers/ApiRenderer.d.ts.map +1 -0
  180. package/dist/generators/svelte/renderers/ApiRenderer.js +44 -0
  181. package/dist/generators/svelte/renderers/ApiRenderer.js.map +1 -0
  182. package/dist/generators/svelte/renderers/ExampleRenderer.d.ts +33 -0
  183. package/dist/generators/svelte/renderers/ExampleRenderer.d.ts.map +1 -0
  184. package/dist/generators/svelte/renderers/ExampleRenderer.js +137 -0
  185. package/dist/generators/svelte/renderers/ExampleRenderer.js.map +1 -0
  186. package/dist/generators/svelte/renderers/OverviewRenderer.d.ts +9 -0
  187. package/dist/generators/svelte/renderers/OverviewRenderer.d.ts.map +1 -0
  188. package/dist/generators/svelte/renderers/OverviewRenderer.js +45 -0
  189. package/dist/generators/svelte/renderers/OverviewRenderer.js.map +1 -0
  190. package/dist/generators/svelte/renderers/PlaygroundRenderer.d.ts +35 -0
  191. package/dist/generators/svelte/renderers/PlaygroundRenderer.d.ts.map +1 -0
  192. package/dist/generators/svelte/renderers/PlaygroundRenderer.js +319 -0
  193. package/dist/generators/svelte/renderers/PlaygroundRenderer.js.map +1 -0
  194. package/dist/generators/svelte/renderers/TypesRenderer.d.ts +9 -0
  195. package/dist/generators/svelte/renderers/TypesRenderer.d.ts.map +1 -0
  196. package/dist/generators/svelte/renderers/TypesRenderer.js +23 -0
  197. package/dist/generators/svelte/renderers/TypesRenderer.js.map +1 -0
  198. package/dist/generators/svelte/renderers/UsageRenderer.d.ts +14 -0
  199. package/dist/generators/svelte/renderers/UsageRenderer.d.ts.map +1 -0
  200. package/dist/generators/svelte/renderers/UsageRenderer.js +91 -0
  201. package/dist/generators/svelte/renderers/UsageRenderer.js.map +1 -0
  202. package/dist/generators/svelte/renderers/VariantsRenderer.d.ts +43 -0
  203. package/dist/generators/svelte/renderers/VariantsRenderer.d.ts.map +1 -0
  204. package/dist/generators/svelte/renderers/VariantsRenderer.js +277 -0
  205. package/dist/generators/svelte/renderers/VariantsRenderer.js.map +1 -0
  206. package/dist/generators/svelte/renderers/index.d.ts +8 -0
  207. package/dist/generators/svelte/renderers/index.d.ts.map +1 -0
  208. package/dist/generators/svelte/renderers/index.js +8 -0
  209. package/dist/generators/svelte/renderers/index.js.map +1 -0
  210. package/dist/generators/svelte/types.d.ts +13 -0
  211. package/dist/generators/svelte/types.d.ts.map +1 -0
  212. package/dist/generators/svelte/types.js +2 -0
  213. package/dist/generators/svelte/types.js.map +1 -0
  214. package/dist/index.d.ts +5 -0
  215. package/dist/index.d.ts.map +1 -0
  216. package/dist/index.js +4 -0
  217. package/dist/index.js.map +1 -0
  218. package/dist/parsers/SvelteDocsParser.d.ts +44 -0
  219. package/dist/parsers/SvelteDocsParser.d.ts.map +1 -0
  220. package/dist/parsers/SvelteDocsParser.js +141 -0
  221. package/dist/parsers/SvelteDocsParser.js.map +1 -0
  222. package/dist/parsers/index.d.ts +2 -0
  223. package/dist/parsers/index.d.ts.map +1 -0
  224. package/dist/parsers/index.js +6 -0
  225. package/dist/parsers/index.js.map +1 -0
  226. package/dist/schema/ConfigurationBuilder.d.ts +55 -0
  227. package/dist/schema/ConfigurationBuilder.d.ts.map +1 -0
  228. package/dist/schema/ConfigurationBuilder.js +447 -0
  229. package/dist/schema/ConfigurationBuilder.js.map +1 -0
  230. package/dist/schema/index.d.ts +1 -0
  231. package/dist/schema/index.d.ts.map +1 -0
  232. package/dist/schema/index.js +2 -0
  233. package/dist/schema/index.js.map +1 -0
  234. package/dist/tsconfig.tsbuildinfo +1 -0
  235. package/dist/types/configuration.d.ts +255 -0
  236. package/dist/types/configuration.d.ts.map +1 -0
  237. package/dist/types/configuration.js +2 -0
  238. package/dist/types/configuration.js.map +1 -0
  239. package/dist/types/core.d.ts +96 -0
  240. package/dist/types/core.d.ts.map +1 -0
  241. package/dist/types/core.js +2 -0
  242. package/dist/types/core.js.map +1 -0
  243. package/dist/types/docs-config.d.ts +5 -0
  244. package/dist/types/docs-config.d.ts.map +1 -0
  245. package/dist/types/docs-config.js +51 -0
  246. package/dist/types/docs-config.js.map +1 -0
  247. package/dist/types/index.d.ts +6 -0
  248. package/dist/types/index.d.ts.map +1 -0
  249. package/dist/types/index.js +9 -0
  250. package/dist/types/index.js.map +1 -0
  251. package/dist/types/validation.d.ts +321 -0
  252. package/dist/types/validation.d.ts.map +1 -0
  253. package/dist/types/validation.js +2 -0
  254. package/dist/types/validation.js.map +1 -0
  255. package/dist/utils/DeploymentManager.d.ts +80 -0
  256. package/dist/utils/DeploymentManager.d.ts.map +1 -0
  257. package/dist/utils/DeploymentManager.js +360 -0
  258. package/dist/utils/DeploymentManager.js.map +1 -0
  259. package/dist/utils/index.d.ts +1 -0
  260. package/dist/utils/index.d.ts.map +1 -0
  261. package/dist/utils/index.js +2 -0
  262. package/dist/utils/index.js.map +1 -0
  263. package/package.json +74 -0
@@ -0,0 +1,709 @@
1
+ import * as ts from 'typescript';
2
+ import { TypeScriptBaseExtractor } from './TypeScriptBaseExtractor';
3
+ /**
4
+ * Extracts props from TypeScript interfaces using AST parsing
5
+ * Supports JSDoc comments, type analysis, and prop categorization
6
+ */
7
+ export class PropsExtractor extends TypeScriptBaseExtractor {
8
+ config;
9
+ currentVariantKeys = [];
10
+ constructor(tsConfig) {
11
+ super(tsConfig);
12
+ const ext = tsConfig
13
+ ?.extraction?.typescript;
14
+ this.config = {
15
+ extractJSDoc: true,
16
+ extractTypeReferences: true,
17
+ extractDefaultValues: true,
18
+ resolveTypeAliases: true,
19
+ includePrivateProps: false,
20
+ ...(ext ?? tsConfig)
21
+ };
22
+ }
23
+ /**
24
+ * Extract props from TypeScript interface
25
+ */
26
+ async extract(input) {
27
+ const startTime = Date.now();
28
+ if (!this.validateInput(input)) {
29
+ return this.handleError(new Error('Invalid input for props extraction'), input);
30
+ }
31
+ try {
32
+ console.log(`🔍 Extracting props for ${input.componentName} from ${input.filePath}`);
33
+ // Keep variant keys for Omit filtering within this extraction call
34
+ this.currentVariantKeys = Array.isArray(input.variantKeys) ? input.variantKeys : [];
35
+ const sourceFile = await this.getSourceFile(input.filePath);
36
+ if (!sourceFile) {
37
+ return this.handleError(new Error(`Could not load source file: ${input.filePath}`), input);
38
+ }
39
+ // Find the props declaration — either an interface or a
40
+ // type-alias whose RHS is a union (discriminated-union pattern).
41
+ const propsDeclaration = this.findPropsDeclaration(sourceFile, input.componentName);
42
+ if (!propsDeclaration) {
43
+ const warning = this.addWarning('no_props_interface', `No ${input.componentName}Props interface found`, `Create a ${input.componentName}Props interface to document component properties`);
44
+ return this.createSuccessResult([], [warning], input.filePath, Date.now() - startTime);
45
+ }
46
+ console.log(`✅ Found ${input.componentName}Props (${propsDeclaration.kind === 'interface' ? 'interface' : 'union type alias'})`);
47
+ // Extract props from interface OR from the union members.
48
+ const props = propsDeclaration.kind === 'interface'
49
+ ? await this.extractPropsFromInterface(propsDeclaration.node, sourceFile)
50
+ : await this.extractPropsFromUnion(propsDeclaration.node, sourceFile, propsDeclaration.jsDocHost.name.text);
51
+ console.log(`📝 Extracted ${props.length} props from ${input.componentName}Props`);
52
+ const duration = Date.now() - startTime;
53
+ const result = this.createSuccessResult(props, [], input.filePath, duration);
54
+ // Clear per-call state
55
+ this.currentVariantKeys = [];
56
+ return result;
57
+ }
58
+ catch (error) {
59
+ this.currentVariantKeys = [];
60
+ return this.handleError(error, input);
61
+ }
62
+ }
63
+ /**
64
+ * Extract the component description from the JSDoc on the *Props declaration.
65
+ * Checks @description tag first, then falls back to leading prose text.
66
+ */
67
+ async extractDescription(input) {
68
+ const sourceFile = await this.getSourceFile(input.filePath);
69
+ if (!sourceFile)
70
+ return null;
71
+ const declaration = this.findPropsDeclaration(sourceFile, input.componentName);
72
+ if (!declaration)
73
+ return null;
74
+ const tagged = this.extractJSDocTag(declaration.jsDocHost, 'description');
75
+ if (tagged)
76
+ return tagged;
77
+ return this.extractJSDocComment(declaration.jsDocHost);
78
+ }
79
+ /**
80
+ * Extract all @tag values from the *Props declaration JSDoc.
81
+ */
82
+ async extractTags(input) {
83
+ const sourceFile = await this.getSourceFile(input.filePath);
84
+ if (!sourceFile)
85
+ return [];
86
+ const declaration = this.findPropsDeclaration(sourceFile, input.componentName);
87
+ if (!declaration)
88
+ return [];
89
+ return this.extractJSDocTagAll(declaration.jsDocHost, 'tag');
90
+ }
91
+ /**
92
+ * Extract all @related values from the *Props declaration JSDoc.
93
+ */
94
+ async extractRelated(input) {
95
+ const sourceFile = await this.getSourceFile(input.filePath);
96
+ if (!sourceFile)
97
+ return [];
98
+ const declaration = this.findPropsDeclaration(sourceFile, input.componentName);
99
+ if (!declaration)
100
+ return [];
101
+ return this.extractJSDocTagAll(declaration.jsDocHost, 'related');
102
+ }
103
+ /**
104
+ * Extract the `@stability` tag from the *Props declaration JSDoc.
105
+ * Accepts `experimental | beta | stable | deprecated`; unknown
106
+ * values are dropped so a typo doesn't silently propagate into the
107
+ * Editorial badge.
108
+ */
109
+ async extractStability(input) {
110
+ const sourceFile = await this.getSourceFile(input.filePath);
111
+ if (!sourceFile)
112
+ return null;
113
+ const declaration = this.findPropsDeclaration(sourceFile, input.componentName);
114
+ if (!declaration)
115
+ return null;
116
+ const raw = this.extractJSDocTag(declaration.jsDocHost, 'stability');
117
+ if (!raw)
118
+ return null;
119
+ const normalised = raw.trim().toLowerCase();
120
+ if (normalised === 'experimental' ||
121
+ normalised === 'beta' ||
122
+ normalised === 'stable' ||
123
+ normalised === 'deprecated') {
124
+ return normalised;
125
+ }
126
+ return null;
127
+ }
128
+ // ==========================================
129
+ // DECLARATION DISCOVERY
130
+ // ==========================================
131
+ /**
132
+ * Locate the component's props declaration. Either:
133
+ * - an `interface FooProps { ... }` → kind: 'interface'
134
+ * - a `type FooProps = A | B | …` → kind: 'union'
135
+ *
136
+ * `node` is the AST node whose members get walked for props; `jsDocHost`
137
+ * is the declaration that owns the leading JSDoc block (for an interface
138
+ * they're the same; for a union the JSDoc lives on the type-alias, not
139
+ * on the `UnionTypeNode` itself). Other type-alias shapes (intersection,
140
+ * single reference, mapped types, etc.) aren't supported here and fall
141
+ * through to `null`.
142
+ */
143
+ findPropsDeclaration(sourceFile, componentName) {
144
+ const possibleNames = [
145
+ `${componentName}Props`,
146
+ `I${componentName}Props`,
147
+ `${componentName}Properties`
148
+ ];
149
+ for (const name of possibleNames) {
150
+ const iface = this.findInterface(sourceFile, name);
151
+ if (iface)
152
+ return { kind: 'interface', node: iface, jsDocHost: iface };
153
+ const alias = this.findTypeAlias(sourceFile, name);
154
+ if (alias && ts.isUnionTypeNode(alias.type)) {
155
+ return { kind: 'union', node: alias.type, jsDocHost: alias };
156
+ }
157
+ }
158
+ return null;
159
+ }
160
+ // ==========================================
161
+ // PROPS EXTRACTION
162
+ // ==========================================
163
+ /**
164
+ * Extract props from a discriminated-union type alias.
165
+ *
166
+ * Algorithm (generic — no hard-coded discriminator name):
167
+ * 1. Resolve each union member to a local interface. Members that
168
+ * can't be resolved (anonymous type literals, external refs,
169
+ * intersections, etc.) are dropped with a warning.
170
+ * 2. Extract props from each resolved interface (reusing the
171
+ * interface path so heritage / Omit / variants are honoured).
172
+ * 3. Detect the discriminator: a property that exists in every
173
+ * member with a single string-literal type, and whose literal
174
+ * value differs across members.
175
+ * 4. Merge the per-member prop sets:
176
+ * - Props that appear in every member → unconditional.
177
+ * - Props that appear in only some members → `conditionalOn`
178
+ * records the discriminator and the values where they apply.
179
+ * - The discriminator prop itself is collapsed into one entry
180
+ * whose `values` array enumerates every literal it can take.
181
+ */
182
+ async extractPropsFromUnion(union, sourceFile, aliasName) {
183
+ const memberProps = [];
184
+ for (const memberType of union.types) {
185
+ const resolved = this.resolveUnionMemberInterface(memberType, sourceFile);
186
+ if (!resolved) {
187
+ console.log(`⚠️ Skipping un-resolvable union member: ${memberType.getText().slice(0, 60)}`);
188
+ continue;
189
+ }
190
+ const props = await this.extractPropsFromInterface(resolved.iface, sourceFile);
191
+ memberProps.push({ memberName: resolved.name, props });
192
+ }
193
+ if (memberProps.length === 0) {
194
+ return [];
195
+ }
196
+ if (memberProps.length === 1) {
197
+ // Degenerate single-member union — treat as plain interface.
198
+ return memberProps[0].props;
199
+ }
200
+ // Build a "prop name → values seen per member" map.
201
+ //
202
+ // A `never` declaration counts as "not present in this variant" —
203
+ // it's the discriminated-union idiom for forbidding a property on
204
+ // a specific arm (`children?: never`). We still keep the
205
+ // occurrence around in case it's the only one we have, but it
206
+ // doesn't gate `conditionalOn` membership.
207
+ const presence = new Map();
208
+ const everPresent = new Map();
209
+ for (const { memberName, props } of memberProps) {
210
+ for (const prop of props) {
211
+ everPresent.set(prop.name, prop);
212
+ if (prop.type === 'never')
213
+ continue;
214
+ if (!presence.has(prop.name))
215
+ presence.set(prop.name, new Map());
216
+ presence.get(prop.name).set(memberName, prop);
217
+ }
218
+ }
219
+ // Seed any properties that only appeared as `never` declarations
220
+ // (no real-typed occurrence anywhere) — they exist syntactically
221
+ // but should be reported as never-typed.
222
+ for (const [name, prop] of everPresent) {
223
+ if (!presence.has(name)) {
224
+ presence.set(name, new Map([['__never__', prop]]));
225
+ }
226
+ }
227
+ const memberCount = memberProps.length;
228
+ // Find the discriminator: the prop that exists in every member with
229
+ // a single distinct string-literal type per member.
230
+ const discriminator = this.detectDiscriminator(presence, memberProps);
231
+ const merged = [];
232
+ for (const [name, byMember] of presence) {
233
+ const occurrences = Array.from(byMember.values());
234
+ // Membership counts only real members (skip the `__never__`
235
+ // sentinel that holds purely-never declarations).
236
+ const realMemberKeys = Array.from(byMember.keys()).filter((k) => k !== '__never__');
237
+ const isUnconditional = realMemberKeys.length === memberCount;
238
+ if (discriminator && name === discriminator.propName) {
239
+ // Collapse the discriminator into one entry whose `values`
240
+ // enumerates every literal it can take, with `type` rebuilt
241
+ // as the union of all member literals.
242
+ const allValues = new Set();
243
+ for (const occ of occurrences) {
244
+ for (const v of occ.values ?? [])
245
+ allValues.add(v);
246
+ }
247
+ const base = { ...this.pickInformativeOccurrence(occurrences) };
248
+ base.values = Array.from(allValues);
249
+ base.type = base.values.map((v) => `'${v}'`).join(' | ');
250
+ // The discriminator is effectively required only when every
251
+ // member declares it as required. If any arm makes it optional
252
+ // (typically the one with a default literal), consumers can
253
+ // omit it and the type narrows to that arm — so from the
254
+ // public API view it's optional.
255
+ base.required = occurrences.every((occ) => occ.required);
256
+ // Re-source onto the outer alias — the discriminator's sub-
257
+ // interface name is implementation detail (see the same
258
+ // re-source below for non-discriminator props).
259
+ base.source = { type: 'direct', name: aliasName };
260
+ // No conditionalOn — the discriminator is the property that's
261
+ // always present.
262
+ delete base.conditionalOn;
263
+ merged.push(base);
264
+ continue;
265
+ }
266
+ // When a prop is declared as `never` in one member and a real
267
+ // type in another (the `BadgeDotProps.interactive?: never` /
268
+ // `BadgeStandardProps.interactive?: boolean` pattern), prefer
269
+ // the real declaration — it's the one consumers actually use.
270
+ const head = { ...this.pickInformativeOccurrence(occurrences) };
271
+ // From the consumer's point of view every prop on the union is
272
+ // direct on the outer alias — the per-member sub-interfaces are
273
+ // implementation detail. Re-source accordingly so the API surface
274
+ // doesn't leak `BadgeBaseProps` / `BadgeStandardProps` as if the
275
+ // consumer had to know them.
276
+ head.source = { type: 'direct', name: aliasName };
277
+ if (!isUnconditional && discriminator) {
278
+ const applicableValues = [];
279
+ for (const memberName of realMemberKeys) {
280
+ const values = discriminator.valuesByMember.get(memberName);
281
+ if (values)
282
+ applicableValues.push(...values);
283
+ }
284
+ head.conditionalOn = {
285
+ propName: discriminator.propName,
286
+ values: Array.from(new Set(applicableValues))
287
+ };
288
+ }
289
+ merged.push(head);
290
+ }
291
+ return this.sortProps(merged);
292
+ }
293
+ /**
294
+ * Pick the most informative occurrence of a prop across union members.
295
+ * Prefers occurrences whose type isn't `never`, whose description isn't
296
+ * an auto-generated placeholder (`'<name> property'`), and which carry
297
+ * a `defaultValue` over those that don't. This keeps
298
+ * `<Badge variant="dot" removable>` extracting as `removable: boolean`
299
+ * (from `BadgeStandardProps`) rather than `removable?: never` (from
300
+ * `BadgeDotProps`) — and, when collapsing the discriminator, picks the
301
+ * arm whose `@default` JSDoc is set so the docs site renders a real
302
+ * default value in the API table.
303
+ */
304
+ pickInformativeOccurrence(occurrences) {
305
+ if (occurrences.length === 0) {
306
+ throw new Error('pickInformativeOccurrence called with no occurrences');
307
+ }
308
+ const ranked = [...occurrences].sort((a, b) => {
309
+ const aPlaceholder = a.type === 'never' ? 2 : 0;
310
+ const bPlaceholder = b.type === 'never' ? 2 : 0;
311
+ const aDoc = a.description.endsWith(' property') ? 1 : 0;
312
+ const bDoc = b.description.endsWith(' property') ? 1 : 0;
313
+ const aNoDefault = a.defaultValue === undefined ? 0.5 : 0;
314
+ const bNoDefault = b.defaultValue === undefined ? 0.5 : 0;
315
+ return aPlaceholder + aDoc + aNoDefault - (bPlaceholder + bDoc + bNoDefault);
316
+ });
317
+ return ranked[0];
318
+ }
319
+ /**
320
+ * Resolve a union-member type to a local interface declaration. Currently
321
+ * supports plain TypeReferenceNode shapes (`A`, `Foo<T>`). Returns null for
322
+ * anonymous type literals, intersections, external references the file
323
+ * doesn't import directly, etc.
324
+ */
325
+ resolveUnionMemberInterface(memberType, sourceFile) {
326
+ if (!ts.isTypeReferenceNode(memberType))
327
+ return null;
328
+ const name = memberType.typeName.getText();
329
+ const iface = this.findInterface(sourceFile, name);
330
+ if (!iface)
331
+ return null;
332
+ return { iface, name };
333
+ }
334
+ /**
335
+ * Detect the discriminator property. A discriminator must:
336
+ * - exist in every union member,
337
+ * - have a string-literal-union type in each member (one or more
338
+ * `'x' | 'y'` values),
339
+ * - have non-overlapping value-sets across members (so the literal
340
+ * uniquely identifies which member a value belongs to).
341
+ *
342
+ * Returns null if no such property exists.
343
+ */
344
+ detectDiscriminator(presence, memberProps) {
345
+ const memberCount = memberProps.length;
346
+ for (const [propName, byMember] of presence) {
347
+ if (byMember.size !== memberCount)
348
+ continue;
349
+ const valuesByMember = new Map();
350
+ let valid = true;
351
+ for (const { memberName } of memberProps) {
352
+ const prop = byMember.get(memberName);
353
+ if (!prop?.values || prop.values.length === 0) {
354
+ valid = false;
355
+ break;
356
+ }
357
+ valuesByMember.set(memberName, prop.values);
358
+ }
359
+ if (!valid)
360
+ continue;
361
+ // Reject the property if any value appears in more than one member.
362
+ const seen = new Set();
363
+ let overlap = false;
364
+ for (const values of valuesByMember.values()) {
365
+ for (const v of values) {
366
+ if (seen.has(v)) {
367
+ overlap = true;
368
+ break;
369
+ }
370
+ seen.add(v);
371
+ }
372
+ if (overlap)
373
+ break;
374
+ }
375
+ if (overlap)
376
+ continue;
377
+ return { propName, valuesByMember };
378
+ }
379
+ return null;
380
+ }
381
+ async extractPropsFromInterface(propsInterface, sourceFile) {
382
+ const props = [];
383
+ // Extract direct properties from interface
384
+ for (const member of propsInterface.members) {
385
+ if (ts.isPropertySignature(member)) {
386
+ const prop = this.extractPropFromMember(member);
387
+ if (prop) {
388
+ // Mark as direct prop
389
+ prop.source = {
390
+ type: 'direct',
391
+ name: propsInterface.name.text
392
+ };
393
+ props.push(prop);
394
+ }
395
+ }
396
+ }
397
+ console.log(`📝 Extracted ${props.length} direct props`);
398
+ // Process heritage clauses (extends/implements)
399
+ if (propsInterface.heritageClauses) {
400
+ console.log(`🔍 Processing ${propsInterface.heritageClauses.length} heritage clauses...`);
401
+ for (const heritageClause of propsInterface.heritageClauses) {
402
+ for (const heritageType of heritageClause.types) {
403
+ const inheritedProps = await this.extractInheritedProps(heritageType, sourceFile);
404
+ props.push(...inheritedProps);
405
+ }
406
+ }
407
+ }
408
+ // Sort props by category and name
409
+ return this.sortProps(props);
410
+ }
411
+ extractPropFromMember(member) {
412
+ const propName = this.getPropertyName(member);
413
+ if (!propName)
414
+ return null;
415
+ // Skip private props if configured
416
+ if (!this.config.includePrivateProps && propName.startsWith('_')) {
417
+ return null;
418
+ }
419
+ const propType = this.getTypeString(member.type);
420
+ const isRequired = this.isPropertyRequired(member);
421
+ // Extract JSDoc information
422
+ let description = `${propName} property`;
423
+ let defaultValue;
424
+ let examples = [];
425
+ let deprecated;
426
+ let seeAlso;
427
+ let experimental = false;
428
+ let since;
429
+ if (this.config.extractJSDoc) {
430
+ const jsDocComment = this.extractJSDocComment(member);
431
+ if (jsDocComment) {
432
+ description = jsDocComment;
433
+ }
434
+ // Extract JSDoc tags
435
+ defaultValue = this.extractJSDocTag(member, 'default');
436
+ since = this.extractJSDocTag(member, 'since');
437
+ // NEW: Extract @see references
438
+ const seeTag = this.extractJSDocTag(member, 'see');
439
+ if (seeTag) {
440
+ seeAlso = seeTag;
441
+ }
442
+ const deprecatedInfo = this.extractJSDocTag(member, 'deprecated');
443
+ if (deprecatedInfo) {
444
+ deprecated = {
445
+ message: deprecatedInfo,
446
+ since: since || ''
447
+ };
448
+ }
449
+ const experimentalInfo = this.extractJSDocTag(member, 'experimental');
450
+ if (experimentalInfo) {
451
+ experimental = true;
452
+ }
453
+ // Extract examples from JSDoc
454
+ examples = this.extractJSDocExamples(member);
455
+ }
456
+ // Extract union values for enum-like types
457
+ const values = member.type ? this.extractUnionValues(member.type) : undefined;
458
+ const prop = {
459
+ name: propName,
460
+ type: propType,
461
+ required: isRequired,
462
+ description,
463
+ source: { type: 'direct' } // Will be updated by caller
464
+ };
465
+ // Add optional fields
466
+ if (defaultValue)
467
+ prop.defaultValue = defaultValue;
468
+ if (values && values.length > 0)
469
+ prop.values = values;
470
+ if (examples && examples.length > 0)
471
+ prop.examples = examples;
472
+ if (deprecated)
473
+ prop.deprecated = deprecated;
474
+ if (experimental)
475
+ prop.experimental = experimental;
476
+ if (since)
477
+ prop.since = since;
478
+ if (seeAlso)
479
+ prop.seeAlso = seeAlso;
480
+ return prop;
481
+ }
482
+ // ==========================================
483
+ // INHERITANCE HANDLING
484
+ // ==========================================
485
+ async extractInheritedProps(heritageType, sourceFile) {
486
+ const typeName = heritageType.expression.getText();
487
+ console.log(`🔍 Processing inheritance from: ${typeName}`);
488
+ // Handle different inheritance patterns
489
+ if (this.isVariantInterface(typeName)) {
490
+ return this.handleVariantInheritance(typeName);
491
+ }
492
+ if (this.isOmitPattern(heritageType)) {
493
+ return this.handleOmitPattern(heritageType, sourceFile);
494
+ }
495
+ if (this.isHTMLAttributes(typeName)) {
496
+ return this.handleHTMLAttributes(typeName);
497
+ }
498
+ // Try to find local interface
499
+ const localInterface = this.findInterface(sourceFile, typeName);
500
+ if (localInterface) {
501
+ return this.extractPropsFromLocalInterface(localInterface, typeName);
502
+ }
503
+ // Create placeholder for unknown inheritance
504
+ console.log(`❓ Creating placeholder for unknown inheritance: ${typeName}`);
505
+ return [
506
+ {
507
+ name: `...${typeName}`,
508
+ type: 'inherited',
509
+ required: false,
510
+ description: `Properties inherited from ${typeName}`,
511
+ source: {
512
+ type: 'inherited',
513
+ name: typeName,
514
+ package: this.getPackageForType(typeName) || ''
515
+ }
516
+ }
517
+ ];
518
+ }
519
+ handleVariantInheritance(typeName) {
520
+ // This will be handled by VariantsExtractor in the coordination phase
521
+ console.log(`🎨 Variant inheritance detected: ${typeName} - will be processed by VariantsExtractor`);
522
+ return [
523
+ {
524
+ name: `...${typeName}`,
525
+ type: 'VariantProps',
526
+ required: false,
527
+ description: `Styling variants from ${typeName}`,
528
+ source: {
529
+ type: 'variant',
530
+ name: typeName
531
+ }
532
+ }
533
+ ];
534
+ }
535
+ handleOmitPattern(heritageType, sourceFile) {
536
+ const fullType = heritageType.getText();
537
+ // Omit pattern detected; filter extracted props based on omitted keys
538
+ // Extract base type and omitted keys
539
+ const match = fullType.match(/Omit<([^,]+),\s*([^>]+)>/);
540
+ if (match?.[1] && match[2]) {
541
+ const baseType = match[1].trim();
542
+ const omittedKeys = match[2].trim();
543
+ if (this.isHTMLAttributes(baseType)) {
544
+ return [
545
+ {
546
+ name: `...${baseType}`,
547
+ type: 'HTMLAttributes',
548
+ required: false,
549
+ description: `HTML attributes${omittedKeys ? ` (excluding: ${omittedKeys})` : ''}`,
550
+ source: {
551
+ type: 'inherited',
552
+ name: fullType,
553
+ package: 'svelte/elements'
554
+ }
555
+ }
556
+ ];
557
+ }
558
+ // *Variants type alias — `findInterface` returns null because
559
+ // *Variants is a `type` alias over `VariantProps<typeof xVariants>`,
560
+ // not an interface. Emit the variant-inheritance placeholder AND
561
+ // omit-markers for each literal-string key in the omitted list.
562
+ // APIDataGenerator filters those markers (and the named keys) out
563
+ // of the final variant-props list so they don't leak into the
564
+ // public API table.
565
+ if (this.isVariantInterface(baseType)) {
566
+ const result = this.handleVariantInheritance(baseType);
567
+ const literalKeys = this.extractOmittedLiteralKeys(omittedKeys);
568
+ for (const key of literalKeys) {
569
+ result.push({
570
+ name: `__OMIT_VARIANT__${key}`,
571
+ type: 'omit-marker',
572
+ required: false,
573
+ description: `Suppress variant prop "${key}" from the public API surface (declared via Omit<${baseType}, ...>).`,
574
+ source: { type: 'inherited', name: fullType }
575
+ });
576
+ }
577
+ return result;
578
+ }
579
+ // Local interface Omit pattern, e.g., Omit<MenuSpecificProps, keyof MenuVariants>
580
+ const localInterface = this.findInterface(sourceFile, baseType);
581
+ if (localInterface) {
582
+ // Extract props from the local interface
583
+ const extracted = this.extractPropsFromLocalInterface(localInterface, baseType);
584
+ // If omittedKeys references keyof Variants, exclude variant keys provided by VariantsExtractor
585
+ const shouldExcludeVariantKeys = /keyof\s+\w*Variants/.test(omittedKeys);
586
+ const variantKeyBlacklist = shouldExcludeVariantKeys
587
+ ? new Set(this.currentVariantKeys)
588
+ : new Set();
589
+ return extracted
590
+ .filter((p) => !variantKeyBlacklist.has(p.name))
591
+ .map((p) => ({
592
+ ...p,
593
+ source: {
594
+ type: 'inherited',
595
+ name: fullType
596
+ }
597
+ }));
598
+ }
599
+ }
600
+ return [];
601
+ }
602
+ handleHTMLAttributes(typeName) {
603
+ const elementType = this.extractElementType(typeName);
604
+ return [
605
+ {
606
+ name: `...${elementType}Attributes`,
607
+ type: 'HTMLAttributes',
608
+ required: false,
609
+ description: `All standard HTML ${elementType.toLowerCase()} attributes`,
610
+ source: {
611
+ type: 'inherited',
612
+ name: typeName,
613
+ package: 'svelte/elements',
614
+ url: `https://developer.mozilla.org/en-US/docs/Web/HTML/Element/${elementType.toLowerCase()}`
615
+ }
616
+ }
617
+ ];
618
+ }
619
+ extractPropsFromLocalInterface(localInterface, interfaceName) {
620
+ const props = [];
621
+ for (const member of localInterface.members) {
622
+ if (ts.isPropertySignature(member)) {
623
+ const prop = this.extractPropFromMember(member);
624
+ if (prop) {
625
+ prop.source = {
626
+ type: 'inherited',
627
+ name: interfaceName
628
+ };
629
+ props.push(prop);
630
+ }
631
+ }
632
+ }
633
+ // extracted local interface props
634
+ return props;
635
+ }
636
+ // ==========================================
637
+ // UTILITY METHODS
638
+ // ==========================================
639
+ isVariantInterface(typeName) {
640
+ return typeName.endsWith('Variants') || typeName.endsWith('VariantProps');
641
+ }
642
+ isOmitPattern(heritageType) {
643
+ return heritageType.expression.getText().startsWith('Omit');
644
+ }
645
+ /**
646
+ * Parse the keys argument of `Omit<X, K>` into a flat string-literal list.
647
+ * Handles `'a'`, `'a' | 'b' | 'c'`, double-quoted, and ignores `keyof T`
648
+ * patterns (those are handled separately via `currentVariantKeys`).
649
+ */
650
+ extractOmittedLiteralKeys(omittedKeys) {
651
+ return Array.from(omittedKeys.matchAll(/['"]([A-Za-z_$][A-Za-z0-9_$]*)['"]/g))
652
+ .map((m) => m[1])
653
+ .filter((k) => Boolean(k));
654
+ }
655
+ isHTMLAttributes(typeName) {
656
+ return typeName.includes('HTML') && typeName.includes('Attributes');
657
+ }
658
+ extractElementType(typeName) {
659
+ const match = typeName.match(/HTML(\w+)Attributes/);
660
+ return match?.[1] ? match[1] : 'Element';
661
+ }
662
+ getPackageForType(typeName) {
663
+ const packageMap = {
664
+ Snippet: 'svelte',
665
+ ComponentEvents: 'svelte',
666
+ MintProp: '@urbicon-ui/blocks',
667
+ ComponentIntent: '@urbicon-ui/blocks',
668
+ ComponentSize: '@urbicon-ui/blocks'
669
+ };
670
+ return packageMap[typeName];
671
+ }
672
+ extractJSDocExamples(member) {
673
+ const examples = [];
674
+ // Extract @example tags
675
+ const jsDocTags = ts.getJSDocTags(member);
676
+ let exampleCount = 1;
677
+ for (const tag of jsDocTags) {
678
+ if (tag.tagName.text === 'example' && tag.comment) {
679
+ const exampleText = this.getCommentText(tag.comment);
680
+ examples.push({
681
+ title: `Example ${exampleCount}`,
682
+ code: exampleText,
683
+ description: `Usage example for ${this.getPropertyName(member)}`
684
+ });
685
+ exampleCount++;
686
+ }
687
+ }
688
+ return examples;
689
+ }
690
+ sortProps(props) {
691
+ return props.sort((a, b) => {
692
+ // Within same category, sort required props first
693
+ if (a.required && !b.required)
694
+ return -1;
695
+ if (!a.required && b.required)
696
+ return 1;
697
+ // Finally, sort alphabetically
698
+ return a.name.localeCompare(b.name);
699
+ });
700
+ }
701
+ // ✅ Removed duplicate getCommentText method - now inherited from TypeScriptBaseExtractor
702
+ /**
703
+ * Clear any caches
704
+ */
705
+ clearCache() {
706
+ // No persistent cache in this implementation
707
+ }
708
+ }
709
+ //# sourceMappingURL=PropsExtractor.js.map