|
1 | 1 | import * as svelte from 'svelte/compiler';
|
2 | 2 | import { safeBase64Hash } from './hash.js';
|
3 | 3 | import { log } from './log.js';
|
4 |
| -import { walk } from 'zimmerframe'; |
5 | 4 |
|
6 | 5 | import {
|
7 | 6 | checkPreprocessDependencies,
|
@@ -69,18 +68,31 @@ export function createCompileSvelte() {
|
69 | 68 | }
|
70 | 69 |
|
71 | 70 | let preprocessed;
|
72 |
| - let preprocessors = options.preprocess; |
| 71 | + let hasUnscopedGlobalCss = false; |
| 72 | + const preprocessors = options.preprocess |
| 73 | + ? Array.isArray(options.preprocess) |
| 74 | + ? [...options.preprocess] |
| 75 | + : [options.preprocess] |
| 76 | + : []; |
| 77 | + |
73 | 78 | if (!options.isBuild && options.emitCss && compileOptions.hmr) {
|
74 | 79 | // inject preprocessor that ensures css hmr works better
|
75 |
| - if (!Array.isArray(preprocessors)) { |
76 |
| - preprocessors = preprocessors |
77 |
| - ? [preprocessors, devStylePreprocessor] |
78 |
| - : [devStylePreprocessor]; |
79 |
| - } else { |
80 |
| - preprocessors = preprocessors.concat(devStylePreprocessor); |
81 |
| - } |
| 80 | + preprocessors.push(devStylePreprocessor); |
| 81 | + } |
| 82 | + |
| 83 | + if (options.emitCss) { |
| 84 | + // check if css has unscoped global rules |
| 85 | + // This is later used to decide if css output can be scoped to the js module for treeshaking |
| 86 | + preprocessors.push({ |
| 87 | + name: 'test-has-global-style', |
| 88 | + style({ content }) { |
| 89 | + hasUnscopedGlobalCss = |
| 90 | + content?.length > 0 && /(?:^|,)\s*(?::global[\s{(]|@keyframes -global-)/m.test(content); |
| 91 | + } |
| 92 | + }); |
82 | 93 | }
|
83 |
| - if (preprocessors) { |
| 94 | + |
| 95 | + if (preprocessors.length > 0) { |
84 | 96 | try {
|
85 | 97 | preprocessed = await svelte.preprocess(code, preprocessors, { filename }); // full filename here so postcss works
|
86 | 98 | } catch (e) {
|
@@ -134,29 +146,13 @@ export function createCompileSvelte() {
|
134 | 146 | try {
|
135 | 147 | compiled = svelte.compile(finalCode, { ...finalCompileOptions, filename });
|
136 | 148 |
|
137 |
| - // check if css has unscoped :global. |
138 |
| - // This is later used to decide if css output can be scoped to the js module for treeshaking |
139 |
| - if (compiled.css && compiled.ast.css && finalCode.includes(':global')) { |
140 |
| - walk( |
141 |
| - compiled.ast.css, |
142 |
| - {}, |
143 |
| - { |
144 |
| - Selector(node, { stop }) { |
145 |
| - if ( |
146 |
| - node.children?.[0].type === 'PseudoClassSelector' && |
147 |
| - node.children[0].name === 'global' |
148 |
| - ) { |
149 |
| - Object.defineProperty(compiled.css, '__meta', { |
150 |
| - value: { hasUnscopedGlobalCss: true }, |
151 |
| - writable: false, |
152 |
| - enumerable: false, |
153 |
| - configurable: false |
154 |
| - }); |
155 |
| - stop(); |
156 |
| - } |
157 |
| - } |
158 |
| - } |
159 |
| - ); |
| 149 | + if (compiled.css && hasUnscopedGlobalCss) { |
| 150 | + Object.defineProperty(compiled.css, '__meta', { |
| 151 | + value: { hasUnscopedGlobalCss }, |
| 152 | + writable: false, |
| 153 | + enumerable: false, |
| 154 | + configurable: false |
| 155 | + }); |
160 | 156 | }
|
161 | 157 |
|
162 | 158 | // patch output with partial accept until svelte does it
|
|
0 commit comments