-
-
Notifications
You must be signed in to change notification settings - Fork 99
/
preprocess.ts
99 lines (92 loc) · 3.08 KB
/
preprocess.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import path from 'path';
import { preprocessCSS, resolveConfig, transformWithEsbuild } from 'vite';
import type { ESBuildOptions, InlineConfig, ResolvedConfig } from 'vite';
// eslint-disable-next-line node/no-missing-import
import type { Preprocessor, PreprocessorGroup } from 'svelte/types/compiler/preprocess';
const supportedStyleLangs = ['css', 'less', 'sass', 'scss', 'styl', 'stylus', 'postcss', 'sss'];
const supportedScriptLangs = ['ts'];
export function vitePreprocess(opts?: {
script?: boolean;
style?: boolean | InlineConfig | ResolvedConfig;
}) {
const preprocessor: PreprocessorGroup = {};
if (opts?.script !== false) {
preprocessor.script = viteScript().script;
}
if (opts?.style !== false) {
const styleOpts = typeof opts?.style == 'object' ? opts?.style : undefined;
preprocessor.style = viteStyle(styleOpts).style;
}
return preprocessor;
}
function viteScript(): { script: Preprocessor } {
return {
async script({ attributes, content, filename = '' }) {
const lang = attributes.lang as string;
if (!supportedScriptLangs.includes(lang)) return;
const transformResult = await transformWithEsbuild(content, filename, {
loader: lang as ESBuildOptions['loader'],
target: 'esnext',
tsconfigRaw: {
compilerOptions: {
// svelte typescript needs this flag to work with type imports
importsNotUsedAsValues: 'preserve',
preserveValueImports: true
}
}
});
return {
code: transformResult.code,
map: transformResult.map
};
}
};
}
function viteStyle(config: InlineConfig | ResolvedConfig = {}): {
style: Preprocessor;
} {
let transform: CssTransform;
const style: Preprocessor = async ({ attributes, content, filename = '' }) => {
const lang = attributes.lang as string;
if (!supportedStyleLangs.includes(lang)) return;
if (!transform) {
let resolvedConfig: ResolvedConfig;
// @ts-expect-error special prop added if running in v-p-s
if (style.__resolvedConfig) {
// @ts-expect-error
resolvedConfig = style.__resolvedConfig;
} else if (isResolvedConfig(config)) {
resolvedConfig = config;
} else {
resolvedConfig = await resolveConfig(
config,
process.env.NODE_ENV === 'production' ? 'build' : 'serve'
);
}
transform = getCssTransformFn(resolvedConfig);
}
const moduleId = `${filename}.${lang}`;
const result = await transform(content, moduleId);
// patch sourcemap source to point back to original filename
if (result.map?.sources?.[0] === moduleId) {
result.map.sources[0] = path.basename(filename);
}
return {
code: result.code,
map: result.map ?? undefined
};
};
// @ts-expect-error tag so can be found by v-p-s
style.__resolvedConfig = null;
return { style };
}
// eslint-disable-next-line no-unused-vars
type CssTransform = (code: string, filename: string) => Promise<{ code: string; map?: any }>;
function getCssTransformFn(config: ResolvedConfig): CssTransform {
return async (code, filename) => {
return preprocessCSS(code, filename, config);
};
}
function isResolvedConfig(config: any): config is ResolvedConfig {
return !!config.inlineConfig;
}