Merge branch 'fix-for-selectors-specificity' of https://github.com/nazar-pc/polymer into nazar-pc-fix-for-selectors-specificity

This commit is contained in:
Daniel Freedman 2015-12-04 12:58:31 -08:00
commit f2b65881e2
9 changed files with 144 additions and 35 deletions

View File

@ -11,11 +11,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
/*
Extremely simple css parser. Intended to be not more than what we need
and definitely not necessarly correct =).
and definitely not necessarily correct =).
*/
Polymer.CssParse = (function() {
var api = {
return {
// given a string of css, return a simple rule tree
parse: function(text) {
text = this._clean(text);
@ -31,7 +31,7 @@ Polymer.CssParse = (function() {
_lex: function(text) {
var root = {start: 0, end: text.length};
var n = root;
for (var i=0, s=0, l=text.length; i < l; i++) {
for (var i=0, l=text.length; i < l; i++) {
switch (text[i]) {
case this.OPEN_BRACE:
//console.group(i);
@ -123,7 +123,7 @@ Polymer.CssParse = (function() {
}
}
}
// emit rule iff there is cssText
// emit rule if there is cssText
if (cssText) {
if (node.selector) {
text += node.selector + ' ' + this.OPEN_BRACE + '\n';
@ -185,10 +185,6 @@ Polymer.CssParse = (function() {
};
// exports
return api;
})();
</script>

View File

@ -87,9 +87,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
var parts = cssText.split(';');
for (var i=0, p; i<parts.length; i++) {
p = parts[i];
if (p.match(this.rx.MIXIN_MATCH) || p.match(this.rx.VAR_MATCH)) {
customCssText += p + ';\n';
}
customCssText += p + ';\n';
}
return customCssText;
},
@ -181,7 +179,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
rule.cssText = output;
},
// Test if the rules in these styles matche the given `element` and if so,
// Test if the rules in these styles matches the given `element` and if so,
// collect any custom properties into `props`.
propertyDataFromStyles: function(styles, element) {
var props = {}, self = this;
@ -208,7 +206,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return {properties: props, key: o};
},
// Test if a rule matches scope crteria (* or :root) and if so,
// Test if a rule matches scope criteria (* or :root) and if so,
// collect any custom properties into `props`.
scopePropertiesFromStyles: function(styles) {
if (!styles._scopeStyleProperties) {
@ -218,7 +216,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return styles._scopeStyleProperties;
},
// Test if a rule matches host crteria (:host) and if so,
// Test if a rule matches host criteria (:host) and if so,
// collect any custom properties into `props`.
//
// TODO(sorvell): this should change to collecting properties from any
@ -319,7 +317,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// otherwise, if we have css to apply, do so
} else if (cssText) {
// apply css after the scope style of the element to help with
// style predence rules.
// style precedence rules.
style = styleUtil.applyCss(cssText, selector,
nativeShadow ? element.root : null, element._scopeStyle);
}
@ -356,7 +354,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// var(--a)
// var(--a, --b)
// var(--a, fallback-literal)
// var(--a, fallback-literal(with-one-nested-parens))
// var(--a, fallback-literal(with-one-nested-parentheses))
VAR_MATCH: /(^|\W+)var\([\s]*([^,)]*)[\s]*,?[\s]*((?:[^,)]*)|(?:[^;]*\([^;)]*\)))[\s]*?\)/gi,
VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gi,
IS_VAR: /^--/,

View File

@ -34,7 +34,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
cannot otherwise be scoped:
e.g. :host ::content > .bar -> x-foo > .bar
* ::shadow, /deep/: processed simimlar to ::content
* ::shadow, /deep/: processed similar to ::content
* :host-context(...): scopeName..., ... scopeName
@ -97,7 +97,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
elementStyles: function(element, callback) {
var styles = element._styles;
var cssText = '';
for (var i=0, l=styles.length, s, text; (i<l) && (s=styles[i]); i++) {
for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {
var rules = styleUtil.rulesForStyle(s);
cssText += nativeShadow ?
styleUtil.toCssText(rules, callback) :
@ -152,7 +152,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
p$[i] = transformer.call(this, p, scope, hostScope);
}
// NOTE: save transformedSelector for subsequent matching of elements
// agsinst selectors (e.g. when calculating style properties)
// against selectors (e.g. when calculating style properties)
rule.selector = rule.transformedSelector =
p$.join(COMPLEX_SELECTOR_SEP);
},
@ -258,9 +258,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// parsing which seems like overkill
var HOST_PAREN = /(\:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;
var HOST_CONTEXT = ':host-context';
var HOST_CONTEXT_PAREN = /(.*)(?:\:host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/;
var HOST_CONTEXT_PAREN = /(.*)(?::host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/;
var CONTENT = '::content';
var SCOPE_JUMP = /\:\:content|\:\:shadow|\/deep\//;
var SCOPE_JUMP = /::content|::shadow|\/deep\//;
var CSS_CLASS_PREFIX = '.';
var CSS_ATTR_PREFIX = '[' + SCOPE_NAME + '~=';
var CSS_ATTR_SUFFIX = ']';

View File

@ -44,15 +44,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return style.__cssRules;
},
clearStyleRules: function(style) {
style.__cssRules = null;
},
forEachStyleRule: function(node, callback) {
if (!node) {
return;
}
var s = node.parsedSelector;
var skipRules = false;
if (node.type === this.ruleTypes.STYLE_RULE) {
callback(node);

View File

@ -79,6 +79,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
style.textContent = cssText;
// extends!!
if (styleExtends.hasExtends(style.textContent)) {
// TODO(sorvell): variable is not used, should it update `style.textContent`?
cssText = styleExtends.transform(style);
}
styles.push(style);
@ -109,7 +110,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
/**
* Apply style scoping to the specified `container` and all its
* descendants. If `shoudlObserve` is true, changes to the container are
* descendants. If `shouldObserve` is true, changes to the container are
* monitored via mutation observer and scoping is applied.
*
* This method is useful for ensuring proper local DOM CSS scoping

View File

@ -166,7 +166,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
assert.equal(t.rules[3].selector, '.\\0c3333d-model');
assert.equal(t.rules[4].selector, '.\\d33333d-model');
assert.equal(t.rules[5].selector, '.\\e33333d-model');
});
});
test('multiple consequent spaces in CSS selector', function() {
var s4 = document.querySelector('#multiple-spaces');
var t = css.parse(s4.textContent);

View File

@ -57,7 +57,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
test(':host, :host(...)', function() {
assertComputed(styled, '1px');
assertComputed(styledWide, '2px');
});
test('scoped selectors, simple and complex', function() {
@ -209,7 +209,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
});
});
}
});
</script>

View File

@ -286,7 +286,6 @@
})();
</script>
<template id="dynamic-style-template">
<style>
:host {
@ -346,3 +345,100 @@
})();
</script>
</dom-module>
<dom-module id="x-specificity">
<template>
<style>
:host {
border-top: 1px solid red;
}
:host(.bar) {
border-top: 2px solid red;
}
</style>
<content></content>
</template>
<script>
Polymer({is: 'x-specificity'});
</script>
</dom-module>
<style is="custom-style">
:root {
--x-specificity-parent : {
border: 10px solid blue;
};
--x-specificity-nested : {
border: 3px solid red;
};
}
</style>
<dom-module id="x-specificity-parent">
<template>
<style>
/* TODO remove `:host` when https://github.com/Polymer/polymer/pull/2419 merged */
:host ::content > :not(template) {
@apply(--x-specificity-parent);
}
</style>
<content></content>
</template>
<script>
Polymer({is: 'x-specificity-parent', extends: 'div'});
</script>
</dom-module>
<dom-module id="x-specificity-nested">
<template>
<style>
:host {
@apply(--x-specificity-nested);
}
</style>
</template>
<script>
Polymer({is: 'x-specificity-nested', extends: 'div'});
</script>
</dom-module>
<style is="custom-style">
:root {
--x-overriding : {
border-top: 1px solid red;
}
}
</style>
<dom-module id="x-overriding">
<template>
<style>
.red {
@apply(--x-overriding);
}
.green {
@apply(--x-overriding);
border-top: 2px solid green;
}
.red-2 {
border-top: 2px solid green;
@apply(--x-overriding);
}
.blue {
@apply(--x-overriding);
border-top: 3px solid blue;
}
</style>
<div class="red">red</div>
<div class="green">green</div>
<div class="red-2">green-2</div>
<div class="blue">blue</div>
</template>
</dom-module>
<script>
Polymer({
is: 'x-overriding'
});
</script>

View File

@ -44,6 +44,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
</template>
<x-dynamic-svg></x-dynamic-svg>
<x-specificity></x-specificity>
<x-specificity class="bar"></x-specificity>
<div is="x-specificity-parent">
<div is="x-specificity-nested"></div>
</div>
<x-overriding></x-overriding>
<script>
suite('scoped-styling', function() {
@ -212,9 +218,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
test('styles shimmed in registration order', function() {
var s$ = document.head.querySelectorAll('style[scope]');
var expected = ['x-gchild', 'x-child2', 'x-styled', 'x-button',
'x-mixed-case', 'x-mixed-case-button', 'x-dynamic-scope',
'x-dynamic-template', 'x-dynamic-svg'];
var expected = ['x-gchild', 'x-child2', 'x-styled', 'x-button', 'x-mixed-case',
'x-mixed-case-button', 'x-dynamic-scope', 'x-dynamic-template',
'x-dynamic-svg', 'x-specificity', 'x-overriding',
'x-overriding-0', 'x-specificity-parent-0', 'x-specificity-nested-0'];
var actual = [];
for (var i=0; i<s$.length; i++) {
actual.push(s$[i].getAttribute('scope'));
@ -255,7 +262,23 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
x = document.createElement('button', 'x-mixed-case-button');
document.body.appendChild(x);
assertComputed(x, '14px');
});
test('specificity of :host selector with class', function() {
assertComputed(document.querySelector('x-specificity'), '1px');
assertComputed(document.querySelector('x-specificity.bar'), '2px');
});
test('specificity of ::content > :not(template) selector', function() {
assertComputed(document.querySelector('[is=x-specificity-nested]'), '10px');
});
test('overwriting mixin properties', function() {
var root = document.querySelector('x-overriding');
assertComputed(root.querySelector('.red'), '1px');
assertComputed(root.querySelector('.green'), '2px');
assertComputed(root.querySelector('.red-2'), '1px');
assertComputed(root.querySelector('.blue'), '3px');
});
});
@ -269,7 +292,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
computed = getComputedStyle(circle);
assert.equal(computed['fill-opacity'], '0.5');
});
});
</script>