Skip to content

Commit 936e41b

Browse files
committed
feat: add singleQuote option to allow custom style for keys with dashes
1 parent 39188ad commit 936e41b

9 files changed

+48
-30
lines changed

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ export = styles;
117117

118118
See also [webpack css-loader's camelCase option](https://github.com/webpack/css-loader#camelcase).
119119

120+
#### Use single quotes to class names in the .d.ts files
121+
122+
With `-sq` or `--singleQuote`, you can configure what quote to use. Useful when tools like prettier format your .d.ts files.
123+
120124
#### named exports (enable tree shaking)
121125

122126
With `-e` or `--namedExports`, types are exported as named exports as opposed to default exports.
@@ -183,6 +187,7 @@ You can set the following options:
183187
- `option.searchDir`: Directory which includes target `*.css` files(default: `'./'`).
184188
- `option.outDir`: Output directory(default: `option.searchDir`).
185189
- `option.camelCase`: Camelize CSS class tokens.
190+
- `option.singleQuote`: Use single quotes on dashed keys.
186191
- `option.namedExports`: Use named exports as opposed to default exports to enable tree shaking. Requires `import * as style from './file.module.css';` (default: `false`)
187192
- `option.allowArbitraryExtensions`: Output filenames that will be compatible with the "arbitrary file extensions" TypeScript feature
188193
- `option.EOL`: EOL (end of line) for the generated `d.ts` files. Possible values `'\n'` or `'\r\n'`(default: `os.EOL`).

fixtures/kebabed.css

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
.my-class {
22
color: red;
33
}
4-

fixtures/testStyle.css.d.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
declare const styles: {
2-
readonly "myClass": string;
2+
readonly myClass: string;
33
};
44
export = styles;
5-

src/cli.ts

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ const yarg = yargs(hideBin(process.argv))
3737
type: 'boolean',
3838
alias: 'camelCase',
3939
},
40+
sq: {
41+
desc: 'Use single quotes for writing the keys when they have a dash',
42+
type: 'boolean',
43+
alias: 'singleQuote',
44+
},
4045
e: {
4146
type: 'boolean',
4247
desc: 'Use named exports as opposed to default exports to enable tree shaking.',
@@ -87,6 +92,7 @@ async function main(): Promise<void> {
8792
outDir: argv.o,
8893
watch: argv.w,
8994
camelCase: argv.c,
95+
singleQuote: argv.sq,
9096
namedExports: argv.e,
9197
dropExtension: argv.d,
9298
allowArbitraryExtensions: argv.a,

src/dts-content.test.ts

+4-10
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,9 @@ describe('DtsContent', () => {
7373
content.formatted,
7474
`\
7575
declare const styles: {
76-
readonly "myClass": string;
76+
readonly myClass: string;
7777
};
7878
export = styles;
79-
8079
`,
8180
);
8281
});
@@ -88,7 +87,6 @@ export = styles;
8887
`\
8988
export const __esModule: true;
9089
export const myClass: string;
91-
9290
`,
9391
);
9492
});
@@ -100,7 +98,6 @@ export const myClass: string;
10098
`\
10199
export const __esModule: true;
102100
export const myClass: string;
103-
104101
`,
105102
);
106103
});
@@ -117,10 +114,9 @@ export const myClass: string;
117114
content.formatted,
118115
`\
119116
declare const styles: {
120-
readonly "myClass": string;
117+
readonly myClass: string;
121118
};
122119
export = styles;
123-
124120
`,
125121
);
126122
});
@@ -131,10 +127,9 @@ export = styles;
131127
content.formatted,
132128
`\
133129
declare const styles: {
134-
readonly "myClass": string;
130+
readonly myClass: string;
135131
};
136132
export = styles;
137-
138133
`,
139134
);
140135
});
@@ -147,10 +142,9 @@ export = styles;
147142
content.formatted,
148143
`\
149144
declare const styles: {
150-
readonly "MyClass": string;
145+
readonly MyClass: string;
151146
};
152147
export = styles;
153-
154148
`,
155149
);
156150
});

src/dts-content.ts

+19-10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ interface DtsContentOptions {
1818
namedExports: boolean;
1919
allowArbitraryExtensions: boolean;
2020
camelCase: CamelCaseOption;
21+
singleQuote?: boolean;
2122
EOL: string;
2223
}
2324

@@ -31,6 +32,7 @@ export class DtsContent {
3132
private namedExports: boolean;
3233
private allowArbitraryExtensions: boolean;
3334
private camelCase: CamelCaseOption;
35+
private quote: '"' | "'";
3436
private resultList: string[];
3537
private EOL: string;
3638

@@ -44,6 +46,7 @@ export class DtsContent {
4446
this.namedExports = options.namedExports;
4547
this.allowArbitraryExtensions = options.allowArbitraryExtensions;
4648
this.camelCase = options.camelCase;
49+
this.quote = options.singleQuote ? "'" : '"';
4750
this.EOL = options.EOL;
4851

4952
// when using named exports, camelCase must be enabled by default
@@ -65,17 +68,18 @@ export class DtsContent {
6568
if (!this.resultList || !this.resultList.length) return 'export {};';
6669

6770
if (this.namedExports) {
68-
return (
69-
['export const __esModule: true;', ...this.resultList.map(line => 'export ' + line), ''].join(this.EOL) +
70-
this.EOL
71-
);
71+
return ['export const __esModule: true;', ...this.resultList.map(line => 'export ' + line), ''].join(this.EOL);
7272
}
7373

74-
return (
75-
['declare const styles: {', ...this.resultList.map(line => ' ' + line), '};', 'export = styles;', ''].join(
76-
this.EOL,
77-
) + this.EOL
78-
);
74+
const data = [
75+
'declare const styles: {',
76+
...this.resultList.map(line => ' ' + line),
77+
'};',
78+
'export = styles;',
79+
'',
80+
].join(this.EOL);
81+
82+
return data;
7983
}
8084

8185
public get tokens(): string[] {
@@ -149,10 +153,15 @@ export class DtsContent {
149153

150154
private createResultList(): string[] {
151155
const convertKey = this.getConvertKeyMethod(this.camelCase);
156+
const quote = this.camelCase ? '' : this.quote;
152157

153158
const result = this.rawTokenList
154159
.map(k => convertKey(k))
155-
.map(k => (!this.namedExports ? 'readonly "' + k + '": string;' : 'const ' + k + ': string;'))
160+
.map(k => {
161+
const q = k.includes('-') ? quote : '';
162+
163+
return !this.namedExports ? `readonly ${q}${k}${q}: string;` : 'const ' + k + ': string;';
164+
})
156165
.sort();
157166

158167
return result;

src/dts-creator.test.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ describe(DtsCreator, () => {
88
it('returns DtsContent instance simple css', async () => {
99
const content = await new DtsCreator().create('fixtures/testStyle.css');
1010
assert.equal(content.contents.length, 1);
11-
assert.equal(content.contents[0], 'readonly "myClass": string;');
11+
assert.equal(content.contents[0], 'readonly myClass: string;');
1212
});
1313

1414
it('rejects an error with invalid CSS', async () => {
@@ -20,27 +20,27 @@ describe(DtsCreator, () => {
2020
it('returns DtsContent instance from composing css', async () => {
2121
const content = await new DtsCreator().create('fixtures/composer.css');
2222
assert.equal(content.contents.length, 1);
23-
assert.equal(content.contents[0], 'readonly "root": string;');
23+
assert.equal(content.contents[0], 'readonly root: string;');
2424
});
2525

2626
it('returns DtsContent instance from composing css whose has invalid import/composes', async () => {
2727
const content = await new DtsCreator().create('fixtures/invalidComposer.scss');
2828
assert.equal(content.contents.length, 1);
29-
assert.equal(content.contents[0], 'readonly "myClass": string;');
29+
assert.equal(content.contents[0], 'readonly myClass: string;');
3030
});
3131

3232
it('returns DtsContent instance from the pair of path and contents', async () => {
3333
const content = await new DtsCreator().create('fixtures/somePath', `.myClass { color: red }`);
3434
assert.equal(content.contents.length, 1);
35-
assert.equal(content.contents[0], 'readonly "myClass": string;');
35+
assert.equal(content.contents[0], 'readonly myClass: string;');
3636
});
3737

3838
it('returns DtsContent instance combined css', async () => {
3939
const content = await new DtsCreator().create('fixtures/combined/combined.css');
4040
assert.equal(content.contents.length, 3);
41-
assert.equal(content.contents[0], 'readonly "block": string;');
42-
assert.equal(content.contents[1], 'readonly "box": string;');
43-
assert.equal(content.contents[2], 'readonly "myClass": string;');
41+
assert.equal(content.contents[0], 'readonly block: string;');
42+
assert.equal(content.contents[1], 'readonly box: string;');
43+
assert.equal(content.contents[2], 'readonly myClass: string;');
4444
});
4545
});
4646

src/dts-creator.ts

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ interface DtsCreatorOptions {
1212
searchDir?: string;
1313
outDir?: string;
1414
camelCase?: CamelCaseOption;
15+
singleQuote?: boolean;
1516
namedExports?: boolean;
1617
allowArbitraryExtensions?: boolean;
1718
dropExtension?: boolean;
@@ -26,6 +27,7 @@ export class DtsCreator {
2627
private loader: FileSystemLoader;
2728
private inputDirectory: string;
2829
private camelCase: CamelCaseOption;
30+
private singleQuote?: boolean;
2931
private namedExports: boolean;
3032
private allowArbitraryExtensions: boolean;
3133
private dropExtension: boolean;
@@ -38,6 +40,7 @@ export class DtsCreator {
3840
this.outDir = options.outDir || this.searchDir;
3941
this.loader = new FileSystemLoader(this.rootDir, options.loaderPlugins);
4042
this.inputDirectory = path.join(this.rootDir, this.searchDir);
43+
this.singleQuote = options.singleQuote;
4144
this.camelCase = options.camelCase;
4245
this.namedExports = !!options.namedExports;
4346
this.allowArbitraryExtensions = !!options.allowArbitraryExtensions;
@@ -79,6 +82,7 @@ export class DtsCreator {
7982
namedExports: this.namedExports,
8083
allowArbitraryExtensions: this.allowArbitraryExtensions,
8184
camelCase: this.camelCase,
85+
singleQuote: this.singleQuote,
8286
EOL: this.EOL,
8387
});
8488

src/run.ts

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ interface RunOptions {
99
outDir?: string;
1010
watch?: boolean;
1111
camelCase?: boolean;
12+
singleQuote?: boolean;
1213
namedExports?: boolean;
1314
allowArbitraryExtensions?: boolean;
1415
dropExtension?: boolean;
@@ -24,6 +25,7 @@ export async function run(searchDir: string, options: RunOptions = {}): Promise<
2425
searchDir,
2526
outDir: options.outDir,
2627
camelCase: options.camelCase,
28+
singleQuote: options.singleQuote,
2729
namedExports: options.namedExports,
2830
allowArbitraryExtensions: options.allowArbitraryExtensions,
2931
dropExtension: options.dropExtension,

0 commit comments

Comments
 (0)