feat(ShadowCss): Make the shim also accept a selector for the host
This commit is contained in:
parent
d67f0299cd
commit
5111f9ae37
|
@ -153,18 +153,22 @@ export class ShadowCss {
|
||||||
* Shim a style element with the given selector. Returns cssText that can
|
* Shim a style element with the given selector. Returns cssText that can
|
||||||
* be included in the document via WebComponents.ShadowCSS.addCssToDocument(css).
|
* be included in the document via WebComponents.ShadowCSS.addCssToDocument(css).
|
||||||
*/
|
*/
|
||||||
shimStyle(style: StyleElement, selector: string): string {
|
shimStyle(style: StyleElement, selector: string, hostSelector: string = ''): string {
|
||||||
var cssText = DOM.getText(style);
|
var cssText = DOM.getText(style);
|
||||||
return this.shimCssText(cssText, selector);
|
return this.shimCssText(cssText, selector, hostSelector);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shim some cssText with the given selector. Returns cssText that can
|
* Shim some cssText with the given selector. Returns cssText that can
|
||||||
* be included in the document via WebComponents.ShadowCSS.addCssToDocument(css).
|
* be included in the document via WebComponents.ShadowCSS.addCssToDocument(css).
|
||||||
|
*
|
||||||
|
* When strictStyling is true:
|
||||||
|
* - selector is the attribute added to all elements inside the host,
|
||||||
|
* - hostSelector is the attribute added to the host itself.
|
||||||
*/
|
*/
|
||||||
shimCssText(cssText: string, selector: string): string {
|
shimCssText(cssText: string, selector: string, hostSelector: string = ''): string {
|
||||||
cssText = this._insertDirectives(cssText);
|
cssText = this._insertDirectives(cssText);
|
||||||
return this._scopeCssText(cssText, selector);
|
return this._scopeCssText(cssText, selector, hostSelector);
|
||||||
}
|
}
|
||||||
|
|
||||||
_insertDirectives(cssText: string): string {
|
_insertDirectives(cssText: string): string {
|
||||||
|
@ -226,7 +230,7 @@ export class ShadowCss {
|
||||||
*
|
*
|
||||||
* scopeName .foo { ... }
|
* scopeName .foo { ... }
|
||||||
*/
|
*/
|
||||||
_scopeCssText(cssText: string, scopeSelector: string): string {
|
_scopeCssText(cssText: string, scopeSelector: string, hostSelector: string): string {
|
||||||
|
|
||||||
var unscoped = this._extractUnscopedRulesFromCssText(cssText);
|
var unscoped = this._extractUnscopedRulesFromCssText(cssText);
|
||||||
cssText = this._insertPolyfillHostInCssText(cssText);
|
cssText = this._insertPolyfillHostInCssText(cssText);
|
||||||
|
@ -235,7 +239,7 @@ export class ShadowCss {
|
||||||
cssText = this._convertShadowDOMSelectors(cssText);
|
cssText = this._convertShadowDOMSelectors(cssText);
|
||||||
if (isPresent(scopeSelector)) {
|
if (isPresent(scopeSelector)) {
|
||||||
_withCssRules(cssText, (rules) => {
|
_withCssRules(cssText, (rules) => {
|
||||||
cssText = this._scopeRules(rules, scopeSelector);
|
cssText = this._scopeRules(rules, scopeSelector, hostSelector);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
cssText = cssText + '\n' + unscoped;
|
cssText = cssText + '\n' + unscoped;
|
||||||
|
@ -344,18 +348,18 @@ export class ShadowCss {
|
||||||
}
|
}
|
||||||
|
|
||||||
// change a selector like 'div' to 'name div'
|
// change a selector like 'div' to 'name div'
|
||||||
_scopeRules(cssRules, scopeSelector: string): string {
|
_scopeRules(cssRules, scopeSelector: string, hostSelector: string): string {
|
||||||
var cssText = '';
|
var cssText = '';
|
||||||
if (isPresent(cssRules)) {
|
if (isPresent(cssRules)) {
|
||||||
for (var i = 0; i < cssRules.length; i++) {
|
for (var i = 0; i < cssRules.length; i++) {
|
||||||
var rule = cssRules[i];
|
var rule = cssRules[i];
|
||||||
if (CSSRuleWrapper.isStyleRule(rule) || CSSRuleWrapper.isPageRule(rule)) {
|
if (CSSRuleWrapper.isStyleRule(rule) || CSSRuleWrapper.isPageRule(rule)) {
|
||||||
cssText += this._scopeSelector(rule.selectorText, scopeSelector,
|
cssText += this._scopeSelector(rule.selectorText, scopeSelector, hostSelector,
|
||||||
this.strictStyling) + ' {\n';
|
this.strictStyling) + ' {\n';
|
||||||
cssText += this._propertiesFromRule(rule) + '\n}\n\n';
|
cssText += this._propertiesFromRule(rule) + '\n}\n\n';
|
||||||
} else if (CSSRuleWrapper.isMediaRule(rule)) {
|
} else if (CSSRuleWrapper.isMediaRule(rule)) {
|
||||||
cssText += '@media ' + rule.media.mediaText + ' {\n';
|
cssText += '@media ' + rule.media.mediaText + ' {\n';
|
||||||
cssText += this._scopeRules(rule.cssRules, scopeSelector);
|
cssText += this._scopeRules(rule.cssRules, scopeSelector, hostSelector);
|
||||||
cssText += '\n}\n\n';
|
cssText += '\n}\n\n';
|
||||||
} else {
|
} else {
|
||||||
// KEYFRAMES_RULE in IE throws when we query cssText
|
// KEYFRAMES_RULE in IE throws when we query cssText
|
||||||
|
@ -388,7 +392,8 @@ export class ShadowCss {
|
||||||
return cssText;
|
return cssText;
|
||||||
}
|
}
|
||||||
|
|
||||||
_scopeSelector(selector: string, scopeSelector: string, strict: boolean): string {
|
_scopeSelector(selector: string, scopeSelector: string, hostSelector: string,
|
||||||
|
strict: boolean): string {
|
||||||
var r = [], parts = selector.split(',');
|
var r = [], parts = selector.split(',');
|
||||||
for (var i = 0; i < parts.length; i++) {
|
for (var i = 0; i < parts.length; i++) {
|
||||||
var p = parts[i];
|
var p = parts[i];
|
||||||
|
@ -396,7 +401,7 @@ export class ShadowCss {
|
||||||
if (this._selectorNeedsScoping(p, scopeSelector)) {
|
if (this._selectorNeedsScoping(p, scopeSelector)) {
|
||||||
p = strict && !StringWrapper.contains(p, _polyfillHostNoCombinator) ?
|
p = strict && !StringWrapper.contains(p, _polyfillHostNoCombinator) ?
|
||||||
this._applyStrictSelectorScope(p, scopeSelector) :
|
this._applyStrictSelectorScope(p, scopeSelector) :
|
||||||
this._applySelectorScope(p, scopeSelector);
|
this._applySelectorScope(p, scopeSelector, hostSelector);
|
||||||
}
|
}
|
||||||
ListWrapper.push(r, p);
|
ListWrapper.push(r, p);
|
||||||
}
|
}
|
||||||
|
@ -416,16 +421,17 @@ export class ShadowCss {
|
||||||
return RegExpWrapper.create('^(' + scopeSelector + ')' + _selectorReSuffix, 'm');
|
return RegExpWrapper.create('^(' + scopeSelector + ')' + _selectorReSuffix, 'm');
|
||||||
}
|
}
|
||||||
|
|
||||||
_applySelectorScope(selector: string, scopeSelector: string): string {
|
_applySelectorScope(selector: string, scopeSelector: string, hostSelector: string): string {
|
||||||
// Difference from webcomponentsjs: scopeSelector could not be an array
|
// Difference from webcomponentsjs: scopeSelector could not be an array
|
||||||
return this._applySimpleSelectorScope(selector, scopeSelector);
|
return this._applySimpleSelectorScope(selector, scopeSelector, hostSelector);
|
||||||
}
|
}
|
||||||
|
|
||||||
// scope via name and [is=name]
|
// scope via name and [is=name]
|
||||||
_applySimpleSelectorScope(selector: string, scopeSelector: string): string {
|
_applySimpleSelectorScope(selector: string, scopeSelector: string, hostSelector: string): string {
|
||||||
if (isPresent(RegExpWrapper.firstMatch(_polyfillHostRe, selector))) {
|
if (isPresent(RegExpWrapper.firstMatch(_polyfillHostRe, selector))) {
|
||||||
selector = StringWrapper.replace(selector, _polyfillHostNoCombinator, scopeSelector);
|
var replaceBy = this.strictStyling ? `[${hostSelector}]` : scopeSelector;
|
||||||
return StringWrapper.replaceAll(selector, _polyfillHostRe, scopeSelector + ' ');
|
selector = StringWrapper.replace(selector, _polyfillHostNoCombinator, replaceBy);
|
||||||
|
return StringWrapper.replaceAll(selector, _polyfillHostRe, replaceBy + ' ');
|
||||||
} else {
|
} else {
|
||||||
return scopeSelector + ' ' + selector;
|
return scopeSelector + ' ' + selector;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ import {RegExpWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('ShadowCss', function() {
|
describe('ShadowCss', function() {
|
||||||
|
|
||||||
function s(css: string, tag:string) {
|
function s(css: string, contentAttr:string, hostAttr:string = '') {
|
||||||
var shadowCss = new ShadowCss();
|
var shadowCss = new ShadowCss();
|
||||||
var shim = shadowCss.shimCssText(css, tag);
|
var shim = shadowCss.shimCssText(css, contentAttr, hostAttr);
|
||||||
var nlRegexp = RegExpWrapper.create('\\n');
|
var nlRegexp = RegExpWrapper.create('\\n');
|
||||||
return StringWrapper.replaceAll(shim, nlRegexp, '');
|
return StringWrapper.replaceAll(shim, nlRegexp, '');
|
||||||
}
|
}
|
||||||
|
@ -65,14 +65,14 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle :host', () => {
|
it('should handle :host', () => {
|
||||||
expect(s(':host {}', 'a')).toEqual('a {}');
|
expect(s(':host {}', 'a', 'a-host')).toEqual('[a-host] {}');
|
||||||
expect(s(':host(.x,.y) {}', 'a')).toEqual('a.x, a.y {}');
|
expect(s(':host(.x,.y) {}', 'a', 'a-host')).toEqual('[a-host].x, [a-host].y {}');
|
||||||
expect(s(':host(.x,.y) > .z {}', 'a')).toEqual('a.x > .z, a.y > .z {}');
|
expect(s(':host(.x,.y) > .z {}', 'a', 'a-host')).toEqual('[a-host].x > .z, [a-host].y > .z {}');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle :host-context', () => {
|
it('should handle :host-context', () => {
|
||||||
expect(s(':host-context(.x) {}', 'a')).toEqual('a.x, .x a {}');
|
expect(s(':host-context(.x) {}', 'a', 'a-host')).toEqual('[a-host].x, .x [a-host] {}');
|
||||||
expect(s(':host-context(.x) > .y {}', 'a')).toEqual('a.x > .y, .x a > .y {}');
|
expect(s(':host-context(.x) > .y {}', 'a', 'a-host')).toEqual('[a-host].x > .y, .x [a-host] > .y {}');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support polyfill-next-selector', () => {
|
it('should support polyfill-next-selector', () => {
|
||||||
|
@ -92,11 +92,11 @@ export function main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support polyfill-rule', () => {
|
it('should support polyfill-rule', () => {
|
||||||
var css = s("polyfill-rule {content: ':host.foo .bar';background: blue;}", 'a');
|
var css = s("polyfill-rule {content: ':host.foo .bar';background: blue;}", 'a', 'a-host');
|
||||||
expect(css).toEqual('a.foo .bar {background: blue;}');
|
expect(css).toEqual('[a-host].foo .bar {background: blue;}');
|
||||||
|
|
||||||
css = s('polyfill-rule {content: ":host.foo .bar";background: blue;}', 'a');
|
css = s('polyfill-rule {content: ":host.foo .bar";background: blue;}', 'a', 'a-host');
|
||||||
expect(css).toEqual('a.foo .bar {background: blue;}');
|
expect(css).toEqual('[a-host].foo .bar {background: blue;}');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle ::shadow', () => {
|
it('should handle ::shadow', () => {
|
||||||
|
|
Loading…
Reference in New Issue