mirror of
https://github.com/Polymer/polymer.git
synced 2025-02-25 18:55:30 -06:00
Replaces style-properties with *experimental* x-style element:
* shims ::shadow, /deep/ * avoids applying styles inside roots * can be used to set root custom property values
This commit is contained in:
@@ -51,7 +51,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="import" href="src/lib/style-properties.html">
|
||||
<link rel="import" href="src/lib/x-style.html">
|
||||
<link rel="import" href="src/lib/template/x-autobind.html">
|
||||
<link rel="import" href="src/lib/template/x-template.html">
|
||||
<link rel="import" href="src/lib/template/x-repeat.html">
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<link rel="import" href="../lib/x-style.html">
|
||||
<script>
|
||||
(function() {
|
||||
|
||||
var transformer = document.createElement('style', 'x-style');
|
||||
|
||||
var styleProtector = {
|
||||
|
||||
scopeDocumentSheets: function() {
|
||||
@@ -22,34 +25,17 @@
|
||||
|
||||
scopeSheet: function(sheet) {
|
||||
var owner = sheet.ownerNode;
|
||||
var css = this.sheetToScopedCss(sheet);
|
||||
var cssText = transformer.scopeCssText(this.rulesToCss(sheet.cssRules));
|
||||
if (owner.localName === 'link') {
|
||||
var style = document.createElement('style');
|
||||
style.textContent = css;
|
||||
style.textContent = cssText;
|
||||
owner.parentNode.insertBefore(style, owner);
|
||||
owner.parentNode.removeChild(owner);
|
||||
} else {
|
||||
owner.textContent = css;
|
||||
owner.textContent = cssText;
|
||||
}
|
||||
},
|
||||
|
||||
sheetToScopedCss: function(sheet) {
|
||||
var css = this.rulesToCss(sheet.cssRules);
|
||||
var rules = Polymer.CssParse.parse(css);
|
||||
var self = this;
|
||||
Polymer.StyleUtil.forEachStyleRule(rules, function(r) {
|
||||
r.selector = self.scopeSelector(r.selector);
|
||||
});
|
||||
return Polymer.CssParse.stringify(rules);
|
||||
},
|
||||
|
||||
scopeSelector: function(selector) {
|
||||
var parts = selector.split(this.SELECTOR_SEP);
|
||||
return parts.map(function(p) {
|
||||
return p.trim() + this.SCOPE_SELECTOR;
|
||||
}, this).join(this.SELECTOR_SEP);
|
||||
},
|
||||
|
||||
rulesToCss: function(cssRules) {
|
||||
for (var i=0, css=[]; i < cssRules.length; i++) {
|
||||
css.push(cssRules[i].cssText);
|
||||
@@ -57,9 +43,7 @@
|
||||
return css.join('\n\n');
|
||||
},
|
||||
|
||||
SCOPE_SELECTOR: ':not([style-scope])',
|
||||
SCOPE_ATTR: 'needs-scoping',
|
||||
SELECTOR_SEP: ','
|
||||
SCOPE_ATTR: 'needs-scoping'
|
||||
};
|
||||
|
||||
addEventListener('DOMContentLoaded', styleProtector.scopeDocumentSheets());
|
||||
|
||||
@@ -107,7 +107,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) {
|
||||
// transform style if necessary and place in correct place
|
||||
if (Polymer.Settings.useNativeShadow) {
|
||||
this._template.content.appendChild(s);
|
||||
if (this._template) {
|
||||
this._template.content.appendChild(s);
|
||||
}
|
||||
} else {
|
||||
var rules = this._rulesForStyle(s);
|
||||
Polymer.StyleUtil.applyCss(
|
||||
|
||||
@@ -20,20 +20,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
Polymer.StyleUtil.parser.parse(defaultSheet.textContent);
|
||||
}
|
||||
|
||||
|
||||
function applyStyle(style) {
|
||||
if (style.parentNode) {
|
||||
style.parentNode.removeChild(style);
|
||||
}
|
||||
applyCss(style.textContent);
|
||||
}
|
||||
|
||||
applyCss('');
|
||||
|
||||
// exports
|
||||
Polymer.StyleDefaults = {
|
||||
applyCss: applyCss,
|
||||
applyStyle: applyStyle,
|
||||
defaultSheet: defaultSheet
|
||||
};
|
||||
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
-->
|
||||
<link rel="import" href="style-defaults.html">
|
||||
<script>
|
||||
|
||||
// allow specification of defaults using <style is="style-properties">
|
||||
Polymer({
|
||||
is: 'style-properties',
|
||||
extends: 'style',
|
||||
created: function() {
|
||||
Polymer.StyleDefaults.applyStyle(this);
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
@@ -78,19 +78,22 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
return ext ? '[is=' + scope + ']' : scope;
|
||||
}
|
||||
|
||||
// transforms a css rule to a scoped rule.
|
||||
function transformRule(rule, scope, hostScope) {
|
||||
_transformRule(rule, transformComplexSelector,
|
||||
scope, hostScope);
|
||||
}
|
||||
|
||||
// transforms a css rule to a scoped rule.
|
||||
function _transformRule(rule, transformer, scope, hostScope) {
|
||||
var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP);
|
||||
for (var i=0, l=p$.length, p; (i<l) && (p=p$[i]); i++) {
|
||||
p$[i] = transformComplexSelector(p, scope, hostScope);
|
||||
p$[i] = transformer(p, scope, hostScope);
|
||||
}
|
||||
rule.selector = p$.join(COMPLEX_SELECTOR_SEP);
|
||||
}
|
||||
|
||||
function transformComplexSelector(selector, scope, hostScope) {
|
||||
var stop = false;
|
||||
var o = selector;
|
||||
|
||||
selector = selector.replace(SIMPLE_SELECTOR_SEP, function(m, c, s) {
|
||||
if (!stop) {
|
||||
var o = transformCompoundSelector(s, c, scope, hostScope);
|
||||
@@ -117,7 +120,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
selector = selector.replace(HOST, hostScope);
|
||||
// replace other selectors with scoping class
|
||||
} else if (jumpIndex !== 0) {
|
||||
selector = transformSimpleSelector(selector, scope);
|
||||
selector = scope ? transformSimpleSelector(selector, scope) : selector;
|
||||
}
|
||||
// remove left-side combinator when dealing with ::content.
|
||||
if (selector.indexOf(CONTENT) >= 0) {
|
||||
@@ -139,7 +142,18 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
return p$.join(PSEUDO_PREFIX);
|
||||
}
|
||||
|
||||
function transformRootRule(rule) {
|
||||
_transformRule(rule, transformRootSelector);
|
||||
}
|
||||
|
||||
function transformRootSelector(selector) {
|
||||
return selector.match(SCOPE_JUMP) ?
|
||||
transformComplexSelector(selector) :
|
||||
selector.trim() + SCOPE_ROOT_SELECTOR;
|
||||
}
|
||||
|
||||
var SCOPE_ATTR = 'style-scope';
|
||||
var SCOPE_ROOT_SELECTOR = ':not([' + SCOPE_ATTR + '])';
|
||||
var SCOPE_SUFFIX = '';
|
||||
var COMPLEX_SELECTOR_SEP = ',';
|
||||
var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)([^\s>+~]+)/g;
|
||||
@@ -161,6 +175,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
dom: transformDom,
|
||||
host: transformHost,
|
||||
css: transformCss,
|
||||
rule: transformRule,
|
||||
rootRule: transformRootRule,
|
||||
SCOPE_SUFFIX: SCOPE_SUFFIX
|
||||
};
|
||||
|
||||
|
||||
61
src/lib/x-style.html
Normal file
61
src/lib/x-style.html
Normal file
@@ -0,0 +1,61 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
-->
|
||||
<link rel="import" href="style-util.html">
|
||||
<link rel="import" href="style-transformer.html">
|
||||
<link rel="import" href="style-defaults.html">
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
|
||||
Polymer({
|
||||
|
||||
is: 'x-style',
|
||||
extends: 'style',
|
||||
|
||||
created: function() {
|
||||
var rules = Polymer.StyleUtil.parser.parse(this.textContent);
|
||||
this.applyProperties(rules);
|
||||
// TODO(sorvell): since custom rules must match directly, they tend to be
|
||||
// made with selectors like `*`.
|
||||
// We *remove them here* so they don't apply too widely and nerf recalc.
|
||||
// This means that normal properties mixe in rules with custom
|
||||
// properties will *not* apply.
|
||||
var cssText = Polymer.StyleUtil.parser.stringify(rules);
|
||||
this.textContent = this.scopeCssText(cssText);
|
||||
},
|
||||
|
||||
scopeCssText: function(cssText) {
|
||||
return Polymer.Settings.useNativeShadow ?
|
||||
cssText :
|
||||
Polymer.StyleUtil.toCssText(cssText, function(rule) {
|
||||
Polymer.StyleTransformer.rootRule(rule);
|
||||
});
|
||||
},
|
||||
|
||||
applyProperties: function(rules) {
|
||||
var cssText = '';
|
||||
Polymer.StyleUtil.forEachStyleRule(rules, function(rule) {
|
||||
if (rule.cssText.match(CUSTOM_RULE)) {
|
||||
// TODO(sorvell): use parser.stringify, it needs an option not to
|
||||
// strip custom properties.
|
||||
cssText += rule.selector + ' {\n' + rule.cssText + '\n}\n';
|
||||
}
|
||||
});
|
||||
if (cssText) {
|
||||
Polymer.StyleDefaults.applyCss(cssText);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var CUSTOM_RULE = /--[^;{'"]*\:/;
|
||||
|
||||
})();
|
||||
</script>
|
||||
@@ -33,7 +33,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
|
||||
'unit/resolveurl.html',
|
||||
'unit/css-parse.html',
|
||||
'unit/styling-scoped.html',
|
||||
'unit/styling-remote.html'
|
||||
'unit/styling-remote.html',
|
||||
'unit/x-style.html'
|
||||
]);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
89
test/unit/x-style.html
Normal file
89
test/unit/x-style.html
Normal file
@@ -0,0 +1,89 @@
|
||||
<!doctype html>
|
||||
<!--
|
||||
@license
|
||||
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
|
||||
<script src="../../../web-component-tester/browser.js"></script>
|
||||
<link rel="import" href="../../polymer.html">
|
||||
<style is="x-style">
|
||||
x-bar {
|
||||
border: 1px solid red;
|
||||
display: block;
|
||||
}
|
||||
|
||||
x-foo::shadow #bar2 {
|
||||
border: 2px solid orange;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<x-bar></x-bar>
|
||||
|
||||
<x-foo></x-foo>
|
||||
|
||||
<dom-module id="x-foo">
|
||||
<template>
|
||||
<div>x-foo</div>
|
||||
<x-bar id="bar1"></x-bar>
|
||||
<x-bar id="bar2"></x-bar>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<dom-module id="x-bar">
|
||||
<template>
|
||||
<div>x-bar</div>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
|
||||
before(function() {
|
||||
|
||||
Polymer({
|
||||
is: 'x-bar'
|
||||
});
|
||||
|
||||
Polymer({
|
||||
is: 'x-foo'
|
||||
});
|
||||
|
||||
xBar = document.querySelector('x-bar');
|
||||
xFoo = document.querySelector('x-foo');
|
||||
|
||||
});
|
||||
|
||||
suite('x-style', function() {
|
||||
|
||||
test('root styles applied', function() {
|
||||
assertComputed(xBar, '1px');
|
||||
});
|
||||
|
||||
test('root styles have lower bound encapsulation', function() {
|
||||
assertComputed(xFoo.$.bar1, '0px');
|
||||
});
|
||||
|
||||
test('::shadow styles applied', function() {
|
||||
assertComputed(xFoo.$.bar2, '2px');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function assertComputed(element, value) {
|
||||
var computed = getComputedStyle(element);
|
||||
assert.equal(computed['border-top-width'], value, 'computed style incorrect');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user