Skip to content

Commit 1c3943f

Browse files
brafdlogmichael-ciniawsky
authored andcommitted
feat: add option.transform (#146)
1 parent e4ac886 commit 1c3943f

File tree

7 files changed

+99
-2
lines changed

7 files changed

+99
-2
lines changed

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,47 @@ If defined, the style-loader will re-use a single `<style>` element, instead of
7777

7878
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`).
7979

80+
#### `transform`
81+
82+
A `transform` is a function that can modify the css just before it is loaded into the page by the style-loader.
83+
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.
84+
If the return value of the `transform` function is falsy, the css will not be loaded into the page at all.
85+
86+
Usage:
87+
88+
**webpack.config.js**
89+
```js
90+
{
91+
loader: 'style-loader'
92+
options: {
93+
transform: 'path/to/transformCSS'
94+
}
95+
}
96+
```
97+
98+
**transformCSS.js**
99+
```js
100+
module.exports = function(originalCss) {
101+
// Here we can change the original css
102+
const transformed = originalCss.replace('.classNameA', '.classNameB');
103+
return transformed;
104+
}
105+
```
106+
107+
Example of conditional loading of css:
108+
109+
**conditionalCSS.js**
110+
```js
111+
module.exports = function (css) {
112+
// If the condition is matched load [and transform] the CSS
113+
if (css.includes('something I want to check')) {
114+
return css;
115+
}
116+
// If a falsy value is returned, the CSS won't be loaded
117+
return false
118+
}
119+
```
120+
80121
#### `attrs`
81122

82123
If defined, style-loader will attach given attributes with their values on `<style>` / `<link>` element.

addStyles.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,24 @@ function attachTagAttrs(element, attrs) {
174174
}
175175

176176
function addStyle(obj, options) {
177-
var styleElement, update, remove;
177+
var styleElement, update, remove, transformResult;
178+
179+
// If a transform function was defined, run it on the css
180+
if (options.transform && obj.css) {
181+
transformResult = options.transform(obj.css);
182+
183+
if (transformResult) {
184+
// If transform returns a value, use that instead of the original css.
185+
// This allows running runtime transformations on the css.
186+
obj.css = transformResult;
187+
} else {
188+
// If the transform function returns a falsy value, don't add this css.
189+
// This allows conditional loading of css
190+
return function() {
191+
// noop
192+
};
193+
}
194+
}
178195

179196
if (options.singleton) {
180197
var styleIndex = singletonCounter++;

index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ module.exports.pitch = function(remainingRequest) {
1414
"// load the styles",
1515
"var content = require(" + loaderUtils.stringifyRequest(this, "!!" + remainingRequest) + ");",
1616
"if(typeof content === 'string') content = [[module.id, content, '']];",
17+
"// Prepare cssTransformation",
18+
"var transform;",
19+
query.transform ? "transform = require('" + path.resolve(query.transform) + "');" : "",
20+
"var options = " + JSON.stringify(query),
21+
"options.transform = transform",
1722
"// add the styles to the DOM",
18-
"var update = require(" + loaderUtils.stringifyRequest(this, "!" + path.join(__dirname, "addStyles.js")) + ")(content, " + JSON.stringify(query) + ");",
23+
"var update = require(" + loaderUtils.stringifyRequest(this, "!" + path.join(__dirname, "addStyles.js")) + ")(content, options);",
1924
"if(content.locals) module.exports = content.locals;",
2025
"// Hot Module Replacement",
2126
"if(module.hot) {",

test/basicTest.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,4 +345,29 @@ describe("basic tests", function() {
345345
runCompilerTest(expected, done, function() { return this.css.locals.className; });
346346
}); // it local scope
347347

348+
describe("transform function", function() {
349+
350+
it("should not load the css if the transform function returns false", function(done) {
351+
styleLoaderOptions.transform = 'test/cssTransformations/returnFalse';
352+
const expected = existingStyle;
353+
runCompilerTest(expected, done);
354+
});
355+
356+
it("should not load the css if the transform function returns undefined", function(done) {
357+
styleLoaderOptions.transform = 'test/cssTransformations/returnNothing';
358+
const expected = existingStyle;
359+
runCompilerTest(expected, done);
360+
});
361+
362+
it("should load the transformed css returned by the transform function", function(done) {
363+
const transformCssFunction = require('./cssTransformations/transformCss');
364+
styleLoaderOptions.transform = 'test/cssTransformations/transformCss';
365+
366+
const expectedTansformedStyle = transformCssFunction(requiredStyle);
367+
const expected = [existingStyle, expectedTansformedStyle].join("\n");
368+
runCompilerTest(expected, done);
369+
});
370+
371+
});
372+
348373
}); // describe
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = function(originalCss) {
2+
return false;
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = function(originalCss) {
2+
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = function(originalCss) {
2+
return originalCss.replace('.required', '.transformed');
3+
}

0 commit comments

Comments
 (0)