using System.Text.Json.Serialization; using System.Text.RegularExpressions; namespace XFEToolBox.Core.Tools; /// /// Describes the source files and metadata contained in an .xfetool package. /// public sealed class ToolPackageManifest { public const int CurrentPackageFormatVersion = 1; public int PackageFormatVersion { get; init; } = CurrentPackageFormatVersion; public required string Id { get; init; } public required string Name { get; init; } /// /// Optional short subtitle shown below the tool name in the standalone window title bar. /// When omitted, the host falls back to the package description. /// public string? Subtitle { get; init; } public required string Version { get; init; } public required string Description { get; init; } public required string Author { get; init; } /// /// Optional package-relative path to a PNG, JPEG, GIF, BMP or ICO icon. /// public string? Icon { get; init; } public string Category { get; init; } = "其他"; public string[] Tags { get; init; } = []; public string? MinimumHostVersion { get; init; } public string? ReleaseNotes { get; init; } /// /// Exact NuGet package references restored when this tool is compiled. /// Package versions are intentionally pinned so a published tool remains reproducible. /// [JsonPropertyName("nugetPackages")] public ToolNuGetPackageReference[] NuGetPackages { get; init; } = []; /// /// Requires the host to display elevation state and launch this tool through Windows UAC. /// Users cannot override this requirement with a per-tool preference. /// public bool RequiresAdministrator { get; init; } public required ToolEntryManifest Entry { get; init; } /// /// Controls the standalone host window used when the tool is launched. /// Older packages that do not contain this section automatically use these defaults. /// public ToolWindowManifest Window { get; init; } = new(); /// /// Optional host capabilities requested by the tool, such as clipboard or network. /// The host must still ask the user or enforce its own policy before granting them. /// public string[] RequestedPermissions { get; init; } = []; } public sealed class ToolNuGetPackageReference { public required string Id { get; init; } public required string Version { get; init; } } public static partial class ToolNuGetPackageRules { public const int MaximumPackageCount = 64; public const int MaximumPackageIdLength = 100; public const int MaximumVersionLength = 64; public static bool IsValidPackageId(string? value) => !string.IsNullOrWhiteSpace(value) && value.Length <= MaximumPackageIdLength && PackageIdRegex().IsMatch(value); public static bool IsValidExactVersion(string? value) => !string.IsNullOrWhiteSpace(value) && value.Length <= MaximumVersionLength && ExactVersionRegex().IsMatch(value); [GeneratedRegex("^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,98}[A-Za-z0-9])?$")] private static partial Regex PackageIdRegex(); [GeneratedRegex("^[0-9]+(?:\\.[0-9]+){0,3}(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$")] private static partial Regex ExactVersionRegex(); } public sealed class ToolWindowManifest { public const double DefaultWidth = 760; public const double DefaultHeight = 560; public const double DefaultMinWidth = 420; public const double DefaultMinHeight = 300; public double Width { get; init; } = DefaultWidth; public double Height { get; init; } = DefaultHeight; public double MinWidth { get; init; } = DefaultMinWidth; public double MinHeight { get; init; } = DefaultMinHeight; public bool AllowResize { get; init; } = true; /// /// Allows maximizing by double-clicking the shared drag handle. The title bar never adds a separate maximize button. /// public bool AllowMaximize { get; init; } = true; public bool ShowMinimizeButton { get; init; } = true; public bool ShowCloseButton { get; init; } = true; } public sealed class ToolEntryManifest { public required string ViewXaml { get; init; } public required string ViewClass { get; init; } public required string ViewCodeBehind { get; init; } public string? ViewModel { get; init; } public string? ViewModelClass { get; init; } }