diff --git a/README.md b/README.md index 5b341ed6..3ab0f6cd 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,10 @@ export = styles; See also [webpack css-loader's camelCase option](https://github.com/webpack/css-loader#camelcase). +#### Use single quotes to class names in the .d.ts files + +With `-sq` or `--singleQuote`, you can configure what quote to use. Useful when tools like prettier format your .d.ts files. + #### named exports (enable tree shaking) 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: - `option.searchDir`: Directory which includes target `*.css` files(default: `'./'`). - `option.outDir`: Output directory(default: `option.searchDir`). - `option.camelCase`: Camelize CSS class tokens. +- `option.singleQuote`: Use single quotes on dashed keys. - `option.namedExports`: Use named exports as opposed to default exports to enable tree shaking. Requires `import * as style from './file.module.css';` (default: `false`) - `option.allowArbitraryExtensions`: Output filenames that will be compatible with the "arbitrary file extensions" TypeScript feature - `option.EOL`: EOL (end of line) for the generated `d.ts` files. Possible values `'\n'` or `'\r\n'`(default: `os.EOL`). diff --git a/fixtures/kebabed.css b/fixtures/kebabed.css index c1ba0f53..db41f983 100644 --- a/fixtures/kebabed.css +++ b/fixtures/kebabed.css @@ -1,4 +1,3 @@ .my-class { color: red; } - diff --git a/fixtures/testStyle.css.d.ts b/fixtures/testStyle.css.d.ts index f4989445..4119e701 100644 --- a/fixtures/testStyle.css.d.ts +++ b/fixtures/testStyle.css.d.ts @@ -1,5 +1,4 @@ declare const styles: { - readonly "myClass": string; + readonly myClass: string; }; export = styles; - diff --git a/src/cli.ts b/src/cli.ts index fecf33b0..20ebcf0e 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -37,6 +37,11 @@ const yarg = yargs(hideBin(process.argv)) type: 'boolean', alias: 'camelCase', }, + sq: { + desc: 'Use single quotes for writing the keys when they have a dash', + type: 'boolean', + alias: 'singleQuote', + }, e: { type: 'boolean', desc: 'Use named exports as opposed to default exports to enable tree shaking.', @@ -87,6 +92,7 @@ async function main(): Promise { outDir: argv.o, watch: argv.w, camelCase: argv.c, + singleQuote: argv.sq, namedExports: argv.e, dropExtension: argv.d, allowArbitraryExtensions: argv.a, diff --git a/src/dts-content.test.ts b/src/dts-content.test.ts index 0e20751c..8f9aabe1 100644 --- a/src/dts-content.test.ts +++ b/src/dts-content.test.ts @@ -73,10 +73,9 @@ describe('DtsContent', () => { content.formatted, `\ declare const styles: { - readonly "myClass": string; + readonly myClass: string; }; export = styles; - `, ); }); @@ -88,7 +87,6 @@ export = styles; `\ export const __esModule: true; export const myClass: string; - `, ); }); @@ -100,7 +98,6 @@ export const myClass: string; `\ export const __esModule: true; export const myClass: string; - `, ); }); @@ -117,10 +114,9 @@ export const myClass: string; content.formatted, `\ declare const styles: { - readonly "myClass": string; + readonly myClass: string; }; export = styles; - `, ); }); @@ -131,10 +127,9 @@ export = styles; content.formatted, `\ declare const styles: { - readonly "myClass": string; + readonly myClass: string; }; export = styles; - `, ); }); @@ -147,10 +142,9 @@ export = styles; content.formatted, `\ declare const styles: { - readonly "MyClass": string; + readonly MyClass: string; }; export = styles; - `, ); }); diff --git a/src/dts-content.ts b/src/dts-content.ts index 46448442..2cfb641a 100644 --- a/src/dts-content.ts +++ b/src/dts-content.ts @@ -18,6 +18,7 @@ interface DtsContentOptions { namedExports: boolean; allowArbitraryExtensions: boolean; camelCase: CamelCaseOption; + singleQuote?: boolean; EOL: string; } @@ -31,6 +32,7 @@ export class DtsContent { private namedExports: boolean; private allowArbitraryExtensions: boolean; private camelCase: CamelCaseOption; + private quote: '"' | "'"; private resultList: string[]; private EOL: string; @@ -44,6 +46,7 @@ export class DtsContent { this.namedExports = options.namedExports; this.allowArbitraryExtensions = options.allowArbitraryExtensions; this.camelCase = options.camelCase; + this.quote = options.singleQuote ? "'" : '"'; this.EOL = options.EOL; // when using named exports, camelCase must be enabled by default @@ -65,17 +68,18 @@ export class DtsContent { if (!this.resultList || !this.resultList.length) return 'export {};'; if (this.namedExports) { - return ( - ['export const __esModule: true;', ...this.resultList.map(line => 'export ' + line), ''].join(this.EOL) + - this.EOL - ); + return ['export const __esModule: true;', ...this.resultList.map(line => 'export ' + line), ''].join(this.EOL); } - return ( - ['declare const styles: {', ...this.resultList.map(line => ' ' + line), '};', 'export = styles;', ''].join( - this.EOL, - ) + this.EOL - ); + const data = [ + 'declare const styles: {', + ...this.resultList.map(line => ' ' + line), + '};', + 'export = styles;', + '', + ].join(this.EOL); + + return data; } public get tokens(): string[] { @@ -149,10 +153,15 @@ export class DtsContent { private createResultList(): string[] { const convertKey = this.getConvertKeyMethod(this.camelCase); + const quote = this.camelCase ? '' : this.quote; const result = this.rawTokenList .map(k => convertKey(k)) - .map(k => (!this.namedExports ? 'readonly "' + k + '": string;' : 'const ' + k + ': string;')) + .map(k => { + const q = k.includes('-') ? quote : ''; + + return !this.namedExports ? `readonly ${q}${k}${q}: string;` : 'const ' + k + ': string;'; + }) .sort(); return result; diff --git a/src/dts-creator.test.ts b/src/dts-creator.test.ts index a1c0aea4..44becb1d 100644 --- a/src/dts-creator.test.ts +++ b/src/dts-creator.test.ts @@ -8,7 +8,7 @@ describe(DtsCreator, () => { it('returns DtsContent instance simple css', async () => { const content = await new DtsCreator().create('fixtures/testStyle.css'); assert.equal(content.contents.length, 1); - assert.equal(content.contents[0], 'readonly "myClass": string;'); + assert.equal(content.contents[0], 'readonly myClass: string;'); }); it('rejects an error with invalid CSS', async () => { @@ -20,27 +20,27 @@ describe(DtsCreator, () => { it('returns DtsContent instance from composing css', async () => { const content = await new DtsCreator().create('fixtures/composer.css'); assert.equal(content.contents.length, 1); - assert.equal(content.contents[0], 'readonly "root": string;'); + assert.equal(content.contents[0], 'readonly root: string;'); }); it('returns DtsContent instance from composing css whose has invalid import/composes', async () => { const content = await new DtsCreator().create('fixtures/invalidComposer.scss'); assert.equal(content.contents.length, 1); - assert.equal(content.contents[0], 'readonly "myClass": string;'); + assert.equal(content.contents[0], 'readonly myClass: string;'); }); it('returns DtsContent instance from the pair of path and contents', async () => { const content = await new DtsCreator().create('fixtures/somePath', `.myClass { color: red }`); assert.equal(content.contents.length, 1); - assert.equal(content.contents[0], 'readonly "myClass": string;'); + assert.equal(content.contents[0], 'readonly myClass: string;'); }); it('returns DtsContent instance combined css', async () => { const content = await new DtsCreator().create('fixtures/combined/combined.css'); assert.equal(content.contents.length, 3); - assert.equal(content.contents[0], 'readonly "block": string;'); - assert.equal(content.contents[1], 'readonly "box": string;'); - assert.equal(content.contents[2], 'readonly "myClass": string;'); + assert.equal(content.contents[0], 'readonly block: string;'); + assert.equal(content.contents[1], 'readonly box: string;'); + assert.equal(content.contents[2], 'readonly myClass: string;'); }); }); diff --git a/src/dts-creator.ts b/src/dts-creator.ts index 230d5ca4..5c62f453 100644 --- a/src/dts-creator.ts +++ b/src/dts-creator.ts @@ -12,6 +12,7 @@ interface DtsCreatorOptions { searchDir?: string; outDir?: string; camelCase?: CamelCaseOption; + singleQuote?: boolean; namedExports?: boolean; allowArbitraryExtensions?: boolean; dropExtension?: boolean; @@ -26,6 +27,7 @@ export class DtsCreator { private loader: FileSystemLoader; private inputDirectory: string; private camelCase: CamelCaseOption; + private singleQuote?: boolean; private namedExports: boolean; private allowArbitraryExtensions: boolean; private dropExtension: boolean; @@ -38,6 +40,7 @@ export class DtsCreator { this.outDir = options.outDir || this.searchDir; this.loader = new FileSystemLoader(this.rootDir, options.loaderPlugins); this.inputDirectory = path.join(this.rootDir, this.searchDir); + this.singleQuote = options.singleQuote; this.camelCase = options.camelCase; this.namedExports = !!options.namedExports; this.allowArbitraryExtensions = !!options.allowArbitraryExtensions; @@ -79,6 +82,7 @@ export class DtsCreator { namedExports: this.namedExports, allowArbitraryExtensions: this.allowArbitraryExtensions, camelCase: this.camelCase, + singleQuote: this.singleQuote, EOL: this.EOL, }); diff --git a/src/run.ts b/src/run.ts index 05bd19ea..3bcb7185 100644 --- a/src/run.ts +++ b/src/run.ts @@ -9,6 +9,7 @@ interface RunOptions { outDir?: string; watch?: boolean; camelCase?: boolean; + singleQuote?: boolean; namedExports?: boolean; allowArbitraryExtensions?: boolean; dropExtension?: boolean; @@ -24,6 +25,7 @@ export async function run(searchDir: string, options: RunOptions = {}): Promise< searchDir, outDir: options.outDir, camelCase: options.camelCase, + singleQuote: options.singleQuote, namedExports: options.namedExports, allowArbitraryExtensions: options.allowArbitraryExtensions, dropExtension: options.dropExtension,