1import resolveFrom from 'resolve-from';
2
3let sassInstance: typeof import('sass') | null = null;
4
5function getSassInstance(projectRoot: string) {
6  if (!sassInstance) {
7    const sassPath = resolveFrom.silent(projectRoot, 'sass');
8
9    if (!sassPath) {
10      throw new Error(
11        `Cannot parse Sass files without the module 'sass' installed. Run 'yarn add sass' and try again.`
12      );
13    }
14
15    sassInstance = require(sassPath) as typeof import('sass');
16  }
17
18  return sassInstance;
19}
20
21export function matchSass(filename: string): import('sass').Syntax | null {
22  if (filename.endsWith('.sass')) {
23    return 'indented';
24  } else if (filename.endsWith('.scss')) {
25    return 'scss';
26  }
27  return null;
28}
29
30export function compileSass(
31  projectRoot: string,
32  { filename, src }: { filename: string; src: string },
33  // TODO: Expose to users somehow...
34  options?: Partial<import('sass').StringOptions<'sync'>>
35) {
36  const sass = getSassInstance(projectRoot);
37  const result = sass.compileString(src, options);
38  return {
39    src: result.css,
40    // TODO: Should we use this? Leaning towards no since the CSS will be parsed again by the CSS loader.
41    map: result.sourceMap,
42  };
43}
44