Skip to content

Commit

Permalink
feat: add option.transform (#146)
Browse files Browse the repository at this point in the history
  • Loading branch information
brafdlog authored and michael-ciniawsky committed Apr 30, 2017
1 parent e4ac886 commit 1c3943f
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 2 deletions.
41 changes: 41 additions & 0 deletions README.md
Expand Up @@ -77,6 +77,47 @@ If defined, the style-loader will re-use a single `<style>` element, instead of

If convertToAbsoluteUrls and sourceMaps are both enabled, relative urls will be converted to absolute urls right before the css is injected into the page. This resolves [an issue](https://github.com/webpack/style-loader/pull/96) where relative resources fail to load when source maps are enabled. You can enable it with the convertToAbsoluteUrls query parameter (`?convertToAbsoluteUrls`).

#### `transform`

A `transform` is a function that can modify the css just before it is loaded into the page by the style-loader.
This function will be called on the css that is about to be loaded and the return value of the function will be loaded into the page instead of the original css.
If the return value of the `transform` function is falsy, the css will not be loaded into the page at all.

Usage:

**webpack.config.js**
```js
{
loader: 'style-loader'
options: {
transform: 'path/to/transformCSS'
}
}
```

**transformCSS.js**
```js
module.exports = function(originalCss) {
// Here we can change the original css
const transformed = originalCss.replace('.classNameA', '.classNameB');
return transformed;
}
```

Example of conditional loading of css:

**conditionalCSS.js**
```js
module.exports = function (css) {
// If the condition is matched load [and transform] the CSS
if (css.includes('something I want to check')) {
return css;
}
// If a falsy value is returned, the CSS won't be loaded
return false
}
```

#### `attrs`

If defined, style-loader will attach given attributes with their values on `<style>` / `<link>` element.
Expand Down
19 changes: 18 additions & 1 deletion addStyles.js
Expand Up @@ -174,7 +174,24 @@ function attachTagAttrs(element, attrs) {
}

function addStyle(obj, options) {
var styleElement, update, remove;
var styleElement, update, remove, transformResult;

// If a transform function was defined, run it on the css
if (options.transform && obj.css) {
transformResult = options.transform(obj.css);

if (transformResult) {
// If transform returns a value, use that instead of the original css.
// This allows running runtime transformations on the css.
obj.css = transformResult;
} else {
// If the transform function returns a falsy value, don't add this css.
// This allows conditional loading of css
return function() {
// noop
};
}
}

if (options.singleton) {
var styleIndex = singletonCounter++;
Expand Down
7 changes: 6 additions & 1 deletion index.js
Expand Up @@ -14,8 +14,13 @@ module.exports.pitch = function(remainingRequest) {
"// load the styles",
"var content = require(" + loaderUtils.stringifyRequest(this, "!!" + remainingRequest) + ");",
"if(typeof content === 'string') content = [[module.id, content, '']];",
"// Prepare cssTransformation",
"var transform;",
query.transform ? "transform = require('" + path.resolve(query.transform) + "');" : "",
"var options = " + JSON.stringify(query),
"options.transform = transform",
"// add the styles to the DOM",
"var update = require(" + loaderUtils.stringifyRequest(this, "!" + path.join(__dirname, "addStyles.js")) + ")(content, " + JSON.stringify(query) + ");",
"var update = require(" + loaderUtils.stringifyRequest(this, "!" + path.join(__dirname, "addStyles.js")) + ")(content, options);",
"if(content.locals) module.exports = content.locals;",
"// Hot Module Replacement",
"if(module.hot) {",
Expand Down
25 changes: 25 additions & 0 deletions test/basicTest.js
Expand Up @@ -345,4 +345,29 @@ describe("basic tests", function() {
runCompilerTest(expected, done, function() { return this.css.locals.className; });
}); // it local scope

describe("transform function", function() {

it("should not load the css if the transform function returns false", function(done) {
styleLoaderOptions.transform = 'test/cssTransformations/returnFalse';
const expected = existingStyle;
runCompilerTest(expected, done);
});

it("should not load the css if the transform function returns undefined", function(done) {
styleLoaderOptions.transform = 'test/cssTransformations/returnNothing';
const expected = existingStyle;
runCompilerTest(expected, done);
});

it("should load the transformed css returned by the transform function", function(done) {
const transformCssFunction = require('./cssTransformations/transformCss');
styleLoaderOptions.transform = 'test/cssTransformations/transformCss';

const expectedTansformedStyle = transformCssFunction(requiredStyle);
const expected = [existingStyle, expectedTansformedStyle].join("\n");
runCompilerTest(expected, done);
});

});

}); // describe
3 changes: 3 additions & 0 deletions test/cssTransformations/returnFalse.js
@@ -0,0 +1,3 @@
module.exports = function(originalCss) {
return false;
}
3 changes: 3 additions & 0 deletions test/cssTransformations/returnNothing.js
@@ -0,0 +1,3 @@
module.exports = function(originalCss) {

}
3 changes: 3 additions & 0 deletions test/cssTransformations/transformCss.js
@@ -0,0 +1,3 @@
module.exports = function(originalCss) {
return originalCss.replace('.required', '.transformed');
}

0 comments on commit 1c3943f

Please sign in to comment.