mnfst-render 0.3.3 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -904,6 +904,7 @@ function stripPrerenderDynamicBindings(html) {
904
904
  return html.replace(/<(\w+)([^>]*)>/g, (match, tagName, attrsStr) => {
905
905
  if (tagName.toLowerCase() === 'script') return match;
906
906
  const isAnchor = tagName.toLowerCase() === 'a';
907
+ const isImg = tagName.toLowerCase() === 'img';
907
908
  let workAttrs = attrsStr;
908
909
  workAttrs = workAttrs.replace(/\s+:style=(?:"([^"]*)"|'([^']*)')/gi, (sub, d, s) => {
909
910
  const val = (d !== undefined ? d : s) || '';
@@ -919,8 +920,9 @@ function stripPrerenderDynamicBindings(html) {
919
920
  let m;
920
921
  while ((m = bindingRegex.exec(workAttrs)) !== null) {
921
922
  const attrName = (m[1] || '').toLowerCase();
922
- // Keep href on anchors so prerendered static navigation stays valid.
923
- if (attrName === 'class' || attrName === 'style' || (isAnchor && attrName === 'href')) continue;
923
+ // Keep href on anchors and src on images: :href / :src often reference x-for iterators (e.g.
924
+ // article?.banner). Stripping the baked literal leaves only :src/:href and breaks static HTML.
925
+ if (attrName === 'class' || attrName === 'style' || (isAnchor && attrName === 'href') || (isImg && attrName === 'src')) continue;
924
926
  const val = (m[2] !== undefined ? m[2] : m[3]) || '';
925
927
  if (val.indexOf('$x') === -1) toStrip.add(attrName);
926
928
  }
@@ -937,6 +939,18 @@ function stripPrerenderDynamicBindings(html) {
937
939
  });
938
940
  }
939
941
 
942
+ // Drop :src / x-bind:src when img already has a baked src= (x-for / iterator expressions break hydrate).
943
+ function stripRedundantImgSrcBindings(html) {
944
+ return html.replace(/<img\b([^>]*)>/gi, (full, attrs) => {
945
+ const srcM = attrs.match(/\ssrc=(["'])([\s\S]*?)\1/i);
946
+ if (!srcM || !String(srcM[2] || '').trim()) return full;
947
+ if (!/\s:src\s*=|\sx-bind:src\s*=/i.test(attrs)) return full;
948
+ let next = attrs.replace(/\s:src=(?:"[^"]*"|'[^']*')/gi, '');
949
+ next = next.replace(/\sx-bind:src=(?:"[^"]*"|'[^']*')/gi, '');
950
+ return `<img${next}>`;
951
+ });
952
+ }
953
+
940
954
  // Remove empty inline mask-image styles emitted before data resolves
941
955
  // (e.g. style="mask-image: url()"), while keeping any :style/x-bind:style bindings.
942
956
  function stripEmptyInlineMaskStyles(html) {
@@ -1993,6 +2007,7 @@ async function runPrerender(config) {
1993
2007
  const xData = { manifest, content };
1994
2008
  html = resolveHeadXBindings(html, xData);
1995
2009
  html = stripPrerenderDynamicBindings(html);
2010
+ html = stripRedundantImgSrcBindings(html);
1996
2011
  html = stripEmptyInlineMaskStyles(html);
1997
2012
  html = rewriteHtmlAssetPaths(html, fileSegments.length);
1998
2013
  const liveBase = config.liveUrl.replace(/\/$/, '');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mnfst-render",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "Render Manifest sites to static HTML for SEO",
5
5
  "type": "module",
6
6
  "bin": {