From c08717195ac049b5799c7742a647a38a563bf62b Mon Sep 17 00:00:00 2001 From: gcch Date: Wed, 29 Apr 2026 10:45:49 +0200 Subject: [PATCH 01/17] ref(boutique) wip scripts sous forme Effect --- .../src/scripts-effect/lib/api.ts | 17 +- .../src/scripts-effect/schemas/api.ts | 58 ++++++- .../src/scripts-effect/schemas/product.ts | 3 + .../src/scripts/page-boutique/runtime.ts | 17 ++ .../src/scripts/page-boutique/service-dom.ts | 163 ++++++++++++++++++ .../scripts/page-boutique/service-elements.ts | 26 +++ .../scripts/page-boutique/service-messages.ts | 29 ++++ .../src/scripts/scripts-page-boutique.ts | 87 ++-------- 8 files changed, 323 insertions(+), 77 deletions(-) create mode 100644 web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts create mode 100644 web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts create mode 100644 web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-elements.ts create mode 100644 web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-messages.ts 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..9903664c 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_eded693107df0dbc19dab937e0c71325db810a4a", + "cs_a68c0f3e711c4a21be51495d09e6fe807649bbfb", + ), // 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..9a404aea --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts @@ -0,0 +1,163 @@ +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); + + 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; + }; + const createNewPageDOM = (products: ReadonlyArray) => { + const fragment: DocumentFragment = document.createDocumentFragment(); + + // Ajoute le HTML des cartes des Produits au fragment. + pipe( + FxArray.take(products, PRODUCTS_PER_PAGE), + FxArray.forEach(product => { + const productHTML = createProductDOM(product); + fragment.append(productHTML); + }), + ); + + return fragment; + }; + + const onMoreProductedWantedHandler = Effect.fn("onMoreProductedWantedHandler")(function*() { + yield* Console.debug("onMoreProductedWantedHandler"); + + /** 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("onMoreProductedWantedHandler", 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. + ProductsGrid.append(fragment); + ProductsGrid.setAttribute(ATTRIBUT_PAGE, String(newPageNumber)); + }); + + const initLoadMoreProductsOnButtonClick = Effect.fn("initLoadMoreProductsOnButtonClick")(function*() { + return yield* pipe( + Stream.fromEventListener(ShowMoreButton, "click"), + Stream.tap(onMoreProductedWantedHandler), + Stream.runDrain, + ); + }); + + return { + ProductsCategoryId, + initLoadMoreProductsOnButtonClick, + }; + }), +}) { + 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..d3b9efc9 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.tapError(Console.error)); + + console.debug(Elements.ProductsGrid); + })); }); From b643443b57b55c97361a662aaf4f09d57b9428da Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 02/17] =?UTF-8?q?corv=C3=A9e(deps)=20met=20=C3=A0=20jour?= =?UTF-8?q?=20les=20d=C3=A9pendances?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aube-lock.yaml | 88 +++++++++++++++++++++++++------------------------- package.json | 2 +- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/aube-lock.yaml b/aube-lock.yaml index f12c431a..6720acf8 100644 --- a/aube-lock.yaml +++ b/aube-lock.yaml @@ -13,7 +13,7 @@ importers: version: 4.0.0-rc.5 '@sentry/browser': specifier: ^10.50.0 - version: 10.50.0 + version: 10.51.0 a11y-dialog: specifier: ^8.1.5 version: 8.1.5 @@ -52,8 +52,8 @@ importers: specifier: ^0.85.1 version: 0.85.1 '@effect/tsgo': - specifier: 0.5.1 - version: 0.5.1 + specifier: ^0.5.1 + 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 @@ -68,7 +68,7 @@ importers: version: 1.59.1 '@sentry/core': specifier: ^10.50.0 - version: 10.50.0 + version: 10.51.0 '@types/bun': specifier: ^1.3.13 version: 1.3.13 @@ -116,7 +116,7 @@ importers: version: 2.6.1 knip: specifier: ^6.8.0 - version: 6.8.0 + version: 6.9.0 lightningcss: specifier: ^1.32.0 version: 1.32.0 @@ -740,15 +740,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 +969,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': @@ -2164,8 +2164,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.9.0: + resolution: {integrity: sha512-2GLjxteBwmsSA3Z5sJZpPDaNPBIMnlm4/9Nx4CZadEK7YccJZ2/4kwKgPWhVYEqxhwhD0WO4txWXNGTO/Odkkg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -3830,11 +3830,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: @@ -4007,33 +4007,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': {} @@ -5310,7 +5310,7 @@ snapshots: kind-of@6.0.3: {} - knip@6.8.0: + knip@6.9.0: dependencies: fdir: 6.5.0(picomatch@4.0.4) formatly: 0.3.0 diff --git a/package.json b/package.json index 5e0a9dd9..45806203 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ }, "devDependencies": { "@effect/language-service": "^0.85.1", - "@effect/tsgo": "0.5.1", + "@effect/tsgo": "^0.5.1", "@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", From de0a175624dded0980f97ead29d17e356985a2c0 Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 03/17] =?UTF-8?q?corv=C3=A9e(deps)=20installe=20html-templ?= =?UTF-8?q?ate-tag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .zed/settings.json | 1 + aube-lock.yaml | 21 +++++++++++++++++++++ package.json | 1 + 3 files changed, 23 insertions(+) diff --git a/.zed/settings.json b/.zed/settings.json index c4e389e2..8ba0003e 100644 --- a/.zed/settings.json +++ b/.zed/settings.json @@ -11,6 +11,7 @@ "!oxlint", "!prettier", "!tailwindcss-language-server", + "!tsgo", "!vtsls", "..." ], diff --git a/aube-lock.yaml b/aube-lock.yaml index 6720acf8..64c19c98 100644 --- a/aube-lock.yaml +++ b/aube-lock.yaml @@ -20,6 +20,9 @@ importers: 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 @@ -1928,13 +1931,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'} @@ -5102,10 +5114,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: {} diff --git a/package.json b/package.json index 45806203..507f7550 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@sentry/browser": "^10.50.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", From 50f2b67bc45309b57541b22634618de954f1960e Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 04/17] ref(styles) wip harmonisation des Boutons --- web/app/themes/haiku-atelier-2024/assets/css/main.css | 6 +++--- web/app/themes/haiku-atelier-2024/assets/css/main.min.css | 2 +- .../src/sass/base/elements/_formulaires.scss | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) 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/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); } } } From 53d71ea18363ad515813db84def51629ead9c488 Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 05/17] =?UTF-8?q?ref(justfile)=20utilise=20watchexec=20pou?= =?UTF-8?q?r=20la=20t=C3=A2che=20de=20compilation=20JS=20=C3=A0=20la=20m?= =?UTF-8?q?=C3=A0j=20des=20fichiers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- justfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/justfile b/justfile index c9fe13a2..5ee66b34 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é')] From c61e63117276d8b7a0de33290ee3c88e6f105d52 Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 06/17] ref(env) wip --- config/environments/development.php | 5 +++ config/environments/production.php | 5 +++ config/environments/staging.php | 5 +++ .../haiku-atelier-2024/archive-product.php | 8 +---- .../src/inc/FonctionnalitesWooCommerce.php | 31 ++++++++++--------- 5 files changed, 33 insertions(+), 21 deletions(-) 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/web/app/themes/haiku-atelier-2024/archive-product.php b/web/app/themes/haiku-atelier-2024/archive-product.php index 2a97be56..a2b49c0f 100755 --- a/web/app/themes/haiku-atelier-2024/archive-product.php +++ b/web/app/themes/haiku-atelier-2024/archive-product.php @@ -17,7 +17,6 @@ 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; @@ -33,12 +32,7 @@ $products = array_map(callback: Product::from_wc_product(...), array: $wc_produc $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; 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..adb6c205 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)) { @@ -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'); From 56af75707f9531089faa4fc14f486042f04e7573 Mon Sep 17 00:00:00 2001 From: gcch Date: Wed, 29 Apr 2026 10:45:49 +0200 Subject: [PATCH 07/17] ref(boutique) wip scripts sous forme Effect --- .../src/scripts-effect/lib/api.ts | 17 +- .../src/scripts-effect/schemas/api.ts | 58 +++++- .../src/scripts-effect/schemas/product.ts | 3 + .../src/scripts/page-boutique/runtime.ts | 17 ++ .../src/scripts/page-boutique/service-dom.ts | 174 ++++++++++++++++++ .../scripts/page-boutique/service-elements.ts | 26 +++ .../scripts/page-boutique/service-messages.ts | 29 +++ .../src/scripts/scripts-page-boutique.ts | 87 ++------- 8 files changed, 334 insertions(+), 77 deletions(-) create mode 100644 web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts create mode 100644 web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts create mode 100644 web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-elements.ts create mode 100644 web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-messages.ts 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); + })); }); From 2aa8d6880c0bcf965128c0895a8c2442a6d29da4 Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 08/17] =?UTF-8?q?corv=C3=A9e(deps)=20met=20=C3=A0=20jour?= =?UTF-8?q?=20les=20d=C3=A9pendances?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aube-lock.yaml | 267 +++++++++++++++++++++++++------------------------ composer.json | 38 ++----- composer.lock | 79 +++++++-------- package.json | 14 +-- 4 files changed, 193 insertions(+), 205 deletions(-) diff --git a/aube-lock.yaml b/aube-lock.yaml index f12c431a..122761db 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,8 +15,8 @@ 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 @@ -52,8 +55,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 +70,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 +79,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 +94,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 +182,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 +743,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 +972,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 +1204,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 +1691,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 +1872,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'} @@ -2164,8 +2171,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 +3837,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 +3853,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 +3874,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 +3887,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 +4014,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 +4086,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 +4127,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 +4152,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 +4234,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 +4717,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 +4753,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 +4763,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 +4773,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 +4787,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 +4809,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 +4847,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 +5057,8 @@ snapshots: globals@17.5.0: {} + globals@17.6.0: {} + globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -5199,10 +5208,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 +5319,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 +6288,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/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/package.json b/package.json index 5e0a9dd9..07d1ce4c 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "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", "lit-html": "^3.3.2", @@ -23,28 +23,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", From 740caa46a660887c34a780916ed41e08e6605d39 Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 09/17] =?UTF-8?q?corv=C3=A9e(deps)=20installe=20html-templ?= =?UTF-8?q?ate-tag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .zed/settings.json | 1 + aube-lock.yaml | 21 +++++++++++++++++++++ package.json | 1 + 3 files changed, 23 insertions(+) diff --git a/.zed/settings.json b/.zed/settings.json index c4e389e2..8ba0003e 100644 --- a/.zed/settings.json +++ b/.zed/settings.json @@ -11,6 +11,7 @@ "!oxlint", "!prettier", "!tailwindcss-language-server", + "!tsgo", "!vtsls", "..." ], diff --git a/aube-lock.yaml b/aube-lock.yaml index 122761db..3809c4e0 100644 --- a/aube-lock.yaml +++ b/aube-lock.yaml @@ -23,6 +23,9 @@ importers: 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 @@ -1935,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'} @@ -5111,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: {} diff --git a/package.json b/package.json index 07d1ce4c..cf80f947 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@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", From b54a4b64b284a703fe037907d3010f539ed9af18 Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 10/17] ref(styles) wip harmonisation des Boutons --- web/app/themes/haiku-atelier-2024/assets/css/main.css | 6 +++--- web/app/themes/haiku-atelier-2024/assets/css/main.min.css | 2 +- .../src/sass/base/elements/_formulaires.scss | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) 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/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); } } } From 4c4528c77091a4bd88a9e6cab99415199d94532a Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 11/17] =?UTF-8?q?ref(justfile)=20utilise=20watchexec=20pou?= =?UTF-8?q?r=20la=20t=C3=A2che=20de=20compilation=20JS=20=C3=A0=20la=20m?= =?UTF-8?q?=C3=A0j=20des=20fichiers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- justfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/justfile b/justfile index c9fe13a2..5ee66b34 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é')] From f986f91f81f7f6aace8cab493cd3a1289576f790 Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 12/17] ref(env) wip --- config/environments/development.php | 5 +++ config/environments/production.php | 5 +++ config/environments/staging.php | 5 +++ .../haiku-atelier-2024/archive-product.php | 8 +---- .../src/inc/FonctionnalitesWooCommerce.php | 31 ++++++++++--------- 5 files changed, 33 insertions(+), 21 deletions(-) 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/web/app/themes/haiku-atelier-2024/archive-product.php b/web/app/themes/haiku-atelier-2024/archive-product.php index 2a97be56..a2b49c0f 100755 --- a/web/app/themes/haiku-atelier-2024/archive-product.php +++ b/web/app/themes/haiku-atelier-2024/archive-product.php @@ -17,7 +17,6 @@ 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; @@ -33,12 +32,7 @@ $products = array_map(callback: Product::from_wc_product(...), array: $wc_produc $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; 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..adb6c205 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)) { @@ -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'); From 1455d81b3b4ac1c7a29ae6c8d77d141057720386 Mon Sep 17 00:00:00 2001 From: gcch Date: Sat, 2 May 2026 10:31:24 +0200 Subject: [PATCH 13/17] =?UTF-8?q?corv=C3=A9e(formatage)=20m=C3=A0j=20de=20?= =?UTF-8?q?la=20configuration=20Mago?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .php-cs-fixer.dist.php | 328 +-- mago-schema.json | 1755 ++++++++++------- mago.toml | 1 + scripts/remove-scaled-images.php | 10 +- web/app/themes/haiku-atelier-2024/404.php | 4 +- .../haiku-atelier-2024/archive-product.php | 10 +- .../themes/haiku-atelier-2024/front-page.php | 6 +- .../themes/haiku-atelier-2024/functions.php | 70 +- web/app/themes/haiku-atelier-2024/index.php | 2 +- .../themes/haiku-atelier-2024/page-about.php | 6 +- .../themes/haiku-atelier-2024/page-cart.php | 56 +- .../haiku-atelier-2024/page-checkout.php | 38 +- .../haiku-atelier-2024/page-contact.php | 4 +- .../haiku-atelier-2024/page-failed-order.php | 4 +- .../page-successful-order.php | 26 +- .../page-terms-and-conditions.php | 4 +- .../haiku-atelier-2024/single-product.php | 22 +- .../haiku-atelier-2024/src/StarterSite.php | 45 +- .../src/inc/ChampsPersonnalises.php | 6 +- .../src/inc/ControlesPersonnalises.php | 8 +- .../src/inc/Data/Attribute.php | 4 +- .../src/inc/Data/AttributeOption.php | 4 +- .../haiku-atelier-2024/src/inc/Data/Cart.php | 4 +- .../src/inc/Data/Product.php | 75 +- .../src/inc/Data/ProductVariation.php | 6 +- .../src/inc/Fonctionnalites.php | 2 +- .../src/inc/FonctionnalitesWooCommerce.php | 8 +- .../haiku-atelier-2024/src/inc/Taxonomies.php | 30 +- .../src/inc/WP/Resource.php | 29 +- .../taxonomy-product_cat.php | 20 +- .../emails/customer-completed-order.php | 4 +- .../woocommerce/emails/customer-invoice.php | 33 +- .../emails/customer-processing-order.php | 20 +- 33 files changed, 1453 insertions(+), 1191 deletions(-) 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/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/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/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 a2b49c0f..5dff6690 100755 --- a/web/app/themes/haiku-atelier-2024/archive-product.php +++ b/web/app/themes/haiku-atelier-2024/archive-product.php @@ -22,13 +22,13 @@ 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. @@ -40,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/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..890ced30 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]; 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 adb6c205..21bed7d8 100755 --- a/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php @@ -143,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], @@ -157,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], 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/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; From 626ae51247c7a11626bf797fe93a4ab2c6175afe Mon Sep 17 00:00:00 2001 From: gcch Date: Sat, 2 May 2026 13:19:47 +0200 Subject: [PATCH 14/17] =?UTF-8?q?fix(sitemaps)=20d=C3=A9sactive=20la=20g?= =?UTF-8?q?=C3=A9n=C3=A9ration=20WP=20des=20Sitemaps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/app/themes/haiku-atelier-2024/src/inc/Fonctionnalites.php | 3 +++ 1 file changed, 3 insertions(+) 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 890ced30..4f09e84a 100755 --- a/web/app/themes/haiku-atelier-2024/src/inc/Fonctionnalites.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/Fonctionnalites.php @@ -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(...)); From ea0dee406ee6f84a9c5b4af5927f59a41c8b4d30 Mon Sep 17 00:00:00 2001 From: gcch Date: Sat, 2 May 2026 14:56:49 +0200 Subject: [PATCH 15/17] =?UTF-8?q?corv=C3=A9e(phpactor)=20met=20=C3=A0=20jo?= =?UTF-8?q?ur=20phpactor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .phpactor.json | 6 ---- phpactor.schema.json | 84 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 9 deletions(-) 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/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" From cefb34caa7ae80a135dc8efb879032cca64651bb Mon Sep 17 00:00:00 2001 From: gcch Date: Sat, 2 May 2026 14:56:49 +0200 Subject: [PATCH 16/17] =?UTF-8?q?corv=C3=A9e(phpantom)=20installe=20le=20L?= =?UTF-8?q?SP=20phpantom?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .phpantom.toml | 19 +++++++++++++++++++ .zed/settings.json | 1 + mise.toml | 2 ++ 3 files changed, 22 insertions(+) create mode 100644 .phpantom.toml create mode 100644 mise.toml 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 8ba0003e..3b8077e7 100644 --- a/.zed/settings.json +++ b/.zed/settings.json @@ -9,6 +9,7 @@ "!oxc", "!oxfmt", "!oxlint", + "!phptools", "!prettier", "!tailwindcss-language-server", "!tsgo", 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" From 75382aec22f04ca78f776d27e4bd6425f87ef72a Mon Sep 17 00:00:00 2001 From: gcch Date: Sat, 2 May 2026 14:56:49 +0200 Subject: [PATCH 17/17] =?UTF-8?q?corv=C3=A9e(playwright)=20met=20=C3=A0=20?= =?UTF-8?q?jour=20la=20configuration=20playwright?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - créé une tâche justfile pour lancer le mode UI de Playwright. --- cfg/playwright.config.ts | 25 +++++-------------------- justfile | 3 +++ tests/playwright/shop.spec.ts | 3 ++- 3 files changed, 10 insertions(+), 21 deletions(-) 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/justfile b/justfile index 5ee66b34..8d2c9d6c 100755 --- a/justfile +++ b/justfile @@ -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/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);