|
1 | 1 | import { defineAddon, defineAddonOptions } from '@sveltejs/cli-core'; |
2 | | -import { addAtRule, addImports } from '@sveltejs/cli-core/css'; |
3 | 2 | import { array, functions, imports, object, exports } from '@sveltejs/cli-core/js'; |
4 | 3 | import { parseCss, parseJson, parseScript, parseSvelte } from '@sveltejs/cli-core/parsers'; |
5 | 4 | import { addSlot } from '@sveltejs/cli-core/html'; |
@@ -74,37 +73,38 @@ export default defineAddon({ |
74 | 73 | }); |
75 | 74 |
|
76 | 75 | sv.file('src/app.css', (content) => { |
77 | | - if (content.includes('tailwindcss')) { |
78 | | - return content; |
| 76 | + let atRules = parseCss(content).ast.nodes.filter((node) => node.type === 'atrule'); |
| 77 | + |
| 78 | + const findAtRule = (name: string, params: string) => |
| 79 | + atRules.find( |
| 80 | + (rule) => |
| 81 | + rule.name === name && |
| 82 | + // checks for both double and single quote variants |
| 83 | + rule.params.replace(/['"]/g, '') === params |
| 84 | + ); |
| 85 | + |
| 86 | + let code = content; |
| 87 | + const importsTailwind = findAtRule('import', 'tailwindcss'); |
| 88 | + if (!importsTailwind) { |
| 89 | + code = "@import 'tailwindcss';\n" + code; |
| 90 | + // reparse to account for the newly added tailwindcss import |
| 91 | + atRules = parseCss(code).ast.nodes.filter((node) => node.type === 'atrule'); |
79 | 92 | } |
80 | 93 |
|
81 | | - const { ast, generateCode } = parseCss(content); |
82 | | - const originalFirst = ast.first; |
83 | | - |
84 | | - const nodes = addImports(ast, ["'tailwindcss'"]); |
| 94 | + const lastAtRule = atRules.findLast((rule) => ['plugin', 'import'].includes(rule.name)); |
| 95 | + const pluginPos = lastAtRule!.source!.end!.offset; |
85 | 96 |
|
86 | 97 | for (const plugin of plugins) { |
87 | 98 | if (!options.plugins.includes(plugin.id)) continue; |
88 | 99 |
|
89 | | - addAtRule(ast, 'plugin', `'${plugin.package}'`, true); |
90 | | - } |
91 | | - |
92 | | - if ( |
93 | | - originalFirst !== ast.first && |
94 | | - originalFirst?.type === 'atrule' && |
95 | | - originalFirst.name === 'import' |
96 | | - ) { |
97 | | - originalFirst.raws.before = '\n'; |
| 100 | + const pluginRule = findAtRule('plugin', plugin.package); |
| 101 | + if (!pluginRule) { |
| 102 | + const pluginImport = `\n@plugin '${plugin.package}';`; |
| 103 | + code = code.substring(0, pluginPos) + pluginImport + code.substring(pluginPos); |
| 104 | + } |
98 | 105 | } |
99 | 106 |
|
100 | | - // We remove the first node to avoid adding a newline at the top of the stylesheet |
101 | | - nodes.shift(); |
102 | | - |
103 | | - // Each node is prefixed with single newline, ensuring the imports will always be single spaced. |
104 | | - // Without this, the CSS printer will vary the spacing depending on the current state of the stylesheet |
105 | | - nodes.forEach((n) => (n.raws.before = '\n')); |
106 | | - |
107 | | - return generateCode(); |
| 107 | + return code; |
108 | 108 | }); |
109 | 109 |
|
110 | 110 | if (!kit) { |
|
0 commit comments