-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix handling of CSS
content
property (#1658)
* Fix handling of content property * Add tests and improve docs * Fix typo in test
- Loading branch information
Showing
3 changed files
with
200 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
'@compiled/babel-plugin': patch | ||
--- | ||
|
||
Fix handling of `content` property. | ||
|
||
- The value of the `content` property will no longer automatically have quotes erroneously added around it, if the value is one of `open-quote`, `counter(...)`, `url(...)`, `inherit`, `none`, and so on. | ||
- The full regex used to check is as follows: `/^([A-Za-z\-]+\([^]*|[^]*-quote|inherit|initial|none|normal|revert|unset)(\s|$)/` |
177 changes: 177 additions & 0 deletions
177
packages/babel-plugin/src/styled/__tests__/content-property.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
import type { TransformOptions } from '../../test-utils'; | ||
import { transform as transformCode } from '../../test-utils'; | ||
|
||
describe('handling of values for CSS `content` property', () => { | ||
beforeAll(() => { | ||
process.env.AUTOPREFIXER = 'off'; | ||
}); | ||
|
||
afterAll(() => { | ||
delete process.env.AUTOPREFIXER; | ||
}); | ||
|
||
const transform = (code: string, opts: TransformOptions = {}) => | ||
transformCode(code, { pretty: false, ...opts }); | ||
|
||
// Tests are based on those covered by vanilla-extract, credit goes to them :) | ||
// | ||
// https://github.com/vanilla-extract-css/vanilla-extract/blob/a623c1c65a543afcedb9feb30a7fe20452b99a95/packages/css/src/transformCss.test.ts#L639 | ||
|
||
it('should handle blank content', () => { | ||
const code = ` | ||
import { styled } from '@compiled/react'; | ||
const ListItem = styled.div({ | ||
content: '', | ||
}); | ||
`; | ||
|
||
const actual = transform(code, { pretty: true }); | ||
expect(actual).toContain('._1sb2b3bt{content:""}'); | ||
}); | ||
|
||
it('should handle blank content (variant #1)', () => { | ||
const code = ` | ||
import { styled } from '@compiled/react'; | ||
const ListItem = styled.div({ | ||
content: \`\`, | ||
}); | ||
`; | ||
|
||
const actual = transform(code, { pretty: true }); | ||
expect(actual).toContain('._1sb2b3bt{content:""}'); | ||
}); | ||
|
||
it('should handle blank content (variant #2)', () => { | ||
const code = ` | ||
import { styled } from '@compiled/react'; | ||
const hello = ''; | ||
const ListItem = styled.div({ | ||
content: \`\${hello}\`, | ||
}); | ||
`; | ||
|
||
const actual = transform(code, { pretty: true }); | ||
expect(actual).toContain('._1sb2b3bt{content:""}'); | ||
}); | ||
|
||
it('should handle blank content (variant #2)', () => { | ||
const code = ` | ||
import { styled } from '@compiled/react'; | ||
const hello = 'this is a string'; | ||
const ListItem = styled.div({ | ||
content: hello, | ||
}); | ||
`; | ||
|
||
const actual = transform(code, { pretty: true }); | ||
expect(actual).toContain('._1sb21icm{content:"this is a string"}'); | ||
}); | ||
|
||
it('should add quotes to custom content values', () => { | ||
const code = ` | ||
import { styled } from '@compiled/react'; | ||
const ListItem = styled.div({ | ||
content: 'hello', | ||
}); | ||
`; | ||
|
||
const actual = transform(code, { pretty: true }); | ||
expect(actual).toContain('._1sb21e8g{content:"hello"}'); | ||
}); | ||
|
||
it('should not add quotes if they exist already', () => { | ||
const code = ` | ||
import { styled } from '@compiled/react'; | ||
const ListItem = styled.div({ | ||
content: "'hello'", | ||
}); | ||
`; | ||
|
||
const actual = transform(code, { pretty: true }); | ||
expect(actual).toContain("._1sb25hbz{content:'hello'}"); | ||
}); | ||
|
||
it('should not add quotes if they exist already (variant)', () => { | ||
const code = ` | ||
import { styled } from '@compiled/react'; | ||
const ListItem = styled.div({ | ||
content: '"hello"', | ||
}); | ||
`; | ||
|
||
const actual = transform(code, { pretty: true }); | ||
expect(actual).toContain('._1sb21e8g{content:"hello"}'); | ||
}); | ||
|
||
it("should not add quotes to content values that shouldn't accept them", () => { | ||
const code = ` | ||
import { styled } from '@compiled/react'; | ||
const ListItem = styled.div({ | ||
'._01 &': { content: 'none' }, | ||
'._02 &': { content: 'url("http://www.example.com/test.png")' }, | ||
'._03 &': { content: 'linear-gradient(#e66465, #9198e5)' }, | ||
'._04 &': { | ||
content: 'image-set("image1x.png" 1x, "image2x.png" 2x)', | ||
}, | ||
'._05 &': { | ||
content: | ||
'url("http://www.example.com/test.png") / "This is the alt text"', | ||
}, | ||
'._06 &': { content: '"prefix"' }, | ||
'._07 &': { content: 'counter(chapter_counter)' }, | ||
'._08 &': { content: 'counter(chapter_counter, upper-roman)' }, | ||
'._09 &': { content: 'counters(section_counter, ".")' }, | ||
'._10 &': { | ||
content: | ||
'counters(section_counter, ".", decimal-leading-zero)', | ||
}, | ||
'._11 &': { content: 'attr(value string)' }, | ||
'._12 &': { content: 'open-quote' }, | ||
'._13 &': { content: 'close-quote' }, | ||
'._14 &': { content: 'no-open-quote' }, | ||
'._15 &': { content: 'no-close-quote' }, | ||
'._16 &': { content: 'open-quote counter(chapter_counter)' }, | ||
'._17 &': { content: 'inherit' }, | ||
'._18 &': { content: 'initial' }, | ||
'._19 &': { content: 'revert' }, | ||
'._20 &': { content: 'unset' }, | ||
}); | ||
`; | ||
|
||
const actual = transform(code, { pretty: true }); | ||
const expectedStrings = [ | ||
'._20 ._dqocn7od{content:unset}', | ||
'._19 ._kyq719ly{content:revert}', | ||
'._18 ._ox6v18uv{content:initial}', | ||
'._17 ._1do11kw7{content:inherit}', | ||
'._16 ._17yjbbkt{content:open-quote counter(chapter_counter)}', | ||
'._15 ._13gv16xt{content:no-close-quote}', | ||
'._14 ._1gw4qmeg{content:no-open-quote}', | ||
'._13 ._1erv1lzr{content:close-quote}', | ||
'._12 ._yz5n12u0{content:open-quote}', | ||
'._11 ._1sv1f7m1{content:attr(value string)}', | ||
'._10 ._11jd1td3{content:counters(section_counter,".",decimal-leading-zero)}', | ||
'._09 ._1vjjgvpy{content:counters(section_counter,".")}', | ||
'._08 ._tc0r17sh{content:counter(chapter_counter,upper-roman)}', | ||
'._07 ._1g4mlfyt{content:counter(chapter_counter)}', | ||
'._06 ._4g5v1dlo{content:"prefix"}', | ||
'._05 ._10o677hy{content:url("http://www.example.com/test.png") /"This is the alt text"}', | ||
'._04 ._124v19iq{content:image-set("image1x.png" 1x,"image2x.png" 2x)}', | ||
'._03 ._qi2v1f55{content:linear-gradient(#e66465,#9198e5)}', | ||
'._02 ._1gdz1dgq{content:url("http://www.example.com/test.png")}', | ||
'._01 ._1sagglyw{content:none}', | ||
]; | ||
|
||
for (const expected of expectedStrings) { | ||
expect(actual).toContain(expected); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters