diff --git a/__tests__/applyComplexClasses.test.js b/__tests__/applyComplexClasses.test.js index f2de66800..2f7d28528 100644 --- a/__tests__/applyComplexClasses.test.js +++ b/__tests__/applyComplexClasses.test.js @@ -12,12 +12,61 @@ function run(input, config = {}) { test('it copies class declarations into itself', () => { const output = '.a { color: red; } .b { color: red; }' + expect.assertions(2) + return run('.a { color: red; } .b { @apply a; }').then(result => { expect(result.css).toMatchCss(output) expect(result.warnings().length).toBe(0) }) }) +test('apply values can contain tabs', () => { + const input = ` + .a { + @apply p-4\tm-4; + } + ` + + const expected = ` + .a { + margin: 1rem; + padding: 1rem; + } + ` + + expect.assertions(2) + + return run(input).then(result => { + expect(result.css).toMatchCss(expected) + expect(result.warnings().length).toBe(0) + }) +}) + +test('apply values can contain newlines', () => { + const input = ` + .a { + @apply p-4 m-4 + flex flex-col; + } + ` + + const expected = ` + .a { + display: flex; + flex-direction: column; + margin: 1rem; + padding: 1rem; + } + ` + + expect.assertions(2) + + return run(input).then(result => { + expect(result.css).toMatchCss(expected) + expect(result.warnings().length).toBe(0) + }) +}) + test('selectors with invalid characters do not need to be manually escaped', () => { const input = ` .a\\:1\\/2 { color: red; } @@ -29,6 +78,8 @@ test('selectors with invalid characters do not need to be manually escaped', () .b { color: red; } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -46,6 +97,8 @@ test('it removes important from applied classes by default', () => { .b { color: red; } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -63,6 +116,8 @@ test('applied rules can be made !important', () => { .b { color: red !important; } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -79,12 +134,16 @@ test('cssnext custom property sets are no longer supported', () => { } ` + expect.assertions(1) + return run(input).catch(e => { expect(e).toMatchObject({ name: 'CssSyntaxError' }) }) }) test('it fails if the class does not exist', () => { + expect.assertions(1) + return run('.b { @apply a; }').catch(e => { expect(e).toMatchObject({ name: 'CssSyntaxError' }) }) @@ -110,6 +169,8 @@ test('applying classes that are defined in a media query is supported', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(output) expect(result.warnings().length).toBe(0) @@ -149,6 +210,8 @@ test('applying classes that are used in a media query is supported', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(output) expect(result.warnings().length).toBe(0) @@ -176,6 +239,8 @@ test('it matches classes that include pseudo-selectors', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(output) expect(result.warnings().length).toBe(0) @@ -212,6 +277,8 @@ test('it matches classes that have multiple rules', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(output) expect(result.warnings().length).toBe(0) @@ -244,6 +311,8 @@ test('applying a class that appears multiple times in one selector', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(output) expect(result.warnings().length).toBe(0) @@ -259,6 +328,8 @@ test('you can apply utility classes that do not actually exist as long as they w .foo { margin-top: 1rem; } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -271,6 +342,8 @@ test('the shadow lookup is only used if no @tailwind rules were in the source tr .foo { @apply mt-4; } ` + expect.assertions(1) + return run(input).catch(e => { expect(e).toMatchObject({ name: 'CssSyntaxError' }) }) @@ -301,6 +374,8 @@ test('you can apply a class that is defined in multiple rules', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -321,6 +396,8 @@ test('you can apply a class that is defined in a media query', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -339,6 +416,8 @@ test('you can apply pseudo-class variant utilities', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -359,6 +438,8 @@ test('you can apply responsive pseudo-class variant utilities', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -397,6 +478,8 @@ test('you can apply the container component', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -428,6 +511,8 @@ test('classes are applied according to CSS source order, not apply order', () => } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -458,6 +543,8 @@ test('you can apply utilities with multi-class selectors like group-hover varian } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -488,6 +575,8 @@ test('you can apply classes recursively', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -523,6 +612,8 @@ test('applied classes are always inserted before subsequent declarations in the } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -554,6 +645,8 @@ test('adjacent rules are collapsed after being applied', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -602,6 +695,8 @@ test('applying a class applies all instances of that class, even complex selecto } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -635,6 +730,8 @@ test('you can apply classes to rules within at-rules', () => { } ` + expect.assertions(2) + return run(input).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -658,6 +755,8 @@ describe('using apply with the prefix option', () => { }, ]) + expect.assertions(2) + return run(input, config).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -682,6 +781,8 @@ describe('using apply with the prefix option', () => { }, ]) + expect.assertions(2) + return run(input, config).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -700,6 +801,8 @@ describe('using apply with the prefix option', () => { }, ]) + expect.assertions(1) + return run(input, config).catch(e => { expect(e).toMatchObject({ name: 'CssSyntaxError' }) }) @@ -723,6 +826,8 @@ describe('using apply with the prefix option', () => { }, ]) + expect.assertions(2) + return run(input, config).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -747,6 +852,8 @@ describe('using apply with the prefix option', () => { }, ]) + expect.assertions(2) + return run(input, config).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -792,6 +899,8 @@ describe('using apply with the prefix option', () => { }, ]) + expect.assertions(2) + return run(input, config).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -815,6 +924,8 @@ describe('using apply with the prefix option', () => { }, ]) + expect.assertions(2) + return run(input, config).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) @@ -843,6 +954,8 @@ test('you can apply utility classes when a selector is used for the important op }, ]) + expect.assertions(2) + return run(input, config).then(result => { expect(result.css).toMatchCss(expected) expect(result.warnings().length).toBe(0) diff --git a/src/flagged/applyComplexClasses.js b/src/flagged/applyComplexClasses.js index 820f2422f..6e5298cbf 100644 --- a/src/flagged/applyComplexClasses.js +++ b/src/flagged/applyComplexClasses.js @@ -220,7 +220,7 @@ function processApplyAtRules(css, lookupTree, config) { importantEntries, applyUtilityNames, important = importantEntries.length > 0, - ] = _.partition(applyRule.params.split(' '), n => n === '!important') + ] = _.partition(applyRule.params.split(/[\s\t\n]+/g), n => n === '!important') const currentUtilityNames = extractUtilityNames(rule.selector)