fix(compiler): handle case-sensitive CSS custom properties (#41380)

Currently we normalize all CSS property names in the `StylingBuilder` which breaks custom properties, because they're case-sensitive. These changes add a check so that custom properties aren't normalized.

Fixes #41364.

PR Close #41380
This commit is contained in:
Kristiyan Kostadinov 2021-03-30 11:08:56 +02:00 committed by Alex Rickabaugh
parent c4628f29be
commit e112e320bf
2 changed files with 34 additions and 3 deletions

View File

@ -219,7 +219,11 @@ export class StylingBuilder {
if (isEmptyExpression(value)) {
return null;
}
name = normalizePropName(name);
// CSS custom properties are case-sensitive so we shouldn't normalize them.
// See: https://www.w3.org/TR/css-variables-1/#defining-variables
if (!isCssCustomProperty(name)) {
name = hyphenate(name);
}
const {property, hasOverrideFlag, suffix: bindingSuffix} = parseProperty(name);
suffix = typeof suffix === 'string' && suffix.length !== 0 ? suffix : bindingSuffix;
const entry:
@ -607,6 +611,10 @@ function getStylePropInterpolationExpression(interpolation: Interpolation) {
}
}
function normalizePropName(prop: string): string {
return hyphenate(prop);
/**
* Checks whether property name is a custom CSS property.
* See: https://www.w3.org/TR/css-variables-1
*/
function isCssCustomProperty(name: string): boolean {
return name.startsWith('--');
}

View File

@ -294,6 +294,29 @@ describe('styling', () => {
const header = fixture.nativeElement.querySelector('h1') as HTMLElement;
expect(getComputedStyle(header).getPropertyValue('width')).toEqual('100px');
});
it('should support case-sensitive css variables', () => {
// This test only works in browsers which support CSS variables.
if (!supportsCssVariables) {
return;
}
@Component({
template: `
<div [style.--MyVar]="'100px'">
<span style="width: var(--MyVar)">CONTENT</span>
</div>
`
})
class Cmp {
}
TestBed.configureTestingModule({declarations: [Cmp]});
const fixture = TestBed.createComponent(Cmp);
fixture.detectChanges();
const span = fixture.nativeElement.querySelector('span') as HTMLElement;
expect(getComputedStyle(span).getPropertyValue('width')).toEqual('100px');
});
});
modifiedInIvy('shadow bindings include static portion')