diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 4ea5c4c8..5245c50e 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -18,156 +18,162 @@ $finder = new Finder()->in(__DIR__)->exclude([ return new Config() ->setRiskyAllowed(true) ->setRules([ - 'array_syntax' => ['syntax' => 'short'], - 'assign_null_coalescing_to_coalesce_equal' => true, - 'attribute_empty_parentheses' => ['use_parentheses' => true], - 'blank_line_after_namespace' => true, - 'blank_lines_before_namespace' => ['min_line_breaks' => 1, 'max_line_breaks' => 2], - 'cast_spaces' => true, - 'class_attributes_separation' => [ - 'elements' => [ - 'case' => 'none', - 'const' => 'none', - 'method' => 'one', - 'property' => 'one', - 'trait_import' => 'none', - ], + 'array_syntax' => ['syntax' => 'short'], + 'assign_null_coalescing_to_coalesce_equal' => true, + 'attribute_empty_parentheses' => ['use_parentheses' => true], + 'blank_line_after_namespace' => true, + 'blank_lines_before_namespace' => ['min_line_breaks' => 1, 'max_line_breaks' => 2], + 'cast_spaces' => true, + 'class_attributes_separation' => ['elements' => [ + 'case' => 'none', + 'const' => 'none', + 'method' => 'one', + 'property' => 'one', + 'trait_import' => 'none', + ]], + 'class_reference_name_casing' => true, + 'clean_namespace' => true, + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, + 'combine_nested_dirname' => true, + 'comment_to_phpdoc' => true, + 'constant_case' => true, + 'date_time_immutable' => true, + 'declare_equal_normalize' => true, + 'declare_parentheses' => true, + 'declare_strict_types' => true, + 'dir_constant' => true, + 'echo_tag_syntax' => true, + 'encoding' => true, + 'ereg_to_preg' => true, + 'error_suppression' => true, + 'explicit_indirect_variable' => true, + 'explicit_string_variable' => true, + 'final_class' => true, + 'final_internal_class' => true, + 'full_opening_tag' => true, + 'fully_qualified_strict_types' => ['import_symbols' => true], + 'function_to_constant' => true, + 'global_namespace_import' => [ + 'import_classes' => true, + 'import_constants' => true, + 'import_functions' => true, ], - 'class_reference_name_casing' => true, - 'clean_namespace' => true, - 'combine_consecutive_issets' => true, - 'combine_consecutive_unsets' => true, - 'combine_nested_dirname' => true, - 'comment_to_phpdoc' => true, - 'constant_case' => true, - 'date_time_immutable' => true, - 'declare_equal_normalize' => true, - 'declare_parentheses' => true, - 'declare_strict_types' => true, - 'dir_constant' => true, - 'echo_tag_syntax' => true, - 'encoding' => true, - 'ereg_to_preg' => true, - 'error_suppression' => true, - 'explicit_indirect_variable' => true, - 'explicit_string_variable' => true, - 'final_class' => true, - 'final_internal_class' => true, - 'full_opening_tag' => true, - 'fully_qualified_strict_types' => ['import_symbols' => true], - 'function_to_constant' => true, - 'global_namespace_import' => ['import_classes' => true, 'import_constants' => true, 'import_functions' => true], - 'heredoc_to_nowdoc' => true, - 'integer_literal_case' => true, - 'lambda_not_used_import' => true, - 'list_syntax' => true, - 'logical_operators' => true, - 'long_to_shorthand_operator' => true, - 'lowercase_cast' => true, - 'lowercase_keywords' => true, - 'lowercase_static_reference' => true, - 'magic_constant_casing' => true, - 'magic_method_casing' => true, - 'mb_str_functions' => true, - 'modernize_strpos' => ['modernize_stripos' => true], - 'modernize_types_casting' => true, - 'modifier_keywords' => true, - 'multiline_comment_opening_closing' => true, - 'native_constant_invocation' => true, - 'native_function_casing' => true, - 'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'namespaced', 'strict' => true], - 'native_type_declaration_casing' => true, - 'new_expression_parentheses' => true, - 'no_alias_functions' => ['sets' => ['@all']], - 'no_alias_language_construct_call' => true, - 'no_alternative_syntax' => true, - 'no_binary_string' => true, - 'no_closing_tag' => true, - 'no_empty_comment' => true, - 'no_homoglyph_names' => true, - 'no_leading_import_slash' => true, - 'no_mixed_echo_print' => ['use' => 'echo'], - 'no_multiline_whitespace_around_double_arrow' => true, - 'no_multiple_statements_per_line' => true, - 'no_null_property_initialization' => true, - 'no_php4_constructor' => true, - 'no_short_bool_cast' => true, - 'no_trailing_comma_in_singleline' => true, - 'no_trailing_whitespace_in_comment' => true, - 'no_unneeded_braces' => ['namespaces' => true], - 'no_unneeded_control_parentheses' => [ - 'statements' => [ - 'break', - 'clone', - 'continue', - 'echo_print', - 'negative_instanceof', - 'others', - 'return', - 'switch_case', - 'yield', - 'yield_from', - ], + 'heredoc_to_nowdoc' => true, + 'integer_literal_case' => true, + 'lambda_not_used_import' => true, + 'list_syntax' => true, + 'logical_operators' => true, + 'long_to_shorthand_operator' => true, + 'lowercase_cast' => true, + 'lowercase_keywords' => true, + 'lowercase_static_reference' => true, + 'magic_constant_casing' => true, + 'magic_method_casing' => true, + 'mb_str_functions' => true, + 'modernize_strpos' => ['modernize_stripos' => true], + 'modernize_types_casting' => true, + 'modifier_keywords' => true, + 'multiline_comment_opening_closing' => true, + 'native_constant_invocation' => true, + 'native_function_casing' => true, + 'native_function_invocation' => [ + 'include' => ['@compiler_optimized'], + 'scope' => 'namespaced', + 'strict' => true, ], - 'no_unneeded_final_method' => true, - 'no_unneeded_import_alias' => true, - 'no_unreachable_default_argument_value' => true, - 'no_unset_cast' => true, - 'no_unset_on_property' => true, - 'no_unused_imports' => true, - 'no_useless_concat_operator' => true, - 'no_useless_nullsafe_operator' => true, - 'no_useless_printf' => true, - 'no_useless_return' => true, - 'no_useless_sprintf' => true, - 'no_whitespace_before_comma_in_array' => ['after_heredoc' => true], - 'non_printable_character' => true, - 'normalize_index_brace' => true, - 'nullable_type_declaration' => ['syntax' => 'union'], + 'native_type_declaration_casing' => true, + 'new_expression_parentheses' => true, + 'no_alias_functions' => ['sets' => ['@all']], + 'no_alias_language_construct_call' => true, + 'no_alternative_syntax' => true, + 'no_binary_string' => true, + 'no_closing_tag' => true, + 'no_empty_comment' => true, + 'no_homoglyph_names' => true, + 'no_leading_import_slash' => true, + 'no_mixed_echo_print' => ['use' => 'echo'], + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_multiple_statements_per_line' => true, + 'no_null_property_initialization' => true, + 'no_php4_constructor' => true, + 'no_short_bool_cast' => true, + 'no_trailing_comma_in_singleline' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_unneeded_braces' => ['namespaces' => true], + 'no_unneeded_control_parentheses' => ['statements' => [ + 'break', + 'clone', + 'continue', + 'echo_print', + 'negative_instanceof', + 'others', + 'return', + 'switch_case', + 'yield', + 'yield_from', + ]], + 'no_unneeded_final_method' => true, + 'no_unneeded_import_alias' => true, + 'no_unreachable_default_argument_value' => true, + 'no_unset_cast' => true, + 'no_unset_on_property' => true, + 'no_unused_imports' => true, + 'no_useless_concat_operator' => true, + 'no_useless_nullsafe_operator' => true, + 'no_useless_printf' => true, + 'no_useless_return' => true, + 'no_useless_sprintf' => true, + 'no_whitespace_before_comma_in_array' => ['after_heredoc' => true], + 'non_printable_character' => true, + 'normalize_index_brace' => true, + 'nullable_type_declaration' => ['syntax' => 'union'], 'nullable_type_declaration_for_default_null_value' => true, - 'numeric_literal_separator' => ['override_existing' => true, 'strategy' => 'use_separator'], - 'ordered_attributes' => true, - 'ordered_class_elements' => ['case_sensitive' => false, 'sort_algorithm' => 'alpha'], - 'ordered_imports' => ['case_sensitive' => true], - 'ordered_interfaces' => true, - 'ordered_traits' => true, - 'ordered_types' => ['null_adjustment' => 'always_last'], - 'phpdoc_readonly_class_comment_to_keyword' => true, - 'phpdoc_to_param_type' => true, - 'phpdoc_to_property_type' => true, - 'phpdoc_to_return_type' => true, - 'pow_to_exponentiation' => true, - 'protected_to_private' => true, - 'psr_autoloading' => true, - 'random_api_migration' => [ - 'replacements' => ['getrandmax' => 'mt_getrandmax', 'rand' => 'mt_rand', 'srand' => 'mt_srand'], - ], - 'return_assignment' => true, - 'self_accessor' => true, - 'self_static_accessor' => true, - 'set_type_to_cast' => true, - 'short_scalar_cast' => true, - 'simple_to_complex_string_variable' => true, - 'simplified_null_return' => true, - 'single_class_element_per_statement' => true, - 'single_import_per_statement' => true, - 'single_line_after_imports' => true, - 'single_line_comment_spacing' => true, - 'single_line_comment_style' => true, - 'single_line_empty_body' => true, - 'single_trait_insert_per_statement' => true, - 'standardize_not_equals' => true, - 'static_lambda' => true, - 'strict_comparison' => true, - 'strict_param' => true, - 'string_implicit_backslashes' => true, - 'string_length_to_empty' => true, - 'switch_continue_to_break' => true, - 'ternary_to_null_coalescing' => true, - 'trim_array_spaces' => true, - 'use_arrow_functions' => true, - 'void_return' => true, - 'whitespace_after_comma_in_array' => ['ensure_single_space' => true], + 'numeric_literal_separator' => ['override_existing' => true, 'strategy' => 'use_separator'], + 'ordered_attributes' => true, + 'ordered_class_elements' => ['case_sensitive' => false, 'sort_algorithm' => 'alpha'], + 'ordered_imports' => ['case_sensitive' => true], + 'ordered_interfaces' => true, + 'ordered_traits' => true, + 'ordered_types' => ['null_adjustment' => 'always_last'], + 'phpdoc_readonly_class_comment_to_keyword' => true, + 'phpdoc_to_param_type' => true, + 'phpdoc_to_property_type' => true, + 'phpdoc_to_return_type' => true, + 'pow_to_exponentiation' => true, + 'protected_to_private' => true, + 'psr_autoloading' => true, + 'random_api_migration' => ['replacements' => [ + 'getrandmax' => 'mt_getrandmax', + 'rand' => 'mt_rand', + 'srand' => 'mt_srand', + ]], + 'return_assignment' => true, + 'self_accessor' => true, + 'self_static_accessor' => true, + 'set_type_to_cast' => true, + 'short_scalar_cast' => true, + 'simple_to_complex_string_variable' => true, + 'simplified_null_return' => true, + 'single_class_element_per_statement' => true, + 'single_import_per_statement' => true, + 'single_line_after_imports' => true, + 'single_line_comment_spacing' => true, + 'single_line_comment_style' => true, + 'single_line_empty_body' => true, + 'single_trait_insert_per_statement' => true, + 'standardize_not_equals' => true, + 'static_lambda' => true, + 'strict_comparison' => true, + 'strict_param' => true, + 'string_implicit_backslashes' => true, + 'string_length_to_empty' => true, + 'switch_continue_to_break' => true, + 'ternary_to_null_coalescing' => true, + 'trim_array_spaces' => true, + 'use_arrow_functions' => true, + 'void_return' => true, + 'whitespace_after_comma_in_array' => ['ensure_single_space' => true], // --- // Each line of multi-line DocComments must have an asterisk [PSR-5] and must be aligned with the first one. 'align_multiline_comment' => ['comment_type' => 'all_multiline'], @@ -178,7 +184,7 @@ return new Config() // Removes @param, @return and @var tags that don't provide any useful information. 'no_superfluous_phpdoc_tags' => [ 'allow_hidden_params' => false, - 'allow_mixed' => false, + 'allow_mixed' => false, 'allow_unused_params' => false, ], // PHPDoc should contain @param for all params. @@ -216,22 +222,20 @@ return new Config() // The type of @return annotations of methods returning a reference to itself must the configured one. 'phpdoc_return_self_reference' => true, // Scalar types should always be written in the same form. int not integer, bool not boolean, float not real or double. - 'phpdoc_scalar' => [ - 'types' => [ - 'boolean', - 'callback', - 'double', - 'integer', - 'never-return', - 'never-returns', - 'no-return', - 'real', - 'str', - ], - ], + 'phpdoc_scalar' => ['types' => [ + 'boolean', + 'callback', + 'double', + 'integer', + 'never-return', + 'never-returns', + 'no-return', + 'real', + 'str', + ]], // Annotations in PHPDoc should be grouped together so that annotations of the same type immediately follow each other. Annotations of a different type are separated by a single blank line. 'phpdoc_separation' => [ - 'groups' => [ + 'groups' => [ ['Annotation', 'NamedArgumentConstructor', 'Target'], ['author', 'copyright', 'license'], ['category', 'package', 'subpackage'], diff --git a/.phpactor.json b/.phpactor.json index d068e282..6e322646 100755 --- a/.phpactor.json +++ b/.phpactor.json @@ -1,11 +1,5 @@ { "$schema": "./phpactor.schema.json", - "indexer.exclude_patterns": [ - "/var/cache/**/*", - "/vendor/**/tests/**/*", - "/vendor/**/Tests/**/*", - "/vendor/composer/**/*" - ], "language_server.diagnostic_outsource_timeout": 5, "language_server.diagnostics_on_save": true, "language_server.diagnostics_on_update": true, diff --git a/.phpantom.toml b/.phpantom.toml new file mode 100644 index 00000000..e9d05ba5 --- /dev/null +++ b/.phpantom.toml @@ -0,0 +1,19 @@ +# :schema: https://github.com/AJenbo/phpantom_lsp/raw/main/config-schema.json + +[php] + # Override the detected PHP version (default: inferred from composer.json, or 8.5). + # version = "8.5" + # + +[diagnostics] + extra-arguments = true + # Report member access on subjects whose type could not be resolved. + # Useful for discovering gaps in type coverage. Off by default. + unresolved-member-access = false + +[indexing] + # How PHPantom discovers classes across the workspace. + # "composer" (default) - use Composer classmap, self-scan on fallback + # "self" - always self-scan, ignore Composer classmap + # "none" - no proactive scanning, Composer classmap only + strategy = "composer" diff --git a/.zed/settings.json b/.zed/settings.json index c4e389e2..3b8077e7 100644 --- a/.zed/settings.json +++ b/.zed/settings.json @@ -9,8 +9,10 @@ "!oxc", "!oxfmt", "!oxlint", + "!phptools", "!prettier", "!tailwindcss-language-server", + "!tsgo", "!vtsls", "..." ], diff --git a/aube-lock.yaml b/aube-lock.yaml index f12c431a..3809c4e0 100644 --- a/aube-lock.yaml +++ b/aube-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +time: + globals@17.6.0: 2026-05-01T16:37:48.055Z + importers: .: @@ -12,14 +15,17 @@ importers: specifier: v4.0.0-rc.5 version: 4.0.0-rc.5 '@sentry/browser': - specifier: ^10.50.0 - version: 10.50.0 + specifier: ^10.51.0 + version: 10.51.0 a11y-dialog: specifier: ^8.1.5 version: 8.1.5 effect: specifier: ^4.0.0-beta.59 version: 4.0.0-beta.59 + html-template-tag: + specifier: ^5.0.0 + version: 5.0.0 lit-html: specifier: ^3.3.2 version: 3.3.2 @@ -52,8 +58,8 @@ importers: specifier: ^0.85.1 version: 0.85.1 '@effect/tsgo': - specifier: 0.5.1 - version: 0.5.1 + specifier: ^0.5.2 + version: 0.5.2 '@gcch/configuration-eslint': specifier: git+https://git.gcch.fr/gcch/configuration-eslint#888eb4aa54 version: https://git.gcch.fr/gcch/configuration-eslint#888eb4aa54e5bfd6251566d7469ee99204c19f45 @@ -67,8 +73,8 @@ importers: specifier: ^1.59.1 version: 1.59.1 '@sentry/core': - specifier: ^10.50.0 - version: 10.50.0 + specifier: ^10.51.0 + version: 10.51.0 '@types/bun': specifier: ^1.3.13 version: 1.3.13 @@ -76,8 +82,8 @@ importers: specifier: ^25.6.0 version: 25.6.0 '@typescript/native-preview': - specifier: 7.0.0-dev.20260429.1 - version: 7.0.0-dev.20260429.1 + specifier: 7.0.0-dev.20260503.1 + version: 7.0.0-dev.20260503.1 '@vitejs/plugin-legacy': specifier: ^8.0.1 version: 8.0.1(terser@5.46.2)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(sass-embedded@1.99.0)(terser@5.46.2)(yaml@2.8.3)) @@ -91,32 +97,32 @@ importers: specifier: ^1.0.30001791 version: 1.0.30001791 eslint: - specifier: ^10.2.1 - version: 10.2.1(jiti@2.6.1) + specifier: ^10.3.0 + version: 10.3.0(jiti@2.6.1) eslint-plugin-functional: specifier: ^9.0.4 - version: 9.0.4(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + version: 9.0.4(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) eslint-plugin-jsx-a11y: specifier: ^6.10.2 - version: 6.10.2(eslint@10.2.1(jiti@2.6.1)) + version: 6.10.2(eslint@10.3.0(jiti@2.6.1)) eslint-plugin-oxlint: specifier: ^1.62.0 version: 1.62.0(oxlint@1.62.0(oxlint-tsgolint@0.22.1)) eslint-plugin-perfectionist: specifier: ^5.9.0 - version: 5.9.0(eslint@10.2.1(jiti@2.6.1)) + version: 5.9.0(eslint@10.3.0(jiti@2.6.1)) fdir: specifier: ^6.5.0 version: 6.5.0(picomatch@4.0.4) globals: - specifier: ^17.5.0 - version: 17.5.0 + specifier: ^17.6 + version: 17.6.0 jiti: specifier: ^2.6.1 version: 2.6.1 knip: - specifier: ^6.8.0 - version: 6.8.0 + specifier: ^6.11.0 + version: 6.11.0 lightningcss: specifier: ^1.32.0 version: 1.32.0 @@ -179,7 +185,7 @@ importers: version: 6.0.3 typescript-eslint: specifier: ^8.59.1 - version: 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + version: 8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) vite: specifier: ^8.0.10 version: 8.0.10(@types/node@25.6.0)(jiti@2.6.1)(sass-embedded@1.99.0)(terser@5.46.2)(yaml@2.8.3) @@ -740,15 +746,15 @@ packages: resolution: {integrity: sha512-EXnJjIy6zQ3nUO/MZ+ynWUb8B895KZPotd1++oTs9JjDkplwM7cb6zo8Zq2zU6piwq+KflO7amXbEfj1UMpHkw==} hasBin: true - '@effect/tsgo-linux-x64@0.5.1': - resolution: {integrity: sha512-70dMv3/H+P3KDNWb31qPXJiJh6s78k3+J+QXN8RatKiQYrJw2HhREYL6ToVx9y5WOV7XFvC0eCIIa4/AMwQLTw==} + '@effect/tsgo-linux-x64@0.5.2': + resolution: {integrity: sha512-V6sHIZlKQv693ABb9REX0RzIvzyCbNg2uP5+4MXwetlSxz8pmeAUCpraAQLXBkKlYL5rG9kMIobDFU9A88Nqig==} os: - linux cpu: - x64 - '@effect/tsgo@0.5.1': - resolution: {integrity: sha512-INANZ/NK9akOwSQVWpQgSDLjlegrs4gui21nuQsgN7zCjCmj4m/ixUDuVgtW2C0UfqhPWWabyFWCDntu7ryCZQ==} + '@effect/tsgo@0.5.2': + resolution: {integrity: sha512-LEKmx1rwP1j3l9mPW6Bx8VIdGKW+uEvvML89z4xiWnPC+h/uFm3y6FGHULop9Kl09Ybwn2TVuZzVPSZLj+ydmg==} hasBin: true '@es-joy/jsdoccomment@0.86.0': @@ -969,28 +975,28 @@ packages: '@rolldown/pluginutils@1.0.0-rc.17': resolution: {integrity: sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==} - '@sentry-internal/browser-utils@10.50.0': - resolution: {integrity: sha512-42bxyRTxnCmYlWnvz4CxikuQNanw8UNma2WJrtxJ0f1MAJV2GhQGSHDLnA+lvFlmiz6qct3pfen/NXGyOTegTA==} + '@sentry-internal/browser-utils@10.51.0': + resolution: {integrity: sha512-lNKBS4P7RUvf1niojXQWe9bU3gnBUCbST4Dj0pSiyat1N96cXVyHkeE+uGxowD0RrVWhs+kGHiVX3FcmRWF6sA==} engines: {node: '>=18'} - '@sentry-internal/feedback@10.50.0': - resolution: {integrity: sha512-0k9XZF0wn86f77mIO2U3gNNyDZooy139CnEanRzHinrN106vVzvBZ6TUEQoHtoO1fqQxr+nWWVrqV/PXUqk47w==} + '@sentry-internal/feedback@10.51.0': + resolution: {integrity: sha512-bCM95bcpphx28e6aU0bwRLxOgwosYsdNzezM1sM0pVOkb0TB3hDFRamramVDK+/Hp1o8qmRxS4c5w/A7YBZGkA==} engines: {node: '>=18'} - '@sentry-internal/replay-canvas@10.50.0': - resolution: {integrity: sha512-jx6RKBmcJSWdI92qDGS/sBv1w+7Cww879Z/moX7bw7ipHa/Ts3iDcB3rgZwvhmi17U+mvYsbJeL2DXkPo3TjPw==} + '@sentry-internal/replay-canvas@10.51.0': + resolution: {integrity: sha512-8PW1Pp+Yl3lPwYqhBCr5SgkuhDanu9ZLzUqD2bPKL/ElqbM2eDVIWxq4z4ZzePrmZa6IcCjTv6sVQJ7Z4dLyLA==} engines: {node: '>=18'} - '@sentry-internal/replay@10.50.0': - resolution: {integrity: sha512-51FYNfnvVLAWw1rrEWPFfwHuMRb9mkVCFGA4J9/un7SpeGBsQDziGB0Di4fsCxI7+EdSBpfLHPF0csKtCCw0oQ==} + '@sentry-internal/replay@10.51.0': + resolution: {integrity: sha512-jCpI5HXSwK6ZT2HX70+mDRciAocHzSiDk4DTgvzV69Wvd+Ei5WLgE+d39eaEPsm8lUC0Ydntb5sJIB6uG9D4bw==} engines: {node: '>=18'} - '@sentry/browser@10.50.0': - resolution: {integrity: sha512-1f6rAvET6myiTaSeYqvaaBwvq1LfxqWjAPIoAW/NVC9bPMkeEcuvgDajHrnZMrBeWoJ81NMyoLkyX+iOc7MoFA==} + '@sentry/browser@10.51.0': + resolution: {integrity: sha512-Zdc0sKfenxUtW/OGhtJ7xHFN44bXR7YqxJ1zBDzlZfW0nTbeTTUZBq9z5NUw6qdS0Vs/i3V4qzAKTbRKWfqSEA==} engines: {node: '>=18'} - '@sentry/core@10.50.0': - resolution: {integrity: sha512-J4A+vzUO3adl0TkFCjaN1+4miamrjHiEIYuLHiuu1lmAjq5WIVw32ObvAh4yMwNtxyaEMosTrrh5M6f12XSJFg==} + '@sentry/core@10.51.0': + resolution: {integrity: sha512-Y45V/YXvVLEXmOdkbD1oG1gkRWFi9guCEGg3PlIlIpRjAbZUrvLGgjRJIc1E7XpSzmOnWbs5BbUxMv4PDaPj2w==} engines: {node: '>=18'} '@sindresorhus/base62@1.0.0': @@ -1201,16 +1207,16 @@ packages: typescript: '>=4.5.2' aliasOf: '@better-typescript-lib/webworker' - '@typescript/native-preview-linux-x64@7.0.0-dev.20260429.1': - resolution: {integrity: sha512-haAOqc0fJCZkt4RDi0/ZQGBdDfpDzr2N+mEcR+FbiYQD3Y00kOK34hXSrjZafO2kq56ZDWunvCaUTCev0fJDbA==} + '@typescript/native-preview-linux-x64@7.0.0-dev.20260503.1': + resolution: {integrity: sha512-M64z7LwpqNfOXYCBKmD/ObwyxYOobUk4tDv0ECNLit7pDER1sswNZjJGjgRYjQsKokmydy6p3FqtJ1uUPUP/sw==} engines: {node: '>=16.20.0'} os: - linux cpu: - x64 - '@typescript/native-preview@7.0.0-dev.20260429.1': - resolution: {integrity: sha512-SGKnvs5EA+V1spnraYJqum/lEajE0IQ2bVVPC72hFfWjoCfQ6N7iVYxLUGreiE3VFyQWWQBPgXZrRUFnawVvpQ==} + '@typescript/native-preview@7.0.0-dev.20260503.1': + resolution: {integrity: sha512-gDro38CPFiBUGbaFGNt+ufOsEd1OrZrfrOPxsLSfBcvvoGaqAxV++ul/BHTOShoEkIYHiFsoDX2az1IPCDV2jQ==} engines: {node: '>=16.20.0'} hasBin: true @@ -1688,8 +1694,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.2.1: - resolution: {integrity: sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q==} + eslint@10.3.0: + resolution: {integrity: sha512-XbEXaRva5cF0ZQB8w6MluHA0kZZfV2DuCMJ3ozyEOHLwDpZX2Lmm/7Pp0xdJmI0GL1W05VH5VwIFHEm1Vcw2gw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -1869,6 +1875,10 @@ packages: resolution: {integrity: sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==} engines: {node: '>=18'} + globals@17.6.0: + resolution: {integrity: sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==} + engines: {node: '>=18'} + globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -1928,13 +1938,22 @@ packages: hookified@2.2.0: resolution: {integrity: sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==} + html-element-attributes@3.5.0: + resolution: {integrity: sha512-rU2BFhp0kQla9sqPBI46C+zbP6PFOtD7z6XNAJ6as+cGecCDXLx0W3aIs6XdPLmBBG/Fy1meRi/n65Exofz4Qw==} + html-entities@2.6.0: resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} + html-es6cape@2.0.2: + resolution: {integrity: sha512-utzhH8rq2VABdW1LsPdv5tmxeMNOtP83If0jKCa79xPBgLWfcMvdf9K+EZoxJ5P7KioCxTs6WBnSDWLQHJ2lWA==} + html-tags@5.1.0: resolution: {integrity: sha512-n6l5uca7/y5joxZ3LUePhzmBFUJ+U2YWzhMa8XUTecSeSlQiZdF5XAd/Q3/WUl0VsXgUwWi8I7CNIwdI5WN1SQ==} engines: {node: '>=20.10'} + html-template-tag@5.0.0: + resolution: {integrity: sha512-FwF3Fi+v5Dr6ygxqqyJwJWdHteQtDusRXF5ae1syxTKbbVRC8UPtlfIua5KWbgXGneRAc7zNc+Z6x9efFl0W/w==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -2164,8 +2183,8 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - knip@6.8.0: - resolution: {integrity: sha512-FaTrNiqc74KTUMI4KZ5CWWxR2oVTm/bEEik16NKz7usiUJXG4+Df2XA2SPAm+mG9bBY22NvBMM4IeBcUZFslyg==} + knip@6.11.0: + resolution: {integrity: sha512-84PTlN8Q5smLpTbzs8smTVh8PMbTDXtw0tFksXq/m6auGFC/KSzJykKFmnYh3As38kiWDkoDBvdTTyKk5M1TAQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -3830,11 +3849,11 @@ snapshots: '@effect/language-service@0.85.1': {} - '@effect/tsgo-linux-x64@0.5.1': {} + '@effect/tsgo-linux-x64@0.5.2': {} - '@effect/tsgo@0.5.1': + '@effect/tsgo@0.5.2': optionalDependencies: - '@effect/tsgo-linux-x64': 0.5.1 + '@effect/tsgo-linux-x64': 0.5.2 '@es-joy/jsdoccomment@0.86.0': dependencies: @@ -3846,9 +3865,9 @@ snapshots: '@es-joy/resolve.exports@1.2.0': {} - '@eslint-community/eslint-utils@4.9.1(eslint@10.2.1(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.9.1(eslint@10.3.0(jiti@2.6.1))': dependencies: - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -3867,9 +3886,9 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/js@10.0.1(eslint@10.2.1(jiti@2.6.1))': + '@eslint/js@10.0.1(eslint@10.3.0(jiti@2.6.1))': dependencies: - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.6.1) '@eslint/object-schema@3.0.5': {} @@ -3880,24 +3899,24 @@ snapshots: '@gcch/configuration-eslint@https://git.gcch.fr/gcch/configuration-eslint#888eb4aa54e5bfd6251566d7469ee99204c19f45': dependencies: - '@eslint/js': 10.0.1(eslint@10.2.1(jiti@2.6.1)) + '@eslint/js': 10.0.1(eslint@10.3.0(jiti@2.6.1)) astro-eslint-parser: 1.4.0 - eslint: 10.2.1(jiti@2.6.1) - eslint-plugin-functional: 9.0.4(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - eslint-plugin-jsdoc: 62.9.0(eslint@10.2.1(jiti@2.6.1)) - eslint-plugin-perfectionist: 5.9.0(eslint@10.2.1(jiti@2.6.1)) - eslint-plugin-sonarjs: 4.0.3(eslint@10.2.1(jiti@2.6.1)) - eslint-plugin-unicorn: 64.0.0(eslint@10.2.1(jiti@2.6.1)) - globals: 17.5.0 - typescript-eslint: 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + eslint: 10.3.0(jiti@2.6.1) + eslint-plugin-functional: 9.0.4(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) + eslint-plugin-jsdoc: 62.9.0(eslint@10.3.0(jiti@2.6.1)) + eslint-plugin-perfectionist: 5.9.0(eslint@10.3.0(jiti@2.6.1)) + eslint-plugin-sonarjs: 4.0.3(eslint@10.3.0(jiti@2.6.1)) + eslint-plugin-unicorn: 64.0.0(eslint@10.3.0(jiti@2.6.1)) + globals: 17.6.0 + typescript-eslint: 8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) '@gcch/configuration-oxlint@https://git.gcch.fr/gcch/configuration-oxlint#83547fc1ebfd6cb402e3c7f074b3e267632ebf4a': dependencies: - eslint-plugin-astro: 1.7.0(eslint@10.2.1(jiti@2.6.1)) - eslint-plugin-functional: 9.0.4(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - eslint-plugin-jsx-a11y: 6.10.2(eslint@10.2.1(jiti@2.6.1)) - eslint-plugin-perfectionist: 5.9.0(eslint@10.2.1(jiti@2.6.1)) - globals: 17.5.0 + eslint-plugin-astro: 1.7.0(eslint@10.3.0(jiti@2.6.1)) + eslint-plugin-functional: 9.0.4(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) + eslint-plugin-jsx-a11y: 6.10.2(eslint@10.3.0(jiti@2.6.1)) + eslint-plugin-perfectionist: 5.9.0(eslint@10.3.0(jiti@2.6.1)) + globals: 17.6.0 oxlint: 1.62.0(oxlint-tsgolint@0.22.1) oxlint-tsgolint: 0.22.1 @@ -4007,33 +4026,33 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.17': {} - '@sentry-internal/browser-utils@10.50.0': + '@sentry-internal/browser-utils@10.51.0': dependencies: - '@sentry/core': 10.50.0 + '@sentry/core': 10.51.0 - '@sentry-internal/feedback@10.50.0': + '@sentry-internal/feedback@10.51.0': dependencies: - '@sentry/core': 10.50.0 + '@sentry/core': 10.51.0 - '@sentry-internal/replay-canvas@10.50.0': + '@sentry-internal/replay-canvas@10.51.0': dependencies: - '@sentry-internal/replay': 10.50.0 - '@sentry/core': 10.50.0 + '@sentry-internal/replay': 10.51.0 + '@sentry/core': 10.51.0 - '@sentry-internal/replay@10.50.0': + '@sentry-internal/replay@10.51.0': dependencies: - '@sentry-internal/browser-utils': 10.50.0 - '@sentry/core': 10.50.0 + '@sentry-internal/browser-utils': 10.51.0 + '@sentry/core': 10.51.0 - '@sentry/browser@10.50.0': + '@sentry/browser@10.51.0': dependencies: - '@sentry-internal/browser-utils': 10.50.0 - '@sentry-internal/feedback': 10.50.0 - '@sentry-internal/replay': 10.50.0 - '@sentry-internal/replay-canvas': 10.50.0 - '@sentry/core': 10.50.0 + '@sentry-internal/browser-utils': 10.51.0 + '@sentry-internal/feedback': 10.51.0 + '@sentry-internal/replay': 10.51.0 + '@sentry-internal/replay-canvas': 10.51.0 + '@sentry/core': 10.51.0 - '@sentry/core@10.50.0': {} + '@sentry/core@10.51.0': {} '@sindresorhus/base62@1.0.0': {} @@ -4079,29 +4098,29 @@ snapshots: '@types/trusted-types@2.0.7': {} '@types/unist@3.0.3': {} - ? '@typescript-eslint/eslint-plugin@8.59.1(@typescript-eslint/parser@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3))(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)' + ? '@typescript-eslint/eslint-plugin@8.59.1(@typescript-eslint/parser@8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3))(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3)' : dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/parser': 8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) '@typescript-eslint/scope-manager': 8.59.1 - '@typescript-eslint/type-utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/type-utils': 8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) '@typescript-eslint/visitor-keys': 8.59.1 - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.6.1) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 - '@typescript-eslint/parser@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/parser@8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3)': dependencies: '@typescript-eslint/scope-manager': 8.59.1 '@typescript-eslint/types': 8.59.1 '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) '@typescript-eslint/visitor-keys': 8.59.1 debug: 4.4.3 - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.6.1) typescript: 6.0.3 '@typescript-eslint/project-service@8.59.1(typescript@6.0.3)': @@ -4120,13 +4139,13 @@ snapshots: dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3)': dependencies: '@typescript-eslint/types': 8.59.1 '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) debug: 4.4.3 - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.6.1) ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 @@ -4145,13 +4164,13 @@ snapshots: ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 - '@typescript-eslint/utils@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3)': + '@typescript-eslint/utils@8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.6.1)) '@typescript-eslint/scope-manager': 8.59.1 '@typescript-eslint/types': 8.59.1 '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.6.1) typescript: 6.0.3 '@typescript-eslint/visitor-keys@8.59.1': @@ -4227,11 +4246,11 @@ snapshots: dependencies: typescript: 6.0.3 - '@typescript/native-preview-linux-x64@7.0.0-dev.20260429.1': {} + '@typescript/native-preview-linux-x64@7.0.0-dev.20260503.1': {} - '@typescript/native-preview@7.0.0-dev.20260429.1': + '@typescript/native-preview@7.0.0-dev.20260503.1': optionalDependencies: - '@typescript/native-preview-linux-x64': 7.0.0-dev.20260429.1 + '@typescript/native-preview-linux-x64': 7.0.0-dev.20260503.1 ? '@vitejs/plugin-legacy@8.0.1(terser@5.46.2)(vite@8.0.10(@types/node@25.6.0)(jiti@2.6.1)(sass-embedded@1.99.0)(terser@5.46.2)(yaml@2.8.3))' : dependencies: @@ -4710,35 +4729,35 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-compat-utils@0.6.5(eslint@10.2.1(jiti@2.6.1)): + eslint-compat-utils@0.6.5(eslint@10.3.0(jiti@2.6.1)): dependencies: - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.6.1) semver: 7.7.4 - eslint-plugin-astro@1.7.0(eslint@10.2.1(jiti@2.6.1)): + eslint-plugin-astro@1.7.0(eslint@10.3.0(jiti@2.6.1)): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.6.1)) '@jridgewell/sourcemap-codec': 1.5.5 '@typescript-eslint/types': 8.59.1 astro-eslint-parser: 1.4.0 - eslint: 10.2.1(jiti@2.6.1) - eslint-compat-utils: 0.6.5(eslint@10.2.1(jiti@2.6.1)) + eslint: 10.3.0(jiti@2.6.1) + eslint-compat-utils: 0.6.5(eslint@10.3.0(jiti@2.6.1)) globals: 16.5.0 postcss: 8.5.12 postcss-selector-parser: 7.1.1 - eslint-plugin-functional@9.0.4(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3): + eslint-plugin-functional@9.0.4(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3): dependencies: - '@typescript-eslint/utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/utils': 8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) deepmerge-ts: 7.1.5 escape-string-regexp: 5.0.0 - eslint: 10.2.1(jiti@2.6.1) - is-immutable-type: 5.0.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + eslint: 10.3.0(jiti@2.6.1) + is-immutable-type: 5.0.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) ts-api-utils: 2.5.0(typescript@6.0.3) ts-declaration-location: 1.0.7(typescript@6.0.3) typescript: 6.0.3 - eslint-plugin-jsdoc@62.9.0(eslint@10.2.1(jiti@2.6.1)): + eslint-plugin-jsdoc@62.9.0(eslint@10.3.0(jiti@2.6.1)): dependencies: '@es-joy/jsdoccomment': 0.86.0 '@es-joy/resolve.exports': 1.2.0 @@ -4746,7 +4765,7 @@ snapshots: comment-parser: 1.4.6 debug: 4.4.3 escape-string-regexp: 4.0.0 - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.6.1) espree: 11.2.0 esquery: 1.7.0 html-entities: 2.6.0 @@ -4756,7 +4775,7 @@ snapshots: spdx-expression-parse: 4.0.0 to-valid-identifier: 1.0.0 - eslint-plugin-jsx-a11y@6.10.2(eslint@10.2.1(jiti@2.6.1)): + eslint-plugin-jsx-a11y@6.10.2(eslint@10.3.0(jiti@2.6.1)): dependencies: aria-query: 5.3.2 array-includes: 3.1.9 @@ -4766,7 +4785,7 @@ snapshots: axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.6.1) hasown: 2.0.3 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -4780,18 +4799,18 @@ snapshots: jsonc-parser: 3.3.1 oxlint: 1.62.0(oxlint-tsgolint@0.22.1) - eslint-plugin-perfectionist@5.9.0(eslint@10.2.1(jiti@2.6.1)): + eslint-plugin-perfectionist@5.9.0(eslint@10.3.0(jiti@2.6.1)): dependencies: - '@typescript-eslint/utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - eslint: 10.2.1(jiti@2.6.1) + '@typescript-eslint/utils': 8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) + eslint: 10.3.0(jiti@2.6.1) natural-orderby: 5.0.0 - eslint-plugin-sonarjs@4.0.3(eslint@10.2.1(jiti@2.6.1)): + eslint-plugin-sonarjs@4.0.3(eslint@10.3.0(jiti@2.6.1)): dependencies: '@eslint-community/regexpp': 4.12.2 builtin-modules: 3.3.0 bytes: 3.1.2 - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.6.1) functional-red-black-tree: 1.0.1 globals: 17.5.0 jsx-ast-utils-x: 0.1.0 @@ -4802,15 +4821,15 @@ snapshots: ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 - eslint-plugin-unicorn@64.0.0(eslint@10.2.1(jiti@2.6.1)): + eslint-plugin-unicorn@64.0.0(eslint@10.3.0(jiti@2.6.1)): dependencies: '@babel/helper-validator-identifier': 7.28.5 - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.6.1)) change-case: 5.4.4 ci-info: 4.4.0 clean-regexp: 1.0.0 core-js-compat: 3.49.0 - eslint: 10.2.1(jiti@2.6.1) + eslint: 10.3.0(jiti@2.6.1) find-up-simple: 1.0.1 globals: 17.5.0 indent-string: 5.0.0 @@ -4840,9 +4859,9 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.2.1(jiti@2.6.1): + eslint@10.3.0(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.3.0(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.23.5 '@eslint/config-helpers': 0.5.5 @@ -5050,6 +5069,8 @@ snapshots: globals@17.5.0: {} + globals@17.6.0: {} + globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -5102,10 +5123,19 @@ snapshots: hookified@2.2.0: {} + html-element-attributes@3.5.0: {} + html-entities@2.6.0: {} + html-es6cape@2.0.2: {} + html-tags@5.1.0: {} + html-template-tag@5.0.0: + dependencies: + html-element-attributes: 3.5.0 + html-es6cape: 2.0.2 + ignore@5.3.2: {} ignore@7.0.5: {} @@ -5199,10 +5229,10 @@ snapshots: dependencies: is-extglob: 2.1.1 - is-immutable-type@5.0.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3): + is-immutable-type@5.0.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3): dependencies: - '@typescript-eslint/type-utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - eslint: 10.2.1(jiti@2.6.1) + '@typescript-eslint/type-utils': 8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) + eslint: 10.3.0(jiti@2.6.1) ts-api-utils: 2.5.0(typescript@6.0.3) ts-declaration-location: 1.0.7(typescript@6.0.3) typescript: 6.0.3 @@ -5310,7 +5340,7 @@ snapshots: kind-of@6.0.3: {} - knip@6.8.0: + knip@6.11.0: dependencies: fdir: 6.5.0(picomatch@4.0.4) formatly: 0.3.0 @@ -6279,13 +6309,13 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3): + typescript-eslint@8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.59.1(@typescript-eslint/parser@8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3))(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - '@typescript-eslint/parser': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/eslint-plugin': 8.59.1(@typescript-eslint/parser@8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3))(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) + '@typescript-eslint/parser': 8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) '@typescript-eslint/typescript-estree': 8.59.1(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.1(eslint@10.2.1(jiti@2.6.1))(typescript@6.0.3) - eslint: 10.2.1(jiti@2.6.1) + '@typescript-eslint/utils': 8.59.1(eslint@10.3.0(jiti@2.6.1))(typescript@6.0.3) + eslint: 10.3.0(jiti@2.6.1) typescript: 6.0.3 typescript@6.0.3: {} diff --git a/cfg/playwright.config.ts b/cfg/playwright.config.ts index 5ea6eced..1087f3a3 100644 --- a/cfg/playwright.config.ts +++ b/cfg/playwright.config.ts @@ -1,33 +1,17 @@ -import { defineConfig, devices } from "@playwright/test"; +import { defineConfig, devices, PlaywrightTestConfig } from "@playwright/test"; -export default defineConfig({ +const playwrightConfig: PlaywrightTestConfig = defineConfig({ fullyParallel: true, projects: [ { name: "desktop-chromium-1920", use: { ...devices["Desktop Chrome"], viewport: { height: 1080, width: 1920 } }, }, - // { - // name: "desktop-chromium-1536", - // use: { ...devices["Desktop Chrome"], viewport: { width: 1536, height: 864 } }, - // }, - // { - // name: "desktop-chromium-1366", - // use: { ...devices["Desktop Chrome"], viewport: { width: 1366, height: 768 } }, - // }, { name: "desktop-firefox-1920", use: { ...devices["Desktop Firefox"], viewport: { height: 1080, width: 1920 } }, }, // { - // name: "desktop-firefox-1536", - // use: { ...devices["Desktop Firefox"], viewport: { width: 1536, height: 864 } }, - // }, - // { - // name: "desktop-firefox-1366", - // use: { ...devices["Desktop Firefox"], viewport: { width: 1366, height: 768 } }, - // }, - // { // name: "tablet-chromium-portrait", // use: { ...devices["Galaxy Tab S9"] }, // }, @@ -49,7 +33,6 @@ export default defineConfig({ testDir: "../tests", timeout: 10_000, use: { - /* Base URL to use in actions like `await page.goto('/')`. */ baseURL: "https://haikuatelier.gcch.local", clientCertificates: [ { @@ -61,5 +44,7 @@ export default defineConfig({ ignoreHTTPSErrors: true, trace: "retry-with-trace", }, - workers: "100%", + workers: "50%", }); + +export default playwrightConfig; diff --git a/composer.json b/composer.json index b9ada9b9..5607dfb7 100755 --- a/composer.json +++ b/composer.json @@ -1,19 +1,10 @@ { - "authors": [ - { - "email": "scott.walkinshaw@gmail.com", - "homepage": "https://github.com/swalkinshaw", - "name": "Scott Walkinshaw" - }, - { - "email": "ben@benword.com", - "homepage": "https://github.com/retlehs", - "name": "Ben Word" - } - ], + "$schema": "https://getcomposer.org/schema.json", + "authors": [], "autoload": { "psr-4": { - "HaikuAtelier\\": "web/app/themes/haiku-atelier-2024/src/inc/" + "HaikuAtelier\\": "web/app/themes/haiku-atelier-2024/src/inc/", + "WooCommerce\\": "web/app/plugins/woocommerce" } }, "config": { @@ -24,11 +15,12 @@ "phpstan/extension-installer": true, "roots/wordpress-core-installer": true }, + "classmap-authoritative": true, "optimize-autoloader": true, "preferred-install": "dist", "sort-packages": true }, - "description": "WordPress boilerplate with Composer, easier configuration, and an improved folder structure", + "description": "", "extra": { "installer-paths": { "web/app/mu-plugins/{$name}/": [ @@ -46,18 +38,8 @@ }, "wordpress-install-dir": "web/wp" }, - "homepage": "https://roots.io/bedrock/", - "keywords": [ - "bedrock", - "composer", - "roots", - "wordpress", - "wp", - "wp-config" - ], - "license": "MIT", - "minimum-stability": "dev", - "name": "roots/bedrock", + "minimum-stability": "stable", + "name": "gcch/haiku-atelier", "prefer-stable": true, "repositories": [ { @@ -111,9 +93,5 @@ "szepeviktor/phpstan-wordpress": "2.x-dev", "vincentlanglet/twig-cs-fixer": "^3.14" }, - "support": { - "forum": "https://discourse.roots.io/category/bedrock", - "issues": "https://github.com/roots/bedrock/issues" - }, "type": "project" } diff --git a/composer.lock b/composer.lock index 81c84e38..95cb4931 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3144138aa029c01a516e9b6ce664271b", + "content-hash": "b81b62efbedadf3c57fb437e86ef6766", "packages": [ { "name": "carbonphp/carbon-doctrine-types", @@ -3176,16 +3176,16 @@ }, { "name": "symfony/uid", - "version": "v8.0.8", + "version": "v8.0.9", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "f63fa6096a24147283bce4d29327d285326438e0" + "reference": "4d9d6510bbe88ebb4608b7200d18606cdf80825c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/f63fa6096a24147283bce4d29327d285326438e0", - "reference": "f63fa6096a24147283bce4d29327d285326438e0", + "url": "https://api.github.com/repos/symfony/uid/zipball/4d9d6510bbe88ebb4608b7200d18606cdf80825c", + "reference": "4d9d6510bbe88ebb4608b7200d18606cdf80825c", "shasum": "" }, "require": { @@ -3230,7 +3230,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v8.0.8" + "source": "https://github.com/symfony/uid/tree/v8.0.9" }, "funding": [ { @@ -3250,7 +3250,7 @@ "type": "tidelift" } ], - "time": "2026-03-30T15:14:47+00:00" + "time": "2026-04-30T16:10:06+00:00" }, { "name": "timber/timber", @@ -4532,11 +4532,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.53", + "version": "2.1.54", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ef67586798c003274797b288a68b221e4270dca7", - "reference": "ef67586798c003274797b288a68b221e4270dca7", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/8be50c3992107dc837b17da4d140fbbdf9a5c5bd", + "reference": "8be50c3992107dc837b17da4d140fbbdf9a5c5bd", "shasum": "" }, "require": { @@ -4581,7 +4581,7 @@ "type": "github" } ], - "time": "2026-04-28T16:09:00+00:00" + "time": "2026-04-29T13:31:09+00:00" }, { "name": "psr/event-dispatcher", @@ -5215,18 +5215,18 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "87a281378fdad8f5926efe259f6ca72e7a395e68" + "reference": "2221f6ef09e87784e78e188aadd8f7e3a50e679a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/87a281378fdad8f5926efe259f6ca72e7a395e68", - "reference": "87a281378fdad8f5926efe259f6ca72e7a395e68", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/2221f6ef09e87784e78e188aadd8f7e3a50e679a", + "reference": "2221f6ef09e87784e78e188aadd8f7e3a50e679a", "shasum": "" }, "conflict": { "3f/pygmentize": "<1.2", "adaptcms/adaptcms": "<=1.3", - "admidio/admidio": "<5.0.8", + "admidio/admidio": "<=5.0.8", "adodb/adodb-php": "<=5.22.9", "aheinze/cockpit": "<2.2", "aimeos/ai-admin-graphql": ">=2022.04.1,<2022.10.10|>=2023.04.1,<2023.10.6|>=2024.04.1,<2024.07.2", @@ -5335,7 +5335,7 @@ "cesnet/simplesamlphp-module-proxystatistics": "<3.1", "chriskacerguis/codeigniter-restserver": "<=2.7.1", "chrome-php/chrome": "<1.14", - "ci4-cms-erp/ci4ms": "<0.31.5", + "ci4-cms-erp/ci4ms": "<=0.31.6", "civicrm/civicrm-core": ">=4.2,<4.2.9|>=4.3,<4.3.3", "ckeditor/ckeditor": "<4.25", "clickstorm/cs-seo": ">=6,<6.8|>=7,<7.5|>=8,<8.4|>=9,<9.3", @@ -5540,7 +5540,7 @@ "geshi/geshi": "<=1.0.9.1", "getformwork/formwork": "<=2.3.3", "getgrav/grav": "<1.11.0.0-beta1", - "getkirby/cms": "<5.4", + "getkirby/cms": "<4.9|>=5,<5.4", "getkirby/kirby": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1", "getkirby/panel": "<2.5.14", "getkirby/starterkit": "<=3.7.0.2", @@ -5600,7 +5600,7 @@ "intelliants/subrion": "<4.2.2", "inter-mediator/inter-mediator": "==5.5", "invoiceninja/invoiceninja": "<5.13.4", - "ipl/web": "<0.10.1", + "ipl/web": "<=0.13", "islandora/crayfish": "<4.1", "islandora/islandora": ">=2,<2.4.1", "ivankristianto/phpwhois": "<=4.3", @@ -5870,7 +5870,7 @@ "prestashop/gamification": "<2.3.2", "prestashop/prestashop": "<8.2.5|>=9.0.0.0-alpha1,<9.1", "prestashop/productcomments": "<5.0.2", - "prestashop/ps_checkout": "<4.4.1|>=5,<5.0.5", + "prestashop/ps_checkout": "<5.3", "prestashop/ps_contactinfo": "<=3.3.2", "prestashop/ps_emailsubscription": "<2.6.1", "prestashop/ps_facetedsearch": "<3.4.1", @@ -5907,6 +5907,7 @@ "rhukster/dom-sanitizer": "<1.0.10", "rmccue/requests": ">=1.6,<1.8", "roadiz/documents": "<2.3.42|>=2.4,<2.5.44|>=2.6,<2.6.28|>=2.7,<2.7.9", + "roadiz/openid": "<2.3.43|>=2.5,<2.5.45|>=2.6,<2.6.31|>=2.7,<2.7.18", "robrichards/xmlseclibs": "<3.1.5", "roots/soil": "<4.1", "roundcube/roundcubemail": "<1.5.10|>=1.6,<1.6.11|>=1.7.0.0-beta,<1.7.0.0-RC5-dev", @@ -6264,7 +6265,7 @@ "type": "tidelift" } ], - "time": "2026-04-28T23:21:55+00:00" + "time": "2026-04-30T21:24:12+00:00" }, { "name": "sebastian/diff", @@ -6347,16 +6348,16 @@ }, { "name": "symfony/console", - "version": "v8.0.8", + "version": "v8.0.9", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "5b66d385dc58f69652e56f78a4184615e3f2b7f7" + "reference": "7113778e2e91f4709cb3194a75dfa9c0d028d94d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/5b66d385dc58f69652e56f78a4184615e3f2b7f7", - "reference": "5b66d385dc58f69652e56f78a4184615e3f2b7f7", + "url": "https://api.github.com/repos/symfony/console/zipball/7113778e2e91f4709cb3194a75dfa9c0d028d94d", + "reference": "7113778e2e91f4709cb3194a75dfa9c0d028d94d", "shasum": "" }, "require": { @@ -6413,7 +6414,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v8.0.8" + "source": "https://github.com/symfony/console/tree/v8.0.9" }, "funding": [ { @@ -6433,20 +6434,20 @@ "type": "tidelift" } ], - "time": "2026-03-30T15:14:47+00:00" + "time": "2026-04-29T15:02:55+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v8.0.8", + "version": "v8.0.9", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "f662acc6ab22a3d6d716dcb44c381c6002940df6" + "reference": "0c3c1a17604c4dbbec4b93fe162c538482096e1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f662acc6ab22a3d6d716dcb44c381c6002940df6", - "reference": "f662acc6ab22a3d6d716dcb44c381c6002940df6", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0c3c1a17604c4dbbec4b93fe162c538482096e1f", + "reference": "0c3c1a17604c4dbbec4b93fe162c538482096e1f", "shasum": "" }, "require": { @@ -6498,7 +6499,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.8" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.9" }, "funding": [ { @@ -6518,7 +6519,7 @@ "type": "tidelift" } ], - "time": "2026-03-30T15:14:47+00:00" + "time": "2026-04-18T13:51:42+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -6598,16 +6599,16 @@ }, { "name": "symfony/filesystem", - "version": "v8.0.8", + "version": "v8.0.9", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "66b769ae743ce2d13e435528fbef4af03d623e5a" + "reference": "d1ec4543d5c6c2dac78503c2fae5ea0b3608ce40" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/66b769ae743ce2d13e435528fbef4af03d623e5a", - "reference": "66b769ae743ce2d13e435528fbef4af03d623e5a", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/d1ec4543d5c6c2dac78503c2fae5ea0b3608ce40", + "reference": "d1ec4543d5c6c2dac78503c2fae5ea0b3608ce40", "shasum": "" }, "require": { @@ -6644,7 +6645,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v8.0.8" + "source": "https://github.com/symfony/filesystem/tree/v8.0.9" }, "funding": [ { @@ -6664,7 +6665,7 @@ "type": "tidelift" } ], - "time": "2026-03-30T15:14:47+00:00" + "time": "2026-04-18T13:51:42+00:00" }, { "name": "symfony/finder", @@ -7565,7 +7566,7 @@ } ], "aliases": [], - "minimum-stability": "dev", + "minimum-stability": "stable", "stability-flags": { "roave/security-advisories": 20, "szepeviktor/phpstan-wordpress": 20 diff --git a/config/environments/development.php b/config/environments/development.php index cfacfcb8..df784947 100755 --- a/config/environments/development.php +++ b/config/environments/development.php @@ -8,6 +8,7 @@ declare(strict_types=1); use Roots\WPConfig\Config; +use function base64_encode; use function Env\env; Config::define('SAVEQUERIES', true); @@ -25,6 +26,10 @@ Config::define('DISALLOW_FILE_MODS', false); // WooCommerce Config::define('WOOCOMMERCE_API_CONSUMER_KEY', env('WOOCOMMERCE_API_CONSUMER_KEY')); Config::define('WOOCOMMERCE_API_CONSUMER_SECRET', env('WOOCOMMERCE_API_CONSUMER_SECRET')); +Config::define( + 'WOOCOMMERCE_API_AUTH_STRING', + base64_encode(env('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . env('WOOCOMMERCE_API_CONSUMER_SECRET')), +); // Stripe Config::define('STRIPE_API_SECRET', env('STRIPE_API_SECRET')); diff --git a/config/environments/production.php b/config/environments/production.php index 93b792c3..0047176f 100755 --- a/config/environments/production.php +++ b/config/environments/production.php @@ -8,6 +8,7 @@ declare(strict_types=1); use Roots\WPConfig\Config; +use function base64_encode; use function Env\env; Config::define('WP_DEBUG', true); @@ -20,6 +21,10 @@ Config::define('DISALLOW_FILE_MODS', false); Config::define('WOOCOMMERCE_API_CONSUMER_KEY', env('WOOCOMMERCE_API_CONSUMER_KEY')); Config::define('WOOCOMMERCE_API_CONSUMER_SECRET', env('WOOCOMMERCE_API_CONSUMER_SECRET')); +Config::define( + 'WOOCOMMERCE_API_AUTH_STRING', + base64_encode(env('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . env('WOOCOMMERCE_API_CONSUMER_SECRET')), +); // Stripe Config::define('STRIPE_API_SECRET', env('STRIPE_API_SECRET')); diff --git a/config/environments/staging.php b/config/environments/staging.php index 1651c055..0f7ba42b 100755 --- a/config/environments/staging.php +++ b/config/environments/staging.php @@ -8,8 +8,13 @@ declare(strict_types=1); use Roots\WPConfig\Config; +use function base64_encode; use function Env\env; Config::define('DISALLOW_INDEXING', true); Config::define('WOOCOMMERCE_API_CONSUMER_KEY', env('WOOCOMMERCE_API_CONSUMER_KEY')); Config::define('WOOCOMMERCE_API_CONSUMER_SECRET', env('WOOCOMMERCE_API_CONSUMER_SECRET')); +Config::define( + 'WOOCOMMERCE_API_AUTH_STRING', + base64_encode(env('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . env('WOOCOMMERCE_API_CONSUMER_SECRET')), +); diff --git a/justfile b/justfile index c9fe13a2..8d2c9d6c 100755 --- a/justfile +++ b/justfile @@ -90,6 +90,11 @@ watch-css: build-js: aube x vite build --config "cfg/vite.config.ts" +# Compile TypeScript à chaque changement de fichier. +[group('js')] +watch-js: + @watchexec -w "web/app/themes/haiku-atelier-2024/src/scripts" -w "web/app/themes/haiku-atelier-2024/src/scripts-effect" -- just build-js treefmt + # Compile tout. [group('css')] [group('js')] @@ -98,11 +103,6 @@ build-all: @just build-js @just format -# Compile TypeScript à chaque changement de fichier. -[group('js')] -watch-js: - aube x vite build --config "cfg/vite.config.ts" --watch - # Vérifie le code TypeScript avec des analyseurs statiques. [group('js')] [group('qualité')] @@ -170,3 +170,6 @@ pull-images: export_production_db: fish "scripts/déclenche-sauvegarde-bdd-production.fish" + +ui_tests: + aube x playwright test --config cfg/playwright.config.ts --ui diff --git a/mago-schema.json b/mago-schema.json index e162e461..1cb5d367 100644 --- a/mago-schema.json +++ b/mago-schema.json @@ -4,6 +4,11 @@ "additionalProperties": false, "description": "Configuration options for the static analyzer.", "properties": { + "allow-implicit-pipe-callable-types": { + "default": false, + "description": "Skip missing-type-hint checks for closures and arrow functions used\nas the right-hand side of the pipe operator (`|>`).\n\nWhen `true`, an inline pipe callable like\n`$x |> fn($p) => strtoupper($p)` will not warn about missing parameter\nor return types, even when the closure / arrow-function checks are\notherwise enabled. The pipe operand's type is enough to derive the\nparameter type, so the hint is mostly noise.\n\nDefaults to `false`.", + "type": "boolean" + }, "allow-possibly-undefined-array-keys": { "default": true, "description": "Allow accessing array keys that may not be defined without reporting an issue.", @@ -1220,6 +1225,10 @@ "enabled": true, "level": "Error" }, + "no-dead-store": { + "enabled": false, + "level": "Warning" + }, "no-debug-symbols": { "enabled": true, "level": "Note" @@ -1326,6 +1335,10 @@ "enabled": true, "level": "Warning" }, + "no-negated-ternary": { + "enabled": false, + "level": "Help" + }, "no-nested-ternary": { "enabled": true, "level": "Warning" @@ -1366,6 +1379,10 @@ "enabled": true, "level": "Help" }, + "no-redundant-else": { + "enabled": false, + "level": "Help" + }, "no-redundant-file": { "enabled": true, "level": "Help" @@ -1414,6 +1431,10 @@ "enabled": true, "level": "Warning" }, + "no-redundant-variable": { + "enabled": false, + "level": "Warning" + }, "no-redundant-write-visibility": { "enabled": true, "level": "Help" @@ -1500,6 +1521,18 @@ "enabled": true, "level": "Error" }, + "no-unused-closure-capture": { + "enabled": false, + "level": "Warning" + }, + "no-unused-global": { + "enabled": false, + "level": "Warning" + }, + "no-unused-static": { + "enabled": false, + "level": "Warning" + }, "no-variable-variable": { "enabled": true, "level": "Warning" @@ -1984,14 +2017,6 @@ "RuleSettings100": { "additionalProperties": false, "properties": { - "camel": { - "default": false, - "type": "boolean" - }, - "either": { - "default": false, - "type": "boolean" - }, "enabled": { "default": true, "type": "boolean" @@ -2004,7 +2029,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Warning" } }, "type": "object" @@ -2064,7 +2089,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Warning" } }, "type": "object" @@ -2086,11 +2111,9 @@ "$ref": "#/$defs/Level", "default": "Help" }, - "max_allowed_statements": { - "default": 0, - "format": "uint", - "minimum": 0, - "type": "integer" + "psr": { + "default": false, + "type": "boolean" } }, "type": "object" @@ -2118,6 +2141,38 @@ "RuleSettings106": { "additionalProperties": false, "properties": { + "check-functions": { + "default": false, + "type": "boolean" + }, + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings107": { + "additionalProperties": false, + "properties": { + "camel": { + "default": false, + "type": "boolean" + }, + "either": { + "default": false, + "type": "boolean" + }, "enabled": { "default": true, "type": "boolean" @@ -2135,26 +2190,6 @@ }, "type": "object" }, - "RuleSettings107": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": false, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Warning" - } - }, - "type": "object" - }, "RuleSettings108": { "additionalProperties": false, "properties": { @@ -2170,7 +2205,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Warning" } }, "type": "object" @@ -2190,7 +2225,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Note" + "default": "Warning" } }, "type": "object" @@ -2234,7 +2269,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Help" } }, "type": "object" @@ -2254,7 +2289,13 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Help" + }, + "max_allowed_statements": { + "default": 0, + "format": "uint", + "minimum": 0, + "type": "integer" } }, "type": "object" @@ -2274,7 +2315,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Note" } }, "type": "object" @@ -2294,7 +2335,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Help" } }, "type": "object" @@ -2303,7 +2344,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -2314,7 +2355,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Error" + "default": "Warning" } }, "type": "object" @@ -2334,7 +2375,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Help" } }, "type": "object" @@ -2354,7 +2395,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Note" } }, "type": "object" @@ -2462,10 +2503,6 @@ "RuleSettings121": { "additionalProperties": false, "properties": { - "allow-loose-behavior": { - "default": false, - "type": "boolean" - }, "enabled": { "default": true, "type": "boolean" @@ -2478,7 +2515,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Error" } }, "type": "object" @@ -2486,10 +2523,6 @@ "RuleSettings122": { "additionalProperties": false, "properties": { - "allow-disabling": { - "default": false, - "type": "boolean" - }, "enabled": { "default": true, "type": "boolean" @@ -2548,6 +2581,174 @@ "type": "object" }, "RuleSettings125": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings126": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings127": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings128": { + "additionalProperties": false, + "properties": { + "allow-loose-behavior": { + "default": false, + "type": "boolean" + }, + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings129": { + "additionalProperties": false, + "properties": { + "allow-disabling": { + "default": false, + "type": "boolean" + }, + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings13": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Help" + } + }, + "type": "object" + }, + "RuleSettings130": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings131": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings132": { "additionalProperties": false, "properties": { "enabled": { @@ -2574,7 +2775,7 @@ }, "type": "object" }, - "RuleSettings126": { + "RuleSettings133": { "additionalProperties": false, "properties": { "count-hooks": { @@ -2609,7 +2810,7 @@ }, "type": "object" }, - "RuleSettings127": { + "RuleSettings134": { "additionalProperties": false, "properties": { "enabled": { @@ -2636,7 +2837,7 @@ }, "type": "object" }, - "RuleSettings128": { + "RuleSettings135": { "additionalProperties": false, "properties": { "enabled": { @@ -2660,7 +2861,7 @@ }, "type": "object" }, - "RuleSettings129": { + "RuleSettings136": { "additionalProperties": false, "properties": { "enabled": { @@ -2680,27 +2881,7 @@ }, "type": "object" }, - "RuleSettings13": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": true, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Help" - } - }, - "type": "object" - }, - "RuleSettings130": { + "RuleSettings137": { "additionalProperties": false, "properties": { "camel": { @@ -2732,7 +2913,7 @@ }, "type": "object" }, - "RuleSettings131": { + "RuleSettings138": { "additionalProperties": false, "properties": { "enabled": { @@ -2752,166 +2933,11 @@ }, "type": "object" }, - "RuleSettings132": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": false, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Warning" - } - }, - "type": "object" - }, - "RuleSettings133": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": true, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Warning" - } - }, - "type": "object" - }, - "RuleSettings134": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": false, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Warning" - } - }, - "type": "object" - }, - "RuleSettings135": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": false, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Error" - } - }, - "type": "object" - }, - "RuleSettings136": { - "additionalProperties": false, - "properties": { - "allow-class-alias": { - "default": true, - "description": "When true, top-level `class_alias(...)` calls are allowed alongside\ndeclarations.", - "type": "boolean" - }, - "allow-class-exists": { - "default": true, - "description": "When true, top-level `class_exists(...)` calls are allowed alongside\ndeclarations. This is commonly used to trigger autoloading/preloading.", - "type": "boolean" - }, - "allow-conditional-declarations": { - "default": true, - "description": "When true, conditional declarations (`if (...) { class Foo {} }`)\nare allowed alongside declarations. This covers the common pattern\nof polyfilling a class depending on an extension or PHP version.", - "type": "boolean" - }, - "enabled": { - "default": false, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Warning" - } - }, - "type": "object" - }, - "RuleSettings137": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": true, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Error" - } - }, - "type": "object" - }, - "RuleSettings138": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": true, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Error" - } - }, - "type": "object" - }, "RuleSettings139": { "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -2920,19 +2946,9 @@ }, "type": "array" }, - "known-sink-functions": { - "default": [ - "printf" - ], - "items": { - "type": "string" - }, - "type": "array", - "uniqueItems": true - }, "level": { "$ref": "#/$defs/Level", - "default": "Error" + "default": "Warning" } }, "type": "object" @@ -2988,7 +3004,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Error" + "default": "Warning" } }, "type": "object" @@ -2996,14 +3012,6 @@ "RuleSettings141": { "additionalProperties": false, "properties": { - "camel": { - "default": true, - "type": "boolean" - }, - "either": { - "default": false, - "type": "boolean" - }, "enabled": { "default": false, "type": "boolean" @@ -3016,7 +3024,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Warning" } }, "type": "object" @@ -3025,7 +3033,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -3044,8 +3052,23 @@ "RuleSettings143": { "additionalProperties": false, "properties": { - "enabled": { + "allow-class-alias": { "default": true, + "description": "When true, top-level `class_alias(...)` calls are allowed alongside\ndeclarations.", + "type": "boolean" + }, + "allow-class-exists": { + "default": true, + "description": "When true, top-level `class_exists(...)` calls are allowed alongside\ndeclarations. This is commonly used to trigger autoloading/preloading.", + "type": "boolean" + }, + "allow-conditional-declarations": { + "default": true, + "description": "When true, conditional declarations (`if (...) { class Foo {} }`)\nare allowed alongside declarations. This covers the common pattern\nof polyfilling a class depending on an extension or PHP version.", + "type": "boolean" + }, + "enabled": { + "default": false, "type": "boolean" }, "exclude": { @@ -3076,7 +3099,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Error" } }, "type": "object" @@ -3096,12 +3119,204 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Error" } }, "type": "object" }, "RuleSettings146": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "known-sink-functions": { + "default": [ + "printf" + ], + "items": { + "type": "string" + }, + "type": "array", + "uniqueItems": true + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Error" + } + }, + "type": "object" + }, + "RuleSettings147": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Error" + } + }, + "type": "object" + }, + "RuleSettings148": { + "additionalProperties": false, + "properties": { + "camel": { + "default": true, + "type": "boolean" + }, + "either": { + "default": false, + "type": "boolean" + }, + "enabled": { + "default": false, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Help" + } + }, + "type": "object" + }, + "RuleSettings149": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Error" + } + }, + "type": "object" + }, + "RuleSettings15": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "extensions": { + "default": [], + "items": { + "$ref": "#/$defs/DisallowedEntry" + }, + "type": "array" + }, + "functions": { + "default": [], + "items": { + "$ref": "#/$defs/DisallowedEntry" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings150": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings151": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings152": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings153": { "additionalProperties": false, "properties": { "allowed-methods": { @@ -3160,184 +3375,6 @@ }, "type": "object" }, - "RuleSettings147": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": true, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Warning" - } - }, - "type": "object" - }, - "RuleSettings148": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": true, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Help" - } - }, - "type": "object" - }, - "RuleSettings149": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": true, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Warning" - } - }, - "type": "object" - }, - "RuleSettings15": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": true, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "extensions": { - "default": [], - "items": { - "$ref": "#/$defs/DisallowedEntry" - }, - "type": "array" - }, - "functions": { - "default": [], - "items": { - "$ref": "#/$defs/DisallowedEntry" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Warning" - } - }, - "type": "object" - }, - "RuleSettings150": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": false, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Warning" - } - }, - "type": "object" - }, - "RuleSettings151": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": false, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Help" - } - }, - "type": "object" - }, - "RuleSettings152": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": false, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Note" - }, - "style": { - "$ref": "#/$defs/StringStyleOption", - "default": "interpolation" - } - }, - "type": "object" - }, - "RuleSettings153": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": true, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Warning" - } - }, - "type": "object" - }, "RuleSettings154": { "additionalProperties": false, "properties": { @@ -3354,13 +3391,6 @@ "level": { "$ref": "#/$defs/Level", "default": "Warning" - }, - "min-digits": { - "default": 5, - "description": "Minimum number of digits before suggesting separators.", - "format": "uint", - "minimum": 0, - "type": "integer" } }, "type": "object" @@ -3369,7 +3399,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": false, + "default": true, "type": "boolean" }, "exclude": { @@ -3389,7 +3419,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": false, + "default": true, "type": "boolean" }, "exclude": { @@ -3400,7 +3430,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Warning" } }, "type": "object" @@ -3460,7 +3490,11 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Note" + }, + "style": { + "$ref": "#/$defs/StringStyleOption", + "default": "interpolation" } }, "type": "object" @@ -3496,7 +3530,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": false, + "default": true, "type": "boolean" }, "exclude": { @@ -3513,6 +3547,33 @@ "type": "object" }, "RuleSettings161": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + }, + "min-digits": { + "default": 5, + "description": "Minimum number of digits before suggesting separators.", + "format": "uint", + "minimum": 0, + "type": "integer" + } + }, + "type": "object" + }, + "RuleSettings162": { "additionalProperties": false, "properties": { "enabled": { @@ -3532,31 +3593,11 @@ }, "type": "object" }, - "RuleSettings162": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": true, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Warning" - } - }, - "type": "object" - }, "RuleSettings163": { "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -3567,7 +3608,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Help" } }, "type": "object" @@ -3576,7 +3617,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -3587,7 +3628,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Error" + "default": "Warning" } }, "type": "object" @@ -3596,7 +3637,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -3607,12 +3648,72 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Error" + "default": "Help" } }, "type": "object" }, "RuleSettings166": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": false, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Help" + } + }, + "type": "object" + }, + "RuleSettings167": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": false, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings168": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": false, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Help" + } + }, + "type": "object" + }, + "RuleSettings169": { "additionalProperties": false, "properties": { "enabled": { @@ -3632,7 +3733,107 @@ }, "type": "object" }, - "RuleSettings167": { + "RuleSettings17": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Help" + } + }, + "type": "object" + }, + "RuleSettings170": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings171": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Error" + } + }, + "type": "object" + }, + "RuleSettings172": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Error" + } + }, + "type": "object" + }, + "RuleSettings173": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings174": { "additionalProperties": false, "properties": { "classes": { @@ -3692,7 +3893,7 @@ }, "type": "object" }, - "RuleSettings168": { + "RuleSettings175": { "additionalProperties": false, "properties": { "enabled": { @@ -3712,26 +3913,6 @@ }, "type": "object" }, - "RuleSettings17": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": true, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Help" - } - }, - "type": "object" - }, "RuleSettings18": { "additionalProperties": false, "properties": { @@ -4679,7 +4860,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -4710,7 +4891,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Help" } }, "type": "object" @@ -4730,7 +4911,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Warning" } }, "type": "object" @@ -4763,7 +4944,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -4783,7 +4964,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -4794,7 +4975,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Warning" } }, "type": "object" @@ -4803,7 +4984,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -4814,7 +4995,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Note" + "default": "Warning" } }, "type": "object" @@ -4823,7 +5004,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -4834,7 +5015,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Warning" } }, "type": "object" @@ -4843,7 +5024,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -4854,7 +5035,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Error" + "default": "Warning" } }, "type": "object" @@ -4874,7 +5055,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Help" } }, "type": "object" @@ -4914,7 +5095,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Help" } }, "type": "object" @@ -4934,7 +5115,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Note" } }, "type": "object" @@ -4954,7 +5135,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Help" } }, "type": "object" @@ -4994,7 +5175,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Note" + "default": "Error" } }, "type": "object" @@ -5014,7 +5195,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Error" + "default": "Warning" } }, "type": "object" @@ -5023,7 +5204,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -5034,7 +5215,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Error" + "default": "Help" } }, "type": "object" @@ -5054,7 +5235,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Error" + "default": "Warning" } }, "type": "object" @@ -5074,7 +5255,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Error" + "default": "Warning" } }, "type": "object" @@ -5094,7 +5275,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Error" + "default": "Warning" } }, "type": "object" @@ -5103,7 +5284,27 @@ "additionalProperties": false, "properties": { "enabled": { - "default": false, + "default": true, + "type": "boolean" + }, + "exclude": { + "items": { + "type": "string" + }, + "type": "array" + }, + "level": { + "$ref": "#/$defs/Level", + "default": "Warning" + } + }, + "type": "object" + }, + "RuleSettings77": { + "additionalProperties": false, + "properties": { + "enabled": { + "default": true, "type": "boolean" }, "exclude": { @@ -5119,33 +5320,9 @@ }, "type": "object" }, - "RuleSettings77": { - "additionalProperties": false, - "properties": { - "enabled": { - "default": false, - "type": "boolean" - }, - "exclude": { - "items": { - "type": "string" - }, - "type": "array" - }, - "level": { - "$ref": "#/$defs/Level", - "default": "Warning" - } - }, - "type": "object" - }, "RuleSettings78": { "additionalProperties": false, "properties": { - "allow-array-checks": { - "default": false, - "type": "boolean" - }, "enabled": { "default": true, "type": "boolean" @@ -5158,7 +5335,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Error" } }, "type": "object" @@ -5178,7 +5355,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Note" + "default": "Error" } }, "type": "object" @@ -5222,11 +5399,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Note" - }, - "preserve-single-line-comments": { - "default": false, - "type": "boolean" + "default": "Error" } }, "type": "object" @@ -5246,7 +5419,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Error" } }, "type": "object" @@ -5266,7 +5439,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Error" } }, "type": "object" @@ -5275,7 +5448,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -5286,7 +5459,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Note" } }, "type": "object" @@ -5295,7 +5468,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -5304,19 +5477,9 @@ }, "type": "array" }, - "exclude-constructors": { - "default": true, - "description": "When enabled, constructors are exempt from this rule.", - "type": "boolean" - }, - "exclude-setters": { - "default": false, - "description": "When enabled, methods whose name starts with `set` are exempt from this rule.", - "type": "boolean" - }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Warning" } }, "type": "object" @@ -5324,10 +5487,14 @@ "RuleSettings85": { "additionalProperties": false, "properties": { - "enabled": { + "allow-array-checks": { "default": false, "type": "boolean" }, + "enabled": { + "default": true, + "type": "boolean" + }, "exclude": { "items": { "type": "string" @@ -5356,7 +5523,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Note" } }, "type": "object" @@ -5365,7 +5532,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": false, + "default": true, "type": "boolean" }, "exclude": { @@ -5376,7 +5543,11 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Note" + }, + "preserve-single-line-comments": { + "default": false, + "type": "boolean" } }, "type": "object" @@ -5385,7 +5556,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": false, + "default": true, "type": "boolean" }, "exclude": { @@ -5396,7 +5567,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" + "default": "Warning" } }, "type": "object" @@ -5405,7 +5576,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": false, + "default": true, "type": "boolean" }, "exclude": { @@ -5456,7 +5627,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Note" + "default": "Help" } }, "type": "object" @@ -5474,6 +5645,16 @@ }, "type": "array" }, + "exclude-constructors": { + "default": true, + "description": "When enabled, constructors are exempt from this rule.", + "type": "boolean" + }, + "exclude-setters": { + "default": false, + "description": "When enabled, methods whose name starts with `set` are exempt from this rule.", + "type": "boolean" + }, "level": { "$ref": "#/$defs/Level", "default": "Help" @@ -5485,7 +5666,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -5525,7 +5706,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -5536,7 +5717,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Help" } }, "type": "object" @@ -5545,7 +5726,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -5556,7 +5737,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Help" } }, "type": "object" @@ -5565,7 +5746,7 @@ "additionalProperties": false, "properties": { "enabled": { - "default": true, + "default": false, "type": "boolean" }, "exclude": { @@ -5576,7 +5757,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Warning" + "default": "Help" } }, "type": "object" @@ -5596,11 +5777,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Help" - }, - "psr": { - "default": false, - "type": "boolean" + "default": "Note" } }, "type": "object" @@ -5620,7 +5797,7 @@ }, "level": { "$ref": "#/$defs/Level", - "default": "Note" + "default": "Help" } }, "type": "object" @@ -5628,10 +5805,6 @@ "RuleSettings99": { "additionalProperties": false, "properties": { - "check-functions": { - "default": false, - "type": "boolean" - }, "enabled": { "default": true, "type": "boolean" @@ -5719,7 +5892,7 @@ } }, "constant-condition": { - "$ref": "#/$defs/RuleSettings131", + "$ref": "#/$defs/RuleSettings138", "default": { "enabled": true, "level": "Help" @@ -5805,21 +5978,21 @@ } }, "explicit-nullable-param": { - "$ref": "#/$defs/RuleSettings101", + "$ref": "#/$defs/RuleSettings108", "default": { "enabled": true, "level": "Warning" } }, "explicit-octal": { - "$ref": "#/$defs/RuleSettings102", + "$ref": "#/$defs/RuleSettings109", "default": { "enabled": true, "level": "Warning" } }, "file-name": { - "$ref": "#/$defs/RuleSettings99", + "$ref": "#/$defs/RuleSettings106", "default": { "check-functions": false, "enabled": true, @@ -5834,7 +6007,7 @@ } }, "function-name": { - "$ref": "#/$defs/RuleSettings100", + "$ref": "#/$defs/RuleSettings107", "default": { "camel": false, "either": false, @@ -5853,42 +6026,42 @@ } }, "identity-comparison": { - "$ref": "#/$defs/RuleSettings92", + "$ref": "#/$defs/RuleSettings99", "default": { "enabled": true, "level": "Warning" } }, "ineffective-format-ignore-next": { - "$ref": "#/$defs/RuleSettings93", + "$ref": "#/$defs/RuleSettings100", "default": { "enabled": true, "level": "Warning" } }, "ineffective-format-ignore-region": { - "$ref": "#/$defs/RuleSettings94", + "$ref": "#/$defs/RuleSettings101", "default": { "enabled": true, "level": "Warning" } }, "inline-variable-return": { - "$ref": "#/$defs/RuleSettings95", + "$ref": "#/$defs/RuleSettings102", "default": { "enabled": true, "level": "Warning" } }, "instanceof-stringable": { - "$ref": "#/$defs/RuleSettings96", + "$ref": "#/$defs/RuleSettings103", "default": { "enabled": true, "level": "Warning" } }, "interface-name": { - "$ref": "#/$defs/RuleSettings97", + "$ref": "#/$defs/RuleSettings104", "default": { "enabled": true, "level": "Help", @@ -5896,7 +6069,7 @@ } }, "invalid-open-tag": { - "$ref": "#/$defs/RuleSettings98", + "$ref": "#/$defs/RuleSettings105", "default": { "enabled": true, "level": "Note" @@ -5934,7 +6107,7 @@ } }, "lowercase-type-hint": { - "$ref": "#/$defs/RuleSettings91", + "$ref": "#/$defs/RuleSettings98", "default": { "enabled": true, "level": "Help" @@ -5951,14 +6124,14 @@ } }, "middleware-in-routes": { - "$ref": "#/$defs/RuleSettings147", + "$ref": "#/$defs/RuleSettings154", "default": { "enabled": true, "level": "Warning" } }, "missing-docs": { - "$ref": "#/$defs/RuleSettings167", + "$ref": "#/$defs/RuleSettings174", "default": { "classes": false, "constants": true, @@ -5975,42 +6148,42 @@ } }, "no-alias-function": { - "$ref": "#/$defs/RuleSettings90", + "$ref": "#/$defs/RuleSettings97", "default": { "enabled": true, "level": "Note" } }, "no-alternative-syntax": { - "$ref": "#/$defs/RuleSettings157", + "$ref": "#/$defs/RuleSettings164", "default": { "enabled": false, "level": "Warning" } }, "no-array-accumulation-in-loop": { - "$ref": "#/$defs/RuleSettings132", + "$ref": "#/$defs/RuleSettings139", "default": { "enabled": false, "level": "Warning" } }, "no-assign-in-argument": { - "$ref": "#/$defs/RuleSettings85", + "$ref": "#/$defs/RuleSettings92", "default": { "enabled": false, "level": "Warning" } }, "no-assign-in-condition": { - "$ref": "#/$defs/RuleSettings86", + "$ref": "#/$defs/RuleSettings93", "default": { "enabled": true, "level": "Warning" } }, "no-boolean-flag-parameter": { - "$ref": "#/$defs/RuleSettings84", + "$ref": "#/$defs/RuleSettings91", "default": { "enabled": true, "exclude-constructors": true, @@ -6019,19 +6192,26 @@ } }, "no-closing-tag": { - "$ref": "#/$defs/RuleSettings83", + "$ref": "#/$defs/RuleSettings90", "default": { "enabled": true, "level": "Help" } }, "no-db-schema-change": { - "$ref": "#/$defs/RuleSettings164", + "$ref": "#/$defs/RuleSettings171", "default": { "enabled": true, "level": "Error" } }, + "no-dead-store": { + "$ref": "#/$defs/RuleSettings61", + "default": { + "enabled": false, + "level": "Warning" + } + }, "no-debug-symbols": { "$ref": "#/$defs/RuleSettings27", "default": { @@ -6040,35 +6220,35 @@ } }, "no-direct-db-query": { - "$ref": "#/$defs/RuleSettings163", + "$ref": "#/$defs/RuleSettings170", "default": { "enabled": true, "level": "Warning" } }, "no-else-clause": { - "$ref": "#/$defs/RuleSettings82", + "$ref": "#/$defs/RuleSettings89", "default": { "enabled": true, "level": "Help" } }, "no-empty": { - "$ref": "#/$defs/RuleSettings75", + "$ref": "#/$defs/RuleSettings82", "default": { "enabled": true, "level": "Error" } }, "no-empty-catch-clause": { - "$ref": "#/$defs/RuleSettings81", + "$ref": "#/$defs/RuleSettings88", "default": { "enabled": true, "level": "Warning" } }, "no-empty-comment": { - "$ref": "#/$defs/RuleSettings80", + "$ref": "#/$defs/RuleSettings87", "default": { "enabled": true, "level": "Note", @@ -6076,112 +6256,112 @@ } }, "no-empty-loop": { - "$ref": "#/$defs/RuleSettings79", + "$ref": "#/$defs/RuleSettings86", "default": { "enabled": true, "level": "Note" } }, "no-error-control-operator": { - "$ref": "#/$defs/RuleSettings74", + "$ref": "#/$defs/RuleSettings81", "default": { "enabled": true, "level": "Error" } }, "no-eval": { - "$ref": "#/$defs/RuleSettings73", + "$ref": "#/$defs/RuleSettings80", "default": { "enabled": true, "level": "Error" } }, "no-ffi": { - "$ref": "#/$defs/RuleSettings72", + "$ref": "#/$defs/RuleSettings79", "default": { "enabled": true, "level": "Error" } }, "no-fully-qualified-global-class-like": { - "$ref": "#/$defs/RuleSettings87", + "$ref": "#/$defs/RuleSettings94", "default": { "enabled": false, "level": "Help" } }, "no-fully-qualified-global-constant": { - "$ref": "#/$defs/RuleSettings88", + "$ref": "#/$defs/RuleSettings95", "default": { "enabled": false, "level": "Help" } }, "no-fully-qualified-global-function": { - "$ref": "#/$defs/RuleSettings89", + "$ref": "#/$defs/RuleSettings96", "default": { "enabled": false, "level": "Help" } }, "no-global": { - "$ref": "#/$defs/RuleSettings71", + "$ref": "#/$defs/RuleSettings78", "default": { "enabled": true, "level": "Error" } }, "no-goto": { - "$ref": "#/$defs/RuleSettings70", + "$ref": "#/$defs/RuleSettings77", "default": { "enabled": true, "level": "Note" } }, "no-hash-comment": { - "$ref": "#/$defs/RuleSettings68", + "$ref": "#/$defs/RuleSettings75", "default": { "enabled": true, "level": "Warning" } }, "no-hash-emoji": { - "$ref": "#/$defs/RuleSettings67", + "$ref": "#/$defs/RuleSettings74", "default": { "enabled": true, "level": "Warning" } }, "no-ini-set": { - "$ref": "#/$defs/RuleSettings133", + "$ref": "#/$defs/RuleSettings140", "default": { "enabled": true, "level": "Warning" } }, "no-inline": { - "$ref": "#/$defs/RuleSettings135", + "$ref": "#/$defs/RuleSettings142", "default": { "enabled": false, "level": "Error" } }, "no-insecure-comparison": { - "$ref": "#/$defs/RuleSettings137", + "$ref": "#/$defs/RuleSettings144", "default": { "enabled": true, "level": "Error" } }, "no-is-null": { - "$ref": "#/$defs/RuleSettings76", + "$ref": "#/$defs/RuleSettings83", "default": { "enabled": false, "level": "Note" } }, "no-isset": { - "$ref": "#/$defs/RuleSettings78", + "$ref": "#/$defs/RuleSettings85", "default": { "allow-array-checks": false, "enabled": true, @@ -6189,77 +6369,84 @@ } }, "no-iterator-to-array-in-foreach": { - "$ref": "#/$defs/RuleSettings77", + "$ref": "#/$defs/RuleSettings84", "default": { "enabled": false, "level": "Warning" } }, "no-literal-namespace-string": { - "$ref": "#/$defs/RuleSettings168", + "$ref": "#/$defs/RuleSettings175", "default": { "enabled": false, "level": "Warning" } }, "no-literal-password": { - "$ref": "#/$defs/RuleSettings138", + "$ref": "#/$defs/RuleSettings145", "default": { "enabled": true, "level": "Error" } }, "no-multi-assignments": { - "$ref": "#/$defs/RuleSettings65", + "$ref": "#/$defs/RuleSettings71", "default": { "enabled": true, "level": "Warning" } }, + "no-negated-ternary": { + "$ref": "#/$defs/RuleSettings72", + "default": { + "enabled": false, + "level": "Help" + } + }, "no-nested-ternary": { - "$ref": "#/$defs/RuleSettings66", + "$ref": "#/$defs/RuleSettings73", "default": { "enabled": true, "level": "Warning" } }, "no-noop": { - "$ref": "#/$defs/RuleSettings63", + "$ref": "#/$defs/RuleSettings69", "default": { "enabled": true, "level": "Help" } }, "no-null-property-init": { - "$ref": "#/$defs/RuleSettings161", + "$ref": "#/$defs/RuleSettings168", "default": { "enabled": false, "level": "Help" } }, "no-only": { - "$ref": "#/$defs/RuleSettings64", + "$ref": "#/$defs/RuleSettings70", "default": { "enabled": true, "level": "Error" } }, "no-parameter-shadowing": { - "$ref": "#/$defs/RuleSettings134", + "$ref": "#/$defs/RuleSettings141", "default": { "enabled": false, "level": "Warning" } }, "no-php-tag-terminator": { - "$ref": "#/$defs/RuleSettings62", + "$ref": "#/$defs/RuleSettings68", "default": { "enabled": true, "level": "Note" } }, "no-protected-in-final": { - "$ref": "#/$defs/RuleSettings61", + "$ref": "#/$defs/RuleSettings67", "default": { "enabled": true, "level": "Help" @@ -6273,7 +6460,7 @@ } }, "no-redundant-block": { - "$ref": "#/$defs/RuleSettings57", + "$ref": "#/$defs/RuleSettings58", "default": { "enabled": true, "level": "Help" @@ -6286,6 +6473,13 @@ "level": "Help" } }, + "no-redundant-else": { + "$ref": "#/$defs/RuleSettings57", + "default": { + "enabled": false, + "level": "Help" + } + }, "no-redundant-file": { "$ref": "#/$defs/RuleSettings55", "default": { @@ -6364,12 +6558,19 @@ } }, "no-redundant-use": { - "$ref": "#/$defs/RuleSettings58", + "$ref": "#/$defs/RuleSettings59", "default": { "enabled": true, "level": "Warning" } }, + "no-redundant-variable": { + "$ref": "#/$defs/RuleSettings60", + "default": { + "enabled": false, + "level": "Warning" + } + }, "no-redundant-write-visibility": { "$ref": "#/$defs/RuleSettings43", "default": { @@ -6378,14 +6579,14 @@ } }, "no-redundant-yield-from": { - "$ref": "#/$defs/RuleSettings59", + "$ref": "#/$defs/RuleSettings65", "default": { "enabled": true, "level": "Help" } }, "no-request-all": { - "$ref": "#/$defs/RuleSettings145", + "$ref": "#/$defs/RuleSettings152", "default": { "enabled": true, "level": "Warning" @@ -6399,21 +6600,21 @@ } }, "no-roles-as-capabilities": { - "$ref": "#/$defs/RuleSettings166", + "$ref": "#/$defs/RuleSettings173", "default": { "enabled": true, "level": "Warning" } }, "no-self-assignment": { - "$ref": "#/$defs/RuleSettings60", + "$ref": "#/$defs/RuleSettings66", "default": { "enabled": true, "level": "Warning" } }, "no-service-state-mutation": { - "$ref": "#/$defs/RuleSettings146", + "$ref": "#/$defs/RuleSettings153", "default": { "allowed-methods": [ "__construct", @@ -6442,7 +6643,7 @@ } }, "no-short-bool-cast": { - "$ref": "#/$defs/RuleSettings156", + "$ref": "#/$defs/RuleSettings163", "default": { "enabled": false, "level": "Help" @@ -6463,7 +6664,7 @@ } }, "no-side-effects-with-declarations": { - "$ref": "#/$defs/RuleSettings136", + "$ref": "#/$defs/RuleSettings143", "default": { "allow-class-alias": true, "allow-class-exists": true, @@ -6494,21 +6695,42 @@ } }, "no-unescaped-output": { - "$ref": "#/$defs/RuleSettings165", + "$ref": "#/$defs/RuleSettings172", "default": { "enabled": true, "level": "Error" } }, "no-unsafe-finally": { - "$ref": "#/$defs/RuleSettings142", + "$ref": "#/$defs/RuleSettings149", "default": { "enabled": true, "level": "Error" } }, + "no-unused-closure-capture": { + "$ref": "#/$defs/RuleSettings64", + "default": { + "enabled": false, + "level": "Warning" + } + }, + "no-unused-global": { + "$ref": "#/$defs/RuleSettings63", + "default": { + "enabled": false, + "level": "Warning" + } + }, + "no-unused-static": { + "$ref": "#/$defs/RuleSettings62", + "default": { + "enabled": false, + "level": "Warning" + } + }, "no-variable-variable": { - "$ref": "#/$defs/RuleSettings69", + "$ref": "#/$defs/RuleSettings76", "default": { "enabled": true, "level": "Warning" @@ -6536,14 +6758,14 @@ } }, "prefer-arrow-function": { - "$ref": "#/$defs/RuleSettings103", + "$ref": "#/$defs/RuleSettings110", "default": { "enabled": true, "level": "Help" } }, "prefer-early-continue": { - "$ref": "#/$defs/RuleSettings104", + "$ref": "#/$defs/RuleSettings111", "default": { "enabled": true, "level": "Help", @@ -6566,56 +6788,56 @@ } }, "prefer-interface": { - "$ref": "#/$defs/RuleSettings105", + "$ref": "#/$defs/RuleSettings112", "default": { "enabled": true, "level": "Note" } }, "prefer-pre-increment": { - "$ref": "#/$defs/RuleSettings158", + "$ref": "#/$defs/RuleSettings165", "default": { "enabled": false, "level": "Help" } }, "prefer-self-return-type": { - "$ref": "#/$defs/RuleSettings159", + "$ref": "#/$defs/RuleSettings166", "default": { "enabled": false, "level": "Help" } }, "prefer-static-closure": { - "$ref": "#/$defs/RuleSettings106", + "$ref": "#/$defs/RuleSettings113", "default": { "enabled": true, "level": "Help" } }, "prefer-test-attribute": { - "$ref": "#/$defs/RuleSettings107", + "$ref": "#/$defs/RuleSettings114", "default": { "enabled": false, "level": "Warning" } }, "prefer-view-array": { - "$ref": "#/$defs/RuleSettings108", + "$ref": "#/$defs/RuleSettings115", "default": { "enabled": true, "level": "Help" } }, "prefer-while-loop": { - "$ref": "#/$defs/RuleSettings109", + "$ref": "#/$defs/RuleSettings116", "default": { "enabled": true, "level": "Note" } }, "property-name": { - "$ref": "#/$defs/RuleSettings141", + "$ref": "#/$defs/RuleSettings148", "default": { "camel": true, "either": false, @@ -6624,70 +6846,70 @@ } }, "psl-array-functions": { - "$ref": "#/$defs/RuleSettings110", - "default": { - "enabled": true, - "level": "Warning" - } - }, - "psl-data-structures": { - "$ref": "#/$defs/RuleSettings111", - "default": { - "enabled": true, - "level": "Warning" - } - }, - "psl-datetime": { - "$ref": "#/$defs/RuleSettings112", - "default": { - "enabled": true, - "level": "Warning" - } - }, - "psl-math-functions": { - "$ref": "#/$defs/RuleSettings113", - "default": { - "enabled": true, - "level": "Warning" - } - }, - "psl-output": { - "$ref": "#/$defs/RuleSettings114", - "default": { - "enabled": true, - "level": "Error" - } - }, - "psl-randomness-functions": { - "$ref": "#/$defs/RuleSettings115", - "default": { - "enabled": true, - "level": "Warning" - } - }, - "psl-regex-functions": { - "$ref": "#/$defs/RuleSettings116", - "default": { - "enabled": true, - "level": "Warning" - } - }, - "psl-sleep-functions": { "$ref": "#/$defs/RuleSettings117", "default": { "enabled": true, "level": "Warning" } }, - "psl-string-functions": { + "psl-data-structures": { "$ref": "#/$defs/RuleSettings118", "default": { "enabled": true, "level": "Warning" } }, + "psl-datetime": { + "$ref": "#/$defs/RuleSettings119", + "default": { + "enabled": true, + "level": "Warning" + } + }, + "psl-math-functions": { + "$ref": "#/$defs/RuleSettings120", + "default": { + "enabled": true, + "level": "Warning" + } + }, + "psl-output": { + "$ref": "#/$defs/RuleSettings121", + "default": { + "enabled": true, + "level": "Error" + } + }, + "psl-randomness-functions": { + "$ref": "#/$defs/RuleSettings122", + "default": { + "enabled": true, + "level": "Warning" + } + }, + "psl-regex-functions": { + "$ref": "#/$defs/RuleSettings123", + "default": { + "enabled": true, + "level": "Warning" + } + }, + "psl-sleep-functions": { + "$ref": "#/$defs/RuleSettings124", + "default": { + "enabled": true, + "level": "Warning" + } + }, + "psl-string-functions": { + "$ref": "#/$defs/RuleSettings125", + "default": { + "enabled": true, + "level": "Warning" + } + }, "readable-literal": { - "$ref": "#/$defs/RuleSettings154", + "$ref": "#/$defs/RuleSettings161", "default": { "enabled": true, "level": "Warning", @@ -6695,63 +6917,63 @@ } }, "require-namespace": { - "$ref": "#/$defs/RuleSettings150", + "$ref": "#/$defs/RuleSettings157", "default": { "enabled": false, "level": "Warning" } }, "require-preg-quote-delimiter": { - "$ref": "#/$defs/RuleSettings149", + "$ref": "#/$defs/RuleSettings156", "default": { "enabled": true, "level": "Warning" } }, "sensitive-parameter": { - "$ref": "#/$defs/RuleSettings140", + "$ref": "#/$defs/RuleSettings147", "default": { "enabled": true, "level": "Error" } }, "single-class-per-file": { - "$ref": "#/$defs/RuleSettings153", + "$ref": "#/$defs/RuleSettings160", "default": { "enabled": true, "level": "Warning" } }, "sorted-integer-keys": { - "$ref": "#/$defs/RuleSettings151", + "$ref": "#/$defs/RuleSettings158", "default": { "enabled": false, "level": "Help" } }, "str-contains": { - "$ref": "#/$defs/RuleSettings119", + "$ref": "#/$defs/RuleSettings126", "default": { "enabled": true, "level": "Warning" } }, "str-starts-with": { - "$ref": "#/$defs/RuleSettings120", + "$ref": "#/$defs/RuleSettings127", "default": { "enabled": true, "level": "Warning" } }, "strict-assertions": { - "$ref": "#/$defs/RuleSettings143", + "$ref": "#/$defs/RuleSettings150", "default": { "enabled": true, "level": "Warning" } }, "strict-behavior": { - "$ref": "#/$defs/RuleSettings121", + "$ref": "#/$defs/RuleSettings128", "default": { "allow-loose-behavior": false, "enabled": true, @@ -6759,7 +6981,7 @@ } }, "strict-types": { - "$ref": "#/$defs/RuleSettings122", + "$ref": "#/$defs/RuleSettings129", "default": { "allow-disabling": false, "enabled": true, @@ -6767,7 +6989,7 @@ } }, "string-style": { - "$ref": "#/$defs/RuleSettings152", + "$ref": "#/$defs/RuleSettings159", "default": { "enabled": false, "level": "Note", @@ -6775,28 +6997,28 @@ } }, "switch-continue-to-break": { - "$ref": "#/$defs/RuleSettings160", + "$ref": "#/$defs/RuleSettings167", "default": { "enabled": false, "level": "Warning" } }, "tagged-fixme": { - "$ref": "#/$defs/RuleSettings123", + "$ref": "#/$defs/RuleSettings130", "default": { "enabled": true, "level": "Warning" } }, "tagged-todo": { - "$ref": "#/$defs/RuleSettings124", + "$ref": "#/$defs/RuleSettings131", "default": { "enabled": true, "level": "Warning" } }, "tainted-data-to-sink": { - "$ref": "#/$defs/RuleSettings139", + "$ref": "#/$defs/RuleSettings146", "default": { "enabled": true, "known-sink-functions": [ @@ -6806,7 +7028,7 @@ } }, "too-many-enum-cases": { - "$ref": "#/$defs/RuleSettings125", + "$ref": "#/$defs/RuleSettings132", "default": { "enabled": true, "level": "Error", @@ -6814,7 +7036,7 @@ } }, "too-many-methods": { - "$ref": "#/$defs/RuleSettings126", + "$ref": "#/$defs/RuleSettings133", "default": { "count-hooks": false, "count-setters-and-getters": false, @@ -6824,7 +7046,7 @@ } }, "too-many-properties": { - "$ref": "#/$defs/RuleSettings127", + "$ref": "#/$defs/RuleSettings134", "default": { "enabled": true, "level": "Error", @@ -6832,7 +7054,7 @@ } }, "trait-name": { - "$ref": "#/$defs/RuleSettings128", + "$ref": "#/$defs/RuleSettings135", "default": { "enabled": true, "level": "Help", @@ -6840,7 +7062,7 @@ } }, "use-compound-assignment": { - "$ref": "#/$defs/RuleSettings148", + "$ref": "#/$defs/RuleSettings155", "default": { "enabled": true, "level": "Help" @@ -6861,7 +7083,7 @@ } }, "use-specific-assertions": { - "$ref": "#/$defs/RuleSettings144", + "$ref": "#/$defs/RuleSettings151", "default": { "enabled": true, "level": "Warning" @@ -6875,21 +7097,21 @@ } }, "use-wp-functions": { - "$ref": "#/$defs/RuleSettings162", + "$ref": "#/$defs/RuleSettings169", "default": { "enabled": true, "level": "Warning" } }, "valid-docblock": { - "$ref": "#/$defs/RuleSettings129", + "$ref": "#/$defs/RuleSettings136", "default": { "enabled": true, "level": "Note" } }, "variable-name": { - "$ref": "#/$defs/RuleSettings130", + "$ref": "#/$defs/RuleSettings137", "default": { "camel": false, "check-parameters": true, @@ -6899,7 +7121,7 @@ } }, "yoda-conditions": { - "$ref": "#/$defs/RuleSettings155", + "$ref": "#/$defs/RuleSettings162", "default": { "enabled": false, "level": "Help" @@ -6957,7 +7179,7 @@ "type": "array" }, "workspace": { - "default": "/home/gcch/Répertoires/git.gcch.fr/haiku-atelier-2024", + "default": "/home/gcch/Répertoires/git.gcch.fr/gcch/haiku-atelier-2024", "description": "The workspace directory from which to start scanning.\n\nDefaults to the current working directory.", "type": "string" } @@ -7161,7 +7383,7 @@ }, "$schema": "https://json-schema.org/draft/2020-12/schema", "additionalProperties": false, - "description": "The main configuration structure for Mago CLI.\n\nThis struct aggregates all configuration settings for Mago, including global options\nlike threading and PHP version, as well as specialized configurations for each service\n(linter, analyzer, formatter, guard).\n\nConfiguration values are loaded from multiple sources with the following precedence\n(from highest to lowest):\n\n1. Environment variables (`MAGO_*`)\n2. Workspace `mago.toml` file\n3. Global `mago.toml` file (`$XDG_CONFIG_HOME` or `$HOME`)\n4. Built-in defaults\n\nThe struct uses serde for deserialization from TOML files and environment variables,\nwith strict validation via `deny_unknown_fields` to catch configuration errors early.", + "description": "The main configuration structure for Mago CLI.\n\nAggregates all settings: top-level scalars (`php-version`, `threads`, …) plus\nservice-specific sub-configurations (linter, analyzer, formatter, guard, parser).\n\nLoaded by [`Configuration::load`]; see the [module-level documentation](self) for the\nfull precedence order and `extends` semantics. Strict validation via\n`deny_unknown_fields` catches typos early (note that the `extends` directive itself is\nstripped from each layer before deserialization, so it never trips the strict check).", "properties": { "allow-unsupported-php-version": { "default": false, @@ -7171,6 +7393,7 @@ "analyzer": { "$ref": "#/$defs/AnalyzerConfiguration", "default": { + "allow-implicit-pipe-callable-types": false, "allow-possibly-undefined-array-keys": true, "allow-side-effects-in-conditions": true, "analyze-dead-code": false, @@ -7494,6 +7717,10 @@ "enabled": true, "level": "Error" }, + "no-dead-store": { + "enabled": false, + "level": "Warning" + }, "no-debug-symbols": { "enabled": true, "level": "Note" @@ -7600,6 +7827,10 @@ "enabled": true, "level": "Warning" }, + "no-negated-ternary": { + "enabled": false, + "level": "Help" + }, "no-nested-ternary": { "enabled": true, "level": "Warning" @@ -7640,6 +7871,10 @@ "enabled": true, "level": "Help" }, + "no-redundant-else": { + "enabled": false, + "level": "Help" + }, "no-redundant-file": { "enabled": true, "level": "Help" @@ -7688,6 +7923,10 @@ "enabled": true, "level": "Warning" }, + "no-redundant-variable": { + "enabled": false, + "level": "Warning" + }, "no-redundant-write-visibility": { "enabled": true, "level": "Help" @@ -7774,6 +8013,18 @@ "enabled": true, "level": "Error" }, + "no-unused-closure-capture": { + "enabled": false, + "level": "Warning" + }, + "no-unused-global": { + "enabled": false, + "level": "Warning" + }, + "no-unused-static": { + "enabled": false, + "level": "Warning" + }, "no-variable-variable": { "enabled": true, "level": "Warning" @@ -8046,7 +8297,7 @@ }, "includes": [], "paths": [], - "workspace": "/home/gcch/Répertoires/git.gcch.fr/haiku-atelier-2024" + "workspace": "/home/gcch/Répertoires/git.gcch.fr/gcch/haiku-atelier-2024" }, "description": "Source discovery and workspace configuration.\n\nDefines the workspace root, source paths to scan, and exclusion patterns.\nThis configuration determines which PHP files are loaded into the database\nfor analysis, linting, or formatting." }, @@ -8058,7 +8309,7 @@ "type": "integer" }, "threads": { - "default": 4, + "default": 12, "description": "Number of worker threads for parallel processing.\n\nControls the thread pool size used by Rayon for parallel operations.\nIf set to 0, defaults to the number of logical CPUs available.\nCan be overridden via `MAGO_THREADS` environment variable or `--threads` CLI flag.", "format": "uint", "minimum": 0, diff --git a/mago.toml b/mago.toml index f29e960d..aa5c2ab6 100644 --- a/mago.toml +++ b/mago.toml @@ -36,6 +36,7 @@ threads = 0 no-else-clause = { enabled = false } [analyzer] + allow-implicit-pipe-callable-types = false allow-possibly-undefined-array-keys = false allow-side-effects-in-conditions = true analyze-dead-code = true diff --git a/mise.toml b/mise.toml new file mode 100644 index 00000000..d2d9db14 --- /dev/null +++ b/mise.toml @@ -0,0 +1,2 @@ +[tools] + "github:AJenbo/phpantom_lsp" = "latest" diff --git a/package.json b/package.json index 5e0a9dd9..cf80f947 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,10 @@ }, "dependencies": { "@mobily/ts-belt": "v4.0.0-rc.5", - "@sentry/browser": "^10.50.0", + "@sentry/browser": "^10.51.0", "a11y-dialog": "^8.1.5", "effect": "^4.0.0-beta.59", + "html-template-tag": "^5.0.0", "lit-html": "^3.3.2", "purify-ts": "2.1.2", "ts-pattern": "^5.9.0", @@ -23,28 +24,28 @@ }, "devDependencies": { "@effect/language-service": "^0.85.1", - "@effect/tsgo": "0.5.1", + "@effect/tsgo": "^0.5.2", "@gcch/configuration-eslint": "git+https://git.gcch.fr/gcch/configuration-eslint#888eb4aa54", "@gcch/configuration-oxlint": "git+https://git.gcch.fr/gcch/configuration-oxlint#83547fc1ebfd", "@gcch/configuration-prettier": "git+https://git.gcch.fr/gcch/configuration-prettier#d267d6dc5e", "@playwright/test": "^1.59.1", - "@sentry/core": "^10.50.0", + "@sentry/core": "^10.51.0", "@types/bun": "^1.3.13", "@types/node": "^25.6.0", - "@typescript/native-preview": "7.0.0-dev.20260429.1", + "@typescript/native-preview": "7.0.0-dev.20260503.1", "@vitejs/plugin-legacy": "^8.0.1", "better-typescript-lib": "^2.12.0", "browserslist": "^4.28.2", "caniuse-lite": "^1.0.30001791", - "eslint": "^10.2.1", + "eslint": "^10.3.0", "eslint-plugin-functional": "^9.0.4", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-oxlint": "^1.62.0", "eslint-plugin-perfectionist": "^5.9.0", "fdir": "^6.5.0", - "globals": "^17.5.0", + "globals": "^17.6", "jiti": "^2.6.1", - "knip": "^6.8.0", + "knip": "^6.11.0", "lightningcss": "^1.32.0", "lightningcss-cli": "^1.32.0", "oxlint": "^1.62.0", diff --git a/phpactor.schema.json b/phpactor.schema.json index 309f3c4c..0b95e93e 100644 --- a/phpactor.schema.json +++ b/phpactor.schema.json @@ -236,6 +236,21 @@ "default": 1610612736, "description": "Ensure that PHP has a memory_limit of at least this amount in bytes" }, + "core.project_config_candidates": { + "default": [], + "description": "(internal) list of potential project-level configuration files" + }, + "core.trust": { + "default": { + "path": null, + "trust": [] + }, + "description": "(internal) map of trusted project directories" + }, + "core.trusted": { + "default": false, + "description": "(internal) if the configuration is trusted" + }, "file_path_resolver.app_name": { "default": "phpactor", "description": null @@ -278,7 +293,8 @@ "default": [ "/vendor/**/tests/**/*", "/vendor/**/Tests/**/*", - "/vendor/composer/**/*" + "/vendor/composer/**/*", + "/vendor/rector/rector/stubs-rector" ], "description": "Glob patterns to exclude while indexing", "type": [ @@ -316,6 +332,13 @@ "string" ] }, + "indexer.max_filesize_to_index": { + "default": 1000000, + "description": "Files larger than this will not be indexed. (Size in bytes)", + "type": [ + "integer" + ] + }, "indexer.poll_time": { "default": 5000, "description": "For polling indexers only: the time, in milliseconds, between polls (e.g. filesystem scans)", @@ -337,6 +360,13 @@ "boolean" ] }, + "indexer.search_include_patterns": { + "default": [], + "description": "When searching the index exclude records whose fully qualified names match any of these regex patterns (use to exclude suggestions from search results). Namespace separators must be escaped as `\\\\\\\\` for example `^Foo\\\\\\\\` to include all namespaces whose first segment is `Foo`", + "type": [ + "object" + ] + }, "indexer.stub_paths": { "default": [], "description": "Paths to external folders to index. They will be indexed only once, if you want to take any changes into account you will have to reindex your project manually.", @@ -362,6 +392,10 @@ "default": [], "description": "List of paths to exclude from diagnostics, e.g. `vendor/**/*`" }, + "language_server.diagnostic_ignore_codes": { + "default": [], + "description": "Ignore diagnostics that have the codes listed here, e.g. [\"fix_namespace_class_name\"]. The codes match those shown in the LSP client." + }, "language_server.diagnostic_outsource": { "default": true, "description": "If applicable diagnostics should be \"outsourced\" to a different process" @@ -389,6 +423,10 @@ "default": true, "description": "Perform diagnostics when the text document is updated" }, + "language_server.enable_trust_check": { + "default": true, + "description": "Check to see if project path is trusted before loading configurations from it" + }, "language_server.enable_workspace": { "default": true, "description": "If workspace management / text synchronization should be enabled (this isn't required for some language server implementations, e.g. static analyzers)" @@ -450,6 +488,17 @@ "boolean" ] }, + "language_server_highlight.enabled": { + "default": true, + "description": "Enable or disable the highlighter (can be expensive on large documents)" + }, + "language_server_indexer.optimiser_timeout": { + "default": 3600, + "description": "Optimise the index every N seconds", + "type": [ + "integer" + ] + }, "language_server_indexer.reindex_timeout": { "default": 300, "description": "Unconditionally reindex modified files every N seconds" @@ -467,15 +516,17 @@ }, "language_server_php_cs_fixer.env": { "default": { - "PHP_CS_FIXER_IGNORE_ENV": true, "XDEBUG_MODE": "off" }, - "description": "Environment for PHP CS Fixer (e.g. to set PHP_CS_FIXER_IGNORE_ENV)" + "description": "Environment for PHP CS Fixer" }, "language_server_php_cs_fixer.show_diagnostics": { "default": true, "description": "Whether PHP CS Fixer diagnostics are shown" }, + "language_server_php_cs_fixer.version": { + "description": "Arbitrary version (if not provided, phpactor tries to detect it - only to run it on unsupported PHP versions)" + }, "language_server_phpstan.bin": { "default": "%project_root%/vendor/bin/phpstan", "description": "Path to the PHPStan executable" @@ -483,12 +534,24 @@ "language_server_phpstan.config": { "description": "Override the PHPStan configuration file" }, + "language_server_phpstan.editor_mode": { + "default": false, + "description": "DEPRECATED. Editor mode of Phpstan is used automatically when it's supported." + }, "language_server_phpstan.level": { "description": "Override the PHPStan level" }, "language_server_phpstan.mem_limit": { "description": "Override the PHPStan memory limit" }, + "language_server_phpstan.severity": { + "default": 1, + "description": "Severity at which PHPStan diagnostics should be reported. Ranges from 1 (error) to 4 (hint)." + }, + "language_server_phpstan.tmp_file_disabled": { + "default": false, + "description": "Disable the use of temporary files when. This prevents as-you-type diagnostics, but ensures paths in phpstan config are respected. See https://github.com/phpactor/phpactor/issues/2763" + }, "language_server_psalm.bin": { "default": "%project_root%/vendor/bin/psalm", "description": "Path to psalm if different from vendor/bin/psalm", @@ -496,6 +559,13 @@ "string" ] }, + "language_server_psalm.config": { + "default": "", + "description": "Path to psalm config. Like %project_root%/psalm.xml", + "type": [ + "string" + ] + }, "language_server_psalm.error_level": { "description": "Override level at which Psalm should report errors (lower => more errors)" }, @@ -527,6 +597,10 @@ "boolean" ] }, + "language_server_reference_finder.soft_timeout": { + "default": 10, + "description": "Interupt and ask for confirmation to continue after this timeout (in seconds)" + }, "language_server_reference_reference_finder.reference_timeout": { "default": 60, "description": "Stop searching for references after this time (in seconds) has expired" @@ -658,6 +732,10 @@ "default": "%project_root%/var/cache/dev/App_KernelDevDebugContainer.xml", "description": "Path to the Symfony container XML dump file" }, + "worse_reflection.additive_stubs": { + "default": [], + "description": "Additive stubs files relative to the project root. These stubs augment existing defininitions." + }, "worse_reflection.cache_dir": { "default": "%cache%/worse-reflection", "description": "Cache directory for stubs" diff --git a/scripts/remove-scaled-images.php b/scripts/remove-scaled-images.php index d4bd6024..678f8f36 100755 --- a/scripts/remove-scaled-images.php +++ b/scripts/remove-scaled-images.php @@ -16,7 +16,7 @@ $wp_postmeta = "{$wpdb->prefix}postmeta"; try { $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Error Handling - $sql = "UPDATE {$wp_postmeta} SET meta_value = REPLACE(meta_value,'-scaled.jpg','.jpg') WHERE meta_key='_wp_attached_file' AND meta_value LIKE '%-scaled.jpg%'"; + $sql = "UPDATE {$wp_postmeta} SET meta_value = REPLACE(meta_value,'-scaled.jpg','.jpg') WHERE meta_key='_wp_attached_file' AND meta_value LIKE '%-scaled.jpg%'"; $result = $pdo->exec($sql); print_r($result); } catch (PDOException $e) { @@ -29,12 +29,12 @@ $image_metas = []; try { $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Error Handling - $sql = "SELECT * FROM {$wp_postmeta} WHERE meta_value LIKE '%-scaled.jpg%' AND meta_key='_wp_attachment_metadata'"; - $statement = $pdo->query($sql); + $sql = "SELECT * FROM {$wp_postmeta} WHERE meta_value LIKE '%-scaled.jpg%' AND meta_key='_wp_attachment_metadata'"; + $statement = $pdo->query($sql); $image_metas = $statement->fetchAll(); foreach ($image_metas as $meta) { - $meta_value = unserialize($meta['meta_value']); - $file = $meta_value['file']; + $meta_value = unserialize($meta['meta_value']); + $file = $meta_value['file']; $meta_value['file'] = str_replace('-scaled.jpg', '.jpg', $file); update_post_meta($meta['post_id'], $meta['meta_key'], $meta_value); $result = get_post_meta($meta['post_id'], $meta['meta_key']); diff --git a/tests/playwright/shop.spec.ts b/tests/playwright/shop.spec.ts index ec8a092c..465f4816 100644 --- a/tests/playwright/shop.spec.ts +++ b/tests/playwright/shop.spec.ts @@ -1,3 +1,4 @@ +/** @effect-diagnostics asyncFunction:skip-file */ import type { APIRequestContext, Locator, Page, Response } from "@playwright/test"; import { expect, test } from "@playwright/test"; import type { WCV3Products } from "../../web/app/themes/haiku-atelier-2024/src/scripts/lib/types/api/v3/products"; @@ -10,7 +11,7 @@ test("can scroll to the end of the grid", async ({ page }): Promise => { await scrollToGridsEnd(page); }); -test.skip("can access all Products' pages", async ({ page, request }): Promise => { +test("can access all Products' pages", async ({ page, request }): Promise => { await page["goto"]("https://haikuatelier.gcch.local/shop/"); const links = await getAllProductsLinks(page, request); diff --git a/web/app/themes/haiku-atelier-2024/404.php b/web/app/themes/haiku-atelier-2024/404.php index f6296dd4..dd1b631e 100755 --- a/web/app/themes/haiku-atelier-2024/404.php +++ b/web/app/themes/haiku-atelier-2024/404.php @@ -14,7 +14,7 @@ use Timber\Timber; use function add_action; -$context = Timber::context(); +$context = Timber::context(); $templates = ['404.twig']; /** @@ -25,7 +25,7 @@ $templates = ['404.twig']; function load_page_resources(): void { Resource::enqueue_style_file( handle: 'haiku-atelier-2024-styles-page-a-propos', - path: '/assets/css/pages/page-modele-simple.css', + path : '/assets/css/pages/page-modele-simple.css', ); } diff --git a/web/app/themes/haiku-atelier-2024/archive-product.php b/web/app/themes/haiku-atelier-2024/archive-product.php index 2a97be56..5dff6690 100755 --- a/web/app/themes/haiku-atelier-2024/archive-product.php +++ b/web/app/themes/haiku-atelier-2024/archive-product.php @@ -17,28 +17,22 @@ use WC_Product; use function add_action; use function array_map; use function assert; -use function base64_encode; use function is_string; use function wc_get_products; use function wp_create_nonce; use function wp_json_encode; -$context = Timber::context(); +$context = Timber::context(); $templates = ['boutique.twig']; /** @var list $wc_products Les informations brutes des Produits. */ $wc_products = wc_get_products(['limit' => 12, 'order' => 'DESC', 'orderby' => 'date', 'status' => 'publish']); -$products = array_map(callback: Product::from_wc_product(...), array: $wc_products); +$products = array_map(callback: Product::from_wc_product(...), array: $wc_products); $context['products'] = $products; // Injecte les états initiaux des données du Produit sous forme de JSON dans le contexte. -$page_states = [ - 'nonce' => wp_create_nonce('wc_store_api'), - 'authString' => base64_encode( - Config::get('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . Config::get('WOOCOMMERCE_API_CONSUMER_SECRET'), - ), -] +$page_states = ['authString' => Config::get('WOOCOMMERCE_API_AUTH_STRING'), 'nonce' => wp_create_nonce('wc_store_api')] |> wp_json_encode(...); assert(is_string($page_states)); $context['page_states'] = $page_states; @@ -46,14 +40,14 @@ $context['page_states'] = $page_states; add_action('wp_enqueue_scripts', function (): void { Resource::enqueue_style_file( handle: 'haiku-atelier-2024-styles-page-boutique', - path: '/assets/css/pages/page-boutique.css', + path : '/assets/css/pages/page-boutique.css', ); Resource::enqueue_script_module_file( - id: 'haiku-atelier-2024-scripts-page-boutique', + id : 'haiku-atelier-2024-scripts-page-boutique', path: '/assets/js/scripts-page-boutique.js', ); Resource::enqueue_script_module_file( - id: 'haiku-atelier-2024-scripts-menu-categories', + id : 'haiku-atelier-2024-scripts-menu-categories', path: '/assets/js/scripts-menu-categories.js', ); }); diff --git a/web/app/themes/haiku-atelier-2024/assets/css/main.css b/web/app/themes/haiku-atelier-2024/assets/css/main.css index b229b3cc..9ac1598c 100755 --- a/web/app/themes/haiku-atelier-2024/assets/css/main.css +++ b/web/app/themes/haiku-atelier-2024/assets/css/main.css @@ -462,8 +462,8 @@ input[type="checkbox"], input[type="radio"] { transition: 0.2s background; } input[type="checkbox"]:checked, input[type="radio"]:checked { - color: var(--couleur-blanc); - background: var(--couleur-gris-fonce); + color: var(--couleur-noir); + background: var(--arriere-plan-points); } input[type="checkbox"]:checked::before, input[type="radio"]:checked::before { content: "x"; @@ -492,7 +492,7 @@ input[type="radio"] + label { } @media (hover: hover) { input[type="checkbox"]:hover, input[type="radio"]:hover { - background: var(--couleur-gris-fonce); + background: var(--arriere-plan-points); } } diff --git a/web/app/themes/haiku-atelier-2024/assets/css/main.min.css b/web/app/themes/haiku-atelier-2024/assets/css/main.min.css index b920d260..6c22705f 100755 --- a/web/app/themes/haiku-atelier-2024/assets/css/main.min.css +++ b/web/app/themes/haiku-atelier-2024/assets/css/main.min.css @@ -1 +1 @@ -@font-face{font-family:Lato;font-weight:100 900;font-style:normal;font-display:swap;src:url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2)format("woff2")tech(variations),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2)format("woff2-variations"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.ttf)format("truetype");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Lato;font-weight:100 900;font-style:italic;font-display:swap;src:url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2)format("woff2")tech(variations),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2)format("woff2-variations"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.ttf)format("truetype");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Myriad;font-weight:300 900;font-style:normal;font-display:swap;font-stretch:70% 110%;src:url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable.ttf)format("truetype")}@font-face{font-family:Myriad;font-weight:300 900;font-style:italic;font-display:swap;font-stretch:70% 110%;src:url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable-italic.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable-italic.ttf)format("truetype")}:root{--couleur-blanc:oklch(100% 0 0);--couleur-blanc-fond:oklch(100% 0 0/.8);--couleur-gris:oklch(93.89% .0025 345.21);--couleur-gris-fond:oklch(93.89% .0025 345.21/.8);--couleur-gris-fond-extra:oklch(93.89% .0025 345.21/.6);--couleur-gris-fonce:oklch(59.99% 0 0);--couleur-gris-fonce-fond:oklch(59.99% 0 0/.8);--couleur-noir:oklch(24.35% 0 0);--arriere-plan-points:repeating-conic-gradient(var(--couleur-noir) 0% 25%, transparent 0% 100%) 1px .5px/2px 2px;--police-lato:"Lato", sans-serif;--hauteur-ligne-classique:1.5;--hauteur-ligne-moitie:1.2;--hauteur-ligne-compacte:1.1;--hauteur-ligne-rapprochee:1;--espacement-inter-lettres-rapproche-m:-1px;--espacement-inter-lettres-rapproche-s:-.5px;--espacement-inter-lettres-etendu-s:.5px;--espacement-inter-lettres-etendu-m:1px;--espacement-inter-lettres-etendu-l:1.5px;--espacement-inter-lettres-etendu-xl:2px;--en-tete-hauteur:61px;--menu-categories-produits-hauteur:calc(var(--espace-m) * 2 + 1rlh);--pied-de-page-hauteur:calc(.8rem * 1.5 * 3 + var(--espace-s) * 2);--contenu-page-hauteur-minimale-sans-categories:calc(100svh - var(--en-tete-hauteur) - var(--pied-de-page-hauteur));--contenu-page-hauteur-minimale-avec-categories:calc(100svh - var(--en-tete-hauteur) - var(--pied-de-page-hauteur) - var(--menu-categories-produits-hauteur));--espace-2xs:.1rem;--espace-xs:.25rem;--espace-s:.5rem;--espace-m:1rem;--espace-l:1.25rem;--espace-xl:2rem}html{scrollbar-gutter:stable;box-sizing:border-box}*,:before,:after{box-sizing:inherit;font:inherit;color:inherit;outline-offset:-2px;outline:2px dashed #0000;margin:0;padding:0}@view-transition{navigation:auto}body{overscroll-behavior:none;accent-color:var(--couleur-gris-fonce);background:var(--couleur-gris)}button,input,select,textarea{font:inherit}::selection{background:var(--couleur-gris-fonce)}[hidden]{display:none!important}:focus-visible{outline-color:var(--couleur-noir);transition:outline-color .2s}.visuellement-cache:not(:focus,:active,:focus-within){white-space:nowrap;clip-path:inset(50%);width:1px;height:1px;position:absolute;overflow:hidden}[disabled]{cursor:not-allowed}html{font:1rem/var(--hauteur-ligne-classique) Lato;font-optical-sizing:auto;font-variant-ligatures:common-ligatures no-discretionary-ligatures no-historical-ligatures contextual;font-kerning:normal;color:var(--couleur-noir);text-decoration-skip-ink:auto;text-size-adjust:none;text-rendering:geometricprecision;letter-spacing:var(--espacement-inter-lettres-etendu-s);-webkit-font-smoothing:antialiased}strong{font-weight:600}em{font-style:italic}code{font-family:monospace;font-size:.9rem}button{all:initial;cursor:pointer;box-sizing:border-box;font:inherit;text-align:center;letter-spacing:inherit;outline-offset:-2px;outline:2px dashed #0000;transition:background .2s,font-weight .2s,color .2s,outline-color .2s}button:focus-visible{z-index:5;outline-color:var(--couleur-noir)}button:active{background:var(--arriere-plan-points)}button:disabled{color:inherit;background:var(--arriere-plan-points);outline-color:#0000}button.bouton-case-pleine{width:100%;height:100%}@media (hover:hover){button.bouton-case-pleine:hover{color:var(--couleur-noir);background:var(--arriere-plan-points)}}button.bouton-inverse{color:var(--couleur-blanc);background:var(--couleur-noir)}button.bouton-inverse:focus-visible{outline-color:var(--couleur-blanc)}button.bouton-inverse:active{color:var(--couleur-noir);background:var(--arriere-plan-points)}button.bouton-inverse:disabled{color:var(--couleur-blanc)}@media (hover:hover){button.bouton-inverse:hover{color:var(--couleur-noir);background:var(--arriere-plan-points)}}button.bouton-retour-haut{z-index:500;right:var(--espace-xl);bottom:calc(var(--espace-l) + var(--pied-de-page-hauteur));padding:var(--espace-m);border:1px solid var(--couleur-noir);visibility:hidden;opacity:0;background:var(--couleur-gris-fond);box-shadow:initial;border-radius:100%;transition:background .2s,opacity .2s,visibility .2s;position:fixed;transform:rotate(180deg)}button.bouton-retour-haut img{background:0 0;width:1rem;height:1rem}button.bouton-retour-haut[data-actif]{visibility:visible;opacity:.5}@media (hover:hover){button.bouton-retour-haut[data-actif]:hover{opacity:1;background:var(--couleur-gris-fond)}button:hover{color:var(--couleur-blanc);background:var(--couleur-gris-fonce)}}dialog{z-index:999;padding:var(--espace-l);opacity:0;background:var(--couleur-blanc);transition-behavior:allow-discrete;flex-flow:column;place-self:center;transition:display .3s,opacity .3s,overlay .3s}dialog::backdrop{transition-behavior:allow-discrete;background-color:#0000;transition:background-color .3s,display .3s,overlay .3s}dialog:open{opacity:1;display:flex}dialog:open::backdrop{background-color:var(--couleur-gris-fond)}dialog *+*{margin-block-start:var(--espace-m)}dialog p{max-inline-size:50ch}dialog button{inline-size:fit-content;padding:var(--espace-s);align-self:end}@starting-style{dialog:open{opacity:0}}@starting-style{dialog:open::backdrop{background-color:#0000}}fieldset{all:initial;margin-top:var(--espace-l);font:inherit;flex-flow:column;display:flex}input,select,textarea{padding:var(--espace-xs);border:1px solid var(--couleur-noir);accent-color:var(--couleur-gris-fonce);background:var(--couleur-gris);transition:background .2s}input:focus-visible,input:focus-within,select:focus-visible,select:focus-within,textarea:focus-visible,textarea:focus-within{z-index:10;outline:2px dashed var(--couleur-noir)}input:active,select:active,textarea:active{background:var(--arriere-plan-points)}input:disabled,select:disabled,textarea:disabled{background:var(--arriere-plan-points);outline-color:#0000}input:is([type=email],[type=text],[type=tel])::placeholder,textarea::placeholder{text-transform:lowercase;letter-spacing:var(--espacement-inter-lettres-etendu-s)}input:is([type=email],[type=text],[type=tel])::selection,textarea::selection{color:var(--couleur-blanc);background:var(--couleur-noir)}input:is([type=email],[type=text],[type=tel]):user-valid,textarea:user-valid{color:var(--couleur-noir);background:var(--arriere-plan-points);font-weight:500}input:is([type=email],[type=text],[type=tel]):user-invalid,textarea:user-invalid{background:var(--couleur-gris)}input,label,select,textarea{cursor:pointer}input[type=checkbox],input[type=radio]{width:var(--espace-l);height:var(--espace-l);padding:initial;border:1px solid var(--couleur-noir);appearance:none;transition:background .2s}input[type=checkbox]:checked,input[type=radio]:checked{color:var(--couleur-blanc);background:var(--couleur-gris-fonce)}input[type=checkbox]:checked:before,input[type=radio]:checked:before{content:"x";position:relative;bottom:.1rem;left:.35rem}@media (hover:hover){input[type=checkbox]:checked:hover,input[type=radio]:checked:hover{color:var(--couleur-noir)}}input[type=checkbox]:not(:checked):user-valid,input[type=radio]:not(:checked):user-valid{background:initial}label:has(~input[type=checkbox],~input[type=radio]),input[type=checkbox]+label,input[type=radio]+label{padding-top:1px;font-size:.9rem}@media (hover:hover){input[type=checkbox]:hover,input[type=radio]:hover{background:var(--couleur-gris-fonce)}}input[type=radio]{appearance:initial;border-radius:100%}input[type=radio]:checked{place-content:center;place-items:center;display:inline-flex}input[type=radio]:checked:before{content:" ";inset:initial;width:calc(var(--espace-l) / 2);height:calc(var(--espace-l) / 2);background:var(--couleur-noir);border-radius:100%;display:inline-block}@media (hover:hover){textarea:hover{color:var(--couleur-noir)}}img,picture{max-width:100%;display:block}img{object-fit:cover;background:var(--couleur-gris-fonce)}a{--lien-contour-couleur-focus:var(--couleur-noir);text-decoration-skip-ink:auto;text-decoration-skip:edges;text-decoration:underline #0000;transition:background .2s,border-color .2s,color .2s,font-weight .2s,outline-color .2s,letter-spacing .2s,text-decoration-color .2s}a:focus-visible{outline-color:var(--lien-contour-couleur-focus)}a.lien-bouton{--lien-bouton-marges-internes-bloc:var(--espace-xs);--lien-bouton-marges-internes-ligne:var(--espace-m);--lien-bouton-arriere-plan-couleur-survol:var(--couleur-gris-fonce);padding:var(--lien-bouton-marges-internes-bloc) var(--lien-bouton-marges-internes-ligne);border:1px solid var(--couleur-noir)}a.lien-bouton:focus-visible{background:var(--lien-bouton-arriere-plan-couleur-survol)}a.lien-bouton:active{border-color:var(--lien-bouton-arriere-plan-couleur-survol)}@media (hover:hover){a.lien-bouton:hover{background:var(--lien-bouton-arriere-plan-couleur-survol)}}a.lien-lien{text-decoration:underline}a.lien-lien:active{text-decoration-color:var(--couleur-gris-fonce);background:var(--couleur-gris-fonce)}@media (hover:hover){a.lien-lien:hover{text-decoration-color:var(--couleur-gris-fonce);background:var(--couleur-gris-fonce)}a:not([class]):hover{text-decoration-color:var(--couleur-noir)}}ul{list-style:none}ul.avec-puce-cercle{--liste-puce-cercle-lien-marges-internes-ligne-debut:2ch;--liste-puce-cercle-puce-position-horizontale:1ch;--liste-puce-cercle-puce-taille:1.25ex}ul.avec-puce-cercle a{padding-left:var(--liste-puce-cercle-lien-marges-internes-ligne-debut);background:no-repeat var(--liste-puce-cercle-puce-position-horizontale) center/var(--liste-puce-cercle-puce-taille) url(/app/themes/haiku-atelier-2024/assets/img/icons/dot.svg)}video{block-size:100%;inline-size:100%;min-inline-size:100%;min-block-size:inherit;object-fit:cover;display:block}.bandeau{column-gap:var(--espace-m);border-top:1px solid var(--couleur-noir);width:100%;color:var(--couleur-noir);text-transform:uppercase;white-space:nowrap;background:var(--couleur-gris-fonce);font-style:italic;display:flex;overflow:hidden}.bandeau__conteneur{column-gap:var(--espace-m);flex-flow:row;animation:15s linear infinite both marquee;display:flex}.bandeau__conteneur ::selection{color:var(--couleur-gris-fonce);background:var(--couleur-noir)}.bandeau__conteneur p{padding:var(--espace-s) 0;display:inline-block}.bandeau__conteneur p strong{font-weight:600}@media (hover:hover){.bandeau:hover .bandeau__conteneur{animation-play-state:paused}}@keyframes marquee{0%{transform:translate(0%)}to{transform:translate(-100%)}}body:has(#menu-mobile:not([aria-hidden=true])){touch-action:none;overflow:hidden}#menu-mobile{--menu-mobile-hauteur:calc(100svh - var(--en-tete-hauteur));z-index:997;inset:var(--en-tete-hauteur) 0 0 0;overscroll-behavior:contain;width:100vw;height:var(--menu-mobile-hauteur);transition:display .4s;transition:display .4s allow-discrete;-webkit-overflow-scrolling:none;display:flex;position:fixed;overflow:hidden}#menu-mobile[aria-hidden=true]{animation:.4s both fade-out;display:none}#menu-mobile[aria-hidden=true] .menu-modale__fond{animation:.4s both fade-out}#menu-mobile .menu-modale__fond{z-index:998;inset:var(--en-tete-hauteur) 0 0 0;height:var(--menu-mobile-hauteur);opacity:0;background-color:var(--couleur-gris-fond);animation:.4s both fade-in;position:fixed}#menu-mobile .menu-modale__conteneur{z-index:999;width:100%;height:fit-content;padding:var(--espace-xl);border-bottom:1px solid var(--couleur-noir);opacity:0;background-color:var(--couleur-gris);flex-flow:column;animation:.4s .2s both fade-in;display:flex;position:relative}#menu-mobile .menu-modale__conteneur .menu-navigation{grid-template-columns:1fr}#menu-mobile .menu-modale__conteneur .menu-navigation ul{grid-column:initial;flex-flow:column;place-items:center}#menu-mobile .menu-modale__conteneur .menu-navigation ul>span{width:fit-content}#menu-mobile .menu-modale__conteneur .menu-navigation ul>span li a{padding-top:var(--espace-m);padding-bottom:var(--espace-m)}@media (width>1000px){#menu-mobile{display:none}}@keyframes fade-in{to{opacity:1}}@keyframes fade-out{to{opacity:0}}@keyframes slide-in{to{transform:translateY(0)}}#en-tete{--en-tete-marges-internes-ligne:var(--espace-xl);--en-tete-marges-internes-bloc:var(--espace-m);--en-tete-section-hauteur:var(--en-tete-hauteur);--en-tete-logo-longueur:160px;z-index:60;min-width:100vw;max-width:100vw;height:var(--en-tete-hauteur);padding:var(--en-tete-marges-internes-bloc) var(--en-tete-marges-internes-ligne);border-bottom:1px solid var(--couleur-noir);background:var(--couleur-gris-fond-extra);backdrop-filter:brightness(125%)blur(6px);flex-flow:row;justify-content:space-between;place-items:center;display:flex;position:fixed;top:0}#en-tete picture,#en-tete img{background:0 0}#en-tete .logo{width:var(--en-tete-logo-longueur)}#en-tete .logo img{object-fit:contain;width:100%;height:40px;image-rendering:crisp-edges;shape-rendering:geometricprecision;margin-left:-6px}#en-tete .menu-navigation{text-align:center;text-transform:lowercase;flex:1;grid-template-columns:1fr auto 1fr;font-size:1.1rem;display:grid}#en-tete .menu-navigation ul{gap:var(--espace-m);flex-flow:row;grid-column:2;justify-content:space-between;display:flex}#en-tete .menu-navigation__entree{--nav-entree-marges-internes-bloc:var(--espace-xs);--nav-entree-marges-internes-ligne:3rem;--liste-puce-cercle-lien-marges-internes-ligne-debut:calc(var(--espace-m) + 1.5ch);--liste-puce-cercle-puce-position-horizontale:3.5ch}#en-tete .menu-navigation__entree:has(a[aria-current=page]),#en-tete .menu-navigation__entree--courante{background:url(/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche-gris.svg) bottom/auto 90% no-repeat}#en-tete .menu-navigation__entree a{padding:var(--nav-entree-marges-internes-bloc) var(--nav-entree-marges-internes-ligne);text-align:center;display:inline-block}@media (hover:hover){#en-tete .menu-navigation__entree:hover{background:url(/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche-gris.svg) bottom/auto 90% no-repeat}}@media (width<=1000px){#en-tete .menu-navigation#menu-navigation-en-tete{display:none}}#en-tete .compte-panier{text-align:center;flex-flow:row;place-items:center;gap:1rem;display:flex}#en-tete .compte-panier[disabled]{background:var(--arriere-plan-points)}#en-tete .compte-panier[disabled] a:hover,#en-tete .compte-panier[disabled] a:active,#en-tete .compte-panier[disabled] a:focus-within{border:1px solid var(--couleur-noir)}#en-tete .compte-panier a{padding-block:var(--espace-2xs);padding-inline:var(--espace-s);text-transform:lowercase;background:0 0}#en-tete .compte-panier a[data-contient-articles=true]{background:var(--couleur-gris-fond)}#en-tete .compte-panier a:hover,#en-tete .compte-panier a:focus-within{color:var(--couleur-blanc);background:var(--couleur-gris-fonce-fond)}#en-tete .compte-panier a:active{color:var(--couleur-noir);background:var(--arriere-plan-points)}#en-tete .conteneur{column-gap:var(--espace-m);display:flex}#en-tete .bouton-menu-mobile{--hauteur-bouton-menu:22px;align-content:center;display:none}#en-tete .bouton-menu-mobile img{height:var(--hauteur-bouton-menu);object-fit:contain;image-rendering:crisp-edges;shape-rendering:geometricprecision}@media (hover:hover){#en-tete .bouton-menu-mobile:hover{background:initial!important}}@media (width<=1000px){#en-tete .bouton-menu-mobile{display:block}}@media (width<=600px){#en-tete{--en-tete-marges-internes-ligne:var(--espace-l)}}#menu-categories-produits{--menu-entree-longueur-minimale:13ch;--menu-section-marges-bloc-debut:var(--en-tete-hauteur);--menu-entree-marges-internes-ligne:var(--espace-m);margin-top:var(--menu-section-marges-bloc-debut);position:relative}#menu-categories-produits[data-entrees-presentes-debut] svg:first-of-type,#menu-categories-produits[data-entrees-presentes-fin] svg:last-of-type{opacity:1}#menu-categories-produits svg{pointer-events:none;opacity:0;mix-blend-mode:exclusion;shape-rendering:geometricprecision;block-size:.8rem;inline-size:.8rem;transition:opacity .2s;position:absolute;bottom:calc(17.59px - .35rem)}#menu-categories-produits svg:first-of-type{left:var(--espace-xs)}#menu-categories-produits svg:last-of-type{right:var(--espace-xs)}@media (width>600px){#menu-categories-produits svg{visibility:hidden}}#menu-categories-produits ul{grid-template-columns:repeat(auto-fit, minmax(var(--menu-entree-longueur-minimale), 1fr));place-items:center;gap:1px;display:grid}#menu-categories-produits ul li{inline-size:100%;color:var(--couleur-gris);text-align:center;text-transform:uppercase;letter-spacing:var(--espacement-inter-lettres-etendu-m);background:var(--couleur-noir);font-style:italic;font-weight:500}#menu-categories-produits ul li:hover{background:var(--couleur-gris)}#menu-categories-produits ul li a{inline-size:inherit;padding:var(--menu-entree-marges-internes-ligne) 0;text-decoration:none;display:inline-block}#menu-categories-produits ul li a:focus-visible{outline-color:var(--couleur-blanc)}@media (hover:hover){#menu-categories-produits ul li a:hover{color:var(--couleur-noir);background:var(--arriere-plan-points)}}#menu-categories-produits ul li.categorie-courante{background:var(--couleur-gris)}#menu-categories-produits ul li.categorie-courante a{color:var(--couleur-noir);background:var(--arriere-plan-points);font-weight:600}#menu-categories-produits ul li.categorie-courante a:focus-visible{outline-color:var(--couleur-noir)}@media (hover:hover){#menu-categories-produits ul li.categorie-courante a:hover{background:var(--arriere-plan-points)}}@media (width<=1000px){#menu-categories-produits ul{--menu-entree-marges-internes-ligne:var(--espace-s);flex-flow:wrap;font-size:.8rem;display:flex}#menu-categories-produits ul li{flex-grow:1;inline-size:min(140px,100%)}#menu-categories-produits ul li a{border:initial;inline-size:100%}}@media (width<=600px){#menu-categories-produits ul{scrollbar-width:none;flex-flow:row;overflow-x:scroll}#menu-categories-produits ul li{inline-size:initial;min-inline-size:140px}}.photos-produit{--colonne-gauche-position-haut:var(--menu-categories-produits-hauteur);--colonne-gauche-photo-hauteur:calc(100svh - var(--menu-categories-produits-hauteur));--colonne-droite-photo-hauteur-minimale:calc(100svh + var(--en-tete-hauteur) + var(--menu-categories-produits-hauteur));--colonne-photo-longueur-minimale:30rem;--section-marges-externes-bloc-fin:1rem;flex-flow:row;max-width:100%;display:flex;position:relative}.photos-produit .colonne{width:min(var(--colonne-photo-longueur-minimale), 100%);flex-flow:column;flex-grow:1;display:flex;position:relative}.photos-produit .colonne.colonne-gauche{top:var(--colonne-gauche-position-haut);height:var(--colonne-gauche-photo-hauteur);position:sticky}.photos-produit .colonne.colonne-gauche figure,.photos-produit .colonne.colonne-gauche picture,.photos-produit .colonne.colonne-gauche img{height:100%}.photos-produit .colonne.colonne-droite img{width:100%;max-height:var(--colonne-droite-photo-hauteur-minimale)}.photos-produit .colonne.colonne-droite figure picture img:only-child{min-height:var(--colonne-droite-photo-hauteur-minimale);max-height:var(--colonne-droite-photo-hauteur-minimale)}@media (width<=60rem){.photos-produit{--colonne-droite-photo-hauteur-minimale:var(--photo-hauteur-maximum);--photo-longueur-maximum:calc(100% - var(--espace-xl));--photo-hauteur-maximum:calc(100svh - var(--en-tete-hauteur) - 87px);scroll-behavior:smooth;scrollbar-width:none;scroll-snap-type:x mandatory;width:fit-content;max-width:initial;flex-flow:row;overflow-x:scroll}.photos-produit::-webkit-scrollbar{display:none}.photos-produit .colonne{scroll-snap-type:x mandatory;width:100%;min-width:100%}.photos-produit .colonne figure{scroll-snap-align:none center}.photos-produit .colonne img{max-height:var(--photo-hauteur-maximum)}.photos-produit .colonne.colonne-gauche{position:initial;min-width:var(--photo-longueur-maximum);height:initial}.photos-produit .colonne.colonne-droite{flex-flow:row}.photos-produit .colonne.colonne-droite figure{min-width:var(--photo-longueur-maximum);flex-grow:1}.photos-produit .colonne.colonne-droite:has(figure:only-child){min-width:var(--photo-longueur-maximum)}}.grille-produits{--grille-produits-hauteur-minimale:var(--contenu-page-hauteur-minimale-avec-categories);--aucun-produit-hauteur:var(--contenu-page-hauteur-minimale-avec-categories);--carte-produit-longueur-minimale:448px;--carte-produit-longueur-maximale:1000px;grid-auto-rows:1fr;grid-template-columns:repeat(auto-fit, minmax(var(--carte-produit-longueur-minimale), 1fr));min-height:var(--grille-produits-hauteur-minimale);gap:1px;display:grid}.grille-produits article{max-width:var(--carte-produit-longueur-maximale);box-shadow:0 0 0 1px var(--couleur-noir)}.grille-produits article figure{row-gap:var(--espace-xl);flex-flow:column;display:flex}.grille-produits article figure a{position:relative}@media (hover:hover){.grille-produits article figure a:hover .produit__illustration__survol{visibility:visible;opacity:1;transition:opacity .3s,visibility .3s}}.grille-produits article figure img{position:inherit;aspect-ratio:9/16;object-fit:cover;background:0 0;width:100%;max-height:70vh}.grille-produits article figure .produit__illustration__principale{display:block}.grille-produits article figure .produit__illustration__principale:before{content:"";z-index:-1;opacity:0;filter:opacity(20%);background-image:url(/app/themes/haiku-atelier-2024/assets/img/icons/cloud-gris.svg);background-position:50%;background-repeat:no-repeat;background-size:50%;width:100%;height:100%;animation:1.5s linear .5s infinite alternate both test;position:absolute;top:0;left:0}.grille-produits article figure .produit__illustration__principale img{opacity:0;transition:opacity 1s}.grille-produits article figure .produit__illustration__survol{visibility:hidden;opacity:0;width:100%;height:100%;transition:opacity .15s,visibility .15s;display:block;position:absolute;top:0;left:0}.grille-produits article figure .produit__illustration__survol img{background:var(--couleur-gris-fond)}.grille-produits article figure figcaption{margin-bottom:var(--espace-xl);padding:var(--espace-m);flex-flow:row;justify-content:space-between;display:flex}.grille-produits article figure figcaption h3{letter-spacing:var(--espacement-inter-lettres-etendu-m);font-style:italic}.grille-produits article figure figcaption p{letter-spacing:var(--espacement-inter-lettres-rapproche-s);font-weight:500}.grille-produits__aucun-produit{min-height:var(--aucun-produit-hauteur);text-align:center;grid-column:span 3;align-content:center}.grille-produits__aucun-produit p+p{margin-top:var(--espace-l);font-size:1.25rem}@media (width<=700px){.grille-produits{grid-template-columns:100%}.grille-produits article figure img{max-height:50svh}}@keyframes test{to{opacity:1}}.resume-produit{--resume-position-basse:0%;--section-marges-internes:var(--espace-l);--espace-inter-colonne:var(--espace-xl);--resume-police-graisse:500;--resume-police-style:italic;--resume-police-taille:var(--espace-l);--resume-police-nom-taille:1.33rem;--resume-police-selecteur-graisse:400;--resume-police-selecteur-taille:var(--espace-m);bottom:var(--resume-position-basse);position:sticky}.resume-produit .selecteur-produit{column-gap:var(--espace-inter-colonne);border-block:1px solid var(--couleur-noir);font-size:var(--resume-police-taille);font-weight:var(--resume-police-graisse);font-style:var(--resume-police-style);line-height:var(--hauteur-ligne-compacte);background:var(--couleur-blanc-fond);grid-template-columns:repeat(3,1fr);grid-auto-flow:column;place-items:center;display:grid;position:relative}.resume-produit .selecteur-produit>*{width:100%;height:100%;padding:var(--section-marges-internes);flex-flow:row;place-content:center;place-items:center;display:flex}.resume-produit .selecteur-produit>:nth-child(2){border-inline-start:1px solid var(--couleur-noir);border-inline-end:1px solid var(--couleur-noir)}.resume-produit .selecteur-produit__nom{font-size:var(--resume-police-nom-taille)}.resume-produit .selecteur-produit__attribut-variation{gap:var(--espace-m) var(--espace-l);font-size:var(--resume-police-selecteur-taille);font-weight:var(--resume-police-selecteur-graisse);text-transform:lowercase;flex-flow:wrap;display:flex}.resume-produit .selecteur-produit__attribut-variation label{margin-right:var(--espace-s)}.resume-produit .selecteur-produit__attribut-variation select{padding:var(--espace-xs) var(--espace-l);border:1px solid var(--couleur-noir);text-align:center;letter-spacing:initial;appearance:none;background:var(--couleur-gris-fond);position:relative}@supports selector(:user-valid){.resume-produit .selecteur-produit__attribut-variation select:user-valid{background:var(--couleur-gris-fond)}}.resume-produit .selecteur-produit__attribut-variation option{background:var(--couleur-gris-fond)}.resume-produit .selecteur-produit__attribut-variation__selecteurs{gap:var(--espace-m);flex-flow:wrap;place-content:center;place-items:center;display:flex;position:relative}.resume-produit .selecteur-produit__prix{font-style:initial}@media (width<=800px){.resume-produit{--section-marges-internes:var(--espace-m);--espace-inter-colonne:var(--espace-m)}}@media (width<=700px){.resume-produit{--resume-police-taille:var(--espace-m);--resume-police-nom-taille:var(--espace-m);--section-marges-internes:var(--espace-m);--espace-inter-colonne:var(--espace-s)}}@media (width<=500px){.resume-produit .selecteur-produit__selection-variation-attribut{row-gap:var(--espace-inter-colonne);flex-flow:column}.resume-produit .selecteur-produit__selection-variation-attribut h3{flex-basis:100%}}.details-produit{--bouton-marges-internes-bloc:var(--espace-l);--espace-inter-lignes:var(--espace-l);--espace-inter-texte:var(--espace-m);--section-marges-internes:var(--espace-l);--textuel-marges-internes-ligne:calc(var(--espace-l) * 2);background-color:var(--couleur-blanc)}.details-produit__textes{grid-template-columns:1fr;grid-auto-flow:row;display:grid}.details-produit__textes .section-textuelle:not(:last-of-type){border-block-end:1px solid var(--couleur-noir)}.details-produit__textes .section-textuelle:has(button[aria-expanded=false]) .section-textuelle__contenu{display:none}.details-produit__textes .section-textuelle h3{line-height:var(--hauteur-ligne-rapprochee)}.details-produit__textes .section-textuelle h3 button{width:100%;min-block-size:1lh;padding:var(--section-marges-internes);text-align:start;display:inline-block}.details-produit__textes .section-textuelle h3 button:active{background:var(--arriere-plan-points)}@media (hover:hover){.details-produit__textes .section-textuelle h3 button:hover{color:inherit;background:inherit}}.details-produit__textes .section-textuelle .section-textuelle__contenu{padding-block-end:var(--section-marges-internes);padding-inline:var(--textuel-marges-internes-ligne)}.details-produit__textes .section-textuelle .section-textuelle__contenu ul{list-style:inside}.details-produit__textes .section-textuelle .section-textuelle__contenu a{text-decoration-color:var(--couleur-noir)}.details-produit__textes .section-textuelle .section-textuelle__contenu>*+*{margin-top:var(--espace-inter-texte)}.details-produit__actions{--section-marges-internes:var(--espace-l);border-block:1px solid var(--couleur-noir);background:var(--arriere-plan-points);transition:background .2s;overflow:hidden}.details-produit__actions:has(button[disabled]){background:var(--couleur-gris-fond)}.details-produit__actions button{padding:var(--section-marges-internes);text-transform:uppercase;font-style:italic}@media (hover:hover){.details-produit__actions button:not([disabled]):hover{color:var(--couleur-blanc);background:var(--couleur-gris-fonce-fond);font-weight:600}}.produits-similaires{--carte-produit-longueur-minimale:448px;--carte-produit-longueur-maximale:1000px;--en-tete-flottante-hauteur:calc(1rem + var(--espace-l) * 2 + 1px);grid-template-rows:1fr auto;grid-template-columns:repeat(3,1fr);grid-template-areas:"en-tete en-tete en-tete""produits produits produits";place-items:center;display:grid;position:relative}.produits-similaires header{z-index:10;top:var(--en-tete-flottante-hauteur);width:100%;padding:var(--espace-l) 0;color:var(--couleur-blanc);text-align:center;background:var(--couleur-noir);grid-area:en-tete;position:sticky}.produits-similaires header h2{font-style:italic;line-height:var(--hauteur-ligne-rapprochee);text-transform:uppercase;letter-spacing:var(--espacement-inter-lettres-etendu-m)}.produits-similaires .grille-produits-similaires{grid-area:produits;grid-auto-rows:1fr;grid-template-columns:repeat(auto-fit, minmax(var(--carte-produit-longueur-minimale), 1fr));gap:1px;width:100%;display:grid}.produits-similaires .grille-produits-similaires article{max-width:var(--carte-produit-longueur-maximale);box-shadow:0 0 0 1px var(--couleur-noir)}.produits-similaires .grille-produits-similaires article figure{row-gap:var(--espace-xl);flex-flow:column;display:flex}.produits-similaires .grille-produits-similaires article figure a{position:relative}@media (hover:hover){.produits-similaires .grille-produits-similaires article figure a:hover .produit__illustration__survol{visibility:visible;opacity:1;transition:opacity .3s,visibility .3s}}.produits-similaires .grille-produits-similaires article figure .produit__illustration__principale{display:block}.produits-similaires .grille-produits-similaires article figure .produit__illustration__survol{visibility:hidden;opacity:0;width:100%;height:100%;transition:opacity .15s,visibility .15s;display:block;position:absolute;top:0;left:0}.produits-similaires .grille-produits-similaires article figure img{aspect-ratio:9/16;object-fit:cover;width:100%;max-height:70svh}.produits-similaires .grille-produits-similaires article figure figcaption{margin-bottom:var(--espace-xl);padding:0 var(--espace-m);flex-flow:row;justify-content:space-between;display:flex}.produits-similaires .grille-produits-similaires article figure figcaption h3{letter-spacing:var(--espacement-inter-lettres-etendu-m);font-style:italic}.produits-similaires .grille-produits-similaires article figure figcaption p{letter-spacing:var(--espacement-inter-lettres-rapproche-s);font-weight:500}@media (width<=700px){.produits-similaires .grille-produits-similaires{grid-template-columns:100%}.produits-similaires .grille-produits-similaires article figure img{max-height:50svh}}#pied-de-page{max-width:100vw;height:var(--pied-de-page-hauteur);padding:var(--espace-s) var(--espace-m);border-top:1px solid var(--couleur-noir);grid-template-columns:1fr 1fr;place-items:center;font-size:.8rem;display:grid}#pied-de-page .zone-menu-navigation-secondaire{text-transform:lowercase;justify-self:start;width:100%;height:100%}#pied-de-page .zone-liens-reseaux-sociaux{text-align:right;justify-items:end;width:100%;height:100%} \ No newline at end of file +@font-face{font-family:Lato;font-weight:100 900;font-style:normal;font-display:swap;src:url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2)format("woff2")tech(variations),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2)format("woff2-variations"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.ttf)format("truetype");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Lato;font-weight:100 900;font-style:italic;font-display:swap;src:url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2)format("woff2")tech(variations),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2)format("woff2-variations"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.ttf)format("truetype");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Myriad;font-weight:300 900;font-style:normal;font-display:swap;font-stretch:70% 110%;src:url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable.ttf)format("truetype")}@font-face{font-family:Myriad;font-weight:300 900;font-style:italic;font-display:swap;font-stretch:70% 110%;src:url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable-italic.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable-italic.ttf)format("truetype")}:root{--couleur-blanc:oklch(100% 0 0);--couleur-blanc-fond:oklch(100% 0 0/.8);--couleur-gris:oklch(93.89% .0025 345.21);--couleur-gris-fond:oklch(93.89% .0025 345.21/.8);--couleur-gris-fond-extra:oklch(93.89% .0025 345.21/.6);--couleur-gris-fonce:oklch(59.99% 0 0);--couleur-gris-fonce-fond:oklch(59.99% 0 0/.8);--couleur-noir:oklch(24.35% 0 0);--arriere-plan-points:repeating-conic-gradient(var(--couleur-noir) 0% 25%, transparent 0% 100%) 1px .5px/2px 2px;--police-lato:"Lato", sans-serif;--hauteur-ligne-classique:1.5;--hauteur-ligne-moitie:1.2;--hauteur-ligne-compacte:1.1;--hauteur-ligne-rapprochee:1;--espacement-inter-lettres-rapproche-m:-1px;--espacement-inter-lettres-rapproche-s:-.5px;--espacement-inter-lettres-etendu-s:.5px;--espacement-inter-lettres-etendu-m:1px;--espacement-inter-lettres-etendu-l:1.5px;--espacement-inter-lettres-etendu-xl:2px;--en-tete-hauteur:61px;--menu-categories-produits-hauteur:calc(var(--espace-m) * 2 + 1rlh);--pied-de-page-hauteur:calc(.8rem * 1.5 * 3 + var(--espace-s) * 2);--contenu-page-hauteur-minimale-sans-categories:calc(100svh - var(--en-tete-hauteur) - var(--pied-de-page-hauteur));--contenu-page-hauteur-minimale-avec-categories:calc(100svh - var(--en-tete-hauteur) - var(--pied-de-page-hauteur) - var(--menu-categories-produits-hauteur));--espace-2xs:.1rem;--espace-xs:.25rem;--espace-s:.5rem;--espace-m:1rem;--espace-l:1.25rem;--espace-xl:2rem}html{scrollbar-gutter:stable;box-sizing:border-box}*,:before,:after{box-sizing:inherit;font:inherit;color:inherit;outline-offset:-2px;outline:2px dashed #0000;margin:0;padding:0}@view-transition{navigation:auto}body{overscroll-behavior:none;accent-color:var(--couleur-gris-fonce);background:var(--couleur-gris)}button,input,select,textarea{font:inherit}::selection{background:var(--couleur-gris-fonce)}[hidden]{display:none!important}:focus-visible{outline-color:var(--couleur-noir);transition:outline-color .2s}.visuellement-cache:not(:focus,:active,:focus-within){white-space:nowrap;clip-path:inset(50%);width:1px;height:1px;position:absolute;overflow:hidden}[disabled]{cursor:not-allowed}html{font:1rem/var(--hauteur-ligne-classique) Lato;font-optical-sizing:auto;font-variant-ligatures:common-ligatures no-discretionary-ligatures no-historical-ligatures contextual;font-kerning:normal;color:var(--couleur-noir);text-decoration-skip-ink:auto;text-size-adjust:none;text-rendering:geometricprecision;letter-spacing:var(--espacement-inter-lettres-etendu-s);-webkit-font-smoothing:antialiased}strong{font-weight:600}em{font-style:italic}code{font-family:monospace;font-size:.9rem}button{all:initial;cursor:pointer;box-sizing:border-box;font:inherit;text-align:center;letter-spacing:inherit;outline-offset:-2px;outline:2px dashed #0000;transition:background .2s,font-weight .2s,color .2s,outline-color .2s}button:focus-visible{z-index:5;outline-color:var(--couleur-noir)}button:active{background:var(--arriere-plan-points)}button:disabled{color:inherit;background:var(--arriere-plan-points);outline-color:#0000}button.bouton-case-pleine{width:100%;height:100%}@media (hover:hover){button.bouton-case-pleine:hover{color:var(--couleur-noir);background:var(--arriere-plan-points)}}button.bouton-inverse{color:var(--couleur-blanc);background:var(--couleur-noir)}button.bouton-inverse:focus-visible{outline-color:var(--couleur-blanc)}button.bouton-inverse:active{color:var(--couleur-noir);background:var(--arriere-plan-points)}button.bouton-inverse:disabled{color:var(--couleur-blanc)}@media (hover:hover){button.bouton-inverse:hover{color:var(--couleur-noir);background:var(--arriere-plan-points)}}button.bouton-retour-haut{z-index:500;right:var(--espace-xl);bottom:calc(var(--espace-l) + var(--pied-de-page-hauteur));padding:var(--espace-m);border:1px solid var(--couleur-noir);visibility:hidden;opacity:0;background:var(--couleur-gris-fond);box-shadow:initial;border-radius:100%;transition:background .2s,opacity .2s,visibility .2s;position:fixed;transform:rotate(180deg)}button.bouton-retour-haut img{background:0 0;width:1rem;height:1rem}button.bouton-retour-haut[data-actif]{visibility:visible;opacity:.5}@media (hover:hover){button.bouton-retour-haut[data-actif]:hover{opacity:1;background:var(--couleur-gris-fond)}button:hover{color:var(--couleur-blanc);background:var(--couleur-gris-fonce)}}dialog{z-index:999;padding:var(--espace-l);opacity:0;background:var(--couleur-blanc);transition-behavior:allow-discrete;flex-flow:column;place-self:center;transition:display .3s,opacity .3s,overlay .3s}dialog::backdrop{transition-behavior:allow-discrete;background-color:#0000;transition:background-color .3s,display .3s,overlay .3s}dialog:open{opacity:1;display:flex}dialog:open::backdrop{background-color:var(--couleur-gris-fond)}dialog *+*{margin-block-start:var(--espace-m)}dialog p{max-inline-size:50ch}dialog button{inline-size:fit-content;padding:var(--espace-s);align-self:end}@starting-style{dialog:open{opacity:0}}@starting-style{dialog:open::backdrop{background-color:#0000}}fieldset{all:initial;margin-top:var(--espace-l);font:inherit;flex-flow:column;display:flex}input,select,textarea{padding:var(--espace-xs);border:1px solid var(--couleur-noir);accent-color:var(--couleur-gris-fonce);background:var(--couleur-gris);transition:background .2s}input:focus-visible,input:focus-within,select:focus-visible,select:focus-within,textarea:focus-visible,textarea:focus-within{z-index:10;outline:2px dashed var(--couleur-noir)}input:active,select:active,textarea:active{background:var(--arriere-plan-points)}input:disabled,select:disabled,textarea:disabled{background:var(--arriere-plan-points);outline-color:#0000}input:is([type=email],[type=text],[type=tel])::placeholder,textarea::placeholder{text-transform:lowercase;letter-spacing:var(--espacement-inter-lettres-etendu-s)}input:is([type=email],[type=text],[type=tel])::selection,textarea::selection{color:var(--couleur-blanc);background:var(--couleur-noir)}input:is([type=email],[type=text],[type=tel]):user-valid,textarea:user-valid{color:var(--couleur-noir);background:var(--arriere-plan-points);font-weight:500}input:is([type=email],[type=text],[type=tel]):user-invalid,textarea:user-invalid{background:var(--couleur-gris)}input,label,select,textarea{cursor:pointer}input[type=checkbox],input[type=radio]{width:var(--espace-l);height:var(--espace-l);padding:initial;border:1px solid var(--couleur-noir);appearance:none;transition:background .2s}input[type=checkbox]:checked,input[type=radio]:checked{color:var(--couleur-noir);background:var(--arriere-plan-points)}input[type=checkbox]:checked:before,input[type=radio]:checked:before{content:"x";position:relative;bottom:.1rem;left:.35rem}@media (hover:hover){input[type=checkbox]:checked:hover,input[type=radio]:checked:hover{color:var(--couleur-noir)}}input[type=checkbox]:not(:checked):user-valid,input[type=radio]:not(:checked):user-valid{background:initial}label:has(~input[type=checkbox],~input[type=radio]),input[type=checkbox]+label,input[type=radio]+label{padding-top:1px;font-size:.9rem}@media (hover:hover){input[type=checkbox]:hover,input[type=radio]:hover{background:var(--arriere-plan-points)}}input[type=radio]{appearance:initial;border-radius:100%}input[type=radio]:checked{place-content:center;place-items:center;display:inline-flex}input[type=radio]:checked:before{content:" ";inset:initial;width:calc(var(--espace-l) / 2);height:calc(var(--espace-l) / 2);background:var(--couleur-noir);border-radius:100%;display:inline-block}@media (hover:hover){textarea:hover{color:var(--couleur-noir)}}img,picture{max-width:100%;display:block}img{object-fit:cover;background:var(--couleur-gris-fonce)}a{--lien-contour-couleur-focus:var(--couleur-noir);text-decoration-skip-ink:auto;text-decoration-skip:edges;text-decoration:underline #0000;transition:background .2s,border-color .2s,color .2s,font-weight .2s,outline-color .2s,letter-spacing .2s,text-decoration-color .2s}a:focus-visible{outline-color:var(--lien-contour-couleur-focus)}a.lien-bouton{--lien-bouton-marges-internes-bloc:var(--espace-xs);--lien-bouton-marges-internes-ligne:var(--espace-m);--lien-bouton-arriere-plan-couleur-survol:var(--couleur-gris-fonce);padding:var(--lien-bouton-marges-internes-bloc) var(--lien-bouton-marges-internes-ligne);border:1px solid var(--couleur-noir)}a.lien-bouton:focus-visible{background:var(--lien-bouton-arriere-plan-couleur-survol)}a.lien-bouton:active{border-color:var(--lien-bouton-arriere-plan-couleur-survol)}@media (hover:hover){a.lien-bouton:hover{background:var(--lien-bouton-arriere-plan-couleur-survol)}}a.lien-lien{text-decoration:underline}a.lien-lien:active{text-decoration-color:var(--couleur-gris-fonce);background:var(--couleur-gris-fonce)}@media (hover:hover){a.lien-lien:hover{text-decoration-color:var(--couleur-gris-fonce);background:var(--couleur-gris-fonce)}a:not([class]):hover{text-decoration-color:var(--couleur-noir)}}ul{list-style:none}ul.avec-puce-cercle{--liste-puce-cercle-lien-marges-internes-ligne-debut:2ch;--liste-puce-cercle-puce-position-horizontale:1ch;--liste-puce-cercle-puce-taille:1.25ex}ul.avec-puce-cercle a{padding-left:var(--liste-puce-cercle-lien-marges-internes-ligne-debut);background:no-repeat var(--liste-puce-cercle-puce-position-horizontale) center/var(--liste-puce-cercle-puce-taille) url(/app/themes/haiku-atelier-2024/assets/img/icons/dot.svg)}video{block-size:100%;inline-size:100%;min-inline-size:100%;min-block-size:inherit;object-fit:cover;display:block}.bandeau{column-gap:var(--espace-m);border-top:1px solid var(--couleur-noir);width:100%;color:var(--couleur-noir);text-transform:uppercase;white-space:nowrap;background:var(--couleur-gris-fonce);font-style:italic;display:flex;overflow:hidden}.bandeau__conteneur{column-gap:var(--espace-m);flex-flow:row;animation:15s linear infinite both marquee;display:flex}.bandeau__conteneur ::selection{color:var(--couleur-gris-fonce);background:var(--couleur-noir)}.bandeau__conteneur p{padding:var(--espace-s) 0;display:inline-block}.bandeau__conteneur p strong{font-weight:600}@media (hover:hover){.bandeau:hover .bandeau__conteneur{animation-play-state:paused}}@keyframes marquee{0%{transform:translate(0%)}to{transform:translate(-100%)}}body:has(#menu-mobile:not([aria-hidden=true])){touch-action:none;overflow:hidden}#menu-mobile{--menu-mobile-hauteur:calc(100svh - var(--en-tete-hauteur));z-index:997;inset:var(--en-tete-hauteur) 0 0 0;overscroll-behavior:contain;width:100vw;height:var(--menu-mobile-hauteur);transition:display .4s;transition:display .4s allow-discrete;-webkit-overflow-scrolling:none;display:flex;position:fixed;overflow:hidden}#menu-mobile[aria-hidden=true]{animation:.4s both fade-out;display:none}#menu-mobile[aria-hidden=true] .menu-modale__fond{animation:.4s both fade-out}#menu-mobile .menu-modale__fond{z-index:998;inset:var(--en-tete-hauteur) 0 0 0;height:var(--menu-mobile-hauteur);opacity:0;background-color:var(--couleur-gris-fond);animation:.4s both fade-in;position:fixed}#menu-mobile .menu-modale__conteneur{z-index:999;width:100%;height:fit-content;padding:var(--espace-xl);border-bottom:1px solid var(--couleur-noir);opacity:0;background-color:var(--couleur-gris);flex-flow:column;animation:.4s .2s both fade-in;display:flex;position:relative}#menu-mobile .menu-modale__conteneur .menu-navigation{grid-template-columns:1fr}#menu-mobile .menu-modale__conteneur .menu-navigation ul{grid-column:initial;flex-flow:column;place-items:center}#menu-mobile .menu-modale__conteneur .menu-navigation ul>span{width:fit-content}#menu-mobile .menu-modale__conteneur .menu-navigation ul>span li a{padding-top:var(--espace-m);padding-bottom:var(--espace-m)}@media (width>1000px){#menu-mobile{display:none}}@keyframes fade-in{to{opacity:1}}@keyframes fade-out{to{opacity:0}}@keyframes slide-in{to{transform:translateY(0)}}#en-tete{--en-tete-marges-internes-ligne:var(--espace-xl);--en-tete-marges-internes-bloc:var(--espace-m);--en-tete-section-hauteur:var(--en-tete-hauteur);--en-tete-logo-longueur:160px;z-index:60;min-width:100vw;max-width:100vw;height:var(--en-tete-hauteur);padding:var(--en-tete-marges-internes-bloc) var(--en-tete-marges-internes-ligne);border-bottom:1px solid var(--couleur-noir);background:var(--couleur-gris-fond-extra);backdrop-filter:brightness(125%)blur(6px);flex-flow:row;justify-content:space-between;place-items:center;display:flex;position:fixed;top:0}#en-tete picture,#en-tete img{background:0 0}#en-tete .logo{width:var(--en-tete-logo-longueur)}#en-tete .logo img{object-fit:contain;width:100%;height:40px;image-rendering:crisp-edges;shape-rendering:geometricprecision;margin-left:-6px}#en-tete .menu-navigation{text-align:center;text-transform:lowercase;flex:1;grid-template-columns:1fr auto 1fr;font-size:1.1rem;display:grid}#en-tete .menu-navigation ul{gap:var(--espace-m);flex-flow:row;grid-column:2;justify-content:space-between;display:flex}#en-tete .menu-navigation__entree{--nav-entree-marges-internes-bloc:var(--espace-xs);--nav-entree-marges-internes-ligne:3rem;--liste-puce-cercle-lien-marges-internes-ligne-debut:calc(var(--espace-m) + 1.5ch);--liste-puce-cercle-puce-position-horizontale:3.5ch}#en-tete .menu-navigation__entree:has(a[aria-current=page]),#en-tete .menu-navigation__entree--courante{background:url(/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche-gris.svg) bottom/auto 90% no-repeat}#en-tete .menu-navigation__entree a{padding:var(--nav-entree-marges-internes-bloc) var(--nav-entree-marges-internes-ligne);text-align:center;display:inline-block}@media (hover:hover){#en-tete .menu-navigation__entree:hover{background:url(/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche-gris.svg) bottom/auto 90% no-repeat}}@media (width<=1000px){#en-tete .menu-navigation#menu-navigation-en-tete{display:none}}#en-tete .compte-panier{text-align:center;flex-flow:row;place-items:center;gap:1rem;display:flex}#en-tete .compte-panier[disabled]{background:var(--arriere-plan-points)}#en-tete .compte-panier[disabled] a:hover,#en-tete .compte-panier[disabled] a:active,#en-tete .compte-panier[disabled] a:focus-within{border:1px solid var(--couleur-noir)}#en-tete .compte-panier a{padding-block:var(--espace-2xs);padding-inline:var(--espace-s);text-transform:lowercase;background:0 0}#en-tete .compte-panier a[data-contient-articles=true]{background:var(--couleur-gris-fond)}#en-tete .compte-panier a:hover,#en-tete .compte-panier a:focus-within{color:var(--couleur-blanc);background:var(--couleur-gris-fonce-fond)}#en-tete .compte-panier a:active{color:var(--couleur-noir);background:var(--arriere-plan-points)}#en-tete .conteneur{column-gap:var(--espace-m);display:flex}#en-tete .bouton-menu-mobile{--hauteur-bouton-menu:22px;align-content:center;display:none}#en-tete .bouton-menu-mobile img{height:var(--hauteur-bouton-menu);object-fit:contain;image-rendering:crisp-edges;shape-rendering:geometricprecision}@media (hover:hover){#en-tete .bouton-menu-mobile:hover{background:initial!important}}@media (width<=1000px){#en-tete .bouton-menu-mobile{display:block}}@media (width<=600px){#en-tete{--en-tete-marges-internes-ligne:var(--espace-l)}}#menu-categories-produits{--menu-entree-longueur-minimale:13ch;--menu-section-marges-bloc-debut:var(--en-tete-hauteur);--menu-entree-marges-internes-ligne:var(--espace-m);margin-top:var(--menu-section-marges-bloc-debut);position:relative}#menu-categories-produits[data-entrees-presentes-debut] svg:first-of-type,#menu-categories-produits[data-entrees-presentes-fin] svg:last-of-type{opacity:1}#menu-categories-produits svg{pointer-events:none;opacity:0;mix-blend-mode:exclusion;shape-rendering:geometricprecision;block-size:.8rem;inline-size:.8rem;transition:opacity .2s;position:absolute;bottom:calc(17.59px - .35rem)}#menu-categories-produits svg:first-of-type{left:var(--espace-xs)}#menu-categories-produits svg:last-of-type{right:var(--espace-xs)}@media (width>600px){#menu-categories-produits svg{visibility:hidden}}#menu-categories-produits ul{grid-template-columns:repeat(auto-fit, minmax(var(--menu-entree-longueur-minimale), 1fr));place-items:center;gap:1px;display:grid}#menu-categories-produits ul li{inline-size:100%;color:var(--couleur-gris);text-align:center;text-transform:uppercase;letter-spacing:var(--espacement-inter-lettres-etendu-m);background:var(--couleur-noir);font-style:italic;font-weight:500}#menu-categories-produits ul li:hover{background:var(--couleur-gris)}#menu-categories-produits ul li a{inline-size:inherit;padding:var(--menu-entree-marges-internes-ligne) 0;text-decoration:none;display:inline-block}#menu-categories-produits ul li a:focus-visible{outline-color:var(--couleur-blanc)}@media (hover:hover){#menu-categories-produits ul li a:hover{color:var(--couleur-noir);background:var(--arriere-plan-points)}}#menu-categories-produits ul li.categorie-courante{background:var(--couleur-gris)}#menu-categories-produits ul li.categorie-courante a{color:var(--couleur-noir);background:var(--arriere-plan-points);font-weight:600}#menu-categories-produits ul li.categorie-courante a:focus-visible{outline-color:var(--couleur-noir)}@media (hover:hover){#menu-categories-produits ul li.categorie-courante a:hover{background:var(--arriere-plan-points)}}@media (width<=1000px){#menu-categories-produits ul{--menu-entree-marges-internes-ligne:var(--espace-s);flex-flow:wrap;font-size:.8rem;display:flex}#menu-categories-produits ul li{flex-grow:1;inline-size:min(140px,100%)}#menu-categories-produits ul li a{border:initial;inline-size:100%}}@media (width<=600px){#menu-categories-produits ul{scrollbar-width:none;flex-flow:row;overflow-x:scroll}#menu-categories-produits ul li{inline-size:initial;min-inline-size:140px}}.photos-produit{--colonne-gauche-position-haut:var(--menu-categories-produits-hauteur);--colonne-gauche-photo-hauteur:calc(100svh - var(--menu-categories-produits-hauteur));--colonne-droite-photo-hauteur-minimale:calc(100svh + var(--en-tete-hauteur) + var(--menu-categories-produits-hauteur));--colonne-photo-longueur-minimale:30rem;--section-marges-externes-bloc-fin:1rem;flex-flow:row;max-width:100%;display:flex;position:relative}.photos-produit .colonne{width:min(var(--colonne-photo-longueur-minimale), 100%);flex-flow:column;flex-grow:1;display:flex;position:relative}.photos-produit .colonne.colonne-gauche{top:var(--colonne-gauche-position-haut);height:var(--colonne-gauche-photo-hauteur);position:sticky}.photos-produit .colonne.colonne-gauche figure,.photos-produit .colonne.colonne-gauche picture,.photos-produit .colonne.colonne-gauche img{height:100%}.photos-produit .colonne.colonne-droite img{width:100%;max-height:var(--colonne-droite-photo-hauteur-minimale)}.photos-produit .colonne.colonne-droite figure picture img:only-child{min-height:var(--colonne-droite-photo-hauteur-minimale);max-height:var(--colonne-droite-photo-hauteur-minimale)}@media (width<=60rem){.photos-produit{--colonne-droite-photo-hauteur-minimale:var(--photo-hauteur-maximum);--photo-longueur-maximum:calc(100% - var(--espace-xl));--photo-hauteur-maximum:calc(100svh - var(--en-tete-hauteur) - 87px);scroll-behavior:smooth;scrollbar-width:none;scroll-snap-type:x mandatory;width:fit-content;max-width:initial;flex-flow:row;overflow-x:scroll}.photos-produit::-webkit-scrollbar{display:none}.photos-produit .colonne{scroll-snap-type:x mandatory;width:100%;min-width:100%}.photos-produit .colonne figure{scroll-snap-align:none center}.photos-produit .colonne img{max-height:var(--photo-hauteur-maximum)}.photos-produit .colonne.colonne-gauche{position:initial;min-width:var(--photo-longueur-maximum);height:initial}.photos-produit .colonne.colonne-droite{flex-flow:row}.photos-produit .colonne.colonne-droite figure{min-width:var(--photo-longueur-maximum);flex-grow:1}.photos-produit .colonne.colonne-droite:has(figure:only-child){min-width:var(--photo-longueur-maximum)}}.grille-produits{--grille-produits-hauteur-minimale:var(--contenu-page-hauteur-minimale-avec-categories);--aucun-produit-hauteur:var(--contenu-page-hauteur-minimale-avec-categories);--carte-produit-longueur-minimale:448px;--carte-produit-longueur-maximale:1000px;grid-auto-rows:1fr;grid-template-columns:repeat(auto-fit, minmax(var(--carte-produit-longueur-minimale), 1fr));min-height:var(--grille-produits-hauteur-minimale);gap:1px;display:grid}.grille-produits article{max-width:var(--carte-produit-longueur-maximale);box-shadow:0 0 0 1px var(--couleur-noir)}.grille-produits article figure{row-gap:var(--espace-xl);flex-flow:column;display:flex}.grille-produits article figure a{position:relative}@media (hover:hover){.grille-produits article figure a:hover .produit__illustration__survol{visibility:visible;opacity:1;transition:opacity .3s,visibility .3s}}.grille-produits article figure img{position:inherit;aspect-ratio:9/16;object-fit:cover;background:0 0;width:100%;max-height:70vh}.grille-produits article figure .produit__illustration__principale{display:block}.grille-produits article figure .produit__illustration__principale:before{content:"";z-index:-1;opacity:0;filter:opacity(20%);background-image:url(/app/themes/haiku-atelier-2024/assets/img/icons/cloud-gris.svg);background-position:50%;background-repeat:no-repeat;background-size:50%;width:100%;height:100%;animation:1.5s linear .5s infinite alternate both test;position:absolute;top:0;left:0}.grille-produits article figure .produit__illustration__principale img{opacity:0;transition:opacity 1s}.grille-produits article figure .produit__illustration__survol{visibility:hidden;opacity:0;width:100%;height:100%;transition:opacity .15s,visibility .15s;display:block;position:absolute;top:0;left:0}.grille-produits article figure .produit__illustration__survol img{background:var(--couleur-gris-fond)}.grille-produits article figure figcaption{margin-bottom:var(--espace-xl);padding:var(--espace-m);flex-flow:row;justify-content:space-between;display:flex}.grille-produits article figure figcaption h3{letter-spacing:var(--espacement-inter-lettres-etendu-m);font-style:italic}.grille-produits article figure figcaption p{letter-spacing:var(--espacement-inter-lettres-rapproche-s);font-weight:500}.grille-produits__aucun-produit{min-height:var(--aucun-produit-hauteur);text-align:center;grid-column:span 3;align-content:center}.grille-produits__aucun-produit p+p{margin-top:var(--espace-l);font-size:1.25rem}@media (width<=700px){.grille-produits{grid-template-columns:100%}.grille-produits article figure img{max-height:50svh}}@keyframes test{to{opacity:1}}.resume-produit{--resume-position-basse:0%;--section-marges-internes:var(--espace-l);--espace-inter-colonne:var(--espace-xl);--resume-police-graisse:500;--resume-police-style:italic;--resume-police-taille:var(--espace-l);--resume-police-nom-taille:1.33rem;--resume-police-selecteur-graisse:400;--resume-police-selecteur-taille:var(--espace-m);bottom:var(--resume-position-basse);position:sticky}.resume-produit .selecteur-produit{column-gap:var(--espace-inter-colonne);border-block:1px solid var(--couleur-noir);font-size:var(--resume-police-taille);font-weight:var(--resume-police-graisse);font-style:var(--resume-police-style);line-height:var(--hauteur-ligne-compacte);background:var(--couleur-blanc-fond);grid-template-columns:repeat(3,1fr);grid-auto-flow:column;place-items:center;display:grid;position:relative}.resume-produit .selecteur-produit>*{width:100%;height:100%;padding:var(--section-marges-internes);flex-flow:row;place-content:center;place-items:center;display:flex}.resume-produit .selecteur-produit>:nth-child(2){border-inline-start:1px solid var(--couleur-noir);border-inline-end:1px solid var(--couleur-noir)}.resume-produit .selecteur-produit__nom{font-size:var(--resume-police-nom-taille)}.resume-produit .selecteur-produit__attribut-variation{gap:var(--espace-m) var(--espace-l);font-size:var(--resume-police-selecteur-taille);font-weight:var(--resume-police-selecteur-graisse);text-transform:lowercase;flex-flow:wrap;display:flex}.resume-produit .selecteur-produit__attribut-variation label{margin-right:var(--espace-s)}.resume-produit .selecteur-produit__attribut-variation select{padding:var(--espace-xs) var(--espace-l);border:1px solid var(--couleur-noir);text-align:center;letter-spacing:initial;appearance:none;background:var(--couleur-gris-fond);position:relative}@supports selector(:user-valid){.resume-produit .selecteur-produit__attribut-variation select:user-valid{background:var(--couleur-gris-fond)}}.resume-produit .selecteur-produit__attribut-variation option{background:var(--couleur-gris-fond)}.resume-produit .selecteur-produit__attribut-variation__selecteurs{gap:var(--espace-m);flex-flow:wrap;place-content:center;place-items:center;display:flex;position:relative}.resume-produit .selecteur-produit__prix{font-style:initial}@media (width<=800px){.resume-produit{--section-marges-internes:var(--espace-m);--espace-inter-colonne:var(--espace-m)}}@media (width<=700px){.resume-produit{--resume-police-taille:var(--espace-m);--resume-police-nom-taille:var(--espace-m);--section-marges-internes:var(--espace-m);--espace-inter-colonne:var(--espace-s)}}@media (width<=500px){.resume-produit .selecteur-produit__selection-variation-attribut{row-gap:var(--espace-inter-colonne);flex-flow:column}.resume-produit .selecteur-produit__selection-variation-attribut h3{flex-basis:100%}}.details-produit{--bouton-marges-internes-bloc:var(--espace-l);--espace-inter-lignes:var(--espace-l);--espace-inter-texte:var(--espace-m);--section-marges-internes:var(--espace-l);--textuel-marges-internes-ligne:calc(var(--espace-l) * 2);background-color:var(--couleur-blanc)}.details-produit__textes{grid-template-columns:1fr;grid-auto-flow:row;display:grid}.details-produit__textes .section-textuelle:not(:last-of-type){border-block-end:1px solid var(--couleur-noir)}.details-produit__textes .section-textuelle:has(button[aria-expanded=false]) .section-textuelle__contenu{display:none}.details-produit__textes .section-textuelle h3{line-height:var(--hauteur-ligne-rapprochee)}.details-produit__textes .section-textuelle h3 button{width:100%;min-block-size:1lh;padding:var(--section-marges-internes);text-align:start;display:inline-block}.details-produit__textes .section-textuelle h3 button:active{background:var(--arriere-plan-points)}@media (hover:hover){.details-produit__textes .section-textuelle h3 button:hover{color:inherit;background:inherit}}.details-produit__textes .section-textuelle .section-textuelle__contenu{padding-block-end:var(--section-marges-internes);padding-inline:var(--textuel-marges-internes-ligne)}.details-produit__textes .section-textuelle .section-textuelle__contenu ul{list-style:inside}.details-produit__textes .section-textuelle .section-textuelle__contenu a{text-decoration-color:var(--couleur-noir)}.details-produit__textes .section-textuelle .section-textuelle__contenu>*+*{margin-top:var(--espace-inter-texte)}.details-produit__actions{--section-marges-internes:var(--espace-l);border-block:1px solid var(--couleur-noir);background:var(--arriere-plan-points);transition:background .2s;overflow:hidden}.details-produit__actions:has(button[disabled]){background:var(--couleur-gris-fond)}.details-produit__actions button{padding:var(--section-marges-internes);text-transform:uppercase;font-style:italic}@media (hover:hover){.details-produit__actions button:not([disabled]):hover{color:var(--couleur-blanc);background:var(--couleur-gris-fonce-fond);font-weight:600}}.produits-similaires{--carte-produit-longueur-minimale:448px;--carte-produit-longueur-maximale:1000px;--en-tete-flottante-hauteur:calc(1rem + var(--espace-l) * 2 + 1px);grid-template-rows:1fr auto;grid-template-columns:repeat(3,1fr);grid-template-areas:"en-tete en-tete en-tete""produits produits produits";place-items:center;display:grid;position:relative}.produits-similaires header{z-index:10;top:var(--en-tete-flottante-hauteur);width:100%;padding:var(--espace-l) 0;color:var(--couleur-blanc);text-align:center;background:var(--couleur-noir);grid-area:en-tete;position:sticky}.produits-similaires header h2{font-style:italic;line-height:var(--hauteur-ligne-rapprochee);text-transform:uppercase;letter-spacing:var(--espacement-inter-lettres-etendu-m)}.produits-similaires .grille-produits-similaires{grid-area:produits;grid-auto-rows:1fr;grid-template-columns:repeat(auto-fit, minmax(var(--carte-produit-longueur-minimale), 1fr));gap:1px;width:100%;display:grid}.produits-similaires .grille-produits-similaires article{max-width:var(--carte-produit-longueur-maximale);box-shadow:0 0 0 1px var(--couleur-noir)}.produits-similaires .grille-produits-similaires article figure{row-gap:var(--espace-xl);flex-flow:column;display:flex}.produits-similaires .grille-produits-similaires article figure a{position:relative}@media (hover:hover){.produits-similaires .grille-produits-similaires article figure a:hover .produit__illustration__survol{visibility:visible;opacity:1;transition:opacity .3s,visibility .3s}}.produits-similaires .grille-produits-similaires article figure .produit__illustration__principale{display:block}.produits-similaires .grille-produits-similaires article figure .produit__illustration__survol{visibility:hidden;opacity:0;width:100%;height:100%;transition:opacity .15s,visibility .15s;display:block;position:absolute;top:0;left:0}.produits-similaires .grille-produits-similaires article figure img{aspect-ratio:9/16;object-fit:cover;width:100%;max-height:70svh}.produits-similaires .grille-produits-similaires article figure figcaption{margin-bottom:var(--espace-xl);padding:0 var(--espace-m);flex-flow:row;justify-content:space-between;display:flex}.produits-similaires .grille-produits-similaires article figure figcaption h3{letter-spacing:var(--espacement-inter-lettres-etendu-m);font-style:italic}.produits-similaires .grille-produits-similaires article figure figcaption p{letter-spacing:var(--espacement-inter-lettres-rapproche-s);font-weight:500}@media (width<=700px){.produits-similaires .grille-produits-similaires{grid-template-columns:100%}.produits-similaires .grille-produits-similaires article figure img{max-height:50svh}}#pied-de-page{max-width:100vw;height:var(--pied-de-page-hauteur);padding:var(--espace-s) var(--espace-m);border-top:1px solid var(--couleur-noir);grid-template-columns:1fr 1fr;place-items:center;font-size:.8rem;display:grid}#pied-de-page .zone-menu-navigation-secondaire{text-transform:lowercase;justify-self:start;width:100%;height:100%}#pied-de-page .zone-liens-reseaux-sociaux{text-align:right;justify-items:end;width:100%;height:100%} \ No newline at end of file diff --git a/web/app/themes/haiku-atelier-2024/front-page.php b/web/app/themes/haiku-atelier-2024/front-page.php index 1c1752ac..f75349c0 100755 --- a/web/app/themes/haiku-atelier-2024/front-page.php +++ b/web/app/themes/haiku-atelier-2024/front-page.php @@ -13,17 +13,17 @@ use Timber\Timber; use function add_action; -$context = Timber::context(); +$context = Timber::context(); $templates = ['accueil.twig']; add_action('wp_enqueue_scripts', function (): void { Resource::enqueue_script_module_file( - id: 'haiku-atelier-2024-scripts-page-accueil', + id : 'haiku-atelier-2024-scripts-page-accueil', path: '/assets/js/scripts-page-accueil.js', ); Resource::enqueue_style_file( handle: 'haiku-atelier-2024-styles-page-accueil', - path: '/assets/css/pages/page-accueil.css', + path : '/assets/css/pages/page-accueil.css', ); }); diff --git a/web/app/themes/haiku-atelier-2024/functions.php b/web/app/themes/haiku-atelier-2024/functions.php index 334520ab..36a38948 100755 --- a/web/app/themes/haiku-atelier-2024/functions.php +++ b/web/app/themes/haiku-atelier-2024/functions.php @@ -24,21 +24,21 @@ Timber::$dirname = ['views']; // Charge les Scripts du thème (report d'erreurs) function load_scripts(): void { wp_enqueue_script_module( - id: 'haiku-atelier-2024-bouton-panier', - deps: [], - src: get_template_directory_uri() . '/assets/js/scripts-bouton-panier.js', + id : 'haiku-atelier-2024-bouton-panier', + deps : [], + src : get_template_directory_uri() . '/assets/js/scripts-bouton-panier.js', version: filemtime(get_template_directory() . '/assets/js/scripts-bouton-panier.js'), ); wp_enqueue_script_module( - id: 'haiku-atelier-2024-menu-mobile', - deps: [], - src: get_template_directory_uri() . '/assets/js/scripts-menu-mobile.js', + id : 'haiku-atelier-2024-menu-mobile', + deps : [], + src : get_template_directory_uri() . '/assets/js/scripts-menu-mobile.js', version: filemtime(get_template_directory() . '/assets/js/scripts-menu-mobile.js'), ); wp_enqueue_script_module( - id: 'haiku-atelier-2024-bouton-retour-sommet', - deps: [], - src: get_template_directory_uri() . '/assets/js/scripts-bouton-retour-sommet.js', + id : 'haiku-atelier-2024-bouton-retour-sommet', + deps : [], + src : get_template_directory_uri() . '/assets/js/scripts-bouton-retour-sommet.js', version: filemtime(get_template_directory() . '/assets/js/scripts-bouton-retour-sommet.js'), ); } @@ -49,10 +49,10 @@ add_action('wp_enqueue_scripts', 'load_scripts'); function charge_styles_haiku_atelier_2024(): void { wp_enqueue_style( handle: 'haiku-atelier-2024-styles', - src: get_template_directory_uri() . '/assets/css/main.css', - deps: [], - ver: filemtime(get_template_directory() . '/assets/css/main.css'), - media: 'all', + src : get_template_directory_uri() . '/assets/css/main.css', + deps : [], + ver : filemtime(get_template_directory() . '/assets/css/main.css'), + media : 'all', ); } @@ -67,70 +67,70 @@ new StarterSite(); function enregistre_personnalisations_theme(mixed $wp_customize): void { // Section « Réseaux sociaux » $wp_customize->add_section('liens_reseaux_sociaux', [ - 'title' => __('Liens des réseaux sociaux'), + 'title' => __('Liens des réseaux sociaux'), 'description' => __("Liens des réseaux sociaux s'affichant dans le pied de page."), ]); // Instagram $wp_customize->add_setting('lien_instagram', ['type' => 'theme_mod', 'capability' => 'edit_theme_options']); $wp_customize->add_control('lien_instagram', [ - 'type' => 'url', + 'type' => 'url', 'section' => 'liens_reseaux_sociaux', - 'label' => __('Profil Instagram'), + 'label' => __('Profil Instagram'), ]); // Facebook $wp_customize->add_setting('lien_facebook', ['type' => 'theme_mod', 'capability' => 'edit_theme_options']); $wp_customize->add_control('lien_facebook', [ - 'type' => 'url', + 'type' => 'url', 'section' => 'liens_reseaux_sociaux', - 'label' => __('Profil Facebook'), + 'label' => __('Profil Facebook'), ]); // Pinterest $wp_customize->add_setting('lien_pinterest', ['type' => 'theme_mod', 'capability' => 'edit_theme_options']); $wp_customize->add_control('lien_pinterest', [ - 'type' => 'url', + 'type' => 'url', 'section' => 'liens_reseaux_sociaux', - 'label' => __('Profil Pinterest'), + 'label' => __('Profil Pinterest'), ]); // Section « Descriptions Produits » $wp_customize->add_section('descriptions_produits', [ - 'title' => __('Textes des descriptions Produits'), + 'title' => __('Textes des descriptions Produits'), 'description' => __('Textes des descriptions apparaissant sur les pages Produit.'), ]); $wp_customize->add_setting('texte_conditions_livraison', [ - 'capability' => 'edit_theme_options', - 'default' => '', + 'capability' => 'edit_theme_options', + 'default' => '', 'sanitize_callback' => 'wp_kses_post', - 'transport' => 'postMessage', - 'type' => 'theme_mod', + 'transport' => 'postMessage', + 'type' => 'theme_mod', ]); $wp_customize->add_control(new Controle_Personnalise_TinyMCE($wp_customize, 'texte_conditions_livraison', [ - 'label' => __('Conditions de livraison'), + 'label' => __('Conditions de livraison'), 'description' => __('Descriptif des conditions de livraison.'), - 'section' => 'descriptions_produits', + 'section' => 'descriptions_produits', 'input_attrs' => [ - 'toolbar1' => 'bold italic bullist numlist alignleft aligncenter alignright link', + 'toolbar1' => 'bold italic bullist numlist alignleft aligncenter alignright link', 'mediaButtons' => true, ], ])); $wp_customize->add_setting('texte_entretien_produit', [ - 'capability' => 'edit_theme_options', - 'default' => '', + 'capability' => 'edit_theme_options', + 'default' => '', 'sanitize_callback' => 'wp_kses_post', - 'transport' => 'postMessage', - 'type' => 'theme_mod', + 'transport' => 'postMessage', + 'type' => 'theme_mod', ]); $wp_customize->add_control(new Controle_Personnalise_TinyMCE($wp_customize, 'texte_entretien_produit', [ - 'label' => __('Entretien du Produit'), + 'label' => __('Entretien du Produit'), 'description' => __("Descriptif des bonnes pratiques pour l'entretien du Produit."), - 'section' => 'descriptions_produits', + 'section' => 'descriptions_produits', 'input_attrs' => [ - 'toolbar1' => 'bold italic bullist numlist alignleft aligncenter alignright link', + 'toolbar1' => 'bold italic bullist numlist alignleft aligncenter alignright link', 'mediaButtons' => true, ], ])); diff --git a/web/app/themes/haiku-atelier-2024/index.php b/web/app/themes/haiku-atelier-2024/index.php index 8cd2f361..d7b2847e 100755 --- a/web/app/themes/haiku-atelier-2024/index.php +++ b/web/app/themes/haiku-atelier-2024/index.php @@ -4,7 +4,7 @@ declare(strict_types=1); use Timber\Timber; -$context = Timber::context(); +$context = Timber::context(); $templates = ['base.twig']; Timber::render(data: $context, filenames: $templates); diff --git a/web/app/themes/haiku-atelier-2024/page-about.php b/web/app/themes/haiku-atelier-2024/page-about.php index 6d8690be..4c98ecd5 100755 --- a/web/app/themes/haiku-atelier-2024/page-about.php +++ b/web/app/themes/haiku-atelier-2024/page-about.php @@ -17,7 +17,7 @@ use function get_template_directory; use function getimagesize; use function is_bool; -$context = Timber::context(); +$context = Timber::context(); $templates = ['a-propos.twig']; /** Les dimensions de l'image du storytelling. */ @@ -32,10 +32,10 @@ $context['image_dimensions'] = $image_dimensions; add_action('wp_enqueue_scripts', function (): void { Resource::enqueue_style_file( handle: 'haiku-atelier-2024-styles-page-a-propos', - path: '/assets/css/pages/page-a-propos.css', + path : '/assets/css/pages/page-a-propos.css', ); Resource::enqueue_script_module_file( - id: 'haiku-atelier-2024-scripts-page-a-propos', + id : 'haiku-atelier-2024-scripts-page-a-propos', path: '/assets/js/scripts-page-a-propos.js', ); }); diff --git a/web/app/themes/haiku-atelier-2024/page-cart.php b/web/app/themes/haiku-atelier-2024/page-cart.php index 6effc12a..1ba84dc7 100755 --- a/web/app/themes/haiku-atelier-2024/page-cart.php +++ b/web/app/themes/haiku-atelier-2024/page-cart.php @@ -20,7 +20,7 @@ use function collect; use function Crell\fp\pipe; use function WC; -$context = Timber::context(); +$context = Timber::context(); $templates = ['panier.twig']; // Récupère les informations affichés des Produits du Panier @@ -47,60 +47,60 @@ $shipping_subtotal = Cart::parse_cart_value($cart_totals['shipping_total'] ?? 0) // TODO: Nettoyer ça. foreach (WC()->cart->get_cart() as $cle_panier => $article_panier) { $cart[$cle_panier] = [ - 'attributs' => $article_panier['data']?->get_type() === 'variation' + 'attributs' => $article_panier['data']?->get_type() === 'variation' ? Product::recupere_et_formate_attributs_produit($article_panier['data']?->get_attributes()) : [], - 'cle' => $cle_panier, - 'id_produit' => $article_panier['product_id'], + 'cle' => $cle_panier, + 'id_produit' => $article_panier['product_id'], 'id_variation' => $article_panier['variation_id'], - 'image' => pipe($article_panier['data']?->get_image_id(), static fn($id): string => Resource::output_multi_formats_img_tag( - id: (string) $id, + 'image' => pipe($article_panier['data']?->get_image_id(), static fn($id): string => Resource::output_multi_formats_img_tag( + id : (string) $id, lazy: true, )), - 'prix' => $article_panier['data']?->get_price(), - 'quantite' => $article_panier['quantity'], - 'url' => $article_panier['data']?->get_permalink(), - 'titre' => $article_panier['data']?->get_title(), + 'prix' => $article_panier['data']?->get_price(), + 'quantite' => $article_panier['quantity'], + 'url' => $article_panier['data']?->get_permalink(), + 'titre' => $article_panier['data']?->get_title(), ]; } // Récupère les Adresses de l'Utilisateur -$email = WC()->customer->get_billing_email(); -$adresse_livraison = WC()->customer->get_shipping(); +$email = WC()->customer->get_billing_email(); +$adresse_livraison = WC()->customer->get_shipping(); $adresse_facturation = WC()->customer->get_billing(); -$adresse_renseignee = $adresse_livraison['city'] !== ''; +$adresse_renseignee = $adresse_livraison['city'] !== ''; // TODO: Déplacer ça dans une fonction statique de Cart. $allowed_countries = collect(WC()->countries->get_countries())->only(Cart::get_allowed_countries())->toArray(); // TODO: Nettoyer ça. $methodes_livraison = collect(WC()->session->get('shipping_for_package_0')['rates']) ->values() ->map(static fn(WC_Shipping_Rate $methode): array => [ - 'id' => $methode->get_method_id(), - 'prix' => Number::format((int) $methode->get_cost(), precision: 2), + 'id' => $methode->get_method_id(), + 'prix' => Number::format((int) $methode->get_cost(), precision: 2), 'selectionnee' => collect(WC()->session->get('chosen_shipping_methods'))->first() === $methode->get_id(), - 'titre' => $methode->get_label(), + 'titre' => $methode->get_label(), ]); -$context['email'] = $email; -$context['adresse_livraison'] = $adresse_livraison; -$context['adresse_facturation'] = $adresse_facturation; -$context['adresse_renseignee'] = $adresse_renseignee; -$context['sous_total_panier'] = $cart_subtotal; -$context['code_promo'] = $promo_code; +$context['email'] = $email; +$context['adresse_livraison'] = $adresse_livraison; +$context['adresse_facturation'] = $adresse_facturation; +$context['adresse_renseignee'] = $adresse_renseignee; +$context['sous_total_panier'] = $cart_subtotal; +$context['code_promo'] = $promo_code; $context['sous_total_reduction'] = $cart_subtotal_with_discount; -$context['total_panier'] = $cart_total; -$context['produits_panier'] = $cart; -$context['pays_livraison'] = $allowed_countries; +$context['total_panier'] = $cart_total; +$context['produits_panier'] = $cart; +$context['pays_livraison'] = $allowed_countries; $context['sous_total_livraison'] = $shipping_subtotal; -$context['methodes_livraison'] = $methodes_livraison; +$context['methodes_livraison'] = $methodes_livraison; add_action('wp_enqueue_scripts', function (): void { Resource::enqueue_style_file( handle: 'haiku-atelier-2024-styles-page-panier', - path: '/assets/css/pages/page-panier.css', + path : '/assets/css/pages/page-panier.css', ); Resource::enqueue_script_module_file( - id: 'haiku-atelier-2024-scripts-page-panier', + id : 'haiku-atelier-2024-scripts-page-panier', path: '/assets/js/scripts-page-panier.js', ); }); diff --git a/web/app/themes/haiku-atelier-2024/page-checkout.php b/web/app/themes/haiku-atelier-2024/page-checkout.php index dbc0f890..5516bd50 100755 --- a/web/app/themes/haiku-atelier-2024/page-checkout.php +++ b/web/app/themes/haiku-atelier-2024/page-checkout.php @@ -44,9 +44,9 @@ $session_wc = WC()->session; /** @var array $urls URLs utilisables pour rediriger l'Utilisateur. */ $urls = [ - 'accueil' => get_page_link(get_page_by_path('home')), + 'accueil' => get_page_link(get_page_by_path('home')), 'succes_commande' => get_page_link(get_page_by_path('successful-order')), - 'echec_commande' => get_page_link(get_page_by_path('failed-order')), + 'echec_commande' => get_page_link(get_page_by_path('failed-order')), ]; // Redirige à la page d'accueil si le Panier est vide @@ -97,14 +97,14 @@ $articles = collect($panier->get_cart()) return [ 'price_data' => [ - 'currency' => 'EUR', + 'currency' => 'EUR', 'product_data' => [ - 'name' => $titre_produit, + 'name' => $titre_produit, 'images' => [wp_get_attachment_image_url($article_panier['data']?->get_image_id())], ], - 'unit_amount' => $article_panier['data']?->get_price() * 100, + 'unit_amount' => $article_panier['data']?->get_price() * 100, ], - 'quantity' => $article_panier['quantity'], + 'quantity' => $article_panier['quantity'], ]; }) ->values() @@ -126,13 +126,13 @@ Stripe::setApiKey(Config::get('STRIPE_API_SECRET')); // Met à jour les Codes promos $coupons_stripe = collect(Coupon::all()->data); -$coupons_wc = collect(WC()->cart->get_coupons()) +$coupons_wc = collect(WC()->cart->get_coupons()) ->map(static fn(WC_Coupon $coupon): array => [ - 'currency' => 'EUR', - 'duration' => get_discount_duration($coupon), + 'currency' => 'EUR', + 'duration' => get_discount_duration($coupon), 'fixed_cart' === $coupon->get_discount_type() ? 'amount_off' : 'percent_off' => get_discount_amount($coupon), - 'id' => $coupon->get_code(), - 'name' => $coupon->get_code(), + 'id' => $coupon->get_code(), + 'name' => $coupon->get_code(), ]) ->each(static function (array $item) use ($coupons_stripe): void { // Si le code promo n'existe pas, le créer @@ -147,19 +147,19 @@ $reductions_stripe = $coupons_wc /** @var Session $session_checkout_stripe */ $session_checkout_stripe = Session::create([ - 'cancel_url' => $urls['echec_commande'], - 'customer_email' => $email_client, - 'discounts' => $reductions_stripe, - 'line_items' => $articles, - 'mode' => 'payment', - 'success_url' => $urls['succes_commande'] . '?session_id={CHECKOUT_SESSION_ID}', - 'metadata' => ['order_id' => $order_id, 'order_key' => $order_key], + 'cancel_url' => $urls['echec_commande'], + 'customer_email' => $email_client, + 'discounts' => $reductions_stripe, + 'line_items' => $articles, + 'mode' => 'payment', + 'success_url' => $urls['succes_commande'] . '?session_id={CHECKOUT_SESSION_ID}', + 'metadata' => ['order_id' => $order_id, 'order_key' => $order_key], 'shipping_options' => [[ 'shipping_rate_data' => [ 'display_name' => $methode_livraison['nom'], 'fixed_amount' => ['amount' => $methode_livraison['cout'], 'currency' => 'EUR'], 'tax_behavior' => 'inclusive', - 'type' => 'fixed_amount', + 'type' => 'fixed_amount', ], ]], ], ['idempotency_key' => Uuid::v4()]); diff --git a/web/app/themes/haiku-atelier-2024/page-contact.php b/web/app/themes/haiku-atelier-2024/page-contact.php index 42d3cb30..784b6b58 100755 --- a/web/app/themes/haiku-atelier-2024/page-contact.php +++ b/web/app/themes/haiku-atelier-2024/page-contact.php @@ -13,13 +13,13 @@ use Timber\Timber; use function add_action; -$context = Timber::context(); +$context = Timber::context(); $templates = ['contact.twig']; add_action('wp_enqueue_scripts', function (): void { Resource::enqueue_style_file( handle: 'haiku-atelier-2024-styles-page-contact', - path: '/assets/css/pages/page-contact.min.css', + path : '/assets/css/pages/page-contact.min.css', ); }); diff --git a/web/app/themes/haiku-atelier-2024/page-failed-order.php b/web/app/themes/haiku-atelier-2024/page-failed-order.php index ea428114..466017d6 100755 --- a/web/app/themes/haiku-atelier-2024/page-failed-order.php +++ b/web/app/themes/haiku-atelier-2024/page-failed-order.php @@ -13,13 +13,13 @@ use Timber\Timber; use function add_action; -$context = Timber::context(); +$context = Timber::context(); $templates = ['echec-commande.twig']; add_action('wp_enqueue_scripts', function (): void { Resource::enqueue_style_file( handle: 'haiku-atelier-2024-styles-page-modele-simple', - path: '/assets/css/pages/page-modele-simple.css', + path : '/assets/css/pages/page-modele-simple.css', ); }); diff --git a/web/app/themes/haiku-atelier-2024/page-successful-order.php b/web/app/themes/haiku-atelier-2024/page-successful-order.php index e72c835a..97684d81 100755 --- a/web/app/themes/haiku-atelier-2024/page-successful-order.php +++ b/web/app/themes/haiku-atelier-2024/page-successful-order.php @@ -61,7 +61,7 @@ try { $panier->empty_cart(); } - $context = Timber::context(); + $context = Timber::context(); $templates = ['succes-commande.twig']; // Récupère les données des Produits @@ -76,7 +76,7 @@ try { // Récupère le nom et la valeur de l'attribut du Produit $attribut = $produit->is_type('variable') ? collect($produit->get_attributes())->mapWithKeys(static function ($_atr, $cle) use ($produit_commande) { - $nom_attribut = wc_attribute_label($cle, $produit_commande->get_product()); + $nom_attribut = wc_attribute_label($cle, $produit_commande->get_product()); $valeur_attribut = $produit_commande->get_product()->get_attribute($cle); return [['nom' => $nom_attribut, 'valeur' => $valeur_attribut]]; @@ -84,16 +84,16 @@ try { : []; return [ - 'attribut' => $attribut, + 'attribut' => $attribut, 'id_produit' => $id_produit, - 'image' => pipe($produit->get_image_id(), static fn($id): string => Resource::output_multi_formats_img_tag( - id: $id, + 'image' => pipe($produit->get_image_id(), static fn($id): string => Resource::output_multi_formats_img_tag( + id : $id, lazy: true, )), - 'permalien' => $produit->get_permalink(), - 'prix' => $produit_commande->get_data()['total'], - 'quantite' => $produit_commande->get_quantity(), - 'titre' => $produit->get_title(), + 'permalien' => $produit->get_permalink(), + 'prix' => $produit_commande->get_data()['total'], + 'quantite' => $produit_commande->get_quantity(), + 'titre' => $produit->get_title(), ]; }); @@ -103,10 +103,10 @@ try { function charge_scripts_styles_page_succes_commande(): void { wp_enqueue_style( handle: 'haiku-atelier-2024-styles-page-succes-commande', - src: get_template_directory_uri() . '/assets/css/pages/page-succes-commande.css', - deps: [], - ver: filemtime(get_template_directory() . '/assets/css/pages/page-succes-commande.css'), - media: 'all', + src : get_template_directory_uri() . '/assets/css/pages/page-succes-commande.css', + deps : [], + ver : filemtime(get_template_directory() . '/assets/css/pages/page-succes-commande.css'), + media : 'all', ); } diff --git a/web/app/themes/haiku-atelier-2024/page-terms-and-conditions.php b/web/app/themes/haiku-atelier-2024/page-terms-and-conditions.php index 0b9d5998..efb74bc7 100755 --- a/web/app/themes/haiku-atelier-2024/page-terms-and-conditions.php +++ b/web/app/themes/haiku-atelier-2024/page-terms-and-conditions.php @@ -13,13 +13,13 @@ use Timber\Timber; use function add_action; -$context = Timber::context(); +$context = Timber::context(); $templates = ['cgv.twig']; add_action('wp_enqueue_scripts', function (): void { Resource::enqueue_style_file( handle: '/assets/css/pages/page-modele-simple.css', - path: '/assets/css/pages/page-modele-simple.css', + path : '/assets/css/pages/page-modele-simple.css', ); }); diff --git a/web/app/themes/haiku-atelier-2024/single-product.php b/web/app/themes/haiku-atelier-2024/single-product.php index 445b0b68..8a4f581a 100755 --- a/web/app/themes/haiku-atelier-2024/single-product.php +++ b/web/app/themes/haiku-atelier-2024/single-product.php @@ -27,7 +27,7 @@ use function wc_get_product; use function wp_create_nonce; use function wp_json_encode; -$context = Timber::context(); +$context = Timber::context(); $templates = ['produit.twig']; $raw_product = wc_get_product(); @@ -55,13 +55,13 @@ $same_collection_products = Product::get_same_collection_products($product->coll Product::from_wc_product(...), )); -$context['product'] = $product; -$context['product_json'] = wp_json_encode($product); -$context['maximum_price'] = $maximum_price; +$context['product'] = $product; +$context['product_json'] = wp_json_encode($product); +$context['maximum_price'] = $maximum_price; $context['same_collection_products'] = $same_collection_products; -$product_tags = $raw_product->get_tag_ids() +$product_tags = $raw_product->get_tag_ids() |> (static fn($tags_ids) => Arr::map($tags_ids, static fn($id) => Term::get_term_by_id( - id: $id, + id : $id, taxonomy: 'product_tag', ))) |> (static fn(/** @var list> */ $tags) => Arr::reject($tags, static fn($tag) => $tag->isNone())) @@ -70,11 +70,11 @@ $tags = get_terms(['taxonomy' => 'product_tag', 'hide_empty' => true]); // Injecte les états initiaux des données du Produit sous forme de JSON dans le contexte. $page_states = [ - 'nonce' => wp_create_nonce('wc_store_api'), + 'nonce' => wp_create_nonce('wc_store_api'), 'product' => [ 'attributes' => $product->attributes, - 'id' => $product->id, - 'price' => $product->price, + 'id' => $product->id, + 'price' => $product->price, 'variations' => $product->variations, ], ] @@ -84,11 +84,11 @@ $context['page_states'] = $page_states; add_action('wp_enqueue_scripts', function (): void { Resource::enqueue_script_module_file( - id: 'haiku-atelier-2024-scripts-page-produit', + id : 'haiku-atelier-2024-scripts-page-produit', path: '/assets/js/scripts-page-produit.js', ); Resource::enqueue_script_module_file( - id: 'haiku-atelier-2024-scripts-menu-categories', + id : 'haiku-atelier-2024-scripts-menu-categories', path: '/assets/js/scripts-menu-categories.js', ); }); diff --git a/web/app/themes/haiku-atelier-2024/src/StarterSite.php b/web/app/themes/haiku-atelier-2024/src/StarterSite.php index 016d7146..555e7a68 100755 --- a/web/app/themes/haiku-atelier-2024/src/StarterSite.php +++ b/web/app/themes/haiku-atelier-2024/src/StarterSite.php @@ -51,8 +51,8 @@ final class StarterSite extends Site { // Récupère les liens des réseaux sociaux définis dans la personnalisation du thème $personnalisations_theme = get_theme_mods(); - $liens_reseaux_sociaux = [ - 'facebook' => ['nom' => 'Facebook', 'url' => $personnalisations_theme['lien_facebook'] ?? ''], + $liens_reseaux_sociaux = [ + 'facebook' => ['nom' => 'Facebook', 'url' => $personnalisations_theme['lien_facebook'] ?? ''], 'instagram' => ['nom' => 'Instagram', 'url' => $personnalisations_theme['lien_instagram'] ?? ''], 'pinterest' => ['nom' => 'Pinterest', 'url' => $personnalisations_theme['lien_pinterest'] ?? ''], ]; @@ -61,14 +61,14 @@ final class StarterSite extends Site { // Récupère les textes apparaissant sur les pages Produits $descriptions_produits = [ 'texte_conditions_livraison' => wpautop($personnalisations_theme['texte_conditions_livraison']) ?? '', - 'texte_entretien_produit' => wpautop($personnalisations_theme['texte_entretien_produit']) ?? '', + 'texte_entretien_produit' => wpautop($personnalisations_theme['texte_entretien_produit']) ?? '', ]; $context['descriptions_produits'] = $descriptions_produits; // Logo personnalisée $context['logo'] = pipe(get_theme_mod('custom_logo'), static fn($id) => wp_get_attachment_image_src( attachment_id: $id, - size: 'full', + size : 'full', )); // Informations des Pages @@ -80,28 +80,27 @@ final class StarterSite extends Site { // Pages spécifiques $context['pages'] = (object) [ - 'about' => $recupere_informations_page('about'), - 'account' => $recupere_informations_page('account'), - 'cart' => $recupere_informations_page('cart'), - 'checkout' => $recupere_informations_page('checkout'), - 'contact' => $recupere_informations_page('contact'), - 'failed_order' => $recupere_informations_page('failed_order'), - 'home' => $recupere_informations_page('home'), - 'shop' => $recupere_informations_page('shop'), + 'about' => $recupere_informations_page('about'), + 'account' => $recupere_informations_page('account'), + 'cart' => $recupere_informations_page('cart'), + 'checkout' => $recupere_informations_page('checkout'), + 'contact' => $recupere_informations_page('contact'), + 'failed_order' => $recupere_informations_page('failed_order'), + 'home' => $recupere_informations_page('home'), + 'shop' => $recupere_informations_page('shop'), 'successful_order' => $recupere_informations_page('successful_order'), ]; // Récupère la Page courante - $url_courante = URLHelper::get_current_url(); - $context['page_courante'] = $url_courante; + $url_courante = URLHelper::get_current_url(); + $context['page_courante'] = $url_courante; $context['est_page_tous_produits'] = preg_match(pattern: '/(\bshop\b)/', subject: $url_courante); - $context['est_page_boutique'] = - preg_match(pattern: '/(\bshop\b)/', subject: $url_courante) - || preg_match(pattern: '/(\bproduct\b)/', subject: $url_courante) - || preg_match(pattern: '/(\bproduct-category\b)/', subject: $url_courante); + $context['est_page_boutique'] = preg_match(pattern: '/(\bshop\b)/', subject: $url_courante) + || preg_match(pattern: '/(\bproduct\b)/', subject: $url_courante) + || preg_match(pattern: '/(\bproduct-category\b)/', subject: $url_courante); // Politique de confidentialité - $politique_confidentialite_lien = pipe(get_privacy_policy_url(), esc_url(...)); + $politique_confidentialite_lien = pipe(get_privacy_policy_url(), esc_url(...)); $context['lien_politique_confidentialite'] = $politique_confidentialite_lien; // Chemin de base pour une Catégorie de Produit (p. ex. /product-category/) @@ -109,7 +108,7 @@ final class StarterSite extends Site { // Récupère les Catégories de Produits $cree_entree_menu = static fn($categorie): array => [ - 'nom' => $categorie->name, + 'nom' => $categorie->name, 'slug' => $categorie->slug, // Détermine si l'URL courante est celle de la Page d'Archive d'une Catégorie de Produits 'courante' => preg_match( @@ -125,16 +124,16 @@ final class StarterSite extends Site { $context['categories_produits'] = $entrees_menu_categories; // Récupère le Panier de l'Utilisateur - $panier = WC()?->cart?->get_cart(); + $panier = WC()?->cart?->get_cart(); $quantite_articles = WC()?->cart?->get_cart_contents_count(); $articles_presents = $quantite_articles > 0 ? 'true' : 'false'; - $context['panier'] = $panier; + $context['panier'] = $panier; $context['quantite_articles'] = $quantite_articles; $context['articles_presents'] = $articles_presents; // Nonce WooCommerce pour l'API Rest - $nonce_wc = wp_create_nonce('wc_store_api'); + $nonce_wc = wp_create_nonce('wc_store_api'); $context['nonce_wc'] = $nonce_wc; // TODO: Utiliser des variables d'environnement $auth_string = base64_encode( diff --git a/web/app/themes/haiku-atelier-2024/src/inc/ChampsPersonnalises.php b/web/app/themes/haiku-atelier-2024/src/inc/ChampsPersonnalises.php index 9d509e72..d3605c09 100755 --- a/web/app/themes/haiku-atelier-2024/src/inc/ChampsPersonnalises.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/ChampsPersonnalises.php @@ -28,9 +28,9 @@ function cree_champs_personnalises_produit(): void { function cree_champ_personnalise_commande($order): void { woocommerce_wp_text_input([ - 'id' => 'tracking_number', - 'label' => 'Tracking Number:', - 'value' => $order->get_meta('tracking_number'), + 'id' => 'tracking_number', + 'label' => 'Tracking Number:', + 'value' => $order->get_meta('tracking_number'), 'wrapper_class' => 'form-field-wide', ]); } diff --git a/web/app/themes/haiku-atelier-2024/src/inc/ControlesPersonnalises.php b/web/app/themes/haiku-atelier-2024/src/inc/ControlesPersonnalises.php index 78d633cd..2ba09723 100755 --- a/web/app/themes/haiku-atelier-2024/src/inc/ControlesPersonnalises.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/ControlesPersonnalises.php @@ -27,10 +27,10 @@ function enregistre_controle_personnalise_tinymce(): void { public function enqueue(): void { wp_enqueue_script( handle: 'controle-personnalise-tinymce', - src: get_template_directory_uri() . '/assets/vendor/controle-personnalise-tinymce.js', - deps: ['jquery'], - ver: '1.3', - args: true, + src : get_template_directory_uri() . '/assets/vendor/controle-personnalise-tinymce.js', + deps : ['jquery'], + ver : '1.3', + args : true, ); wp_enqueue_editor(); } diff --git a/web/app/themes/haiku-atelier-2024/src/inc/Data/Attribute.php b/web/app/themes/haiku-atelier-2024/src/inc/Data/Attribute.php index 27ca18be..9cf8ab97 100644 --- a/web/app/themes/haiku-atelier-2024/src/inc/Data/Attribute.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/Data/Attribute.php @@ -17,7 +17,7 @@ final readonly class Attribute { public function __construct( public string $name, public string $slug, - public array $options, + public array $options, ) {} /** @@ -26,8 +26,10 @@ final readonly class Attribute { public static function new(WC_Product_Attribute $attribute): self { $name = wc_attribute_label($attribute->get_name()); $slug = $attribute->get_name(); + /** @var list */ $terms = $attribute->get_terms() ?? []; + /** @var list */ $options = Arr::map($terms, AttributeOption::new(...)) |> (static fn($options) => Arr::sort($options, static fn($attribute) => $attribute->id)) diff --git a/web/app/themes/haiku-atelier-2024/src/inc/Data/AttributeOption.php b/web/app/themes/haiku-atelier-2024/src/inc/Data/AttributeOption.php index a2d77967..c353ccb5 100644 --- a/web/app/themes/haiku-atelier-2024/src/inc/Data/AttributeOption.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/Data/AttributeOption.php @@ -8,7 +8,7 @@ use WP_Term; final readonly class AttributeOption { public function __construct( - public int $id, + public int $id, public string $name, public string $slug, ) {} @@ -17,7 +17,7 @@ final readonly class AttributeOption { * Créé une nouvelle instance de `AttributeOption` depuis un `WP_Term`. */ public static function new(WP_Term $term): self { - $id = $term->term_taxonomy_id; + $id = $term->term_taxonomy_id; $name = $term->name; $slug = $term->slug; diff --git a/web/app/themes/haiku-atelier-2024/src/inc/Data/Cart.php b/web/app/themes/haiku-atelier-2024/src/inc/Data/Cart.php index 1ad27c0d..1849cd35 100644 --- a/web/app/themes/haiku-atelier-2024/src/inc/Data/Cart.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/Data/Cart.php @@ -112,10 +112,10 @@ final readonly class Cart { private static function format_number(int|float $number): string { $formatted_number = Number::format( - number: $number, + number : $number, // precision et max_precision sont mutuellement exclusifs. precision: 2, - locale: 'fr', + locale : 'fr', ); return is_bool($formatted_number) ? self::DEFAULT_VALUE : $formatted_number; diff --git a/web/app/themes/haiku-atelier-2024/src/inc/Data/Product.php b/web/app/themes/haiku-atelier-2024/src/inc/Data/Product.php index 0cca2cb7..5fa1118a 100644 --- a/web/app/themes/haiku-atelier-2024/src/inc/Data/Product.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/Data/Product.php @@ -18,28 +18,31 @@ use function Psl\Option\from_nullable; use function wc_get_products; use function wpautop; +/** + * Représente un **Produit** (selon _WooCommerce_) avec de nombreuses données d'intérêt pour les opérations courantes. + */ final readonly class Product { /** - * @param list $attributes + * @param list $attributes La liste des `Attribute` appliquées. * @param list $left_column_photos * @param list $right_column_photos * @param array $variations */ private function __construct( - public array $attributes, + public array $attributes, public string $category, public string $collection, public string $details, - public int $id, + public int $id, public string $name, public string $price, - public array $left_column_photos, - public array $right_column_photos, + public array $left_column_photos, + public array $right_column_photos, public string $default_photo, public string $hover_photo, public string $slug, - public int $stock, - public array $variations, + public int $stock, + public array $variations, public string $url, ) {} @@ -59,17 +62,17 @@ final readonly class Product { /** @var string */ $details = $product->get_description() |> wpautop(...); - $id = $product->get_id(); - $name = $product->get_name(); - $price = $product->get_price(); + $id = $product->get_id(); + $name = $product->get_name(); + $price = $product->get_price(); /** @var list */ $left_column_photos = HaikuProduct::get_left_column_photos($id); /** @var list */ $right_column_photos = HaikuProduct::get_right_column_photos($id); - $default_photo = $left_column_photos[0] ?? Resource::output_multi_formats_img_tag('-1'); - $hover_photo = $right_column_photos[0] ?? Resource::output_multi_formats_img_tag('-1', true); - $slug = $product->get_slug(); - $stock = $product->get_stock_quantity() ?? 1; + $default_photo = $left_column_photos[0] ?? Resource::output_multi_formats_img_tag('-1'); + $hover_photo = $right_column_photos[0] ?? Resource::output_multi_formats_img_tag('-1', true); + $slug = $product->get_slug(); + $stock = $product->get_stock_quantity() ?? 1; /** @var array */ $variations = $product->get_children() |> (static fn(/** @var list */ array $ids): array => Arr::map($ids, wc_get_product(...))) @@ -80,21 +83,21 @@ final readonly class Product { $url = $product->get_permalink(); return new self( - attributes: $attributes, - category: $category, - collection: $collection, - details: $details, - id: $id, - name: $name, - price: $price, - left_column_photos: $left_column_photos, + attributes : $attributes, + category : $category, + collection : $collection, + details : $details, + id : $id, + name : $name, + price : $price, + left_column_photos : $left_column_photos, right_column_photos: $right_column_photos, - default_photo: $default_photo, - hover_photo: $hover_photo, - slug: $slug, - stock: $stock, - variations: $variations, - url: $url, + default_photo : $default_photo, + hover_photo : $hover_photo, + slug : $slug, + stock : $stock, + variations : $variations, + url : $url, ); } @@ -115,21 +118,21 @@ final readonly class Product { */ public static function get_same_collection_products(string $slug_collection): callable { return static fn(int $id_produit): array|stdClass => wc_get_products([ - 'exclude' => [$id_produit], - 'limit' => 4, - 'order' => 'DESC', - 'orderby' => 'date', - 'status' => 'publish', + 'exclude' => [$id_produit], + 'limit' => 4, + 'order' => 'DESC', + 'orderby' => 'date', + 'status' => 'publish', 'tax_query' => [['taxonomy' => 'collection', 'field' => 'slug', 'terms' => $slug_collection]], ]); } public static function recupere_et_formate_attributs_produit(mixed $attributs_produit): mixed { return [ - 'cote' => ['nom' => 'Side', 'valeur' => $attributs_produit['pa_side'] ?? false], + 'cote' => ['nom' => 'Side', 'valeur' => $attributs_produit['pa_side'] ?? false], 'materiel' => ['nom' => 'Material', 'valeur' => $attributs_produit['pa_material-workshop'] ?? false], - 'pierre' => ['nom' => 'Stone', 'valeur' => $attributs_produit['pa_stone'] ?? false], - 'taille' => ['nom' => 'Size', 'valeur' => $attributs_produit['pa_size'] ?? false], + 'pierre' => ['nom' => 'Stone', 'valeur' => $attributs_produit['pa_stone'] ?? false], + 'taille' => ['nom' => 'Size', 'valeur' => $attributs_produit['pa_size'] ?? false], ]; } } diff --git a/web/app/themes/haiku-atelier-2024/src/inc/Data/ProductVariation.php b/web/app/themes/haiku-atelier-2024/src/inc/Data/ProductVariation.php index 6609537e..0cc6cc63 100644 --- a/web/app/themes/haiku-atelier-2024/src/inc/Data/ProductVariation.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/Data/ProductVariation.php @@ -13,16 +13,16 @@ final readonly class ProductVariation { * @param list $attributes Les attributs appliqués à la Variation */ private function __construct( - public int $id, + public int $id, public string $price, - public array $attributes, + public array $attributes, ) {} /** * Créé une nouvelle instance de `ProductVariation` depuis un `WC_Product`. */ public static function new(WC_Product $product): self { - $id = $product->get_id(); + $id = $product->get_id(); $price = $product->get_price(); /** @var list */ $attributes = array_map( diff --git a/web/app/themes/haiku-atelier-2024/src/inc/Fonctionnalites.php b/web/app/themes/haiku-atelier-2024/src/inc/Fonctionnalites.php index 771f1c3d..4f09e84a 100755 --- a/web/app/themes/haiku-atelier-2024/src/inc/Fonctionnalites.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/Fonctionnalites.php @@ -40,7 +40,7 @@ function desactive_transformation_contenu_tinymce(array $configuration): array { * @return array le même tableau avec SVG en plus */ function autorise_import_svg_mediatheque(array $file_types): array { - $new_filetypes = []; + $new_filetypes = []; $new_filetypes['svg'] = 'image/svg+xml'; return [...$file_types, ...$new_filetypes]; @@ -58,6 +58,9 @@ function retire_styles_core_block(): void { add_filter('async_update_translation', '__return_false'); add_filter('auto_update_translation', '__return_false'); +// Désactive la génération automatique de sitemaps. +add_filter('wp_sitemaps_enabled', '__return_false'); + add_action('init', desactive_wpautop(...)); add_filter('tiny_mce_before_init', desactive_transformation_contenu_tinymce(...)); add_filter('upload_mimes', autorise_import_svg_mediatheque(...)); diff --git a/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php b/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php index 479b02e7..21bed7d8 100755 --- a/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php @@ -131,7 +131,8 @@ function retire_merdes_wc(): void { */ function genere_balises_img_dans_produit_dans_reponse_rest( WP_REST_Response $response, - mixed $_product, + WC_Data $_product, + WP_REST_Request $_request, ): WP_REST_Response { // Vérifie que la Réponse a des données if (empty($response->data)) { @@ -142,11 +143,11 @@ function genere_balises_img_dans_produit_dans_reponse_rest( $response->data['image_repos'] = pipe( $response->data['meta_data'], static fn($metadata): array => array_filter( - array: $metadata, + array : $metadata, callback: static fn($entree): bool => '_photos_colonne_gauche|||0|value' === $entree->key, ), static fn($metadata): array => array_map(array: $metadata, callback: static fn($entree): string => Resource::output_multi_formats_img_tag( - id: $entree?->value, + id : $entree?->value, lazy: true, )), static fn($image) => array_values(array: $image)[0], @@ -156,11 +157,11 @@ function genere_balises_img_dans_produit_dans_reponse_rest( $response->data['image_survol'] = pipe( $response->data['meta_data'], static fn($metadata): array => array_filter( - array: $metadata, + array : $metadata, callback: static fn($entree): bool => '_photos_colonne_droite|||0|value' === $entree->key, ), static fn($metadata): array => array_map(array: $metadata, callback: static fn($entree): string => Resource::output_multi_formats_img_tag( - id: $entree?->value, + id : $entree?->value, lazy: true, )), static fn($image) => array_values(array: $image)[0], @@ -169,37 +170,34 @@ function genere_balises_img_dans_produit_dans_reponse_rest( return $response; } -add_filter('woocommerce_rest_prepare_product_object', 'genere_balises_img_dans_produit_dans_reponse_rest', 10, 2); - /** * TODO. */ function genere_prix_maximal_produit_variable_dans_reponse_rest( - WP_REST_Response $reponse, - WC_Data $_produit, + WP_REST_Response $response, + WC_Data $_product, + WP_REST_Request $_request, ): WP_REST_Response { // Vérifie que la Réponse a des données - if (empty($reponse->data)) { - return $reponse; + if (empty($response->data)) { + return $response; } // Si le Produit n'est pas Variable, assigner le prix du Produit comme prix maximal - if ('variable' !== $reponse->data['type']) { - $reponse->data['prix_maximal'] = $reponse->data['regular_price']; + if ('variable' !== $response->data['type']) { + $response->data['prix_maximal'] = $response->data['regular_price']; - return $reponse; + return $response; } // Assigne le prix de la Variation la plus chère dans la Réponse - $reponse->data['prix_maximal'] = collect($reponse->data['variations']) + $response->data['prix_maximal'] = collect($response->data['variations']) ->map(wc_get_product(...)) ->map(static fn($p) => $p->get_price())->max(); - return $reponse; + return $response; } -add_filter('woocommerce_rest_prepare_product_object', 'genere_prix_maximal_produit_variable_dans_reponse_rest', 10, 2); - /** * Retire la propagande commerciale de WooCommerce du menu. */ @@ -216,3 +214,8 @@ add_action('init', 'retire_script_galerie'); add_action('template_redirect', 'retire_merdes_wc'); add_action('wp_enqueue_scripts', 'dequeue_woocommerce_styles_scripts'); add_filter('woocommerce_enqueue_styles', '__return_empty_array'); +add_filter('woocommerce_rest_prepare_product_object', 'genere_balises_img_dans_produit_dans_reponse_rest', 10, 3); +add_filter('woocommerce_rest_prepare_product_object', 'genere_prix_maximal_produit_variable_dans_reponse_rest', 10, 3); + +// DEBUG +// add_filter('woocommerce_store_api_disable_nonce_check', '__return_true'); diff --git a/web/app/themes/haiku-atelier-2024/src/inc/Taxonomies.php b/web/app/themes/haiku-atelier-2024/src/inc/Taxonomies.php index 727459f0..4956bf7e 100755 --- a/web/app/themes/haiku-atelier-2024/src/inc/Taxonomies.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/Taxonomies.php @@ -16,27 +16,27 @@ use function register_taxonomy; */ function enregistre_taxonomie_collection(): void { $labels = [ - 'add_new_item' => __('Add New Collection'), - 'all_items' => __('All Collections'), - 'edit_item' => __('Edit Collection'), - 'menu_name' => __('Collections'), - 'name' => __('Collections'), + 'add_new_item' => __('Add New Collection'), + 'all_items' => __('All Collections'), + 'edit_item' => __('Edit Collection'), + 'menu_name' => __('Collections'), + 'name' => __('Collections'), 'new_item_name' => __('New Collection Name'), - 'search_items' => __('Search Collections'), + 'search_items' => __('Search Collections'), 'singular_name' => __('Collection'), - 'update_item' => __('Update Collection'), + 'update_item' => __('Update Collection'), ]; $args = [ - 'description' => __('An ensemble of pieces thematically or chronologically grouped together.'), - 'hierarchical' => false, - 'labels' => $labels, + 'description' => __('An ensemble of pieces thematically or chronologically grouped together.'), + 'hierarchical' => false, + 'labels' => $labels, 'publicly_queryable' => false, - 'query_var' => true, - 'rewrite' => ['slug' => 'collection'], - 'show_admin_column' => true, - 'show_in_menu' => true, + 'query_var' => true, + 'rewrite' => ['slug' => 'collection'], + 'show_admin_column' => true, + 'show_in_menu' => true, 'show_in_quick_edit' => true, - 'show_ui' => true, + 'show_ui' => true, ]; register_taxonomy('collection', ['product'], $args); diff --git a/web/app/themes/haiku-atelier-2024/src/inc/WP/Resource.php b/web/app/themes/haiku-atelier-2024/src/inc/WP/Resource.php index d4a67475..6b286404 100644 --- a/web/app/themes/haiku-atelier-2024/src/inc/WP/Resource.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/WP/Resource.php @@ -21,7 +21,7 @@ final readonly class Resource { public static function enqueue_script_module_file(string $path, string $id): void { $file_uri = get_template_directory_uri() . $path; - $file_path = get_template_directory() . $path; + $file_path = get_template_directory() . $path; $file_mtime = filemtime($file_path); if (is_bool($file_mtime)) { @@ -39,7 +39,7 @@ final readonly class Resource { public static function enqueue_style_file(string $path, string $handle): void { $file_uri = get_template_directory_uri() . $path; - $file_path = get_template_directory() . $path; + $file_path = get_template_directory() . $path; $file_mtime = filemtime($file_path); if (is_bool($file_mtime)) { @@ -66,30 +66,29 @@ final readonly class Resource { return ''; } - $url = wp_get_attachment_image_url($int_id, 'full'); - $chemin = realpath(get_attached_file($int_id)) ?: realpath(get_attached_file($int_id)); - $alt = get_post_meta($int_id, '_wp_attachment_image_alt', true); + $url = wp_get_attachment_image_url($int_id, 'full'); + $chemin = realpath(get_attached_file($int_id)) ?: realpath(get_attached_file($int_id)); + $alt = get_post_meta($int_id, '_wp_attachment_image_alt', true); $dimensions = $chemin ? getimagesize($chemin) : ['', '']; $avif = $chemin ? realpath(pathinfo($chemin)['dirname'] . '/' . pathinfo($chemin)['filename'] . '.avif') : false; - $jxl = $chemin ? realpath(pathinfo($chemin)['dirname'] . '/' . pathinfo($chemin)['filename'] . '.jxl') : false; + $jxl = $chemin ? realpath(pathinfo($chemin)['dirname'] . '/' . pathinfo($chemin)['filename'] . '.jxl') : false; // Génère un tableau avec les différents formats valides $formats = pipe( [$avif, $jxl], static fn($tableau): array => array_filter( - array: $tableau, + array : $tableau, callback: static fn($chemin_format): bool => false !== $chemin_format, ), static fn($tableau): array => array_map(array: $tableau, callback: static fn($chemin_format): array => [ 'format' => pathinfo((string) $chemin_format)['extension'], 'taille' => filesize($chemin_format), - 'url' => - pathinfo($url)['dirname'] - . '/' - . pathinfo($url)['filename'] - . '.' - . pathinfo((string) $chemin_format)['extension'], + 'url' => pathinfo($url)['dirname'] + . '/' + . pathinfo($url)['filename'] + . '.' + . pathinfo((string) $chemin_format)['extension'], ]), ); usort(array: $formats, callback: static fn($a, $b): int => $a['taille'] <=> $b['taille']); @@ -97,8 +96,8 @@ final readonly class Resource { // Construis les balises avec les formats valides $sources = ''; foreach ($formats as $format) { - $height = $dimensions[0]; - $width = $dimensions[1]; + $height = $dimensions[0]; + $width = $dimensions[1]; $sources .= "\n"; } diff --git a/web/app/themes/haiku-atelier-2024/src/sass/base/elements/_formulaires.scss b/web/app/themes/haiku-atelier-2024/src/sass/base/elements/_formulaires.scss index 869974b1..4f01cd72 100755 --- a/web/app/themes/haiku-atelier-2024/src/sass/base/elements/_formulaires.scss +++ b/web/app/themes/haiku-atelier-2024/src/sass/base/elements/_formulaires.scss @@ -66,8 +66,8 @@ input[type="checkbox"], input[type="radio"] { transition: 0.2s background; &:checked { - color: var(--couleur-blanc); - background: var(--couleur-gris-fonce); + color: var(--couleur-noir); + background: var(--arriere-plan-points); // TODO: Utiliser un SVG plutôt qu'un « x » ? &::before { @@ -98,7 +98,7 @@ input[type="checkbox"], input[type="radio"] { @media (hover: hover) { &:hover { - background: var(--couleur-gris-fonce); + background: var(--arriere-plan-points); } } } diff --git a/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts b/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts index dc58274a..a928ba02 100644 --- a/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts @@ -1,4 +1,4 @@ -import { Console, Context, Effect, Layer, Match, pipe, Schedule, Schema, SchemaIssue } from "effect"; +import { Console, Context, Effect, Layer, Match, pipe, References, Schedule, Schema, SchemaIssue } from "effect"; import type { SchemaError } from "effect/Schema"; import type { HttpClientError, @@ -11,6 +11,7 @@ import { } from "effect/unstable/http"; import { HttpClientErrorSchema } from "effect/unstable/http/HttpClientError"; import type { CartProduct, GetProducts } from "../schemas/api.ts"; +import { Product } from "../schemas/api.ts"; import { WooCommerceCart } from "../schemas/cart.ts"; /** Le nombre maximal d'essais pour une Requête. */ @@ -52,7 +53,7 @@ const APIFetchClient = FetchHttpClient.layer.pipe( Layer.succeed( FetchHttpClient.RequestInit, { - credentials: "same-origin", + credentials: "include", headers: { Accept: "application/json", "Content-Type": "application/json", @@ -135,18 +136,22 @@ class APIClient extends Context.Service()("haikuatelier.fr/APIClient" ); const GetProducts = Effect.fn("APIClient.GetProducts")( - function*(nonce: string, authString: string, queryParams: GetProducts) { + function*(nonce: string, queryParams: GetProducts) { const request = pipe( - HttpClientRequest.get(`/wp-json/wc/store/products`), + HttpClientRequest.get(`/wp-json/wc/v3/products`), HttpClientRequest.setHeader("Nonce", nonce), - HttpClientRequest.bearerToken(authString), + // TODO: Utiliser l'environnement + HttpClientRequest.basicAuth( + "ck_ed966a2265099a6dfe9915db692cbd2450cceed6", + "cs_a046c91647af95188a3e39a736ebe02f2024e430", + ), // Le corps de la Requête a été validée en amont, on peut utiliser Unsafe. HttpClientRequest.setUrlParams(queryParams), ); const response = yield* pipe( haikuHTTPClient.execute(request), - Effect.flatMap(HttpClientResponse.schemaBodyJson(Schema.Unknown)), + Effect.flatMap(HttpClientResponse.schemaBodyJson(Schema.Array(Product))), Effect.mapError(error => matchAPIError(error)), Effect.tapError(error => printErrorAsSuccinctMessage(error)), ); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/api.ts b/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/api.ts index e3480331..69342d57 100644 --- a/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/api.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/api.ts @@ -1,5 +1,5 @@ import { Schema } from "effect"; -import { ProductId, ProductQuantity, ProductVariationAttribute } from "./product.ts"; +import { ProductId, ProductQuantity, ProductStatus, ProductVariationAttribute } from "./product.ts"; class CartProduct extends Schema.Class("CartProduct")({ id: ProductId, @@ -7,4 +7,58 @@ class CartProduct extends Schema.Class("CartProduct")({ variation: Schema.Array(ProductVariationAttribute), }) {} -export { CartProduct }; +class GetProducts extends Schema.Class("GetProducts")({ + /** L'ID de la Catégorie de Produits demandé. */ + category: Schema.Int.pipe(Schema.optional), + /** Le numéro de page demandé. */ + page: Schema.Int, + /** Le nombre de Produits par page demandé. */ + per_page: Schema.Int, + /** Le statut demandé des Produits. */ + status: ProductStatus, +}) {} + +class Product extends Schema.Class("Product")({ + attributes: Schema.Unknown, + brands: Schema.Unknown, + // TODO: Pourrait être une énumération. + catalog_visibility: Schema.String, + categories: Schema.Unknown, + description: Schema.String, + dimensions: Schema.Unknown, + featured: Schema.Boolean, + grouped_products: Schema.Unknown, + has_options: Schema.Boolean, + id: Schema.Int, + // NOTE: Non-standard, injecté dans la Réponse. + image_repos: Schema.String, + // NOTE: Non-standard, injecté dans la Réponse. + image_survol: Schema.String, + images: Schema.Unknown, + low_stock_amount: Schema.Union([Schema.Number, Schema.Null]), + menu_order: Schema.Int, + meta_data: Schema.Unknown, + name: Schema.String, + on_sale: Schema.Boolean, + parent_id: Schema.Int, + permalink: Schema.URLFromString, + price: Schema.String, + // NOTE: Non-standard, injecté dans la Réponse. + prix_maximal: Schema.String, + regular_price: Schema.String, + sale_price: Schema.String, + short_description: Schema.String, + sku: Schema.String, + slug: Schema.String, + sold_individually: Schema.Boolean, + stock_quantity: Schema.Union([Schema.Int, Schema.Null]), + // TODO: Pourrait être une énumération. + stock_status: Schema.String, + tags: Schema.Unknown, + type: Schema.Literals(["external", "grouped", "simple", "variable"]), + variations: Schema.Array(Schema.Int), + virtual: Schema.Boolean, + weight: Schema.String, +}) {} + +export { CartProduct, GetProducts, Product }; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/product.ts b/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/product.ts index 80cb0405..825adeb7 100644 --- a/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/product.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/product.ts @@ -2,6 +2,8 @@ import { Effect, Option, pipe, Schema, SchemaIssue, SchemaTransformation } from "effect"; import type { SchemaError } from "effect/Schema"; +const ProductStatus = Schema.Literals(["any", "draft", "future", "pending", "private", "publish", "trash"]); + /** Représente l'identifiant numérique unique d'un Produit. */ const ProductId = Schema.Int.pipe(Schema.brand("ProductId")).check(Schema.isGreaterThan(0)); @@ -78,6 +80,7 @@ export { ProductId, ProductQuantity, ProductQuantityFromString, + ProductStatus, ProductVariation, ProductVariationAttribute, }; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts new file mode 100644 index 00000000..5ae434cd --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts @@ -0,0 +1,17 @@ +import { Console, Layer, ManagedRuntime, pipe } from "effect"; + +import { APIClient } from "../../scripts-effect/lib/api.ts"; +import ShopPageDOM from "./service-dom.ts"; +import ShopPageElements from "./service-elements.ts"; +import ShopPageMessages from "./service-messages.ts"; + +const ShopPageRuntime = ManagedRuntime.make( + pipe( + ShopPageDOM.Live, + Layer.provideMerge(ShopPageMessages.Live), + Layer.provideMerge(ShopPageElements.Live), + Layer.provide(APIClient.Live), + Layer.tapError(error => Console.error("ProductPageRuntime", "Impossible de créer le Layer :", error)), + ), +); +export default ShopPageRuntime; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts new file mode 100644 index 00000000..6639ae12 --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts @@ -0,0 +1,174 @@ +import { + Array as FxArray, + Console, + Context, + Effect, + Layer, + Option, + pipe, + Ref, + Schema, + SchemaIssue, + Stream, + SubscriptionRef, +} from "effect"; +import { SchemaError } from "effect/Schema"; +import html from "html-template-tag"; +import { APIClient } from "../../scripts-effect/lib/api.ts"; +import { setLoadingState } from "../../scripts-effect/lib/elements.ts"; +import { GetProducts, Product } from "../../scripts-effect/schemas/api.ts"; +import { ATTRIBUT_HIDDEN, ATTRIBUT_ID_CATEGORIE_PRODUITS, ATTRIBUT_PAGE } from "../constantes/dom.ts"; +import ShopPageElements from "./service-elements.ts"; +import ShopPageMessages from "./service-messages.ts"; + +/** Le nombre de Produits à afficher par « page ». */ +const PRODUCTS_PER_PAGE = 18; + +/** Forme attendue des données injectées dans la page sous forme de JSON. */ +class PageStates extends Schema.Opaque()( + Schema.Struct({ + authString: Schema.NonEmptyString, + nonce: Schema.NonEmptyString, + }), +) {} + +/** Représente une Erreur liée à un état de page invalide ou incohérent empêchant la poursuite des interactions/de la navigation. */ +class InvalidShopPageStateError + extends Schema.TaggedErrorClass()("InvalidShopPageStateError", { + cause: Schema.String, + }) +{ + /** Créé une `InvalidShopPageStateError` depuis une `SchemaError` levée suite à une validation. */ + static readonly fromSchemaError = (schemaError: SchemaError): InvalidShopPageStateError => + new InvalidShopPageStateError({ + cause: SchemaIssue.makeFormatterDefault()(schemaError.issue), + }); +} + +class ShopPageDOM extends Context.Service()("haikuatelier.fr/Shop/ShopPageDOM", { + make: Effect.gen(function*() { + const { PageStatesRawJson, ProductsGrid, ShowMoreButton } = yield* ShopPageElements; + const { ShowMoreButtonText } = yield* ShopPageMessages; + const API = yield* APIClient; + + const { authString, nonce } = yield* pipe( + PageStatesRawJson.textContent, + (textContent: string) => + Schema.decodeUnknownEffect(Schema.fromJsonString(PageStates))(textContent, { errors: "all" }), + Effect.mapError(InvalidShopPageStateError.fromSchemaError), + ); + + /** ID de la Catégorie des Produits de la Page, si la Page courante est une Archive. */ + const ProductsCategoryId = yield* pipe( + ProductsGrid.getAttribute(ATTRIBUT_ID_CATEGORIE_PRODUITS), + Number, + Option.fromNullishOr, + Ref.make, + ); + + // TODO: Créer une SubscriptionRef mettant à jour le DOM au changement de valeur. + const PageNumber = yield* Ref.make(1); + + /** + * Créé le `DOM` d'une Carte de Produit sous forme de `
`. + */ + const createProductDOM = (product: Product): HTMLElement => { + const article = document.createElement("article"); + article.classList.add("produit"); + article.innerHTML = html`
+ + + $${product.image_repos} + + + + $${product.image_survol} + + + +
+

+ ${product.name} +

+

+ ${product.prix_maximal}€ +

+
+
+ `; + return article; + }; + + /** + * Créé le `DOM` des Cartes d'une nouvelle page de Produits sous forme d'un `DocumentFragment`. + */ + const createNewPageDOM = (products: ReadonlyArray) => { + const fragment: DocumentFragment = document.createDocumentFragment(); + + // Ajoute le HTML des Produits au fragment. + pipe( + FxArray.take(products, PRODUCTS_PER_PAGE), + FxArray.forEach(product => { + const productHTML = createProductDOM(product); + fragment.append(productHTML); + }), + ); + + return fragment; + }; + + const onMoreProductsWantedHandler = Effect.fn("onMoreProductsWantedHandler")(function*() { + yield* Console.debug("onMoreProductsWantedHandler"); + + /** Le numéro de page souhaitée. */ + const newPageNumber = yield* Ref.updateAndGet(PageNumber, pageNumber => pageNumber + 1); + /** L'ID de la Catégorie de Produits affichée dans la page si elle existe. */ + const categoryId = pipe(yield* Ref.get(ProductsCategoryId), Option.getOrUndefined); + + const requestBody = yield* GetProducts.makeEffect({ + page: newPageNumber, + per_page: PRODUCTS_PER_PAGE, + status: "publish", + ...(categoryId && { category: categoryId }), + }); + + // Désactive les interactions et affiche un texte de chargement le temps de la requête. + yield* setLoadingState(ShowMoreButton, true); + yield* SubscriptionRef.set(ShowMoreButtonText, "Getting Products..."); + + const newProducts = yield* API.GetProducts(nonce, requestBody); + yield* Console.debug("onMoreProductsWantedHandler", newProducts); + + // Rétablis le texte du Bouton et réactive les interactions. + yield* SubscriptionRef.set(ShowMoreButtonText, "Show more"); + yield* setLoadingState(ShowMoreButton, false); + + // Cache le bouton s'il y a moins de Produits disponibles que PRODUCTS_PER_PAGE (que l'on est donc à la dernière page). + ShowMoreButton.toggleAttribute(ATTRIBUT_HIDDEN, newProducts.length < PRODUCTS_PER_PAGE); + + // Ajoute les nouveaux Produits dans le DOM. + const newProductsFragment = createNewPageDOM(newProducts); + ProductsGrid.append(newProductsFragment); + ProductsGrid.setAttribute(ATTRIBUT_PAGE, String(newPageNumber)); + }); + + /** + * Initialise l'écouteur d'événements de clic sur le bouton de chargement d'une nouvelle page de Produits (« Show more »). + */ + const initMoreProductsOnButtonClick = Effect.fn("initMoreProductsOnButtonClick")(function*() { + return yield* pipe( + Stream.fromEventListener(ShowMoreButton, "click"), + Stream.tap(onMoreProductsWantedHandler), + Stream.runDrain, + ); + }); + + return { + ProductsCategoryId, + initMoreProductsOnButtonClick, + }; + }), +}) { + static readonly Live = Layer.effect(this, this.make); +} +export default ShopPageDOM; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-elements.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-elements.ts new file mode 100644 index 00000000..208f4dbf --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-elements.ts @@ -0,0 +1,26 @@ +import { Context, Effect, Layer } from "effect"; +import { getFirstSelectorFromDocument } from "../../scripts-effect/lib/dom.ts"; +import { IncoherentDOMError } from "../page-produit/errors.ts"; + +class ShopPageElements extends Context.Service()("haikuatelier.fr/Shop/ShopPageElements", { + make: Effect.gen(function*() { + const PageStatesRawJson = yield* getFirstSelectorFromDocument("#page-states"); + + /** Le Bouton « Show more » pour afficher plus de Produits à la suite de la Grille. */ + const ShowMoreButton = yield* getFirstSelectorFromDocument( + "#page-boutique #bouton-plus-de-produits", + ); + + /** Le conteneur de la Grille des Produits. */ + const ProductsGrid = yield* getFirstSelectorFromDocument("#page-boutique .grille-produits"); + + return { + PageStatesRawJson, + ProductsGrid, + ShowMoreButton, + }; + }).pipe(Effect.mapErrorEager(IncoherentDOMError.fromNoSuchElementError)), +}) { + static readonly Live = Layer.effect(this, this.make); +} +export default ShopPageElements; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-messages.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-messages.ts new file mode 100644 index 00000000..dcb27d02 --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-messages.ts @@ -0,0 +1,29 @@ +import { Context, Effect, Layer, pipe, Stream, SubscriptionRef } from "effect"; + +import ShopPageElements from "./service-elements.ts"; + +class ShopPageMessages extends Context.Service()("haikuatelier.fr/Shop/Messages", { + make: Effect.gen(function*() { + const { ShowMoreButton } = yield* ShopPageElements; + + const ShowMoreButtonText = yield* SubscriptionRef.make("Show more"); + // Const ShowMoreErrorText = yield* SubscriptionRef.make>(Option.none()); + + const initShowMoreButtonUpdates = Effect.fn("initShowMoreButtonUpdates")(function*() { + return yield* pipe( + SubscriptionRef.changes(ShowMoreButtonText), + Stream.tap(newText => { + ShowMoreButton.textContent = newText; + return Effect.succeed(newText); + }), + Stream.runDrain, + ); + }); + + return { ShowMoreButtonText, initShowMoreButtonUpdates }; + }), +}) { + static readonly Live = Layer.effect(this, this.make); +} + +export default ShopPageMessages; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts index 5f8b9d50..9d516e2d 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts @@ -2,75 +2,24 @@ * Scripts pour les fonctionnalités de la page Boutique. */ -import { pipe } from "@mobily/ts-belt"; -import { tap } from "@mobily/ts-belt/Function"; -import { EitherAsync } from "purify-ts"; -import { match, P } from "ts-pattern"; -import { ValiError } from "valibot"; - -import type { APIFetchErrors } from "./lib/types/api/erreurs"; -import type { WCV3Products, WCV3ProductsArgs } from "./lib/types/api/v3/products.ts"; -import type { GenericPageState } from "./lib/types/pages"; - -import { ROUTE_API_NOUVELLE_PRODUCTS } from "./constantes/api.ts"; -import { PRODUCT_STATUTES } from "./constantes/api/products.ts"; -import { - ATTRIBUT_CHARGEMENT, - ATTRIBUT_DESACTIVE, - ATTRIBUT_HIDDEN, - ATTRIBUT_ID_CATEGORIE_PRODUITS, - ATTRIBUT_PAGE, - DOM_BOUTON_PLUS_PRODUITS, - DOM_GRILLE_PRODUITS, -} from "./constantes/dom.ts"; -import { lanceAnimationCycleLoading } from "./lib/animations.ts"; -import { html, mustGetEleInDocument } from "./lib/dom.ts"; -import { BadRequestError, reporteErreur, ServerError } from "./lib/erreurs.ts"; -import { getBackendAvecParametresUrl, newPartialResponse } from "./lib/reseau.ts"; -import { WCV3ProductsArgsSchema, WCV3ProductsSchema } from "./lib/schemas/api/v3/products.ts"; -import { safeSchemaParse } from "./lib/validation.ts"; - -type APIProductsErrors = - | APIFetchErrors - | ValiError - | ValiError; - -// @ts-expect-error -- États injectés par le modèle PHP -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- États injectés par le modèle PHP -const ETATS_PAGE: GenericPageState = _etats; - -// Numéros magiques -const PRODUCTS_PER_PAGE = 12; - -// Éléments d'intérêt -const E = { - BOUTON_PLUS_DE_PRODUITS: mustGetEleInDocument(DOM_BOUTON_PLUS_PRODUITS), - GRILLE_PRODUITS: mustGetEleInDocument(DOM_GRILLE_PRODUITS), -}; - -/** - * TODO - */ -const initialisePageBoutique = (): void => { - /** ID de la Catégorie de Produits si la Page courante est l'Archive d'une Catégorie. */ - const idCategorieProduits: null | string = E.GRILLE_PRODUITS.getAttribute(ATTRIBUT_ID_CATEGORIE_PRODUITS); - - E.BOUTON_PLUS_DE_PRODUITS.addEventListener("click", (): void => { - /** Le numéro de page demandée par l'Utilisateur. */ - const nouveauNumeroPage = Number(E.GRILLE_PRODUITS.getAttribute(ATTRIBUT_PAGE)) + 1; - /** Les arguments passés à la requête auprès Backend pour la nouvelle page de Produits. */ - const args: WCV3ProductsArgs = { - page: nouveauNumeroPage, - per_page: PRODUCTS_PER_PAGE, - status: PRODUCT_STATUTES.PUBLISH, - // Ajoute conditionnellement la Catégorie de Produits - ...(idCategorieProduits && { category: idCategorieProduits }), - }; - - undefined; - }); -}; +import { Console, Effect } from "effect"; +import ShopPageRuntime from "./page-boutique/runtime.ts"; +import ShopPageDOM from "./page-boutique/service-dom.ts"; +import ShopPageElements from "./page-boutique/service-elements.ts"; +import ShopPageMessages from "./page-boutique/service-messages.ts"; document.addEventListener("DOMContentLoaded", (): void => { - initialisePageBoutique(); + console.debug("scripts-page-boutique"); + // initialisePageBoutique(); + ShopPageRuntime.runFork(Effect.gen(function*() { + const Elements = yield* ShopPageElements; + const DOM = yield* ShopPageDOM; + const Messages = yield* ShopPageMessages; + + yield* Effect.all([DOM.initLoadMoreProductsOnButtonClick(), Messages.initShowMoreButtonUpdates()], { + concurrency: "unbounded", + }).pipe(Effect.tapCause(Console.error)); + + console.debug(Elements.ProductsGrid); + })); }); diff --git a/web/app/themes/haiku-atelier-2024/taxonomy-product_cat.php b/web/app/themes/haiku-atelier-2024/taxonomy-product_cat.php index a589bd00..fde37cdd 100755 --- a/web/app/themes/haiku-atelier-2024/taxonomy-product_cat.php +++ b/web/app/themes/haiku-atelier-2024/taxonomy-product_cat.php @@ -26,7 +26,7 @@ use function wc_get_products; use function wp_create_nonce; use function wp_json_encode; -$context = Timber::context(); +$context = Timber::context(); $templates = ['boutique.twig']; /** @var WP_Term La Catégorie affichée. */ @@ -35,10 +35,10 @@ $current_term = get_queried_object(); /** @var list Les Produits de la Catégorie affichée. */ $products = wc_get_products([ 'category' => [$current_term->slug], - 'limit' => 12, - 'order' => 'DESC', - 'orderby' => 'date', - 'status' => 'publish', + 'limit' => 12, + 'order' => 'DESC', + 'orderby' => 'date', + 'status' => 'publish', ]) |> function (/** @var list|stdClass */ mixed $products): array { assert(is_array($products), 'Les Produits de la Catégorie doivent être un tableau.'); @@ -50,12 +50,12 @@ $products = wc_get_products([ Product::from_wc_product(...), )); -$context['products'] = $products; +$context['products'] = $products; $context['category_id'] = $current_term->term_id; // Injecte les états initiaux des données du Produit sous forme de JSON dans le contexte. $page_states = [ - 'nonce' => wp_create_nonce('wc_store_api'), + 'nonce' => wp_create_nonce('wc_store_api'), 'authString' => base64_encode( Config::get('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . Config::get('WOOCOMMERCE_API_CONSUMER_SECRET'), ), @@ -67,14 +67,14 @@ $context['page_states'] = $page_states; add_action('wp_enqueue_scripts', function (): void { Resource::enqueue_style_file( handle: 'haiku-atelier-2024-styles-page-boutique', - path: '/assets/css/pages/page-boutique.css', + path : '/assets/css/pages/page-boutique.css', ); Resource::enqueue_script_module_file( - id: 'haiku-atelier-2024-scripts-page-boutique', + id : 'haiku-atelier-2024-scripts-page-boutique', path: '/assets/js/scripts-page-boutique.js', ); Resource::enqueue_script_module_file( - id: 'haiku-atelier-2024-scripts-menu-categories', + id : 'haiku-atelier-2024-scripts-menu-categories', path: '/assets/js/scripts-menu-categories.js', ); }); diff --git a/web/app/themes/haiku-atelier-2024/woocommerce/emails/customer-completed-order.php b/web/app/themes/haiku-atelier-2024/woocommerce/emails/customer-completed-order.php index 61fbe911..923ef72d 100755 --- a/web/app/themes/haiku-atelier-2024/woocommerce/emails/customer-completed-order.php +++ b/web/app/themes/haiku-atelier-2024/woocommerce/emails/customer-completed-order.php @@ -20,7 +20,7 @@ Timber::init(); // Sélectionne le répertoire contenant les modèles Twig Timber::$dirname = ['views']; -$context = Timber::context(); +$context = Timber::context(); $templates = ['email-commande-envoyee.twig']; /** @var Order $commande La Commande issue du contexte contenu dans la variable $order. */ @@ -30,7 +30,7 @@ $commande = $order; $date = new Carbon($commande->get_date_created()); $email = [ - 'commande' => ['date' => $date->toDateString(), 'id' => $commande->get_id()], + 'commande' => ['date' => $date->toDateString(), 'id' => $commande->get_id()], 'livraison' => [ 'transporteur' => Str::of($commande->get_shipping_method())->replace(' (Free)', ''), 'numero_suivi' => blank($commande->get_meta('tracking_number')) diff --git a/web/app/themes/haiku-atelier-2024/woocommerce/emails/customer-invoice.php b/web/app/themes/haiku-atelier-2024/woocommerce/emails/customer-invoice.php index cbdcd419..27697389 100755 --- a/web/app/themes/haiku-atelier-2024/woocommerce/emails/customer-invoice.php +++ b/web/app/themes/haiku-atelier-2024/woocommerce/emails/customer-invoice.php @@ -21,7 +21,7 @@ Timber::init(); // Sélectionne le répertoire contenant les modèles Twig Timber::$dirname = ['views']; -$context = Timber::context(); +$context = Timber::context(); $templates = ['email-base.twig']; /** @var Order $commande La Commande issue du contexte contenu dans la variable $order. */ @@ -31,14 +31,17 @@ $commande = $order; $date = new Carbon($commande->get_date_created()); $email = [ - 'adresses' => ['facturation' => $commande->get_address('billing'), 'livraison' => $commande->get_address('shipping')], - 'commande' => ['date' => $date->toDateString(), 'id' => $commande->get_id()], + 'adresses' => [ + 'facturation' => $commande->get_address('billing'), + 'livraison' => $commande->get_address('shipping'), + ], + 'commande' => ['date' => $date->toDateString(), 'id' => $commande->get_id()], 'livraison' => [ - 'methode' => $commande->get_shipping_method(), + 'methode' => $commande->get_shipping_method(), 'numero_suivi' => $commande->get_meta('tracking_number'), ], - 'paiement' => ['methode' => ''], - 'produits' => collect($commande->get_items())->map(static function (WC_Order_Item_Product $article) { + 'paiement' => ['methode' => ''], + 'produits' => collect($commande->get_items())->map(static function (WC_Order_Item_Product $article) { $produit = $article->get_product(); if (is_bool($produit) || $produit === null) { @@ -47,31 +50,31 @@ $email = [ return [ // Récupère l'Attribut d'un Produit variable ou renvoie un tableau vide - 'attribut' => $produit->is_type('variable') + 'attribut' => $produit->is_type('variable') ? collect($produit->get_attributes()) ->mapWithKeys(static fn($_atr, $cle): array => [ - 'nom' => Str::lower(wc_attribute_label($cle, $produit)), + 'nom' => Str::lower(wc_attribute_label($cle, $produit)), 'valeur' => $produit->get_attribute($cle), ]) ->toArray() : [], - 'lien' => $produit->get_permalink(), - 'nom' => $produit->get_title(), + 'lien' => $produit->get_permalink(), + 'nom' => $produit->get_title(), 'prix_total' => $article->get_total(), - 'quantite' => $article->get_quantity(), + 'quantite' => $article->get_quantity(), ]; }), - 'totaux' => [ + 'totaux' => [ 'sous_total_livraison' => '0' === $commande->get_shipping_total() ? 'Free' : $commande->get_shipping_total() . '€', - 'sous_total_produits' => $commande->get_subtotal() . '€', + 'sous_total_produits' => $commande->get_subtotal() . '€', 'sous_total_reduction' => '0.00' === $commande->get_discount_total() ? '0' : Number::format((float) $commande->get_discount_total(), maxPrecision: 2) . '€', - 'total' => Number::format((float) $commande->get_total(), maxPrecision: 2) . '€', + 'total' => Number::format((float) $commande->get_total(), maxPrecision: 2) . '€', ], ]; // Transforme les codes de pays en noms de pays -$email['adresses']['livraison']['country'] = WC()->countries->countries[$commande->get_shipping_country()]; +$email['adresses']['livraison']['country'] = WC()->countries->countries[$commande->get_shipping_country()]; $email['adresses']['facturation']['country'] = WC()->countries->countries[$commande->get_billing_country()]; $context['commande'] = $email; diff --git a/web/app/themes/haiku-atelier-2024/woocommerce/emails/customer-processing-order.php b/web/app/themes/haiku-atelier-2024/woocommerce/emails/customer-processing-order.php index 830883aa..1b093035 100755 --- a/web/app/themes/haiku-atelier-2024/woocommerce/emails/customer-processing-order.php +++ b/web/app/themes/haiku-atelier-2024/woocommerce/emails/customer-processing-order.php @@ -21,7 +21,7 @@ Timber::init(); // Sélectionne le répertoire contenant les modèles Twig Timber::$dirname = ['views']; -$context = Timber::context(); +$context = Timber::context(); $templates = ['email-commande-recue.twig']; /** @var Order $commande La Commande issue du contexte contenu dans la variable $order. */ @@ -43,31 +43,31 @@ $email = [ return [ // Récupère l'Attribut d'un Produit variable ou renvoie un tableau vide - 'attribut' => $article->is_type('variable') + 'attribut' => $article->is_type('variable') ? collect($produit->get_attributes()) ->mapWithKeys(static fn($_atr, $cle): array => [ - 'nom' => Str::lower(wc_attribute_label($cle, $produit)), + 'nom' => Str::lower(wc_attribute_label($cle, $produit)), 'valeur' => $produit->get_attribute($cle), ]) ->toArray() : [], - 'lien' => $produit->get_permalink(), - 'nom' => $produit->get_title(), + 'lien' => $produit->get_permalink(), + 'nom' => $produit->get_title(), 'prix_total' => $article->get_total(), - 'quantite' => $article->get_quantity(), + 'quantite' => $article->get_quantity(), ]; }), - 'totaux' => [ + 'totaux' => [ 'sous_total_livraison' => '0' === $commande->get_shipping_total() ? 'Free' : $commande->get_shipping_total() . '€', - 'sous_total_produits' => $commande->get_subtotal() . '€', + 'sous_total_produits' => $commande->get_subtotal() . '€', 'sous_total_reduction' => '0.00' === $commande->get_discount_total() ? '0' : Number::format((float) $commande->get_discount_total(), maxPrecision: 2) . '€', - 'total' => Number::format((float) $commande->get_total(), maxPrecision: 2) . '€', + 'total' => Number::format((float) $commande->get_total(), maxPrecision: 2) . '€', ], ]; // Transforme les codes de pays en noms de pays -$email['adresses']['livraison']['country'] = WC()->countries->countries[$commande->get_shipping_country()]; +$email['adresses']['livraison']['country'] = WC()->countries->countries[$commande->get_shipping_country()]; $email['adresses']['facturation']['country'] = WC()->countries->countries[$commande->get_billing_country()]; $context['commande'] = $email;