From f60f75f1f377d8b49bb3c18c974f9ea59fac5b05 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Fri, 14 Dec 2018 18:49:32 +0300 Subject: [PATCH] feat: support `data` as `Function` --- README.md | 21 +++++++++++++++++++++ lib/normalizeOptions.js | 8 +++++++- test/index.test.js | 12 +++++++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 56e76651..8cb23f33 100644 --- a/README.md +++ b/README.md @@ -274,6 +274,27 @@ If you want to prepend Sass code before the actual entry file, you can set the ` } ``` +The `data` option supports `Function` notation: + +```javascript +{ + loader: "sass-loader", + options: { + data: (loaderContext) => { + // More information about avalaible options https://webpack.js.org/api/loaders/ + const { resourcePath, rootContext } = loaderContext; + const relativePath = path.relative(rootContext,resourcePath); + + if (relativePath === "styles/foo.scss") { + return "$value: 100px;" + } + + return "$value: 200px;" + } + } +} +``` + **Please note:** Since you're injecting code, this will break the source mappings in your entry file. Often there's a simpler solution than this, like multiple Sass entry files.

Maintainers

diff --git a/lib/normalizeOptions.js b/lib/normalizeOptions.js index c7ef5c17..3dde5253 100644 --- a/lib/normalizeOptions.js +++ b/lib/normalizeOptions.js @@ -23,7 +23,13 @@ function normalizeOptions(loaderContext, content, webpackImporter) { const options = cloneDeep(utils.getOptions(loaderContext)) || {}; const { resourcePath } = loaderContext; - options.data = options.data ? options.data + os.EOL + content : content; + let { data } = options; + + if (typeof options.data === 'function') { + data = options.data(loaderContext); + } + + options.data = data ? data + os.EOL + content : content; // opt.outputStyle if (!options.outputStyle && loaderContext.minimize) { diff --git a/test/index.test.js b/test/index.test.js index 63c99a92..3bcac39a 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -47,6 +47,8 @@ Object.defineProperty(loaderContextMock, 'options', { }, }); +/* global should */ + implementations.forEach((implementation) => { const [implementationName] = implementation.info.split('\t'); @@ -185,10 +187,18 @@ implementations.forEach((implementation) => { })); }); describe('prepending data', () => { - it('should extend the data-option if present', () => + it('should extend the data option if present and it is string', () => execTest('prepending-data', { data: `$prepended-data: hotpink${ext === 'sass' ? '\n' : ';'}`, })); + it('should extend the data option if present and it is function', () => + execTest('prepending-data', { + data: (loaderContext) => { + should.exist(loaderContext); + + return `$prepended-data: hotpink${ext === 'sass' ? '\n' : ';'}`; + }, + })); }); // See https://github.com/webpack-contrib/sass-loader/issues/21 describe('empty files', () => {