Skip to content

Commit 3dec210

Browse files
authored
refactor(LLMs): improve generator tools (#889)
* refactor: 更新命名空间 * refactor: 精简逻辑 * chore: bump version 10.0.1
1 parent 8475d1a commit 3dec210

8 files changed

Lines changed: 112 additions & 303 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
// Website: https://www.blazor.zone
4+
5+
using BootstrapBlazorLLMsDocsGenerator;
6+
using System.CommandLine;
7+
8+
namespace BootstrapBlazor.LLMsDocsGenerator;
9+
10+
internal static class ArgumentsHelper
11+
{
12+
public static ParseResult Parse(string[] args)
13+
{
14+
var rootFolderOption = new Option<string?>("--root") { Description = "Set the root folder of project" };
15+
16+
var rootCommand = new RootCommand("BootstrapBlazor LLMs Documentation Generator")
17+
{
18+
rootFolderOption
19+
};
20+
21+
rootCommand.SetAction(async result =>
22+
{
23+
var rootFolder = result.GetValue(rootFolderOption);
24+
if (string.IsNullOrEmpty(rootFolder))
25+
{
26+
return;
27+
}
28+
29+
await DocsGenerator.GenerateAllAsync(rootFolder);
30+
});
31+
32+
return rootCommand.Parse(args);
33+
}
34+
}

tools/BootstrapBlazor.LLMsDocsGenerator/BootstrapBlazor.LLMsDocsGenerator.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<Version>10.0.0</Version>
4+
<Version>10.0.1</Version>
55
<OutputType>Exe</OutputType>
66
<TargetFramework>net10.0</TargetFramework>
77
<ImplicitUsings>enable</ImplicitUsings>
88
<Nullable>enable</Nullable>
9+
<SatelliteResourceLanguages>false</SatelliteResourceLanguages>
910
</PropertyGroup>
1011

1112
<PropertyGroup>

tools/BootstrapBlazor.LLMsDocsGenerator/ComponentAnalyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
using Microsoft.CodeAnalysis.CSharp.Syntax;
99
using System.Text.RegularExpressions;
1010

11-
namespace LlmsDocsGenerator;
11+
namespace BootstrapBlazorLLMsDocsGenerator;
1212

1313
/// <summary>
1414
/// Analyzes Blazor component source files using Roslyn

tools/BootstrapBlazor.LLMsDocsGenerator/ComponentInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
55

6-
namespace LlmsDocsGenerator;
6+
namespace BootstrapBlazorLLMsDocsGenerator;
77

88
/// <summary>
99
/// Represents information about a Blazor component

tools/BootstrapBlazor.LLMsDocsGenerator/DocsGenerator.cs

Lines changed: 22 additions & 207 deletions
Original file line numberDiff line numberDiff line change
@@ -3,241 +3,56 @@
33
// See the LICENSE file in the project root for more information.
44
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
55

6-
namespace LlmsDocsGenerator;
6+
namespace BootstrapBlazorLLMsDocsGenerator;
77

8-
/// <summary>
9-
/// Main documentation generator class
10-
/// </summary>
11-
public class DocsGenerator
8+
internal static class DocsGenerator
129
{
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-
5710
/// <summary>
5811
/// Generate all documentation files
5912
/// </summary>
60-
public async Task GenerateAllAsync()
13+
public static async Task GenerateAllAsync(string rootFolder)
6114
{
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+
6219
Logger($"Source path: {_sourcePath}");
6320
Logger($"Output path: {_outputPath}");
6421
Logger($"Components path: {_componentsOutputPath}");
6522

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))
8124
{
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}");
11725
return;
11826
}
11927

120-
// Ensure output directory exists
28+
Directory.CreateDirectory(_outputPath);
12129
Directory.CreateDirectory(_componentsOutputPath);
12230

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...");
14132

33+
var _analyzer = new ComponentAnalyzer(_sourcePath);
14234
var components = await _analyzer.AnalyzeAllComponentsAsync();
35+
Logger($"Found {components.Count} components");
14336

144-
// Check index file
14537
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}");
16541

166-
// Check each component file
42+
Logger("Generating individual component documentation...");
16743
foreach (var component in components)
16844
{
45+
content = MarkdownBuilder.BuildComponentDoc(component);
16946
var fileName = $"{component.Name}.txt";
17047
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}");
18550
}
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!");
23452
}
23553

236-
private void Logger(string message)
54+
private static void Logger(string message)
23755
{
238-
if (_debug)
239-
{
240-
Console.WriteLine(message);
241-
}
56+
Console.WriteLine(message);
24257
}
24358
}

0 commit comments

Comments
 (0)