Skip to content

Commit 8235a81

Browse files
committed
#8 Fix typings to allow wildcard exports
1 parent 6b2f4ab commit 8235a81

File tree

4 files changed

+121
-68
lines changed

4 files changed

+121
-68
lines changed

src/index.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// @ts-check
22
const {
3-
filenameToInterfaceName,
3+
filenameToPascalCase,
44
filenameToTypingsFilename,
55
getCssModuleKeys,
66
generateGenericExportInterface
@@ -67,10 +67,9 @@ module.exports = function(content, ...args) {
6767
const filename = this.resourcePath;
6868

6969
const cssModuleInterfaceFilename = filenameToTypingsFilename(filename);
70-
const interfaceName = filenameToInterfaceName(filename);
7170
const cssModuleDefinition = generateGenericExportInterface(
7271
cssModuleKeys,
73-
interfaceName
72+
filenameToPascalCase(filename)
7473
);
7574

7675
applyFormattingAndOptions(cssModuleDefinition, options)

src/utils.js

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,18 @@ const getCssModuleKeys = content => {
2222
/**
2323
* @param {string} filename
2424
*/
25-
const filenameToInterfaceName = filename => {
26-
return "I" + camelCase(path.basename(filename), { pascalCase: true });
25+
const filenameToPascalCase = filename => {
26+
return camelCase(path.basename(filename), { pascalCase: true });
2727
};
2828

2929
/**
3030
* @param {string[]} cssModuleKeys
31+
* @param {string=} indent
3132
*/
32-
const cssModuleToTypescriptInterfaceProperties = cssModuleKeys => {
33+
const cssModuleToTypescriptInterfaceProperties = (cssModuleKeys, indent) => {
3334
return [...cssModuleKeys]
3435
.sort()
35-
.map(key => ` '${key}': string;`)
36+
.map(key => `${indent || ""}'${key}': string;`)
3637
.join("\n");
3738
};
3839

@@ -44,23 +45,33 @@ const filenameToTypingsFilename = filename => {
4445

4546
/**
4647
* @param {string[]} cssModuleKeys
47-
* @param {string} interfaceName
48+
* @param {string} pascalCaseFileName
4849
*/
49-
const generateGenericExportInterface = (cssModuleKeys, interfaceName) => {
50+
const generateGenericExportInterface = (cssModuleKeys, pascalCaseFileName) => {
51+
const interfaceName = `I${pascalCaseFileName}`;
52+
const moduleName = `${pascalCaseFileName}Module`;
53+
5054
const interfaceProperties = cssModuleToTypescriptInterfaceProperties(
51-
cssModuleKeys
55+
cssModuleKeys,
56+
" "
5257
);
53-
return `export interface ${interfaceName} {
58+
return `declare namespace ${moduleName} {
59+
export interface I${pascalCaseFileName} {
5460
${interfaceProperties}
61+
}
5562
}
5663
57-
export const locals: ${interfaceName};
58-
export default locals;`;
64+
declare const ${moduleName}: ${moduleName}.${interfaceName} & {
65+
/** WARNING: Only available when \`css-loader\` is used without \`style-loader\` or \`mini-css-extract-plugin\` */
66+
locals: ${moduleName}.${interfaceName};
67+
};
68+
69+
export = ${moduleName};`;
5970
};
6071

6172
module.exports = {
6273
getCssModuleKeys,
63-
filenameToInterfaceName,
74+
filenameToPascalCase,
6475
filenameToTypingsFilename,
6576
generateGenericExportInterface
6677
};

test/__snapshots__/index.test.js.snap

Lines changed: 85 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,128 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

33
exports[`default options 1`] = `
4-
"export interface IExampleCss {
5-
\\"bar-baz\\": string;
6-
composed: string;
7-
foo: string;
4+
"declare namespace ExampleCssModule {
5+
export interface IExampleCss {
6+
\\"bar-baz\\": string;
7+
composed: string;
8+
foo: string;
9+
}
810
}
911
10-
export const locals: IExampleCss;
11-
export default locals;
12+
declare const ExampleCssModule: ExampleCssModule.IExampleCss & {
13+
/** WARNING: Only available when \`css-loader\` is used without \`style-loader\` or \`mini-css-extract-plugin\` */
14+
locals: ExampleCssModule.IExampleCss;
15+
};
16+
17+
export = ExampleCssModule;
1218
"
1319
`;
1420

1521
exports[`localsConvention asIs 1`] = `
16-
"export interface IExampleCss {
17-
\\"bar-baz\\": string;
18-
composed: string;
19-
foo: string;
22+
"declare namespace ExampleCssModule {
23+
export interface IExampleCss {
24+
\\"bar-baz\\": string;
25+
composed: string;
26+
foo: string;
27+
}
2028
}
2129
22-
export const locals: IExampleCss;
23-
export default locals;
30+
declare const ExampleCssModule: ExampleCssModule.IExampleCss & {
31+
/** WARNING: Only available when \`css-loader\` is used without \`style-loader\` or \`mini-css-extract-plugin\` */
32+
locals: ExampleCssModule.IExampleCss;
33+
};
34+
35+
export = ExampleCssModule;
2436
"
2537
`;
2638

2739
exports[`localsConvention camelCase 1`] = `
28-
"export interface IExampleCss {
29-
\\"bar-baz\\": string;
30-
barBaz: string;
31-
composed: string;
32-
foo: string;
40+
"declare namespace ExampleCssModule {
41+
export interface IExampleCss {
42+
\\"bar-baz\\": string;
43+
barBaz: string;
44+
composed: string;
45+
foo: string;
46+
}
3347
}
3448
35-
export const locals: IExampleCss;
36-
export default locals;
49+
declare const ExampleCssModule: ExampleCssModule.IExampleCss & {
50+
/** WARNING: Only available when \`css-loader\` is used without \`style-loader\` or \`mini-css-extract-plugin\` */
51+
locals: ExampleCssModule.IExampleCss;
52+
};
53+
54+
export = ExampleCssModule;
3755
"
3856
`;
3957

4058
exports[`with banner 1`] = `
4159
"// autogenerated by typings-for-css-modules-loader
42-
export interface IExampleCss {
43-
\\"bar-baz\\": string;
44-
composed: string;
45-
foo: string;
60+
declare namespace ExampleCssModule {
61+
export interface IExampleCss {
62+
\\"bar-baz\\": string;
63+
composed: string;
64+
foo: string;
65+
}
4666
}
4767
48-
export const locals: IExampleCss;
49-
export default locals;
68+
declare const ExampleCssModule: ExampleCssModule.IExampleCss & {
69+
/** WARNING: Only available when \`css-loader\` is used without \`style-loader\` or \`mini-css-extract-plugin\` */
70+
locals: ExampleCssModule.IExampleCss;
71+
};
72+
73+
export = ExampleCssModule;
5074
"
5175
`;
5276

5377
exports[`with no formatter 1`] = `
54-
"export interface IExampleCss {
55-
'bar-baz': string;
56-
'composed': string;
57-
'foo': string;
78+
"declare namespace ExampleCssModule {
79+
export interface IExampleCss {
80+
'bar-baz': string;
81+
'composed': string;
82+
'foo': string;
83+
}
5884
}
5985
60-
export const locals: IExampleCss;
61-
export default locals;"
86+
declare const ExampleCssModule: ExampleCssModule.IExampleCss & {
87+
/** WARNING: Only available when \`css-loader\` is used without \`style-loader\` or \`mini-css-extract-plugin\` */
88+
locals: ExampleCssModule.IExampleCss;
89+
};
90+
91+
export = ExampleCssModule;"
6292
`;
6393

6494
exports[`with prettier 1`] = `
65-
"export interface IExampleCss {
66-
\\"bar-baz\\": string;
67-
composed: string;
68-
foo: string;
95+
"declare namespace ExampleCssModule {
96+
export interface IExampleCss {
97+
\\"bar-baz\\": string;
98+
composed: string;
99+
foo: string;
100+
}
69101
}
70102
71-
export const locals: IExampleCss;
72-
export default locals;
103+
declare const ExampleCssModule: ExampleCssModule.IExampleCss & {
104+
/** WARNING: Only available when \`css-loader\` is used without \`style-loader\` or \`mini-css-extract-plugin\` */
105+
locals: ExampleCssModule.IExampleCss;
106+
};
107+
108+
export = ExampleCssModule;
73109
"
74110
`;
75111

76112
exports[`with sourcemap 1`] = `
77-
"export interface IExampleCss {
78-
\\"bar-baz\\": string;
79-
composed: string;
80-
foo: string;
113+
"declare namespace ExampleCssModule {
114+
export interface IExampleCss {
115+
\\"bar-baz\\": string;
116+
composed: string;
117+
foo: string;
118+
}
81119
}
82120
83-
export const locals: IExampleCss;
84-
export default locals;
121+
declare const ExampleCssModule: ExampleCssModule.IExampleCss & {
122+
/** WARNING: Only available when \`css-loader\` is used without \`style-loader\` or \`mini-css-extract-plugin\` */
123+
locals: ExampleCssModule.IExampleCss;
124+
};
125+
126+
export = ExampleCssModule;
85127
"
86128
`;

test/utils.test.js

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
1-
const { filenameToInterfaceName } = require("../src/utils");
1+
// @ts-check
2+
const { filenameToPascalCase } = require("../src/utils");
23

3-
describe("filenameToInterfaceName", () => {
4+
describe("filenameToPascalCase", () => {
45
it("camelCase", () => {
5-
const actual = filenameToInterfaceName("reactDatePicker");
6-
expect(actual).toBe("IReactDatePicker");
6+
const actual = filenameToPascalCase("reactDatePicker");
7+
expect(actual).toBe("ReactDatePicker");
78
});
89

910
it("PascalCase", () => {
10-
const actual = filenameToInterfaceName("reactDatePicker");
11-
expect(actual).toBe("IReactDatePicker");
11+
const actual = filenameToPascalCase("reactDatePicker");
12+
expect(actual).toBe("ReactDatePicker");
1213
});
1314

1415
it("snake_case", () => {
15-
const actual = filenameToInterfaceName("_React_date_picker");
16-
expect(actual).toBe("IReactDatePicker");
16+
const actual = filenameToPascalCase("_React_date_picker");
17+
expect(actual).toBe("ReactDatePicker");
1718
});
18-
19+
1920
it("_mixed-case", () => {
20-
const actual = filenameToInterfaceName("_React-date_picker");
21-
expect(actual).toBe("IReactDatePicker");
21+
const actual = filenameToPascalCase("_React-date_picker");
22+
expect(actual).toBe("ReactDatePicker");
2223
});
2324
});

0 commit comments

Comments
 (0)