From 9a52dbee68969c0afbb045aab729dadc16d9d4cf Mon Sep 17 00:00:00 2001 From: Alexandre Capt Date: Tue, 23 Jan 2024 14:21:43 +0100 Subject: [PATCH 1/2] feat: rewrite metadata urls --- src/steps/extract-metadata.js | 10 +++- src/steps/utils.js | 34 +++++++++++ .../content/page-metadata-block-urls.html | 30 ++++++++++ .../content/page-metadata-block-urls.md | 34 +++++++++++ test/rendering.test.js | 29 +++++++++ test/steps/utils.test.js | 59 ++++++++++++++++++- 6 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 test/fixtures/content/page-metadata-block-urls.html create mode 100644 test/fixtures/content/page-metadata-block-urls.md diff --git a/src/steps/extract-metadata.js b/src/steps/extract-metadata.js index eb17c9a6..bfae7c97 100644 --- a/src/steps/extract-metadata.js +++ b/src/steps/extract-metadata.js @@ -14,7 +14,7 @@ import { toString } from 'hast-util-to-string'; import { remove } from 'unist-util-remove'; import { visit, EXIT, CONTINUE } from 'unist-util-visit'; import { - getAbsoluteUrl, makeCanonicalHtmlUrl, optimizeImageURL, resolveUrl, + getAbsoluteUrl, makeCanonicalHtmlUrl, optimizeImageURL, resolveUrl, makeAbsoluteURLForMeta, } from './utils.js'; import { toMetaName } from '../utils/modifiers.js'; import { childNodes } from '../utils/hast-utils.js'; @@ -293,10 +293,16 @@ export default function extractMetaData(state, req) { } } - // remove undefined metadata for (const name of Object.keys(metadata)) { if (metadata[name] === undefined) { + // remove undefined metadata delete metadata[name]; + } else if (Array.isArray(metadata[name])) { + // make absolute URLs for arrays + metadata[name] = metadata[name].map((value) => makeAbsoluteURLForMeta(state, value)); + } else { + // make absolute URLs for strings + metadata[name] = makeAbsoluteURLForMeta(state, metadata[name]); } } diff --git a/src/steps/utils.js b/src/steps/utils.js index 82b72238..babc21bf 100644 --- a/src/steps/utils.js +++ b/src/steps/utils.js @@ -223,3 +223,37 @@ export function toArray(v) { } return Array.isArray(v) ? v : [v]; } + +/** + * Returns an updated value of the provided metadata value: + * if the metadata is a URL or an array of URLs (comma separated) + * and if the URL(s) contains the preview or live host, + * the URL(s) are replaced by the absolute URL(s) to the production host + * @param {PipelineState} state the request state + * @param {string} meta the metadata value + * @returns {string} meta the update metadata value or the original value + */ +export function makeAbsoluteURLForMeta(state, meta) { + if (meta && meta.startsWith('http')) { + const rewrite = []; + const split = meta.split(', '); + + const previewSuffix = state.previewHost?.replace(/^.*?--/, '--'); + const liveSuffix = state.liveHost?.replace(/^.*?--/, '--'); + split.forEach((v) => { + try { + const u = new URL(v); + if ((previewSuffix && u.host.endsWith(previewSuffix)) + || (liveSuffix && u.host.endsWith(liveSuffix))) { + rewrite.push(getAbsoluteUrl(state, `${u.pathname}${u.search}${u.hash}`)); + } else { + rewrite.push(v); + } + } catch (e) { + rewrite.push(v); + } + }); + return rewrite.join(', '); + } + return meta; +} diff --git a/test/fixtures/content/page-metadata-block-urls.html b/test/fixtures/content/page-metadata-block-urls.html new file mode 100644 index 00000000..2fe45481 --- /dev/null +++ b/test/fixtures/content/page-metadata-block-urls.html @@ -0,0 +1,30 @@ + + ACME CORP + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/content/page-metadata-block-urls.md b/test/fixtures/content/page-metadata-block-urls.md new file mode 100644 index 00000000..ab6701d8 --- /dev/null +++ b/test/fixtures/content/page-metadata-block-urls.md @@ -0,0 +1,34 @@ +# Metadata URLs rewrite Test + + + + + + + + + + + + + + + + + + + + + + + + + +
Metadata
hlx.page urlhttps://main--helix-pages--adobe.hlx.page/express/
hlx.page urls 1 +

https://main--helix-pages--adobe.hlx.page/express/page1

+

https://main--helix-pages--adobe.hlx.page/express/page2

hlx.page urls 2 + +
hlx.live urlhttps://main--helix-pages--adobe.hlx.page/express/
branch hlx.live urlhttps://another-ref--helix-pages--adobe.hlx.page/express/
diff --git a/test/rendering.test.js b/test/rendering.test.js index 3b02fbff..5358a260 100644 --- a/test/rendering.test.js +++ b/test/rendering.test.js @@ -398,6 +398,35 @@ describe('Rendering', () => { config = DEFAULT_CONFIG_EMPTY; await testRender('page-metadata-twitter-fallback', 'head'); }); + + it('renders meta with URLs - rewrites urls', async () => { + config = structuredClone(DEFAULT_CONFIG); + config.cdn.preview = { + host: '$ref--$repo--$owner.hlx.page', + }; + config.cdn.live = { + host: '$ref--$site--$org.hlx.live', + }; + + config.metadata.live.data['/**'] = config.metadata.live.data['/**'].concat([{ + key: 'page-url-branch', + value: 'https://super-test--helix-pages--adobe.hlx.page/page.html', + }, { + key: 'live-url-branch', + value: 'https://super-test--helix-pages--adobe.hlx.live/live.html', + }, { + key: 'page-url-main', + value: 'https://main--helix-pages--adobe.hlx.page/page.html', + }, { + key: 'live-url-main', + value: 'https://main--helix-pages--adobe.hlx.live/live.html', + }, { + key: 'prod-url', + value: 'https://www.adobe.com/prod-page.html', + }]); + + await testRender('page-metadata-block-urls', 'head'); + }); }); describe('Miscellaneous', () => { diff --git a/test/steps/utils.test.js b/test/steps/utils.test.js index f64ba7b4..be3f0619 100644 --- a/test/steps/utils.test.js +++ b/test/steps/utils.test.js @@ -14,11 +14,13 @@ import assert from 'assert'; import { getAbsoluteUrl, - getOriginalHost, makeCanonicalHtmlUrl, + getOriginalHost, + makeCanonicalHtmlUrl, optimizeImageURL, rewriteUrl, toBlockCSSClassNames, toArray, + makeAbsoluteURLForMeta, } from '../../src/steps/utils.js'; describe('Optimize Image URLs', () => { @@ -199,3 +201,58 @@ describe('to array test', () => { assert.deepStrictEqual(toArray(null), []); }); }); + +describe('Make absolute URLs for meta test', () => { + const SAMPLE_STATE = { + prodHost: 'www.my.com', + previewHost: 'main--repo--owner.my.page', + liveHost: 'main--repo--owner.my.live', + }; + + it('returns input for falsy', () => { + const test = (state) => { + assert.strictEqual(makeAbsoluteURLForMeta(state, null), null); + assert.strictEqual(makeAbsoluteURLForMeta(state, ''), ''); + assert.strictEqual(makeAbsoluteURLForMeta(state, undefined), undefined); + }; + test({}); + test(SAMPLE_STATE); + }); + + it('keeps non-url meta', () => { + const test = (state) => { + assert.strictEqual(makeAbsoluteURLForMeta(state, 'This can be a title'), 'This can be a title'); + assert.strictEqual(makeAbsoluteURLForMeta(state, 'Tag 1, Tag 2'), 'Tag 1, Tag 2'); + }; + test({}); + test(SAMPLE_STATE); + }); + + it('keeps "external" urls', () => { + const test = (state) => { + assert.strictEqual(makeAbsoluteURLForMeta(state, 'https://www.hlx.page/docs'), 'https://www.hlx.page/docs'); + assert.strictEqual(makeAbsoluteURLForMeta(state, 'https://www.aem.live/docs'), 'https://www.aem.live/docs'); + assert.strictEqual(makeAbsoluteURLForMeta(state, 'https://admin.hlx.live/api'), 'https://admin.hlx.live/api'); + assert.strictEqual(makeAbsoluteURLForMeta(state, 'https://www.my.com'), 'https://www.my.com'); + assert.strictEqual(makeAbsoluteURLForMeta(state, 'https://www.sample.com/a/b/c/page.html?p=v#anchor'), 'https://www.sample.com/a/b/c/page.html?p=v#anchor'); + assert.strictEqual(makeAbsoluteURLForMeta(state, 'https://main--another-repo--owner.my.page/a/b/c/page.html'), 'https://main--another-repo--owner.my.page/a/b/c/page.html'); + assert.strictEqual(makeAbsoluteURLForMeta(state, 'https://main--another-repo--owner.my.live/a/b/c/page.html'), 'https://main--another-repo--owner.my.live/a/b/c/page.html'); + }; + test({}); + test(SAMPLE_STATE); + }); + + it('deals with invalid urls', () => { + assert.strictEqual(makeAbsoluteURLForMeta(SAMPLE_STATE, 'httpwww.sample.com/a/b/c/page.html'), 'httpwww.sample.com/a/b/c/page.html'); + }); + + it('makes absolute urls', () => { + assert.strictEqual(makeAbsoluteURLForMeta(SAMPLE_STATE, 'https://main--repo--owner.my.page/a/b/c/page.html'), 'https://www.my.com/a/b/c/page.html'); + assert.strictEqual(makeAbsoluteURLForMeta(SAMPLE_STATE, 'https://main--repo--owner.my.live/a/b/c/page.html'), 'https://www.my.com/a/b/c/page.html'); + assert.strictEqual(makeAbsoluteURLForMeta(SAMPLE_STATE, 'https://anotherbranch--repo--owner.my.page/a/b/c/page.html'), 'https://www.my.com/a/b/c/page.html'); + assert.strictEqual(makeAbsoluteURLForMeta(SAMPLE_STATE, 'https://main--repo--owner.my.page/a/b/c/page.html?p1=v1&p2=v2'), 'https://www.my.com/a/b/c/page.html?p1=v1&p2=v2'); + assert.strictEqual(makeAbsoluteURLForMeta(SAMPLE_STATE, 'https://main--repo--owner.my.page/a/b/c/page.html#anchor'), 'https://www.my.com/a/b/c/page.html#anchor'); + assert.strictEqual(makeAbsoluteURLForMeta(SAMPLE_STATE, 'https://main--repo--owner.my.page/a/b/c/page.html?p1=v1&p2=v2#anchor'), 'https://www.my.com/a/b/c/page.html?p1=v1&p2=v2#anchor'); + assert.strictEqual(makeAbsoluteURLForMeta(SAMPLE_STATE, 'https://main--repo--owner.my.page/a/b/c/page.html, https://main--repo--owner.my.live/d/e/f/page.html, combo, https://www.sample.com, https://main--repo--owner.my.page/'), 'https://www.my.com/a/b/c/page.html, https://www.my.com/d/e/f/page.html, combo, https://www.sample.com, https://www.my.com/'); + }); +}); From 13cfd577e5a72bba9b8573bf5b2d44c2e5708a35 Mon Sep 17 00:00:00 2001 From: Alexandre Capt Date: Wed, 24 Jan 2024 09:43:19 +0100 Subject: [PATCH 2/2] chore: improve value split --- src/steps/utils.js | 2 +- test/fixtures/content/page-metadata-block-urls.html | 3 ++- test/fixtures/content/page-metadata-block-urls.md | 10 ++++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/steps/utils.js b/src/steps/utils.js index babc21bf..fdafe3e9 100644 --- a/src/steps/utils.js +++ b/src/steps/utils.js @@ -236,7 +236,7 @@ export function toArray(v) { export function makeAbsoluteURLForMeta(state, meta) { if (meta && meta.startsWith('http')) { const rewrite = []; - const split = meta.split(', '); + const split = meta.split(/\s*,\s*/).map((v) => v.trim()); const previewSuffix = state.previewHost?.replace(/^.*?--/, '--'); const liveSuffix = state.liveHost?.replace(/^.*?--/, '--'); diff --git a/test/fixtures/content/page-metadata-block-urls.html b/test/fixtures/content/page-metadata-block-urls.html index 2fe45481..cedef79a 100644 --- a/test/fixtures/content/page-metadata-block-urls.html +++ b/test/fixtures/content/page-metadata-block-urls.html @@ -20,7 +20,8 @@ - + + diff --git a/test/fixtures/content/page-metadata-block-urls.md b/test/fixtures/content/page-metadata-block-urls.md index ab6701d8..98fdf208 100644 --- a/test/fixtures/content/page-metadata-block-urls.md +++ b/test/fixtures/content/page-metadata-block-urls.md @@ -16,10 +16,16 @@ hlx.page urls 2 + +

https://main--helix-pages--adobe.hlx.page/express/page3 

+

https://main--helix-pages--adobe.hlx.page/express/page4 

+ + + hlx.page urls 3