From 0fb7abae87408bab2dd9a9c1c22ab793e55430f3 Mon Sep 17 00:00:00 2001 From: Rishabh Garg Date: Tue, 28 Mar 2023 15:59:15 +0530 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20LinkReplacer=20bug?= =?UTF-8?q?=20causing=20broken=20links=20on=20published=20post/page=20(#16?= =?UTF-8?q?514)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refs TryGhost/Team#2840 - moves the `entities.decode()` step to the `LinkReplacer` class so that it's applied to all links, not just the ones that are replaced in the email service - adds a test case to `LinkReplacer` to ensure that the `entities.decode()` step is applied to all links correctly, decoding any URLs with HTML entities in them --------- Co-authored-by: Chris Raible --- ghost/email-service/lib/email-renderer.js | 3 --- ghost/email-service/package.json | 1 - ghost/link-replacer/lib/LinkReplacer.js | 3 ++- ghost/link-replacer/package.json | 3 ++- ghost/link-replacer/test/LinkReplacer.test.js | 7 +++++++ yarn.lock | 10 +++++----- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/ghost/email-service/lib/email-renderer.js b/ghost/email-service/lib/email-renderer.js index 422b77519f..fde383874b 100644 --- a/ghost/email-service/lib/email-renderer.js +++ b/ghost/email-service/lib/email-renderer.js @@ -8,7 +8,6 @@ const {textColorForBackgroundColor, darkenToContrastThreshold} = require('@trygh const {DateTime} = require('luxon'); const htmlToPlaintext = require('@tryghost/html-to-plaintext'); const tpl = require('@tryghost/tpl'); -const entities = require('entities'); const messages = { subscriptionStatus: { @@ -293,8 +292,6 @@ class EmailRenderer { // Link tracking if (options.clickTrackingEnabled) { html = await this.#linkReplacer.replace(html, async (url) => { - // Decode any escaped entities in the url - url = new URL(entities.decode(url.toString())); // We ignore all links that contain %%{uuid}%% // because otherwise we would add tracking to links that need to be replaced first if (url.toString().indexOf('%%{uuid}%%') !== -1) { diff --git a/ghost/email-service/package.json b/ghost/email-service/package.json index 5c497041c9..8d53eb6b68 100644 --- a/ghost/email-service/package.json +++ b/ghost/email-service/package.json @@ -35,7 +35,6 @@ "@tryghost/validator": "^0.2.0", "bson-objectid": "2.0.4", "cheerio": "0.22.0", - "entities": "4.4.0", "handlebars": "4.7.7", "juice": "8.1.0", "moment-timezone": "0.5.23" diff --git a/ghost/link-replacer/lib/LinkReplacer.js b/ghost/link-replacer/lib/LinkReplacer.js index ef31fe08a6..efcf444f2e 100644 --- a/ghost/link-replacer/lib/LinkReplacer.js +++ b/ghost/link-replacer/lib/LinkReplacer.js @@ -7,6 +7,7 @@ class LinkReplacer { */ async replace(html, replaceLink) { const cheerio = require('cheerio'); + const entities = require('entities'); try { const $ = cheerio.load(html, { xml: { @@ -22,7 +23,7 @@ class LinkReplacer { if (href) { let url; try { - url = new URL(href); + url = new URL(entities.decode(href)); } catch (e) { // Ignore invalid URLs } diff --git a/ghost/link-replacer/package.json b/ghost/link-replacer/package.json index 9722e54440..cc7a42bd83 100644 --- a/ghost/link-replacer/package.json +++ b/ghost/link-replacer/package.json @@ -24,6 +24,7 @@ "sinon": "15.0.2" }, "dependencies": { - "cheerio": "0.22.0" + "cheerio": "0.22.0", + "entities": "^4.4.0" } } diff --git a/ghost/link-replacer/test/LinkReplacer.test.js b/ghost/link-replacer/test/LinkReplacer.test.js index 13490b9628..0c0f78dbb8 100644 --- a/ghost/link-replacer/test/LinkReplacer.test.js +++ b/ghost/link-replacer/test/LinkReplacer.test.js @@ -36,6 +36,13 @@ describe('LinkReplacementService', function () { assert.equal(replaced, html); }); + it('Does escape HTML characters within a link\'s href', async function () { + const html = 'link'; + const expected = 'link'; + const replaced = await linkReplacer.replace(html, url => new URL(url)); + assert.equal(replaced, expected); + }); + it('Can replace to string', async function () { const html = 'link'; const expected = 'link'; diff --git a/yarn.lock b/yarn.lock index 7b3b297dbc..91af9bf6f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13838,11 +13838,6 @@ ensure-posix-path@^1.0.0, ensure-posix-path@^1.0.1, ensure-posix-path@^1.0.2, en resolved "https://registry.yarnpkg.com/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz#3c62bdb19fa4681544289edb2b382adc029179ce" integrity sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw== -entities@4.4.0, entities@^4.2.0, entities@^4.3.0, entities@^4.4.0, entities@~4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" - integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== - entities@^1.1.1, entities@~1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" @@ -13853,6 +13848,11 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entities@^4.2.0, entities@^4.3.0, entities@^4.4.0, entities@~4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" + integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== + entities@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" From d811440b54e38bd7a216078a2538e2cbc1e41ca2 Mon Sep 17 00:00:00 2001 From: Simon Backx Date: Mon, 27 Mar 2023 10:24:34 +0200 Subject: [PATCH 2/3] Fixed batch sending snapshot date matching no issue The replacement didn't match dates with only one number. --- .../__snapshots__/batch-sending.test.js.snap | 60 +++++++++---------- .../email-service/batch-sending.test.js | 2 +- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/ghost/core/test/integration/services/email-service/__snapshots__/batch-sending.test.js.snap b/ghost/core/test/integration/services/email-service/__snapshots__/batch-sending.test.js.snap index 06a10b9b45..989e914e18 100644 --- a/ghost/core/test/integration/services/email-service/__snapshots__/batch-sending.test.js.snap +++ b/ghost/core/test/integration/services/email-service/__snapshots__/batch-sending.test.js.snap @@ -408,7 +408,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -542,7 +542,7 @@ A random test post [http://127.0.0.1:2369/r/xxxxxx?m=member-uuid] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/r/xxxxxx?m=member-uuid] @@ -1021,7 +1021,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -1147,7 +1147,7 @@ This is a test post title [http://127.0.0.1:2369/email/post-uuid/] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/email/post-uuid/] @@ -1620,7 +1620,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -1746,7 +1746,7 @@ This is a test post title [http://127.0.0.1:2369/this-is-a-test-post-title-6/] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/this-is-a-test-post-title-6/] @@ -2219,7 +2219,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -2345,7 +2345,7 @@ This is a test post title [http://127.0.0.1:2369/this-is-a-test-post-title-7/] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/this-is-a-test-post-title-7/] @@ -3365,7 +3365,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -3491,7 +3491,7 @@ This is a test post title [http://127.0.0.1:2369/r/xxxxxx?m=member-uuid] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/r/xxxxxx?m=member-uuid] @@ -5038,7 +5038,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date \\"Comment\\" @@ -5206,7 +5206,7 @@ This is a test post title [http://127.0.0.1:2369/this-is-a-test-post-title-4/] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date • [http://127.0.0.1:2369/this-is-a-test-post-title-4/#ghost-comments] @@ -5737,7 +5737,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date \\"Comment\\" @@ -5887,7 +5887,7 @@ This is a test post title [http://127.0.0.1:2369/this-is-a-test-post-title-3/] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date • [http://127.0.0.1:2369/this-is-a-test-post-title-3/#ghost-comments] @@ -6392,7 +6392,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -6577,7 +6577,7 @@ This is the main post title [http://127.0.0.1:2369/r/xxxxxx?m=member-uuid] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/r/xxxxxx?m=member-uuid] @@ -8301,7 +8301,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -8447,7 +8447,7 @@ This is a test post title [http://127.0.0.1:2369/this-is-a-test-post-title-12/] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/this-is-a-test-post-title-12/] @@ -8955,7 +8955,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -9101,7 +9101,7 @@ This is a test post title [http://127.0.0.1:2369/this-is-a-test-post-title-9/] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/this-is-a-test-post-title-9/] @@ -9609,7 +9609,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -9755,7 +9755,7 @@ This is a test post title [http://127.0.0.1:2369/this-is-a-test-post-title-8/] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/this-is-a-test-post-title-8/] @@ -10263,7 +10263,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -10409,7 +10409,7 @@ This is a test post title [http://127.0.0.1:2369/this-is-a-test-post-title-11/] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/this-is-a-test-post-title-11/] @@ -10917,7 +10917,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -11063,7 +11063,7 @@ This is a test post title [http://127.0.0.1:2369/this-is-a-test-post-title-10/] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/this-is-a-test-post-title-10/] @@ -12207,7 +12207,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -12333,7 +12333,7 @@ A random test post [http://127.0.0.1:2369/r/xxxxxx?m=member-uuid] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/r/xxxxxx?m=member-uuid] @@ -12808,7 +12808,7 @@ table.body figcaption a {
- By Joe Bloggs • 1 Jan 2050 + By Joe Bloggs • date View in browser @@ -12934,7 +12934,7 @@ A random test post [http://127.0.0.1:2369/r/xxxxxx?m=member-uuid] -By Joe Bloggs • 1 Jan 2050 +By Joe Bloggs • date View in browser [http://127.0.0.1:2369/r/xxxxxx?m=member-uuid] diff --git a/ghost/core/test/integration/services/email-service/batch-sending.test.js b/ghost/core/test/integration/services/email-service/batch-sending.test.js index 701f7063fc..558ceb75f7 100644 --- a/ghost/core/test/integration/services/email-service/batch-sending.test.js +++ b/ghost/core/test/integration/services/email-service/batch-sending.test.js @@ -155,7 +155,7 @@ async function lastEmailMatchSnapshot() { const ignoreReplacements = [ { - match: /\d{2}\s\w+\s\d{4}/g, + match: /\d{1,2}\s\w+\s\d{4}/g, replacement: 'date' }, { From 370ec93736ce8d2c14b7db8d620d1da0efcf8c30 Mon Sep 17 00:00:00 2001 From: Ghost CI <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Mar 2023 13:20:23 +0100 Subject: [PATCH 3/3] v5.40.2 --- ghost/admin/package.json | 2 +- ghost/core/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ghost/admin/package.json b/ghost/admin/package.json index 431e8e6e29..512f573333 100644 --- a/ghost/admin/package.json +++ b/ghost/admin/package.json @@ -1,6 +1,6 @@ { "name": "ghost-admin", - "version": "5.40.1", + "version": "5.40.2", "description": "Ember.js admin client for Ghost", "author": "Ghost Foundation", "homepage": "http://ghost.org", diff --git a/ghost/core/package.json b/ghost/core/package.json index 09d934e8aa..f310a1421e 100644 --- a/ghost/core/package.json +++ b/ghost/core/package.json @@ -1,6 +1,6 @@ { "name": "ghost", - "version": "5.40.1", + "version": "5.40.2", "description": "The professional publishing platform", "author": "Ghost Foundation", "homepage": "https://ghost.org",