Skip to content

Commit

Permalink
Merge pull request #1948 from Polymer/style-parsing-fixes
Browse files Browse the repository at this point in the history
Custom property parsing fixes
  • Loading branch information
kevinpschaaf committed Jun 25, 2015
2 parents 3e96425 + b0b0fdc commit a1fc29f
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 28 deletions.
8 changes: 4 additions & 4 deletions src/lib/css-parse.html
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,10 @@
var rx = {
comments: /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,
port: /@import[^;]*;/gim,
customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?;/gim,
mixinProp: /(?:^|[\s;])--[^;{]*?:[^{;]*?{[^}]*?};?/gim,
mixinApply: /@apply[\s]*\([^)]*?\)[\s]*;/gim,
varApply: /[^;:]*?:[^;]*var[^;]*;/gim,
customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?(?:[;\n]|$)/gim,
mixinProp: /(?:^|[\s;])--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim,
mixinApply: /@apply[\s]*\([^)]*?\)[\s]*(?:[;\n]|$)?/gim,
varApply: /[^;:]*?:[^;]*var[^;]*(?:[;\n]|$)?/gim,
keyframesRule: /^@[^\s]*keyframes/,
};

Expand Down
4 changes: 4 additions & 0 deletions src/lib/dom-api.html
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,10 @@
toggle: function() {
this.node.classList.toggle.apply(this.node.classList, arguments);
this.domApi._distributeParent();
},
contains: function() {
return this.node.classList.contains.apply(this.node.classList,
arguments);
}
}

Expand Down
19 changes: 9 additions & 10 deletions src/lib/style-properties.html
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,13 @@
// but not production, so strip out {...}
cssText = cssText.replace(this.rx.BRACKETED, '')
.replace(this.rx.VAR_ASSIGN, '');
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';
}
// If any custom properties are used, then return the entire
// declaration. This avoids some specificity issues with splitting
// delcarations into separate styles.
if (cssText.match(this.rx.MIXIN_MATCH) ||
cssText.match(this.rx.VAR_MATCH)) {
return cssText;
}
return customCssText;
},

collectPropertiesInCssText: function(cssText, props) {
Expand Down Expand Up @@ -344,8 +343,8 @@
},

rx: {
VAR_ASSIGN: /(?:^|;\s*)(--[^\:;]*?):\s*?(?:([^;{]*?)|{([^}]*)})(?=;)/gim,
MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\);?/im,
VAR_ASSIGN: /(?:^|[;\n]\s*)(--[\w-]*?):\s*?(?:([^;{]*?)|{([^}]*)})(?:(?=[;\n])|$)/gim,
MIXIN_MATCH: /(?:^|\W+)@apply[\s]*\(([^)]*)\)/im,
// note, this supports:
// var(--a)
// var(--a, --b)
Expand All @@ -355,7 +354,7 @@
VAR_CAPTURE: /\([\s]*(--[^,\s)]*)(?:,[\s]*(--[^,\s)]*))?(?:\)|,)/gim,
IS_VAR: /^--/,
BRACKETED: /\{[^}]*\}/g,
HOST_PREFIX: '(?:^|[^.])',
HOST_PREFIX: '(?:^|[^.#[:])',
HOST_SUFFIX: '($|[.:[\\s>+~])'
},

Expand Down
33 changes: 23 additions & 10 deletions src/lib/style-transformer.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
* ::shadow, /deep/: processed simimlar to ::content
* :host-context(...): NOT SUPPORTED
* :host-context(...): scopeName..., ... scopeName
*/
var api = {
Expand Down Expand Up @@ -156,28 +156,38 @@

_transformComplexSelector: function(selector, scope, hostScope) {
var stop = false;
var hostContext = false;
var self = this;
selector = selector.replace(SIMPLE_SELECTOR_SEP, function(m, c, s) {
if (!stop) {
var o = self._transformCompoundSelector(s, c, scope, hostScope);
if (o.stop) {
stop = true;
}
c = o.combinator;
s = o.value;
var info = self._transformCompoundSelector(s, c, scope, hostScope);
stop = stop || info.stop;
hostContext = hostContext || info.hostContext;
c = info.combinator;
s = info.value;
} else {
s = s.replace(SCOPE_JUMP, ' ');
}
return c + s;
});
if (hostContext) {
selector = selector.replace(HOST_CONTEXT_PAREN,
function(m, pre, paren, post) {
return pre + paren + ' ' + hostScope + post +
COMPLEX_SELECTOR_SEP + ' ' + pre + hostScope + paren + post;
});
}
return selector;
},

_transformCompoundSelector: function(selector, combinator, scope, hostScope) {
// replace :host with host scoping class
var jumpIndex = selector.search(SCOPE_JUMP);
if (selector.indexOf(HOST) >=0) {
// :host(...)
var hostContext = false;
if (selector.indexOf(HOST_CONTEXT) >=0) {
hostContext = true;
} else if (selector.indexOf(HOST) >=0) {
// :host(...) -> scopeName...
selector = selector.replace(HOST_PAREN, function(m, host, paren) {
return hostScope + paren;
});
Expand All @@ -199,7 +209,8 @@
selector = selector.replace(SCOPE_JUMP, ' ');
stop = true;
}
return {value: selector, combinator: combinator, stop: stop};
return {value: selector, combinator: combinator, stop: stop,
hostContext: hostContext};
},

_transformSimpleSelector: function(selector, scope) {
Expand Down Expand Up @@ -243,6 +254,8 @@
// :host(:not([selected]), more general support requires
// parsing which seems like overkill
var HOST_PAREN = /(\:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;
var HOST_CONTEXT = ':host-context';
var HOST_CONTEXT_PAREN = /(.*)(?:\:host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/;
var CONTENT = '::content';
var SCOPE_JUMP = /\:\:content|\:\:shadow|\/deep\//;
var CSS_CLASS_PREFIX = '.';
Expand Down
44 changes: 44 additions & 0 deletions test/smoke/host-context.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!doctype html>
<html>
<head>

<title>dom-if</title>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="../../polymer.html">

</head>
<body>

<dom-module id="x-host">
<style>
:host {
display: block;
}

:host-context([dir="rtl"]):after {
content: 'rtl';
}
</style>
<template>
Hi!
</template>
<script>
Polymer({
is:'x-host',
});
</script>
</dom-module>

<div dir="rtl">
<x-host></x-host>
</div>
<br>
<x-host></x-host>


</body>
</html>
12 changes: 11 additions & 1 deletion test/unit/polymer-dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ suite('Polymer.dom', function() {
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), []);
});

test('Polymer.dom.classListAdd/Remove/Toggle (reproject)', function() {
test('Polymer.dom.classListAdd/Remove/Toggle/Contains (reproject)', function() {
var select = document.querySelector('x-select-class1');
var child = Polymer.dom(select).firstElementChild;
var c1 = Polymer.dom(select.root).querySelector('content');
Expand All @@ -203,31 +203,41 @@ suite('Polymer.dom', function() {
var ip$ = [c1, c2, c3];
assert.equal(Polymer.dom(child).getDestinationInsertionPoints().length, 0);
Polymer.dom(child).classList.add('s1');
assert.isTrue(Polymer.dom(child).classList.contains('s1'));
Polymer.dom.flush();
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), [c1]);
Polymer.dom(child).classList.add('s2');
assert.isTrue(Polymer.dom(child).classList.contains('s2'));
Polymer.dom.flush();
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), [c1, c2]);
Polymer.dom(child).classList.add('s3');
assert.isTrue(Polymer.dom(child).classList.contains('s3'));
Polymer.dom.flush();
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), [c1, c2, c3]);
Polymer.dom(child).classList.toggle('s1');
assert.isFalse(Polymer.dom(child).classList.contains('s1'));
Polymer.dom.flush();
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), []);
Polymer.dom(child).classList.toggle('s1');
assert.isTrue(Polymer.dom(child).classList.contains('s1'));
Polymer.dom.flush();
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), [c1, c2, c3]);
Polymer.dom(child).classList.remove('s2');
assert.isFalse(Polymer.dom(child).classList.contains('s2'));
Polymer.dom.flush();
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), [c1]);
Polymer.dom(child).classList.toggle('s2');
assert.isTrue(Polymer.dom(child).classList.contains('s2'));
Polymer.dom.flush();
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), [c1, c2, c3]);
Polymer.dom(child).classList.remove('s3');
assert.isFalse(Polymer.dom(child).classList.contains('s3'));
Polymer.dom.flush();
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), [c1, c2]);
Polymer.dom(child).classList.remove('s2');
Polymer.dom(child).classList.remove('s1');
assert.isFalse(Polymer.dom(child).classList.contains('s2'));
assert.isFalse(Polymer.dom(child).classList.contains('s1'));
Polymer.dom.flush();
assert.deepEqual(Polymer.dom(child).getDestinationInsertionPoints(), []);
});
Expand Down
73 changes: 72 additions & 1 deletion test/unit/styling-cross-scope-apply.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,32 @@

<x-scope></x-scope>

<dom-module id="story-card">

<style>
:host {
display: block;
}

#story-card .story-content {
font-family: 'Roboto', sans-serif;
font-size: 1.2em;
@apply(--story-content);
}
</style>

<template>
<div id="story-card">
<div class="story-content" id="content">Content</div>
</div>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({is: 'story-card'});
});
</script>
</dom-module>

<dom-module id="x-child-scope">
<style>
:host {
Expand Down Expand Up @@ -46,13 +72,21 @@
#mixin4 {
@apply(--mixin4);
}

#mixin6 {
@apply(--mixin6)
}

#mixin7 {@apply(--mixin7)}
</style>

<template>
<div id="mixin1">mixin1</div>
<div id="mixin2">mixin2</div>
<div id="mixin3">mixin3</div>
<div id="mixin4">mixin4</div>
<div id="mixin6">mixin6</div>
<div id="mixin7">mixin7</div>
</template>
<script>
HTMLImports.whenReady(function() {
Expand All @@ -67,6 +101,10 @@
display: block;
padding: 8px;

--override-me: {
border: 11px solid black;
};

--mixin1: {
border: 1px solid black;
};
Expand Down Expand Up @@ -96,7 +134,14 @@
--mixin5: {
border: calc(var(--c1) + var(--c2)) solid orange;
};
}

--mixin6: {
border: 16px solid orange;
}

--mixin7: {
border: 17px solid navy;
}}

#mixin1 {
@apply(--mixin1);
Expand Down Expand Up @@ -124,6 +169,17 @@
padding: 10px;
}

#card {
--story-content: {
border: 11px solid orange;
};
}

#override {
@apply(--override-me);
border: 19px solid steelblue;
}

</style>

<template>
Expand All @@ -134,6 +190,8 @@
<div id="mixin5">mixin5</div>
<hr>
<x-child-scope id="child"></x-child-scope>
<story-card id="card"></story-card>
<div id="override">override</div>
</template>
<script>
HTMLImports.whenReady(function() {
Expand Down Expand Up @@ -199,6 +257,19 @@
test('calc can be used in mixins', function() {
assertComputed(styled.$.mixin5, '15px');
});

test('mixins work with selectors that contain element name', function() {
assertComputed(styled.$.card.$.content, '11px');
});

test('mixins with trailing new line or } apply', function() {
assertComputed(styled.$.child.$.mixin6, '16px');
assertComputed(styled.$.child.$.mixin7, '17px');
});

test('mixin values can be overridden by subsequent concrete properties', function() {
assertComputed(styled.$.override, '19px');
});
});

</script>
Expand Down
Loading

0 comments on commit a1fc29f

Please sign in to comment.