From ed75136a3274b6ec383c43d8af91e80032118c38 Mon Sep 17 00:00:00 2001 From: Giuseppe Date: Thu, 5 Oct 2017 21:54:46 +0200 Subject: [PATCH] Fix animation names not being scoped in optimizeForSpeed mode (#294) --- src/lib/style-transform.js | 17 ++++--- test/styles.js | 92 +++++++++++++++++++++++--------------- 2 files changed, 66 insertions(+), 43 deletions(-) diff --git a/src/lib/style-transform.js b/src/lib/style-transform.js index 1ee2f168..01c79e03 100644 --- a/src/lib/style-transform.js +++ b/src/lib/style-transform.js @@ -76,6 +76,7 @@ function sourceMapsPlugin(...args) { let isSplitRulesEnabled = false let splitRules = [] let splitRulesQueue = [] +let scopeHash const nestedAtRules = ['m', 's', 'd', 'k', '-'] function splitRulesPlugin( @@ -119,10 +120,13 @@ function splitRulesPlugin( const selectrs = selectors.join(',') if (nestedAtRules.indexOf(selectrs.charAt(1)) === -1) { splitRulesQueue.push(`${selectrs}${content}`) + } else if (selectrs.charAt(1) === 'k') { + const animationName = scopeHash.replace(/^\./, '-') + splitRulesQueue.push( + `@-webkit-${selectrs.slice(1)}${animationName}{${content}}` + ) + splitRulesQueue.push(`${selectrs}${animationName}{${content}}`) } else { - if (selectrs.charAt(1) === 'k') { - splitRulesQueue.push(`@-webkit-${selectrs.slice(1)}{${content}}`) - } splitRulesQueue.push(`${selectrs}{${content}}`) } } @@ -139,19 +143,20 @@ stylis.set({ /** * Public transform function * - * @param {String} prefix + * @param {String} hash * @param {String} styles * @param {Object} settings * @return {string} */ -function transform(prefix, styles, settings = {}) { +function transform(hash, styles, settings = {}) { generator = settings.generator offset = settings.offset filename = settings.filename isSplitRulesEnabled = settings.splitRules splitRules = [] + scopeHash = hash - const cssString = stylis(prefix, styles) + const cssString = stylis(scopeHash, styles) if (isSplitRulesEnabled) { return splitRules diff --git a/test/styles.js b/test/styles.js index c2bfe68c..f3a2a552 100644 --- a/test/styles.js +++ b/test/styles.js @@ -11,35 +11,23 @@ test('transpile styles with attributes', async t => { }) test('throws when using nesting', t => { - const fixtures = [ - `div { &:hover { color: red } }`, - - `div { + const fixtures = [`div { &:hover { color: red } }`, `div { color: green; - &:hover { color: red } }`, - - `:hover { div { color: red } }`, - - `@media all { + &:hover { color: red } }`, `:hover { div { color: red } }`, `@media all { div { &:hover { color: red } } - }`, - - `* { div { color: red } + }`, `* { div { color: red } &.test { color: red; } - }`, - - `span {} + }`, `span {} .test { color: red; div& { color: red; } - }` - ] + }`] fixtures.forEach(fixture => { t.throws(() => transform('', fixture)) @@ -48,29 +36,15 @@ test('throws when using nesting', t => { }) test("doesn't throw when using at-rules", t => { - const fixtures = [ - '@media (min-width: 480px) { div { color: red } }', - - `span {} - @media (min-width: 480px) { div { color: red } }`, - - `@media (min-width: 480px) { div { color: red } } - span {}`, - - `:hover {} - @media (min-width: 480px) { div { color: red } }`, - - `:hover { color: green } - @media (min-width: 480px) { div { color: red } }`, - - `@media (min-width: 480px) { div {} }`, - - `@keyframes foo { + const fixtures = ['@media (min-width: 480px) { div { color: red } }', `span {} + @media (min-width: 480px) { div { color: red } }`, `@media (min-width: 480px) { div { color: red } } + span {}`, `:hover {} + @media (min-width: 480px) { div { color: red } }`, `:hover { color: green } + @media (min-width: 480px) { div { color: red } }`, `@media (min-width: 480px) { div {} }`, `@keyframes foo { 0% { opacity: 0 } 100% { opacity: 1} } - ` - ] + `] fixtures.forEach(fixture => { t.notThrows(() => transform('', fixture)) @@ -184,4 +158,48 @@ test('splits rules for `optimizeForSpeed`', t => { '@namespace svg url(http://www.w3.org/2000/svg)' ]) assert('@page :first { margin: 1in; }', ['@page :first{margin:1in;}']) + + assert(` + div { + animation: fade-in ease-in 1; + animation-fill-mode: forwards; + animation-duration: 500ms; + opacity: 0; + } + @keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } + } + `, ['div.jsx-123{-webkit-animation:fade-in-jsx-123 ease-in 1;animation:fade-in-jsx-123 ease-in 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-duration:500ms;animation-duration:500ms;opacity:0;}', '@-webkit-keyframes fade-in-jsx-123{from{opacity:0;}to{opacity:1;}}', '@keyframes fade-in-jsx-123{from{opacity:0;}to{opacity:1;}}'], '.jsx-123') + + assert( + ` + div { + animation: fade-in ease-in 1; + animation-fill-mode: forwards; + animation-duration: 500ms; + opacity: 0; + } + + @keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } + } + `, + [ + 'div{-webkit-animation:fade-in ease-in 1;animation:fade-in ease-in 1;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-duration:500ms;animation-duration:500ms;opacity:0;}', + '@-webkit-keyframes fade-in{from{opacity:0;}to{opacity:1;}}', + '@keyframes fade-in{from{opacity:0;}to{opacity:1;}}' + ] + ) })