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