|
1 | | -import { Declaration, Rule, AtRule, Comment, type CssAst, type CssChildNode } from '../index.ts'; |
2 | | - |
3 | | -export type { CssAst }; |
4 | | - |
5 | | -export function addRule(node: CssAst, options: { selector: string }): Rule { |
6 | | - const rules = node.nodes.filter((x): x is Rule => x.type === 'rule'); |
7 | | - let rule = rules.find((x) => x.selector === options.selector); |
| 1 | +import type { SvelteAst } from '../index.ts'; |
| 2 | + |
| 3 | +export function addRule( |
| 4 | + node: SvelteAst.CSS.StyleSheet, |
| 5 | + options: { selector: string } |
| 6 | +): SvelteAst.CSS.Rule { |
| 7 | + // we do not check for existing rules here, as the selector AST from svelte is really complex |
| 8 | + const rules = node.children.filter((x) => x.type === 'Rule'); |
| 9 | + let rule = rules.find((x) => { |
| 10 | + const selector = x.prelude.children[0].children[0].selectors[0]; |
| 11 | + return selector.type === 'ClassSelector' && selector.name === options.selector; |
| 12 | + }); |
8 | 13 |
|
9 | 14 | if (!rule) { |
10 | | - rule = new Rule(); |
11 | | - rule.selector = options.selector; |
12 | | - node.nodes.push(rule); |
| 15 | + rule = { |
| 16 | + type: 'Rule', |
| 17 | + prelude: { |
| 18 | + type: 'SelectorList', |
| 19 | + children: [ |
| 20 | + { |
| 21 | + type: 'ComplexSelector', |
| 22 | + children: [ |
| 23 | + { |
| 24 | + type: 'RelativeSelector', |
| 25 | + selectors: [ |
| 26 | + { |
| 27 | + type: 'ClassSelector', |
| 28 | + name: options.selector, |
| 29 | + start: 0, |
| 30 | + end: 0 |
| 31 | + } |
| 32 | + ], |
| 33 | + combinator: null, |
| 34 | + start: 0, |
| 35 | + end: 0 |
| 36 | + } |
| 37 | + ], |
| 38 | + start: 0, |
| 39 | + end: 0 |
| 40 | + } |
| 41 | + ], |
| 42 | + start: 0, |
| 43 | + end: 0 |
| 44 | + }, |
| 45 | + block: { type: 'Block', children: [], start: 0, end: 0 }, |
| 46 | + start: 0, |
| 47 | + end: 0 |
| 48 | + }; |
| 49 | + node.children.push(rule); |
13 | 50 | } |
14 | 51 |
|
15 | 52 | return rule; |
16 | 53 | } |
17 | 54 |
|
18 | 55 | export function addDeclaration( |
19 | | - node: Rule | CssAst, |
| 56 | + node: SvelteAst.CSS.Rule, |
20 | 57 | options: { property: string; value: string } |
21 | 58 | ): void { |
22 | | - const declarations = node.nodes.filter((x): x is Declaration => x.type === 'decl'); |
23 | | - let declaration = declarations.find((x) => x.prop === options.property); |
| 59 | + const declarations = node.block.children.filter((x) => x.type === 'Declaration'); |
| 60 | + let declaration = declarations.find((x) => x.property === options.property); |
24 | 61 |
|
25 | 62 | if (!declaration) { |
26 | | - declaration = new Declaration({ prop: options.property, value: options.value }); |
27 | | - node.append(declaration); |
| 63 | + declaration = { |
| 64 | + type: 'Declaration', |
| 65 | + property: options.property, |
| 66 | + value: options.value, |
| 67 | + start: 0, |
| 68 | + end: 0 |
| 69 | + }; |
| 70 | + node.block.children.push(declaration); |
28 | 71 | } else { |
29 | 72 | declaration.value = options.value; |
30 | 73 | } |
31 | 74 | } |
32 | 75 |
|
33 | | -export function addImports(node: Rule | CssAst, options: { imports: string[] }): CssChildNode[] { |
34 | | - let prev: CssChildNode | undefined; |
35 | | - const nodes = options.imports.map((param) => { |
36 | | - const found = node.nodes.find( |
37 | | - (x) => x.type === 'atrule' && x.name === 'import' && x.params === param |
38 | | - ); |
39 | | - |
40 | | - if (found) return (prev = found); |
| 76 | +export function addImports(node: SvelteAst.CSS.StyleSheet, options: { imports: string[] }): void { |
| 77 | + let lastImportIndex = -1; |
41 | 78 |
|
42 | | - const rule = new AtRule({ name: 'import', params: param }); |
43 | | - if (prev) node.insertAfter(prev, rule); |
44 | | - else node.prepend(rule); |
| 79 | + // Find the last existing @import to insert after it |
| 80 | + for (let i = 0; i < node.children.length; i++) { |
| 81 | + const child = node.children[i]; |
| 82 | + if (child.type === 'Atrule' && child.name === 'import') { |
| 83 | + lastImportIndex = i; |
| 84 | + } |
| 85 | + } |
45 | 86 |
|
46 | | - return (prev = rule); |
47 | | - }); |
| 87 | + for (const param of options.imports) { |
| 88 | + const found = node.children.find( |
| 89 | + (x) => x.type === 'Atrule' && x.name === 'import' && x.prelude === param |
| 90 | + ); |
48 | 91 |
|
49 | | - return nodes; |
| 92 | + if (found) continue; |
| 93 | + |
| 94 | + const atRule: SvelteAst.CSS.Atrule = { |
| 95 | + type: 'Atrule', |
| 96 | + name: 'import', |
| 97 | + prelude: param, |
| 98 | + block: null, |
| 99 | + start: 0, |
| 100 | + end: 0 |
| 101 | + }; |
| 102 | + |
| 103 | + if (lastImportIndex >= 0) { |
| 104 | + // Insert after the last @import |
| 105 | + lastImportIndex++; |
| 106 | + node.children.splice(lastImportIndex, 0, atRule); |
| 107 | + } else { |
| 108 | + // No existing imports, prepend at the start |
| 109 | + node.children.unshift(atRule); |
| 110 | + lastImportIndex = 0; |
| 111 | + } |
| 112 | + } |
50 | 113 | } |
51 | 114 |
|
52 | 115 | export function addAtRule( |
53 | | - node: CssAst, |
| 116 | + node: SvelteAst.CSS.StyleSheet, |
54 | 117 | options: { name: string; params: string; append: boolean } |
55 | | -): AtRule { |
56 | | - const atRules = node.nodes.filter((x): x is AtRule => x.type === 'atrule'); |
57 | | - let atRule = atRules.find((x) => x.name === options.name && x.params === options.params); |
| 118 | +): SvelteAst.CSS.Atrule { |
| 119 | + const atRules = node.children.filter((x) => x.type === 'Atrule'); |
| 120 | + let atRule = atRules.find((x) => x.name === options.name && x.prelude === options.params); |
58 | 121 |
|
59 | 122 | if (atRule) { |
60 | 123 | return atRule; |
61 | 124 | } |
62 | 125 |
|
63 | | - atRule = new AtRule({ name: options.name, params: options.params }); |
| 126 | + atRule = { |
| 127 | + type: 'Atrule', |
| 128 | + name: options.name, |
| 129 | + prelude: options.params, |
| 130 | + block: null, |
| 131 | + start: 0, |
| 132 | + end: 0 |
| 133 | + }; |
| 134 | + |
64 | 135 | if (!options.append) { |
65 | | - node.prepend(atRule); |
| 136 | + node.children.unshift(atRule); |
66 | 137 | } else { |
67 | | - node.append(atRule); |
| 138 | + node.children.push(atRule); |
68 | 139 | } |
69 | 140 |
|
70 | 141 | return atRule; |
71 | 142 | } |
72 | | - |
73 | | -export function addComment(node: CssAst, options: { value: string }): void { |
74 | | - const comment = new Comment({ text: options.value }); |
75 | | - node.append(comment); |
76 | | -} |
|
0 commit comments