mirror of
https://github.com/Polymer/polymer.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #3413 from Polymer/style-fixes
Includes changes from a few style related PRs and adds more tests
This commit is contained in:
commit
596b6901d1
@ -82,23 +82,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
|
|
||||||
// returns cssText of properties that consume variables/mixins
|
// returns cssText of properties that consume variables/mixins
|
||||||
collectCssText: function(rule) {
|
collectCssText: function(rule) {
|
||||||
var customCssText = '';
|
|
||||||
var cssText = rule.parsedCssText;
|
var cssText = rule.parsedCssText;
|
||||||
// NOTE: we support consumption inside mixin assignment
|
// NOTE: we support consumption inside mixin assignment
|
||||||
// but not production, so strip out {...}
|
// but not production, so strip out {...}
|
||||||
cssText = cssText.replace(this.rx.BRACKETED, '')
|
cssText = cssText.replace(this.rx.BRACKETED, '')
|
||||||
.replace(this.rx.VAR_ASSIGN, '');
|
.replace(this.rx.VAR_ASSIGN, '');
|
||||||
var parts = cssText.split(';');
|
return cssText;
|
||||||
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) ||
|
|
||||||
this.rx.ANIMATION_MATCH.test(p) ||
|
|
||||||
styleUtil.isKeyframesSelector(rule)) {
|
|
||||||
customCssText += p + ';\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return customCssText;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
collectPropertiesInCssText: function(cssText, props) {
|
collectPropertiesInCssText: function(cssText, props) {
|
||||||
@ -360,7 +349,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
|
|
||||||
// Strategy: x scope shim a selector e.g. to scope `.x-foo-42` (via classes):
|
// 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
|
// non-host selector: .a.x-foo -> .x-foo-42 .a.x-foo
|
||||||
// host selector: x-foo.wide -> x-foo.x-foo-42.wide
|
// host selector: x-foo.wide -> .x-foo-42.wide
|
||||||
|
// note: we use only the scope class (.x-foo-42) and not the hostSelector
|
||||||
|
// (x-foo) to scope :host rules; this helps make property host rules
|
||||||
|
// have low specificity. They are overrideable by class selectors but,
|
||||||
|
// unfortunately, not by type selectors (e.g. overriding via
|
||||||
|
// `.special` is ok, but not by `x-foo`).
|
||||||
_scopeSelector: function(rule, hostRx, hostSelector, viaAttr, scopeId) {
|
_scopeSelector: function(rule, hostRx, hostSelector, viaAttr, scopeId) {
|
||||||
rule.transformedSelector = rule.transformedSelector || rule.selector;
|
rule.transformedSelector = rule.transformedSelector || rule.selector;
|
||||||
var selector = rule.transformedSelector;
|
var selector = rule.transformedSelector;
|
||||||
@ -370,7 +364,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
var parts = selector.split(',');
|
var parts = selector.split(',');
|
||||||
for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) {
|
for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) {
|
||||||
parts[i] = p.match(hostRx) ?
|
parts[i] = p.match(hostRx) ?
|
||||||
p.replace(hostSelector, hostSelector + scope) :
|
p.replace(hostSelector, scope) :
|
||||||
scope + ' ' + p;
|
scope + ' ' + p;
|
||||||
}
|
}
|
||||||
rule.selector = parts.join(',');
|
rule.selector = parts.join(',');
|
||||||
|
@ -253,7 +253,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
var SCOPE_DOC_SELECTOR = ':not([' + SCOPE_NAME + '])' +
|
var SCOPE_DOC_SELECTOR = ':not([' + SCOPE_NAME + '])' +
|
||||||
':not(.' + SCOPE_NAME + ')';
|
':not(.' + SCOPE_NAME + ')';
|
||||||
var COMPLEX_SELECTOR_SEP = ',';
|
var COMPLEX_SELECTOR_SEP = ',';
|
||||||
var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)([^\s>+~]+)/g;
|
var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)((?:\[.+?\]|[^\s>+~=\[])+)/g;
|
||||||
var HOST = ':host';
|
var HOST = ':host';
|
||||||
var ROOT = ':root';
|
var ROOT = ':root';
|
||||||
// NOTE: this supports 1 nested () pair for things like
|
// NOTE: this supports 1 nested () pair for things like
|
||||||
|
@ -42,8 +42,19 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
}
|
}
|
||||||
if (this._template) {
|
if (this._template) {
|
||||||
this._styles = this._collectStyles();
|
this._styles = this._collectStyles();
|
||||||
|
// calculate shimmed styles (we must always do this as it
|
||||||
|
// stores shimmed style data in the css rules for later use)
|
||||||
var cssText = styleTransformer.elementStyles(this);
|
var cssText = styleTransformer.elementStyles(this);
|
||||||
if (cssText) {
|
// do we really need to output shimmed styles
|
||||||
|
var needsStatic = this._needsStaticStyles(this._styles);
|
||||||
|
// under shady dom we always output a shimmed style (which may be
|
||||||
|
// empty) so that other dynamic stylesheets can always be placed
|
||||||
|
// after the element's main stylesheet.
|
||||||
|
// This helps ensure element styles are always in registration order.
|
||||||
|
if (needsStatic || !nativeShadow) {
|
||||||
|
// NOTE: IE has css style ordering issues unless there's at least a
|
||||||
|
// space in the stylesheet.
|
||||||
|
cssText = needsStatic ? cssText : ' ';
|
||||||
var style = styleUtil.applyCss(cssText, this.is,
|
var style = styleUtil.applyCss(cssText, this.is,
|
||||||
nativeShadow ? this._template.content : null);
|
nativeShadow ? this._template.content : null);
|
||||||
// keep track of style when in document scope (polyfill) so we can
|
// keep track of style when in document scope (polyfill) so we can
|
||||||
|
@ -18,6 +18,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
var serializeValueToAttribute = Polymer.Base.serializeValueToAttribute;
|
var serializeValueToAttribute = Polymer.Base.serializeValueToAttribute;
|
||||||
|
|
||||||
var propertyUtils = Polymer.StyleProperties;
|
var propertyUtils = Polymer.StyleProperties;
|
||||||
|
var styleUtil = Polymer.StyleUtil;
|
||||||
var styleTransformer = Polymer.StyleTransformer;
|
var styleTransformer = Polymer.StyleTransformer;
|
||||||
var styleDefaults = Polymer.StyleDefaults;
|
var styleDefaults = Polymer.StyleDefaults;
|
||||||
|
|
||||||
@ -25,6 +26,22 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
|
|
||||||
Polymer.Base._addFeature({
|
Polymer.Base._addFeature({
|
||||||
|
|
||||||
|
// Skip applying CSS if there are some mixins or variables used
|
||||||
|
// since styles with mixins and variables will be added on later stages anyway,
|
||||||
|
// and will include styles applied here, no need to do this twice
|
||||||
|
_needsStaticStyles: function(styles) {
|
||||||
|
var needsStatic;
|
||||||
|
for (var i=0, l=styles.length, css; i < l; i++) {
|
||||||
|
css = styleUtil.parser._clean(styles[i].textContent);
|
||||||
|
needsStatic = needsStatic || Boolean(css);
|
||||||
|
if (css.match(propertyUtils.rx.MIXIN_MATCH) ||
|
||||||
|
css.match(propertyUtils.rx.VAR_MATCH)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return needsStatic;
|
||||||
|
},
|
||||||
|
|
||||||
_prepStyleProperties: function() {
|
_prepStyleProperties: function() {
|
||||||
// note: an element should produce an x-scope stylesheet
|
// note: an element should produce an x-scope stylesheet
|
||||||
// if it has any _stylePropertyNames
|
// if it has any _stylePropertyNames
|
||||||
|
@ -14,6 +14,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
|
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
|
||||||
<script src="../../../web-component-tester/browser.js"></script>
|
<script src="../../../web-component-tester/browser.js"></script>
|
||||||
<link rel="import" href="../../polymer.html">
|
<link rel="import" href="../../polymer.html">
|
||||||
|
<style>
|
||||||
|
.variable-override {
|
||||||
|
border-top-width: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
@ -533,12 +538,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
</dom-module>
|
</dom-module>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.variable-override {
|
|
||||||
border-top-width: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<dom-module id="x-variable-override">
|
<dom-module id="x-variable-override">
|
||||||
<template>
|
<template>
|
||||||
<style>
|
<style>
|
||||||
@ -558,11 +557,53 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
</script>
|
</script>
|
||||||
</dom-module>
|
</dom-module>
|
||||||
|
|
||||||
|
<dom-module id="x-variable-consumer">
|
||||||
|
<template>
|
||||||
|
<style>
|
||||||
|
:host(.foo) {
|
||||||
|
border: var(--consumer);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
test
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
HTMLImports.whenReady(function() {
|
||||||
|
Polymer({
|
||||||
|
is: 'x-variable-consumer'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</dom-module>
|
||||||
|
|
||||||
|
<dom-module id="x-host-variable-consumer">
|
||||||
|
<template>
|
||||||
|
<style>
|
||||||
|
:host {
|
||||||
|
--consumer: 2px solid orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
.foo {
|
||||||
|
display: block;
|
||||||
|
/* should override */
|
||||||
|
border: 10px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<x-variable-consumer id="consumer" class="foo"></x-variable-consumer>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
HTMLImports.whenReady(function() {
|
||||||
|
Polymer({
|
||||||
|
is: 'x-host-variable-consumer'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</dom-module>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
suite('scoped-styling-var', function() {
|
suite('scoped-styling-var', function() {
|
||||||
|
|
||||||
function assertComputed(element, value, pseudo, name) {
|
function assertComputed(element, value, pseudo, name) {
|
||||||
var name = name || 'border-top-width';
|
name = name || 'border-top-width';
|
||||||
var computed = element.getComputedStyleValue && !pseudo ?
|
var computed = element.getComputedStyleValue && !pseudo ?
|
||||||
element.getComputedStyleValue(name) :
|
element.getComputedStyleValue(name) :
|
||||||
getComputedStyle(element, pseudo)[name];
|
getComputedStyle(element, pseudo)[name];
|
||||||
@ -800,21 +841,28 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('variable with parenthesis', function() {
|
test('variable with parenthesis', function() {
|
||||||
assertComputed(styled.$.parenthesis, 'url("http://placehold.it/400x300")', false, 'background-image');
|
var url = getComputedStyle(styled.$.parenthesis).backgroundImage.replace(/['"]/g, '');
|
||||||
|
assert.equal('url(http://placehold.it/400x300)', url);
|
||||||
});
|
});
|
||||||
|
|
||||||
// skip for now, until #3326 is fixed
|
test('custom style class overrides css variable', function() {
|
||||||
test.skip('custom style class overrides css variable', function() {
|
|
||||||
var d = document.createElement('x-variable-override');
|
var d = document.createElement('x-variable-override');
|
||||||
d.classList.add('variable-override');
|
d.classList.add('variable-override');
|
||||||
document.body.appendChild(d);
|
document.body.appendChild(d);
|
||||||
|
CustomElements.takeRecords();
|
||||||
assertComputed(d, '10px');
|
assertComputed(d, '10px');
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO(sorvell): fix for #1761 was reverted; include test once this issue is addressed
|
test('class selector overrides :host(class) property on element with only dynamic styles', function() {
|
||||||
// test('var values can be overridden by subsequent concrete properties', function() {
|
var d = document.createElement('x-host-variable-consumer');
|
||||||
// assertComputed(styled.$.overridesConcrete, '4px');
|
document.body.appendChild(d);
|
||||||
// });
|
CustomElements.takeRecords();
|
||||||
|
assertComputed(d.$.consumer, '10px');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('var values can be overridden by subsequent concrete properties', function() {
|
||||||
|
assertComputed(styled.$.overridesConcrete, '4px');
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -199,13 +199,23 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('styles shimmed in registration order', function() {
|
test('styles shimmed in registration order', function() {
|
||||||
var s$ = document.head.querySelectorAll('style[scope]');
|
var regList = Polymer.telemetry.registrations.map(function(reg) {
|
||||||
var expected = ['x-order', 'x-child2', 'x-styled', 'x-styled-0', 'x-button', 'x-dynamic-scope'];
|
return reg.is;
|
||||||
var actual = [];
|
});
|
||||||
for (var i=0; i<s$.length; i++) {
|
function regIndex(styleScope) {
|
||||||
actual.push(s$[i].getAttribute('scope'));
|
for (var i=0, r; (r=regList[i]); i++) {
|
||||||
|
if (styleScope.match(new RegExp(r + '\\-?\\d*$'))) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var s$ = document.head.querySelectorAll('style[scope]');
|
||||||
|
for (var i=0, scope, n=0, o=0; i<s$.length; i++) {
|
||||||
|
scope = s$[i].getAttribute('scope');
|
||||||
|
n = regIndex(scope);
|
||||||
|
assert.isTrue(n >= o, 'style not in registration order: ' + scope);
|
||||||
|
o = n;
|
||||||
}
|
}
|
||||||
assert.deepEqual(actual, expected);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -506,6 +506,34 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<dom-module id="x-attr-selector">
|
||||||
|
<template>
|
||||||
|
<style>
|
||||||
|
#foo1 ~ #bar1 {
|
||||||
|
border: 2px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#foo1 ~ #bar1 ~ #foo2[attr~=foo2] ~ #bar2[attr~=bar2] {
|
||||||
|
border: 4px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#foo1 ~ #bar1 ~ #foo2[attr~=foo2] ~ #bar2[attr~=bar2] ~ #foo3[attr~=foo3][a~=a] ~ #bar3[attr~=bar3][a~=a] {
|
||||||
|
border: 6px solid red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div id="foo1"></div>
|
||||||
|
<div id="bar1">bar1</div>
|
||||||
|
<div id="foo2" attr="foo2"></div>
|
||||||
|
<div id="bar2" attr="bar2">bar2</div>
|
||||||
|
<div id="foo3" attr="foo3" a="a"></div>
|
||||||
|
<div id="bar3" attr="bar3" a="a">bar3</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
Polymer({is: 'x-attr-selector'});
|
||||||
|
</script>
|
||||||
|
</dom-module>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
Polymer({
|
Polymer({
|
||||||
is: 'x-scope-no-class',
|
is: 'x-scope-no-class',
|
||||||
|
@ -240,6 +240,14 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
document.body.removeChild(el);
|
document.body.removeChild(el);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('attribute inclusive selector and general sibling selectors', function() {
|
||||||
|
var e = document.createElement('x-attr-selector');
|
||||||
|
document.body.appendChild(e);
|
||||||
|
assertComputed(e.$.bar1, '2px');
|
||||||
|
assertComputed(e.$.bar2, '4px');
|
||||||
|
assertComputed(e.$.bar3, '6px');
|
||||||
|
});
|
||||||
|
|
||||||
suite('scoped-styling-shady-only', function() {
|
suite('scoped-styling-shady-only', function() {
|
||||||
|
|
||||||
suiteSetup(function() {
|
suiteSetup(function() {
|
||||||
@ -253,17 +261,23 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('styles shimmed in registration order', function() {
|
test('styles shimmed in registration order', function() {
|
||||||
var s$ = document.head.querySelectorAll('style[scope]');
|
var regList = Polymer.telemetry.registrations.map(function(reg) {
|
||||||
var expected = ['x-keyframes', 'x-keyframes-1', 'x-keyframes-0', 'x-gchild', 'x-child2',
|
return reg.is;
|
||||||
'x-styled', 'x-button', 'x-mixed-case', 'x-mixed-case-button',
|
});
|
||||||
'x-dynamic-scope', 'x-dynamic-template', 'x-dynamic-svg',
|
function regIndex(styleScope) {
|
||||||
'x-specificity', 'x-overriding', 'x-overriding-0',
|
for (var i=0, r; (r=regList[i]); i++) {
|
||||||
'x-specificity-parent-0', 'x-specificity-nested-0'];
|
if (styleScope.match(new RegExp(r + '\\-?\\d*$'))) {
|
||||||
var actual = [];
|
return i;
|
||||||
for (var i=0; i<s$.length; i++) {
|
}
|
||||||
actual.push(s$[i].getAttribute('scope'));
|
}
|
||||||
|
}
|
||||||
|
var s$ = document.head.querySelectorAll('style[scope]');
|
||||||
|
for (var i=0, scope, n=0, o=0; i<s$.length; i++) {
|
||||||
|
scope = s$[i].getAttribute('scope');
|
||||||
|
n = regIndex(scope);
|
||||||
|
assert.isTrue(n >= o, 'style not in registration order: ' + scope);
|
||||||
|
o = n;
|
||||||
}
|
}
|
||||||
assert.deepEqual(actual, expected);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('svg elements properly scoped', function() {
|
test('svg elements properly scoped', function() {
|
||||||
@ -311,9 +325,18 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
assertComputed(document.querySelector('[is=x-specificity-nested]'), '10px');
|
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');
|
||||||
|
});
|
||||||
|
|
||||||
test('x-scope with no class attribute', function () {
|
test('x-scope with no class attribute', function () {
|
||||||
assert.equal(document.querySelector('x-scope-no-class > div').className, 'style-scope x-scope-no-class');
|
assert.equal(document.querySelector('x-scope-no-class > div').className, 'style-scope x-scope-no-class');
|
||||||
})
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('svg classes are dynamically scoped correctly', function() {
|
test('svg classes are dynamically scoped correctly', function() {
|
||||||
@ -326,6 +349,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
|||||||
computed = getComputedStyle(circle);
|
computed = getComputedStyle(circle);
|
||||||
assert.equal(computed['fill-opacity'], '0.5');
|
assert.equal(computed['fill-opacity'], '0.5');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
Reference in New Issue
Block a user