From ddd359a0322e3de2180146e04d0da99a631a081f Mon Sep 17 00:00:00 2001 From: Bart Veneman Date: Tue, 10 Feb 2026 18:14:50 +0100 Subject: [PATCH] fix: correctly add or omit quotes around `url()` value --- index.ts | 8 +++++++- test/values.test.ts | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/index.ts b/index.ts index a4e790e..710fbbd 100644 --- a/index.ts +++ b/index.ts @@ -153,7 +153,13 @@ export function format(css: string, { minify = false, tab_size = undefined }: Fo parts.push(OPEN_PARENTHESES, print_list(node.children), CLOSE_PARENTHESES) } else if (node.type === NODE.URL && typeof node.value === 'string') { parts.push('url(') - parts.push(print_string(node.value)) + let { value } = node + // if the value starts with data:, 'data:, "data: + if (/^['"]?data:/i.test(value)) { + parts.push(unquote(value)) + } else { + parts.push(print_string(value)) + } parts.push(CLOSE_PARENTHESES) } else { parts.push(node.text) diff --git a/test/values.test.ts b/test/values.test.ts index fcfd1aa..b748e20 100644 --- a/test/values.test.ts +++ b/test/values.test.ts @@ -283,3 +283,36 @@ test('adds quotes around strings in url()', () => { }` expect(actual).toEqual(expected) }) + +test.each([ + `data:image/svg+xml;utf8,`, + `data:image/svg+xml;utf8,`, +])('Does not mess up URLs with inlined SVG', (input) => { + let actual = format(`test { + background-image: url('${input}'); + background-image: url(${input}); + }`) + let expected = `test { + background-image: url(${input}); + background-image: url(${input}); +}` + expect(actual).toEqual(expected) +}) + +test.each([ + // Examples from https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes/data + 'data:,Hello%2C%20World%21', + 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==', + 'data:text/html,%3Ch1%3EHello%2C%20World%21%3C%2Fh1%3E', + 'data:text/html,%3Cscript%3Ealert%28%27hi%27%29%3B%3C%2Fscript%3E', + // from https://github.com/projectwallace/format-css/issues/144 + `data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgaGVpZ2h0PSIyNHB4IiB3aWR0aD0iMjRweCI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJsaW5lYXItZ3JhZGllbnQiIHgxPSIyMi4zMSIgeTE9IjIzLjYyIiB4Mj0iMy43MyIgeTI9IjMuMDUiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNlOTM3MjIiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNmODZmMjUiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48dGl0bGU+TWFnbmlmaWVyPC90aXRsZT48cGF0aCBmaWxsPSJ1cmwoI2xpbmVhci1ncmFkaWVudCkiIGQ9Ik0yMy4zMyAyMC4xbC00LjczLTQuNzRhMTAuMDYgMTAuMDYgMCAxIDAtMy4yMyAzLjIzbDQuNzQgNC43NGEyLjI5IDIuMjkgMCAxIDAgMy4yMi0zLjIzem0tMTcuNDgtNS44NGE1Ljk0IDUuOTQgMCAxIDEgOC40MiAwIDYgNiAwIDAgMS04LjQyIDB6Ii8+PC9zdmc+`, +])('Does not mess up URLs with encoded inlined content: %s', (input) => { + let actual = format(`test { + background-image: url(${input}); + }`) + let expected = `test { + background-image: url(${input}); +}` + expect(actual).toBe(expected) +})