Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 4 additions & 20 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion test/declarations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ test('Declarations end with a semicolon (;)', () => {
}
`)
let expected = `@font-face {
src: url("test");
src: url('test');
font-family: Test;
}

Expand Down
22 changes: 11 additions & 11 deletions test/values.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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)
Expand All @@ -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)
})
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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)
})
Expand Down
Loading