Skip to content

Commit 61abfbd

Browse files
committed
Fix parsing of custom properties with 'var' in value
Fixes #2660
1 parent 0dc69df commit 61abfbd

4 files changed

Lines changed: 98 additions & 21 deletions

File tree

‎src/lib/css-parse.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@
160160
customProp: /(?:^|[\s;])--[^;{]*?:[^{};]*?(?:[;\n]|$)/gim,
161161
mixinProp: /(?:^|[\s;])?--[^;{]*?:[^{;]*?{[^}]*?}(?:[;\n]|$)?/gim,
162162
mixinApply: /@apply[\s]*\([^)]*?\)[\s]*(?:[;\n]|$)?/gim,
163-
varApply: /[^;:]*?:[^;]*var[^;]*(?:[;\n]|$)?/gim,
163+
varApply: /[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,
164164
keyframesRule: /^@[^\s]*keyframes/,
165165
},
166166

‎src/lib/style-transformer.html‎

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
/* Transforms ShadowDOM styling into ShadyDOM styling
2121
22-
* scoping:
22+
* scoping:
2323
2424
* elements in scope get scoping selector class="x-foo-scope"
2525
* selectors re-written as follows:
@@ -41,8 +41,8 @@
4141
*/
4242
var api = {
4343

44-
// Given a node and scope name, add a scoping class to each node
45-
// in the tree. This facilitates transforming css into scoped rules.
44+
// Given a node and scope name, add a scoping class to each node
45+
// in the tree. This facilitates transforming css into scoped rules.
4646
dom: function(node, scope, useAttr, shouldRemoveScope) {
4747
this._transformDom(node, scope || '', useAttr, shouldRemoveScope);
4848
},
@@ -86,7 +86,7 @@
8686
.replace(scope, ''));
8787
}
8888
} else {
89-
element.setAttribute(CLASS, c + (c ? ' ' : '') +
89+
element.setAttribute(CLASS, c + (c ? ' ' : '') +
9090
SCOPE_NAME + ' ' + scope);
9191
}
9292
}
@@ -153,7 +153,7 @@
153153
}
154154
// NOTE: save transformedSelector for subsequent matching of elements
155155
// agsinst selectors (e.g. when calculating style properties)
156-
rule.selector = rule.transformedSelector =
156+
rule.selector = rule.transformedSelector =
157157
p$.join(COMPLEX_SELECTOR_SEP);
158158
},
159159

@@ -167,16 +167,16 @@
167167
stop = stop || info.stop;
168168
hostContext = hostContext || info.hostContext;
169169
c = info.combinator;
170-
s = info.value;
170+
s = info.value;
171171
} else {
172172
s = s.replace(SCOPE_JUMP, ' ');
173173
}
174174
return c + s;
175175
});
176176
if (hostContext) {
177-
selector = selector.replace(HOST_CONTEXT_PAREN,
177+
selector = selector.replace(HOST_CONTEXT_PAREN,
178178
function(m, pre, paren, post) {
179-
return pre + paren + ' ' + hostScope + post +
179+
return pre + paren + ' ' + hostScope + post +
180180
COMPLEX_SELECTOR_SEP + ' ' + pre + hostScope + paren + post;
181181
});
182182
}
@@ -198,7 +198,7 @@
198198
selector = selector.replace(HOST, hostScope);
199199
// replace other selectors with scoping class
200200
} else if (jumpIndex !== 0) {
201-
selector = scope ? this._transformSimpleSelector(selector, scope) :
201+
selector = scope ? this._transformSimpleSelector(selector, scope) :
202202
selector;
203203
}
204204
// remove left-side combinator when dealing with ::content.
@@ -212,7 +212,7 @@
212212
selector = selector.replace(SCOPE_JUMP, ' ');
213213
stop = true;
214214
}
215-
return {value: selector, combinator: combinator, stop: stop,
215+
return {value: selector, combinator: combinator, stop: stop,
216216
hostContext: hostContext};
217217
},
218218

@@ -247,13 +247,13 @@
247247
};
248248

249249
var SCOPE_NAME = api.SCOPE_NAME;
250-
var SCOPE_DOC_SELECTOR = ':not([' + SCOPE_NAME + '])' +
250+
var SCOPE_DOC_SELECTOR = ':not([' + SCOPE_NAME + '])' +
251251
':not(.' + SCOPE_NAME + ')';
252252
var COMPLEX_SELECTOR_SEP = ',';
253253
var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)([^\s>+~]+)/g;
254254
var HOST = ':host';
255255
var ROOT = ':root';
256-
// NOTE: this supports 1 nested () pair for things like
256+
// NOTE: this supports 1 nested () pair for things like
257257
// :host(:not([selected]), more general support requires
258258
// parsing which seems like overkill
259259
var HOST_PAREN = /(\:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;

‎src/lib/style-util.html‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
toCssText: function(rules, callback, preserveProperties) {
2323
if (typeof rules === 'string') {
2424
rules = this.parser.parse(rules);
25-
}
25+
}
2626
if (callback) {
2727
this.forEachStyleRule(rules, callback);
2828
}
@@ -56,7 +56,7 @@
5656
var skipRules = false;
5757
if (node.type === this.ruleTypes.STYLE_RULE) {
5858
callback(node);
59-
} else if (node.type === this.ruleTypes.KEYFRAMES_RULE ||
59+
} else if (node.type === this.ruleTypes.KEYFRAMES_RULE ||
6060
node.type === this.ruleTypes.MIXIN_RULE) {
6161
skipRules = true;
6262
}
@@ -79,8 +79,8 @@
7979
if (!afterNode) {
8080
var n$ = target.querySelectorAll('style[scope]');
8181
afterNode = n$[n$.length-1];
82-
}
83-
target.insertBefore(style,
82+
}
83+
target.insertBefore(style,
8484
(afterNode && afterNode.nextSibling) || target.firstChild);
8585
return style;
8686
},
@@ -142,7 +142,7 @@
142142
}
143143
return cssText;
144144
},
145-
145+
146146
resolveCss: Polymer.ResolveUrl.resolveCss,
147147
parser: Polymer.CssParse,
148148
ruleTypes: Polymer.CssParse.types
@@ -151,4 +151,4 @@
151151

152152
})();
153153

154-
</script>
154+
</script>

‎test/unit/custom-style.html‎

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@
8484
body /deep/ * {
8585
--deeep: 6px solid orange;
8686
}
87-
88-
8987
</style>
9088
<style is="custom-style">
9189
.bag {
@@ -138,6 +136,8 @@
138136

139137
<x-blue-bold-text></x-blue-bold-text>
140138

139+
<parent-variable-with-var></parent-variable-with-var>
140+
141141
<br><br>
142142
<div id="after"></div>
143143

@@ -212,10 +212,59 @@
212212
</template>
213213
</dom-module>
214214

215+
<dom-module id="parent-variable-with-var">
216+
<template>
217+
<style>
218+
child-variable-with-var {
219+
--variable-property-own-line: 1px;
220+
--variable-property-preceded-property: 2px;
221+
--variable-property-before-property: yellow;
222+
--variable-property-after-property: 3px;
223+
--variable-property-after-assignment: 4px;
224+
--variable-property-before-assignment: 5px;
225+
}
226+
</style>
227+
<child-variable-with-var id="child"></child-variable-with-var>
228+
</template>
229+
</dom-module>
230+
231+
<dom-module id="child-variable-with-var">
232+
<template>
233+
<style>
234+
child-of-child-with-var {
235+
--variable-own-line: "Varela font";
236+
margin-top: var(--variable-property-own-line);
237+
margin-bottom: var(--variable-property-preceded-property);
238+
--variable-between-properties: 6px;
239+
background-color: var(--variable-property-before-property); padding-top: var(--variable-property-after-property);
240+
--variable-assignment-before-property: 7px; padding-bottom: var(--variable-property-after-assignment);
241+
padding-left: var(--variable-property-before-assignment);--variable-assignment-after-property: 8px
242+
}
243+
</style>
244+
<child-of-child-with-var id="child"></child-of-child-with-var>
245+
</template>
246+
</dom-module>
247+
248+
<dom-module id="child-of-child-with-var">
249+
<template>
250+
<style>
251+
:host {
252+
font-family: var(--variable-own-line);
253+
padding-right: var(--variable-between-properties);
254+
margin-left: var(--variable-assignment-before-property);
255+
margin-right: var(--variable-assignment-after-property);
256+
}
257+
</style>
258+
Text
259+
</template>
260+
</dom-module>
261+
215262
<script>
216263

217264
suite('custom-style', function() {
218265

266+
var xBar, xFoo;
267+
219268
suiteSetup(function() {
220269

221270
Polymer({
@@ -385,6 +434,34 @@
385434
document.body.removeChild(d);
386435
});
387436

437+
test('variable name with assignment including var correctly applied', function() {
438+
Polymer({
439+
is: 'parent-variable-with-var'
440+
});
441+
Polymer({
442+
is: 'child-variable-with-var'
443+
});
444+
Polymer({
445+
is: 'child-of-child-with-var'
446+
});
447+
448+
var d = document.querySelector('parent-variable-with-var');
449+
var el = d.$.child.$.child;
450+
assertComputed(el, '1px', 'margin-top');
451+
assertComputed(el, '2px', 'margin-bottom');
452+
assertComputed(el, '3px', 'padding-top');
453+
assertComputed(el, '4px', 'padding-bottom');
454+
assertComputed(el, '5px', 'padding-left');
455+
assertComputed(el, '6px', 'padding-right');
456+
assertComputed(el, '7px', 'margin-left');
457+
assertComputed(el, '8px', 'margin-right');
458+
assertComputed(el, 'rgb(255, 255, 0)', 'background-color');
459+
460+
// Because FireFox and Chrome parse font-family differently...
461+
var computed = getComputedStyle(el);
462+
assert.equal(computed['font-family'].replace(/['"]+/g, ''), 'Varela font');
463+
});
464+
388465
});
389466

390467

0 commit comments

Comments
 (0)