diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 00000000..3c0721e4 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,19 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "csharpier": { + "version": "1.2.1", + "commands": [ + "csharpier" + ], + "rollForward": false + }, + "jetbrains.resharper.globaltools": { + "version": "2025.2.4", + "commands": [ + "jb" + ] + } + } +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..4759af6a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,189 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# All files +[*] +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space + +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 +end_of_line = lf + +# XML project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 2 + +# XML config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 2 + +# JSON files +[*.json] +indent_size = 2 + +# YAML files +[*.{yml,yaml}] +indent_size = 2 + +# Markdown files +[*.md] +trim_trailing_whitespace = false + +# Shell scripts +[*.sh] +end_of_line = lf + +# Batch files +[*.{cmd,bat}] +end_of_line = crlf + +# TypeScript/JavaScript files +[*.{ts,tsx,js,jsx}] +indent_size = 2 +end_of_line = lf + +# C# files +[*.cs] + +# New line preferences +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = one_less_than_current +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents_when_block = false + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_parentheses = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_after_comma = true +csharp_space_before_comma = false +csharp_space_after_dot = false +csharp_space_before_dot = false +csharp_space_after_semicolon_in_for_statement = true +csharp_space_before_semicolon_in_for_statement = false +csharp_space_around_declaration_statements = false +csharp_space_before_open_square_brackets = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_square_brackets = false + +# Organize usings +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false + +# Code style rules +csharp_prefer_braces = true:suggestion +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_static_local_function = true:suggestion +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_pattern_matching = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_style_var_for_built_in_types = false:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = false:suggestion + +# Expression preferences +csharp_style_inlined_variable_declaration = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion + +# Null checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion + +# Modifier preferences +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion + +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion + +# Null checking preferences +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion + +# File header +file_header_template = unset + +# Naming conventions +dotnet_naming_rule.interfaces_should_be_prefixed_with_i.severity = warning +dotnet_naming_rule.interfaces_should_be_prefixed_with_i.symbols = interface +dotnet_naming_rule.interfaces_should_be_prefixed_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = warning +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = warning +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none diff --git a/.github/scripts/install_deps.sh b/.github/scripts/install_deps.sh old mode 100644 new mode 100755 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2d4942ab..d4e00160 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -60,6 +60,23 @@ jobs: fi echo "Generated version: $VERSION" + lint-and-format: + name: Lint and Format Check + needs: prepare + timeout-minutes: 10 + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v5 + - name: Setup Environment + uses: ./.github/actions/setup-environment + with: + install-build-tools: "false" + - name: Check C# formatting + run: make format-check-csharp + - name: Check TypeScript/JavaScript formatting and linting + run: make format-check-typescript lint-typescript + test: name: Run All Tests needs: prepare @@ -81,7 +98,7 @@ jobs: build: name: Build Binaries - needs: [prepare, test] + needs: [prepare, lint-and-format, test] runs-on: ${{ matrix.os }} if: needs.prepare.outputs.sync == 'false' strategy: @@ -121,7 +138,7 @@ jobs: build-browser: name: Build Browser for Pages - needs: [prepare, test] + needs: [prepare, lint-and-format, test] runs-on: ubuntu-latest steps: - name: Check out code @@ -172,7 +189,6 @@ jobs: deploy-pages: name: Deploy to GitHub Pages needs: [release, build-browser] - if: always() && needs.build-browser.result runs-on: ubuntu-latest environment: name: github-pages diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9d6e7fe3..b0b6b26d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,6 +13,25 @@ concurrency: cancel-in-progress: true jobs: + lint-and-format: + name: Lint and Format Check + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Check out code + uses: actions/checkout@v5 + + - name: Setup Environment + uses: ./.github/actions/setup-environment + with: + install-build-tools: "false" + + - name: Check C# formatting + run: make format-check-csharp + + - name: Check TypeScript/JavaScript formatting and linting + run: make format-check-typescript lint-typescript + test: name: Run All Tests runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 4971f35e..6d0bece3 100644 --- a/.gitignore +++ b/.gitignore @@ -491,4 +491,6 @@ src/*/.avalonia*/* src/AvaloniaXKCD.Browser/wwwroot # Build output -out/ \ No newline at end of file +out/ + +.lfs-files.txt \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3e01109e..dbe7d5a0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,4 +22,28 @@ Use the [Dev Container](https://code.visualstudio.com/docs/remote/containers) fo 1. Tests must pass. 2. Include tests for new functionality. -3. Ensure code formatted using `make format`. +3. Ensure code is formatted and linted before submitting: + - Run `make format` to format all code (C# and TypeScript). + - Run `make lint` to check for linting issues in TypeScript. + - Run `make format-check` to verify formatting without making changes. + +### Code Quality Standards + +This project uses automated linting and formatting tools to maintain code quality and consistency: + +- **C#**: Uses CSharpier for opinionated formatting and `dotnet format` for style analysis. ReSharper is available for advanced local linting (optional, requires significant disk space). +- **TypeScript/JavaScript**: Uses Prettier for formatting and ESLint for linting + +**Available Commands:** + +- `make format` - Format all code (C# and TypeScript) +- `make format-csharp` - Format only C# code +- `make format-typescript` - Format only TypeScript code +- `make lint` - Run all linters (TypeScript in CI) +- `make lint-typescript` - Lint TypeScript code +- `make lint-csharp-local` - Lint C# with ReSharper (local development only, resource-intensive) +- `make format-check` - Check formatting without making changes (used in CI) + +**Note on C# Linting:** ReSharper linting (`make lint-csharp-local`) is available for local development but requires building the entire solution and significant disk space (~3GB+). It is not run in CI due to resource constraints. The CI pipeline focuses on formatting checks with CSharpier and dotnet format. + +The CI pipeline will automatically check formatting and linting on all pull requests. diff --git a/makefile b/makefile index ea7dee8a..0f1d5aab 100644 --- a/makefile +++ b/makefile @@ -183,15 +183,46 @@ endif @dotnet tool install --global verify.tool @dotnet tool install --global dotnet-outdated-tool @dotnet tool install --global KuiperZone.PupNet - @cd src; dotnet workload restore - @cd src/AvaloniaXKCD.Site; bun ci + @dotnet tool restore + @cd src/AvaloniaXKCD.Site; npm ci + @cd src; sudo dotnet workload restore setup-playwright: ## Setup playwright browsers for testing. @cd src; dotnet build; dotnet dnx -y Microsoft.Playwright.CLI -p ./AvaloniaXKCD.Tests install --with-deps -format: ## Format source code. +format-csharp: ## Format C# source code with CSharpier and dotnet format. + @$(ECHO) "--- Formatting C# code ---" + @dotnet csharpier format . @cd src; dotnet format +format-typescript: ## Format TypeScript/JavaScript source code with Prettier. + @$(ECHO) "--- Formatting TypeScript/JavaScript code with Prettier ---" + @cd src/AvaloniaXKCD.Site; npm run format + +format: format-csharp format-typescript ## Format all source code (C# and TypeScript). + +format-check-csharp: ## Check C# formatting without making changes. + @$(ECHO) "--- Checking C# formatting ---" + @dotnet csharpier check . + @cd src; dotnet format --verify-no-changes + +format-check-typescript: ## Check TypeScript/JavaScript formatting without making changes. + @$(ECHO) "--- Checking TypeScript/JavaScript formatting ---" + @cd src/AvaloniaXKCD.Site; npm run format:check + +format-check: format-check-csharp format-check-typescript ## Check all code formatting (C# and TypeScript). + +lint-csharp-local: ## Lint C# source code with ReSharper (local development only - requires significant disk space). + @$(ECHO) "--- Linting C# code with ReSharper (this may take several minutes) ---" + @cd src; dotnet jb inspectcode AvaloniaXKCD.slnx --output=/tmp/resharper-report.xml --severity=WARNING --build + @$(ECHO) "ReSharper report generated at /tmp/resharper-report.xml" + +lint-typescript: ## Lint TypeScript/JavaScript source code. + @$(ECHO) "--- Linting TypeScript/JavaScript code ---" + @cd src/AvaloniaXKCD.Site; npm run lint + +lint: lint-typescript ## Lint all source code (TypeScript only in CI). + clean: ## Clean local environment (bin/obj folders). @cd src; dotnet clean diff --git a/src/.csharpierignore b/src/.csharpierignore new file mode 100644 index 00000000..b3cb54d2 --- /dev/null +++ b/src/.csharpierignore @@ -0,0 +1 @@ +AvaloniaXKCD.Tests/Setup/GlobalUsings.Tests.cs \ No newline at end of file diff --git a/src/.csharpierrc.json b/src/.csharpierrc.json new file mode 100644 index 00000000..e071b2a9 --- /dev/null +++ b/src/.csharpierrc.json @@ -0,0 +1,6 @@ +{ + "printWidth": 120, + "useTabs": false, + "tabWidth": 4, + "endOfLine": "lf" +} diff --git a/src/AvaloniaXKCD.Browser/AvaloniaXKCD.Browser.csproj b/src/AvaloniaXKCD.Browser/AvaloniaXKCD.Browser.csproj index d79df0ee..900ad7b1 100644 --- a/src/AvaloniaXKCD.Browser/AvaloniaXKCD.Browser.csproj +++ b/src/AvaloniaXKCD.Browser/AvaloniaXKCD.Browser.csproj @@ -1,25 +1,29 @@ - - - net10.0-browser - Exe - true - true - false - true - true - InterpreterAndAOT - false - - - - - - - - - - - - - - + + + net10.0-browser + Exe + true + true + false + true + true + InterpreterAndAOT + false + + + + + + + + + + + + + + diff --git a/src/AvaloniaXKCD.Browser/BuildSite.targets b/src/AvaloniaXKCD.Browser/BuildSite.targets index 42370afe..7a3450b2 100644 --- a/src/AvaloniaXKCD.Browser/BuildSite.targets +++ b/src/AvaloniaXKCD.Browser/BuildSite.targets @@ -12,9 +12,17 @@ - - + + - \ No newline at end of file + diff --git a/src/AvaloniaXKCD.Browser/CSharpEventBridge.cs b/src/AvaloniaXKCD.Browser/CSharpEventBridge.cs index 8b7555e4..e1d0c7e9 100644 --- a/src/AvaloniaXKCD.Browser/CSharpEventBridge.cs +++ b/src/AvaloniaXKCD.Browser/CSharpEventBridge.cs @@ -19,14 +19,13 @@ private Handler(object original, Action wrapped) WrappedHandler = wrapped; } - public static implicit operator Handler(Action action) - => new(action, action); + public static implicit operator Handler(Action action) => new(action, action); - public static implicit operator Handler(EventHandler eventHandler) - => new(eventHandler, data => eventHandler(null, data)); + public static implicit operator Handler(EventHandler eventHandler) => + new(eventHandler, data => eventHandler(null, data)); - public static implicit operator Handler(CSharpGenericEventHandler csharpGenericEventHandler) - => new(csharpGenericEventHandler, data => csharpGenericEventHandler(data)); + public static implicit operator Handler(CSharpGenericEventHandler csharpGenericEventHandler) => + new(csharpGenericEventHandler, data => csharpGenericEventHandler(data)); } public abstract class EventBridge @@ -112,12 +111,10 @@ public static partial class CSharpEventBridgeFactory } } - public static string? Add(string handlerName, Action callback) - => GetBridge(handlerName)?.Add(callback); + public static string? Add(string handlerName, Action callback) => GetBridge(handlerName)?.Add(callback); - public static void Remove(string handlerName, string subscription) - => GetBridge(handlerName)?.Remove(subscription); + public static void Remove(string handlerName, string subscription) => + GetBridge(handlerName)?.Remove(subscription); - public static void Invoke(string handlerName, T data) - => GetBridge(handlerName)?.Invoke(data); -} \ No newline at end of file + public static void Invoke(string handlerName, T data) => GetBridge(handlerName)?.Invoke(data); +} diff --git a/src/AvaloniaXKCD.Browser/Exports/Config.cs b/src/AvaloniaXKCD.Browser/Exports/Config.cs index 43a68d0e..b6157a48 100644 --- a/src/AvaloniaXKCD.Browser/Exports/Config.cs +++ b/src/AvaloniaXKCD.Browser/Exports/Config.cs @@ -4,11 +4,20 @@ namespace AvaloniaXKCD.Browser; public class Config : IConfig { - public PlatformType PlatformType { get => PlatformType.Browser; } + public PlatformType PlatformType + { + get => PlatformType.Browser; + } #if DEBUG - public LogLevel LogLevel { get => LogLevel.Trace; } + public LogLevel LogLevel + { + get => LogLevel.Trace; + } #else - public LogLevel LogLevel { get => LogLevel.Critical; } + public LogLevel LogLevel + { + get => LogLevel.Critical; + } #endif -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Browser/Exports/LocalizationService.cs b/src/AvaloniaXKCD.Browser/Exports/LocalizationService.cs index cc637055..f02be996 100644 --- a/src/AvaloniaXKCD.Browser/Exports/LocalizationService.cs +++ b/src/AvaloniaXKCD.Browser/Exports/LocalizationService.cs @@ -19,11 +19,11 @@ public partial class BrowserLocalizationService : LocalizationService [JSImport("getString", "interop")] internal static partial string GetBrowserString(string key); - public override CultureInfo GetCulture() - => GetBrowserLocale() switch + public override CultureInfo GetCulture() => + GetBrowserLocale() switch { null or "" => CultureInfo.GetCultureInfo("en"), - var locale => CultureInfo.GetCultureInfo(locale) + var locale => CultureInfo.GetCultureInfo(locale), }; public override string GetString(string key) @@ -31,7 +31,8 @@ public override string GetString(string key) return GetBrowserString(key); } - public BrowserLocalizationService() : base() + public BrowserLocalizationService() + : base() { CultureChanged += OnCultureChangedHandler; } diff --git a/src/AvaloniaXKCD.Browser/Exports/Logger.cs b/src/AvaloniaXKCD.Browser/Exports/Logger.cs index 35469dd9..4630b530 100644 --- a/src/AvaloniaXKCD.Browser/Exports/Logger.cs +++ b/src/AvaloniaXKCD.Browser/Exports/Logger.cs @@ -12,21 +12,29 @@ public partial class BrowserLogger : ILogger { [JSImport("globalThis.console.log")] internal static partial Task Log([JSMarshalAs] string message); + [JSImport("globalThis.console.info")] internal static partial Task Info([JSMarshalAs] string message); + [JSImport("globalThis.console.warn")] internal static partial Task Warn([JSMarshalAs] string message); + [JSImport("globalThis.console.debug")] internal static partial Task Debug([JSMarshalAs] string message); + [JSImport("globalThis.console.error")] internal static partial Task Error([JSMarshalAs] string message); + [JSImport("globalThis.console.trace")] internal static partial Task Trace([JSMarshalAs] string message); - public bool ShouldLog(LogLevel level) => level.ShouldLog(App.Config.LogLevel); - public void Log(LogLevel level, string message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) + + public void Log( + LogLevel level, + string message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) { var messageTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); var category = Path.GetFileNameWithoutExtension(file); @@ -54,7 +62,10 @@ public void Log(LogLevel level, string message, break; } } - public void Log(LogLevel level, Exception err, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => Log(level, err.ToString(), file); -} \ No newline at end of file + + public void Log( + LogLevel level, + Exception err, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => Log(level, err.ToString(), file); +} diff --git a/src/AvaloniaXKCD.Browser/Exports/SettingsRepo.cs b/src/AvaloniaXKCD.Browser/Exports/SettingsRepo.cs index fbecdf9b..f4da0cc9 100644 --- a/src/AvaloniaXKCD.Browser/Exports/SettingsRepo.cs +++ b/src/AvaloniaXKCD.Browser/Exports/SettingsRepo.cs @@ -1,11 +1,11 @@ using System; -using AvaloniaXKCD.Exports; +using System.Runtime.InteropServices.JavaScript; using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; -using System.Runtime.InteropServices.JavaScript; using System.Threading.Tasks; +using AvaloniaXKCD.Exports; namespace AvaloniaXKCD.Browser; @@ -21,7 +21,6 @@ public LocalStorageSettingsRepo() Load(); } - // JS-imported localStorage [JSImport("globalThis.localStorage.getItem")] internal static partial Task LocalStorage_GetItem(string key); @@ -75,4 +74,4 @@ public override void Set(T obj, JsonTypeInfo typeInfo) Save(); } } -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Browser/Exports/SystemActions.cs b/src/AvaloniaXKCD.Browser/Exports/SystemActions.cs index e3371065..f853754f 100644 --- a/src/AvaloniaXKCD.Browser/Exports/SystemActions.cs +++ b/src/AvaloniaXKCD.Browser/Exports/SystemActions.cs @@ -11,13 +11,16 @@ public partial class BrowserSystemActions : ISystemActions { #region Handle URI Change [JSExport] - public static string? AddOnUriChangeCallback([JSMarshalAs>()] Action callback) + public static string? AddOnUriChangeCallback( + [JSMarshalAs>()] Action callback + ) { if (App.SystemActions is BrowserSystemActions self && self._uriChangeBridge != null) { return self._uriChangeBridge.Add(callback); } - else throw new NullReferenceException(); + else + throw new NullReferenceException(); } [JSExport] @@ -27,7 +30,8 @@ public static void RemoveOnUriChangeCallback(string subscription) { self._uriChangeBridge.Remove(subscription); } - else throw new NullReferenceException(); + else + throw new NullReferenceException(); } [JSExport] @@ -37,21 +41,25 @@ public static void InvokeOnUriChangeCallback(string uri) { self._uriChangeBridge.Invoke(uri); } - else throw new NullReferenceException(); + else + throw new NullReferenceException(); } - private readonly CSharpGenericEventBridge? _uriChangeBridge = - CSharpEventBridgeFactory.GetBridge($"{nameof(BrowserSystemActions)}.${nameof(OnUriChange)}"); + private readonly CSharpGenericEventBridge? _uriChangeBridge = CSharpEventBridgeFactory.GetBridge( + $"{nameof(BrowserSystemActions)}.${nameof(OnUriChange)}" + ); public event EventHandler? OnUriChange { add { - if (value != null) _uriChangeBridge?.Add(value); + if (value != null) + _uriChangeBridge?.Add(value); } remove { - if (value != null) _uriChangeBridge?.Remove(value); + if (value != null) + _uriChangeBridge?.Remove(value); } } @@ -85,4 +93,4 @@ public void SetTitle(string title) { SetTitleInternal(title); } -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Browser/Program.cs b/src/AvaloniaXKCD.Browser/Program.cs index c00b01e7..10d2b0bf 100644 --- a/src/AvaloniaXKCD.Browser/Program.cs +++ b/src/AvaloniaXKCD.Browser/Program.cs @@ -1,28 +1,32 @@ -using System; -using System.Runtime.Versioning; -using System.Threading.Tasks; -using Avalonia; -using Avalonia.Browser; -using AvaloniaXKCD; -using AvaloniaXKCD.Browser; -using AvaloniaXKCD.Exports; - -internal sealed partial class Program -{ - private static Task Main(string[] args) => - CommandLineParser.Instance.Invoke(args, async (parsedArguments) => - await BuildAvaloniaApp(parsedArguments) - .WithInterFont() - .StartBrowserAppAsync("out")).ContinueWith(result => - { - if (result.IsFaulted) - { - ExportContainer.Get()?.HandleError(result.Exception); - Environment.FailFast(result.Exception.ToString()); - } - }); - - public static AppBuilder BuildAvaloniaApp() => BuildAvaloniaApp(new ParsedArguments()); - public static AppBuilder BuildAvaloniaApp(ParsedArguments parsedArguments) - => AppBuilder.Configure(() => new App(parsedArguments)); -} \ No newline at end of file +using System; +using System.Runtime.Versioning; +using System.Threading.Tasks; +using Avalonia; +using Avalonia.Browser; +using AvaloniaXKCD; +using AvaloniaXKCD.Browser; +using AvaloniaXKCD.Exports; + +internal sealed partial class Program +{ + private static Task Main(string[] args) => + CommandLineParser + .Instance.Invoke( + args, + async (parsedArguments) => + await BuildAvaloniaApp(parsedArguments).WithInterFont().StartBrowserAppAsync("out") + ) + .ContinueWith(result => + { + if (result.IsFaulted) + { + ExportContainer.Get()?.HandleError(result.Exception); + Environment.FailFast(result.Exception.ToString()); + } + }); + + public static AppBuilder BuildAvaloniaApp() => BuildAvaloniaApp(new ParsedArguments()); + + public static AppBuilder BuildAvaloniaApp(ParsedArguments parsedArguments) => + AppBuilder.Configure(() => new App(parsedArguments)); +} diff --git a/src/AvaloniaXKCD.Browser/Properties/AssemblyInfo.cs b/src/AvaloniaXKCD.Browser/Properties/AssemblyInfo.cs index e64d71fd..c4039b7b 100644 --- a/src/AvaloniaXKCD.Browser/Properties/AssemblyInfo.cs +++ b/src/AvaloniaXKCD.Browser/Properties/AssemblyInfo.cs @@ -1 +1 @@ -[assembly: System.Runtime.Versioning.SupportedOSPlatform("browser")] +[assembly: System.Runtime.Versioning.SupportedOSPlatform("browser")] diff --git a/src/AvaloniaXKCD.Desktop/AvaloniaXKCD.Desktop.csproj b/src/AvaloniaXKCD.Desktop/AvaloniaXKCD.Desktop.csproj index 0366eb30..a0bdf224 100644 --- a/src/AvaloniaXKCD.Desktop/AvaloniaXKCD.Desktop.csproj +++ b/src/AvaloniaXKCD.Desktop/AvaloniaXKCD.Desktop.csproj @@ -1,44 +1,48 @@ - - - WinExe - net10.0 - true - true - true - false - Assets\avalonia-logo.ico - AXKCD - - - - app.manifest - - - - - - None - All - - - - - - - - - - - - - - WINDOWS - $(NoWarn);CA1416 - - - MACOS - - - LINUX - - + + + WinExe + net10.0 + true + true + true + false + Assets\avalonia-logo.ico + AXKCD + + + + app.manifest + + + + + + None + All + + + + + + + + + + + + + + WINDOWS + $(NoWarn);CA1416 + + + MACOS + + + LINUX + + diff --git a/src/AvaloniaXKCD.Desktop/Exports/Config.cs b/src/AvaloniaXKCD.Desktop/Exports/Config.cs index 50862806..58aed52b 100644 --- a/src/AvaloniaXKCD.Desktop/Exports/Config.cs +++ b/src/AvaloniaXKCD.Desktop/Exports/Config.cs @@ -4,11 +4,20 @@ namespace AvaloniaXKCD.Desktop; public class Config : IConfig { - public PlatformType PlatformType { get => PlatformType.Desktop; } + public PlatformType PlatformType + { + get => PlatformType.Desktop; + } #if DEBUG - public LogLevel LogLevel { get => LogLevel.Trace; } + public LogLevel LogLevel + { + get => LogLevel.Trace; + } #else - public LogLevel LogLevel { get => LogLevel.Critical; } + public LogLevel LogLevel + { + get => LogLevel.Critical; + } #endif -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Desktop/Exports/LocalizationService.cs b/src/AvaloniaXKCD.Desktop/Exports/LocalizationService.cs index 1dc7879c..5042ffad 100644 --- a/src/AvaloniaXKCD.Desktop/Exports/LocalizationService.cs +++ b/src/AvaloniaXKCD.Desktop/Exports/LocalizationService.cs @@ -8,6 +8,5 @@ namespace AvaloniaXKCD.Desktop; /// public class DesktopLocalizationService : LocalizationService { - public override CultureInfo GetCulture() - => CultureInfo.CurrentUICulture; + public override CultureInfo GetCulture() => CultureInfo.CurrentUICulture; } diff --git a/src/AvaloniaXKCD.Desktop/Exports/Logger.cs b/src/AvaloniaXKCD.Desktop/Exports/Logger.cs index 9c1f31fc..b1f39880 100644 --- a/src/AvaloniaXKCD.Desktop/Exports/Logger.cs +++ b/src/AvaloniaXKCD.Desktop/Exports/Logger.cs @@ -16,13 +16,14 @@ public class DesktopLogger : Exports.ILogger public DesktopLogger() { _innerFactory = LoggerFactory.Create(builder => - builder.AddSimpleConsole(options => - { - options.IncludeScopes = false; - options.SingleLine = true; - options.TimestampFormat = "HH:mm:ss "; - }) - .SetMinimumLevel(MapLevel(App.Config.LogLevel)) + builder + .AddSimpleConsole(options => + { + options.IncludeScopes = false; + options.SingleLine = true; + options.TimestampFormat = "HH:mm:ss "; + }) + .SetMinimumLevel(MapLevel(App.Config.LogLevel)) ); } @@ -35,20 +36,25 @@ private Microsoft.Extensions.Logging.LogLevel MapLevel(Exports.LogLevel level) = Exports.LogLevel.Warning => Microsoft.Extensions.Logging.LogLevel.Warning, Exports.LogLevel.Error => Microsoft.Extensions.Logging.LogLevel.Error, Exports.LogLevel.Critical => Microsoft.Extensions.Logging.LogLevel.Critical, - _ => Microsoft.Extensions.Logging.LogLevel.None + _ => Microsoft.Extensions.Logging.LogLevel.None, }; public bool ShouldLog(Exports.LogLevel level) => level.ShouldLog(App.Config.LogLevel); - public void Log(Exports.LogLevel level, string message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) + public void Log( + Exports.LogLevel level, + string message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) { var category = Path.GetFileNameWithoutExtension(file); var logger = _innerFactory.CreateLogger(category ?? "Logger"); logger.Log(MapLevel(level), message); } - public void Log(Exports.LogLevel level, Exception ex, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => Log(level, ex.Message, file); -} \ No newline at end of file + public void Log( + Exports.LogLevel level, + Exception ex, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => Log(level, ex.Message, file); +} diff --git a/src/AvaloniaXKCD.Desktop/Exports/SettingsRepo.cs b/src/AvaloniaXKCD.Desktop/Exports/SettingsRepo.cs index 0eaf78e7..f23d7f70 100644 --- a/src/AvaloniaXKCD.Desktop/Exports/SettingsRepo.cs +++ b/src/AvaloniaXKCD.Desktop/Exports/SettingsRepo.cs @@ -1,10 +1,10 @@ using System; using System.IO; -using AvaloniaXKCD.Exports; using System.Text.Json; using System.Text.Json.Nodes; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; +using AvaloniaXKCD.Exports; namespace AvaloniaXKCD.Desktop; @@ -23,6 +23,7 @@ public JsonSettingsRepo() } private bool _isDirty = false; + public override void Save() { if (!_isDirty) @@ -73,4 +74,4 @@ public override void Set(T obj, JsonTypeInfo typeInfo) _isDirty = true; } } -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Desktop/Exports/SystemActions.Linux.cs b/src/AvaloniaXKCD.Desktop/Exports/SystemActions.Linux.cs index d877509a..beb984e6 100644 --- a/src/AvaloniaXKCD.Desktop/Exports/SystemActions.Linux.cs +++ b/src/AvaloniaXKCD.Desktop/Exports/SystemActions.Linux.cs @@ -27,4 +27,4 @@ internal static partial class NativeMethods [LibraryImport("libc", EntryPoint = "syslog")] internal static partial void syslog(int priority, byte[] message); } -#endif \ No newline at end of file +#endif diff --git a/src/AvaloniaXKCD.Desktop/Exports/SystemActions.Windows.cs b/src/AvaloniaXKCD.Desktop/Exports/SystemActions.Windows.cs index 4fa219fe..bc87deb3 100644 --- a/src/AvaloniaXKCD.Desktop/Exports/SystemActions.Windows.cs +++ b/src/AvaloniaXKCD.Desktop/Exports/SystemActions.Windows.cs @@ -28,4 +28,4 @@ internal bool HandleErrorWindows(Exception error) } } } -#endif \ No newline at end of file +#endif diff --git a/src/AvaloniaXKCD.Desktop/Exports/SystemActions.cs b/src/AvaloniaXKCD.Desktop/Exports/SystemActions.cs index 6b0ec39b..e6f20496 100644 --- a/src/AvaloniaXKCD.Desktop/Exports/SystemActions.cs +++ b/src/AvaloniaXKCD.Desktop/Exports/SystemActions.cs @@ -38,4 +38,4 @@ public void SetTitle(string title) { // Noop } -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Desktop/Program.cs b/src/AvaloniaXKCD.Desktop/Program.cs index a5efa457..bc88d806 100644 --- a/src/AvaloniaXKCD.Desktop/Program.cs +++ b/src/AvaloniaXKCD.Desktop/Program.cs @@ -1,48 +1,53 @@ -using System; -using System.Runtime.Loader; -using System.Threading; -using System.Threading.Tasks; -using Avalonia; -using Avalonia.Controls; -using AvaloniaXKCD.Exports; - -namespace AvaloniaXKCD.Desktop; - -sealed class Program -{ - // Initialization code. Don't use any Avalonia, third-party APIs or any - // SynchronizationContext-reliant code before AppMain is called: things aren't initialized - // yet and stuff might break. - [STAThread] - public static async Task Main(string[] args) - { - var cts = new CancellationTokenSource(); - Console.CancelKeyPress += (s, e) => - { - cts.Cancel(); - e.Cancel = true; - }; - - return await CommandLineParser.Instance.Invoke(args, async (parsedArgs) => - { - try - { - return BuildAvaloniaApp(parsedArgs, cts.Token) - .StartWithClassicDesktopLifetime(args); - } - catch (Exception err) - { - ExportContainer.Get()?.HandleError(err); - throw; - } - }, cts.Token); - } - - // Avalonia configuration, don't remove; also used by visual designer. - public static AppBuilder BuildAvaloniaApp() => BuildAvaloniaApp(new ParsedArguments(), CancellationToken.None); - public static AppBuilder BuildAvaloniaApp(ParsedArguments parsedArguments, CancellationToken cancellationToken) - => AppBuilder.Configure(() => new App(parsedArguments, cancellationToken)) - .UsePlatformDetect() - .WithInterFont() - .LogToTrace(); -} +using System; +using System.Runtime.Loader; +using System.Threading; +using System.Threading.Tasks; +using Avalonia; +using Avalonia.Controls; +using AvaloniaXKCD.Exports; + +namespace AvaloniaXKCD.Desktop; + +sealed class Program +{ + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + [STAThread] + public static async Task Main(string[] args) + { + var cts = new CancellationTokenSource(); + Console.CancelKeyPress += (s, e) => + { + cts.Cancel(); + e.Cancel = true; + }; + + return await CommandLineParser.Instance.Invoke( + args, + async (parsedArgs) => + { + try + { + return BuildAvaloniaApp(parsedArgs, cts.Token).StartWithClassicDesktopLifetime(args); + } + catch (Exception err) + { + ExportContainer.Get()?.HandleError(err); + throw; + } + }, + cts.Token + ); + } + + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() => BuildAvaloniaApp(new ParsedArguments(), CancellationToken.None); + + public static AppBuilder BuildAvaloniaApp(ParsedArguments parsedArguments, CancellationToken cancellationToken) => + AppBuilder + .Configure(() => new App(parsedArguments, cancellationToken)) + .UsePlatformDetect() + .WithInterFont() + .LogToTrace(); +} diff --git a/src/AvaloniaXKCD.Exports/AvaloniaXKCD.Exports.csproj b/src/AvaloniaXKCD.Exports/AvaloniaXKCD.Exports.csproj index bdc90881..6ae00721 100644 --- a/src/AvaloniaXKCD.Exports/AvaloniaXKCD.Exports.csproj +++ b/src/AvaloniaXKCD.Exports/AvaloniaXKCD.Exports.csproj @@ -1,5 +1,4 @@ - netstandard2.0 @@ -7,5 +6,4 @@ - diff --git a/src/AvaloniaXKCD.Exports/ExportContainer.cs b/src/AvaloniaXKCD.Exports/ExportContainer.cs index 3b7c1ce2..e10ed625 100644 --- a/src/AvaloniaXKCD.Exports/ExportContainer.cs +++ b/src/AvaloniaXKCD.Exports/ExportContainer.cs @@ -6,15 +6,22 @@ public partial class ExportContainer { private static readonly Dictionary>> _multiFactories = new(); - public static void Add(string name, Func factory) where T : IExport => AddMulti(name, factory); - - public static void Add(Func factory) where T : IExport => Add(typeof(T).FullName, factory); - - public static void Add(string name) where T : IExport where C : T, new() => Add(name, () => new C()); - - public static void Add() where T : IExport where C : T, new() => Add(() => new C()); - - public static void AddMulti(string name, Func factory) where T : IExport + public static void Add(string name, Func factory) + where T : IExport => AddMulti(name, factory); + + public static void Add(Func factory) + where T : IExport => Add(typeof(T).FullName, factory); + + public static void Add(string name) + where T : IExport + where C : T, new() => Add(name, () => new C()); + + public static void Add() + where T : IExport + where C : T, new() => Add(() => new C()); + + public static void AddMulti(string name, Func factory) + where T : IExport { if (!_multiFactories.ContainsKey(name)) { @@ -22,19 +29,29 @@ public static void AddMulti(string name, Func factory) where T : IExport } _multiFactories[name].Add(new Lazy(() => factory())); } - - public static void AddMulti(Func factory) where T : IExport => AddMulti(typeof(T).FullName, factory); - - public static void AddMulti(string name) where T : IExport where C : T, new() => AddMulti(name, () => new C()); - - public static void AddMulti() where T : IExport where C : T, new() => AddMulti(() => new C()); - - public static T? Get(string name) where T : IExport => GetAllEnumerable(name).SingleOrDefault(); - - public static T? Get() where T : IExport => Get(typeof(T).FullName); - - public static T[] GetAll(string name) where T : IExport => GetAllEnumerable(name).ToArray(); - static IEnumerable GetAllEnumerable(string name) where T : IExport + + public static void AddMulti(Func factory) + where T : IExport => AddMulti(typeof(T).FullName, factory); + + public static void AddMulti(string name) + where T : IExport + where C : T, new() => AddMulti(name, () => new C()); + + public static void AddMulti() + where T : IExport + where C : T, new() => AddMulti(() => new C()); + + public static T? Get(string name) + where T : IExport => GetAllEnumerable(name).SingleOrDefault(); + + public static T? Get() + where T : IExport => Get(typeof(T).FullName); + + public static T[] GetAll(string name) + where T : IExport => GetAllEnumerable(name).ToArray(); + + static IEnumerable GetAllEnumerable(string name) + where T : IExport { if (!_multiFactories.TryGetValue(name, out var lazyList)) { @@ -42,6 +59,7 @@ static IEnumerable GetAllEnumerable(string name) where T : IExport } return lazyList.Select(lazy => (T)lazy.Value); } - - public static T[] GetAll() where T : IExport => GetAll(typeof(T).FullName); -} \ No newline at end of file + + public static T[] GetAll() + where T : IExport => GetAll(typeof(T).FullName); +} diff --git a/src/AvaloniaXKCD.Exports/IConfig.cs b/src/AvaloniaXKCD.Exports/IConfig.cs index 0e28b0a2..87b7bf77 100644 --- a/src/AvaloniaXKCD.Exports/IConfig.cs +++ b/src/AvaloniaXKCD.Exports/IConfig.cs @@ -11,5 +11,5 @@ public enum PlatformType { Headless, Browser, - Desktop -}; \ No newline at end of file + Desktop, +}; diff --git a/src/AvaloniaXKCD.Exports/IExport.cs b/src/AvaloniaXKCD.Exports/IExport.cs index 4b9542dc..20637e7c 100644 --- a/src/AvaloniaXKCD.Exports/IExport.cs +++ b/src/AvaloniaXKCD.Exports/IExport.cs @@ -1,3 +1,3 @@ -namespace AvaloniaXKCD.Exports; +namespace AvaloniaXKCD.Exports; public interface IExport { } diff --git a/src/AvaloniaXKCD.Exports/ILogger.cs b/src/AvaloniaXKCD.Exports/ILogger.cs index 9ef57c14..6b98c2f7 100644 --- a/src/AvaloniaXKCD.Exports/ILogger.cs +++ b/src/AvaloniaXKCD.Exports/ILogger.cs @@ -4,61 +4,110 @@ public interface ILogger : IExport { bool ShouldLog(LogLevel level); - void Log(LogLevel level, string message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null); - public void Log(LogLevel level, Exception err, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null); + void Log(LogLevel level, string message, [System.Runtime.CompilerServices.CallerFilePath] string? file = null); + public void Log( + LogLevel level, + Exception err, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ); } public abstract class BaseLogger : ILogger { - public bool ShouldLogTrace { get => ShouldLog(LogLevel.Trace); } - public bool ShouldLogDebug { get => ShouldLog(LogLevel.Debug); } - public bool ShouldLogInformation { get => ShouldLog(LogLevel.Information); } - public bool ShouldLogWarning { get => ShouldLog(LogLevel.Warning); } - public bool ShouldLogError { get => ShouldLog(LogLevel.Error); } - public bool ShouldLogCritical { get => ShouldLog(LogLevel.Critical); } + public bool ShouldLogTrace + { + get => ShouldLog(LogLevel.Trace); + } + public bool ShouldLogDebug + { + get => ShouldLog(LogLevel.Debug); + } + public bool ShouldLogInformation + { + get => ShouldLog(LogLevel.Information); + } + public bool ShouldLogWarning + { + get => ShouldLog(LogLevel.Warning); + } + public bool ShouldLogError + { + get => ShouldLog(LogLevel.Error); + } + public bool ShouldLogCritical + { + get => ShouldLog(LogLevel.Critical); + } public abstract bool ShouldLog(LogLevel level); - - public abstract void Log(LogLevel level, string message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null); - public abstract void Log(LogLevel level, Exception err, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null); + public abstract void Log( + LogLevel level, + string message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ); + public abstract void Log( + LogLevel level, + Exception err, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ); } public static class LoggerExtensions { - public static void LogTrace(this ILogger logger, string message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.Log(LogLevel.Trace, message, file); - public static void LogDebug(this ILogger logger, string message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.Log(LogLevel.Debug, message, file); - public static void LogInformation(this ILogger logger, string message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.Log(LogLevel.Information, message, file); - public static void LogWarning(this ILogger logger, string message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.Log(LogLevel.Warning, message, file); - public static void LogError(this ILogger logger, string message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.Log(LogLevel.Error, message, file); - public static void LogError(this ILogger logger, Exception err, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.Log(LogLevel.Error, err, file); - public static void LogCritical(this ILogger logger, string message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.Log(LogLevel.Critical, message, file); - public static void LogCritical(this ILogger logger, Exception err, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.Log(LogLevel.Error, err, file); + public static void LogTrace( + this ILogger logger, + string message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.Log(LogLevel.Trace, message, file); + + public static void LogDebug( + this ILogger logger, + string message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.Log(LogLevel.Debug, message, file); + + public static void LogInformation( + this ILogger logger, + string message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.Log(LogLevel.Information, message, file); + + public static void LogWarning( + this ILogger logger, + string message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.Log(LogLevel.Warning, message, file); + + public static void LogError( + this ILogger logger, + string message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.Log(LogLevel.Error, message, file); + + public static void LogError( + this ILogger logger, + Exception err, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.Log(LogLevel.Error, err, file); + + public static void LogCritical( + this ILogger logger, + string message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.Log(LogLevel.Critical, message, file); + + public static void LogCritical( + this ILogger logger, + Exception err, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.Log(LogLevel.Error, err, file); public static bool IfShouldLog( this ILogger logger, LogLevel level, Func message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) { if (logger.ShouldLog(level)) { @@ -67,11 +116,13 @@ public static bool IfShouldLog( } return false; } + public static bool IfShouldLog( this ILogger logger, LogLevel level, Func err, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) { if (logger.ShouldLog(level)) { @@ -81,33 +132,55 @@ public static bool IfShouldLog( return false; } - public static bool IfShouldLogTrace(this ILogger logger, Func message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.IfShouldLog(LogLevel.Trace, message, file); - public static bool IfShouldLogDebug(this ILogger logger, Func message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.IfShouldLog(LogLevel.Debug, message, file); - public static bool IfShouldLogInformation(this ILogger logger, Func message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.IfShouldLog(LogLevel.Information, message, file); - public static bool IfShouldLogWarning(this ILogger logger, Func message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.IfShouldLog(LogLevel.Warning, message, file); - public static bool IfShouldLogError(this ILogger logger, Func message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.IfShouldLog(LogLevel.Error, message, file); - public static bool IfShouldLogError(this ILogger logger, Func err, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.IfShouldLog(LogLevel.Error, err, file); - public static bool IfShouldLogCritical(this ILogger logger, Func message, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.IfShouldLog(LogLevel.Critical, message, file); - public static bool IfShouldLogCritical(this ILogger logger, Func err, - [System.Runtime.CompilerServices.CallerFilePath] string? file = null) - => logger.IfShouldLog(LogLevel.Error, err, file); - - public static bool ShouldLog(this LogLevel currentLevel, LogLevel desiredLevel) - => currentLevel >= desiredLevel; + public static bool IfShouldLogTrace( + this ILogger logger, + Func message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.IfShouldLog(LogLevel.Trace, message, file); + + public static bool IfShouldLogDebug( + this ILogger logger, + Func message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.IfShouldLog(LogLevel.Debug, message, file); + + public static bool IfShouldLogInformation( + this ILogger logger, + Func message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.IfShouldLog(LogLevel.Information, message, file); + + public static bool IfShouldLogWarning( + this ILogger logger, + Func message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.IfShouldLog(LogLevel.Warning, message, file); + + public static bool IfShouldLogError( + this ILogger logger, + Func message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.IfShouldLog(LogLevel.Error, message, file); + + public static bool IfShouldLogError( + this ILogger logger, + Func err, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.IfShouldLog(LogLevel.Error, err, file); + + public static bool IfShouldLogCritical( + this ILogger logger, + Func message, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.IfShouldLog(LogLevel.Critical, message, file); + + public static bool IfShouldLogCritical( + this ILogger logger, + Func err, + [System.Runtime.CompilerServices.CallerFilePath] string? file = null + ) => logger.IfShouldLog(LogLevel.Error, err, file); + + public static bool ShouldLog(this LogLevel currentLevel, LogLevel desiredLevel) => currentLevel >= desiredLevel; } public enum LogLevel @@ -118,5 +191,5 @@ public enum LogLevel Warning, Error, Critical, - None -} \ No newline at end of file + None, +} diff --git a/src/AvaloniaXKCD.Exports/ISettingsRepo.cs b/src/AvaloniaXKCD.Exports/ISettingsRepo.cs index cf73a115..4267a060 100644 --- a/src/AvaloniaXKCD.Exports/ISettingsRepo.cs +++ b/src/AvaloniaXKCD.Exports/ISettingsRepo.cs @@ -10,7 +10,8 @@ public interface ISettingsRepo : IExport, IDisposable void Load(); void Save(); - T? Get(JsonTypeInfo typeInfo) where T : class, new(); + T? Get(JsonTypeInfo typeInfo) + where T : class, new(); void Set(T obj, JsonTypeInfo typeInfo); } @@ -20,7 +21,8 @@ public abstract class BaseSettingsRepo : ISettingsRepo public abstract void Load(); - public abstract T? Get(JsonTypeInfo typeInfo) where T : class, new(); + public abstract T? Get(JsonTypeInfo typeInfo) + where T : class, new(); public abstract void Set(T obj, JsonTypeInfo typeInfo); void IDisposable.Dispose() @@ -36,4 +38,4 @@ protected virtual void Dispose(bool disposing) Save(); } } -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Exports/ISystemActions.cs b/src/AvaloniaXKCD.Exports/ISystemActions.cs index 7dc9ba24..e103a66f 100644 --- a/src/AvaloniaXKCD.Exports/ISystemActions.cs +++ b/src/AvaloniaXKCD.Exports/ISystemActions.cs @@ -7,4 +7,4 @@ public interface ISystemActions : IExport public event EventHandler? OnUriChange; public void InvokeOnUriChange(string newUri); public void SetTitle(string title); -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Generators/AvaloniaXKCD.Generators.csproj b/src/AvaloniaXKCD.Generators/AvaloniaXKCD.Generators.csproj index c210097f..9ff797e9 100644 --- a/src/AvaloniaXKCD.Generators/AvaloniaXKCD.Generators.csproj +++ b/src/AvaloniaXKCD.Generators/AvaloniaXKCD.Generators.csproj @@ -1,5 +1,4 @@ - netstandard2.0 true @@ -25,7 +24,12 @@ - + @@ -41,8 +45,10 @@ - + - - \ No newline at end of file + diff --git a/src/AvaloniaXKCD.Generators/ExportRegistrarGenerator.cs b/src/AvaloniaXKCD.Generators/ExportRegistrarGenerator.cs index 3c4a8883..860834f1 100644 --- a/src/AvaloniaXKCD.Generators/ExportRegistrarGenerator.cs +++ b/src/AvaloniaXKCD.Generators/ExportRegistrarGenerator.cs @@ -16,7 +16,13 @@ public class ExportRegistrarGenerator : IIncrementalGenerator // Models for the Scriban template public record ConstructorDependency(string Type); - public record ExportedType(string FullTypeName, List Interfaces, List ConstructorDependencies); + + public record ExportedType( + string FullTypeName, + List Interfaces, + List ConstructorDependencies + ); + public record ExportedInterface(string Name, List Implementations); public void Initialize(IncrementalGeneratorInitializationContext context) @@ -27,10 +33,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context) Debugger.Launch(); } #endif - var exportsProvider = context.SyntaxProvider - .CreateSyntaxProvider( + var exportsProvider = context + .SyntaxProvider.CreateSyntaxProvider( static (syntax, _) => syntax is ClassDeclarationSyntax { BaseList: not null }, - static (ctx, _) => TransformClass(ctx)) + static (ctx, _) => TransformClass(ctx) + ) .Where(static model => model is not null); context.RegisterSourceOutput(exportsProvider.Collect(), GenerateSource); @@ -41,7 +48,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context) if (ctx.Node is not ClassDeclarationSyntax classDecl) return null; - if (ctx.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol typeSymbol || typeSymbol.IsAbstract) + if ( + ctx.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol typeSymbol + || typeSymbol.IsAbstract + ) return null; var iExportInterface = ctx.SemanticModel.Compilation.GetTypeByMetadataName(IExportFullName); @@ -55,12 +65,15 @@ public void Initialize(IncrementalGeneratorInitializationContext context) return null; // Find interfaces that derive from IExport (but are not IExport itself) - var exportInterfaces = typeSymbol.AllInterfaces - .Where(i => - !SymbolEqualityComparer.Default.Equals(i, iExportInterface) && - (i.AllInterfaces.Any(x => SymbolEqualityComparer.Default.Equals(x, iExportInterface)) || - i.AllInterfaces.Any(x => x.ToDisplayString() == IExportFullName) || - i.ToDisplayString() == IExportFullName)) + var exportInterfaces = typeSymbol + .AllInterfaces.Where(i => + !SymbolEqualityComparer.Default.Equals(i, iExportInterface) + && ( + i.AllInterfaces.Any(x => SymbolEqualityComparer.Default.Equals(x, iExportInterface)) + || i.AllInterfaces.Any(x => x.ToDisplayString() == IExportFullName) + || i.ToDisplayString() == IExportFullName + ) + ) .Select(i => i.ToDisplayString()) .Distinct() .ToList(); @@ -68,13 +81,13 @@ public void Initialize(IncrementalGeneratorInitializationContext context) if (exportInterfaces.Count == 0) return null; - var constructor = typeSymbol.InstanceConstructors - .OrderByDescending(c => c.Parameters.Length) + var constructor = typeSymbol + .InstanceConstructors.OrderByDescending(c => c.Parameters.Length) .FirstOrDefault(); - var deps = constructor?.Parameters - .Select(p => new ConstructorDependency(p.Type.ToDisplayString())) - .ToList() ?? new(); + var deps = + constructor?.Parameters.Select(p => new ConstructorDependency(p.Type.ToDisplayString())).ToList() + ?? new(); return new ExportedType(typeSymbol.ToDisplayString(), exportInterfaces, deps); } @@ -83,24 +96,38 @@ private static void GenerateSource(SourceProductionContext spc, ImmutableArray e?.FullTypeName == "IEXPORT_NOT_FOUND")) { - Report(spc, "XKC002", "IExport interface not found", - $"The required interface '{IExportFullName}' was not found in the compilation.", DiagnosticSeverity.Warning); + Report( + spc, + "XKC002", + "IExport interface not found", + $"The required interface '{IExportFullName}' was not found in the compilation.", + DiagnosticSeverity.Warning + ); return; } var validExports = exports.Where(e => e is not null).ToList(); if (validExports.Count == 0) { - Report(spc, "XKC003", "No valid exports found", + Report( + spc, + "XKC003", + "No valid exports found", "The ExportRegistrarGenerator found IExport but no concrete classes implementing it with service interfaces.", - DiagnosticSeverity.Info); + DiagnosticSeverity.Info + ); return; } @@ -125,8 +152,13 @@ private static void GenerateSource(SourceProductionContext spc, ImmutableArray m.Message)); - Report(spc, "XKC005", "Scriban template parsing error", - $"The Scriban template has errors:\n{errors}", DiagnosticSeverity.Error); + Report( + spc, + "XKC005", + "Scriban template parsing error", + $"The Scriban template has errors:\n{errors}", + DiagnosticSeverity.Error + ); return; } @@ -142,18 +174,27 @@ private static string GetEmbeddedResource(string resourceName) var assembly = typeof(ExportRegistrarGenerator).Assembly; var fullName = $"AvaloniaXKCD.Generators.{resourceName}"; - using var stream = assembly.GetManifestResourceStream(fullName) + using var stream = + assembly.GetManifestResourceStream(fullName) ?? throw new FileNotFoundException( - $"Embedded resource '{fullName}' not found. Available: {string.Join(", ", assembly.GetManifestResourceNames())}"); + $"Embedded resource '{fullName}' not found. Available: {string.Join(", ", assembly.GetManifestResourceNames())}" + ); using var reader = new StreamReader(stream); return reader.ReadToEnd(); } - private static void Report(SourceProductionContext spc, string id, string title, string message, DiagnosticSeverity severity) + private static void Report( + SourceProductionContext spc, + string id, + string title, + string message, + DiagnosticSeverity severity + ) { - spc.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor(id, title, message, "Generator", severity, true), null)); + spc.ReportDiagnostic( + Diagnostic.Create(new DiagnosticDescriptor(id, title, message, "Generator", severity, true), null) + ); } } } diff --git a/src/AvaloniaXKCD.Generators/IsExternalInit.cs b/src/AvaloniaXKCD.Generators/IsExternalInit.cs index b770df78..2f67a905 100644 --- a/src/AvaloniaXKCD.Generators/IsExternalInit.cs +++ b/src/AvaloniaXKCD.Generators/IsExternalInit.cs @@ -5,4 +5,4 @@ namespace System.Runtime.CompilerServices { internal static class IsExternalInit { } -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Generators/Resources/ServiceAttribute.cs b/src/AvaloniaXKCD.Generators/Resources/ServiceAttribute.cs index 29d85004..4478ff9c 100644 --- a/src/AvaloniaXKCD.Generators/Resources/ServiceAttribute.cs +++ b/src/AvaloniaXKCD.Generators/Resources/ServiceAttribute.cs @@ -12,4 +12,4 @@ public ServiceAttribute(ServiceLifetime lifetime = ServiceLifetime.Transient) Lifetime = lifetime; } } -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Generators/Resources/ServiceLifetime.cs b/src/AvaloniaXKCD.Generators/Resources/ServiceLifetime.cs index 489b69fd..7a35c7c0 100644 --- a/src/AvaloniaXKCD.Generators/Resources/ServiceLifetime.cs +++ b/src/AvaloniaXKCD.Generators/Resources/ServiceLifetime.cs @@ -4,6 +4,6 @@ internal enum ServiceLifetime { Singleton, Scoped, - Transient + Transient, } -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Generators/Resources/ServiceProviderAttribute.cs b/src/AvaloniaXKCD.Generators/Resources/ServiceProviderAttribute.cs index 35918683..7ea4b4bd 100644 --- a/src/AvaloniaXKCD.Generators/Resources/ServiceProviderAttribute.cs +++ b/src/AvaloniaXKCD.Generators/Resources/ServiceProviderAttribute.cs @@ -3,7 +3,5 @@ namespace AvaloniaXKCD.Generators { [AttributeUsage(AttributeTargets.Class, Inherited = false)] - internal sealed class ServiceProviderAttribute : Attribute - { - } -} \ No newline at end of file + internal sealed class ServiceProviderAttribute : Attribute { } +} diff --git a/src/AvaloniaXKCD.Generators/Resources/ViewLocatorAttribute.cs b/src/AvaloniaXKCD.Generators/Resources/ViewLocatorAttribute.cs index 1c0554f6..32cf509a 100644 --- a/src/AvaloniaXKCD.Generators/Resources/ViewLocatorAttribute.cs +++ b/src/AvaloniaXKCD.Generators/Resources/ViewLocatorAttribute.cs @@ -1,7 +1,5 @@ namespace AvaloniaXKCD.Generators { [System.AttributeUsage(System.AttributeTargets.Class, Inherited = false, AllowMultiple = false)] - internal sealed class ViewLocatorAttribute : System.Attribute - { - } -} \ No newline at end of file + internal sealed class ViewLocatorAttribute : System.Attribute { } +} diff --git a/src/AvaloniaXKCD.Generators/ServiceProviderGenerator.cs b/src/AvaloniaXKCD.Generators/ServiceProviderGenerator.cs index 966b929e..d4e979e7 100644 --- a/src/AvaloniaXKCD.Generators/ServiceProviderGenerator.cs +++ b/src/AvaloniaXKCD.Generators/ServiceProviderGenerator.cs @@ -3,11 +3,11 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Scriban; -using System.Text; using Microsoft.CodeAnalysis.Text; +using Scriban; namespace AvaloniaXKCD.Generators { @@ -18,6 +18,7 @@ public class ServiceProviderGenerator : IIncrementalGenerator private const string ServiceProviderAttributeName = "AvaloniaXKCD.Generators.ServiceProviderAttribute"; public record ServiceInfo(string ImplementationType, string? ServiceType, string Lifetime); + public record TargetClassInfo(string Namespace, string ClassName); public void Initialize(IncrementalGeneratorInitializationContext context) @@ -38,18 +39,22 @@ public void Initialize(IncrementalGeneratorInitializationContext context) ctx.AddSource("ServiceAttribute.g.cs", SourceText.From(attributeSource, Encoding.UTF8)); var serviceProviderAttributeSource = GetEmbeddedResource("Resources.ServiceProviderAttribute.cs"); - ctx.AddSource("ServiceProviderAttribute.g.cs", SourceText.From(serviceProviderAttributeSource, Encoding.UTF8)); + ctx.AddSource( + "ServiceProviderAttribute.g.cs", + SourceText.From(serviceProviderAttributeSource, Encoding.UTF8) + ); }); - var servicesProvider = context.SyntaxProvider - .CreateSyntaxProvider( + var servicesProvider = context + .SyntaxProvider.CreateSyntaxProvider( static (syntax, _) => syntax is ClassDeclarationSyntax { AttributeLists.Count: > 0 }, - static (ctx, _) => TransformService(ctx)) + static (ctx, _) => TransformService(ctx) + ) .Where(static model => model is not null) .Collect(); - var targetClassProvider = context.SyntaxProvider - .CreateSyntaxProvider( + var targetClassProvider = context + .SyntaxProvider.CreateSyntaxProvider( static (node, _) => node is ClassDeclarationSyntax { AttributeLists.Count: > 0 }, static (ctx, _) => { @@ -59,34 +64,44 @@ public void Initialize(IncrementalGeneratorInitializationContext context) return null; } - var hasAttribute = typeSymbol.GetAttributes() + var hasAttribute = typeSymbol + .GetAttributes() .Any(attr => attr.AttributeClass?.ToDisplayString() == ServiceProviderAttributeName); if (hasAttribute) { - return new TargetClassInfo(typeSymbol.ContainingNamespace.ToDisplayString(), typeSymbol.Name); + return new TargetClassInfo( + typeSymbol.ContainingNamespace.ToDisplayString(), + typeSymbol.Name + ); } return null; - }) + } + ) .Where(static model => model is not null); var combinedProvider = servicesProvider.Combine(targetClassProvider.Collect()); - context.RegisterSourceOutput(combinedProvider, (spc, source) => - GenerateSource(spc, source.Left, source.Right!)); + context.RegisterSourceOutput( + combinedProvider, + (spc, source) => GenerateSource(spc, source.Left, source.Right!) + ); } private static ServiceInfo? TransformService(GeneratorSyntaxContext ctx) { - if (ctx.Node is not ClassDeclarationSyntax classDecl || - ctx.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol typeSymbol || - typeSymbol.IsAbstract) + if ( + ctx.Node is not ClassDeclarationSyntax classDecl + || ctx.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol typeSymbol + || typeSymbol.IsAbstract + ) { return null; } - var serviceAttribute = typeSymbol.GetAttributes() + var serviceAttribute = typeSymbol + .GetAttributes() .FirstOrDefault(attr => attr.AttributeClass?.ToDisplayString() == ServiceAttributeName); if (serviceAttribute == null) @@ -106,13 +121,17 @@ public void Initialize(IncrementalGeneratorInitializationContext context) 0 => "Singleton", 1 => "Scoped", 2 => "Transient", - _ => "Transient" + _ => "Transient", }; return new ServiceInfo(typeSymbol.ToDisplayString(), null, lifetimeString); } - private static void GenerateSource(SourceProductionContext spc, ImmutableArray services, ImmutableArray targets) + private static void GenerateSource( + SourceProductionContext spc, + ImmutableArray services, + ImmutableArray targets + ) { if (targets.IsDefaultOrEmpty || targets.Length == 0) { @@ -122,9 +141,13 @@ private static void GenerateSource(SourceProductionContext spc, ImmutableArray 1) { - Report(spc, "SPG001", "Multiple ServiceProvider classes", - $"Only one class can be decorated with the [ServiceProvider] attribute.", - DiagnosticSeverity.Error); + Report( + spc, + "SPG001", + "Multiple ServiceProvider classes", + $"Only one class can be decorated with the [ServiceProvider] attribute.", + DiagnosticSeverity.Error + ); return; } @@ -145,7 +168,13 @@ private static void GenerateSource(SourceProductionContext spc, ImmutableArray m.Message)); - Report(spc, "SPG103", "Scriban template parsing error", $"The Scriban template has errors:\n{errors}", DiagnosticSeverity.Error); + Report( + spc, + "SPG103", + "Scriban template parsing error", + $"The Scriban template has errors:\n{errors}", + DiagnosticSeverity.Error + ); return; } @@ -153,7 +182,7 @@ private static void GenerateSource(SourceProductionContext spc, ImmutableArray s is not null).ToList() + Services = services.Where(s => s is not null).ToList(), }; var result = template.Render(model, member => member.Name); @@ -174,10 +203,17 @@ private static string GetEmbeddedResource(string resourceName) return reader.ReadToEnd(); } - private static void Report(SourceProductionContext spc, string id, string title, string message, DiagnosticSeverity severity) + private static void Report( + SourceProductionContext spc, + string id, + string title, + string message, + DiagnosticSeverity severity + ) { - spc.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor(id, title, message, "Generator", severity, true), null)); + spc.ReportDiagnostic( + Diagnostic.Create(new DiagnosticDescriptor(id, title, message, "Generator", severity, true), null) + ); } } -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Generators/ViewLocatorGenerator.cs b/src/AvaloniaXKCD.Generators/ViewLocatorGenerator.cs index bed78380..37f431b8 100644 --- a/src/AvaloniaXKCD.Generators/ViewLocatorGenerator.cs +++ b/src/AvaloniaXKCD.Generators/ViewLocatorGenerator.cs @@ -3,11 +3,11 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; -using Scriban; -using System.Text; using Microsoft.CodeAnalysis.Text; +using Scriban; namespace AvaloniaXKCD.Generators { @@ -15,8 +15,11 @@ namespace AvaloniaXKCD.Generators public class ViewLocatorGenerator : IIncrementalGenerator { private const string AttributeName = "AvaloniaXKCD.Generators.ViewLocatorAttribute"; + public record DiscoveredType(string FullTypeName, string ClassName, string Suffix); + public record ViewModelViewPair(string ViewModel, string View); + public record TargetClassInfo(string Namespace, string ClassName); public void Initialize(IncrementalGeneratorInitializationContext context) @@ -34,14 +37,15 @@ public void Initialize(IncrementalGeneratorInitializationContext context) ctx.AddSource("ViewLocatorAttribute.g.cs", SourceText.From(attributeSource, Encoding.UTF8)); }); - var typesProvider = context.SyntaxProvider - .CreateSyntaxProvider( + var typesProvider = context + .SyntaxProvider.CreateSyntaxProvider( static (syntax, _) => syntax is ClassDeclarationSyntax, - static (ctx, _) => TransformClass(ctx)) + static (ctx, _) => TransformClass(ctx) + ) .Where(static model => model is not null); - var targetClassProvider = context.SyntaxProvider - .CreateSyntaxProvider( + var targetClassProvider = context + .SyntaxProvider.CreateSyntaxProvider( static (node, _) => node is ClassDeclarationSyntax c && c.AttributeLists.Count > 0, static (ctx, _) => { @@ -51,29 +55,38 @@ public void Initialize(IncrementalGeneratorInitializationContext context) return null; } - var hasAttribute = typeSymbol.GetAttributes() + var hasAttribute = typeSymbol + .GetAttributes() .Any(attr => attr.AttributeClass?.ToDisplayString() == AttributeName); if (hasAttribute) { - return new TargetClassInfo(typeSymbol.ContainingNamespace.ToDisplayString(), typeSymbol.Name); + return new TargetClassInfo( + typeSymbol.ContainingNamespace.ToDisplayString(), + typeSymbol.Name + ); } return null; - }) + } + ) .Where(static model => model is not null); var combinedProvider = typesProvider.Collect().Combine(targetClassProvider.Collect()); - context.RegisterSourceOutput(combinedProvider, (spc, source) => - GenerateSource(spc, source.Left, source.Right)); + context.RegisterSourceOutput( + combinedProvider, + (spc, source) => GenerateSource(spc, source.Left, source.Right) + ); } private static DiscoveredType? TransformClass(GeneratorSyntaxContext ctx) { - if (ctx.Node is not ClassDeclarationSyntax classDecl || - ctx.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol typeSymbol || - typeSymbol.IsAbstract) + if ( + ctx.Node is not ClassDeclarationSyntax classDecl + || ctx.SemanticModel.GetDeclaredSymbol(classDecl) is not INamedTypeSymbol typeSymbol + || typeSymbol.IsAbstract + ) { return null; } @@ -94,7 +107,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context) return null; } - private static void GenerateSource(SourceProductionContext spc, ImmutableArray types, ImmutableArray targets) + private static void GenerateSource( + SourceProductionContext spc, + ImmutableArray types, + ImmutableArray targets + ) { if (targets.IsDefaultOrEmpty || targets.Length == 0) { @@ -104,9 +121,13 @@ private static void GenerateSource(SourceProductionContext spc, ImmutableArray 1) { - Report(spc, "XKC001", "Multiple ViewLocator classes", - $"Only one class can be decorated with the [ViewLocator] attribute.", - DiagnosticSeverity.Error); + Report( + spc, + "XKC001", + "Multiple ViewLocator classes", + $"Only one class can be decorated with the [ViewLocator] attribute.", + DiagnosticSeverity.Error + ); return; } @@ -118,15 +139,15 @@ private static void GenerateSource(SourceProductionContext spc, ImmutableArray t!.Suffix == "View") - .ToDictionary( - t => t!.ClassName.Substring(0, t.ClassName.Length - "View".Length), - t => t!.FullTypeName - ); + .ToDictionary(t => t!.ClassName.Substring(0, t.ClassName.Length - "View".Length), t => t!.FullTypeName); var pairs = new List(); foreach (var viewModel in viewModels) { - var viewModelBaseName = viewModel!.ClassName.Substring(0, viewModel.ClassName.Length - "ViewModel".Length); + var viewModelBaseName = viewModel!.ClassName.Substring( + 0, + viewModel.ClassName.Length - "ViewModel".Length + ); if (viewsByBaseName.TryGetValue(viewModelBaseName, out var matchedViewFullName)) { @@ -135,9 +156,13 @@ private static void GenerateSource(SourceProductionContext spc, ImmutableArray m.Message)); - Report(spc, "XKC103", "Scriban template parsing error", $"The Scriban template has errors:\n{errors}", DiagnosticSeverity.Error); + Report( + spc, + "XKC103", + "Scriban template parsing error", + $"The Scriban template has errors:\n{errors}", + DiagnosticSeverity.Error + ); return; } @@ -164,7 +195,7 @@ private static void GenerateSource(SourceProductionContext spc, ImmutableArray member.Name); @@ -176,17 +207,27 @@ private static string GetEmbeddedResource(string resourceName) var assembly = typeof(ViewLocatorGenerator).Assembly; var fullName = $"AvaloniaXKCD.Generators.{resourceName}"; - using var stream = assembly.GetManifestResourceStream(fullName) - ?? throw new FileNotFoundException($"Embedded resource '{fullName}' not found. Available: {string.Join(", ", assembly.GetManifestResourceNames())}"); + using var stream = + assembly.GetManifestResourceStream(fullName) + ?? throw new FileNotFoundException( + $"Embedded resource '{fullName}' not found. Available: {string.Join(", ", assembly.GetManifestResourceNames())}" + ); using var reader = new StreamReader(stream); return reader.ReadToEnd(); } - private static void Report(SourceProductionContext spc, string id, string title, string message, DiagnosticSeverity severity) + private static void Report( + SourceProductionContext spc, + string id, + string title, + string message, + DiagnosticSeverity severity + ) { - spc.ReportDiagnostic(Diagnostic.Create( - new DiagnosticDescriptor(id, title, message, "Generator", severity, true), null)); + spc.ReportDiagnostic( + Diagnostic.Create(new DiagnosticDescriptor(id, title, message, "Generator", severity, true), null) + ); } } -} \ No newline at end of file +} diff --git a/src/AvaloniaXKCD.Site/.prettierignore b/src/AvaloniaXKCD.Site/.prettierignore new file mode 100644 index 00000000..caaa7803 --- /dev/null +++ b/src/AvaloniaXKCD.Site/.prettierignore @@ -0,0 +1,10 @@ +node_modules +dist +out +build +.vite +xliff +bun.lock +package-lock.json +*.config.js +*.config.ts diff --git a/src/AvaloniaXKCD.Site/.prettierrc.json b/src/AvaloniaXKCD.Site/.prettierrc.json new file mode 100644 index 00000000..c0143348 --- /dev/null +++ b/src/AvaloniaXKCD.Site/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "useTabs": false, + "printWidth": 100, + "trailingComma": "es5", + "arrowParens": "always", + "endOfLine": "lf" +} diff --git a/src/AvaloniaXKCD.Site/README.md b/src/AvaloniaXKCD.Site/README.md index 75e23a30..3ee54166 100644 --- a/src/AvaloniaXKCD.Site/README.md +++ b/src/AvaloniaXKCD.Site/README.md @@ -4,23 +4,23 @@ Contains web frontend for AvaloniaXKCD. Hosts WASM application and provides Type ## Project provides -- **WASM Hosting:** Hosts `AvaloniaXKCD.Browser` WASM app and provides infrastructure. -- **TypeScript Integration:** Contains TypeScript code integrating with C# WASM app for communication. -- **Asset Management:** Manages web assets (HTML, CSS, JS). +- **WASM Hosting:** Hosts `AvaloniaXKCD.Browser` WASM app and provides infrastructure. +- **TypeScript Integration:** Contains TypeScript code integrating with C# WASM app for communication. +- **Asset Management:** Manages web assets (HTML, CSS, JS). ## TypeScript layer responsibilities -- Initializes WASM app and provides configuration. -- Integrates WASM app with DOM for UI rendering. -- Handles browser events, forwards to WASM app. +- Initializes WASM app and provides configuration. +- Integrates WASM app with DOM for UI rendering. +- Handles browser events, forwards to WASM app. ## Development ### Prerequisites -- Bun -- TypeScript -- .NET SDK +- Bun +- TypeScript +- .NET SDK ### Local Development @@ -40,11 +40,11 @@ make publish-browser ## Integration -- Handles TypeScript/web logic. -- `AvaloniaXKCD.Browser`: C# WASM code. -- Components work together for web experience. +- Handles TypeScript/web logic. +- `AvaloniaXKCD.Browser`: C# WASM code. +- Components work together for web experience. ## Resources - [Project Architecture](../README.md) -- [Browser Component](../AvaloniaXKCD.Browser/README.md) \ No newline at end of file +- [Browser Component](../AvaloniaXKCD.Browser/README.md) diff --git a/src/AvaloniaXKCD.Site/bun.lock b/src/AvaloniaXKCD.Site/bun.lock index 15ba4a17..2cb0d34c 100644 --- a/src/AvaloniaXKCD.Site/bun.lock +++ b/src/AvaloniaXKCD.Site/bun.lock @@ -9,17 +9,22 @@ "lit": "^3.3.1", }, "devDependencies": { + "@eslint/js": "^9.18.0", "@lit/localize-tools": "^0.8.0", + "@types/eslint__js": "^8.42.3", "@types/fs-extra": "^11.0.4", "@types/glob": "^9.0.0", "@types/html-minifier-terser": "^7.0.2", "@types/node": "^24.10.0", "@vite-pwa/assets-generator": "^1.0.2", + "eslint": "^9.18.0", "fs-extra": "^11.3.2", "glob": "^11.0.3", "html-minifier-terser": "^7.2.0", + "prettier": "^3.4.2", "rollup-plugin-minify-template-literals": "^1.1.7", "typescript": "~5.9.3", + "typescript-eslint": "^8.19.1", "vite": "npm:rolldown-vite@7.1.14", "vite-plugin-pwa": "^1.1.0", "vite-plugin-singlefile": "^2.3.0", @@ -220,6 +225,32 @@ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], + + "@eslint/config-array": ["@eslint/config-array@0.21.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="], + + "@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="], + + "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], + + "@eslint/js": ["@eslint/js@9.39.1", "", {}, "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw=="], + + "@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="], + + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], + + "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="], "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="], @@ -388,6 +419,10 @@ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], + "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], + + "@types/eslint__js": ["@types/eslint__js@8.42.3", "", { "dependencies": { "@types/eslint": "*" } }, "sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw=="], + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/fs-extra": ["@types/fs-extra@11.0.4", "", { "dependencies": { "@types/jsonfile": "*", "@types/node": "*" } }, "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ=="], @@ -396,6 +431,8 @@ "@types/html-minifier-terser": ["@types/html-minifier-terser@7.0.2", "", {}, "sha512-mm2HqV22l8lFQh4r2oSsOEVea+m0qqxEmwpc9kC1p/XzmjLWrReR9D/GRs8Pex2NX/imyEH9c5IU/7tMBQCHOA=="], + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + "@types/jsonfile": ["@types/jsonfile@6.1.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ=="], "@types/node": ["@types/node@24.10.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A=="], @@ -404,20 +441,44 @@ "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.46.4", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.46.4", "@typescript-eslint/type-utils": "8.46.4", "@typescript-eslint/utils": "8.46.4", "@typescript-eslint/visitor-keys": "8.46.4", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.46.4", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-R48VhmTJqplNyDxCyqqVkFSZIx1qX6PzwqgcXn1olLrzxcSBDlOsbtcnQuQhNtnNiJ4Xe5gREI1foajYaYU2Vg=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.46.4", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.46.4", "@typescript-eslint/types": "8.46.4", "@typescript-eslint/typescript-estree": "8.46.4", "@typescript-eslint/visitor-keys": "8.46.4", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w=="], + + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.46.4", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.46.4", "@typescript-eslint/types": "^8.46.4", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.46.4", "", { "dependencies": { "@typescript-eslint/types": "8.46.4", "@typescript-eslint/visitor-keys": "8.46.4" } }, "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA=="], + + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.46.4", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.46.4", "", { "dependencies": { "@typescript-eslint/types": "8.46.4", "@typescript-eslint/typescript-estree": "8.46.4", "@typescript-eslint/utils": "8.46.4", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.46.4", "", {}, "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.46.4", "", { "dependencies": { "@typescript-eslint/project-service": "8.46.4", "@typescript-eslint/tsconfig-utils": "8.46.4", "@typescript-eslint/types": "8.46.4", "@typescript-eslint/visitor-keys": "8.46.4", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.46.4", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.46.4", "@typescript-eslint/types": "8.46.4", "@typescript-eslint/typescript-estree": "8.46.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.46.4", "", { "dependencies": { "@typescript-eslint/types": "8.46.4", "eslint-visitor-keys": "^4.2.1" } }, "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw=="], + "@vite-pwa/assets-generator": ["@vite-pwa/assets-generator@1.0.2", "", { "dependencies": { "cac": "^6.7.14", "colorette": "^2.0.20", "consola": "^3.4.2", "sharp": "^0.33.5", "sharp-ico": "^0.1.5", "unconfig": "^7.3.1" }, "bin": { "pwa-assets-generator": "bin/pwa-assets-generator.mjs" } }, "sha512-MCbrb508JZHqe7bUibmZj/lyojdhLRnfkmyXnkrCM2zVrjTgL89U8UEfInpKTvPeTnxsw2hmyZxnhsdNR6yhwg=="], "@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="], "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], - "ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - "ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="], + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="], "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="], @@ -456,10 +517,14 @@ "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + "camel-case": ["camel-case@4.1.2", "", { "dependencies": { "pascal-case": "^3.1.2", "tslib": "^2.0.3" } }, "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw=="], "caniuse-lite": ["caniuse-lite@1.0.30001753", "", {}, "sha512-Bj5H35MD/ebaOV4iDLqPEtiliTN29qkGtEHCwawWn4cYm+bPJM2NsaP30vtZcnERClMzp52J4+aw2UNbK4o+zw=="], + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + "clean-css": ["clean-css@5.3.3", "", { "dependencies": { "source-map": "~0.6.0" } }, "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg=="], "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], @@ -500,6 +565,8 @@ "decode-ico": ["decode-ico@0.4.1", "", { "dependencies": { "@canvas/image-data": "^1.0.0", "decode-bmp": "^0.2.0", "to-data-view": "^1.1.0" } }, "sha512-69NZfbKIzux1vBOd31al3XnMnH+2mqDhEgLdpygErm4d60N+UwA5Sq5WFjmEDQzumgB9fElojGwWG0vybVfFmA=="], + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], @@ -538,6 +605,22 @@ "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@9.39.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.39.1", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g=="], + + "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], + + "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], @@ -548,16 +631,26 @@ "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + "filelist": ["filelist@1.0.4", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], @@ -588,7 +681,9 @@ "glob": ["glob@11.0.3", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.0.3", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA=="], - "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], @@ -596,8 +691,12 @@ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], + "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="], @@ -614,6 +713,12 @@ "idb": ["idb@7.1.1", "", {}, "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ=="], + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], @@ -694,11 +799,17 @@ "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="], - "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], @@ -708,8 +819,12 @@ "jsonschema": ["jsonschema@1.5.0", "", {}, "sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw=="], + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + "leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="], + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + "lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="], "lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="], @@ -740,10 +855,14 @@ "lit-html": ["lit-html@3.3.1", "", { "dependencies": { "@types/trusted-types": "^2.0.2" } }, "sha512-S9hbyDu/vs1qNrithiNyeyv64c9yqiW9l+DBgI18fL+MTvOtWoFR0FWiyq1TxaYef5wNlpEmzlXoBlZEO+WjoA=="], + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="], + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + "lodash.sortby": ["lodash.sortby@4.7.0", "", {}, "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="], "lower-case": ["lower-case@2.0.2", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg=="], @@ -760,7 +879,7 @@ "minify-literals": ["minify-literals@1.0.10", "", { "dependencies": { "clean-css": "^5.3.3", "html-minifier-terser": "^7.2.0", "magic-string": "^0.30.7", "parse-literals": "^1.2.1" } }, "sha512-3gzrwHTd7kRTqsoGhGw4iySDy7JGgc3RozKZ7IT9vcXPyno5egKkpFqud+F1ECSPxi/ls2JwQCUYZr5SeUci0Q=="], - "minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], @@ -770,6 +889,8 @@ "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + "no-case": ["no-case@3.0.4", "", { "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" } }, "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg=="], "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="], @@ -782,18 +903,28 @@ "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="], + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], "param-case": ["param-case@3.0.4", "", { "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A=="], + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + "parse-literals": ["parse-literals@1.2.1", "", { "dependencies": { "typescript": "^2.9.2 || ^3.0.0 || ^4.0.0" } }, "sha512-Ml0w104Ph2wwzuRdxrg9booVWsngXbB4bZ5T2z6WyF8b5oaNkUmBiDtahi34yUIpXD8Y13JjAK6UyIyApJ73RQ=="], "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], "pascal-case": ["pascal-case@3.1.2", "", { "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g=="], + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], @@ -810,6 +941,10 @@ "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], + "pretty-bytes": ["pretty-bytes@6.1.1", "", {}, "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ=="], "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], @@ -840,6 +975,8 @@ "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], "rolldown": ["rolldown@1.0.0-beta.41", "", { "dependencies": { "@oxc-project/types": "=0.93.0", "@rolldown/pluginutils": "1.0.0-beta.41", "ansis": "=4.2.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-beta.41", "@rolldown/binding-darwin-arm64": "1.0.0-beta.41", "@rolldown/binding-darwin-x64": "1.0.0-beta.41", "@rolldown/binding-freebsd-x64": "1.0.0-beta.41", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.41", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.41", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.41", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.41", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.41", "@rolldown/binding-openharmony-arm64": "1.0.0-beta.41", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.41", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.41", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.41", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.41" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-U+NPR0Bkg3wm61dteD2L4nAM1U9dtaqVrpDXwC36IKRHpEO/Ubpid4Nijpa2imPchcVNHfxVFwSSMJdwdGFUbg=="], @@ -920,6 +1057,10 @@ "strip-comments": ["strip-comments@2.0.1", "", {}, "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw=="], + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], "temp-dir": ["temp-dir@2.0.0", "", {}, "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg=="], @@ -936,8 +1077,12 @@ "tr46": ["tr46@1.0.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA=="], + "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + "type-fest": ["type-fest@0.16.0", "", {}, "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg=="], "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="], @@ -950,6 +1095,8 @@ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + "typescript-eslint": ["typescript-eslint@8.46.4", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.46.4", "@typescript-eslint/parser": "8.46.4", "@typescript-eslint/typescript-estree": "8.46.4", "@typescript-eslint/utils": "8.46.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-KALyxkpYV5Ix7UhvjTwJXZv76VWsHG+NjNlt/z+a17SOQSiOcBdUXdbJdyXi7RPxrBFECtFOiPwUJQusJuCqrg=="], + "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], "unconfig": ["unconfig@7.3.3", "", { "dependencies": { "@quansync/fs": "^0.1.5", "defu": "^6.1.4", "jiti": "^2.5.1", "quansync": "^0.2.11" } }, "sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA=="], @@ -972,6 +1119,8 @@ "update-browserslist-db": ["update-browserslist-db@1.1.4", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A=="], + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + "vite": ["rolldown-vite@7.1.14", "", { "dependencies": { "@oxc-project/runtime": "0.92.0", "fdir": "^6.5.0", "lightningcss": "^1.30.1", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rolldown": "1.0.0-beta.41", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "esbuild": "^0.25.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-eSiiRJmovt8qDJkGyZuLnbxAOAdie6NCmmd0NkTC0RJI9duiSBTfr8X2mBYJOUFzxQa2USaHmL99J9uMxkjCyw=="], "vite-plugin-pwa": ["vite-plugin-pwa@1.1.0", "", { "dependencies": { "debug": "^4.3.6", "pretty-bytes": "^6.1.1", "tinyglobby": "^0.2.10", "workbox-build": "^7.3.0", "workbox-window": "^7.3.0" }, "peerDependencies": { "@vite-pwa/assets-generator": "^1.0.0", "vite": "^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["@vite-pwa/assets-generator"] }, "sha512-VsSpdubPzXhHWVINcSx6uHRMpOHVHQcHsef1QgkOlEoaIDAlssFEW88LBq1a59BuokAhsh2kUDJbaX1bZv4Bjw=="], @@ -992,6 +1141,8 @@ "which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="], + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + "workbox-background-sync": ["workbox-background-sync@7.3.0", "", { "dependencies": { "idb": "^7.0.1", "workbox-core": "7.3.0" } }, "sha512-PCSk3eK7Mxeuyatb22pcSx9dlgWNv3+M8PqPaYDokks8Y5/FX4soaOqj3yhAZr5k6Q5JWTOMYgaJBpbw11G9Eg=="], "workbox-broadcast-update": ["workbox-broadcast-update@7.3.0", "", { "dependencies": { "workbox-core": "7.3.0" } }, "sha512-T9/F5VEdJVhwmrIAE+E/kq5at2OY6+OXXgOWQevnubal6sO92Gjo24v6dCVwQiclAF5NS3hlmsifRrpQzZCdUA=="], @@ -1032,6 +1183,10 @@ "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "@apideck/better-ajv-errors/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], @@ -1044,6 +1199,8 @@ "@babel/preset-env/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@lit/localize-tools/fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], "@lit/localize-tools/typescript": ["typescript@5.5.4", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q=="], @@ -1064,10 +1221,18 @@ "@types/jsonfile/@types/node": ["@types/node@24.9.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA=="], + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], + "glob/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "parse-literals/typescript": ["typescript@4.9.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g=="], @@ -1082,6 +1247,8 @@ "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + "workbox-build/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], + "workbox-build/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], "workbox-build/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], @@ -1092,12 +1259,14 @@ "workbox-build/source-map": ["source-map@0.8.0-beta.0", "", { "dependencies": { "whatwg-url": "^7.0.0" } }, "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA=="], - "wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "@apideck/better-ajv-errors/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + "@rollup/plugin-babel/@rollup/pluginutils/@types/estree": ["@types/estree@0.0.39", "", {}, "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="], "@rollup/plugin-babel/@rollup/pluginutils/estree-walker": ["estree-walker@1.0.1", "", {}, "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg=="], @@ -1110,11 +1279,13 @@ "@rollup/plugin-replace/@rollup/pluginutils/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + "filelist/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "workbox-build/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "workbox-build/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], diff --git a/src/AvaloniaXKCD.Site/eslint.config.js b/src/AvaloniaXKCD.Site/eslint.config.js new file mode 100644 index 00000000..6f78e8e1 --- /dev/null +++ b/src/AvaloniaXKCD.Site/eslint.config.js @@ -0,0 +1,57 @@ +// @ts-check + +import eslint from '@eslint/js'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config( + eslint.configs.recommended, + ...tseslint.configs.recommended, + { + languageOptions: { + parserOptions: { + project: true, + tsconfigRootDir: import.meta.dirname, + }, + }, + }, + { + ignores: [ + '**/node_modules/**', + '**/dist/**', + '**/out/**', + '**/build/**', + '**/.vite/**', + '**/xliff/**', + 'src/localization/locales/**', + 'vite.config.ts', + 'pwa-assets.config.ts', + '**/types/dotnet.d.ts', + 'plugins/**', + 'scripts/**', + 'eslint.config.js', + ], + }, + { + rules: { + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-unused-vars': [ + 'warn', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + }, + ], + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-non-null-assertion': 'error', + '@typescript-eslint/no-unsafe-assignment': 'error', + '@typescript-eslint/no-unsafe-member-access': 'error', + '@typescript-eslint/no-unsafe-call': 'error', + '@typescript-eslint/no-unsafe-return': 'error', + '@typescript-eslint/no-unsafe-argument': 'error', + '@typescript-eslint/unbound-method': 'error', + '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/no-unnecessary-type-assertion': 'error', + }, + } +); diff --git a/src/AvaloniaXKCD.Site/index.html b/src/AvaloniaXKCD.Site/index.html index 74b3b33e..699c37d0 100644 --- a/src/AvaloniaXKCD.Site/index.html +++ b/src/AvaloniaXKCD.Site/index.html @@ -1,63 +1,132 @@ - + + + A(valonia)XKCD + + + + + + - - A(valonia)XKCD - - - - - - - - - - A(valonia)XKCD - Because laughing in C# is still (technically) laughing. - In Development - - - - - - - This page requires JavaScript to function properly. - Please enable JavaScript in your browser settings and refresh the page. - - + + + A(valonia)XKCD + Because laughing in C# is still (technically) laughing. + + In Development - - - - - - + + + + + + + This page requires JavaScript to function properly. + Please enable JavaScript in your browser settings and refresh the page. + + + + + + - \ No newline at end of file + + +
Because laughing in C# is still (technically) laughing.
This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings and refresh the page.