From 2d105e4204d312a57c6a1c21e74c107eaf1b2d24 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Tue, 9 Apr 2024 12:14:59 +0100 Subject: [PATCH] fix: regression for astro attributes escaping --- .changeset/large-knives-confess.md | 5 +++++ packages/astro/src/runtime/server/render/util.ts | 9 +++++---- packages/astro/test/astro-attrs.test.js | 6 ++++++ .../test/fixtures/astro-attrs/src/pages/index.astro | 3 ++- 4 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 .changeset/large-knives-confess.md diff --git a/.changeset/large-knives-confess.md b/.changeset/large-knives-confess.md new file mode 100644 index 000000000000..364054ce3793 --- /dev/null +++ b/.changeset/large-knives-confess.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Fixes a regression where some very **specific** code rendered using `expressive-code` was not escaped properly. diff --git a/packages/astro/src/runtime/server/render/util.ts b/packages/astro/src/runtime/server/render/util.ts index 5e1fff9fc0ea..39414591f58f 100644 --- a/packages/astro/src/runtime/server/render/util.ts +++ b/packages/astro/src/runtime/server/render/util.ts @@ -105,7 +105,7 @@ Make sure to use the static attribute syntax (\`${key}={value}\`) instead of the } // Prevents URLs in attributes from being escaped in static builds - if (typeof value === 'string' && value.includes('&') && urlCanParse(value)) { + if (typeof value === 'string' && value.includes('&') && isHttpUrl(value)) { return markHTMLString(` ${key}="${toAttributeString(value, false)}"`); } @@ -247,10 +247,11 @@ export function promiseWithResolvers(): PromiseWithResolvers { }; } -function urlCanParse(url: string) { +const VALID_PROTOCOLS = ['http:', 'https:']; +function isHttpUrl(url: string) { try { - new URL(url); - return true; + const parsedUrl = new URL(url); + return VALID_PROTOCOLS.includes(parsedUrl.protocol); } catch { return false; } diff --git a/packages/astro/test/astro-attrs.test.js b/packages/astro/test/astro-attrs.test.js index b307a3f39707..f4a0140427a5 100644 --- a/packages/astro/test/astro-attrs.test.js +++ b/packages/astro/test/astro-attrs.test.js @@ -37,6 +37,12 @@ describe('Attributes', async () => { true ); + // cheerio will unescape the values, so checking that the url rendered unescaped to begin with has to be done manually + assert.equal( + html.includes('cmd: echo "foo" && echo "bar" > /tmp/hello.txt'), + true + ); + for (const id of Object.keys(attrs)) { const { attribute, value } = attrs[id]; const attr = $(`#${id}`).attr(attribute); diff --git a/packages/astro/test/fixtures/astro-attrs/src/pages/index.astro b/packages/astro/test/fixtures/astro-attrs/src/pages/index.astro index b7e617e365d2..7ac96635fd14 100644 --- a/packages/astro/test/fixtures/astro-attrs/src/pages/index.astro +++ b/packages/astro/test/fixtures/astro-attrs/src/pages/index.astro @@ -6,6 +6,7 @@ + /tmp/hello.txt"} /> - \ No newline at end of file +