diff --git a/modules/@angular/compiler/src/shadow_css.ts b/modules/@angular/compiler/src/shadow_css.ts index b1052f3edd..42aa5604c8 100644 --- a/modules/@angular/compiler/src/shadow_css.ts +++ b/modules/@angular/compiler/src/shadow_css.ts @@ -200,7 +200,7 @@ export class ShadowCss { // Difference with webcomponents.js: does not handle comments return StringWrapper.replaceAllMapped( cssText, _cssContentRuleRe, function(m: any /** TODO #9100 */) { - var rule = m[0]; + let rule = m[0]; rule = StringWrapper.replace(rule, m[1], ''); rule = StringWrapper.replace(rule, m[2], ''); return m[3] + rule; @@ -216,7 +216,7 @@ export class ShadowCss { * scopeName .foo { ... } */ private _scopeCssText(cssText: string, scopeSelector: string, hostSelector: string): string { - var unscoped = this._extractUnscopedRulesFromCssText(cssText); + const unscoped = this._extractUnscopedRulesFromCssText(cssText); cssText = this._insertPolyfillHostInCssText(cssText); cssText = this._convertColonHost(cssText); cssText = this._convertColonHostContext(cssText); @@ -245,10 +245,11 @@ export class ShadowCss { **/ private _extractUnscopedRulesFromCssText(cssText: string): string { // Difference with webcomponents.js: does not handle comments - var r = '', m: RegExpExecArray; + let r = ''; + let m: RegExpExecArray; _cssContentUnscopedRuleRe.lastIndex = 0; while ((m = _cssContentUnscopedRuleRe.exec(cssText)) !== null) { - var rule = m[0]; + let rule = m[0]; rule = StringWrapper.replace(rule, m[2], ''); rule = StringWrapper.replace(rule, m[1], m[3]); r += rule + '\n\n'; @@ -291,9 +292,9 @@ export class ShadowCss { // p1 = :host, p2 = contents of (), p3 rest of rule return StringWrapper.replaceAllMapped(cssText, regExp, function(m: any /** TODO #9100 */) { if (isPresent(m[2])) { - var parts = m[2].split(','), r: any[] /** TODO #9100 */ = []; - for (var i = 0; i < parts.length; i++) { - var p = parts[i]; + const parts = m[2].split(','), r: any[] /** TODO #9100 */ = []; + for (let i = 0; i < parts.length; i++) { + let p = parts[i]; if (isBlank(p)) break; p = p.trim(); r.push(partReplacer(_polyfillHostNoCombinator, p, m[3])); @@ -322,7 +323,7 @@ export class ShadowCss { * by replacing with space. */ private _convertShadowDOMSelectors(cssText: string): string { - for (var i = 0; i < _shadowDOMSelectorsRe.length; i++) { + for (let i = 0; i < _shadowDOMSelectorsRe.length; i++) { cssText = StringWrapper.replaceAll(cssText, _shadowDOMSelectorsRe[i], ' '); } return cssText; @@ -331,8 +332,8 @@ export class ShadowCss { // change a selector like 'div' to 'name div' private _scopeSelectors(cssText: string, scopeSelector: string, hostSelector: string): string { return processRules(cssText, (rule: CssRule) => { - var selector = rule.selector; - var content = rule.content; + let selector = rule.selector; + let content = rule.content; if (rule.selector[0] != '@' || rule.selector.startsWith('@page')) { selector = this._scopeSelector(rule.selector, scopeSelector, hostSelector, this.strictStyling); @@ -345,11 +346,11 @@ export class ShadowCss { private _scopeSelector( selector: string, scopeSelector: string, hostSelector: string, strict: boolean): string { - var r: any[] /** TODO #9100 */ = [], parts = selector.split(','); - for (var i = 0; i < parts.length; i++) { - var p = parts[i].trim(); - var deepParts = StringWrapper.split(p, _shadowDeepSelectors); - var shallowPart = deepParts[0]; + const r: any[] /** TODO #9100 */ = [], parts = selector.split(','); + for (let i = 0; i < parts.length; i++) { + const p = parts[i].trim(); + const deepParts = StringWrapper.split(p, _shadowDeepSelectors); + const shallowPart = deepParts[0]; if (this._selectorNeedsScoping(shallowPart, scopeSelector)) { deepParts[0] = strict && !StringWrapper.contains(shallowPart, _polyfillHostNoCombinator) ? this._applyStrictSelectorScope(shallowPart, scopeSelector) : @@ -362,13 +363,13 @@ export class ShadowCss { } private _selectorNeedsScoping(selector: string, scopeSelector: string): boolean { - var re = this._makeScopeMatcher(scopeSelector); + const re = this._makeScopeMatcher(scopeSelector); return !re.test(selector); } private _makeScopeMatcher(scopeSelector: string): RegExp { - var lre = /\[/g; - var rre = /\]/g; + const lre = /\[/g; + const rre = /\]/g; scopeSelector = StringWrapper.replaceAll(scopeSelector, lre, '\\['); scopeSelector = StringWrapper.replaceAll(scopeSelector, rre, '\\]'); return new RegExp('^(' + scopeSelector + ')' + _selectorReSuffix, 'm'); @@ -384,7 +385,7 @@ export class ShadowCss { private _applySimpleSelectorScope(selector: string, scopeSelector: string, hostSelector: string): string { if (_polyfillHostRe.test(selector)) { - var replaceBy = this.strictStyling ? `[${hostSelector}]` : scopeSelector; + const replaceBy = this.strictStyling ? `[${hostSelector}]` : scopeSelector; selector = StringWrapper.replace(selector, _polyfillHostNoCombinator, replaceBy); return StringWrapper.replaceAll(selector, _polyfillHostRe, replaceBy + ' '); } else { @@ -395,17 +396,19 @@ export class ShadowCss { // return a selector with [name] suffix on each simple selector // e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name] /** @internal */ private _applyStrictSelectorScope(selector: string, scopeSelector: string): string { - var isRe = /\[is=([^\]]*)\]/g; + const isRe = /\[is=([^\]]*)\]/g; scopeSelector = StringWrapper.replaceAllMapped(scopeSelector, isRe, (m: any /** TODO #9100 */) => m[1]); - var splits = [' ', '>', '+', '~'], scoped = selector, attrName = '[' + scopeSelector + ']'; - for (var i = 0; i < splits.length; i++) { - var sep = splits[i]; - var parts = scoped.split(sep); + const splits = [' ', '>', '+', '~']; + let scoped = selector; + const attrName = '[' + scopeSelector + ']'; + for (let i = 0; i < splits.length; i++) { + const sep = splits[i]; + const parts = scoped.split(sep); scoped = parts .map(p => { // remove :host since it should be unnecessary - var t = StringWrapper.replaceAll(p.trim(), _polyfillHostRe, ''); + const t = StringWrapper.replaceAll(p.trim(), _polyfillHostRe, ''); if (t.length > 0 && !ListWrapper.contains(splits, t) && !StringWrapper.contains(t, attrName)) { const m = t.match(/([^:]*)(:*)(.*)/); @@ -426,21 +429,21 @@ export class ShadowCss { return selector; } } -var _cssContentNextSelectorRe = +const _cssContentNextSelectorRe = /polyfill-next-selector[^}]*content:[\s]*?['"](.*?)['"][;\s]*}([^{]*?){/gim; -var _cssContentRuleRe = /(polyfill-rule)[^}]*(content:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim; -var _cssContentUnscopedRuleRe = +const _cssContentRuleRe = /(polyfill-rule)[^}]*(content:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim; +const _cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim; -var _polyfillHost = '-shadowcsshost'; +const _polyfillHost = '-shadowcsshost'; // note: :host-context pre-processed to -shadowcsshostcontext. -var _polyfillHostContext = '-shadowcsscontext'; -var _parenSuffix = ')(?:\\((' + +const _polyfillHostContext = '-shadowcsscontext'; +const _parenSuffix = ')(?:\\((' + '(?:\\([^)(]*\\)|[^)(]*)+?' + ')\\))?([^,{]*)'; -var _cssColonHostRe = new RegExp('(' + _polyfillHost + _parenSuffix, 'gim'); -var _cssColonHostContextRe = new RegExp('(' + _polyfillHostContext + _parenSuffix, 'gim'); -var _polyfillHostNoCombinator = _polyfillHost + '-no-combinator'; -var _shadowDOMSelectorsRe = [ +const _cssColonHostRe = new RegExp('(' + _polyfillHost + _parenSuffix, 'gim'); +const _cssColonHostContextRe = new RegExp('(' + _polyfillHostContext + _parenSuffix, 'gim'); +const _polyfillHostNoCombinator = _polyfillHost + '-no-combinator'; +const _shadowDOMSelectorsRe = [ /::shadow/g, /::content/g, // Deprecated selectors // TODO(vicb): see https://github.com/angular/clang-format/issues/16 @@ -449,28 +452,28 @@ var _shadowDOMSelectorsRe = [ /\/shadow\//g, // former ::shadow // clanf-format on ]; -var _shadowDeepSelectors = /(?:>>>)|(?:\/deep\/)/g; -var _selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$'; -var _polyfillHostRe = new RegExp(_polyfillHost, 'im'); -var _colonHostRe = /:host/gim; -var _colonHostContextRe = /:host-context/gim; +const _shadowDeepSelectors = /(?:>>>)|(?:\/deep\/)/g; +const _selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$'; +const _polyfillHostRe = new RegExp(_polyfillHost, 'im'); +const _colonHostRe = /:host/gim; +const _colonHostContextRe = /:host-context/gim; -var _commentRe = /\/\*\s*[\s\S]*?\*\//g; +const _commentRe = /\/\*\s*[\s\S]*?\*\//g; function stripComments(input:string):string { return StringWrapper.replaceAllMapped(input, _commentRe, (_: any /** TODO #9100 */) => ''); } // all comments except inline source mapping ("/* #sourceMappingURL= ... */") -var _sourceMappingUrlRe = /[\s\S]*(\/\*\s*#\s*sourceMappingURL=[\s\S]+?\*\/)\s*$/; +const _sourceMappingUrlRe = /[\s\S]*(\/\*\s*#\s*sourceMappingURL=[\s\S]+?\*\/)\s*$/; function extractSourceMappingUrl(input:string):string { const matcher = input.match(_sourceMappingUrlRe); return matcher ? matcher[1] : ''; } -var _ruleRe = /(\s*)([^;\{\}]+?)(\s*)((?:{%BLOCK%}?\s*;?)|(?:\s*;))/g; -var _curlyRe = /([{}])/g; +const _ruleRe = /(\s*)([^;\{\}]+?)(\s*)((?:{%BLOCK%}?\s*;?)|(?:\s*;))/g; +const _curlyRe = /([{}])/g; const OPEN_CURLY = '{'; const CLOSE_CURLY = '}'; const BLOCK_PLACEHOLDER = '%BLOCK%'; @@ -480,19 +483,19 @@ export class CssRule { } export function processRules(input:string, ruleCallback:Function):string { - var inputWithEscapedBlocks = escapeBlocks(input); - var nextBlockIndex = 0; + const inputWithEscapedBlocks = escapeBlocks(input); + let nextBlockIndex = 0; return StringWrapper.replaceAllMapped(inputWithEscapedBlocks.escapedString, _ruleRe, function(m: any /** TODO #9100 */) { - var selector = m[2]; - var content = ''; - var suffix = m[4]; - var contentPrefix = ''; + const selector = m[2]; + let content = ''; + let suffix = m[4]; + let contentPrefix = ''; if (isPresent(m[4]) && m[4].startsWith('{'+BLOCK_PLACEHOLDER)) { content = inputWithEscapedBlocks.blocks[nextBlockIndex++]; suffix = m[4].substring(BLOCK_PLACEHOLDER.length+1); contentPrefix = '{'; } - var rule = ruleCallback(new CssRule(selector, content)); + const rule = ruleCallback(new CssRule(selector, content)); return `${m[1]}${rule.selector}${m[3]}${contentPrefix}${rule.content}${suffix}`; }); } @@ -502,13 +505,13 @@ class StringWithEscapedBlocks { } function escapeBlocks(input:string):StringWithEscapedBlocks { - var inputParts = StringWrapper.split(input, _curlyRe); - var resultParts: any[] /** TODO #9100 */ = []; - var escapedBlocks: any[] /** TODO #9100 */ = []; - var bracketCount = 0; - var currentBlockParts: any[] /** TODO #9100 */ = []; - for (var partIndex = 0; partIndex { expect(s('', 'a')).toEqual(''); }); it('should add an attribute to every rule', () => { - var css = 'one {color: red;}two {color: red;}'; - var expected = 'one[a] {color:red;}two[a] {color:red;}'; + const css = 'one {color: red;}two {color: red;}'; + const expected = 'one[a] {color:red;}two[a] {color:red;}'; expect(s(css, 'a')).toEqual(expected); }); it('should handle invalid css', () => { - var css = 'one {color: red;}garbage'; - var expected = 'one[a] {color:red;}garbage'; + const css = 'one {color: red;}garbage'; + const expected = 'one[a] {color:red;}garbage'; expect(s(css, 'a')).toEqual(expected); }); it('should add an attribute to every selector', () => { - var css = 'one, two {color: red;}'; - var expected = 'one[a], two[a] {color:red;}'; + const css = 'one, two {color: red;}'; + const expected = 'one[a], two[a] {color:red;}'; expect(s(css, 'a')).toEqual(expected); }); it('should support newlines in the selector and content ', () => { - var css = 'one, \ntwo {\ncolor: red;}'; - var expected = 'one[a], two[a] {color:red;}'; + const css = 'one, \ntwo {\ncolor: red;}'; + const expected = 'one[a], two[a] {color:red;}'; expect(s(css, 'a')).toEqual(expected); }); it('should handle media rules', () => { - var css = '@media screen and (max-width:800px, max-height:100%) {div {font-size:50px;}}'; - var expected = + const css = '@media screen and (max-width:800px, max-height:100%) {div {font-size:50px;}}'; + const expected = '@media screen and (max-width:800px, max-height:100%) {div[a] {font-size:50px;}}'; expect(s(css, 'a')).toEqual(expected); }); it('should handle media rules with simple rules', () => { - var css = '@media screen and (max-width: 800px) {div {font-size: 50px;}} div {}'; - var expected = '@media screen and (max-width:800px) {div[a] {font-size:50px;}} div[a] {}'; + const css = '@media screen and (max-width: 800px) {div {font-size: 50px;}} div {}'; + const expected = '@media screen and (max-width:800px) {div[a] {font-size:50px;}} div[a] {}'; expect(s(css, 'a')).toEqual(expected); }); it('should handle support rules', () => { - var css = '@supports (display: flex) {section {display: flex;}}'; - var expected = '@supports (display:flex) {section[a] {display:flex;}}'; + const css = '@supports (display: flex) {section {display: flex;}}'; + const expected = '@supports (display:flex) {section[a] {display:flex;}}'; expect(s(css, 'a')).toEqual(expected); }); // Check that the browser supports unprefixed CSS animation it('should handle keyframes rules', () => { - var css = '@keyframes foo {0% {transform:translate(-50%) scaleX(0);}}'; + const css = '@keyframes foo {0% {transform:translate(-50%) scaleX(0);}}'; expect(s(css, 'a')).toEqual(css); }); it('should handle -webkit-keyframes rules', () => { - var css = '@-webkit-keyframes foo {0% {-webkit-transform:translate(-50%) scaleX(0);}}'; + const css = '@-webkit-keyframes foo {0% {-webkit-transform:translate(-50%) scaleX(0);}}'; expect(s(css, 'a')).toEqual(css); }); @@ -84,7 +84,7 @@ export function main() { expect(s('one > two {}', 'a')).toEqual('one[a] > two[a] {}'); expect(s('one + two {}', 'a')).toEqual('one[a] + two[a] {}'); expect(s('one ~ two {}', 'a')).toEqual('one[a] ~ two[a] {}'); - var res = s('.one.two > three {}', 'a'); // IE swap classes + const res = s('.one.two > three {}', 'a'); // IE swap classes expect(res == '.one.two[a] > three[a] {}' || res == '.two.one[a] > three[a] {}') .toEqual(true); expect(s('one[attr="value"] {}', 'a')).toEqual('one[attr="value"][a] {}'); @@ -111,7 +111,7 @@ export function main() { }); it('should support polyfill-next-selector', () => { - var css = s('polyfill-next-selector {content: \'x > y\'} z {}', 'a'); + let css = s('polyfill-next-selector {content: \'x > y\'} z {}', 'a'); expect(css).toEqual('x[a] > y[a]{}'); css = s('polyfill-next-selector {content: "x > y"} z {}', 'a'); @@ -119,7 +119,7 @@ export function main() { }); it('should support polyfill-unscoped-rule', () => { - var css = s('polyfill-unscoped-rule {content: \'#menu > .bar\';color: blue;}', 'a'); + let css = s('polyfill-unscoped-rule {content: \'#menu > .bar\';color: blue;}', 'a'); expect(StringWrapper.contains(css, '#menu > .bar {;color:blue;}')).toBeTruthy(); css = s('polyfill-unscoped-rule {content: "#menu > .bar";color: blue;}', 'a'); @@ -127,7 +127,7 @@ export function main() { }); it('should support multiple instances polyfill-unscoped-rule', () => { - var css = + const css = s('polyfill-unscoped-rule {content: \'foo\';color: blue;}' + 'polyfill-unscoped-rule {content: \'bar\';color: blue;}', 'a'); @@ -136,7 +136,7 @@ export function main() { }); it('should support polyfill-rule', () => { - var css = s('polyfill-rule {content: \':host.foo .bar\';color: blue;}', 'a', 'a-host'); + let css = s('polyfill-rule {content: \':host.foo .bar\';color: blue;}', 'a', 'a-host'); expect(css).toEqual('[a-host].foo .bar {;color:blue;}'); css = s('polyfill-rule {content: ":host.foo .bar";color:blue;}', 'a', 'a-host'); @@ -144,35 +144,35 @@ export function main() { }); it('should handle ::shadow', () => { - var css = s('x::shadow > y {}', 'a'); + const css = s('x::shadow > y {}', 'a'); expect(css).toEqual('x[a] > y[a] {}'); }); it('should handle /deep/', () => { - var css = s('x /deep/ y {}', 'a'); + const css = s('x /deep/ y {}', 'a'); expect(css).toEqual('x[a] y {}'); }); it('should handle >>>', () => { - var css = s('x >>> y {}', 'a'); + const css = s('x >>> y {}', 'a'); expect(css).toEqual('x[a] y {}'); }); it('should pass through @import directives', () => { - var styleStr = '@import url("https://fonts.googleapis.com/css?family=Roboto");'; - var css = s(styleStr, 'a'); + const styleStr = '@import url("https://fonts.googleapis.com/css?family=Roboto");'; + const css = s(styleStr, 'a'); expect(css).toEqual(styleStr); }); it('should shim rules after @import', () => { - var styleStr = '@import url("a"); div {}'; - var css = s(styleStr, 'a'); + const styleStr = '@import url("a"); div {}'; + const css = s(styleStr, 'a'); expect(css).toEqual('@import url("a"); div[a] {}'); }); it('should leave calc() unchanged', () => { - var styleStr = 'div {height:calc(100% - 55px);}'; - var css = s(styleStr, 'a'); + const styleStr = 'div {height:calc(100% - 55px);}'; + const css = s(styleStr, 'a'); expect(css).toEqual('div[a] {height:calc(100% - 55px);}'); }); @@ -195,7 +195,7 @@ export function main() { describe('processRules', () => { describe('parse rules', () => { function captureRules(input: string): CssRule[] { - var result: any[] /** TODO #9100 */ = []; + const result: any[] /** TODO #9100 */ = []; processRules(input, (cssRule: any /** TODO #9100 */) => { result.push(cssRule); return cssRule;