# Changelog All notable changes to this project will be documented in this file. ## [0.1.5] - 2026-03-01 ### Fixed - **Empty page title on catalog pages** (`header.html.twig`): Replaced `page_title` context variable (never passed by WC) with direct `fn('woocommerce_page_title', false)` call - **Missing breadcrumbs on catalog pages** (`archive-product.php`): Added `woocommerce_breadcrumb()` call before shop loop header - **Missing product categories on catalog pages** (`content-product-cat.html.twig`): Renamed template from hyphen (`content-product-cat`) to underscore (`content-product_cat`) to match WC's `wc_get_template()` filename convention - **Product grid 4 columns instead of 3** (`functions.php`, `loop-start.html.twig`): Changed default columns from 4 to 3 for better card proportions with sidebar - **Double chevron on sort dropdown** (`wc-bootstrap.css`): Removed conflicting `appearance: auto` rule; set `appearance: none` to let Bootstrap's `form-select` class handle the dropdown arrow exclusively - **Variable product add-to-cart button stays disabled** (`variable.html.twig`, `variation-add-to-cart-button.html.twig`): Added missing `data-product_id` and `data-product_variations` attributes to form; replaced HTML `disabled` attribute on button with CSS classes `disabled wc-variation-selection-needed` (WC JS only toggles CSS classes, never removes the HTML attribute) - **Variable product select white background in dark mode** (`wc-bootstrap.css`): Increased dark mode override specificity to `(0,5,1)` to beat WC's `.woocommerce div.product form.cart .variations select` at `(0,4,3)` which uses `background` shorthand; also overrides `background-image` for Bootstrap's dark-mode-aware chevron SVG - **Product gallery missing main image in thumbnail strip** (`product-image.html.twig`): Prepend main image ID to gallery IDs using `[post_thumbnail_id]|merge(gallery_image_ids)` with active state on first thumbnail; added `{% if thumb_url %}` guard to skip invalid attachment IDs - **Related/upsells products show same product repeated** (`related.html.twig`, `up-sells.html.twig`): Added `wc_setup_product_data()` call before each product render and `wp_reset_postdata()` after loop to set global `$product` correctly for WC hooks - **Grouped product add-to-cart button/pricing broken** (`grouped.html.twig`): Rewrote template to compute `quantites_required` and `show_add_to_cart_button` in loop (matching WC PHP logic); moved hidden `add-to-cart` input outside conditional; added `has_options()` and `is_sold_individually()` checks - **Downloads page empty** (`downloads.html.twig`): Replaced fragile `fn('WC').customer.get_downloadable_products()` chain with direct `fn('wc_get_customer_available_downloads', get_current_user_id())` call ### Added - **Product gallery JS** (`product-gallery.js`): Vanilla JS click handler for thumbnail-to-main-image swap with active state highlighting and gallery fade-in - **`wc_setup_product_data()` Twig function** (`WooCommerceExtension.php`): Sets `$GLOBALS['product']` and calls `setup_postdata()` for correct product context in Twig loops - **`wp_reset_postdata` Twig function** (`WooCommerceExtension.php`): Restores global post state after product loops - **`sanitize_title` Twig filter** (`WooCommerceExtension.php`): Matches WC PHP's lowercase attribute name handling for variation form data attributes - **Product thumbnails suppressor** (`product-thumbnails.html.twig`): Empty template override to prevent WC's default full-size gallery images rendering below custom thumbnail row ### Changed - **Whitelisted functions** (`WooCommerceExtension.php`): Added `woocommerce_page_title` and `wc_get_customer_available_downloads` to `ALLOWED_FUNCTIONS` - **Removed obsolete files**: Deleted `PLAN.md` and `SETUP.md` (superseded by CLAUDE.md) ## [0.1.4] - 2026-03-01 ### Security - **fn() function whitelist** (`WooCommerceExtension`): The `callFunction()` method (exposed as `fn()` in Twig templates) now restricts callable functions to an explicit `ALLOWED_FUNCTIONS` whitelist. Previously any PHP function could be called, risking arbitrary code execution if template context were compromised. Only the 6 functions actually used in templates are permitted. - **Notice data attribute escaping**: Changed `{{ notice.data|raw }}` to `{{ notice.data|wp_kses_post }}` in success, error, and notice Twig templates. Defense-in-depth against potential XSS via data attributes. - **Search query escaping** (`product-searchform.html.twig`): Added `|esc_attr` filter to `get_search_query()` output in the search input value attribute. ### Performance - **Per-request ContextBuilder caching**: New `wc_bootstrap_get_theme_context()` function with static variable caching eliminates redundant `ContextBuilder::build()` calls (10-20 DB queries each) when multiple WooCommerce render functions fire in the same request. ### Changed - **Shared page shell helper**: New `wc_bootstrap_render_in_page_shell()` function extracts the duplicated context-injection-and-render pattern from `wc_bootstrap_render_page()`, `wc_bootstrap_render_product_archive()`, and `wc_bootstrap_render_single_product()`. - **Removed unused constants**: Removed `WC_BOOTSTRAP_VERSION` and `WC_BOOTSTRAP_URL` constants that were defined but never referenced. ## [0.1.3] - 2026-02-28 ### Added - Theme screenshot showing dark mode product archive with Bootstrap 5 card grid ## [0.1.2] - 2026-02-28 ### Fixed - Dark mode: text inputs and textareas showing white background due to WooCommerce's `.woocommerce form .form-row .input-text` (specificity `0,3,1`) overriding theme's checkout form rules with `var(--wc-form-color-background, #fff)` fallback - Dark mode: `table-light` class on `` forcing white table headers in cart, checkout review, orders, and payment methods pages - Dark mode: WooCommerce notice focus ring appearing white when `focus_populate_live_region()` JS programmatically focuses alerts for screen reader accessibility - WooCommerce notice overrides not matching alerts rendered by Twig templates (added `.alert.woocommerce-*` compound selectors alongside `.woocommerce .woocommerce-*` descendant selectors) - Order details table on thank-you page not wrapped in a card like other sections - Thank-you page success message line-wrapping after icon due to block-level `

` inside inline alert context ## [0.1.1] - 2026-02-28 ### Fixed - Dark mode: native `