Skip to content

Image replacement causing invalid HTML and JS errors #86

@rhoerr

Description

@rhoerr

Environment

Magento 2.4.5-p10
Hyva theme 1.3.10
Yireo WebP 0.14.3
NextGenImages 0.5.10

Issue

I've observed on several sites that some pages throw JS errors due to the picture replacement and lazy loading ending at the wrong point. This seems to especially affect page builder category descriptions with an image, but I'm not sure if it's limited to that.

Example wrong output:

<div id="category-view-container" class="category-view container"><div class="category-image"><picture class="image"><source type="image/webp" srcset="https://example.com/media/catalog/category/banners-03_1.webp"><img src="https://example.com/media/catalog/category/banners-03_1.png" alt="Variety&#x20;Boxes" title="Variety&#x20;Boxes" class="image" "/></div><div class="category-description"><div data-content-type="row" data-appearance="contained" data-element="main"><div data-enable-parallax="0" data-parallax-speed="0.5" data-background-images="{}" data-element="inner" style="justify-content: flex-start; display: flex; flex-direction: column; background-position: left top; background-size: cover; background-repeat: no-repeat; background-attachment: scroll; border-style: none; border-width: 1px; border-radius: 0px; margin: 0px 0px 10px; padding: 10px;"><div data-content-type="html" data-appearance="default" data-element="main" style="border-style: none; border-width: 1px; border-radius: 0px; margin: 0px; padding: 0px;"> Just can't decide what to buy?</div></div></div></div></div><div class="columns"><aside class="sidebar sidebar-main"><div role="region" aria-label="Product&#x20;filters" class="block border border-container bg-container-darker p-4 md:border-0 md:bg-transparent md:py-0 md:px-0 md:my-6" x-data="initLayeredNavigation()" x-init="checkIsMobileResolution()" @resize.window.debounce="checkIsMobileResolution()" @visibilitychange.window.debounce="checkIsMobileResolution()"><h2><div class="block-title h-10 flex items-center justify-between" :class="{ 'cursor-pointer' : isMobile }" :role="isMobile ? 'button' : 'presentation'" :aria-expanded="isMobile ? blockOpen : undefined" :aria-controls="isMobile ? 'filters-content' : undefined" :tabindex="isMobile ? 0 : undefined" @click="blockOpen = !blockOpen" @keydown.enter="blockOpen = !blockOpen" @keydown.space="blockOpen = !blockOpen"><span class="text-primary text-md md:text-3xl font-medium uppercase"> Shop By</span><span class="py-1 px-1 bg-container-lighter rounded border border-container-darker hidden" :class="{ 'block' : isMobile, 'hidden': !isMobile }"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="transition-transform transform duration-300 ease-in-out" :class="blockOpen ? 'rotate-180' : ''"><path d="M19 9L12 16L5 9" stroke="#4A5568" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div></h2><div id="filters-content" class="block-content filter-content pt-3" x-show="isMobile && blockOpen || !isMobile"><a href="#products-list" class="sr-only focus:not-sr-only bg-blue-600 text-white px-12 py-4 text-center block rounded-sm"> Skip to product list</a><div role="group" aria-labelledby="filter-option-0-title" class="filter-option card my-4" x-data="{ open: true }"><h3 id="filter-option-0-title" class="filter-options-title"><button class="flex justify-between items-center cursor-pointer hover:text-secondary-darker border-container w-full" :class="{ 'border-b pb-4': open }" @click="open = !open" aria-controls="filter-option-0-content" :aria-expanded="open"><span class="title text-md md:text-lg font-semibold"> Price<span class="sr-only"> filter</span></span><span class="py-1 px-1 rounded border border-container"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="transition-transform transform duration-300 ease-in-out" :class="open ? 'rotate-180' : ''" aria-hidden="true"><path d="M19 9L12 16L5 9" stroke="#4A5568" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /></svg></span></button></h3><div id="filter-option-0-content" class="filter-options-content pt-3" x-show="open"><script> function rangeSlider_67a27cb1842e4(options) { "use strict"; return { options: {"minValue":52,"maxValue":60,"currentValue":{"from":52,"to":60},"fieldFormat":{"pattern":"$%s","precision":2,"requiredPrecision":2,"decimalSymbol":".","groupSymbol":",","groupLength":3,"integerRequired":false},"intervals":[{"value":52,"count":1},{"value":59,"count":4}],"adaptiveIntervals":[],"showAdaptiveSlider":false,"urlTemplate":"https:\/\/example.com\/new-arrivals\/variety-boxes?price=<%- from % loading="lazy"></picture>-<%- to %>","messageTemplates":{"displayOne":"1 product","displayCount":"<%- count %> products","displayEmpty":"No products in the selected range."},"rate":1},

Pardon it all being on one line, but that's how it is in the source (possibly related).

Note particularly:

  • The image tag has an extra quote at the end of the replaced code
<picture class="image">...banners-03_1.png" alt="Variety&#x20;Boxes" title="Variety&#x20;Boxes" class="image" "/>
  • The closing picture tag and loading bit ended up in the price filter JS, breaking JS execution on the page:
"urlTemplate":"...?price=<%- from % loading="lazy"></picture>-<%- to %>"

The other instances I've noticed of this issue have been similar if not identical.

Possibly related

The image matching code was changed recently.

#82
#84
867ef31#diff-56e9cb219161815f1d7336e26a686ab654e4ce468c6cf20463274e162a7b4ffdR116

The code was changed in 0.5.10. I downgraded to 0.5.9 and that seems to work better. I haven't seen the case that fixes yet.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions