base -> components -> style.css * (layout and pages). Each layer may only use what the layers before it * defined, which is what keeps the cascade free of override chains. * * @package VyatkaShop */ if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Version a theme asset with a short token derived from the file itself. * * Four characters is enough to tell one build of a file from the next, and it * keeps the query string out of the way. Deriving it from the file rather than * randomising it per request is what lets the browser actually cache: the * token only moves when the file does. * * @param string $relative_path Path relative to the theme root. * @return string */ function vyatka_shop_asset_version( string $relative_path ): string { $file = get_template_directory() . '/' . ltrim( $relative_path, '/' ); if ( ! is_readable( $file ) ) { return substr( hash( 'crc32b', $relative_path . VYATKA_SHOP_VERSION ), 0, 4 ); } return substr( hash( 'crc32b', $relative_path . filemtime( $file ) . filesize( $file ) ), 0, 4 ); } /** * Icons the front-end script has to render on its own (toasts, dismiss * buttons). Sharing them from PHP keeps `assets/icons/*.svg` the single * source of truth. * * @return array */ function vyatka_shop_script_icons(): array { $icons = array(); foreach ( array( 'check-circle-fill', 'x-circle-fill', 'warning-fill', 'info-fill', 'x', 'caret-down' ) as $name ) { $icons[ $name ] = vyatka_shop_get_icon( $name ); } return $icons; } /** * Load public assets. */ function vyatka_shop_assets(): void { /* * Order is the cascade. Each layer may only build on the ones before it: * tokens define the vocabulary, base sets element defaults, components own * the controls, the page layers place them, and responsive comes last * because it overrides all of the above. */ $layers = array( 'vyatka-tokens' => 'assets/css/tokens.css', 'vyatka-base' => 'assets/css/base.css', 'vyatka-components' => 'assets/css/components.css', 'vyatka-layout' => 'assets/css/layout.css', 'vyatka-home' => 'assets/css/home.css', 'vyatka-catalog' => 'assets/css/catalog.css', 'vyatka-product' => 'assets/css/product.css', 'vyatka-blog' => 'assets/css/blog.css', 'vyatka-cart' => 'assets/css/cart.css', 'vyatka-responsive' => 'assets/css/responsive.css', 'vyatka-misc' => 'assets/css/misc.css', ); $previous = array(); foreach ( $layers as $handle => $path ) { wp_enqueue_style( $handle, get_template_directory_uri() . '/' . $path, $previous, vyatka_shop_asset_version( $path ) ); $previous = array( $handle ); } // style.css only carries the theme header WordPress reads, but it still has // to be enqueued so child themes can depend on it. wp_enqueue_style( 'vyatka-shop', get_stylesheet_uri(), array( 'vyatka-misc' ), vyatka_shop_asset_version( 'style.css' ) ); wp_enqueue_script( 'vyatka-shop', get_template_directory_uri() . '/assets/js/theme.js', array(), vyatka_shop_asset_version( 'assets/js/theme.js' ), true ); wp_localize_script( 'vyatka-shop', 'vyatkaShopCart', array( 'ajaxUrl' => '/wp-admin/admin-ajax.php', 'nonce' => wp_create_nonce( 'vyatka-cart' ), ) ); wp_localize_script( 'vyatka-shop', 'vyatkaShopIcons', vyatka_shop_script_icons() ); } add_action( 'wp_enqueue_scripts', 'vyatka_shop_assets' ); /** * Drop WooCommerce's default presentation. * * The theme templates every WooCommerce surface it uses, so the plugin's * stylesheets only add rules that have to be fought with `!important`. * Removing them is what lets the component layer win on its own specificity. * * @param array> $styles Registered WooCommerce styles. * @return array> */ function vyatka_shop_remove_woocommerce_styles( array $styles ): array { unset( $styles['woocommerce-general'], $styles['woocommerce-layout'], $styles['woocommerce-smallscreen'] ); return $styles; } add_filter( 'woocommerce_enqueue_styles', 'vyatka_shop_remove_woocommerce_styles' ); /** * Remove the block-editor front-end styles WooCommerce and core add for * surfaces this theme renders itself. * * Hooked on `wp_print_styles` rather than `wp_enqueue_scripts`: WooCommerce * Blocks registers its stylesheet from `enqueue_block_assets`, which runs * after the theme's own enqueue pass. */ function vyatka_shop_dequeue_block_styles(): void { if ( is_admin() ) { return; } $handles = array( 'wc-blocks-style', 'wc-blocks-style-all-products', 'wc-blocks-packages-style', 'wp-block-library-theme', 'classic-theme-styles', 'global-styles', ); foreach ( $handles as $handle ) { wp_dequeue_style( $handle ); wp_deregister_style( $handle ); } } add_action( 'wp_print_styles', 'vyatka_shop_dequeue_block_styles', 100 );