XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEToolBox

【WPF】XFE工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;

namespace XFEToolBox.Core.Tools;

/// <summary>
/// Describes the source files and metadata contained in an .xfetool package.
/// </summary>
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; }

    /// <summary>
    /// Optional short subtitle shown below the tool name in the standalone window title bar.
    /// When omitted, the host falls back to the package description.
    /// </summary>
    public string? Subtitle { get; init; }

    public required string Version { get; init; }

    public required string Description { get; init; }

    public required string Author { get; init; }

    /// <summary>
    /// Optional package-relative path to a PNG, JPEG, GIF, BMP or ICO icon.
    /// </summary>
    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; }

    /// <summary>
    /// Exact NuGet package references restored when this tool is compiled.
    /// Package versions are intentionally pinned so a published tool remains reproducible.
    /// </summary>
    [JsonPropertyName("nugetPackages")]
    public ToolNuGetPackageReference[] NuGetPackages { get; init; } = [];

    /// <summary>
    /// Requires the host to display elevation state and launch this tool through Windows UAC.
    /// Users cannot override this requirement with a per-tool preference.
    /// </summary>
    public bool RequiresAdministrator { get; init; }

    public required ToolEntryManifest Entry { get; init; }

    /// <summary>
    /// Controls the standalone host window used when the tool is launched.
    /// Older packages that do not contain this section automatically use these defaults.
    /// </summary>
    public ToolWindowManifest Window { get; init; } = new();

    /// <summary>
    /// 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.
    /// </summary>
    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;

    /// <summary>
    /// Allows maximizing by double-clicking the shared drag handle. The title bar never adds a separate maximize button.
    /// </summary>
    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; }
}