| 702 | }; |
| 703 | |
| 704 | export const parseCss = ( |
| 705 | css: string, |
| 706 | cssVars: Map<string, string> |
| 707 | ): ParseCssResult => { |
| 708 | const ast = cssTreeTryParse(css); |
| 709 | const stylesMap = new Map<string, ParsedStyleDecl>(); |
| 710 | const errors: string[] = []; |
| 711 | |
| 712 | if (ast === undefined) { |
| 713 | return { styles: [], errors }; |
| 714 | } |
| 715 | |
| 716 | // Track context as we traverse — use a stack to support nested @media |
| 717 | const atruleStack: csstree.Atrule[] = []; |
| 718 | let currentRule: csstree.Rule | undefined; |
| 719 | // Custom properties declared in the current rule, used to resolve var() in shorthand expansion. |
| 720 | // Pre-populated for each rule (two-pass) so that forward references like |
| 721 | // border-color: rgb(x y z / var(--op)); --op: 0.6; |
| 722 | // resolve correctly regardless of declaration order. |
| 723 | const customProperties = new Map<string, string>(); |
| 724 | |
| 725 | const collectRuleCustomProperties = (rule: csstree.Rule) => { |
| 726 | customProperties.clear(); |
| 727 | csstree.walk(rule, { |
| 728 | visit: "Declaration", |
| 729 | enter(node) { |
| 730 | const decl = node as csstree.Declaration; |
| 731 | const prop = normalizeProperty(decl.property); |
| 732 | if (prop.startsWith("--")) { |
| 733 | const value = getRawDeclarationValue(css, decl); |
| 734 | if (value !== undefined && isValidCustomPropertyValue(value)) { |
| 735 | customProperties.set(prop, normalizeCustomPropertyValue(value)); |
| 736 | } |
| 737 | } |
| 738 | }, |
| 739 | }); |
| 740 | }; |
| 741 | |
| 742 | csstree.walk(ast, { |
| 743 | enter(node) { |
| 744 | if (node.type === "Atrule") { |
| 745 | atruleStack.push(node); |
| 746 | } else if (node.type === "Rule") { |
| 747 | currentRule = node; |
| 748 | collectRuleCustomProperties(node); |
| 749 | } |
| 750 | }, |
| 751 | leave(node) { |
| 752 | if (node.type === "Atrule") { |
| 753 | atruleStack.pop(); |
| 754 | } else if (node.type === "Rule") { |
| 755 | currentRule = undefined; |
| 756 | } |
| 757 | |
| 758 | // Process declarations |
| 759 | if ( |
| 760 | node.type !== "Declaration" || |
| 761 | !currentRule || |