Skip to content

Commit

Permalink
fix(compiler): apply style on :host attribudes in prod builds.
Browse files Browse the repository at this point in the history
In prod builds, selectors are optimized and spaces a removed. #48558 introduced a regression on selectors without spaces. This commit fixes tihs.

Fixes #49100
  • Loading branch information
JeanMeche committed Jun 5, 2023
1 parent cb31dbc commit ecbaee1
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 6 deletions.
16 changes: 10 additions & 6 deletions packages/compiler/src/shadow_css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ export class ShadowCss {
// (ie: ".\fc ber" for ".über") is not a separator between 2 selectors
// also keep in mind that backslashes are replaced by a placeholder by SafeSelector
// These escaped selectors happen for example when esbuild runs with optimization.minify.
if (part.match(_placeholderRe) && selector[res.index + 1]?.match(/[a-fA-F\d]/)) {
if (part.match(/__esc-ph-(\d+)__/g) && selector[res.index + 1]?.match(/[a-fA-F\d]/)) {
continue;
}

Expand Down Expand Up @@ -752,7 +752,13 @@ class SafeSelector {
// pseudo-class, but writing `.foo\:blue` will match, because the colon was escaped.
// Replace all escape sequences (`\` followed by a character) with a placeholder so
// that our handling of pseudo-selectors doesn't mess with them.
selector = this._escapeRegexMatches(selector, /(\\.)/g);
// Escaped characters have a specific placeholder so they can be detected separately.
selector = selector.replace(/(\\.)/g, (_, keep) => {
const replaceBy = `__esc-ph-${this.index}__`;
this.placeholders.push(keep);
this.index++;
return replaceBy;
});

// Replaces the expression in `:nth-child(2n + 1)` with a placeholder.
// WS and "+" would otherwise be interpreted as selector separators.
Expand All @@ -765,7 +771,7 @@ class SafeSelector {
}

restore(content: string): string {
return content.replace(_placeholderRe, (_ph, index) => this.placeholders[+index]);
return content.replace(/__(?:ph|esc-ph)-(\d+)__/g, (_ph, index) => this.placeholders[+index]);
}

content(): string {
Expand Down Expand Up @@ -821,12 +827,10 @@ const _colonHostContextRe = /:host-context/gim;

const _newLinesRe = /\r?\n/g;
const _commentRe = /\/\*[\s\S]*?\*\//g;
const _commentWithHashRe = /\/\*\s*#\s*source(Mapping)?URL=/g;
const _commentWithHashRe = /\/\*\s*#\s*source(Mapping)?URL=[\s\S]+?\*\//g;
const COMMENT_PLACEHOLDER = '%COMMENT%';
const _commentWithHashPlaceHolderRe = new RegExp(COMMENT_PLACEHOLDER, 'g');

const _placeholderRe = /__ph-(\d+)__/g;

const BLOCK_PLACEHOLDER = '%BLOCK%';
const _ruleRe = new RegExp(
`(\\s*(?:${COMMENT_PLACEHOLDER}\\s*)*)([^;\\{\\}]+?)(\\s*)((?:{%BLOCK%}?\\s*;?)|(?:\\s*;))`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ describe('ShadowCss, :host and :host-context', () => {
expect(shim(':host([a=b]) {}', 'contenta', 'a-host')).toEqualCss('[a=b][a-host] {}');
});

it('should handle attribute and next operator without spaces', () => {
expect(shim(':host[foo]>div {}', 'contenta', 'a-host'))
.toEqualCss(('[foo][a-host] > div[contenta] {}'));
});

it('should handle multiple tag selectors', () => {
expect(shim(':host(ul,li) {}', 'contenta', 'a-host')).toEqualCss('ul[a-host], li[a-host] {}');
expect(shim(':host(ul,li) > .z {}', 'contenta', 'a-host'))
Expand Down

0 comments on commit ecbaee1

Please sign in to comment.