@adobe/helix-html-pipeline 6.32.1 → 6.32.3

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [6.32.3](https://github.com/adobe/helix-html-pipeline/compare/v6.32.2...v6.32.3) (2026-09-22)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * resolve custom og:image/twitter:image metadata to absolute urls ([f9624e5](https://github.com/adobe/helix-html-pipeline/commit/f9624e5dc5b0588ac620ac6ed77fad8eb7c95268)), closes [#768](https://github.com/adobe/helix-html-pipeline/issues/768)
7
+
8
+ ## [6.32.2](https://github.com/adobe/helix-html-pipeline/compare/v6.32.1...v6.32.2) (2026-09-17)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **urls:** use http protocol for localhost origins ([#1140](https://github.com/adobe/helix-html-pipeline/issues/1140)) ([d6c329a](https://github.com/adobe/helix-html-pipeline/commit/d6c329a4fb2985fc30b0b8146bf07a0aae5f8510))
14
+
1
15
  ## [6.32.1](https://github.com/adobe/helix-html-pipeline/compare/v6.32.0...v6.32.1) (2026-09-15)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/helix-html-pipeline",
3
- "version": "6.32.1",
3
+ "version": "6.32.3",
4
4
  "description": "Helix HTML Pipeline",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -15,6 +15,7 @@ import { computeCodePathKey } from './steps/set-x-surrogate-key-header.js';
15
15
  import setCustomResponseHeaders from './steps/set-custom-response-headers.js';
16
16
  import { PipelineResponse } from './PipelineResponse.js';
17
17
  import initConfig from './steps/init-config.js';
18
+ import { getOrigin } from './steps/utils.js';
18
19
 
19
20
  /**
20
21
  * Default robots.txt contents returned on inner/outer CDN.
@@ -89,7 +90,7 @@ function generateRobots(state) {
89
90
  'User-Agent: *',
90
91
  'Allow: /',
91
92
  '',
92
- `Sitemap: https://${prodHost}/sitemap.xml`,
93
+ `Sitemap: ${getOrigin(prodHost)}/sitemap.xml`,
93
94
  '',
94
95
  ].join('\n');
95
96
  return new PipelineResponse(txt, {
@@ -19,6 +19,7 @@ import { PipelineStatusError } from './PipelineStatusError.js';
19
19
  import { PipelineResponse } from './PipelineResponse.js';
20
20
  import initConfig from './steps/init-config.js';
21
21
  import { extractLastModified, recordLastModified, setLastModified } from './utils/last-modified.js';
22
+ import { getOrigin } from './steps/utils.js';
22
23
 
23
24
  async function generateSitemapIndex(state) {
24
25
  const {
@@ -38,7 +39,7 @@ async function generateSitemapIndex(state) {
38
39
  const host = partition === 'preview'
39
40
  ? (previewHost || `${ref}--${repo}--${owner}.aem.page`)
40
41
  : (prodHost || liveHost || `${ref}--${repo}--${owner}.aem.live`);
41
- const loc = (path) => (path.startsWith('/') ? `https://${host}${escape(path)}` : path);
42
+ const loc = (path) => (path.startsWith('/') ? `${getOrigin(host)}${escape(path)}` : path);
42
43
  const xml = [
43
44
  '<?xml version="1.0" encoding="utf-8"?>',
44
45
  '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
@@ -19,6 +19,7 @@ import { PipelineStatusError } from './PipelineStatusError.js';
19
19
  import { PipelineResponse } from './PipelineResponse.js';
20
20
  import initConfig from './steps/init-config.js';
21
21
  import { extractLastModified, recordLastModified, setLastModified } from './utils/last-modified.js';
22
+ import { getOrigin } from './steps/utils.js';
22
23
 
23
24
  async function generateSitemap(state) {
24
25
  const {
@@ -45,7 +46,7 @@ async function generateSitemap(state) {
45
46
  : (prodHost || liveHost || `${ref}--${repo}--${owner}.aem.live`);
46
47
  const safeNumber = (num) => parseInt(num, 10) || 0;
47
48
  const loc = ({ path, lastModified }) => ` <url>
48
- <loc>https://${host}${escape(path)}</loc>
49
+ <loc>${getOrigin(host)}${escape(path)}</loc>
49
50
  <lastmod>${new Date(safeNumber(lastModified) * 1000).toISOString().substring(0, 10)}</lastmod>
50
51
  </url>`;
51
52
  const xml = [
@@ -348,6 +348,22 @@ export default function extractMetaData(state, req) {
348
348
 
349
349
  meta.imageAlt = meta['image-alt'] ?? content.imageAlt;
350
350
 
351
+ // custom og:image/twitter:image overrides authored directly in the metadata block or sheet
352
+ // should be resolved to an absolute, optimized url, just like the default image, but only
353
+ // if they actually look like a url or path. plain text values are passed through as-is.
354
+ ['og:image', 'og:image:secure_url', 'twitter:image'].forEach((name) => {
355
+ const value = metaConfig[name];
356
+ if (value && /^(https?:\/\/|\.?\/)/.test(value)) {
357
+ try {
358
+ let img = rewriteUrl(state, value);
359
+ img = optimizeMetaImage(state.info.path, img);
360
+ metaConfig[name] = getAbsoluteUrl(state, img);
361
+ } catch (e) {
362
+ // ignore url errors
363
+ }
364
+ }
365
+ });
366
+
351
367
  // compute the final page metadata
352
368
  const metadata = {
353
369
  description: meta.description,
@@ -198,6 +198,18 @@ export function resolveUrl(from, to) {
198
198
  return resolvedUrl.toString();
199
199
  }
200
200
 
201
+ const LOCALHOST_REGEXP = /^(localhost|127\.0\.0\.1)(:\d+)?$/;
202
+
203
+ /**
204
+ * Returns the origin for the given host, using `http` for loopback hosts
205
+ * (e.g. when developing locally against `localhost:3000`) and `https` otherwise.
206
+ * @param {string} host the host, optionally including a port
207
+ * @returns {string} the origin
208
+ */
209
+ export function getOrigin(host) {
210
+ return `${LOCALHOST_REGEXP.test(host) ? 'http' : 'https'}://${host}`;
211
+ }
212
+
201
213
  /**
202
214
  * Turns a relative into an absolute URL.
203
215
  * @param {PipelineState} state the request state
@@ -209,7 +221,7 @@ export function getAbsoluteUrl(state, url) {
209
221
  if (typeof url !== 'string') {
210
222
  return null;
211
223
  }
212
- return resolveUrl(`https://${state.prodHost}${state.info?.path || '/'}`, url);
224
+ return resolveUrl(`${getOrigin(state.prodHost)}${state.info?.path || '/'}`, url);
213
225
  }
214
226
 
215
227
  /**