|
179 | 179 | rule.cssText = output;
|
180 | 180 | },
|
181 | 181 |
|
| 182 | + // Apply keyframe transformations to the cssText of a given rule. The |
| 183 | + // keyframeTransforms object is a map of keyframe names to transformer |
| 184 | + // functions which take in cssText and spit out transformed cssText. |
| 185 | + applyKeyframeTransforms: function(rule, keyframeTransforms) { |
| 186 | + var output = rule.cssText; |
| 187 | + if (this.rx.ANIMATION_MATCH.test(output)) { |
| 188 | + for (var keyframe in keyframeTransforms) { |
| 189 | + var transform = keyframeTransforms[keyframe]; |
| 190 | + output = transform(output); |
| 191 | + } |
| 192 | + } |
| 193 | + rule.cssText = output; |
| 194 | + }, |
| 195 | + |
182 | 196 | // Test if the rules in these styles matches the given `element` and if so,
|
183 | 197 | // collect any custom properties into `props`.
|
184 | 198 | propertyDataFromStyles: function(styles, element) {
|
|
254 | 268 | hostSelector;
|
255 | 269 | var hostRx = new RegExp(this.rx.HOST_PREFIX + rxHostSelector +
|
256 | 270 | this.rx.HOST_SUFFIX);
|
| 271 | + var keyframeTransforms = {}; |
| 272 | + |
257 | 273 | return styleTransformer.elementStyles(element, function(rule) {
|
258 | 274 | self.applyProperties(rule, properties);
|
259 |
| - if (rule.cssText && !nativeShadow) { |
260 |
| - self._scopeSelector(rule, hostRx, hostSelector, |
261 |
| - element._scopeCssViaAttr, scopeSelector); |
| 275 | + self.applyKeyframeTransforms(rule, keyframeTransforms); |
| 276 | + if (!nativeShadow) { |
| 277 | + // If the rule is a keyframe selector, we put a transformation in |
| 278 | + // the keyframeTransforms map so that it can be applied to other |
| 279 | + // rules in the future. We use an anonymous function for the |
| 280 | + // transformer so that we can avoid creating a new RegExp for every |
| 281 | + // call to `applyKeyframeTransforms`. |
| 282 | + if (Polymer.StyleUtil.isKeyframesSelector(rule)) { |
| 283 | + var keyframesNameRx = new RegExp(rule.parent.keyframesName, 'g'); |
| 284 | + self._scopeKeyframes(rule.parent, scopeSelector); |
| 285 | + keyframeTransforms[rule.parent.keyframesName] = function(cssText) { |
| 286 | + return cssText.replace( |
| 287 | + keyframesNameRx, rule.parent.transformedKeyframesName); |
| 288 | + }; |
| 289 | + } else if (rule.cssText) { |
| 290 | + self._scopeSelector(rule, hostRx, hostSelector, |
| 291 | + element._scopeCssViaAttr, scopeSelector); |
| 292 | + } |
262 | 293 | }
|
263 | 294 | });
|
264 | 295 | },
|
265 | 296 |
|
| 297 | + // Transforms `@keyframes` names to be unique for the current host. |
| 298 | + // Example: @keyframes foo-anim -> @keyframes foo-anim-x-foo-0 |
| 299 | + _scopeKeyframes: function(rule, scopeId) { |
| 300 | + rule.transformedKeyframesName = rule.keyframesName + '-' + scopeId; |
| 301 | + rule.selector = '@keyframes ' + rule.transformedKeyframesName; |
| 302 | + }, |
| 303 | + |
266 | 304 | // Strategy: x scope shim a selector e.g. to scope `.x-foo-42` (via classes):
|
267 | 305 | // non-host selector: .a.x-foo -> .x-foo-42 .a.x-foo
|
268 | 306 | // host selector: x-foo.wide -> x-foo.x-foo-42.wide
|
|
357 | 395 | // var(--a, fallback-literal(with-one-nested-parentheses))
|
358 | 396 | VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)))[\s]*?\)/gi,
|
359 | 397 | VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gi,
|
| 398 | + ANIMATION_MATCH: /animation|animation-name/g, |
360 | 399 | IS_VAR: /^--/,
|
361 | 400 | BRACKETED: /\{[^}]*\}/g,
|
362 | 401 | HOST_PREFIX: '(?:^|[^.#[:])',
|
|
0 commit comments