| 2979 | // Collect idents/strings to export — top-level only, except grid-template recurses (`[line-name]` blocks live in `repeat(…)`). |
| 2980 | /** @type {(cvs: AstNode[]) => void} */ |
| 2981 | const walkExports = (cvs) => { |
| 2982 | for (const cv of cvs) { |
| 2983 | switch (A.type(cv)) { |
| 2984 | case NodeType.Comma: |
| 2985 | parsedKeywords = Object.create(null); |
| 2986 | break; |
| 2987 | case NodeType.Delim: |
| 2988 | afterExclamation = A.value(cv) === "!"; |
| 2989 | break; |
| 2990 | case NodeType.Ident: { |
| 2991 | if (isGridTemplate) break; |
| 2992 | if (afterExclamation) { |
| 2993 | afterExclamation = false; |
| 2994 | break; |
| 2995 | } |
| 2996 | const identifier = A.value(cv); |
| 2997 | const keyword = identifier.toLowerCase(); |
| 2998 | parsedKeywords[keyword] = |
| 2999 | typeof parsedKeywords[keyword] !== "undefined" |
| 3000 | ? parsedKeywords[keyword] + 1 |
| 3001 | : 0; |
| 3002 | if ( |
| 3003 | keywords[keyword] && |
| 3004 | parsedKeywords[keyword] < keywords[keyword] |
| 3005 | ) { |
| 3006 | break; |
| 3007 | } |
| 3008 | emit(A.start(cv), A.end(cv)); |
| 3009 | break; |
| 3010 | } |
| 3011 | case NodeType.String: { |
| 3012 | if ( |
| 3013 | declPropertyName === "animation" || |
| 3014 | declPropertyName === "animation-name" |
| 3015 | ) { |
| 3016 | emit(A.start(cv), A.end(cv), true); |
| 3017 | } |
| 3018 | if ( |
| 3019 | declPropertyName === "grid" || |
| 3020 | declPropertyName === "grid-template" || |
| 3021 | declPropertyName === "grid-template-areas" |
| 3022 | ) { |
| 3023 | const areas = A.unescaped(cv); |
| 3024 | const matches = matchAll(/\b\w+\b/g, areas); |
| 3025 | for (const match of matches) { |
| 3026 | const areaStart = A.start(cv) + 1 + match.index; |
| 3027 | emit(areaStart, areaStart + match[0].length, false); |
| 3028 | } |
| 3029 | } |
| 3030 | break; |
| 3031 | } |
| 3032 | case NodeType.SimpleBlock: { |
| 3033 | const block = /** @type {SimpleBlock} */ (cv); |
| 3034 | if (A.blockToken(block) === "[") { |
| 3035 | // Collect identifiers until the first non-ident token (`<line-names> = '[' <custom-ident>* ']'`). |
| 3036 | for (const inner of A.children(block)) { |
| 3037 | if (A.type(inner) === NodeType.Whitespace) continue; |
| 3038 | if (A.type(inner) !== NodeType.Ident) break; |