-
Notifications
You must be signed in to change notification settings - Fork 150
/
scss.ts
89 lines (70 loc) · 2.43 KB
/
scss.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
import { readFileSync } from 'fs';
import { isAbsolute, join } from 'path';
import { getIncludePaths, findUp } from '../modules/utils';
import type { LegacySyncImporter, LegacyStringOptions } from 'sass';
import type { Transformer, Options } from '../types';
const tildeImporter: LegacySyncImporter = (url, prev) => {
if (!url.startsWith('~')) {
return null;
}
// not sure why this ends up here, but let's remove it
prev = prev.replace('http://localhost', '');
// on windows, path comes encoded
if (process.platform === 'win32') {
prev = decodeURIComponent(prev);
}
const modulePath = join('node_modules', ...url.slice(1).split(/[\\/]/g));
const foundPath = findUp({ what: modulePath, from: prev });
// istanbul ignore if
if (foundPath == null) {
return null;
}
const contents = readFileSync(foundPath).toString();
return { contents };
};
const transformer: Transformer<Options.Sass> = async ({
content,
filename,
options = {},
}) => {
const { renderSync } = await import('sass');
const { prependData, ...restOptions } = options;
const sassOptions: LegacyStringOptions<'sync'> = {
...restOptions,
includePaths: getIncludePaths(filename, options.includePaths),
sourceMap: true,
sourceMapEmbed: false,
omitSourceMapUrl: true,
outFile: `${filename}.css`,
outputStyle: 'expanded',
file: filename,
data: content,
};
if (Array.isArray(sassOptions.importer)) {
sassOptions.importer = [tildeImporter, ...sassOptions.importer];
} else if (sassOptions.importer == null) {
sassOptions.importer = [tildeImporter];
} else {
sassOptions.importer = [sassOptions.importer, tildeImporter];
}
// scss errors if passed an empty string
if (content.length === 0) {
return { code: '' };
}
const compiled = renderSync(sassOptions);
// For some reason, scss includes the main 'file' in the array, we don't want that
// Unfortunately I didn't manage to reproduce this in the test env
// More info: https://github.com/sveltejs/svelte-preprocess/issues/346
const absoluteEntryPath = isAbsolute(compiled.stats.entry)
? compiled.stats.entry
: join(process.cwd(), compiled.stats.entry);
const processed = {
code: compiled.css.toString(),
map: compiled.map?.toString(),
dependencies: Array.from(compiled.stats.includedFiles).filter(
(filepath) => filepath !== absoluteEntryPath,
),
};
return processed;
};
export { transformer };