diff --git a/README.md b/README.md index 10430fa7..db634a54 100644 --- a/README.md +++ b/README.md @@ -393,6 +393,11 @@ const options = { /** Disable a language by setting it to 'false' */ scss: false, + /** or pass an option to render synchronously and any other node-sass or sass options*/ + scss: { + renderSync: true + }, + /** Pass options to the default preprocessor method */ stylus: { paths: ['node_modules'], diff --git a/src/transformers/scss.ts b/src/transformers/scss.ts index e1532293..b80164b3 100644 --- a/src/transformers/scss.ts +++ b/src/transformers/scss.ts @@ -8,8 +8,25 @@ let sass: { options: SassOptions, callback: (exception: SassException, result: Result) => void, ) => void; + renderSync: ( + options: SassOptions + ) => Result; }; +type ResolveResult = { + code: string; + map: string | undefined; + dependencies: string[]; +}; + +function getResultForResolve(result: Result): ResolveResult { + return { + code: result.css.toString(), + map: result.map ? result.map.toString() : undefined, + dependencies: result.stats.includedFiles, + }; +} + const transformer: Transformer = async ({ content, filename, @@ -19,12 +36,15 @@ const transformer: Transformer = async ({ ({ default: sass } = await importAny('node-sass', 'sass')); } - options = { - sourceMap: true, - ...options, - includePaths: getIncludePaths(filename, options.includePaths), - outFile: filename + '.css', - }; + let renderSync: boolean; + ( + {renderSync, ...options} = { + sourceMap: true, + ...options, + includePaths: getIncludePaths(filename, options.includePaths), + outFile: filename + '.css', + } + ); options.data = options.data ? options.data + content : content; @@ -34,14 +54,21 @@ const transformer: Transformer = async ({ } return new Promise((resolve, reject) => { + if (renderSync){ + try { + const result = sass.renderSync(options); + + return resolve(getResultForResolve(result)); + } + catch (err){ + return reject(err as SassException); + } + } + sass.render(options, (err, result) => { if (err) return reject(err); - resolve({ - code: result.css.toString(), - map: result.map ? result.map.toString() : undefined, - dependencies: result.stats.includedFiles, - }); + resolve(getResultForResolve(result)); }); }); }; diff --git a/src/types/options.ts b/src/types/options.ts index 10a8c931..b3d4061a 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -26,7 +26,7 @@ export interface Babel extends BabelOptions { } export type Pug = PugOptions; -export type Sass = Omit; +export type Sass = Omit & { renderSync?: boolean }; // from /~https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/less/index.d.ts#L80 export interface Less { paths?: string[]; diff --git a/test/transformers/scss.test.ts b/test/transformers/scss.test.ts index 14edb120..aeb21db2 100644 --- a/test/transformers/scss.test.ts +++ b/test/transformers/scss.test.ts @@ -4,7 +4,7 @@ import getAutoPreprocess from '../../src'; import { preprocess } from '../utils'; describe('transformer - scss', () => { - it('should prepend scss content via `data` option property', async () => { + it('should prepend scss content via `data` option property - via defaul async render', async () => { const template = ``; const opts = getAutoPreprocess({ scss: { @@ -15,7 +15,7 @@ describe('transformer - scss', () => { expect(preprocessed.toString()).toContain('red'); }); - it('should return @imported files as dependencies', async () => { + it('should return @imported files as dependencies - via default async render', async () => { const template = ``; const opts = getAutoPreprocess(); const preprocessed = await preprocess(template, opts); @@ -23,4 +23,29 @@ describe('transformer - scss', () => { resolve(__dirname, '..', 'fixtures', 'style.scss').replace(/[\\/]/g, '/'), ); }); + + it('should prepend scss content via `data` option property - via renderSync', async () => { + const template = ``; + const opts = getAutoPreprocess({ + scss: { + data: '$color:blue;div{color:$color}', + renderSync: true, + }, + }); + const preprocessed = await preprocess(template, opts); + expect(preprocessed.toString()).toContain('blue'); + }); + + it('should return @imported files as dependencies - via renderSync', async () => { + const template = ``; + const opts = getAutoPreprocess({ + scss: { + renderSync: true, + }, + }); + const preprocessed = await preprocess(template, opts); + expect(preprocessed.dependencies).toContain( + resolve(__dirname, '..', 'fixtures', 'style.scss').replace(/[\\/]/g, '/'), + ); + }); });