Skip to content

Commit

Permalink
feat: allow data to be prepended via options.prependData
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Clark committed Mar 16, 2020
1 parent a6be94a commit db6fbdd
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 3 deletions.
69 changes: 69 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,75 @@ module.exports = {
};
```

### `prependData`

Type: `String|Function`
Default: `undefined`

Prepends `Less` code before the actual entry file.

This is especially useful when some of your Less variables depend on the environment:

> ℹ 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 Less entry files.
#### `String`

```js
module.exports = {
module: {
rules: [
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
prependData: `@env: ${process.env.NODE_ENV};`,
},
},
],
},
],
},
};
```

#### `Function`

```js
module.exports = {
module: {
rules: [
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
prependData: (loaderContext) => {
// More information about available properties 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;';
},
},
},
],
},
],
},
};
```

### `sourceMap`

Type: `Boolean`
Expand Down
12 changes: 11 additions & 1 deletion src/getLessOptions.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os from 'os';

import clone from 'clone';

import createWebpackLessPlugin from './createWebpackLessPlugin';
Expand All @@ -7,9 +9,10 @@ import createWebpackLessPlugin from './createWebpackLessPlugin';
*
* @param {object} loaderContext
* @param {object} loaderOptions
* @param {string} content
* @returns {Object}
*/
function getLessOptions(loaderContext, loaderOptions) {
function getLessOptions(loaderContext, loaderOptions, content) {
const options = clone(
loaderOptions.lessOptions
? typeof loaderOptions.lessOptions === 'function'
Expand All @@ -18,12 +21,19 @@ function getLessOptions(loaderContext, loaderOptions) {
: {}
);

const data = loaderOptions.prependData
? typeof loaderOptions.prependData === 'function'
? loaderOptions.prependData(loaderContext) + os.EOL + content
: loaderOptions.prependData + os.EOL + content
: content;

const lessOptions = {
plugins: [],
relativeUrls: true,
// We need to set the filename because otherwise our WebpackFileManager will receive an undefined path for the entry
filename: loaderContext.resourcePath,
...options,
data,
};

if (typeof lessOptions.paths === 'undefined') {
Expand Down
4 changes: 2 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ function lessLoader(source) {
});

const callback = this.async();
const lessOptions = getLessOptions(this, options);
const lessOptions = getLessOptions(this, options, source);

processResult(this, render(source, lessOptions), callback);
processResult(this, render(lessOptions.data, lessOptions), callback);
}

export default lessLoader;
11 changes: 11 additions & 0 deletions src/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@
}
]
},
"prependData": {
"description": "Prepends `Less` code before the actual entry file (https://github.com/webpack-contrib/less-loader#prependdata).",
"anyOf": [
{
"type": "string"
},
{
"instanceof": "Function"
}
]
},
"sourceMap": {
"description": "Enables/Disables generation of source maps (https://github.com/webpack-contrib/less-loader#sourcemap).",
"type": "boolean"
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/less/prepend-data.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.background {
color: @background;
}
20 changes: 20 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,26 @@ test("should resolve all imports from the given paths using Less' resolver", asy
});
});

test('should prepend data', async () => {
const loaderOptions = {
prependData() {
return `@background: red;`;
},
};

let inspect;

const rules = moduleRules.basic(loaderOptions, {}, (i) => {
inspect = i;
});

await compile('prepend-data', rules).catch((e) => e);

const [css] = inspect.arguments;

expect(css).toEqual('.background {\n color: red;\n}\n');
});

test('should allow a function to be passed through for `lessOptions`', async () => {
await compileAndCompare('import-paths', {
lessLoaderOptions: {
Expand Down

0 comments on commit db6fbdd

Please sign in to comment.