Skip to content

Commit ccbc01f

Browse files
committed
Update all functions
1 parent da0e4bf commit ccbc01f

File tree

1 file changed

+232
-101
lines changed

1 file changed

+232
-101
lines changed

index.js

Lines changed: 232 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,134 +1,265 @@
11
const mix = require("laravel-mix");
22

3-
class VueCssModule {
3+
class VueCssModules {
44
/**
55
* Register the component.
66
*
7-
* When your component is called, all user parameters
8-
* will be passed to this method.
9-
*
10-
* Ex: register(src, output) {}
11-
* Ex: mix.yourPlugin('src/path', 'output/path');
12-
*
13-
* @param {*} ...params
14-
* @return {void}
15-
*
7+
* @param {Object} options
8+
* @param {Boolean} [options.oneOf]
9+
* @param {Boolean} [options.preProcessor]
10+
* @param {String} [options.localIdentNameType]
11+
* @param {Object} [options.cssLoaderOptions]
1612
*/
17-
register({
18-
localIdentName = "[local]_[hash:base64:8]",
19-
mode = "global",
20-
oneOf = false,
21-
sass = false,
22-
} = {}) {
23-
this.localIdentName = localIdentName;
24-
this.mode = mode;
25-
this.oneOf = oneOf;
26-
this.sass = sass;
13+
register(options = {}) {
14+
const config = {
15+
modules: true, // {Boolean\|String\|Object}
16+
sourceMap: false, // {Boolean}
17+
importLoaders: 1, // {Number} // webpackDefault: 0 // laravel-mix default: 1
18+
esModule: true, // {Boolean},
19+
localIdentName: options.cssLoaderOptions.localIdentName
20+
? options.cssLoaderOptions.localIdentName
21+
: this.defaultLocalIdentName(options.localIdentNameType), // {String}
22+
};
23+
24+
const cssLoaderOptions = {
25+
...config,
26+
...options.cssLoaderOptions,
27+
};
28+
29+
delete options.cssLoaderOptions;
30+
31+
this.options = Object.assign(
32+
{
33+
oneOf: false,
34+
preProcessor: true,
35+
exclude: [],
36+
cssLoaderOptions: cssLoaderOptions,
37+
},
38+
options
39+
);
40+
41+
console.log(this.options);
2742
}
2843

2944
/**
3045
* Override the generated webpack configuration.
3146
*
32-
* @param {Object} webpackConfig
33-
* @return {void}
47+
* @param {Object} config
3448
*/
35-
webpackConfig(webpackConfig) {
36-
webpackConfig.module.rules = webpackConfig.module.rules.map((rule) => {
37-
if (!rule.loaders) {
38-
return rule;
39-
}
49+
webpackConfig(config) {
50+
// for css-loader
51+
const cssLoaders = config.module.rules.find(
52+
(rule) => rule.test.toString() === "/\\.css$/"
53+
);
54+
55+
if (this.options.oneOf) this.handleOneOfCss(cssLoaders);
56+
else this.handleCss(cssLoaders);
4057

41-
const sass = rule.loaders.find(
42-
(loader) => loader.loader === "sass-loader"
58+
// only if pre-processor activated || default is active
59+
if (this.options.preProcessor) {
60+
// for sass-loader
61+
const sassLoaders = config.module.rules.find(
62+
(rule) => rule.test.toString() === "/\\.scss$/"
4363
);
44-
const css = rule.loaders.find((loader) => loader.loader === "css-loader");
45-
46-
if (css != undefined) {
47-
if (this.oneOf) {
48-
const postCssConfig = rule.loaders.find(
49-
(loader) => loader.loader === "postcss-loader"
50-
);
51-
52-
delete rule.loaders;
53-
Object.assign(rule, {
54-
test: /\.css$/,
55-
oneOf: [
56-
{
57-
resourceQuery: /module/,
58-
use: [
59-
"style-loader",
60-
{
61-
loader: "css-loader",
62-
options: this[this.mode](),
63-
},
64-
],
65-
},
66-
{
67-
use: ["style-loader", postCssConfig],
68-
},
69-
],
70-
});
71-
} else {
72-
Object.assign(css.options, this[this.mode]());
73-
}
74-
}
7564

76-
if (
77-
this.sass &&
78-
sass != undefined &&
79-
rule.test.toString() === /\.scss$/.toString()
80-
) {
81-
const postCssLoader = rule.loaders.find(
82-
(l) => l.loader === "postcss-loader"
83-
);
84-
const sassLoader = rule.loaders.find((l) => l.loader === "sass-loader");
85-
delete rule.loaders;
86-
87-
Object.assign(rule, {
88-
test: /\.scss$/,
89-
use: [
90-
"style-loader",
91-
{
92-
loader: "css-loader",
93-
options: this[this.mode](),
94-
},
95-
postCssLoader,
96-
sassLoader,
97-
],
65+
if (this.options.oneOf) this.handleOneOfPreProcessor(sassLoaders);
66+
else this.handlePreProcessor(sassLoaders);
67+
}
68+
}
69+
70+
/**
71+
* handle normal css-module
72+
*
73+
* @param {*} cssLoaders
74+
* @returns
75+
* @memberof VueCssModule
76+
*
77+
*/
78+
handleCss(cssLoaders) {
79+
this.handleExclude(cssLoaders);
80+
81+
cssLoaders.loaders.forEach((cssLoader) => {
82+
if (cssLoader.loader === "css-loader") {
83+
Object.assign(cssLoader, {
84+
options: this.options.cssLoaderOptions,
9885
});
9986
}
100-
101-
return rule;
10287
});
10388

104-
return webpackConfig;
89+
return cssLoaders;
10590
}
10691

10792
/**
108-
* Return default mode
93+
* handle oneOf css-module
10994
*
110-
* @return {object}
95+
* @param {*} cssLoaders
96+
* @returns
97+
* @memberof VueCssModule
11198
*/
112-
global() {
113-
return {
114-
modules: true,
115-
localIdentName: this.localIdentName,
116-
};
99+
handleOneOfCss(cssLoaders) {
100+
this.handleExclude(cssLoaders);
101+
102+
// keep default config for postcss-loader
103+
const postCssLoader = cssLoaders.loaders.find(
104+
(cssLoader) => cssLoader.loader === "postcss-loader"
105+
);
106+
107+
// reset loaders change with use
108+
delete cssLoaders.loaders;
109+
110+
cssLoaders.oneOf = [
111+
{
112+
resourceQuery: /module/,
113+
use: [
114+
"style-loader",
115+
{
116+
loader: "css-loader",
117+
options: this.options.cssLoaderOptions,
118+
},
119+
],
120+
},
121+
{
122+
use: ["style-loader", postCssLoader],
123+
},
124+
];
125+
126+
return cssLoaders;
117127
}
118128

119129
/**
120-
* Return local mode
130+
* handle normal css-module for pre-processcor
121131
*
122-
* @return {object}
132+
* @param {*} sassLoaders
133+
* @returns
134+
* @memberof VueCssModule
123135
*/
124-
local() {
125-
return {
126-
modules: {
127-
mode: this.mode,
128-
localIdentName: this.localIdentName,
136+
handlePreProcessor(sassLoaders) {
137+
this.handleExclude(sassLoaders);
138+
139+
const [postCssLoader, sassLoader] = this.getDefaultPreProcessorConfig(
140+
sassLoaders
141+
);
142+
143+
// re-create config & add custom css-loader for .scss
144+
sassLoaders.loaders = [
145+
"style-loader",
146+
{
147+
loader: "css-loader",
148+
options: this.options.cssLoaderOptions,
129149
},
130-
};
150+
postCssLoader,
151+
sassLoader,
152+
];
153+
154+
return sassLoaders;
155+
}
156+
157+
/**
158+
* handle oneOf css-module for pre-processcor
159+
*
160+
* @param {*} sassLoaders
161+
* @returns
162+
* @memberof VueCssModule
163+
*/
164+
handleOneOfPreProcessor(sassLoaders) {
165+
this.handleExclude(sassLoaders);
166+
167+
const [postCssLoader, sassLoader] = this.getDefaultPreProcessorConfig(
168+
sassLoaders
169+
);
170+
171+
delete sassLoaders.loaders;
172+
173+
sassLoaders.oneOf = [
174+
{
175+
resourceQuery: /module/,
176+
use: [
177+
"style-loader",
178+
{
179+
loader: "css-loader",
180+
options: this.options.cssLoaderOptions,
181+
},
182+
],
183+
},
184+
{
185+
use: ["style-loader", "css-loader", postCssLoader, sassLoader],
186+
},
187+
];
188+
189+
return sassLoaders;
190+
}
191+
192+
/**
193+
* get default config from laravel-mix
194+
*
195+
* @param {*} sassLoaders
196+
* @returns
197+
* @memberof VueCssModule
198+
*/
199+
getDefaultPreProcessorConfig(sassLoaders) {
200+
// keep default config for postcss-loader
201+
const postCssLoader = sassLoaders.loaders.find(
202+
(sassLoader) => sassLoader.loader === "postcss-loader"
203+
);
204+
205+
// keep default config for sass-loader
206+
const sassLoader = sassLoaders.loaders.find(
207+
(sassLoader) => sassLoader.loader === "sass-loader"
208+
);
209+
210+
return [postCssLoader, sassLoader];
211+
}
212+
213+
/**
214+
* handle exclude
215+
*
216+
* @param {*} loaders
217+
* @returns
218+
* @memberof VueCssModule
219+
*/
220+
handleExclude(loaders) {
221+
if (this.options.exclude.length > 0) {
222+
if (loaders.exclude === undefined) {
223+
loaders.exclude = this.options.exclude;
224+
} else {
225+
this.options.exclude.forEach((e) => loaders.exclude.push(e));
226+
}
227+
}
228+
229+
return loaders;
230+
}
231+
232+
/**
233+
* get default type for localIdentName
234+
*
235+
* @returns
236+
* @memberof VueCssModule
237+
*/
238+
defaultLocalIdentName(type) {
239+
if (type === "react") {
240+
return this.reactLocalIdentName();
241+
}
242+
243+
if (type === "discord") {
244+
return this.discordLocalIdentName();
245+
}
246+
247+
return Mix.inProduction() ? "[hash:base64]" : "[path][name]__[local]";
248+
}
249+
250+
/**
251+
* Example localIdentName like react
252+
*/
253+
reactLocalIdentName() {
254+
return "[name]___[local]___[hash:base64:5]";
255+
}
256+
257+
/**
258+
* Example localIdentName like discord
259+
*/
260+
discordLocalIdentName() {
261+
return "[local]-[hash:base64:5]";
131262
}
132263
}
133264

134-
mix.extend("vueCssModules", new VueCssModule());
265+
mix.extend("vueCssModules", new VueCssModules());

0 commit comments

Comments
 (0)