Skip to content

Commit 940d652

Browse files
authored
Merge pull request #24 from raphael-leger/feat/option-to-disable-locals-generation
feat: add an option to disable locals export
2 parents a8fe7ee + daccbec commit 940d652

File tree

5 files changed

+96
-31
lines changed

5 files changed

+96
-31
lines changed

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ module.exports = {
4444
| **[`formatter`](#formatter)** | `{String}` | Formats the generated `*.d.ts` file with specified formatter, eg. `prettier` |
4545
| **[`eol`](#eol)** | `{String}` | Newline character to be used in generated `*.d.ts` files |
4646
| **[`verifyOnly`](#verifyOnly)** | `{Boolean}` | Validate generated `*.d.ts` files and fail if an update is needed (useful in CI) |
47+
| **[`disableLocalsExport`](#disableLocalsExport)** | `{Boolean}` | Disable the use of locals export. |
4748

4849
### `banner`
4950

@@ -159,6 +160,35 @@ module.exports = {
159160
};
160161
```
161162

163+
### `disableLocalsExport`
164+
165+
Disable the use of locals export. Defaults to `false`.
166+
167+
```js
168+
module.exports = {
169+
module: {
170+
rules: [
171+
{
172+
test: /\.css$/i,
173+
use: [
174+
{
175+
loader: "@teamsupercell/typings-for-css-modules-loader",
176+
options: {
177+
disableLocalsExport: true
178+
}
179+
},
180+
{
181+
loader: "css-loader",
182+
options: { modules: true }
183+
}
184+
]
185+
}
186+
]
187+
}
188+
};
189+
```
190+
191+
162192
## Example
163193

164194
Imagine you have a file `~/my-project/src/component/MyComponent/myComponent.scss` in your project with the following content:

src/index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ const schema = {
2727
"Possible options: none and prettier (requires prettier package installed). Defaults to prettier if `prettier` module can be resolved",
2828
enum: ["prettier", "none"]
2929
},
30+
disableLocalsExport: {
31+
description:
32+
"Disable the use of locals export. Defaults to `false`",
33+
type: "boolean"
34+
},
3035
verifyOnly: {
3136
description:
3237
"Validate generated `*.d.ts` files and fail if an update is needed (useful in CI). Defaults to `false`",
@@ -75,7 +80,8 @@ module.exports = function(content, ...args) {
7580
const cssModuleInterfaceFilename = filenameToTypingsFilename(filename);
7681
const cssModuleDefinition = generateGenericExportInterface(
7782
cssModuleKeys,
78-
filenameToPascalCase(filename)
83+
filenameToPascalCase(filename),
84+
options.disableLocalsExport
7985
);
8086

8187
applyFormattingAndOptions(cssModuleDefinition, options)

src/utils.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,16 @@ const filenameToTypingsFilename = filename => {
4747
* @param {string[]} cssModuleKeys
4848
* @param {string} pascalCaseFileName
4949
*/
50-
const generateGenericExportInterface = (cssModuleKeys, pascalCaseFileName) => {
50+
const generateGenericExportInterface = (cssModuleKeys, pascalCaseFileName, disableLocalsExport) => {
5151
const interfaceName = `I${pascalCaseFileName}`;
5252
const moduleName = `${pascalCaseFileName}Module`;
5353
const namespaceName = `${pascalCaseFileName}Namespace`;
5454

55+
const localsExportType = disableLocalsExport ? `` : ` & {
56+
/** WARNING: Only available when \`css-loader\` is used without \`style-loader\` or \`mini-css-extract-plugin\` */
57+
locals: ${namespaceName}.${interfaceName};
58+
}`;
59+
5560
const interfaceProperties = cssModuleToTypescriptInterfaceProperties(
5661
cssModuleKeys,
5762
" "
@@ -62,10 +67,7 @@ ${interfaceProperties}
6267
}
6368
}
6469
65-
declare const ${moduleName}: ${namespaceName}.${interfaceName} & {
66-
/** WARNING: Only available when \`css-loader\` is used without \`style-loader\` or \`mini-css-extract-plugin\` */
67-
locals: ${namespaceName}.${interfaceName};
68-
};
70+
declare const ${moduleName}: ${namespaceName}.${interfaceName}${localsExportType};
6971
7072
export = ${moduleName};`;
7173
};

test/__snapshots__/index.test.js.snap

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,21 @@ export = ExampleCssModule;
7474
"
7575
`;
7676

77+
exports[`with locals export disabled 1`] = `
78+
"declare namespace ExampleCssNamespace {
79+
export interface IExampleCss {
80+
\\"bar-baz\\": string;
81+
composed: string;
82+
foo: string;
83+
}
84+
}
85+
86+
declare const ExampleCssModule: ExampleCssNamespace.IExampleCss;
87+
88+
export = ExampleCssModule;
89+
"
90+
`;
91+
7792
exports[`with no formatter 1`] = `
7893
"declare namespace ExampleCssNamespace {
7994
export interface IExampleCss {

test/index.test.js

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ beforeEach(() => {
1212
it("default options", async () => {
1313
await runTest();
1414

15-
const persisteMock = jest.requireMock("../src/persist");
16-
expect(persisteMock).toBeCalledTimes(1);
17-
expect(persisteMock.mock.calls[0][1]).toMatchSnapshot();
15+
const persistMock = jest.requireMock("../src/persist");
16+
expect(persistMock).toBeCalledTimes(1);
17+
expect(persistMock.mock.calls[0][1]).toMatchSnapshot();
1818

1919
const verifyMock = jest.requireMock("../src/verify");
2020
expect(verifyMock).toBeCalledTimes(0);
@@ -27,9 +27,9 @@ it("with sourcemap", async () => {
2727
}
2828
});
2929

30-
const persisteMock = jest.requireMock("../src/persist");
31-
expect(persisteMock).toBeCalledTimes(1);
32-
expect(persisteMock.mock.calls[0][1]).toMatchSnapshot();
30+
const persistMock = jest.requireMock("../src/persist");
31+
expect(persistMock).toBeCalledTimes(1);
32+
expect(persistMock.mock.calls[0][1]).toMatchSnapshot();
3333
});
3434

3535
it("no modules", async () => {
@@ -39,8 +39,8 @@ it("no modules", async () => {
3939
}
4040
});
4141

42-
const persisteMock = jest.requireMock("../src/persist");
43-
expect(persisteMock).toBeCalledTimes(0);
42+
const persistMock = jest.requireMock("../src/persist");
43+
expect(persistMock).toBeCalledTimes(0);
4444
});
4545

4646
it("localsConvention asIs", async () => {
@@ -50,9 +50,9 @@ it("localsConvention asIs", async () => {
5050
}
5151
});
5252

53-
const persisteMock = jest.requireMock("../src/persist");
54-
expect(persisteMock).toBeCalledTimes(1);
55-
expect(persisteMock.mock.calls[0][1]).toMatchSnapshot();
53+
const persistMock = jest.requireMock("../src/persist");
54+
expect(persistMock).toBeCalledTimes(1);
55+
expect(persistMock.mock.calls[0][1]).toMatchSnapshot();
5656
});
5757

5858
it("localsConvention camelCase", async () => {
@@ -62,9 +62,9 @@ it("localsConvention camelCase", async () => {
6262
}
6363
});
6464

65-
const persisteMock = jest.requireMock("../src/persist");
66-
expect(persisteMock).toBeCalledTimes(1);
67-
expect(persisteMock.mock.calls[0][1]).toMatchSnapshot();
65+
const persistMock = jest.requireMock("../src/persist");
66+
expect(persistMock).toBeCalledTimes(1);
67+
expect(persistMock.mock.calls[0][1]).toMatchSnapshot();
6868
});
6969

7070
it("with prettier", async () => {
@@ -74,9 +74,9 @@ it("with prettier", async () => {
7474
}
7575
});
7676

77-
const persisteMock = jest.requireMock("../src/persist");
78-
expect(persisteMock).toBeCalledTimes(1);
79-
expect(persisteMock.mock.calls[0][1]).toMatchSnapshot();
77+
const persistMock = jest.requireMock("../src/persist");
78+
expect(persistMock).toBeCalledTimes(1);
79+
expect(persistMock.mock.calls[0][1]).toMatchSnapshot();
8080
});
8181

8282
it("with no formatter", async () => {
@@ -86,9 +86,9 @@ it("with no formatter", async () => {
8686
}
8787
});
8888

89-
const persisteMock = jest.requireMock("../src/persist");
90-
expect(persisteMock).toBeCalledTimes(1);
91-
expect(persisteMock.mock.calls[0][1]).toMatchSnapshot();
89+
const persistMock = jest.requireMock("../src/persist");
90+
expect(persistMock).toBeCalledTimes(1);
91+
expect(persistMock.mock.calls[0][1]).toMatchSnapshot();
9292
});
9393

9494
it("with banner", async () => {
@@ -98,9 +98,21 @@ it("with banner", async () => {
9898
}
9999
});
100100

101-
const persisteMock = jest.requireMock("../src/persist");
102-
expect(persisteMock).toBeCalledTimes(1);
103-
expect(persisteMock.mock.calls[0][1]).toMatchSnapshot();
101+
const persistMock = jest.requireMock("../src/persist");
102+
expect(persistMock).toBeCalledTimes(1);
103+
expect(persistMock.mock.calls[0][1]).toMatchSnapshot();
104+
});
105+
106+
it("with locals export disabled", async () => {
107+
await runTest({
108+
options: {
109+
disableLocalsExport: true
110+
}
111+
});
112+
113+
const persistMock = jest.requireMock("../src/persist");
114+
expect(persistMock).toBeCalledTimes(1);
115+
expect(persistMock.mock.calls[0][1]).toMatchSnapshot();
104116
});
105117

106118
it("with verify only", async () => {
@@ -110,8 +122,8 @@ it("with verify only", async () => {
110122
}
111123
});
112124

113-
const persisteMock = jest.requireMock("../src/persist");
114-
expect(persisteMock).toBeCalledTimes(0);
125+
const persistMock = jest.requireMock("../src/persist");
126+
expect(persistMock).toBeCalledTimes(0);
115127

116128
const verifyMock = jest.requireMock("../src/verify");
117129
expect(verifyMock).toBeCalledTimes(1);

0 commit comments

Comments
 (0)