From 50fb1c3cfc9ce3033fe8a12bdb7a275016b48cf7 Mon Sep 17 00:00:00 2001 From: Quramy Date: Tue, 1 Jun 2021 21:40:37 +0900 Subject: [PATCH] Chore: Install prettier --- .github/workflows/build.yml | 7 +- .husky/.gitignore | 1 + .husky/pre-commit | 5 + .prettierignore | 8 ++ .prettierrc.yml | 7 + README.md | 58 +++++---- package-lock.json | 218 ++++++++++++++++++++++++++++--- package.json | 14 +- renovate.json | 3 + src/cli.ts | 50 +++++--- src/dts-content.ts | 250 ++++++++++++++++++------------------ src/dts-creator.ts | 23 ++-- src/file-system-loader.ts | 52 ++++---- src/index.ts | 4 +- src/is-there.d.ts | 4 +- src/run.ts | 98 +++++++------- test/dts-creator.spec.ts | 102 +++++++-------- 17 files changed, 572 insertions(+), 332 deletions(-) create mode 100644 .husky/.gitignore create mode 100755 .husky/pre-commit create mode 100644 .prettierignore create mode 100644 .prettierrc.yml create mode 100644 renovate.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f6b22b7a..ce3c2d3b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,9 +16,14 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - - name: npm install, build, and test + - name: npm install, build run: | npm ci + - name: Lint + run: | + npm run lint + - name: Test + run: | npm run test:ci env: CI: true diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 00000000..31354ec1 --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000..c537582f --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,5 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx pretty-quick --staged + diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..965ef942 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +.git/ +.husky/ +node_modules/ +lib/ +__snapshots__/ +coverage/ +*.css.d.ts +test/**/*.css diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 index 00000000..8dbc64f9 --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1,7 @@ +trailingComma: all +tabWidth: 2 +semi: true +singleQuote: true +bracketSpacing: true +printWidth: 120 +arrowParens: avoid diff --git a/README.md b/README.md index a3079aa5..bd4af51e 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ typed-css-modules creates the following .d.ts files from the above css: ```ts /* styles.css.d.ts */ declare const styles: { - readonly "primary": string; - readonly "myClass": string; + readonly primary: string; + readonly myClass: string; }; export = styles; ``` @@ -57,6 +57,7 @@ Then, this creates `*.css.d.ts` files under the directory which has original .cs ``` #### output directory + Use `-o` or `--outDir` option. For example: @@ -84,11 +85,12 @@ tcm -p 'src/**/*.icss' . ``` #### watch + With `-w` or `--watch`, this CLI watches files in the input directory. #### camelize CSS token -With `-c` or `--camelCase`, kebab-cased CSS classes(such as `.my-class {...}`) are exported as camelized TypeScript varibale name(`export const myClass: string`). +With `-c` or `--camelCase`, kebab-cased CSS classes(such as `.my-class {...}`) are exported as camelized TypeScript varibale name(`export const myClass: string`). You can pass `--camelCase dashes` to only camelize dashes in the class name. Since version `0.27.1` in the webpack `css-loader`. This will keep upperCase class names intact, e.g.: @@ -103,7 +105,7 @@ becomes ```typescript declare const styles: { - readonly "SomeComponent": string; + readonly SomeComponent: string; }; export = styles; ``` @@ -111,6 +113,7 @@ export = styles; See also [webpack css-loader's camelCase option](https://github.com/webpack/css-loader#camelcase). #### named exports (enable tree shaking) + With `-e` or `--namedExports`, types are exported as named exports as opposed to default exports. This enables support for the `namedExports` css-loader feature, required for webpack to tree shake the final CSS (learn more [here](https://webpack.js.org/loaders/css-loader/#namedexport)). @@ -118,7 +121,7 @@ Use this option in combination with https://webpack.js.org/loaders/css-loader/#n When this option is enabled, the type definition changes to support named exports. -*NOTE: this option enables camelcase by default.* +_NOTE: this option enables camelcase by default._ ```css .SomeComponent { @@ -130,7 +133,7 @@ When this option is enabled, the type definition changes to support named export ```typescript declare const styles: { - readonly "SomeComponent": string; + readonly SomeComponent: string; }; export = styles; ``` @@ -151,56 +154,62 @@ npm install typed-css-modules import DtsCreator from 'typed-css-modules'; let creator = new DtsCreator(); creator.create('src/style.css').then(content => { - console.log(content.tokens); // ['myClass'] - console.log(content.formatted); // 'export const myClass: string;' - content.writeFile(); // writes this content to "src/style.css.d.ts" + console.log(content.tokens); // ['myClass'] + console.log(content.formatted); // 'export const myClass: string;' + content.writeFile(); // writes this content to "src/style.css.d.ts" }); ``` ### class DtsCreator + DtsCreator instance processes the input CSS and create TypeScript definition contents. #### `new DtsCreator(option)` + You can set the following options: -* `option.rootDir`: Project root directory(default: `process.cwd()`). -* `option.searchDir`: Directory which includes target `*.css` files(default: `'./'`). -* `option.outDir`: Output directory(default: `option.searchDir`). -* `option.camelCase`: Camelize CSS class tokens. -* `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.EOL`: EOL (end of line) for the generated `d.ts` files. Possible values `'\n'` or `'\r\n'`(default: `os.EOL`). +- `option.rootDir`: Project root directory(default: `process.cwd()`). +- `option.searchDir`: Directory which includes target `*.css` files(default: `'./'`). +- `option.outDir`: Output directory(default: `option.searchDir`). +- `option.camelCase`: Camelize CSS class tokens. +- `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.EOL`: EOL (end of line) for the generated `d.ts` files. Possible values `'\n'` or `'\r\n'`(default: `os.EOL`). #### `create(filepath, contents) => Promise(dtsContent)` + Returns `DtsContent` instance. -* `filepath`: path of target .css file. -* `contents`(optional): the CSS content of the `filepath`. If set, DtsCreator uses the contents instead of the original contents of the `filepath`. +- `filepath`: path of target .css file. +- `contents`(optional): the CSS content of the `filepath`. If set, DtsCreator uses the contents instead of the original contents of the `filepath`. ### class DtsContent + DtsContent instance has `*.d.ts` content, final output path, and function to write file. #### `writeFile(postprocessor) => Promise(dtsContent)` + Writes the DtsContent instance's content to a file. Returns the DtsContent instance. -* `postprocessor` (optional): a function that takes the formatted definition string and returns a modified string that will be the final content written to the file. +- `postprocessor` (optional): a function that takes the formatted definition string and returns a modified string that will be the final content written to the file. You could use this, for example, to pass generated definitions through a formatter like Prettier, or to add a comment to the top of generated files: ```js - dtsContent.writeFile( - definition => `// Generated automatically, do not edit\n${definition}` - ) + dtsContent.writeFile(definition => `// Generated automatically, do not edit\n${definition}`); ``` #### `tokens` + An array of tokens retrieved from input CSS file. e.g. `['myClass']` #### `contents` + An array of TypeScript definition expressions. e.g. `['export const myClass: string;']`. #### `formatted` + A string of TypeScript definition expression. e.g. @@ -210,13 +219,16 @@ export const myClass: string; ``` #### `messageList` + An array of messages. The messages contains invalid token information. e.g. `['my-class is not valid TypeScript variable name.']`. #### `outputFilePath` + Final output file path. ## Remarks + If your input CSS file has the following class names, these invalid tokens are not written to output `.d.ts` file. ```css @@ -227,7 +239,7 @@ If your input CSS file has the following class names, these invalid tokens are n /* invalid TypeScript variable */ /* If camelCase option is set, this token will be converted to 'myClass' */ -.my-class{ +.my-class { color: red; } @@ -238,9 +250,11 @@ If your input CSS file has the following class names, these invalid tokens are n ``` ## Example + There is a minimum example in this repository `example` folder. Clone this repository and run `cd example; npm i; npm start`. Or please see [https://github.com/Quramy/typescript-css-modules-demo](https://github.com/Quramy/typescript-css-modules-demo). It's a working demonstration of CSS Modules with React and TypeScript. ## License + This software is released under the MIT License, see LICENSE.txt. diff --git a/package-lock.json b/package-lock.json index 782816e4..37f26ebb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1311,11 +1311,6 @@ "@babel/types": "^7.3.0" } }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" - }, "@types/css-modules-loader-core": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@types/css-modules-loader-core/-/css-modules-loader-core-1.1.0.tgz", @@ -1518,6 +1513,24 @@ "sprintf-js": "~1.0.2" } }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2140,6 +2153,15 @@ "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", "dev": true }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -2361,6 +2383,12 @@ "mime-types": "^2.1.12" } }, + "fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2498,6 +2526,12 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, + "husky": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/husky/-/husky-6.0.0.tgz", + "integrity": "sha512-SQS2gDTB7tBN486QSoKPKQItZw97BMOd+Kdb6ghfpBc0yXyzrddI0oDV5MkDAbuB4X2mO3/nj60TRMcYxwzZeQ==", + "dev": true + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -2512,6 +2546,12 @@ "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=" }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, "import-local": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", @@ -5416,12 +5456,31 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, + "mri": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", + "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5557,6 +5616,15 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" }, + "pinst": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/pinst/-/pinst-2.1.6.tgz", + "integrity": "sha512-B4dYmf6nEXg1NpDSB+orYWvKa5Kfmz5KzWC29U59dpVM4S/+xp0ak/JMEsw04UQTNNKps7klu0BUalr343Gt9g==", + "dev": true, + "requires": { + "fromentries": "^1.3.2" + } + }, "pirates": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", @@ -5576,9 +5644,9 @@ } }, "postcss": { - "version": "7.0.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.18.tgz", - "integrity": "sha512-/7g1QXXgegpF+9GJj4iN7ChGF40sYuGYJ8WZu8DZWnmhQ/G36hfdk3q9LBJmoK+lZ+yzZ5KYpOoxq7LF1BxE8g==", + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -5706,6 +5774,12 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true + }, "pretty-format": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", @@ -5750,6 +5824,103 @@ } } }, + "pretty-quick": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.0.tgz", + "integrity": "sha512-DtxIxksaUWCgPFN7E1ZZk4+Aav3CCuRdhrDSFZENb404sYMtuo9Zka823F+Mgeyt8Zt3bUiCjFzzWYE9LYqkmQ==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "execa": "^4.0.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.5", + "multimatch": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "prompts": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", @@ -5766,6 +5937,16 @@ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -6344,11 +6525,10 @@ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -6411,9 +6591,9 @@ "dev": true }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, "yallist": { "version": "4.0.0", @@ -6422,9 +6602,9 @@ "dev": true }, "yargs": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", - "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "requires": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -6436,7 +6616,7 @@ "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^18.1.1" + "yargs-parser": "^18.1.2" } }, "yargs-parser": { diff --git a/package.json b/package.json index 43d927e8..dfe7629f 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,16 @@ "scripts": { "clean": "rimraf lib/", "build": "npm run clean && tsc && chmod +x lib/cli.js", + "prettier": "prettier \"*.{md,js,json.yml,yaml}\" \"{src,test}/**/*\"", + "format": "npm run prettier -- --write", + "lint": "npm run prettier -- --check", "test": "jest", "test:watch": "jest --watch", "test:ci": "jest --coverage", - "prepublish": "npm run build" + "prepublish": "npm run build", + "postinstall": "husky install", + "prepublishOnly": "pinst --disable", + "postpublish": "pinst --enable" }, "bin": { "tcm": "lib/cli.js" @@ -37,7 +43,7 @@ "glob": "^7.1.2", "is-there": "^4.4.2", "mkdirp": "^1.0.0", - "yargs": "^15.3.1" + "yargs": "^15.4.1" }, "devDependencies": { "@types/glob": "^7.1.1", @@ -45,7 +51,11 @@ "@types/mkdirp": "^1.0.0", "@types/node": "^14.14.37", "@types/yargs": "^15.0.4", + "husky": "^6.0.0", "jest": "^27.0.0", + "pinst": "^2.1.6", + "prettier": "^2.3.0", + "pretty-quick": "^3.1.0", "ts-jest": "^27.0.0", "typescript": "^4.3.0" }, diff --git a/renovate.json b/renovate.json new file mode 100644 index 00000000..4f39080e --- /dev/null +++ b/renovate.json @@ -0,0 +1,3 @@ +{ + "extends": ["config:base"] +} diff --git a/src/cli.ts b/src/cli.ts index 10a4e8a8..31896b99 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,42 +1,56 @@ #!/usr/bin/env node import * as yargs from 'yargs'; -import {run} from "./run"; +import { run } from './run'; - -const yarg = yargs.usage('Create .css.d.ts from CSS modules *.css files.\nUsage: $0 [options] ') +const yarg = yargs + .usage('Create .css.d.ts from CSS modules *.css files.\nUsage: $0 [options] ') .example('$0 src/styles', '') .example('$0 src -o dist', '') .example('$0 -p styles/**/*.icss -w', '') .detectLocale(false) .demand(['_']) - .alias('p', 'pattern').describe('p', 'Glob pattern with css files').string("p") - .alias('o', 'outDir').describe('o', 'Output directory').string("o") - .alias('w', 'watch').describe('w', 'Watch input directory\'s css files or pattern').boolean('w') - .alias('c', 'camelCase').describe('c', 'Convert CSS class tokens to camelcase').boolean("c") - .alias('e', 'namedExports').describe('e', 'Use named exports as opposed to default exports to enable tree shaking.').boolean("e") - .alias('d', 'dropExtension').describe('d', 'Drop the input files extension').boolean('d') - .alias('s', 'silent').describe('s', 'Silent output. Do not show "files written" messages').boolean('s') - .alias('h', 'help').help('h') + .alias('p', 'pattern') + .describe('p', 'Glob pattern with css files') + .string('p') + .alias('o', 'outDir') + .describe('o', 'Output directory') + .string('o') + .alias('w', 'watch') + .describe('w', "Watch input directory's css files or pattern") + .boolean('w') + .alias('c', 'camelCase') + .describe('c', 'Convert CSS class tokens to camelcase') + .boolean('c') + .alias('e', 'namedExports') + .describe('e', 'Use named exports as opposed to default exports to enable tree shaking.') + .boolean('e') + .alias('d', 'dropExtension') + .describe('d', 'Drop the input files extension') + .boolean('d') + .alias('s', 'silent') + .describe('s', 'Silent output. Do not show "files written" messages') + .boolean('s') + .alias('h', 'help') + .help('h') .version(require('../package.json').version); - main(); async function main(): Promise { const argv = yarg.argv; - if(argv.h) { + if (argv.h) { yarg.showHelp(); return; } let searchDir: string; - if(argv._ && argv._[0]) { + if (argv._ && argv._[0]) { searchDir = argv._[0]; - }else if(argv.p) { + } else if (argv.p) { searchDir = './'; - }else{ + } else { yarg.showHelp(); return; } @@ -48,6 +62,6 @@ async function main(): Promise { camelCase: argv.c, namedExports: argv.e, dropExtension: argv.d, - silent: argv.s + silent: argv.s, }); -}; +} diff --git a/src/dts-content.ts b/src/dts-content.ts index c41702a6..81e02416 100644 --- a/src/dts-content.ts +++ b/src/dts-content.ts @@ -1,159 +1,155 @@ -import * as fs from "fs"; -import * as os from "os"; -import * as path from "path"; -import isThere from "is-there"; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import isThere from 'is-there'; import * as mkdirp from 'mkdirp'; -import * as util from "util"; -import camelcase from "camelcase"; +import * as util from 'util'; +import camelcase from 'camelcase'; const writeFile = util.promisify(fs.writeFile); const readFile = util.promisify(fs.readFile); -export type CamelCaseOption = boolean | 'dashes' | undefined; +export type CamelCaseOption = boolean | 'dashes' | undefined; interface DtsContentOptions { - dropExtension: boolean; - rootDir: string; - searchDir: string; - outDir: string; - rInputPath: string; - rawTokenList: string[]; - namedExports: boolean; - camelCase: CamelCaseOption; - EOL: string; + dropExtension: boolean; + rootDir: string; + searchDir: string; + outDir: string; + rInputPath: string; + rawTokenList: string[]; + namedExports: boolean; + camelCase: CamelCaseOption; + EOL: string; } export class DtsContent { - private dropExtension: boolean; - private rootDir: string; - private searchDir: string; - private outDir: string; - private rInputPath: string; - private rawTokenList: string[]; - private namedExports: boolean; - private camelCase: CamelCaseOption; - private resultList: string[]; - private EOL: string; - - constructor(options: DtsContentOptions) { - this.dropExtension = options.dropExtension; - this.rootDir = options.rootDir; - this.searchDir = options.searchDir; - this.outDir = options.outDir; - this.rInputPath = options.rInputPath; - this.rawTokenList = options.rawTokenList; - this.namedExports = options.namedExports; - this.camelCase = options.camelCase; - this.EOL = options.EOL; - - // when using named exports, camelCase must be enabled by default - // (see https://webpack.js.org/loaders/css-loader/#namedexport) - // we still accept external control for the 'dashes' option, - // so we only override in case is false or undefined - if (this.namedExports && !this.camelCase) { - this.camelCase = true; - } - - this.resultList = this.createResultList(); + private dropExtension: boolean; + private rootDir: string; + private searchDir: string; + private outDir: string; + private rInputPath: string; + private rawTokenList: string[]; + private namedExports: boolean; + private camelCase: CamelCaseOption; + private resultList: string[]; + private EOL: string; + + constructor(options: DtsContentOptions) { + this.dropExtension = options.dropExtension; + this.rootDir = options.rootDir; + this.searchDir = options.searchDir; + this.outDir = options.outDir; + this.rInputPath = options.rInputPath; + this.rawTokenList = options.rawTokenList; + this.namedExports = options.namedExports; + this.camelCase = options.camelCase; + this.EOL = options.EOL; + + // when using named exports, camelCase must be enabled by default + // (see https://webpack.js.org/loaders/css-loader/#namedexport) + // we still accept external control for the 'dashes' option, + // so we only override in case is false or undefined + if (this.namedExports && !this.camelCase) { + this.camelCase = true; } - public get contents(): string[] { - return this.resultList; - } + this.resultList = this.createResultList(); + } - public get formatted(): string { - if(!this.resultList || !this.resultList.length) return ''; - - if (this.namedExports) { - return [ - 'export const __esModule: true;', - ...this.resultList.map(line => 'export ' + line), - '' - ].join(os.EOL) + this.EOL; - } - - return [ - 'declare const styles: {', - ...this.resultList.map(line => ' ' + line), - '};', - 'export = styles;', - '' - ].join(os.EOL) + this.EOL; - } + public get contents(): string[] { + return this.resultList; + } - public get tokens(): string[] { - return this.rawTokenList; - } - - public get outputFilePath(): string { - const outputFileName = this.dropExtension ? removeExtension(this.rInputPath) : this.rInputPath; - return path.join(this.rootDir, this.outDir, outputFileName + '.d.ts'); - } + public get formatted(): string { + if (!this.resultList || !this.resultList.length) return ''; - public get inputFilePath(): string { - return path.join(this.rootDir, this.searchDir, this.rInputPath); + if (this.namedExports) { + return ( + ['export const __esModule: true;', ...this.resultList.map(line => 'export ' + line), ''].join(os.EOL) + this.EOL + ); } - public async writeFile(postprocessor = (formatted: string) => formatted): Promise { - const finalOutput = postprocessor(this.formatted); + return ( + ['declare const styles: {', ...this.resultList.map(line => ' ' + line), '};', 'export = styles;', ''].join( + os.EOL, + ) + this.EOL + ); + } - const outPathDir = path.dirname(this.outputFilePath); - if(!isThere(outPathDir)) { - mkdirp.sync(outPathDir); - } + public get tokens(): string[] { + return this.rawTokenList; + } - let isDirty = false; + public get outputFilePath(): string { + const outputFileName = this.dropExtension ? removeExtension(this.rInputPath) : this.rInputPath; + return path.join(this.rootDir, this.outDir, outputFileName + '.d.ts'); + } - if(!isThere(this.outputFilePath)) { - isDirty = true; - } else { - const content = (await readFile(this.outputFilePath)).toString(); + public get inputFilePath(): string { + return path.join(this.rootDir, this.searchDir, this.rInputPath); + } - if(content !== finalOutput) { - isDirty = true; - } - } + public async writeFile(postprocessor = (formatted: string) => formatted): Promise { + const finalOutput = postprocessor(this.formatted); - if(isDirty) { - await writeFile(this.outputFilePath, finalOutput, 'utf8'); - } + const outPathDir = path.dirname(this.outputFilePath); + if (!isThere(outPathDir)) { + mkdirp.sync(outPathDir); } - private createResultList(): string[] { - const convertKey = this.getConvertKeyMethod(this.camelCase); + let isDirty = false; - const result = this.rawTokenList - .map(k => convertKey(k)) - .map(k => !this.namedExports ? 'readonly "' + k + '": string;' : 'const ' + k + ': string;') + if (!isThere(this.outputFilePath)) { + isDirty = true; + } else { + const content = (await readFile(this.outputFilePath)).toString(); - return result; + if (content !== finalOutput) { + isDirty = true; + } } - private getConvertKeyMethod(camelCaseOption: CamelCaseOption): (str: string) => string { - switch (camelCaseOption) { - case true: - return camelcase; - case 'dashes': - return this.dashesCamelCase; - default: - return (key) => key; - } - } - - /** - * Replaces only the dashes and leaves the rest as-is. - * - * Mirrors the behaviour of the css-loader: - * https://github.com/webpack-contrib/css-loader/blob/1fee60147b9dba9480c9385e0f4e581928ab9af9/lib/compile-exports.js#L3-L7 - */ - private dashesCamelCase(str: string): string { - return str.replace(/-+(\w)/g, function(match, firstLetter) { - return firstLetter.toUpperCase(); - }); - } + if (isDirty) { + await writeFile(this.outputFilePath, finalOutput, 'utf8'); + } + } + + private createResultList(): string[] { + const convertKey = this.getConvertKeyMethod(this.camelCase); + + const result = this.rawTokenList + .map(k => convertKey(k)) + .map(k => (!this.namedExports ? 'readonly "' + k + '": string;' : 'const ' + k + ': string;')); + + return result; + } + + private getConvertKeyMethod(camelCaseOption: CamelCaseOption): (str: string) => string { + switch (camelCaseOption) { + case true: + return camelcase; + case 'dashes': + return this.dashesCamelCase; + default: + return key => key; + } + } + + /** + * Replaces only the dashes and leaves the rest as-is. + * + * Mirrors the behaviour of the css-loader: + * https://github.com/webpack-contrib/css-loader/blob/1fee60147b9dba9480c9385e0f4e581928ab9af9/lib/compile-exports.js#L3-L7 + */ + private dashesCamelCase(str: string): string { + return str.replace(/-+(\w)/g, function (match, firstLetter) { + return firstLetter.toUpperCase(); + }); + } } function removeExtension(filePath: string): string { - const ext = path.extname(filePath); - return filePath.replace(new RegExp(ext + '$'), ''); + const ext = path.extname(filePath); + return filePath.replace(new RegExp(ext + '$'), ''); } diff --git a/src/dts-creator.ts b/src/dts-creator.ts index 7073a032..fde4110e 100644 --- a/src/dts-creator.ts +++ b/src/dts-creator.ts @@ -1,10 +1,9 @@ import * as process from 'process'; -import * as path from'path'; +import * as path from 'path'; import * as os from 'os'; import FileSystemLoader from './file-system-loader'; -import {DtsContent, CamelCaseOption} from "./dts-content"; -import {Plugin} from "postcss"; - +import { DtsContent, CamelCaseOption } from './dts-content'; +import { Plugin } from 'postcss'; interface DtsCreatorOptions { rootDir?: string; @@ -30,7 +29,7 @@ export class DtsCreator { private EOL: string; constructor(options?: DtsCreatorOptions) { - if(!options) options = {}; + if (!options) options = {}; this.rootDir = options.rootDir || process.cwd(); this.searchDir = options.searchDir || ''; this.outDir = options.outDir || this.searchDir; @@ -45,17 +44,17 @@ export class DtsCreator { public async create(filePath: string, initialContents?: string, clearCache: boolean = false): Promise { let rInputPath: string; - if(path.isAbsolute(filePath)) { + if (path.isAbsolute(filePath)) { rInputPath = path.relative(this.inputDirectory, filePath); - }else{ + } else { rInputPath = path.relative(this.inputDirectory, path.join(process.cwd(), filePath)); } - if(clearCache) { + if (clearCache) { this.loader.tokensByFile = {}; } - const res = await this.loader.fetch(filePath, "/", undefined, initialContents); - if(res) { + const res = await this.loader.fetch(filePath, '/', undefined, initialContents); + if (res) { const tokens = res; const keys = Object.keys(tokens); @@ -68,11 +67,11 @@ export class DtsCreator { rawTokenList: keys, namedExports: this.namedExports, camelCase: this.camelCase, - EOL: this.EOL + EOL: this.EOL, }); return content; - }else{ + } else { throw res; } } diff --git a/src/file-system-loader.ts b/src/file-system-loader.ts index ee1355ad..028083e7 100644 --- a/src/file-system-loader.ts +++ b/src/file-system-loader.ts @@ -1,11 +1,10 @@ /* this file is forked from https://raw.githubusercontent.com/css-modules/css-modules-loader-core/master/src/file-system-loader.js */ -import Core from 'css-modules-loader-core' -import * as fs from 'fs' -import * as path from 'path' -import * as util from 'util' -import { Plugin } from "postcss"; - +import Core from 'css-modules-loader-core'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as util from 'util'; +import { Plugin } from 'postcss'; type Dictionary = { [key: string]: T | undefined; @@ -13,7 +12,6 @@ type Dictionary = { const readFile = util.promisify(fs.readFile); - export default class FileSystemLoader { private root: string; private sources: Dictionary; @@ -21,7 +19,7 @@ export default class FileSystemLoader { private core: Core; public tokensByFile: Dictionary; - constructor( root: string, plugins?: Array> ) { + constructor(root: string, plugins?: Array>) { this.root = root; this.sources = {}; this.importNr = 0; @@ -29,8 +27,13 @@ export default class FileSystemLoader { this.tokensByFile = {}; } - public async fetch(_newPath: string, relativeTo: string, _trace?: string, initialContents?: string): Promise { - const newPath = _newPath.replace(/^["']|["']$/g, ""); + public async fetch( + _newPath: string, + relativeTo: string, + _trace?: string, + initialContents?: string, + ): Promise { + const newPath = _newPath.replace(/^["']|["']$/g, ''); const trace = _trace || String.fromCharCode(this.importNr++); const relativeDir = path.dirname(relativeTo); @@ -43,22 +46,20 @@ export default class FileSystemLoader { if (isNodeModule(newPath)) { try { fileRelativePath = require.resolve(newPath); - } - catch (e) {} + } catch (e) {} } let source: string; if (!initialContents) { - const tokens = this.tokensByFile[fileRelativePath] + const tokens = this.tokensByFile[fileRelativePath]; if (tokens) { return tokens; } try { - source = await readFile(fileRelativePath, "utf-8"); - } - catch (error) { + source = await readFile(fileRelativePath, 'utf-8'); + } catch (error) { if (relativeTo && relativeTo !== '/') { return {}; } @@ -69,7 +70,12 @@ export default class FileSystemLoader { source = initialContents; } - const { injectableSource, exportTokens } = await this.core.load(source, rootRelativePath, trace, this.fetch.bind(this)); + const { injectableSource, exportTokens } = await this.core.load( + source, + rootRelativePath, + trace, + this.fetch.bind(this), + ); const re = new RegExp(/@import\s'(\D+?)';/, 'gm'); @@ -77,20 +83,20 @@ export default class FileSystemLoader { let result; - while (result = re.exec(injectableSource)) { + while ((result = re.exec(injectableSource))) { const importFile = result?.[1]; - if (importFile) { - let importFilePath = isNodeModule(importFile) ? - importFile : - path.resolve(path.dirname(fileRelativePath), importFile); + if (importFile) { + let importFilePath = isNodeModule(importFile) + ? importFile + : path.resolve(path.dirname(fileRelativePath), importFile); const localTokens = await this.fetch(importFilePath, relativeTo, undefined, initialContents); Object.assign(importTokens, localTokens); } } - const tokens = {...exportTokens, ...importTokens}; + const tokens = { ...exportTokens, ...importTokens }; this.sources[trace] = injectableSource; this.tokensByFile[fileRelativePath] = tokens; diff --git a/src/index.ts b/src/index.ts index 12a9d6b9..dccc17c6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,2 @@ -export {DtsCreator as default} from './dts-creator'; -export {run} from './run'; +export { DtsCreator as default } from './dts-creator'; +export { run } from './run'; diff --git a/src/is-there.d.ts b/src/is-there.d.ts index 3224c390..043be73b 100644 --- a/src/is-there.d.ts +++ b/src/is-there.d.ts @@ -1,4 +1,4 @@ declare module 'is-there' { - function isThere(path: string): boolean; - export = isThere; + function isThere(path: string): boolean; + export = isThere; } diff --git a/src/run.ts b/src/run.ts index 83b86279..8ac660fd 100644 --- a/src/run.ts +++ b/src/run.ts @@ -1,63 +1,61 @@ -import * as path from "path"; -import * as util from "util"; -import chalk from "chalk"; -import * as chokidar from "chokidar"; +import * as path from 'path'; +import * as util from 'util'; +import chalk from 'chalk'; +import * as chokidar from 'chokidar'; import _glob from 'glob'; -import {DtsCreator} from "./dts-creator"; -import {DtsContent} from "./dts-content"; +import { DtsCreator } from './dts-creator'; +import { DtsContent } from './dts-content'; const glob = util.promisify(_glob); - interface RunOptions { - pattern?: string; - outDir?: string; - watch?: boolean; - camelCase?: boolean; - namedExports?: boolean; - dropExtension?: boolean; - silent?: boolean; + pattern?: string; + outDir?: string; + watch?: boolean; + camelCase?: boolean; + namedExports?: boolean; + dropExtension?: boolean; + silent?: boolean; } export async function run(searchDir: string, options: RunOptions = {}): Promise { - const filesPattern = path.join(searchDir, options.pattern || '**/*.css'); - - const creator = new DtsCreator({ - rootDir: process.cwd(), - searchDir, - outDir: options.outDir, - camelCase: options.camelCase, - namedExports: options.namedExports, - dropExtension: options.dropExtension, - }); - - const writeFile = async (f: string): Promise => { - try { - const content: DtsContent = await creator.create(f, undefined, !!options.watch); - await content.writeFile(); - - if (!options.silent) { - console.log('Wrote ' + chalk.green(content.outputFilePath)); - } - } - catch (error) { - console.error(chalk.red('[Error] ' + error)); - } - }; - - if(!options.watch) { - const files = await glob(filesPattern); - await Promise.all(files.map(writeFile)); - } else { - console.log('Watch ' + filesPattern + '...'); - - const watcher = chokidar.watch([filesPattern.replace(/\\/g, "/")]); - watcher.on('add', writeFile); - watcher.on('change', writeFile); - await waitForever(); + const filesPattern = path.join(searchDir, options.pattern || '**/*.css'); + + const creator = new DtsCreator({ + rootDir: process.cwd(), + searchDir, + outDir: options.outDir, + camelCase: options.camelCase, + namedExports: options.namedExports, + dropExtension: options.dropExtension, + }); + + const writeFile = async (f: string): Promise => { + try { + const content: DtsContent = await creator.create(f, undefined, !!options.watch); + await content.writeFile(); + + if (!options.silent) { + console.log('Wrote ' + chalk.green(content.outputFilePath)); + } + } catch (error) { + console.error(chalk.red('[Error] ' + error)); } + }; + + if (!options.watch) { + const files = await glob(filesPattern); + await Promise.all(files.map(writeFile)); + } else { + console.log('Watch ' + filesPattern + '...'); + + const watcher = chokidar.watch([filesPattern.replace(/\\/g, '/')]); + watcher.on('add', writeFile); + watcher.on('change', writeFile); + await waitForever(); + } } async function waitForever(): Promise { - return new Promise(() => {}); + return new Promise(() => {}); } diff --git a/test/dts-creator.spec.ts b/test/dts-creator.spec.ts index b1d4314e..6cf0358d 100644 --- a/test/dts-creator.spec.ts +++ b/test/dts-creator.spec.ts @@ -43,31 +43,31 @@ describe('DtsCreator', () => { }); }); it('returns DtsContent instance from the pair of path and contents', done => { - creator - .create('test/somePath', `.myClass { color: red }`) - .then(content => { - assert.equal(content.contents.length, 1); - assert.equal(content.contents[0], 'readonly "myClass": string;'); - done(); - }); + creator.create('test/somePath', `.myClass { color: red }`).then(content => { + assert.equal(content.contents.length, 1); + assert.equal(content.contents[0], 'readonly "myClass": string;'); + done(); + }); }); it('returns DtsContent instance combined css', done => { creator.create('test/combined/combined.css').then(content => { - assert.equal(content.contents.length, 3); - assert.equal(content.contents[0], 'readonly "block": string;'); - assert.equal(content.contents[1], 'readonly "myClass": string;'); - assert.equal(content.contents[2], 'readonly "box": string;'); - done(); + assert.equal(content.contents.length, 3); + assert.equal(content.contents[0], 'readonly "block": string;'); + assert.equal(content.contents[1], 'readonly "myClass": string;'); + assert.equal(content.contents[2], 'readonly "box": string;'); + done(); }); }); }); describe('#modify path', () => { it('can be set outDir', done => { - new DtsCreator({searchDir: "test", outDir: "dist"}).create(path.normalize('test/testStyle.css')).then(content => { - assert.equal(path.relative(process.cwd(), content.outputFilePath), path.normalize("dist/testStyle.css.d.ts")); - done(); - }); + new DtsCreator({ searchDir: 'test', outDir: 'dist' }) + .create(path.normalize('test/testStyle.css')) + .then(content => { + assert.equal(path.relative(process.cwd(), content.outputFilePath), path.normalize('dist/testStyle.css.d.ts')); + done(); + }); }); }); }); @@ -85,7 +85,7 @@ describe('DtsContent', () => { describe('#inputFilePath', () => { it('returns original CSS file name', done => { new DtsCreator().create(path.normalize('test/testStyle.css')).then(content => { - assert.equal(path.relative(process.cwd(), content.inputFilePath), path.normalize("test/testStyle.css")); + assert.equal(path.relative(process.cwd(), content.inputFilePath), path.normalize('test/testStyle.css')); done(); }); }); @@ -94,14 +94,14 @@ describe('DtsContent', () => { describe('#outputFilePath', () => { it('adds d.ts to the original filename', done => { new DtsCreator().create(path.normalize('test/testStyle.css')).then(content => { - assert.equal(path.relative(process.cwd(), content.outputFilePath), path.normalize("test/testStyle.css.d.ts")); + assert.equal(path.relative(process.cwd(), content.outputFilePath), path.normalize('test/testStyle.css.d.ts')); done(); }); }); it('can drop the original extension when asked', done => { - new DtsCreator({dropExtension: true}).create(path.normalize('test/testStyle.css')).then(content => { - assert.equal(path.relative(process.cwd(), content.outputFilePath), path.normalize("test/testStyle.d.ts")); + new DtsCreator({ dropExtension: true }).create(path.normalize('test/testStyle.css')).then(content => { + assert.equal(path.relative(process.cwd(), content.outputFilePath), path.normalize('test/testStyle.d.ts')); done(); }); }); @@ -118,7 +118,7 @@ declare const styles: { }; export = styles; -` +`, ); done(); }); @@ -132,7 +132,7 @@ export = styles; export const __esModule: true; export const myClass: string; -` +`, ); done(); }); @@ -146,7 +146,7 @@ export const myClass: string; export const __esModule: true; export const myClass: string; -` +`, ); done(); }); @@ -161,57 +161,51 @@ export const myClass: string; describe('#camelCase option', () => { it('camelCase == true: returns camelized tokens for lowercase classes', done => { - new DtsCreator({ camelCase: true }) - .create('test/kebabed.css') - .then(content => { - assert.equal( - content.formatted, - `\ + new DtsCreator({ camelCase: true }).create('test/kebabed.css').then(content => { + assert.equal( + content.formatted, + `\ declare const styles: { readonly "myClass": string; }; export = styles; -` - ); - done(); - }); +`, + ); + done(); + }); }); it('camelCase == true: returns camelized tokens for uppercase classes ', done => { - new DtsCreator({ camelCase: true }) - .create('test/kebabedUpperCase.css') - .then(content => { - assert.equal( - content.formatted, - `\ + new DtsCreator({ camelCase: true }).create('test/kebabedUpperCase.css').then(content => { + assert.equal( + content.formatted, + `\ declare const styles: { readonly "myClass": string; }; export = styles; -` - ); - done(); - }); +`, + ); + done(); + }); }); it('camelCase == "dashes": returns camelized tokens for dashes only', done => { - new DtsCreator({ camelCase: 'dashes' }) - .create('test/kebabedUpperCase.css') - .then(content => { - assert.equal( - content.formatted, - `\ + new DtsCreator({ camelCase: 'dashes' }).create('test/kebabedUpperCase.css').then(content => { + assert.equal( + content.formatted, + `\ declare const styles: { readonly "MyClass": string; }; export = styles; -` - ); - done(); - }); +`, + ); + done(); + }); }); }); }); @@ -222,7 +216,7 @@ export = styles; .create('test/testStyle.css') .then(content => { return content.writeFile( - formatted => `// this banner was added to the .d.ts file automatically.\n${formatted}` + formatted => `// this banner was added to the .d.ts file automatically.\n${formatted}`, ); }) .then(() => {