Skip to content

Commit

Permalink
Make :dir more robust
Browse files Browse the repository at this point in the history
Fixes #4952
  • Loading branch information
dfreedm committed Nov 29, 2017
1 parent c6a29dc commit f0ff70d
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 19 deletions.
45 changes: 26 additions & 19 deletions src/lib/style-transformer.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
* :host-context(...): scopeName..., ... scopeName
* ...:dir(ltr|rtl) -> [dir="ltr|rtl"] ..., ...[dir="ltr|rtl"]
* ...:dir(ltr|rtl) -> :host-context([dir]) -> [dir="ltr|rtl"] scopeName ..., scopeName[dir="ltr|rtl"] ...
* :host(:dir[rtl]) -> scopeName:dir(rtl) -> [dir="rtl"] scopeName, scopeName[dir="rtl"]
Expand Down Expand Up @@ -189,6 +189,17 @@
return p$.join(COMPLEX_SELECTOR_SEP);
},

// make sure `:dir() {` acts as `*:dir() {`
// otherwise, it would transform to `:host-context([dir="rtl"])` and apply incorrectly to the host
// so make it `:host-context([dir="rtl"]) *`
_ensureScopedDir: function(s) {
var m = s.match(DIR_PAREN);
if (m && m[1] === '' && m[0].length === s.length) {
s = '*' + s;
}
return s;
},

_transformComplexSelector: function(selector, scope, hostScope) {
var stop = false;
var hostContext = false;
Expand All @@ -197,6 +208,7 @@
selector = this._slottedToContent(selector);
selector = selector.replace(ROOT, ':host > *');
selector = selector.replace(CONTENT_START, HOST + ' $1');
selector = this._ensureScopedDir(selector);
selector = selector.replace(SIMPLE_SELECTOR_SEP, function(m, c, s) {
if (!stop) {
var info = self._transformCompoundSelector(s, c, scope, hostScope);
Expand All @@ -219,10 +231,19 @@
return selector;
},

_transformDir: function (s) {
// replaces :host(:dir(rtl)) with :host-context([dir="rtl"])
s = s.replace(HOST_DIR, HOST_DIR_REPLACE);
// replaces `.foo :dir(rtl)` with `:host-context([dir="rtl") .foo`
s = s.replace(DIR_PAREN, DIR_REPLACE);
return s;
},

_transformCompoundSelector: function(selector, combinator, scope, hostScope) {
// replace :host with host scoping class
var jumpIndex = selector.search(SCOPE_JUMP);
var hostContext = false;
selector = this._transformDir(selector);
if (selector.indexOf(HOST_CONTEXT) >=0) {
hostContext = true;
} else if (selector.indexOf(HOST) >=0) {
Expand All @@ -243,7 +264,6 @@
selector = selector.replace(SCOPE_JUMP, ' ');
stop = true;
}
selector = selector.replace(DIR_PAREN, DIR_REPLACE);
return {value: selector, combinator: combinator, stop: stop,
hostContext: hostContext};
},
Expand Down Expand Up @@ -318,21 +338,9 @@

_dirShadowTransform: function(selector) {
return selector.split(',').map(function(s) {
// replaces :host(:dir(rtl)) with :host-context([dir="rtl"])
s = s.replace(HOST_DIR, HOST_DIR_REPLACE);
var m;
if ((m = s.match(DIR_PAREN))) {
// replaces `.foo :dir(rtl)` with `:host-context([dir="rtl") .foo`
s = s.replace(DIR_PAREN, SHADOW_DIR_REPLACE);
// make sure `:dir() {` acts as `*:dir() {`
// otherwise, it would transform to `:host-context([dir="rtl"])` and apply incorrectly to the host
// so make it `:host-context([dir="rtl"]) *`
if (!m[1] || m[1].match(/^\s*$/)) {
s = s + '*';
}
}
return s;
}).join(',');
s = this._ensureScopedDir(s);
return this._transformDir(s);
}, this).join(',');
},

SCOPE_NAME: 'style-scope'
Expand Down Expand Up @@ -364,8 +372,7 @@
var SLOTTED_PAREN = /(?:::slotted)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;
var HOST_OR_HOST_GT_STAR = /:host(?:\s*>\s*\*)?/;
var DIR_PAREN = /(.*):dir\((ltr|rtl)\)/;
var DIR_REPLACE = '[dir="$2"] $1, $1[dir="$2"]';
var SHADOW_DIR_REPLACE = ':host-context([dir="$2"]) $1';
var DIR_REPLACE = ':host-context([dir="$2"]) $1';
var HOST_DIR = /:host\(:dir\((rtl|ltr)\)\)/g;
var HOST_DIR_REPLACE = ':host-context([dir="$1"])';

Expand Down
49 changes: 49 additions & 0 deletions test/smoke/dir.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<!DOCTYPE html>
<!--
@license
Copyright (c) 2017 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 dir="rtl">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes">

<title>Polymer</title>

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

<x-el></x-el>

<dom-module id="x-el">
<template>
<style>
#target {
padding: 20px;
color: white;
background: blue;
}
:dir(rtl) #target {
background: red;
}
</style>
<div>hello</div>
<div id="target">am i red?</div>
</template>
<script>
addEventListener('WebComponentsReady', function() {
Polymer({is: 'x-el'});
});
</script>
</dom-module>

</body>
</html>
34 changes: 34 additions & 0 deletions test/unit/dir.html
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,28 @@
</script>
</dom-module>

<dom-module id="x-complicated">
<template>
<style>
#target {
padding: 20px;
color: white;
background: rgb(0, 0, 255);
}
:dir(rtl) #target {
background: rgb(255, 0, 0);
}
</style>
<div id="normal">hello</div>
<div id="target">am i red?</div>
</template>
<script>
addEventListener('WebComponentsReady', function() {
Polymer({is: 'x-complicated'});
});
</script>
</dom-module>

<test-fixture id="dir">
<template>
<x-dir></x-dir>
Expand All @@ -133,6 +155,12 @@
</template>
</test-fixture>

<test-fixture id="complicated">
<template>
<x-complicated></x-complicated>
</template>
</test-fixture>

<script>
function assertComputed(node, expected, property) {
property = property || 'border-top-width';
Expand Down Expand Up @@ -208,6 +236,12 @@
var el = fixture('var')[1];
assertComputed(el, '10px');
assertComputed(el.$.inner, '2px');
});

test('complicated styles work as expected', function() {
var el = fixture('complicated');
assertComputed(el.$.normal, '0px', 'padding-left');
assertComputed(el.$.target, 'rgb(255, 0, 0)', 'background-color');
})
});
</script>
Expand Down

0 comments on commit f0ff70d

Please sign in to comment.