Skip to content

Commit 7bbcc81

Browse files
authored
Merge pull request #36 from TeamSupercell/SupportCssLoader4
Add css-loader 4 support
2 parents 7a2b2e1 + aacefb8 commit 7bbcc81

File tree

10 files changed

+566
-173
lines changed

10 files changed

+566
-173
lines changed

.travis.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
language: node_js
2+
23
node_js:
34
- "10"
5+
46
branches:
57
only:
68
- master
9+
10+
jobs:
11+
include:
12+
- install: npm ci
13+
- install: npm install --no-shrinkwrap
14+
15+
before_script:
16+
- npm ls css-loader
17+
- npm ls typescript

package-lock.json

Lines changed: 62 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
},
2828
"devDependencies": {
2929
"@types/jest": "^24.0.23",
30-
"css-loader": "^3.1.0",
30+
"css-loader": "*",
31+
"css-loader3": "npm:css-loader@^3.1.0",
3132
"eslint": "4.18.2",
3233
"eslint-config-prettier": "^6.0.0",
3334
"jest": "^24.9.0",

src/index.js

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const {
33
filenameToPascalCase,
44
filenameToTypingsFilename,
55
getCssModuleKeys,
6-
generateGenericExportInterface
6+
generateGenericExportInterface,
77
} = require("./utils");
88
const persist = require("./persist");
99
const verify = require("./verify");
@@ -16,39 +16,38 @@ const schema = {
1616
eol: {
1717
description:
1818
"Newline character to be used in generated d.ts files. Uses OS default. This option is overridden by the formatter option.",
19-
type: "string"
19+
type: "string",
2020
},
2121
banner: {
2222
description: "To add a 'banner' prefix to each generated `*.d.ts` file",
23-
type: "string"
23+
type: "string",
2424
},
2525
formatter: {
2626
description:
2727
"Possible options: none and prettier (requires prettier package installed). Defaults to prettier if `prettier` module can be resolved",
28-
enum: ["prettier", "none"]
28+
enum: ["prettier", "none"],
2929
},
3030
disableLocalsExport: {
31-
description:
32-
"Disable the use of locals export. Defaults to `false`",
33-
type: "boolean"
31+
description: "Disable the use of locals export. Defaults to `false`",
32+
type: "boolean",
3433
},
3534
verifyOnly: {
3635
description:
3736
"Validate generated `*.d.ts` files and fail if an update is needed (useful in CI). Defaults to `false`",
38-
type: "boolean"
39-
}
37+
type: "boolean",
38+
},
4039
},
41-
additionalProperties: false
40+
additionalProperties: false,
4241
};
4342

4443
/** @type {any} */
4544
const configuration = {
4645
name: "typings-for-css-modules-loader",
47-
baseDataPath: "options"
46+
baseDataPath: "options",
4847
};
4948

5049
/** @type {((this: import('webpack').loader.LoaderContext, ...args: any[]) => void) & {pitch?: import('webpack').loader.Loader['pitch']}} */
51-
module.exports = function(content, ...args) {
50+
module.exports = function (content, ...args) {
5251
const options = getOptions(this) || {};
5352

5453
validateOptions(schema, options, configuration);
@@ -58,9 +57,12 @@ module.exports = function(content, ...args) {
5857
}
5958

6059
// let's only check `exports.locals` for keys to avoid getting keys from the sourcemap when it's enabled
61-
const cssModuleKeys = getCssModuleKeys(
62-
content.substring(content.indexOf("exports.locals"))
63-
);
60+
// if we cannot find locals, then the module only contains global styles
61+
const indexOfLocals = content.indexOf(".locals");
62+
const cssModuleKeys =
63+
indexOfLocals === -1
64+
? []
65+
: getCssModuleKeys(content.substring(indexOfLocals));
6466

6567
/** @type {any} */
6668
const callback = this.async();
@@ -85,14 +87,14 @@ module.exports = function(content, ...args) {
8587
);
8688

8789
applyFormattingAndOptions(cssModuleDefinition, options)
88-
.then(output => {
90+
.then((output) => {
8991
if (options.verifyOnly === true) {
9092
return verify(cssModuleInterfaceFilename, output);
9193
} else {
9294
persist(cssModuleInterfaceFilename, output);
9395
}
9496
})
95-
.catch(err => {
97+
.catch((err) => {
9698
this.emitError(err);
9799
})
98100
.then(successfulCallback);
@@ -132,7 +134,7 @@ async function applyPrettier(input) {
132134
const prettier = require("prettier");
133135

134136
const config = await prettier.resolveConfig("./", {
135-
editorconfig: true
137+
editorconfig: true,
136138
});
137139

138140
return prettier.format(

src/utils.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const camelCase = require("camelcase");
66
* @param {string} content
77
* @returns {string[]}
88
*/
9-
const getCssModuleKeys = content => {
9+
const getCssModuleKeys = (content) => {
1010
const keyRegex = /"([\w-]+)":/g;
1111
let match;
1212
const cssModuleKeys = [];
@@ -22,7 +22,7 @@ const getCssModuleKeys = content => {
2222
/**
2323
* @param {string} filename
2424
*/
25-
const filenameToPascalCase = filename => {
25+
const filenameToPascalCase = (filename) => {
2626
return camelCase(path.basename(filename), { pascalCase: true });
2727
};
2828

@@ -33,11 +33,11 @@ const filenameToPascalCase = filename => {
3333
const cssModuleToTypescriptInterfaceProperties = (cssModuleKeys, indent) => {
3434
return [...cssModuleKeys]
3535
.sort()
36-
.map(key => `${indent || ""}'${key}': string;`)
36+
.map((key) => `${indent || ""}'${key}': string;`)
3737
.join("\n");
3838
};
3939

40-
const filenameToTypingsFilename = filename => {
40+
const filenameToTypingsFilename = (filename) => {
4141
const dirName = path.dirname(filename);
4242
const baseName = path.basename(filename);
4343
return path.join(dirName, `${baseName}.d.ts`);
@@ -47,12 +47,18 @@ const filenameToTypingsFilename = filename => {
4747
* @param {string[]} cssModuleKeys
4848
* @param {string} pascalCaseFileName
4949
*/
50-
const generateGenericExportInterface = (cssModuleKeys, pascalCaseFileName, disableLocalsExport) => {
50+
const generateGenericExportInterface = (
51+
cssModuleKeys,
52+
pascalCaseFileName,
53+
disableLocalsExport
54+
) => {
5155
const interfaceName = `I${pascalCaseFileName}`;
5256
const moduleName = `${pascalCaseFileName}Module`;
5357
const namespaceName = `${pascalCaseFileName}Namespace`;
5458

55-
const localsExportType = disableLocalsExport ? `` : ` & {
59+
const localsExportType = disableLocalsExport
60+
? ``
61+
: ` & {
5662
/** WARNING: Only available when \`css-loader\` is used without \`style-loader\` or \`mini-css-extract-plugin\` */
5763
locals: ${namespaceName}.${interfaceName};
5864
}`;
@@ -76,5 +82,5 @@ module.exports = {
7682
getCssModuleKeys,
7783
filenameToPascalCase,
7884
filenameToTypingsFilename,
79-
generateGenericExportInterface
85+
generateGenericExportInterface,
8086
};

src/verify.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @ts-check
2-
const fs = require('fs');
3-
const util = require('util');
2+
const fs = require("fs");
3+
const util = require("util");
44
const fsStat = util.promisify(fs.stat);
55
const fsReadFile = util.promisify(fs.readFile);
66
/**
@@ -10,18 +10,23 @@ const fsReadFile = util.promisify(fs.readFile);
1010
*/
1111
module.exports = async (filename, content) => {
1212
const fileExists = await fsStat(filename)
13-
.then(() => true).catch(() => false);
13+
.then(() => true)
14+
.catch(() => false);
1415

1516
if (!fileExists) {
16-
throw new Error(`Verification failed: Generated typings for css-module file '${filename}' is not found. ` +
17-
"It typically happens when the generated typings were not committed.");
17+
throw new Error(
18+
`Verification failed: Generated typings for css-module file '${filename}' is not found. ` +
19+
"It typically happens when the generated typings were not committed."
20+
);
1821
}
1922

20-
const existingFileContent = await fsReadFile(filename, 'utf-8');
23+
const existingFileContent = await fsReadFile(filename, "utf-8");
2124

2225
// let's not fail the build if there are whitespace changes only
2326
if (existingFileContent.replace(/\s+/g, "") !== content.replace(/\s+/g, "")) {
24-
throw new Error(`Verification failed: Generated typings for css-modules file '${filename}' is out of date. ` +
25-
"It typically happens when the up-to-date generated typings are not committed.");
27+
throw new Error(
28+
`Verification failed: Generated typings for css-modules file '${filename}' is out of date. ` +
29+
"It typically happens when the up-to-date generated typings are not committed."
30+
);
2631
}
2732
};

0 commit comments

Comments
 (0)