Skip to content

Commit 38951ce

Browse files
committed
add .lazy.css
1 parent 09b69e0 commit 38951ce

File tree

4 files changed

+80
-68
lines changed

4 files changed

+80
-68
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ module.exports = {
4646
| **[`verifyOnly`](#verifyOnly)** | `{Boolean}` | Validate generated `*.d.ts` files and fail if an update is needed (useful in CI) |
4747
| **[`disableLocalsExport`](#disableLocalsExport)** | `{Boolean}` | Disable the use of locals export. |
4848
| **[`prettierConfigFile`](#prettierConfigFile)** | `{String}` | Path to prettier config file |
49-
49+
| **[`lazy`](#lazy)** | `{boolean}` | Emit 'use()' & 'unuse()' for *.lazy.css. Defaults to `true` |
5050
### `banner`
5151

5252
To add a "banner" prefix to each generated `*.d.ts` file, you can pass a string to this option as shown below. The prefix is quite literally prefixed into the generated file, so please ensure it conforms to the type definition syntax.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"name": "@teamsupercell/typings-for-css-modules-loader",
3-
"version": "2.5.1",
2+
"name": "typings-for-lazy-css-modules-loader",
3+
"version": "2.5.5",
44
"description": "Webpack loader that generates TypeScript typings for CSS modules from css-loader on the fly",
55
"main": "src/index.js",
66
"scripts": {
@@ -69,4 +69,4 @@
6969
"after:bump": "npx auto-changelog --commit-limit false https://raw.githubusercontent.com/release-it/release-it/master/templates/keepachangelog.hbs"
7070
}
7171
}
72-
}
72+
}

src/index.js

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ const {
44
filenameToTypingsFilename,
55
getCssModuleKeys,
66
generateGenericExportInterface,
7-
} = require("./utils");
8-
const persist = require("./persist");
9-
const verify = require("./verify");
10-
const { getOptions } = require("loader-utils");
11-
const validateOptions = require("schema-utils");
7+
} = require("./utils")
8+
const persist = require("./persist")
9+
const verify = require("./verify")
10+
const { getOptions } = require("loader-utils")
11+
const validateOptions = require("schema-utils")
1212

1313
const schema = {
1414
type: "object",
@@ -40,70 +40,75 @@ const schema = {
4040
description:
4141
"Path to prettier config file",
4242
type: "string",
43+
},
44+
lazy: {
45+
description: "Emit 'use()' & 'unuse()' for *.lazy.css. Defaults to `true`",
46+
type: "boolean",
4347
}
4448
},
4549
additionalProperties: false,
46-
};
50+
}
4751

4852
/** @type {any} */
4953
const configuration = {
5054
name: "typings-for-css-modules-loader",
5155
baseDataPath: "options",
52-
};
56+
}
5357

5458
/** @type {((this: import('webpack').loader.LoaderContext, ...args: any[]) => void) & {pitch?: import('webpack').loader.Loader['pitch']}} */
5559
module.exports = function (content, ...args) {
56-
const options = getOptions(this) || {};
60+
const options = getOptions(this) || {}
61+
if (typeof options.lazy === 'undefined') options.lazy = true
5762

58-
validateOptions(schema, options, configuration);
63+
validateOptions(schema, options, configuration)
5964

6065
if (this.cacheable) {
61-
this.cacheable();
66+
this.cacheable()
6267
}
6368

6469
// let's only check `exports.locals` for keys to avoid getting keys from the sourcemap when it's enabled
6570
// if we cannot find locals, then the module only contains global styles
66-
const indexOfLocals = content.indexOf(".locals");
71+
const indexOfLocals = content.indexOf(".locals")
6772
const cssModuleKeys =
6873
indexOfLocals === -1
6974
? []
70-
: getCssModuleKeys(content.substring(indexOfLocals));
75+
: getCssModuleKeys(content.substring(indexOfLocals))
7176

7277
/** @type {any} */
73-
const callback = this.async();
78+
const callback = this.async()
7479

7580
const successfulCallback = () => {
76-
callback(null, content, ...args);
77-
};
81+
callback(null, content, ...args)
82+
}
7883

7984
if (cssModuleKeys.length === 0) {
8085
// no css module output found
81-
successfulCallback();
82-
return;
86+
successfulCallback()
87+
return
8388
}
8489

85-
const filename = this.resourcePath;
90+
const filename = this.resourcePath
8691

87-
const cssModuleInterfaceFilename = filenameToTypingsFilename(filename);
92+
const cssModuleInterfaceFilename = filenameToTypingsFilename(filename)
8893
const cssModuleDefinition = generateGenericExportInterface(
8994
cssModuleKeys,
9095
filenameToPascalCase(filename),
9196
options.disableLocalsExport
92-
);
97+
)
9398

9499
applyFormattingAndOptions(cssModuleDefinition, options)
95100
.then((output) => {
96101
if (options.verifyOnly === true) {
97-
return verify(cssModuleInterfaceFilename, output);
102+
return verify(cssModuleInterfaceFilename, output)
98103
} else {
99-
persist(cssModuleInterfaceFilename, output);
104+
persist(cssModuleInterfaceFilename, output)
100105
}
101106
})
102107
.catch((err) => {
103-
this.emitError(err);
108+
this.emitError(err)
104109
})
105-
.then(successfulCallback);
106-
};
110+
.then(successfulCallback)
111+
}
107112

108113
/**
109114
* @param {string} cssModuleDefinition
@@ -112,23 +117,23 @@ module.exports = function (content, ...args) {
112117
async function applyFormattingAndOptions(cssModuleDefinition, options) {
113118
if (options.banner) {
114119
// Prefix banner to CSS module
115-
cssModuleDefinition = options.banner + "\n" + cssModuleDefinition;
120+
cssModuleDefinition = options.banner + "\n" + cssModuleDefinition
116121
}
117122

118123
if (
119124
options.formatter === "prettier" ||
120125
(!options.formatter && canUsePrettier())
121126
) {
122-
cssModuleDefinition = await applyPrettier(cssModuleDefinition, options);
127+
cssModuleDefinition = await applyPrettier(cssModuleDefinition, options)
123128
} else {
124129
// at very least let's ensure we're using OS eol if it's not provided
125130
cssModuleDefinition = cssModuleDefinition.replace(
126131
/\r?\n/g,
127132
options.eol || require("os").EOL
128-
);
133+
)
129134
}
130135

131-
return cssModuleDefinition;
136+
return cssModuleDefinition
132137
}
133138

134139
/**
@@ -137,32 +142,32 @@ async function applyFormattingAndOptions(cssModuleDefinition, options) {
137142
* @returns {Promise<string>}
138143
*/
139144
async function applyPrettier(input, options) {
140-
const prettier = require("prettier");
145+
const prettier = require("prettier")
141146

142-
const configPath = options.prettierConfigFile ? options.prettierConfigFile : "./";
143-
const config = await prettier.resolveConfig(configPath, {
147+
const configPath = options.prettierConfigFile ? options.prettierConfigFile : "./"
148+
const config = await prettier.resolveConfig(configPath, {
144149
editorconfig: true,
145-
});
150+
})
146151

147152
return prettier.format(
148153
input,
149154
Object.assign({}, config, { parser: "typescript" })
150-
);
155+
)
151156
}
152157

153-
let isPrettierInstalled;
158+
let isPrettierInstalled
154159
/**
155160
* @returns {boolean}
156161
*/
157162
function canUsePrettier() {
158163
if (typeof isPrettierInstalled !== "boolean") {
159164
try {
160-
require.resolve("prettier");
161-
isPrettierInstalled = true;
165+
require.resolve("prettier")
166+
isPrettierInstalled = true
162167
} catch (_) {
163-
isPrettierInstalled = false;
168+
isPrettierInstalled = false
164169
}
165170
}
166171

167-
return isPrettierInstalled;
172+
return isPrettierInstalled
168173
}

src/utils.js

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
// @ts-check
2-
const path = require("path");
3-
const camelCase = require("camelcase");
2+
const path = require("path")
3+
const camelCase = require("camelcase")
44

55
/**
66
* @param {string} content
77
* @returns {string[]}
88
*/
99
const getCssModuleKeys = (content) => {
10-
const keyRegex = /"([^"\n]+)":/g;
11-
let match;
12-
const cssModuleKeys = [];
10+
const keyRegex = /"([^"\n]+)":/g
11+
let match
12+
const cssModuleKeys = []
1313

1414
while ((match = keyRegex.exec(content))) {
1515
if (cssModuleKeys.indexOf(match[1]) < 0) {
16-
cssModuleKeys.push(match[1]);
16+
cssModuleKeys.push(match[1])
1717
}
1818
}
19-
return cssModuleKeys;
20-
};
19+
return cssModuleKeys
20+
}
2121

2222
/**
2323
* @param {string} filename
2424
*/
2525
const filenameToPascalCase = (filename) => {
26-
return camelCase(path.basename(filename), { pascalCase: true });
27-
};
26+
return camelCase(path.basename(filename), { pascalCase: true })
27+
}
2828

2929
/**
3030
* @param {string[]} cssModuleKeys
@@ -34,14 +34,14 @@ const cssModuleToTypescriptInterfaceProperties = (cssModuleKeys, indent) => {
3434
return [...cssModuleKeys]
3535
.sort()
3636
.map((key) => `${indent || ""}'${key}': string;`)
37-
.join("\n");
38-
};
37+
.join("\n")
38+
}
3939

4040
const filenameToTypingsFilename = (filename) => {
41-
const dirName = path.dirname(filename);
42-
const baseName = path.basename(filename);
43-
return path.join(dirName, `${baseName}.d.ts`);
44-
};
41+
const dirName = path.dirname(filename)
42+
const baseName = path.basename(filename)
43+
return path.join(dirName, `${baseName}.d.ts`)
44+
}
4545

4646
/**
4747
* @param {string[]} cssModuleKeys
@@ -50,37 +50,44 @@ const filenameToTypingsFilename = (filename) => {
5050
const generateGenericExportInterface = (
5151
cssModuleKeys,
5252
pascalCaseFileName,
53-
disableLocalsExport
53+
disableLocalsExport,
54+
lazy = false
5455
) => {
55-
const interfaceName = `I${pascalCaseFileName}`;
56-
const moduleName = `${pascalCaseFileName}Module`;
57-
const namespaceName = `${pascalCaseFileName}Namespace`;
56+
const interfaceName = `I${pascalCaseFileName}`
57+
const moduleName = `${pascalCaseFileName}Module`
58+
const namespaceName = `${pascalCaseFileName}Namespace`
5859

5960
const localsExportType = disableLocalsExport
6061
? ``
6162
: ` & {
6263
/** WARNING: Only available when \`css-loader\` is used without \`style-loader\` or \`mini-css-extract-plugin\` */
6364
locals: ${namespaceName}.${interfaceName};
64-
}`;
65+
}`
6566

6667
const interfaceProperties = cssModuleToTypescriptInterfaceProperties(
6768
cssModuleKeys,
6869
" "
69-
);
70+
)
71+
const lz = lazy ? `
72+
use: () => void;
73+
unuse: () => void;
74+
`: ``
75+
7076
return `declare namespace ${namespaceName} {
7177
export interface I${pascalCaseFileName} {
7278
${interfaceProperties}
79+
${lz}
7380
}
7481
}
7582
7683
declare const ${moduleName}: ${namespaceName}.${interfaceName}${localsExportType};
7784
78-
export = ${moduleName};`;
79-
};
85+
export = ${moduleName};`
86+
}
8087

8188
module.exports = {
8289
getCssModuleKeys,
8390
filenameToPascalCase,
8491
filenameToTypingsFilename,
8592
generateGenericExportInterface,
86-
};
93+
}

0 commit comments

Comments
 (0)