Skip to content

Commit cbb8702

Browse files
committed
fix(compiler): namespace @property declarations
The `@property` atrule allows users to define custom CSS variables. These changes update the compiler to account for when namespacing variables. (cherry picked from commit 9b80d4c)
1 parent 046c16d commit cbb8702

2 files changed

Lines changed: 98 additions & 9 deletions

File tree

‎packages/compiler/src/shadow_css.ts‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,32 +1036,33 @@ const _cssColonInPlaceholderReGlobal = new RegExp(COLON_IN_PLACEHOLDER, 'g');
10361036

10371037
// Matches any CSS variable name, defined by a double-hyphen followed by any valid ident.
10381038
// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
1039-
const _cssVariableRe = /(var\(\s*)?(--(?:[a-zA-Z0-9_-]|[^\x00-\x7F])+)(\s*:)?/g;
1039+
const _cssVariableRe = /(var\(\s*|@property\s+)?(--(?:[a-zA-Z0-9_-]|[^\x00-\x7F])+)(\s*:)?/g;
10401040

10411041
/**
10421042
* Transforms CSS variables within a stylesheet to include a namespace placeholder.
10431043
*
10441044
* E.g. `--foo: bar;` becomes `--%NS%foo: bar;`
10451045
* E.g. `color: var(--foo);` becomes `color: var(--%NS%foo);`
1046+
* E.g. `@property --foo` becomes `@property --%NS%foo`
10461047
*
10471048
* If a variable is prefixed with `--global--`, it is NOT namespaced and the prefix is removed.
10481049
* E.g. `--global--mycolor: red;` becomes `--mycolor: red;`
10491050
*/
10501051
export function namespaceCssVariables(cssText: string): string {
1051-
return cssText.replace(_cssVariableRe, (match, leadingVar, varName, trailingColon) => {
1052-
// Check for a leading `var(` or trailing `:` to approximate whether we're operating on a
1053-
// real CSS variable, not another piece of syntax that resembles it. For example, this
1054-
// guards against:
1052+
return cssText.replace(_cssVariableRe, (match, prefix, varName, trailingColon) => {
1053+
// Check for a leading `var(`, `@property`, or trailing `:` to approximate whether we're
1054+
// operating on a real CSS variable, not another piece of syntax that resembles it.
1055+
// For example, this guards against:
10551056
// - `.foo--bar {}`
10561057
// - `/* --foo */`
10571058
// - `p { content: "--foo" }`
10581059
// - `[data---bar] {}`
10591060
// - `[data-status=foo--bar] {}`
10601061
// etc.
1061-
if (!leadingVar && !trailingColon) {
1062+
if (!prefix && !trailingColon) {
10621063
return match;
10631064
}
1064-
return (leadingVar ?? '') + namespaceCssVariable(varName) + (trailingColon ?? '');
1065+
return (prefix ?? '') + namespaceCssVariable(varName) + (trailingColon ?? '');
10651066
});
10661067
}
10671068

‎packages/compiler/test/shadow_css/shadow_css_spec.ts‎

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ describe('ShadowCss', () => {
433433
const input = `
434434
.foo {
435435
border: var(--global--border-size) solid var(--border-color);
436-
box-shadow:
436+
box-shadow:
437437
var(--shadow-1),
438438
var(--global--shadow-2),
439439
var(--shadow-3);
@@ -443,7 +443,7 @@ describe('ShadowCss', () => {
443443
const expected = `
444444
.foo {
445445
border: var(--border-size) solid var(--%NS%border-color);
446-
box-shadow:
446+
box-shadow:
447447
var(--%NS%shadow-1),
448448
var(--shadow-2),
449449
var(--%NS%shadow-3);
@@ -597,5 +597,93 @@ p {
597597
'CSS variable "--global-" has a single hyphen after "--global". Use two hyphens ("--global--") to opt-out of namespacing.',
598598
);
599599
});
600+
601+
it('should namespace @property declarations', () => {
602+
const input = `
603+
@property --myColor {
604+
syntax: "<color>";
605+
inherits: true;
606+
initial-value: rebeccapurple;
607+
}
608+
609+
@property --myWidth {
610+
syntax: "<length> | <percentage>";
611+
inherits: true;
612+
initial-value: 200px;
613+
}
614+
615+
p {
616+
background-color: var(--myColor);
617+
width: var(--myWidth);
618+
color: white;
619+
}
620+
`.trim();
621+
622+
const expected = `
623+
@property --%NS%myColor {
624+
syntax: "<color>";
625+
inherits: true;
626+
initial-value: rebeccapurple;
627+
}
628+
629+
@property --%NS%myWidth {
630+
syntax: "<length> | <percentage>";
631+
inherits: true;
632+
initial-value: 200px;
633+
}
634+
635+
p {
636+
background-color: var(--%NS%myColor);
637+
width: var(--%NS%myWidth);
638+
color: white;
639+
}
640+
`.trim();
641+
642+
expect(namespaceCssVariables(input)).toBe(expected);
643+
});
644+
645+
it('should not namespace @property if --global-- is present', () => {
646+
const input = `
647+
@property --global--my-color {
648+
syntax: "<color>";
649+
inherits: true;
650+
initial-value: rebeccapurple;
651+
}
652+
653+
@property --global--my-width {
654+
syntax: "<length> | <percentage>";
655+
inherits: true;
656+
initial-value: 200px;
657+
}
658+
659+
p {
660+
background-color: var(--global--my-color);
661+
width: var(--global--my-width);
662+
color: white;
663+
}
664+
`.trim();
665+
666+
const expected = `
667+
@property --my-color {
668+
syntax: "<color>";
669+
inherits: true;
670+
initial-value: rebeccapurple;
671+
}
672+
673+
@property --my-width {
674+
syntax: "<length> | <percentage>";
675+
inherits: true;
676+
initial-value: 200px;
677+
}
678+
679+
p {
680+
background-color: var(--my-color);
681+
width: var(--my-width);
682+
color: white;
683+
}
684+
`.trim();
685+
686+
expect(namespaceCssVariables(input)).toBe(expected);
687+
});
600688
});
601689
});

0 commit comments

Comments
 (0)