Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/thin-shrimps-sip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@lynx-js/css-serializer": patch
---

feat: support custom property declaration in keyframe rule
30 changes: 17 additions & 13 deletions packages/tools/css-serializer/src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,21 @@ function transformDeclaration(
}
}

function transformVariables(block: csstree.Block): Record<string, string> {
return Object.fromEntries(
block.children.toArray().filter((node) => {
return node.type === 'Declaration' && node.property.startsWith('--');
}).map((node) => {
const declaration = node as csstree.Declaration;
return [
declaration.property,
toString(declaration.value)
+ (declaration.important ? ' !important' : ''),
];
}),
);
}

function transformStyleRule(
node: csstree.Rule,
errors: ParserError[],
Expand All @@ -129,19 +144,7 @@ function transformStyleRule(
value: preludeText,
loc: toLoc(node.prelude.loc!.end),
},
variables: Object.fromEntries(
node.block.children.toArray().filter(node =>
node.type === 'Declaration' && node.property.startsWith('--')
).map((node) => {
return [
(node as csstree.Declaration).property,
toString((node as csstree.Declaration).value)
+ ((node as csstree.Declaration).important
? ' !important'
: ''),
];
}),
),
variables: transformVariables(node.block),
};
}

Expand Down Expand Up @@ -337,6 +340,7 @@ export function parse(content: string, options: {
value: preludeText,
loc: toLoc(rule.prelude.loc!.start, preludeText.length),
},
variables: transformVariables(rule.block),
style: transformBlock(rule.block, errors),
Comment thread
coderabbitai[bot] marked this conversation as resolved.
};
}),
Expand Down
1 change: 1 addition & 0 deletions packages/tools/css-serializer/src/types/LynxStyleNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export interface ImportRule {
}
export interface KeyframesStyle {
keyText: Value;
variables: Record<string, string>;
style: Declaration[];
}
export interface KeyframesRule {
Expand Down
17 changes: 17 additions & 0 deletions packages/tools/css-serializer/test/__preparation__/keyframes.css
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,20 @@
c: none;
}
}

@keyframes test-keyframe-declaration {
0% {
--bg-color: red;
background-color: var(--bg-color);
}

50% {
--bg-color: green;
background-color: var(--bg-color);
}

100% {
--bg-color: blue;
background-color: var(--bg-color);
}
}
115 changes: 115 additions & 0 deletions packages/tools/css-serializer/test/__snapshots__/lynx.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2030,6 +2030,7 @@ exports[`keyframes 1`] = `
"value": "translateX(0%)",
},
],
"variables": {},
},
{
"keyText": {
Expand All @@ -2053,6 +2054,7 @@ exports[`keyframes 1`] = `
"value": "translateX(100%)",
},
],
"variables": {},
},
],
"type": "KeyframesRule",
Expand Down Expand Up @@ -2100,6 +2102,7 @@ exports[`keyframes 1`] = `
"value": "0",
},
],
"variables": {},
},
{
"keyText": {
Expand All @@ -2123,6 +2126,7 @@ exports[`keyframes 1`] = `
"value": "50px",
},
],
"variables": {},
},
{
"keyText": {
Expand All @@ -2146,6 +2150,7 @@ exports[`keyframes 1`] = `
"value": "50px",
},
],
"variables": {},
},
{
"keyText": {
Expand Down Expand Up @@ -2181,6 +2186,7 @@ exports[`keyframes 1`] = `
"value": "100%",
},
],
"variables": {},
},
],
"type": "KeyframesRule",
Expand Down Expand Up @@ -2216,6 +2222,7 @@ exports[`keyframes 1`] = `
"value": "1",
},
],
"variables": {},
},
{
"keyText": {
Expand Down Expand Up @@ -2251,6 +2258,7 @@ exports[`keyframes 1`] = `
"value": "3",
},
],
"variables": {},
},
{
"keyText": {
Expand All @@ -2274,6 +2282,7 @@ exports[`keyframes 1`] = `
"value": "5",
},
],
"variables": {},
},
{
"keyText": {
Expand All @@ -2297,6 +2306,112 @@ exports[`keyframes 1`] = `
"value": "none",
},
],
"variables": {},
},
],
"type": "KeyframesRule",
},
{
"name": {
"loc": {
"column": 37,
"line": 37,
},
"value": "test-keyframe-declaration",
},
"styles": [
{
"keyText": {
"loc": {
"column": 5,
"line": 38,
},
"value": "0%",
},
"style": [
{
"defaultValue": "",
"defaultValueMap": {
"--bg-color": "",
},
"keyLoc": {
"column": 21,
"line": 40,
},
"name": "background-color",
"type": "css_var",
"valLoc": {
"column": 39,
"line": 40,
},
"value": "{{--bg-color}}",
},
],
"variables": {
"--bg-color": "red",
},
},
{
"keyText": {
"loc": {
"column": 6,
"line": 43,
},
"value": "50%",
},
"style": [
{
"defaultValue": "",
"defaultValueMap": {
"--bg-color": "",
},
"keyLoc": {
"column": 21,
"line": 45,
},
"name": "background-color",
"type": "css_var",
"valLoc": {
"column": 39,
"line": 45,
},
"value": "{{--bg-color}}",
},
],
"variables": {
"--bg-color": "green",
},
},
{
"keyText": {
"loc": {
"column": 7,
"line": 48,
},
"value": "100%",
},
"style": [
{
"defaultValue": "",
"defaultValueMap": {
"--bg-color": "",
},
"keyLoc": {
"column": 21,
"line": 50,
},
"name": "background-color",
"type": "css_var",
"valLoc": {
"column": 39,
"line": 50,
},
"value": "{{--bg-color}}",
},
],
"variables": {
"--bg-color": "blue",
},
},
],
"type": "KeyframesRule",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ exports[`encodeCSS > scoped css 1`] = `".foo:where([l-css-id="1"]):not([l-e-name
exports[`encodeCSS > scoped css, 2 css id 1`] = `".foo:where([l-css-id="1"]):not([l-e-name]),.foo:where([l-css-id="2"]):not([l-e-name]){background:red;}"`;

exports[`encodeCSS > scoped css, import non existing 1`] = `".foo:where([l-css-id="1"]):not([l-e-name]),.foo:where([l-css-id="20"]):not([l-e-name]),.foo:where([l-css-id="2"]):not([l-e-name]){background:red;}"`;

exports[`encodeCSS > should encode KeyframesRule with CSS variables 1`] = `"@keyframes my-animation-with-vars{from{--my-var:0;opacity:{{--my-var}};}to{--my-var:1;opacity:{{--my-var}};}}"`;
25 changes: 25 additions & 0 deletions packages/web-platform/web-core/tests/encode.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,31 @@ describe('encodeCSS', () => {
expect(buffer.length).toBeGreaterThan(0);
});

test('should encode KeyframesRule with CSS variables', () => {
const css = `
@keyframes my-animation-with-vars {
from {
--my-var: 0;
opacity: var(--my-var);
}
to {
--my-var: 1;
opacity: var(--my-var);
}
}
`;
const cssMap = {
'1': CSS.parse(css).root,
};
const buffer = encodeCSS(cssMap);
expect(buffer).toBeInstanceOf(Uint8Array);
expect(buffer.length).toBeGreaterThan(0);
const decodedString = get_style_content(
decode_style_info(buffer, undefined, true),
);
expect(decodedString.trim()).toMatchSnapshot();
});

test('should handle complex selectors', () => {
const css = `
div > .foo + #bar[attr="val"]::before:hover {
Expand Down
6 changes: 6 additions & 0 deletions packages/web-platform/web-core/ts/encode/encodeCSS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ export function encodeCSS(

keyFrameChildrenRule.set_prelude(prelude);

for (
const [key, value] of Object.entries(keyframesStyle.variables ?? {})
) {
keyFrameChildrenRule.push_declaration(key, value);
}

for (const decl of keyframesStyle.style) {
keyFrameChildrenRule.push_declaration(decl.name, decl.value);
}
Expand Down
Loading