diff --git a/src/lib/index.ts b/src/lib/index.ts index ff9b022..a6b2fc2 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -61,7 +61,6 @@ export type FormatOptions = { } const UNQUOTE_RE = /(?:^['"])|(?:['"]$)/g -const DATA_URL_RE = /^['"]?data:/i const FONT_SLASH_RE = /\s*\/\s*/ const ATRULE_COLON_COMMA_RE = /\s*([:,])/g const ATRULE_PAREN_TEXT_RE = /\)([a-zA-Z])/g @@ -93,26 +92,11 @@ function print_string(str: string | number | null, quote?: '"' | "'"): string { return quote + inner + quote } +/** Prints a `url(...)`: lowercases the `url(` keyword but leaves quote style + * untouched. A Url node's text always starts with `url(` (any casing) — it's + * how the parser identifies the node as a Url in the first place. */ function print_url(node: Url): string { - let value = node.value ?? '' - let unquoted = unquote(value) - - let inner: string - if (DATA_URL_RE.test(value)) { - let has_double = unquoted.includes('"') - let has_single = unquoted.includes("'") - if (has_double && has_single) { - inner = print_string(unquoted.replaceAll('"', '%22'), '"') - } else if (has_double || has_single) { - inner = print_string(unquoted) - } else { - inner = unquoted - } - } else { - inner = print_string(value) - } - - return 'url(' + inner + CLOSE_PARENTHESES + return 'url(' + node.text.slice(4) } function print_operator(node: Operator, optional_space = SPACE): string { diff --git a/test/declarations.test.ts b/test/declarations.test.ts index d915342..75c55fe 100644 --- a/test/declarations.test.ts +++ b/test/declarations.test.ts @@ -27,7 +27,7 @@ test('Declarations end with a semicolon (;)', () => { } `) let expected = `@font-face { - src: url("test"); + src: url('test'); font-family: Test; } diff --git a/test/values.test.ts b/test/values.test.ts index 10ebc7c..d63de21 100644 --- a/test/values.test.ts +++ b/test/values.test.ts @@ -280,7 +280,7 @@ test('Does not mess up quotes inside `content`', () => { expect(actual).toBe(expected) }) -test('adds quotes around strings in url()', () => { +test('leaves url() quoting untouched', () => { let actual = format(`a { background-image: url("star.gif"); list-style-image: url('../images/bullet.jpg'); @@ -293,12 +293,12 @@ test('adds quotes around strings in url()', () => { }`) let expected = `a { background-image: url("star.gif"); - list-style-image: url("../images/bullet.jpg"); + list-style-image: url('../images/bullet.jpg'); content: url("pdficon.jpg"); - cursor: url("mycursor.cur"); - border-image-source: url("/media/diamonds.png"); - src: url("fantasticfont.woff"); - offset-path: url("#path"); + cursor: url(mycursor.cur); + border-image-source: url(/media/diamonds.png); + src: url('fantasticfont.woff'); + offset-path: url(#path); mask-image: url("masks.svg#mask1"); }` expect(actual).toEqual(expected) @@ -314,7 +314,7 @@ test.each([ }`) let expected = `test { background-image: url('${input}'); - background-image: url('${input}'); + background-image: url(${input}); }` expect(actual).toEqual(expected) }) @@ -337,7 +337,7 @@ test.each([ expect(actual).toBe(expected) }) -test('wraps data: URL in single quotes when it contains double quotes', () => { +test('leaves a single-quoted data: URL containing double quotes untouched', () => { let input = `.a { background: url('data:image/svg+xml,%3Csvg fill="red"%3E%3C/svg%3E'); }` let actual = format(input) let expected = `.a { @@ -346,7 +346,7 @@ test('wraps data: URL in single quotes when it contains double quotes', () => { expect(actual).toEqual(expected) }) -test('wraps data: URL in double quotes when it contains single quotes', () => { +test('leaves a double-quoted data: URL containing single quotes untouched', () => { let input = `.a { background: url("data:image/svg+xml,%3Csvg fill='red'%3E%3C/svg%3E"); }` let actual = format(input) let expected = `.a { @@ -355,11 +355,11 @@ test('wraps data: URL in double quotes when it contains single quotes', () => { expect(actual).toEqual(expected) }) -test('encodes double quotes when data: URL contains both quote types', () => { +test('leaves a data: URL with both quote types untouched', () => { let input = `.a { background: url('data:image/svg+xml,%3Csvg fill="x" alt=\\'y\\'%3E'); }` let actual = format(input) let expected = `.a { - background: url("data:image/svg+xml,%3Csvg fill=%22x%22 alt=\\'y\\'%3E"); + background: url('data:image/svg+xml,%3Csvg fill="x" alt=\\'y\\'%3E'); }` expect(actual).toEqual(expected) })