|
3 | 3 | // See the LICENSE file in the project root for more information. |
4 | 4 | // Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone |
5 | 5 |
|
6 | | -namespace LlmsDocsGenerator; |
| 6 | +namespace BootstrapBlazorLLMsDocsGenerator; |
7 | 7 |
|
8 | | -/// <summary> |
9 | | -/// Main documentation generator class |
10 | | -/// </summary> |
11 | | -public class DocsGenerator |
| 8 | +internal static class DocsGenerator |
12 | 9 | { |
13 | | - private readonly string _outputPath; |
14 | | - private readonly string _componentsOutputPath; |
15 | | - private readonly string _sourcePath; |
16 | | - private readonly ComponentAnalyzer _analyzer; |
17 | | - private readonly MarkdownBuilder _markdownBuilder; |
18 | | - private readonly bool _debug; |
19 | | - |
20 | | - public DocsGenerator(string? rootFolder, bool debug) |
21 | | - { |
22 | | - _debug = debug; |
23 | | - |
24 | | - // Find the source directory (relative to tool location or current directory) |
25 | | - var root = FindSourcePath(rootFolder); |
26 | | - |
27 | | - _sourcePath = Path.Combine(root, "src", "BootstrapBlazor"); |
28 | | - _outputPath = Path.Combine(root, "src", "BootstrapBlazor.Server", "wwwroot", "llms"); |
29 | | - _componentsOutputPath = Path.Combine(_outputPath, "components"); |
30 | | - _analyzer = new ComponentAnalyzer(_sourcePath); |
31 | | - _markdownBuilder = new MarkdownBuilder(); |
32 | | - } |
33 | | - |
34 | | - private string FindSourcePath(string? rootFolder) |
35 | | - { |
36 | | - // Try to find src/BootstrapBlazor from current directory or parent directories |
37 | | - var current = rootFolder ?? AppContext.BaseDirectory; |
38 | | - Logger($"Root path: {current}"); |
39 | | - |
40 | | - while (!string.IsNullOrEmpty(current)) |
41 | | - { |
42 | | - var parent = Directory.GetParent(current); |
43 | | - if (parent == null) |
44 | | - { |
45 | | - break; |
46 | | - } |
47 | | - if (parent.Name.Equals("BootstrapBlazor", StringComparison.OrdinalIgnoreCase)) |
48 | | - { |
49 | | - return parent.FullName; |
50 | | - } |
51 | | - current = parent.FullName; |
52 | | - } |
53 | | - |
54 | | - throw new DirectoryNotFoundException("Could not find src directory. Please run this tool from the BootstrapBlazor repository root."); |
55 | | - } |
56 | | - |
57 | 10 | /// <summary> |
58 | 11 | /// Generate all documentation files |
59 | 12 | /// </summary> |
60 | | - public async Task GenerateAllAsync() |
| 13 | + public static async Task GenerateAllAsync(string rootFolder) |
61 | 14 | { |
| 15 | + var _sourcePath = Path.Combine(rootFolder, "..", "BootstrapBlazor"); |
| 16 | + var _outputPath = Path.Combine(rootFolder, "bin", "Release", "net10.0", "publish", "wwwroot", "llms"); |
| 17 | + var _componentsOutputPath = Path.Combine(_outputPath, "components"); |
| 18 | + |
62 | 19 | Logger($"Source path: {_sourcePath}"); |
63 | 20 | Logger($"Output path: {_outputPath}"); |
64 | 21 | Logger($"Components path: {_componentsOutputPath}"); |
65 | 22 |
|
66 | | - // Ensure output directories exist |
67 | | - Directory.CreateDirectory(_outputPath); |
68 | | - Directory.CreateDirectory(_componentsOutputPath); |
69 | | - |
70 | | - // Analyze all components |
71 | | - Logger("Analyzing components..."); |
72 | | - var components = await _analyzer.AnalyzeAllComponentsAsync(); |
73 | | - Logger($"Found {components.Count} components"); |
74 | | - |
75 | | - // Generate index file |
76 | | - await GenerateIndexAsync(components); |
77 | | - |
78 | | - // Generate individual component documentation files |
79 | | - Logger("Generating individual component documentation..."); |
80 | | - foreach (var component in components) |
| 23 | + if (!Directory.Exists(_sourcePath)) |
81 | 24 | { |
82 | | - await GenerateComponentDocAsync(component); |
83 | | - } |
84 | | - |
85 | | - Logger("Documentation generation complete!"); |
86 | | - } |
87 | | - |
88 | | - /// <summary> |
89 | | - /// Generate only the index file |
90 | | - /// </summary> |
91 | | - public async Task GenerateIndexAsync() |
92 | | - { |
93 | | - var components = await _analyzer.AnalyzeAllComponentsAsync(); |
94 | | - await GenerateIndexAsync(components); |
95 | | - } |
96 | | - |
97 | | - private async Task GenerateIndexAsync(List<ComponentInfo> components) |
98 | | - { |
99 | | - // Ensure output directory exists |
100 | | - Directory.CreateDirectory(_outputPath); |
101 | | - |
102 | | - var indexPath = Path.Combine(_outputPath, "llms.txt"); |
103 | | - var content = _markdownBuilder.BuildIndex(components); |
104 | | - await File.WriteAllTextAsync(indexPath, content); |
105 | | - Logger($"Generated: {indexPath}"); |
106 | | - } |
107 | | - |
108 | | - /// <summary> |
109 | | - /// Generate documentation for a specific component |
110 | | - /// </summary> |
111 | | - public async Task GenerateComponentAsync(string componentName) |
112 | | - { |
113 | | - var component = await _analyzer.AnalyzeComponentAsync(componentName); |
114 | | - if (component == null) |
115 | | - { |
116 | | - Logger($"Component not found: {componentName}"); |
117 | 25 | return; |
118 | 26 | } |
119 | 27 |
|
120 | | - // Ensure output directory exists |
| 28 | + Directory.CreateDirectory(_outputPath); |
121 | 29 | Directory.CreateDirectory(_componentsOutputPath); |
122 | 30 |
|
123 | | - await GenerateComponentDocAsync(component); |
124 | | - } |
125 | | - |
126 | | - private async Task GenerateComponentDocAsync(ComponentInfo component) |
127 | | - { |
128 | | - var content = _markdownBuilder.BuildComponentDoc(component); |
129 | | - var fileName = $"{component.Name}.txt"; |
130 | | - var filePath = Path.Combine(_componentsOutputPath, fileName); |
131 | | - await File.WriteAllTextAsync(filePath, content); |
132 | | - Logger($"Generated: {filePath}"); |
133 | | - } |
134 | | - |
135 | | - /// <summary> |
136 | | - /// Check if documentation is up-to-date |
137 | | - /// </summary> |
138 | | - public async Task<bool> CheckAsync() |
139 | | - { |
140 | | - Logger("Checking documentation freshness..."); |
| 31 | + Logger("Analyzing components..."); |
141 | 32 |
|
| 33 | + var _analyzer = new ComponentAnalyzer(_sourcePath); |
142 | 34 | var components = await _analyzer.AnalyzeAllComponentsAsync(); |
| 35 | + Logger($"Found {components.Count} components"); |
143 | 36 |
|
144 | | - // Check index file |
145 | 37 | var indexPath = Path.Combine(_outputPath, "llms.txt"); |
146 | | - if (!File.Exists(indexPath)) |
147 | | - { |
148 | | - Logger("OUTDATED: llms.txt does not exist"); |
149 | | - return false; |
150 | | - } |
151 | | - |
152 | | - var indexLastWrite = File.GetLastWriteTimeUtc(indexPath); |
153 | | - |
154 | | - // compute the most recent component source timestamp: |
155 | | - var newestComponentWrite = components |
156 | | - .Select(c => c.LastModified) |
157 | | - .DefaultIfEmpty(indexLastWrite) |
158 | | - .Max(); |
159 | | - |
160 | | - if (indexLastWrite < newestComponentWrite) |
161 | | - { |
162 | | - Logger("Index file is stale relative to component sources. Please regenerate docs."); |
163 | | - return false; |
164 | | - } |
| 38 | + var content = MarkdownBuilder.BuildIndexDoc(components); |
| 39 | + await File.WriteAllTextAsync(indexPath, content); |
| 40 | + Logger($"Generated: {indexPath}"); |
165 | 41 |
|
166 | | - // Check each component file |
| 42 | + Logger("Generating individual component documentation..."); |
167 | 43 | foreach (var component in components) |
168 | 44 | { |
| 45 | + content = MarkdownBuilder.BuildComponentDoc(component); |
169 | 46 | var fileName = $"{component.Name}.txt"; |
170 | 47 | var filePath = Path.Combine(_componentsOutputPath, fileName); |
171 | | - |
172 | | - if (!File.Exists(filePath)) |
173 | | - { |
174 | | - Logger($"OUTDATED: {fileName} does not exist"); |
175 | | - return false; |
176 | | - } |
177 | | - |
178 | | - // Check if source file is newer than the doc file |
179 | | - var docLastWrite = File.GetLastWriteTimeUtc(filePath); |
180 | | - if (component.LastModified > docLastWrite) |
181 | | - { |
182 | | - Logger($"OUTDATED: {component.Name} was modified after {fileName}"); |
183 | | - return false; |
184 | | - } |
| 48 | + await File.WriteAllTextAsync(filePath, content); |
| 49 | + Logger($"Generated: {filePath}"); |
185 | 50 | } |
186 | | - |
187 | | - Logger("Documentation is up-to-date"); |
188 | | - return true; |
189 | | - } |
190 | | - |
191 | | - private static string GetComponentCategory(string componentName) |
192 | | - { |
193 | | - return componentName.ToLowerInvariant() switch |
194 | | - { |
195 | | - // Table family |
196 | | - var n when n.Contains("table") => "table", |
197 | | - |
198 | | - // Input family |
199 | | - var n when n.Contains("input") || n.Contains("textarea") || |
200 | | - n.Contains("password") || n == "otpinput" => "input", |
201 | | - |
202 | | - // Select family |
203 | | - var n when n.Contains("select") || n.Contains("dropdown") || |
204 | | - n.Contains("autocomplete") || n.Contains("cascader") || |
205 | | - n.Contains("transfer") || n.Contains("multiselect") => "select", |
206 | | - |
207 | | - // Button family |
208 | | - var n when n.Contains("button") || n == "gotop" || |
209 | | - n.Contains("popconfirm") => "button", |
210 | | - |
211 | | - // Dialog family |
212 | | - var n when n.Contains("dialog") || n.Contains("modal") || |
213 | | - n.Contains("drawer") || n.Contains("swal") || |
214 | | - n.Contains("toast") || n.Contains("message") => "dialog", |
215 | | - |
216 | | - // Navigation family |
217 | | - var n when n.Contains("menu") || n.Contains("tab") || |
218 | | - n.Contains("breadcrumb") || n.Contains("step") || |
219 | | - n.Contains("anchor") || n.Contains("nav") => "nav", |
220 | | - |
221 | | - // Card/Container family |
222 | | - var n when n.Contains("card") || n.Contains("collapse") || |
223 | | - n.Contains("groupbox") || n.Contains("panel") => "card", |
224 | | - |
225 | | - // TreeView |
226 | | - var n when n.Contains("tree") => "treeview", |
227 | | - |
228 | | - // Form |
229 | | - var n when n.Contains("validateform") || n.Contains("editorform") || |
230 | | - n.Contains("validator") => "form", |
231 | | - |
232 | | - _ => "other" |
233 | | - }; |
| 51 | + Logger("Documentation generation complete!"); |
234 | 52 | } |
235 | 53 |
|
236 | | - private void Logger(string message) |
| 54 | + private static void Logger(string message) |
237 | 55 | { |
238 | | - if (_debug) |
239 | | - { |
240 | | - Console.WriteLine(message); |
241 | | - } |
| 56 | + Console.WriteLine(message); |
242 | 57 | } |
243 | 58 | } |
0 commit comments