Skip to content

Commit

Permalink
fix(compiler): handle css selectors with space after an escaped chara…
Browse files Browse the repository at this point in the history
…cter. (#48558)

In Css, selectors with escaped characters require a space after if the following character is a hex character. ie: .\fc ber which matches class="über"
These escaped selectors happen for example when esbuild run with `optimization.minify`

fixes #48524

PR Close #48558
  • Loading branch information
JeanMeche authored and thePunderWoman committed Jan 24, 2023
1 parent 64416a6 commit 98ccb57
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
14 changes: 13 additions & 1 deletion packages/compiler/src/shadow_css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ const animationKeywords = new Set([
in comments in lieu of the next selector when running under polyfill.
*/
export class ShadowCss {
// TODO: Is never re-assigned, could be removed.
strictStyling: boolean = true;

/*
Expand Down Expand Up @@ -729,6 +730,15 @@ export class ShadowCss {
while ((res = sep.exec(selector)) !== null) {
const separator = res[1];
const part = selector.slice(startIndex, res.index).trim();

// A space following an escaped hex value and followed by another hex character
// (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]/)) {
continue;
}

shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1;
const scopedPart = shouldScope ? _scopeSelectorPart(part) : part;
scopedSelector += `${scopedPart} ${separator} `;
Expand Down Expand Up @@ -777,7 +787,7 @@ class SafeSelector {
}

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

content(): string {
Expand Down Expand Up @@ -833,6 +843,8 @@ const _colonHostContextRe = /:host-context/gim;

const _commentRe = /\/\*[\s\S]*?\*\//g;

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

function stripComments(input: string): string {
return input.replace(_commentRe, '');
}
Expand Down
9 changes: 9 additions & 0 deletions packages/compiler/test/shadow_css/shadow_css_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ describe('ShadowCss', () => {
.toEqualCss('.one\\:two[contenta] .three\\:four[contenta] {}');
});

it('should handle escaped selector with space (if followed by a hex char)', () => {
// When esbuild runs with optimization.minify
// selectors are escaped: .über becomes .\fc ber.
// The space here isn't a separator between 2 selectors
expect(shim('.\\fc ber {}', 'contenta')).toEqual('.\\fc ber[contenta] {}');
expect(shim('.\\fc ker {}', 'contenta')).toEqual('.\\fc[contenta] ker[contenta] {}');
expect(shim('.pr\\fc fung {}', 'contenta')).toEqual('.pr\\fc fung[contenta] {}');
});

it('should handle ::shadow', () => {
const css = shim('x::shadow > y {}', 'contenta');
expect(css).toEqualCss('x[contenta] > y[contenta] {}');
Expand Down

0 comments on commit 98ccb57

Please sign in to comment.