|
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