From b9f2482eb58f9b9bfec8b83334c27b1d6110a465 Mon Sep 17 00:00:00 2001 From: Chris Joel Date: Fri, 4 Dec 2015 17:06:41 -0800 Subject: [PATCH] Non-destructive `@keyframes` rule transformation. Previously, the transformer did not disambiguate selectors in `@media` blocks and keyframes in `@keyframes` blocks. Now, the transformer can safely transform `@keyframes` blocks. Before a selector is transformed, if the selector has a parent, it is checked. If the checked parent is a `@keyframes` rule, the selector transformation is skipped. Element-specific `@keyframes` are suffixed with the scoped element name. For example, `@keyframes foo` in an element scoped with `x-el-0` will by transformed to `@keyframes foo-x-el-0`. References to that animation in the element's local styles will be updated as well. Added tests for the new keyframes transformation. --- src/lib/css-parse.html | 2 + src/lib/custom-style.html | 2 +- src/lib/style-extends.html | 6 +- src/lib/style-properties.html | 99 +++- src/lib/style-transformer.html | 8 +- src/lib/style-util.html | 29 +- test/smoke/keyframes.html | 60 +++ test/unit/styling-cross-scope-apply.html | 98 +++- test/unit/styling-cross-scope-var.html | 630 +++++++++++++---------- test/unit/styling-scoped-elements.html | 63 +++ test/unit/styling-scoped.html | 41 +- 11 files changed, 747 insertions(+), 291 deletions(-) create mode 100644 test/smoke/keyframes.html diff --git a/src/lib/css-parse.html b/src/lib/css-parse.html index 13b1ec32..7dcaa1a9 100644 --- a/src/lib/css-parse.html +++ b/src/lib/css-parse.html @@ -73,6 +73,8 @@ Polymer.CssParse = (function() { node.type = this.types.MEDIA_RULE; } else if (s.match(this._rx.keyframesRule)) { node.type = this.types.KEYFRAMES_RULE; + node.keyframesName = + node.selector.split(this._rx.multipleSpaces).pop(); } } else { if (s.indexOf(this.VAR_START) === 0) { diff --git a/src/lib/custom-style.html b/src/lib/custom-style.html index a90b2c34..2530b885 100644 --- a/src/lib/custom-style.html +++ b/src/lib/custom-style.html @@ -139,7 +139,7 @@ Note, all features of `custom-style` are available when defining styles as part e.textContent; } if (e.textContent) { - styleUtil.forEachStyleRule(styleUtil.rulesForStyle(e), function(rule) { + styleUtil.forEachRule(styleUtil.rulesForStyle(e), function(rule) { styleTransformer.documentRule(rule); }); // Allow all custom-styles defined in this turn to register diff --git a/src/lib/style-extends.html b/src/lib/style-extends.html index 93b2fe62..414f1ba2 100644 --- a/src/lib/style-extends.html +++ b/src/lib/style-extends.html @@ -16,7 +16,7 @@ Polymer.StyleExtends = (function() { var styleUtil = Polymer.StyleUtil; return { - + hasExtends: function(cssText) { return Boolean(cssText.match(this.rx.EXTEND)); }, @@ -24,7 +24,7 @@ Polymer.StyleExtends = (function() { transform: function(style) { var rules = styleUtil.rulesForStyle(style); var self = this; - styleUtil.forEachStyleRule(rules, function(rule) { + styleUtil.forEachRule(rules, function(rule) { var map = self._mapRule(rule); if (rule.parent) { var m; @@ -72,7 +72,7 @@ Polymer.StyleExtends = (function() { // TODO: this misses `%foo, .bar` as an unetended selector but // this seems rare and could possibly be unsupported. source.selector = source.selector.replace(this.rx.STRIP, ''); - source.selector = (source.selector && source.selector + ',\n') + + source.selector = (source.selector && source.selector + ',\n') + target.selector; if (source.extends) { source.extends.forEach(function(e) { diff --git a/src/lib/style-properties.html b/src/lib/style-properties.html index dec71dde..544a0be9 100644 --- a/src/lib/style-properties.html +++ b/src/lib/style-properties.html @@ -25,11 +25,15 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN // decorates styles with rule info and returns an array of used style // property names decorateStyles: function(styles) { - var self = this, props = {}; + var self = this, props = {}, keyframes = []; styleUtil.forRulesInStyles(styles, function(rule) { self.decorateRule(rule); self.collectPropertiesInCssText(rule.propertyInfo.cssText, props); + }, function onKeyframesRule(rule) { + keyframes.push(rule); }); + // Cache all found keyframes rules for later reference: + styles._keyframes = keyframes; // return this list of property names *consumes* in these styles. var names = []; for (var i in props) { @@ -87,7 +91,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN var parts = cssText.split(';'); for (var i=0, p; i @keyframes foo-anim-x-foo-0 + _scopeKeyframes: function(rule, scopeId) { + rule.keyframesNameRx = new RegExp(rule.keyframesName, 'g'); + rule.transformedKeyframesName = rule.keyframesName + '-' + scopeId; + rule.transformedSelector = rule.transformedSelector || rule.selector; + rule.selector = rule.transformedSelector.replace( + rule.keyframesName, rule.transformedKeyframesName); + }, + // Strategy: x scope shim a selector e.g. to scope `.x-foo-42` (via classes): // non-host selector: .a.x-foo -> .x-foo-42 .a.x-foo // host selector: x-foo.wide -> x-foo.x-foo-42.wide @@ -359,6 +451,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN // var(--a, fallback-literal(with-one-nested-parentheses)) VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)))[\s]*?\)/gi, VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gi, + ANIMATION_MATCH: /(animation\s*:)|(animation-name\s*:)/, IS_VAR: /^--/, BRACKETED: /\{[^}]*\}/g, HOST_PREFIX: '(?:^|[^.#[:])', diff --git a/src/lib/style-transformer.html b/src/lib/style-transformer.html index 1a072f76..406f889c 100644 --- a/src/lib/style-transformer.html +++ b/src/lib/style-transformer.html @@ -148,8 +148,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN // transforms a css rule to a scoped rule. _transformRule: function(rule, transformer, scope, hostScope) { var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP); - for (var i=0, l=p$.length, p; (i + + + + + + + + + + + + +

Text should be the color blue. Background should animate from the color red to the color yellow, and then become transparent.

+ red + +

Text should be the color green. Background should animate from the color blue to the color yellow, and then become transparent.

+ blue + + diff --git a/test/unit/styling-cross-scope-apply.html b/test/unit/styling-cross-scope-apply.html index 06bfaac1..ed2c6531 100644 --- a/test/unit/styling-cross-scope-apply.html +++ b/test/unit/styling-cross-scope-apply.html @@ -25,7 +25,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN :host { display: block; } - + #story-card .story-content { font-family: 'Roboto', sans-serif; font-size: 1.2em; @@ -55,7 +55,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN background: url(http://www.google.com/icon.png); }; } - + #mixin1 { @apply(--mixin1); } @@ -95,6 +95,67 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN + + + + + -