is_main_query() ) { self::$product_index = 0; self::$post_index = 0; } } /** * Check if current item is an LCP candidate (above the fold) * * @param string $context Context type (product, post, etc.). * @return bool Whether the item is an LCP candidate. */ public static function is_lcp_candidate( $context = 'product' ) { // Homepage hero and first few products are LCP candidates if ( is_front_page() || ( function_exists( 'is_shop' ) && is_shop() ) ) { if ( 'product' === $context ) { return self::$product_index < self::LCP_CANDIDATE_COUNT; } } // First post on archive pages if ( is_archive() || is_home() ) { if ( 'post' === $context ) { return self::$post_index < 1; } } return false; } /** * Increment product counter */ public static function increment_product_index() { self::$product_index++; } /** * Increment post counter */ public static function increment_post_index() { self::$post_index++; } /** * Get current product index * * @return int Current product index. */ public static function get_product_index() { return self::$product_index; } /** * Optimize image attributes for performance * * @param array $attr Image attributes. * @param WP_Post $attachment Attachment post object. * @param string $size Requested image size. * @return array Modified attributes. */ public function optimize_image_attributes( $attr, $attachment, $size ) { // Add decoding async for all images (improves render performance) if ( ! isset( $attr['decoding'] ) ) { $attr['decoding'] = 'async'; } return $attr; } /** * Skip lazy loading for above-fold images * * @param string|false $value The loading attribute value. * @param string $image The HTML img tag. * @param string $context Context for the image. * @return string|false Modified loading attribute. */ public function maybe_skip_lazy_loading( $value, $image, $context ) { // Skip lazy loading for site logo if ( strpos( $image, 'custom-logo' ) !== false ) { return false; } // Skip lazy loading for header images if ( strpos( $image, 'header-image' ) !== false ) { return false; } return $value; } /** * Add preload hints for critical fonts */ public function add_font_preload_hints() { // Only output if not in admin if ( is_admin() ) { return; } // Preload system fonts hint (browser will optimize) // Note: Custom fonts should be added here if used $fonts = apply_filters( 'brandy_preload_fonts', array() ); foreach ( $fonts as $font ) { if ( ! empty( $font['href'] ) ) { printf( '%s', esc_url( $font['href'] ), esc_attr( $font['type'] ?? 'font/woff2' ), "\n" ); } } } /** * Get image attributes optimized for LCP * * @param bool $is_lcp_candidate Whether this image is an LCP candidate. * @return array Image attributes. */ public static function get_lcp_image_attrs( $is_lcp_candidate = false ) { if ( $is_lcp_candidate ) { return array( 'loading' => false, // Disable lazy loading 'fetchpriority' => 'high', 'decoding' => 'async', ); } return array( 'loading' => 'lazy', 'decoding' => 'async', ); } }