├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ ├── deploy.yml │ └── verify.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── babel.config.json ├── fixtures ├── composee.css ├── composer.css ├── empty.css ├── errorCss.css ├── example.css └── invalidComposer.scss ├── lerna.json ├── package.json ├── packages ├── css-modules-flow-types-cli │ ├── README.md │ ├── babel.config.json │ ├── bin │ │ └── cli.js │ ├── package.json │ ├── src │ │ ├── __test__ │ │ │ └── converter.test.js │ │ ├── cli.js │ │ ├── converter.js │ │ ├── css-modules │ │ │ └── fileSystemLoader.js │ │ └── writer.js │ └── yarn.lock ├── css-modules-flow-types-loader │ ├── README.md │ ├── __mocks__ │ │ └── fs.js │ ├── __test__ │ │ └── index.test.js │ ├── babel.config.json │ ├── index.js │ └── package.json └── css-modules-flow-types-printer │ ├── README.md │ ├── __test__ │ └── index.test.js │ ├── babel.config.json │ ├── index.js │ └── package.json ├── publish.sh └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bin 3 | dist 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['eslint:recommended', 'prettier'], 3 | parser: 'babel-eslint', 4 | plugins: ['import', 'prettier'], 5 | env: { 6 | node: true, 7 | es6: true, 8 | }, 9 | root: true, 10 | rules: { 11 | 'prettier/prettier': [ 12 | 'error', 13 | { trailingComma: 'es5', singleQuote: true, tabWidth: 2, }, 14 | ], 15 | 16 | 'prefer-const': 'error', 17 | 'import/order': [ 18 | 'error', 19 | { 20 | groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'], 21 | }, 22 | ], 23 | 'no-unused-vars': ['error', { vars: 'all', args: 'none' }], 24 | 'no-underscore-dangle': 'off', 25 | 'no-param-reassign': 'off', 26 | 'no-console': 'off', 27 | 'no-warning-comments': ['warn', { terms: ['fixme'], location: 'start' }], 28 | }, 29 | parserOptions: { 30 | sourceType: "module" 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Publish changes 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: 12 17 | registry-url: https://registry.npmjs.org/ 18 | 19 | - run: | 20 | git config --local user.email "kenneth.skovhus@gmail.com" 21 | git config --local user.name "skovhus" 22 | name: Configure for pushing git tags 23 | 24 | - run: bash publish.sh 25 | name: Publish changes 26 | env: 27 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 28 | -------------------------------------------------------------------------------- /.github/workflows/verify.yml: -------------------------------------------------------------------------------- 1 | name: Verify changes 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | verify: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: 12 17 | registry-url: https://registry.npmjs.org/ 18 | 19 | - run: yarn install 20 | name: Install dependencies 21 | 22 | - run: yarn verify:bail 23 | name: Verify changes 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *.log 4 | coverage 5 | dist 6 | .idea -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # [2.0.0](https://github.com/skovhus/css-modules-flow-types/compare/v1.4.1...v2.0.0) (2020-08-12) 3 | 4 | ### Features 5 | * Security fix for [trim-newlines CVE](https://github.com/advisories/GHSA-7p7h-4mm5-852v) by upgrading `meow` dependency in `css-modules-flow-flow-types-cli` 6 | * Change minimum Node version to 8 as latest version of `meow` requires Node 8 or newer 7 | 8 | 9 | # [1.4.1](https://github.com/skovhus/css-modules-flow-types/compare/v1.3.0...v1.4.1) (2020-08-12) 10 | 11 | ### Features 12 | * Support for css-loader 4.x (https://github.com/skovhus/css-modules-flow-types/pull/48) 13 | * Various security fixes 14 | 15 | 16 | 17 | # [1.3.0](https://github.com/skovhus/css-modules-flow-types/compare/v1.2.0...v1.3.0) (2019-05-27) 18 | 19 | ### Features 20 | * Change delimiter from `;` to `,` for improved syntax highlighting (https://github.com/skovhus/css-modules-flow-types/pull/25) 21 | 22 | 23 | # [1.2.0](https://github.com/skovhus/css-modules-flow-types/compare/v1.1.1...v1.2.0) (2019-04-12) 24 | 25 | ### Features 26 | * Added end of line detection (https://github.com/skovhus/css-modules-flow-types/pull/26) 27 | 28 | 29 | 30 | # [1.1.1](https://github.com/skovhus/css-modules-flow-types/compare/v1.1.0...v1.1.1) (2018-09-17) 31 | 32 | ### Features 33 | * Change header to 'flow strict' ([e38ad5a](https://github.com/skovhus/css-modules-flow-types/commit/e38ad5a)) 34 | 35 | 36 | 37 | 38 | # [1.1.0](https://github.com/skovhus/css-modules-flow-types/compare/v1.0.1...v1.1.0) (2017-10-15) 39 | 40 | 41 | ### Features 42 | 43 | * silence non-error log output ([46b3366](https://github.com/skovhus/css-modules-flow-types/commit/46b3366)) 44 | 45 | 46 | 47 | 48 | ## [1.0.1](https://github.com/skovhus/css-modules-flow-types/compare/v1.0.0...v1.0.1) (2017-10-13) 49 | 50 | 51 | ### Bug Fixes 52 | 53 | * update yarn.lock files (lerna did not do this) ([f835591](https://github.com/skovhus/css-modules-flow-types/commit/f835591)) 54 | 55 | 56 | 57 | 58 | # [1.0.0](https://github.com/skovhus/css-modules-flow-types/compare/v0.3.1...v1.0.0) (2017-10-13) 59 | 60 | 61 | ### Features 62 | 63 | * rewrite loader tokenization to account for external `composes` rules, change printer to accept tokens as [] instad of {} (fixes [#5](https://github.com/skovhus/css-modules-flow-types/issues/5)) ([b3e2747](https://github.com/skovhus/css-modules-flow-types/commit/b3e2747)) 64 | 65 | 66 | 67 | 68 | ## [0.3.1](https://github.com/skovhus/css-modules-flow-types/compare/v0.3.0...v0.3.1) (2017-06-20) 69 | 70 | 71 | ### Bug Fixes 72 | 73 | * correct webpack setup ([9e0f3f0](https://github.com/skovhus/css-modules-flow-types/commit/9e0f3f0)) 74 | 75 | 76 | 77 | 78 | # [0.3.0](https://github.com/skovhus/css-modules-flow-types/compare/v0.2.2...v0.3.0) (2017-06-19) 79 | 80 | 81 | ### Features 82 | 83 | * detect dangling .flow files ([d006402](https://github.com/skovhus/css-modules-flow-types/commit/d006402)) 84 | 85 | 86 | 87 | 88 | ## [0.2.2](https://github.com/skovhus/css-modules-flow-types/compare/v0.2.1...v0.2.2) (2017-06-18) 89 | 90 | 91 | ### Bug Fixes 92 | 93 | * spelling and flow pragma on top ([286fd58](https://github.com/skovhus/css-modules-flow-types/commit/286fd58)) 94 | 95 | 96 | 97 | 98 | ## [0.2.1](https://github.com/skovhus/css-modules-flow-types/compare/v0.2.0...v0.2.1) (2017-06-18) 99 | 100 | 101 | 102 | 103 | # [0.2.0](https://github.com/skovhus/css-modules-flow-types/compare/v0.1.3...v0.2.0) (2017-06-18) 104 | 105 | 106 | ### Bug Fixes 107 | 108 | * also emit empty .css.flow files (closes [#2](https://github.com/skovhus/css-modules-flow-types/issues/2)) ([ed07c60](https://github.com/skovhus/css-modules-flow-types/commit/ed07c60)) 109 | 110 | 111 | 112 | 113 | ## [0.1.3](https://github.com/skovhus/css-modules-flow-types/compare/v0.1.2...v0.1.3) (2017-06-18) 114 | 115 | 116 | ### Bug Fixes 117 | 118 | * correct cli binary path ([fa26038](https://github.com/skovhus/css-modules-flow-types/commit/fa26038)) 119 | 120 | 121 | 122 | 123 | ## [0.1.2](https://github.com/skovhus/css-modules-flow-types/compare/v0.1.1...v0.1.2) (2017-06-16) 124 | 125 | 126 | ### Bug Fixes 127 | 128 | * webpack loader cannot use emitFile when running in dev mode ([2ac51b0](https://github.com/skovhus/css-modules-flow-types/commit/2ac51b0)) 129 | 130 | 131 | 132 | 133 | ## [0.1.1](https://github.com/skovhus/css-modules-flow-types/compare/v0.1.0...v0.1.1) (2017-06-16) 134 | 135 | 136 | 137 | 138 | # 0.1.0 (2017-06-16) 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Kenneth Skovhus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

css-modules-flow-types

3 | 4 | [![MIT License](https://img.shields.io/npm/l/css-modules-flow-types-loader.svg?style=flat-square)](https://github.com/skovhus/css-modules-flow-types-loader/blob/master/LICENSE) 5 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) 6 |
7 | 8 | CLI and Webpack loader for creating [Flow](https://flow.org/) type definitions based on [CSS Modules](https://github.com/css-modules/css-modules) files. 9 | 10 | This gives you: 11 | - auto-completing for css files in most editors 12 | - flow type safety showing usage of non existing classes 13 | 14 | Read more about the background in this blog post: ["Type safe CSS Modules with Flow"](https://hackernoon.com/type-safe-css-modules-with-flow-dd95e761bbe5). 15 | 16 | 17 | ## Example 18 | 19 | Given the following css file using CSS Modules: 20 | ```css 21 | @value primary: red; 22 | 23 | .myClass { 24 | color: primary; 25 | } 26 | ``` 27 | 28 | `css-modules-flow-types` creates the following .flow file next to it: 29 | 30 | ```javascript 31 | // @flow 32 | /* This file is automatically generated by css-modules-flow-types */ 33 | declare module.exports: {| 34 | +'myClass': string; 35 | +'primary': string; 36 | |}; 37 | ``` 38 | 39 | 40 | ## Usage (Webpack loader) 41 | 42 | ### style-loader 43 | The `css-modules-flow-types-loader` need to be added right after after `style-loader`: 44 | 45 | ```sh 46 | $ npm install --dev css-modules-flow-types-loader 47 | $ yarn add -D css-modules-flow-types-loader 48 | ``` 49 | 50 | ```javascript 51 | { 52 | test: /\.css$/, // or the file format you are using for your CSS Modules 53 | use: [ 54 | 'style-loader', 55 | 'css-modules-flow-types-loader', 56 | // Other loaders like css-loader after this: 57 | { 58 | ... 59 | } 60 | ] 61 | } 62 | ``` 63 | 64 | ### css-loader 65 | 66 | For `css-loader`, `css-modules-flow-types-loader` needs to come _before_ 67 | `css-loader`. 68 | 69 | ```javascript 70 | { 71 | test: /\.css$/, // or the file format you are using for your CSS Modules 72 | use: [ 73 | ExtractTextPlugin.extract({ 74 | use: [ 75 | 'css-modules-flow-types-loader', 76 | { 77 | loader: 'css-loader', 78 | options: {}, // Any options for css-loader 79 | } 80 | ] 81 | }) 82 | ] 83 | } 84 | ``` 85 | 86 | ## Usage (CLI) 87 | 88 | ```sh 89 | $ npm install --dev css-modules-flow-types-cli 90 | $ yarn add -D css-modules-flow-types-cli 91 | ``` 92 | 93 | This installs the runner as `css-modules-flow-types`. 94 | 95 | And run `css-modules-flow-types ` command. 96 | 97 | For example, if you have .css files under `src` directory, exec the following: 98 | 99 | Running, 100 | 101 | ```sh 102 | css-modules-flow-types src 103 | ``` 104 | 105 | Creates `*.css.flow` files next to all css files. 106 | 107 | ```text 108 | (your project root) 109 | - src/ 110 | | myStyle.css 111 | | myStyle.css.flow [created] 112 | ``` 113 | 114 | 115 | 116 | ## Troubleshooting 117 | 118 | ### Support for other file extensions 119 | 120 | To support `.scss`, `.sass`, `.scss.module` or similar files extensions 121 | you need to update your `.flowconfig` file with the following section: 122 | 123 | ``` 124 | [options] 125 | 126 | ; Extensions 127 | module.file_ext=.js 128 | module.file_ext=.jsx 129 | module.file_ext=.json 130 | module.file_ext=.css 131 | module.file_ext=.scss 132 | module.file_ext=.sass 133 | module.file_ext=.scss.module 134 | // other files used by flow 135 | ``` 136 | 137 | Without this Flow might error out with `Required module not found`. 138 | 139 | ### Dynamic imports in Webpack 140 | 141 | In some cases, attempting to load imports using dynamic references could choke webpack as it attempts to parse `.flow` files and encounters unknown syntax. The solution is to exclude `.flow` files with a `webpackExclude` directive in the import statement. 142 | 143 | If you have an import like this: 144 | 145 | ```javascript 146 | import( 147 | /* webpackChunkName: "[request]" */ 148 | `/Path/To/Components/${ getComponent()}` 149 | ) 150 | ``` 151 | 152 | Add `webpackExclude` like this: 153 | 154 | ```javascript 155 | import( 156 | /* webpackChunkName: "[request]" */ 157 | /* webpackExclude: /\.flow$/ */ 158 | `/Path/To/Components/${ getComponent()}` 159 | ) 160 | ``` 161 | 162 | ## Inspiration 163 | 164 | - https://github.com/Quramy/typed-css-modules 165 | - https://github.com/Jimdo/typings-for-css-modules-loader 166 | 167 | 168 | ## Contributing 169 | 170 | To get started, run: 171 | 172 | yarn 173 | 174 | When developing: 175 | 176 | yarn verify # (runs lint and unit test) 177 | yarn lint 178 | yarn test 179 | yarn test:cov 180 | yarn test:watch 181 | 182 | 183 | ## Deployment 184 | 185 | On a new branch run: 186 | 187 | yarn lerna version --no-git-tag-version 188 | # update the CHANGELOG.md file 189 | git add -p 190 | git commit -m 'chore: bump version to x.x' 191 | 192 | Once the branch is merged, the new version is deployed. 193 | 194 | ## License 195 | This software is released under the MIT License. 196 | -------------------------------------------------------------------------------- /babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": "4" 8 | } 9 | } 10 | ] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /fixtures/composee.css: -------------------------------------------------------------------------------- 1 | .box { 2 | padding: 0; 3 | } 4 | -------------------------------------------------------------------------------- /fixtures/composer.css: -------------------------------------------------------------------------------- 1 | .root { 2 | composes: box from "./composee.css"; 3 | color: red; 4 | } 5 | -------------------------------------------------------------------------------- /fixtures/empty.css: -------------------------------------------------------------------------------- 1 | /* 2 | .box { 3 | padding: 0; 4 | } 5 | */ 6 | -------------------------------------------------------------------------------- /fixtures/errorCss.css: -------------------------------------------------------------------------------- 1 | 2 | .class { 3 | -------------------------------------------------------------------------------- /fixtures/example.css: -------------------------------------------------------------------------------- 1 | @value primary: red; 2 | 3 | .myClass {color: red;} 4 | 5 | .while { 6 | color: red; 7 | } 8 | 9 | .my-class { 10 | color: red; 11 | } 12 | 13 | .a {} 14 | -------------------------------------------------------------------------------- /fixtures/invalidComposer.scss: -------------------------------------------------------------------------------- 1 | .myClass { 2 | composes: something from 'path/that/cant/be/found.scss'; 3 | background: red; 4 | } 5 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "lerna": "3.22.1", 4 | "npmClient": "yarn", 5 | "packages": [ 6 | "packages/*" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "lerna run build", 5 | "verify": "yarn run lint && yarn run test:cov", 6 | "verify:bail": "eslint packages && yarn run test:cov", 7 | "clean": "rm -rf coverage *.log packages/*/dist && lerna clean --yes", 8 | "lint": "eslint --fix packages", 9 | "prepublishOnly": "yarn run build && yarn run verify:bail", 10 | "postinstall": "lerna run build && lerna bootstrap --concurrency=1", 11 | "ci": "yarn run verify:bail", 12 | "test:cov": "yarn run test --coverage", 13 | "test:watch": "yarn run test --watch", 14 | "test": "jest --runInBand" 15 | }, 16 | "devDependencies": { 17 | "@babel/cli": "^7.10.5", 18 | "@babel/core": "^7.11.1", 19 | "@babel/preset-env": "^7.11.0", 20 | "babel-eslint": "^10.1.0", 21 | "babel-jest": "^26.3.0", 22 | "eslint": "^7.6.0", 23 | "eslint-config-prettier": "^6.11.0", 24 | "eslint-plugin-import": "^2.22.0", 25 | "eslint-plugin-prettier": "^3.1.4", 26 | "jest": "^26.3.0", 27 | "lerna": "^3.22.1", 28 | "prettier": "^2.0.5" 29 | }, 30 | "jest": { 31 | "collectCoverageFrom": [ 32 | "packages/**/*.js" 33 | ], 34 | "coverageReporters": [ 35 | "text", 36 | "html" 37 | ], 38 | "coveragePathIgnorePatterns": [ 39 | "/node_modules/", 40 | ".json", 41 | "/dist/" 42 | ], 43 | "testEnvironment": "node" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-cli/README.md: -------------------------------------------------------------------------------- 1 | # css-modules-flow-types-cli [![npm version](https://badge.fury.io/js/css-modules-flow-types-cli.svg)](http://badge.fury.io/js/css-modules-flow-types-cli) 2 | 3 | CLI for creating [Flow](https://flow.org/) type definitions based on [CSS Modules](https://github.com/css-modules/css-modules) files. 4 | 5 | This gives you: 6 | - auto-completing for css files in most editors 7 | - flow type safety showing usage of non existing classes 8 | 9 | 10 | ## Example 11 | 12 | Given the following css file using CSS Modules: 13 | ```css 14 | @value primary: red; 15 | 16 | .myClass { 17 | color: primary; 18 | } 19 | ``` 20 | 21 | `css-modules-flow-types` creates the following .flow file next to it: 22 | 23 | ```javascript 24 | // @flow 25 | /* This file is automatically generated by css-modules-flow-types */ 26 | declare module.exports: {| 27 | +'myClass': string; 28 | +'primary': string; 29 | |}; 30 | ``` 31 | 32 | 33 | ## Usage 34 | 35 | ```sh 36 | $ npm install --dev css-modules-flow-types-cli 37 | $ yarn install -D css-modules-flow-types-cli 38 | ``` 39 | 40 | This installs the runner as `css-modules-flow-types`. 41 | 42 | And run `css-modules-flow-types ` command. 43 | 44 | For example, if you have .css files under `src` directory, exec the following: 45 | 46 | Running, 47 | 48 | ```sh 49 | css-modules-flow-types src 50 | ``` 51 | 52 | Creates `*.css.flow` files next to all css files. 53 | 54 | ```text 55 | (your project root) 56 | - src/ 57 | | myStyle.css 58 | | myStyle.css.flow [created] 59 | ``` 60 | 61 | 62 | ## Inspiration 63 | - https://github.com/Quramy/typed-css-modules 64 | - https://github.com/Jimdo/typings-for-css-modules-loader 65 | 66 | 67 | ## License 68 | This software is released under the MIT License. 69 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-cli/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": "4" 8 | } 9 | } 10 | ] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-cli/bin/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('../dist/cli'); 3 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-modules-flow-types-cli", 3 | "version": "2.0.0", 4 | "description": "CLI for creating flow definitions from CSS Modules files", 5 | "author": "skovhus", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/skovhus/css-modules-flow-types.git" 10 | }, 11 | "main": "dist/converter.js", 12 | "bin": { 13 | "css-modules-flow-types": "bin/cli.js" 14 | }, 15 | "engines": { 16 | "node": ">=8" 17 | }, 18 | "scripts": { 19 | "build": "babel src -d dist --ignore *.test.js", 20 | "prepublishOnly": "cd ../../ && npm run prepublishOnly" 21 | }, 22 | "files": [ 23 | "bin", 24 | "dist" 25 | ], 26 | "keywords": [ 27 | "css-modules", 28 | "types", 29 | "flow" 30 | ], 31 | "dependencies": { 32 | "chalk": "^1.1.3", 33 | "css-modules-flow-types-printer": "^2.0.0", 34 | "css-modules-loader-core": "^1.0.0", 35 | "gaze": "^1.1.1", 36 | "globby": "^6.1.0", 37 | "meow": "^6.0.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-cli/src/__test__/converter.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | import { EOL, HEADER } from 'css-modules-flow-types-printer'; 3 | import Converter from '../converter'; 4 | 5 | const converter = new Converter('./fixtures', EOL.LF); 6 | 7 | it('returns sorted content from simple css', () => { 8 | return converter.convert('./example.css').then((content) => { 9 | expect(content).toBe(`${HEADER} 10 | declare module.exports: {| 11 | +'a': string, 12 | +'my-class': string, 13 | +'myClass': string, 14 | +'primary': string, 15 | +'while': string, 16 | |}; 17 | `); 18 | }); 19 | }); 20 | 21 | it('returns content from empty css files', () => { 22 | return converter.convert('./empty.css').then((content) => { 23 | expect(content).toBe(`${HEADER} 24 | declare module.exports: {| 25 | 26 | |}; 27 | `); 28 | }); 29 | }); 30 | 31 | it('rejects invalid CSS', () => { 32 | expect.assertions(1); 33 | return converter.convert('./errorCss.css').catch((err) => { 34 | expect(err.name).toBe('CssSyntaxError'); 35 | }); 36 | }); 37 | 38 | it('returns content from composing css', () => { 39 | return converter.convert('./composer.css').then((content) => { 40 | expect(content).toBe(`${HEADER} 41 | declare module.exports: {| 42 | +'root': string, 43 | |}; 44 | `); 45 | }); 46 | }); 47 | 48 | it('returns content from composing css whose has invalid import/composes', () => { 49 | return converter.convert('./invalidComposer.scss').then((content) => { 50 | expect(content).toBe(`${HEADER} 51 | declare module.exports: {| 52 | +'myClass': string, 53 | |}; 54 | `); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-cli/src/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | import path from 'path'; 5 | 6 | import chalk from 'chalk'; 7 | import gaze from 'gaze'; 8 | import globby from 'globby'; 9 | import meow from 'meow'; 10 | 11 | import Converter from './converter'; 12 | import writeFile from './writer'; 13 | 14 | const cli = meow( 15 | { 16 | description: 'Creates .flow type definition files from CSS Modules files', 17 | help: ` 18 | Usage 19 | $ css-modules-flow-types [] [options] 20 | 21 | path directory to search for CSS Modules (or concrete files to convert) 22 | 23 | Options 24 | --watch, -w Run in watch mode 25 | --extension, -e File extension (defaults to "css") 26 | --silent, -s Silences all output except errors 27 | `, 28 | inferType: true, 29 | }, 30 | { 31 | flags: { 32 | _: { 33 | type: 'string', 34 | }, 35 | extension: { 36 | alias: 'e', 37 | }, 38 | help: { 39 | alias: 'h', 40 | }, 41 | silent: { 42 | alias: 's', 43 | type: 'boolean', 44 | }, 45 | watch: { 46 | alias: 'w', 47 | type: 'boolean', 48 | }, 49 | }, 50 | } 51 | ); 52 | 53 | function detectDanlingFlowFiles(filesPattern, cssFiles) { 54 | const flowFiles = globby.sync(filesPattern + '.flow'); 55 | const cssFilesSet = new Set(cssFiles); 56 | const danglingFlowFiles = flowFiles.filter( 57 | (f) => !cssFilesSet.has(f.replace('.flow', '')) 58 | ); 59 | 60 | if (danglingFlowFiles.length > 0) { 61 | console.error( 62 | chalk.red( 63 | `Detected ${danglingFlowFiles.length} dangling .flow file(s), that can be removed:` 64 | ) 65 | ); 66 | danglingFlowFiles.forEach((f) => { 67 | console.error(chalk.red(`- ${f}`)); 68 | }); 69 | } 70 | } 71 | 72 | const main = () => { 73 | const { watch, silent } = cli.flags; 74 | 75 | if (!cli.input || cli.input.length === 0) { 76 | return cli.showHelp(); 77 | } 78 | 79 | const extension = cli.flags.extension || 'css'; 80 | 81 | const filesList = cli.input.length > 1 ? cli.input : null; 82 | const filePath = cli.input.length === 1 ? cli.input[0] : null; 83 | const filesPattern = filePath && path.join(filePath, `**/*.${extension}`); 84 | 85 | const rootDir = process.cwd(); 86 | const converter = new Converter(rootDir); 87 | 88 | function handleFile(filePath) { 89 | const f = path.resolve(filePath); 90 | converter 91 | .convert(f) 92 | .then((content) => { 93 | const outputFilePath = path.join(f + '.flow'); 94 | return writeFile(outputFilePath, content); 95 | }) 96 | .then((outputFilePath) => { 97 | if (!silent) { 98 | console.log('Wrote ' + chalk.green(outputFilePath)); 99 | } 100 | }) 101 | .catch((reason) => console.error(chalk.red('[Error] ' + reason))); 102 | } 103 | 104 | if (!watch) { 105 | const cssFiles = filesList ? filesList : globby.sync(filesPattern); 106 | cssFiles.forEach(handleFile); 107 | 108 | if (!filesList) { 109 | detectDanlingFlowFiles(filesPattern, cssFiles); 110 | } 111 | } else { 112 | if (!filePath) { 113 | console.error( 114 | chalk.red(`Watch mode requires a single path... Not ${filesList}`) 115 | ); 116 | return; 117 | } 118 | gaze(filesPattern, function (err, files) { 119 | this.on('changed', handleFile); 120 | this.on('added', handleFile); 121 | }); 122 | } 123 | }; 124 | 125 | main(); 126 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-cli/src/converter.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import printFlowDefinition, { 4 | getLineSeparator, 5 | } from 'css-modules-flow-types-printer'; 6 | import FileSystemLoader from './css-modules/fileSystemLoader'; 7 | 8 | export default class Converter { 9 | constructor(rootDir, eol) { 10 | this.loader = new FileSystemLoader(rootDir); 11 | this.eol = eol; 12 | } 13 | 14 | convert(filePath) { 15 | return new Promise((resolve, reject) => { 16 | // TODO: benchmark this (maybe this should only be cleared when watching) 17 | this.loader.tokensByFile = {}; 18 | 19 | this.loader 20 | .fetch(filePath, '/', undefined, undefined) 21 | .then((res) => { 22 | if (res) { 23 | const tokens = Object.keys(res); 24 | const content = printFlowDefinition( 25 | tokens, 26 | this.eol || getLineSeparator(tokens[0]) 27 | ); 28 | resolve(content); 29 | } else { 30 | reject(res); 31 | } 32 | }) 33 | .catch((err) => reject(err)); 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-cli/src/css-modules/fileSystemLoader.js: -------------------------------------------------------------------------------- 1 | /* 2 | Notice: 3 | 4 | This file was originally forked from: https://raw.githubusercontent.com/css-modules/css-modules-loader-core/master/src/file-system-loader.js 5 | 6 | See: 7 | https://github.com/Quramy/typed-css-modules/blob/master/src/fileSystemLoader.js 8 | */ 9 | /* this file is forked from https://raw.githubusercontent.com/css-modules/css-modules-loader-core/master/src/file-system-loader.js */ 10 | /* eslint-disable prefer-const, no-empty, prettier/prettier */ 11 | // prettier-ignore 12 | 13 | import fs from 'fs'; 14 | import path from 'path'; 15 | 16 | import Core from 'css-modules-loader-core'; 17 | 18 | export default class FileSystemLoader { 19 | constructor(root, plugins) { 20 | this.root = root; 21 | this.sources = {}; 22 | this.importNr = 0; 23 | this.core = new Core(plugins); 24 | this.tokensByFile = {}; 25 | } 26 | 27 | fetch(_newPath, relativeTo, _trace, initialContents) { 28 | let newPath = _newPath.replace(/^["']|["']$/g, ''), 29 | trace = _trace || String.fromCharCode(this.importNr++); 30 | return new Promise((resolve, reject) => { 31 | let relativeDir = path.dirname(relativeTo), 32 | rootRelativePath = path.resolve(relativeDir, newPath), 33 | fileRelativePath = path.resolve( 34 | path.join(this.root, relativeDir), 35 | newPath 36 | ); 37 | 38 | // if the path is not relative or absolute, try to resolve it in node_modules 39 | if (newPath[0] !== '.' && newPath[0] !== '/') { 40 | try { 41 | fileRelativePath = require.resolve(newPath); 42 | } catch (e) {} 43 | } 44 | 45 | if (!initialContents) { 46 | const tokens = this.tokensByFile[fileRelativePath]; 47 | if (tokens) { 48 | return resolve(tokens); 49 | } 50 | 51 | fs.readFile(fileRelativePath, 'utf-8', (err, source) => { 52 | if (err && relativeTo && relativeTo !== '/') { 53 | resolve([]); 54 | } else if (err && (!relativeTo || relativeTo === '/')) { 55 | reject(err); 56 | } else { 57 | this.core 58 | .load(source, rootRelativePath, trace, this.fetch.bind(this)) 59 | .then(({ injectableSource, exportTokens }) => { 60 | this.sources[trace] = injectableSource; 61 | this.tokensByFile[fileRelativePath] = exportTokens; 62 | resolve(exportTokens); 63 | }, reject); 64 | } 65 | }); 66 | } else { 67 | this.core 68 | .load(initialContents, rootRelativePath, trace, this.fetch.bind(this)) 69 | .then(({ injectableSource, exportTokens }) => { 70 | this.sources[trace] = injectableSource; 71 | this.tokensByFile[fileRelativePath] = exportTokens; 72 | resolve(exportTokens); 73 | }, reject); 74 | } 75 | }); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-cli/src/writer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import fs from 'fs'; 4 | 5 | export default function writeFile(outputFilePath, content) { 6 | return new Promise((resolve, reject) => { 7 | fs.writeFile(outputFilePath, content, 'utf8', (err) => { 8 | if (err) { 9 | reject(err); 10 | } else { 11 | resolve(outputFilePath); 12 | } 13 | }); 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-cli/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.14.5" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" 8 | integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== 9 | dependencies: 10 | "@babel/highlight" "^7.14.5" 11 | 12 | "@babel/helper-validator-identifier@^7.14.5": 13 | version "7.14.5" 14 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz#d0f0e277c512e0c938277faa85a3968c9a44c0e8" 15 | integrity sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg== 16 | 17 | "@babel/highlight@^7.14.5": 18 | version "7.14.5" 19 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" 20 | integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== 21 | dependencies: 22 | "@babel/helper-validator-identifier" "^7.14.5" 23 | chalk "^2.0.0" 24 | js-tokens "^4.0.0" 25 | 26 | "@types/minimist@^1.2.0": 27 | version "1.2.1" 28 | resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256" 29 | integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg== 30 | 31 | "@types/normalize-package-data@^2.4.0": 32 | version "2.4.0" 33 | resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" 34 | integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== 35 | 36 | ansi-regex@^2.0.0: 37 | version "2.1.1" 38 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 39 | 40 | ansi-styles@^2.2.1: 41 | version "2.2.1" 42 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 43 | 44 | ansi-styles@^3.2.1: 45 | version "3.2.1" 46 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 47 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 48 | dependencies: 49 | color-convert "^1.9.0" 50 | 51 | array-union@^1.0.1: 52 | version "1.0.2" 53 | resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" 54 | dependencies: 55 | array-uniq "^1.0.1" 56 | 57 | array-uniq@^1.0.1: 58 | version "1.0.3" 59 | resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" 60 | 61 | arrify@^1.0.1: 62 | version "1.0.1" 63 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" 64 | integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= 65 | 66 | balanced-match@^1.0.0: 67 | version "1.0.2" 68 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 69 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 70 | 71 | brace-expansion@^1.1.7: 72 | version "1.1.11" 73 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 74 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 75 | dependencies: 76 | balanced-match "^1.0.0" 77 | concat-map "0.0.1" 78 | 79 | camelcase-keys@^6.2.2: 80 | version "6.2.2" 81 | resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" 82 | integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== 83 | dependencies: 84 | camelcase "^5.3.1" 85 | map-obj "^4.0.0" 86 | quick-lru "^4.0.1" 87 | 88 | camelcase@^5.0.0, camelcase@^5.3.1: 89 | version "5.3.1" 90 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" 91 | integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== 92 | 93 | chalk@^1.1.3: 94 | version "1.1.3" 95 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 96 | dependencies: 97 | ansi-styles "^2.2.1" 98 | escape-string-regexp "^1.0.2" 99 | has-ansi "^2.0.0" 100 | strip-ansi "^3.0.0" 101 | supports-color "^2.0.0" 102 | 103 | chalk@^2.0.0: 104 | version "2.4.2" 105 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 106 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 107 | dependencies: 108 | ansi-styles "^3.2.1" 109 | escape-string-regexp "^1.0.5" 110 | supports-color "^5.3.0" 111 | 112 | color-convert@^1.9.0: 113 | version "1.9.3" 114 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 115 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 116 | dependencies: 117 | color-name "1.1.3" 118 | 119 | color-name@1.1.3: 120 | version "1.1.3" 121 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 122 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 123 | 124 | concat-map@0.0.1: 125 | version "0.0.1" 126 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 127 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 128 | 129 | css-modules-flow-types-printer@^2.0.0: 130 | version "2.0.0" 131 | resolved "https://registry.yarnpkg.com/css-modules-flow-types-printer/-/css-modules-flow-types-printer-2.0.0.tgz#f3308c4a81169dd9a933ccb0e76e3a49bf58c4dc" 132 | integrity sha512-OJXluvPgEzifS0IO/cSaHrVpZL9Cz1wqYv58WIpD4tB8so+a43xhnoiZWx28Rr6zyqQdsW5IoS5aCPZl66AKFg== 133 | 134 | css-modules-loader-core@^1.0.0: 135 | version "1.1.0" 136 | resolved "https://registry.yarnpkg.com/css-modules-loader-core/-/css-modules-loader-core-1.1.0.tgz#5908668294a1becd261ae0a4ce21b0b551f21d16" 137 | dependencies: 138 | icss-replace-symbols "1.1.0" 139 | postcss "6.0.1" 140 | postcss-modules-extract-imports "1.1.0" 141 | postcss-modules-local-by-default "1.2.0" 142 | postcss-modules-scope "1.1.0" 143 | postcss-modules-values "1.3.0" 144 | 145 | css-selector-tokenizer@^0.7.0: 146 | version "0.7.0" 147 | resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86" 148 | dependencies: 149 | cssesc "^0.1.0" 150 | fastparse "^1.1.1" 151 | regexpu-core "^1.0.0" 152 | 153 | cssesc@^0.1.0: 154 | version "0.1.0" 155 | resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4" 156 | 157 | decamelize-keys@^1.1.0: 158 | version "1.1.0" 159 | resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" 160 | integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= 161 | dependencies: 162 | decamelize "^1.1.0" 163 | map-obj "^1.0.0" 164 | 165 | decamelize@^1.1.0, decamelize@^1.2.0: 166 | version "1.2.0" 167 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 168 | integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= 169 | 170 | error-ex@^1.3.1: 171 | version "1.3.2" 172 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 173 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 174 | dependencies: 175 | is-arrayish "^0.2.1" 176 | 177 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 178 | version "1.0.5" 179 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 180 | 181 | fastparse@^1.1.1: 182 | version "1.1.1" 183 | resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" 184 | 185 | find-up@^4.1.0: 186 | version "4.1.0" 187 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 188 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 189 | dependencies: 190 | locate-path "^5.0.0" 191 | path-exists "^4.0.0" 192 | 193 | fs.realpath@^1.0.0: 194 | version "1.0.0" 195 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 196 | 197 | function-bind@^1.1.1: 198 | version "1.1.1" 199 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 200 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 201 | 202 | gaze@^1.1.1: 203 | version "1.1.2" 204 | resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.2.tgz#847224677adb8870d679257ed3388fdb61e40105" 205 | dependencies: 206 | globule "^1.0.0" 207 | 208 | glob@^7.0.3, glob@~7.1.1: 209 | version "7.1.2" 210 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 211 | dependencies: 212 | fs.realpath "^1.0.0" 213 | inflight "^1.0.4" 214 | inherits "2" 215 | minimatch "^3.0.4" 216 | once "^1.3.0" 217 | path-is-absolute "^1.0.0" 218 | 219 | globby@^6.1.0: 220 | version "6.1.0" 221 | resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" 222 | dependencies: 223 | array-union "^1.0.1" 224 | glob "^7.0.3" 225 | object-assign "^4.0.1" 226 | pify "^2.0.0" 227 | pinkie-promise "^2.0.0" 228 | 229 | globule@^1.0.0: 230 | version "1.2.0" 231 | resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.0.tgz#1dc49c6822dd9e8a2fa00ba2a295006e8664bd09" 232 | dependencies: 233 | glob "~7.1.1" 234 | lodash "~4.17.4" 235 | minimatch "~3.0.2" 236 | 237 | hard-rejection@^2.1.0: 238 | version "2.1.0" 239 | resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" 240 | integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== 241 | 242 | has-ansi@^2.0.0: 243 | version "2.0.0" 244 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 245 | dependencies: 246 | ansi-regex "^2.0.0" 247 | 248 | has-flag@^1.0.0: 249 | version "1.0.0" 250 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" 251 | 252 | has-flag@^3.0.0: 253 | version "3.0.0" 254 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 255 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 256 | 257 | has@^1.0.3: 258 | version "1.0.3" 259 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 260 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 261 | dependencies: 262 | function-bind "^1.1.1" 263 | 264 | hosted-git-info@^2.1.4: 265 | version "2.8.9" 266 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" 267 | integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== 268 | 269 | icss-replace-symbols@1.1.0, icss-replace-symbols@^1.1.0: 270 | version "1.1.0" 271 | resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" 272 | 273 | indent-string@^4.0.0: 274 | version "4.0.0" 275 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" 276 | integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== 277 | 278 | inflight@^1.0.4: 279 | version "1.0.6" 280 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 281 | dependencies: 282 | once "^1.3.0" 283 | wrappy "1" 284 | 285 | inherits@2: 286 | version "2.0.3" 287 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 288 | 289 | is-arrayish@^0.2.1: 290 | version "0.2.1" 291 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 292 | 293 | is-core-module@^2.2.0: 294 | version "2.4.0" 295 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1" 296 | integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A== 297 | dependencies: 298 | has "^1.0.3" 299 | 300 | is-plain-obj@^1.1.0: 301 | version "1.1.0" 302 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" 303 | integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= 304 | 305 | js-tokens@^4.0.0: 306 | version "4.0.0" 307 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 308 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 309 | 310 | jsesc@~0.5.0: 311 | version "0.5.0" 312 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" 313 | 314 | json-parse-even-better-errors@^2.3.0: 315 | version "2.3.1" 316 | resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" 317 | integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== 318 | 319 | kind-of@^6.0.3: 320 | version "6.0.3" 321 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" 322 | integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== 323 | 324 | lines-and-columns@^1.1.6: 325 | version "1.1.6" 326 | resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" 327 | integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= 328 | 329 | locate-path@^5.0.0: 330 | version "5.0.0" 331 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 332 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 333 | dependencies: 334 | p-locate "^4.1.0" 335 | 336 | lodash@~4.17.4: 337 | version "4.17.21" 338 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 339 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 340 | 341 | map-obj@^1.0.0: 342 | version "1.0.1" 343 | resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" 344 | 345 | map-obj@^4.0.0: 346 | version "4.2.1" 347 | resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.2.1.tgz#e4ea399dbc979ae735c83c863dd31bdf364277b7" 348 | integrity sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ== 349 | 350 | meow@^6.0.0: 351 | version "6.1.1" 352 | resolved "https://registry.yarnpkg.com/meow/-/meow-6.1.1.tgz#1ad64c4b76b2a24dfb2f635fddcadf320d251467" 353 | integrity sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg== 354 | dependencies: 355 | "@types/minimist" "^1.2.0" 356 | camelcase-keys "^6.2.2" 357 | decamelize-keys "^1.1.0" 358 | hard-rejection "^2.1.0" 359 | minimist-options "^4.0.2" 360 | normalize-package-data "^2.5.0" 361 | read-pkg-up "^7.0.1" 362 | redent "^3.0.0" 363 | trim-newlines "^3.0.0" 364 | type-fest "^0.13.1" 365 | yargs-parser "^18.1.3" 366 | 367 | min-indent@^1.0.0: 368 | version "1.0.1" 369 | resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" 370 | integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== 371 | 372 | minimatch@^3.0.4, minimatch@~3.0.2: 373 | version "3.0.8" 374 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" 375 | integrity sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q== 376 | dependencies: 377 | brace-expansion "^1.1.7" 378 | 379 | minimist-options@^4.0.2: 380 | version "4.1.0" 381 | resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" 382 | integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== 383 | dependencies: 384 | arrify "^1.0.1" 385 | is-plain-obj "^1.1.0" 386 | kind-of "^6.0.3" 387 | 388 | normalize-package-data@^2.5.0: 389 | version "2.5.0" 390 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" 391 | integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== 392 | dependencies: 393 | hosted-git-info "^2.1.4" 394 | resolve "^1.10.0" 395 | semver "2 || 3 || 4 || 5" 396 | validate-npm-package-license "^3.0.1" 397 | 398 | object-assign@^4.0.1: 399 | version "4.1.1" 400 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 401 | 402 | once@^1.3.0: 403 | version "1.4.0" 404 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 405 | dependencies: 406 | wrappy "1" 407 | 408 | p-limit@^2.2.0: 409 | version "2.3.0" 410 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 411 | integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 412 | dependencies: 413 | p-try "^2.0.0" 414 | 415 | p-locate@^4.1.0: 416 | version "4.1.0" 417 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 418 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 419 | dependencies: 420 | p-limit "^2.2.0" 421 | 422 | p-try@^2.0.0: 423 | version "2.2.0" 424 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 425 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 426 | 427 | parse-json@^5.0.0: 428 | version "5.2.0" 429 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" 430 | integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== 431 | dependencies: 432 | "@babel/code-frame" "^7.0.0" 433 | error-ex "^1.3.1" 434 | json-parse-even-better-errors "^2.3.0" 435 | lines-and-columns "^1.1.6" 436 | 437 | path-exists@^4.0.0: 438 | version "4.0.0" 439 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 440 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 441 | 442 | path-is-absolute@^1.0.0: 443 | version "1.0.1" 444 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 445 | 446 | path-parse@^1.0.6: 447 | version "1.0.7" 448 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 449 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 450 | 451 | pify@^2.0.0: 452 | version "2.3.0" 453 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 454 | 455 | pinkie-promise@^2.0.0: 456 | version "2.0.1" 457 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 458 | dependencies: 459 | pinkie "^2.0.0" 460 | 461 | pinkie@^2.0.0: 462 | version "2.0.4" 463 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 464 | 465 | postcss-modules-extract-imports@1.1.0: 466 | version "1.1.0" 467 | resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz#b614c9720be6816eaee35fb3a5faa1dba6a05ddb" 468 | dependencies: 469 | postcss "^6.0.1" 470 | 471 | postcss-modules-local-by-default@1.2.0: 472 | version "1.2.0" 473 | resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" 474 | dependencies: 475 | css-selector-tokenizer "^0.7.0" 476 | postcss "^6.0.1" 477 | 478 | postcss-modules-scope@1.1.0: 479 | version "1.1.0" 480 | resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" 481 | dependencies: 482 | css-selector-tokenizer "^0.7.0" 483 | postcss "^6.0.1" 484 | 485 | postcss-modules-values@1.3.0: 486 | version "1.3.0" 487 | resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" 488 | dependencies: 489 | icss-replace-symbols "^1.1.0" 490 | postcss "^6.0.1" 491 | 492 | postcss@6.0.1, postcss@^6.0.1: 493 | version "6.0.1" 494 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.1.tgz#000dbd1f8eef217aa368b9a212c5fc40b2a8f3f2" 495 | dependencies: 496 | chalk "^1.1.3" 497 | source-map "^0.5.6" 498 | supports-color "^3.2.3" 499 | 500 | quick-lru@^4.0.1: 501 | version "4.0.1" 502 | resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" 503 | integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== 504 | 505 | read-pkg-up@^7.0.1: 506 | version "7.0.1" 507 | resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" 508 | integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== 509 | dependencies: 510 | find-up "^4.1.0" 511 | read-pkg "^5.2.0" 512 | type-fest "^0.8.1" 513 | 514 | read-pkg@^5.2.0: 515 | version "5.2.0" 516 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" 517 | integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== 518 | dependencies: 519 | "@types/normalize-package-data" "^2.4.0" 520 | normalize-package-data "^2.5.0" 521 | parse-json "^5.0.0" 522 | type-fest "^0.6.0" 523 | 524 | redent@^3.0.0: 525 | version "3.0.0" 526 | resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" 527 | integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== 528 | dependencies: 529 | indent-string "^4.0.0" 530 | strip-indent "^3.0.0" 531 | 532 | regenerate@^1.2.1: 533 | version "1.3.2" 534 | resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" 535 | 536 | regexpu-core@^1.0.0: 537 | version "1.0.0" 538 | resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" 539 | dependencies: 540 | regenerate "^1.2.1" 541 | regjsgen "^0.2.0" 542 | regjsparser "^0.1.4" 543 | 544 | regjsgen@^0.2.0: 545 | version "0.2.0" 546 | resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" 547 | 548 | regjsparser@^0.1.4: 549 | version "0.1.5" 550 | resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" 551 | dependencies: 552 | jsesc "~0.5.0" 553 | 554 | resolve@^1.10.0: 555 | version "1.20.0" 556 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" 557 | integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== 558 | dependencies: 559 | is-core-module "^2.2.0" 560 | path-parse "^1.0.6" 561 | 562 | "semver@2 || 3 || 4 || 5": 563 | version "5.3.0" 564 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" 565 | 566 | source-map@^0.5.6: 567 | version "0.5.6" 568 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" 569 | 570 | spdx-correct@~1.0.0: 571 | version "1.0.2" 572 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" 573 | dependencies: 574 | spdx-license-ids "^1.0.2" 575 | 576 | spdx-expression-parse@~1.0.0: 577 | version "1.0.4" 578 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" 579 | 580 | spdx-license-ids@^1.0.2: 581 | version "1.2.2" 582 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" 583 | 584 | strip-ansi@^3.0.0: 585 | version "3.0.1" 586 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 587 | dependencies: 588 | ansi-regex "^2.0.0" 589 | 590 | strip-indent@^3.0.0: 591 | version "3.0.0" 592 | resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" 593 | integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== 594 | dependencies: 595 | min-indent "^1.0.0" 596 | 597 | supports-color@^2.0.0: 598 | version "2.0.0" 599 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 600 | 601 | supports-color@^3.2.3: 602 | version "3.2.3" 603 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" 604 | dependencies: 605 | has-flag "^1.0.0" 606 | 607 | supports-color@^5.3.0: 608 | version "5.5.0" 609 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 610 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 611 | dependencies: 612 | has-flag "^3.0.0" 613 | 614 | trim-newlines@^3.0.0: 615 | version "3.0.1" 616 | resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" 617 | integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== 618 | 619 | type-fest@^0.13.1: 620 | version "0.13.1" 621 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" 622 | integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== 623 | 624 | type-fest@^0.6.0: 625 | version "0.6.0" 626 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" 627 | integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== 628 | 629 | type-fest@^0.8.1: 630 | version "0.8.1" 631 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" 632 | integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== 633 | 634 | validate-npm-package-license@^3.0.1: 635 | version "3.0.1" 636 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" 637 | dependencies: 638 | spdx-correct "~1.0.0" 639 | spdx-expression-parse "~1.0.0" 640 | 641 | wrappy@1: 642 | version "1.0.2" 643 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 644 | 645 | yargs-parser@^18.1.3: 646 | version "18.1.3" 647 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" 648 | integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== 649 | dependencies: 650 | camelcase "^5.0.0" 651 | decamelize "^1.2.0" 652 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-loader/README.md: -------------------------------------------------------------------------------- 1 | # css-modules-flow-types-loader [![npm version](https://badge.fury.io/js/css-modules-flow-types-loader.svg)](http://badge.fury.io/js/css-modules-flow-types-loader) 2 | 3 | Webpack loader for creating [Flow](https://flow.org/) type definitions based on [CSS Modules](https://github.com/css-modules/css-modules) files. 4 | 5 | This gives you: 6 | - auto-completing for css files in most editors 7 | - flow type safety showing usage of non existing classes 8 | 9 | 10 | ## Example 11 | 12 | Given the following css file using CSS Modules: 13 | ```css 14 | @value primary: red; 15 | 16 | .myClass { 17 | color: primary; 18 | } 19 | ``` 20 | 21 | `css-modules-flow-types` creates the following .flow file next to it: 22 | 23 | ```javascript 24 | // @flow 25 | /* This file is automatically generated by css-modules-flow-types */ 26 | declare module.exports: {| 27 | +'myClass': string; 28 | +'primary': string; 29 | |}; 30 | ``` 31 | 32 | 33 | ## Usage 34 | 35 | The `css-modules-flow-types-loader` need to be added right after after `style-loader`: 36 | 37 | ```sh 38 | $ npm install --dev css-modules-flow-types-loader 39 | $ yarn install -D css-modules-flow-types-loader 40 | ``` 41 | 42 | ```javascript 43 | { 44 | test: /\.css$/, // or the file format you are using for your CSS Modules 45 | use: [ 46 | 'style-loader', 47 | 'css-modules-flow-types-loader', 48 | // Other loaders like css-loader after this: 49 | { 50 | ... 51 | } 52 | ] 53 | } 54 | ``` 55 | 56 | 57 | ## Inspiration 58 | - https://github.com/Quramy/typed-css-modules 59 | - https://github.com/Jimdo/typings-for-css-modules-loader 60 | 61 | 62 | ## License 63 | This software is released under the MIT License. 64 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-loader/__mocks__/fs.js: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | 3 | const fs = jest.genMockFromModule('fs'); 4 | module.exports = fs; 5 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-loader/__test__/index.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | jest.mock('fs'); 3 | 4 | import fs from 'fs'; 5 | import { HEADER } from 'css-modules-flow-types-printer'; 6 | import loader from '../index'; 7 | 8 | const getStyleLoaderOutput = (exports = '') => ` 9 | // imports 10 | 11 | 12 | // module 13 | exports.push([module.id, ".btn__app-components-Page-styles__2BmYx {\n background: #FFF;\n}\n", "", {"version":3,"sources":["/./app/components/Page/styles.css"],"names":[],"mappings":"AAAA;EACE,iBAAiB;CAClB","file":"styles.css","sourcesContent":[".btn {\n background: #FFF;\n}\n"],"sourceRoot":"webpack://"}]); 14 | 15 | // exports 16 | ${exports} 17 | `; 18 | 19 | const STYLE_LOADER_OUTPUT_LEGACY = getStyleLoaderOutput(` 20 | exports.locals = { 21 | "btn": "btn__app-components-Page-styles__2BmYx" 22 | }; 23 | `); 24 | 25 | const STYLE_LOADER_OUTPUT = getStyleLoaderOutput(` 26 | ___CSS_LOADER_EXPORT___.locals = { 27 | "btn": "btn__app-components-Page-styles__2BmYx" 28 | }; 29 | `); 30 | 31 | const STYLE_LOADER_OUTPUT_WITH_JS = getStyleLoaderOutput(` 32 | ___CSS_LOADER_EXPORT___.locals = { 33 | "foo": "bar" + require("-!css-loader!styles/baz.scss").locals["xyz"] + "", 34 | "foo2": "bar" + new String('lorem lipsum') + "" 35 | }; 36 | `); 37 | 38 | const EMPTY_STYLE_LOADER_OUTPUT = getStyleLoaderOutput(); 39 | 40 | describe('webpack loader', () => { 41 | beforeEach(() => { 42 | fs.writeFile.mockReset(); 43 | }); 44 | 45 | it('emits a css.flow file for a non-empty CSS file with css-loader < v4', () => { 46 | loader.call( 47 | { 48 | resourcePath: 'test.css', 49 | }, 50 | STYLE_LOADER_OUTPUT_LEGACY 51 | ); 52 | 53 | expect(fs.writeFile.mock.calls.length).toBe(1); 54 | expect(fs.writeFile.mock.calls[0][0]).toBe('test.css.flow'); 55 | 56 | expect(fs.writeFile.mock.calls[0][1]).toBe( 57 | `${HEADER} 58 | declare module.exports: {| 59 | +'btn': string, 60 | |}; 61 | ` 62 | ); 63 | }); 64 | 65 | it('emits a css.flow file for a non-empty CSS file with css-loader v4', () => { 66 | loader.call( 67 | { 68 | resourcePath: 'test.css', 69 | }, 70 | STYLE_LOADER_OUTPUT 71 | ); 72 | 73 | expect(fs.writeFile.mock.calls.length).toBe(1); 74 | expect(fs.writeFile.mock.calls[0][0]).toBe('test.css.flow'); 75 | 76 | expect(fs.writeFile.mock.calls[0][1]).toBe( 77 | `${HEADER} 78 | declare module.exports: {| 79 | +'btn': string, 80 | |}; 81 | ` 82 | ); 83 | }); 84 | 85 | it('emits a css.flow file for an empty css file', () => { 86 | loader.call( 87 | { 88 | resourcePath: 'test.css', 89 | }, 90 | EMPTY_STYLE_LOADER_OUTPUT 91 | ); 92 | 93 | expect(fs.writeFile.mock.calls.length).toBe(1); 94 | expect(fs.writeFile.mock.calls[0][1]).toBe( 95 | `${HEADER} 96 | declare module.exports: {| 97 | 98 | |}; 99 | ` 100 | ); 101 | }); 102 | 103 | it('returns same content as given', () => { 104 | const emitFile = jest.fn(); 105 | const returnedContent = loader.call( 106 | { 107 | resourcePath: 'test.css', 108 | emitFile, 109 | }, 110 | STYLE_LOADER_OUTPUT 111 | ); 112 | expect(returnedContent).toBe(STYLE_LOADER_OUTPUT); 113 | }); 114 | 115 | it('does not fail on arbitrary javascript in the ICSS value', () => { 116 | loader.call({ resourcePath: 'test.css' }, STYLE_LOADER_OUTPUT_WITH_JS); 117 | 118 | expect(fs.writeFile.mock.calls[0][1]).toBe( 119 | `${HEADER} 120 | declare module.exports: {| 121 | +'foo': string, 122 | +'foo2': string, 123 | |}; 124 | ` 125 | ); 126 | }); 127 | }); 128 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-loader/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": "4" 8 | } 9 | } 10 | ] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-loader/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import fs from 'fs'; 4 | import printFlowDefinition, { 5 | getLineSeparator, 6 | } from 'css-modules-flow-types-printer'; 7 | 8 | function getTokens(content) { 9 | const tokens = []; 10 | 11 | // Only `locals` export is desired 12 | // css-loader v4 uses ___CSS_LOADER_EXPORT___.locals 13 | // css-loader v3 used exports.locals 14 | const locals = content.match( 15 | /(?:exports|___CSS_LOADER_EXPORT___)\.locals = ([\s\S]*);/ 16 | ); 17 | 18 | if (!locals) return tokens; 19 | let match; 20 | 21 | // RegExp.exec is state-full, so we need to initialize new one for each run 22 | const re = /"(.*?)":.*\n/g; 23 | while ((match = re.exec(locals[1])) !== null) tokens.push(match[1]); 24 | 25 | return tokens; 26 | } 27 | 28 | module.exports = function cssModulesFlowTypesLoader(content) { 29 | const tokens = getTokens(content); 30 | 31 | // NOTE: We cannot use .emitFile as people might use this with devServer 32 | // (e.g. in memory storage). 33 | const outputPath = this.resourcePath + '.flow'; 34 | fs.writeFile( 35 | outputPath, 36 | printFlowDefinition(tokens, getLineSeparator(content)), 37 | {}, 38 | function () {} 39 | ); 40 | 41 | return content; 42 | }; 43 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-loader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-modules-flow-types-loader", 3 | "version": "2.0.0", 4 | "description": "Webpack loader creating Flow type definitions from CSS Modules files", 5 | "author": "skovhus", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/skovhus/css-modules-flow-types.git" 10 | }, 11 | "main": "dist/index.js", 12 | "engines": { 13 | "node": ">=8" 14 | }, 15 | "scripts": { 16 | "build": "babel *.js -d dist --ignore *.test.js", 17 | "prepublishOnly": "cd ../../ && npm run prepublishOnly" 18 | }, 19 | "files": [ 20 | "dist" 21 | ], 22 | "keywords": [ 23 | "css-modules", 24 | "types", 25 | "flow", 26 | "webpack", 27 | "webpack loader" 28 | ], 29 | "dependencies": { 30 | "css-modules-flow-types-printer": "^2.0.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-printer/README.md: -------------------------------------------------------------------------------- 1 | # css-modules-flow-types-printer [![npm version](https://badge.fury.io/js/css-modules-flow-types-printer.svg)](http://badge.fury.io/js/css-modules-flow-types-printer) 2 | 3 | Just a small printer taking [CSS Modules](https://github.com/css-modules/css-modules) tokens 4 | and prints out [Flow](https://flow.org/) type definitions. 5 | 6 | See usage of this package at https://github.com/skovhus/css-modules-flow-types 7 | 8 | 9 | ## License 10 | This software is released under the MIT License. 11 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-printer/__test__/index.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-env jest */ 2 | import printer, { EOL, HEADER } from '../index'; 3 | 4 | describe('printer', () => { 5 | it('prints given tokens', () => { 6 | const result = printer(['btn1', 'btn2'], EOL.LF); 7 | expect(result).toBe( 8 | `${HEADER} 9 | declare module.exports: {| 10 | +'btn1': string, 11 | +'btn2': string, 12 | |}; 13 | ` 14 | ); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-printer/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": "4" 8 | } 9 | } 10 | ] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-printer/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import os from 'os'; 4 | 5 | export const HEADER = `// @flow strict 6 | /* This file is automatically generated by css-modules-flow-types */`; 7 | 8 | export const EOL = { 9 | LF: '\n', 10 | CRLF: '\r\n', 11 | }; 12 | 13 | export function getLineSeparator(content) { 14 | if (typeof content !== 'string') return os.EOL; 15 | if (content.includes(EOL.CRLF)) return EOL.CRLF; 16 | if (content.includes(EOL.LF)) return EOL.LF; 17 | return os.EOL; 18 | } 19 | 20 | export default function printFlowDefinition( 21 | tokensArray, 22 | eol = os.EOL, 23 | indent = ' ' 24 | ) { 25 | const props = tokensArray 26 | .sort() 27 | .map((key) => `${indent}+'${key}': string,`) 28 | .join(eol); 29 | 30 | return `${HEADER} 31 | declare module.exports: {| 32 | ${props} 33 | |}; 34 | `; 35 | } 36 | -------------------------------------------------------------------------------- /packages/css-modules-flow-types-printer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-modules-flow-types-printer", 3 | "version": "2.0.0", 4 | "description": "Prints CSS Modules tokens as a flow definition", 5 | "author": "skovhus", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/skovhus/css-modules-flow-types.git" 10 | }, 11 | "main": "dist/index.js", 12 | "engines": { 13 | "node": ">=8" 14 | }, 15 | "scripts": { 16 | "build": "babel *.js -d dist --ignore *.test.js", 17 | "prepublishOnly": "cd ../../ && npm run prepublishOnly" 18 | }, 19 | "files": [ 20 | "dist" 21 | ], 22 | "keywords": [ 23 | "css-modules", 24 | "types", 25 | "flow", 26 | "printer" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /publish.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | version=$(cat lerna.json | jq -r .version) 6 | tag="v${version}" 7 | 8 | publishedVersion=$(yarn info css-modules-flow-types-cli --json | jq -r .data.\"dist-tags\".latest) 9 | 10 | if [ "$version" = "$publishedVersion" ]; then 11 | echo "Newest version is already deployed." 12 | exit 0 13 | fi 14 | 15 | yarn install 16 | yarn run verify:bail 17 | 18 | # Until we enforce semantic commits (and can use lerna publish), we need to publish in the right order 19 | cd packages/css-modules-flow-types-printer && npm publish && cd ../../ 20 | cd packages/css-modules-flow-types-cli && npm publish && cd ../../ 21 | cd packages/css-modules-flow-types-loader && npm publish && cd ../../ 22 | 23 | git tag -a "${tag}" -m "${tag}" 24 | git push origin "${tag}" 25 | --------------------------------------------------------------------------------