diff --git a/modules/tome_static/src/StaticGenerator.php b/modules/tome_static/src/StaticGenerator.php index 446f07f9e6f2a2998bbec53bbca0c60afe8c22ce..11d209341d7c428081b3ce0cbaf1969454dff293 100644 --- a/modules/tome_static/src/StaticGenerator.php +++ b/modules/tome_static/src/StaticGenerator.php @@ -408,6 +408,40 @@ class StaticGenerator implements StaticGeneratorInterface { return $paths; } + /** + * Parses a srcset attribute into individual URLs. + * + * Drupal commonly emits srcset values without a space after each + * comma — `/url1 650w,/url2 870w,/url3 1090w` — and the upstream + * Tome regex (` [^ ]+(,|$)`) treats the comma as just another + * non-space character. The result is that all URLs collapse into + * one concatenated garbage path. Split on comma first, then + * extract the URL from each candidate, to produce the actual + * list of URLs. + * + * @param string $srcset + * A srcset attribute value. + * + * @return string[] + * The URLs in the srcset. + */ + protected function parseSrcset(string $srcset): array { + $urls = []; + foreach (explode(',', $srcset) as $candidate) { + $candidate = trim($candidate); + if ($candidate === '') { + continue; + } + // Each candidate is "URL [size_descriptor]". The URL is the + // first whitespace-separated token. + $parts = preg_split('/\s+/', $candidate, 2); + if (!empty($parts[0])) { + $urls[] = $parts[0]; + } + } + return $urls; + } + /** * Finds and exports assets for the given HTML content. * @@ -433,9 +467,20 @@ class StaticGenerator implements StaticGeneratorInterface { $paths[] = $image->getAttribute('poster'); } if ($image->hasAttribute('srcset')) { - $srcset = $image->getAttribute('srcset'); - $sources = explode(' ', preg_replace('/ [^ ]+(,|$)/', '', $srcset)); - foreach ($sources as $src) { + foreach ($this->parseSrcset($image->getAttribute('srcset')) as $src) { + $paths[] = $src; + } + } + // Lazy-load conventions: real image URLs live in data-src / + // data-srcset with a placeholder in the canonical src. Easy + // LQP, Lazysizes, and similar modules all use these. Without + // scanning them, image-style derivatives referenced by + // lazy-loaded images never enter the static export. + if ($image->hasAttribute('data-src')) { + $paths[] = $image->getAttribute('data-src'); + } + if ($image->hasAttribute('data-srcset')) { + foreach ($this->parseSrcset($image->getAttribute('data-srcset')) as $src) { $paths[] = $src; } }