mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-20 15:52:17 +08:00
159 lines
6.2 KiB
C#
159 lines
6.2 KiB
C#
using AtomUI.Docs.LLMsGenerator.Config;
|
|
|
|
namespace AtomUI.Docs.LLMsGenerator.Catalog;
|
|
|
|
public static class ControlInventory
|
|
{
|
|
public const string DefaultOutputRoot = "docs/AI/generated/llms";
|
|
public const string DefaultLanguage = "cn";
|
|
|
|
public static IReadOnlyList<ControlDocumentInfo> Discover(
|
|
string repositoryRoot,
|
|
LLMsControlSetConfig controlSet,
|
|
string outputRoot = DefaultOutputRoot,
|
|
string language = DefaultLanguage)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(repositoryRoot))
|
|
{
|
|
throw new ArgumentException("Repository root is required.", nameof(repositoryRoot));
|
|
}
|
|
|
|
ArgumentNullException.ThrowIfNull(controlSet);
|
|
|
|
var docsRoot = ResolvePath(repositoryRoot, controlSet.DocsRoot);
|
|
if (!Directory.Exists(docsRoot))
|
|
{
|
|
throw new DirectoryNotFoundException($"Control docs root was not found: {docsRoot}");
|
|
}
|
|
|
|
var categoryDirectories = Directory.GetDirectories(docsRoot)
|
|
.Where(directory => !IsHidden(directory))
|
|
.Select(directory => new
|
|
{
|
|
Name = Path.GetFileName(directory),
|
|
Path = directory
|
|
})
|
|
.Where(directory => !string.IsNullOrWhiteSpace(directory.Name))
|
|
.ToDictionary(
|
|
directory => directory.Name!,
|
|
directory => directory.Path,
|
|
StringComparer.Ordinal);
|
|
|
|
var orderedCategoryNames = GetOrderedCategories(categoryDirectories.Keys, controlSet.CategoryOrder);
|
|
var controls = new List<ControlDocumentInfo>();
|
|
|
|
foreach (var categoryName in orderedCategoryNames)
|
|
{
|
|
var categoryDirectory = categoryDirectories[categoryName];
|
|
var controlDirectories = Directory.GetDirectories(categoryDirectory)
|
|
.Where(directory => !IsHidden(directory))
|
|
.OrderBy(Path.GetFileName, StringComparer.Ordinal);
|
|
|
|
foreach (var controlDirectory in controlDirectories)
|
|
{
|
|
var controlName = Path.GetFileName(controlDirectory);
|
|
if (string.IsNullOrWhiteSpace(controlName))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
controls.Add(new ControlDocumentInfo
|
|
{
|
|
ControlSetId = controlSet.Id,
|
|
Platform = controlSet.Platform,
|
|
Category = categoryName,
|
|
Name = controlName,
|
|
DirectoryPath = controlDirectory,
|
|
GalleryRoot = ResolvePath(repositoryRoot, controlSet.GalleryRoot),
|
|
SourceRoots = controlSet.SourceRoots
|
|
.Select(sourceRoot => ResolvePath(repositoryRoot, sourceRoot))
|
|
.ToArray(),
|
|
OverviewPath = Path.Combine(controlDirectory, "overview.md"),
|
|
ImplementationPath = Path.Combine(controlDirectory, "implementation.md"),
|
|
TokenPath = GetOptionalFilePath(controlDirectory, "token.md"),
|
|
ChangelogPath = Path.Combine(controlDirectory, "changelog.md"),
|
|
OutputIndexPath = BuildOutputPath(outputRoot, controlName, $"index-{language}.md"),
|
|
OutputSemanticPath = BuildOutputPath(outputRoot, controlName, $"semantic-{language}.md")
|
|
});
|
|
}
|
|
}
|
|
|
|
return controls;
|
|
}
|
|
|
|
private static IReadOnlyList<string> GetOrderedCategories(
|
|
IEnumerable<string?> categoryNames,
|
|
IReadOnlyList<string> configuredOrder)
|
|
{
|
|
var availableCategories = categoryNames
|
|
.Where(name => !string.IsNullOrWhiteSpace(name))
|
|
.Select(name => name!)
|
|
.ToHashSet(StringComparer.Ordinal);
|
|
|
|
var orderedCategories = new List<string>();
|
|
foreach (var categoryName in configuredOrder)
|
|
{
|
|
if (availableCategories.Remove(categoryName))
|
|
{
|
|
orderedCategories.Add(categoryName);
|
|
}
|
|
}
|
|
|
|
orderedCategories.AddRange(availableCategories.OrderBy(name => name, StringComparer.Ordinal));
|
|
return orderedCategories;
|
|
}
|
|
|
|
private static string? GetOptionalFilePath(string directory, string fileName)
|
|
{
|
|
var path = Path.Combine(directory, fileName);
|
|
return File.Exists(path) ? path : null;
|
|
}
|
|
|
|
private static string BuildOutputPath(string outputRoot, string controlName, string fileName)
|
|
{
|
|
return string.Join("/", outputRoot.TrimEnd('/'), "controls", controlName, fileName);
|
|
}
|
|
|
|
private static string ResolvePath(string repositoryRoot, string path)
|
|
{
|
|
return Path.IsPathFullyQualified(path)
|
|
? Path.GetFullPath(path)
|
|
: Path.GetFullPath(Path.Combine(repositoryRoot, path));
|
|
}
|
|
|
|
private static bool IsHidden(string directory)
|
|
{
|
|
var name = Path.GetFileName(directory);
|
|
return name.StartsWith(".", StringComparison.Ordinal);
|
|
}
|
|
}
|
|
|
|
public sealed class ControlDocumentInfo
|
|
{
|
|
public string ControlSetId { get; init; } = string.Empty;
|
|
|
|
public string Platform { get; init; } = string.Empty;
|
|
|
|
public string Category { get; init; } = string.Empty;
|
|
|
|
public string Name { get; init; } = string.Empty;
|
|
|
|
public string DirectoryPath { get; init; } = string.Empty;
|
|
|
|
public string GalleryRoot { get; init; } = string.Empty;
|
|
|
|
public IReadOnlyList<string> SourceRoots { get; init; } = [];
|
|
|
|
public string OverviewPath { get; init; } = string.Empty;
|
|
|
|
public string ImplementationPath { get; init; } = string.Empty;
|
|
|
|
public string? TokenPath { get; init; }
|
|
|
|
public string ChangelogPath { get; init; } = string.Empty;
|
|
|
|
public string OutputIndexPath { get; init; } = string.Empty;
|
|
|
|
public string OutputSemanticPath { get; init; } = string.Empty;
|
|
}
|