happy-css-modules 2.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/bin/hcm.js +0 -1
  2. package/dist/cli.js +7 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/cli.test.js +5 -0
  5. package/dist/cli.test.js.map +1 -1
  6. package/dist/config.d.ts +1 -0
  7. package/dist/config.js +2 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/emitter/dts.d.ts +2 -1
  10. package/dist/emitter/dts.js +10 -3
  11. package/dist/emitter/dts.js.map +1 -1
  12. package/dist/emitter/dts.test.js +4 -1
  13. package/dist/emitter/dts.test.js.map +1 -1
  14. package/dist/emitter/index.d.ts +12 -3
  15. package/dist/emitter/index.js +7 -5
  16. package/dist/emitter/index.js.map +1 -1
  17. package/dist/emitter/source-map.d.ts +2 -1
  18. package/dist/emitter/source-map.js +3 -2
  19. package/dist/emitter/source-map.js.map +1 -1
  20. package/dist/emitter/source-map.test.js +4 -1
  21. package/dist/emitter/source-map.test.js.map +1 -1
  22. package/dist/library/source-map/index.d.ts +1 -1
  23. package/dist/locator/index.d.ts +4 -4
  24. package/dist/locator/postcss.d.ts +3 -3
  25. package/dist/locator/postcss.js +4 -1
  26. package/dist/locator/postcss.js.map +1 -1
  27. package/dist/locator/postcss.test.js +6 -0
  28. package/dist/locator/postcss.test.js.map +1 -1
  29. package/dist/logger.d.ts +1 -1
  30. package/dist/resolver/index.d.ts +3 -3
  31. package/dist/resolver/webpack-resolver.d.ts +1 -1
  32. package/dist/runner.d.ts +12 -3
  33. package/dist/runner.js +3 -1
  34. package/dist/runner.js.map +1 -1
  35. package/dist/runner.test.js +4 -0
  36. package/dist/runner.test.js.map +1 -1
  37. package/dist/test-util/jest/resolver.d.cts +1 -15
  38. package/dist/test-util/tsserver.d.ts +1 -1
  39. package/dist/test-util/tsserver.js.map +1 -1
  40. package/dist/test-util/util.d.ts +3 -3
  41. package/dist/transformer/index.d.ts +4 -4
  42. package/dist/transformer/postcss-transformer.d.ts +1 -1
  43. package/dist/transformer/postcss-transformer.js +2 -2
  44. package/dist/transformer/postcss-transformer.js.map +1 -1
  45. package/dist/util.test.js +1 -2
  46. package/dist/util.test.js.map +1 -1
  47. package/package.json +10 -53
  48. package/src/cli.test.ts +5 -0
  49. package/src/cli.ts +7 -0
  50. package/src/config.ts +1 -0
  51. package/src/emitter/dts.test.ts +4 -1
  52. package/src/emitter/dts.ts +9 -3
  53. package/src/emitter/index.ts +16 -4
  54. package/src/emitter/source-map.test.ts +4 -1
  55. package/src/emitter/source-map.ts +3 -2
  56. package/src/locator/postcss.test.ts +10 -0
  57. package/src/locator/postcss.ts +5 -1
  58. package/src/runner.test.ts +6 -0
  59. package/src/runner.ts +16 -1
  60. package/src/test-util/tsserver.ts +14 -13
  61. package/src/transformer/postcss-transformer.ts +2 -2
  62. package/src/util.test.ts +1 -2
  63. package/LICENSE.txt +0 -23
  64. package/README.md +0 -277
package/src/runner.ts CHANGED
@@ -7,6 +7,7 @@ import AwaitLock from 'await-lock';
7
7
  import chalk from 'chalk';
8
8
  import * as chokidar from 'chokidar';
9
9
  import _glob from 'glob';
10
+ import { DEFAULT_ARBITRARY_EXTENSIONS } from './config.js';
10
11
  import { isGeneratedFilesExist, emitGeneratedFiles } from './emitter/index.js';
11
12
  import { Locator } from './locator/index.js';
12
13
  import { Logger } from './logger.js';
@@ -26,6 +27,10 @@ export type LocalsConvention = 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashe
26
27
  export interface RunnerOptions {
27
28
  pattern: string;
28
29
  watch?: boolean | undefined;
30
+ /**
31
+ * Style of exported class names.
32
+ * @default undefined
33
+ */
29
34
  localsConvention?: LocalsConvention | undefined;
30
35
  declarationMap?: boolean | undefined;
31
36
  transformer?: Transformer | undefined;
@@ -55,6 +60,11 @@ export interface RunnerOptions {
55
60
  * @example '/home/user/repository/src'
56
61
  */
57
62
  postcssConfig?: string | undefined;
63
+ /**
64
+ * Generate `.d.css.ts` instead of `.css.d.ts`.
65
+ * @default false
66
+ */
67
+ arbitraryExtensions?: boolean | undefined;
58
68
  /**
59
69
  * Only generate .d.ts and .d.ts.map for changed files.
60
70
  * @default true
@@ -126,7 +136,11 @@ export async function run(options: RunnerOptions): Promise<Watcher | void> {
126
136
  await lock.acquireAsync();
127
137
 
128
138
  try {
129
- const _isGeneratedFilesExist = await isGeneratedFilesExist(filePath, options.declarationMap);
139
+ const _isGeneratedFilesExist = await isGeneratedFilesExist(
140
+ filePath,
141
+ options.declarationMap,
142
+ options.arbitraryExtensions ?? DEFAULT_ARBITRARY_EXTENSIONS,
143
+ );
130
144
  const _isChangedFile = await isChangedFile(filePath);
131
145
  // Generate .d.ts and .d.ts.map only when the file has been updated.
132
146
  // However, if .d.ts or .d.ts.map has not yet been generated, always generate.
@@ -142,6 +156,7 @@ export async function run(options: RunnerOptions): Promise<Watcher | void> {
142
156
  emitDeclarationMap: options.declarationMap,
143
157
  dtsFormatOptions: {
144
158
  localsConvention: options.localsConvention,
159
+ arbitraryExtensions: options.arbitraryExtensions,
145
160
  },
146
161
  isExternalFile,
147
162
  });
@@ -7,9 +7,8 @@ import serverHarness from '@typescript/server-harness';
7
7
  import _glob from 'glob';
8
8
  import { resolve } from 'import-meta-resolve';
9
9
  import lineColumn from 'line-column';
10
- import type { UpdateOpenRequest, DefinitionResponse, DefinitionRequest } from 'typescript/lib/protocol.js';
10
+ import type { server } from 'typescript/lib/tsserverlibrary.js';
11
11
  import { getFixturePath } from './util.js';
12
-
13
12
  const glob = promisify(_glob);
14
13
 
15
14
  async function writeFile(path: string, content: string): Promise<void> {
@@ -68,7 +67,7 @@ export async function createTSServer() {
68
67
  const results: { identifier: string; definitions: Definition[] }[] = [];
69
68
 
70
69
  for (let i = 0; i < identifiers.length; i++) {
71
- const response: DefinitionResponse = await server.message({
70
+ const response: server.protocol.DefinitionResponse = await server.message({
72
71
  seq: 0,
73
72
  type: 'request',
74
73
  command: 'definition',
@@ -77,7 +76,7 @@ export async function createTSServer() {
77
76
  line: i + 2, // line, 1-based
78
77
  offset: 8, // column, 1-based
79
78
  },
80
- } as DefinitionRequest);
79
+ } as server.protocol.DefinitionRequest);
81
80
  const definitions: Definition[] = response.body!.map((definition) => {
82
81
  const { file, start, end } = definition;
83
82
  const fileContent = readFileSync(file, 'utf-8');
@@ -100,7 +99,7 @@ export async function createTSServer() {
100
99
 
101
100
  await this.refreshCache();
102
101
 
103
- const response: DefinitionResponse = await server.message({
102
+ const response: server.protocol.DefinitionResponse = await server.message({
104
103
  seq: 0,
105
104
  type: 'request',
106
105
  command: 'definition',
@@ -109,7 +108,7 @@ export async function createTSServer() {
109
108
  line: 1, // line, 1-based
110
109
  offset: 20, // column, 1-based
111
110
  },
112
- } as DefinitionRequest);
111
+ } as server.protocol.DefinitionRequest);
113
112
  const definitions: Definition[] = response.body!.map((definition) => {
114
113
  const { file, start, end } = definition;
115
114
  const fileContent = readFileSync(file, 'utf-8');
@@ -127,12 +126,14 @@ export async function createTSServer() {
127
126
 
128
127
  const fixtureFilePaths = await glob(getFixturePath('/**/*.ts'), { dot: true });
129
128
  // latest contents
130
- const openFiles: UpdateOpenRequest['arguments']['openFiles'] = fixtureFilePaths.map((filePath) => ({
131
- file: filePath,
132
- fileContent: readFileSync(filePath, 'utf-8'),
133
- projectRootPath: getFixturePath('/server-harness'),
134
- scriptKindName: 'TS', // It's easy to get this wrong when copy-pasting
135
- }));
129
+ const openFiles: server.protocol.UpdateOpenRequest['arguments']['openFiles'] = fixtureFilePaths.map(
130
+ (filePath) => ({
131
+ file: filePath,
132
+ fileContent: readFileSync(filePath, 'utf-8'),
133
+ projectRootPath: getFixturePath('/server-harness'),
134
+ scriptKindName: 'TS', // It's easy to get this wrong when copy-pasting
135
+ }),
136
+ );
136
137
 
137
138
  // override the cache
138
139
  await server.message({
@@ -144,7 +145,7 @@ export async function createTSServer() {
144
145
  closedFiles: [],
145
146
  openFiles,
146
147
  },
147
- } as UpdateOpenRequest);
148
+ } as server.protocol.UpdateOpenRequest);
148
149
  },
149
150
  exit: async () => {
150
151
  await server.message({ command: 'exit' });
@@ -1,6 +1,6 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import { resolve } from 'node:path';
3
- import { default as postcss, type Message } from 'postcss';
3
+ import postcss, { type Message } from 'postcss';
4
4
  import type { Result } from 'postcss-load-config';
5
5
  import type { Transformer } from '../index.js';
6
6
 
@@ -44,7 +44,7 @@ export const createPostcssTransformer: (postcssTransformerOptions?: PostcssTrans
44
44
  });
45
45
  if (postcssConfig === undefined) return false;
46
46
 
47
- const result = await postcss(postcssConfig.plugins).process(source, {
47
+ const result = await postcss.default(postcssConfig.plugins).process(source, {
48
48
  ...postcssConfig.options,
49
49
  from: options.from,
50
50
  map: { inline: false, absolute: true },
package/src/util.test.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { join } from 'path';
2
- import { hasProp, isObject, isSystemError, unique, uniqueBy } from '../src/util.js';
3
2
  import { createFixtures, getFixturePath } from './test-util/util.js';
4
- import { isMatchByGlob, exists } from './util.js';
3
+ import { hasProp, isObject, isSystemError, unique, uniqueBy, isMatchByGlob, exists } from './util.js';
5
4
 
6
5
  function fakeSystemError({ code }: { code: string }) {
7
6
  const error = new Error();
package/LICENSE.txt DELETED
@@ -1,23 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2022 mizdra
4
- Copyright (c) [2016] [Yosuke Kurami]
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining a copy
7
- of this software and associated documentation files (the "Software"), to deal
8
- in the Software without restriction, including without limitation the rights
9
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- copies of the Software, and to permit persons to whom the Software is
11
- furnished to do so, subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in all
14
- copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
- SOFTWARE.
23
-
package/README.md DELETED
@@ -1,277 +0,0 @@
1
- <p align="center">
2
- <img alt="Cover image" src="./docs/cover.svg" />
3
- </p>
4
-
5
- <h2 align="center">Happy CSS Modules</h2>
6
-
7
- <p align="center">
8
- <em>Typed, definition jumpable CSS Modules.</em>
9
- <br />
10
- <em>Moreover, easy!</em>
11
- </p>
12
-
13
- https://user-images.githubusercontent.com/9639995/189538880-872ad38d-2c9d-4c19-b257-521018963eec.mov
14
-
15
- ## Features
16
-
17
- - :white_check_mark: Strict type checking
18
- - Generate `.d.ts` of CSS Modules for type checking
19
- - :mag: Definition jumps
20
- - Clicking on a property on `.jsx`/`.tsx` will jump to the source of the definition on `.module.css`.
21
- - This is accomplished by generating `.d.ts.map` (a.k.a. [Declaration Map](https://www.typescriptlang.org/tsconfig#declarationMap)).
22
- - :handshake: High compatibility with the ecosystem
23
- - Support for Postcss/Sass/Less
24
- - Implement webpack-compatible resolving algorithms
25
- - Also supports [`resolve.alias`](https://webpack.js.org/configuration/resolve/#resolvealias)
26
- - :beginner: Easy to use
27
- - No configuration file, some simple CLI options
28
-
29
- ## Installation
30
-
31
- ```console
32
- $ npm i -D happy-css-modules
33
- ```
34
-
35
- ## Usage
36
-
37
- In the simple case, everything goes well with the following!
38
-
39
- ```console
40
- $ hcm 'src/**/*.module.{css,scss,less}'
41
- ```
42
-
43
- If you want to customize the behavior, see `--help`.
44
-
45
- ```console
46
- $ hcm --help
47
- Generate .d.ts and .d.ts.map for CSS modules.
48
-
49
- hcm [options] <glob>
50
-
51
- Options:
52
- -w, --watch Watch input directory's css files or pattern [boolean] [default: false]
53
- --localsConvention Style of exported class names. [choices: "camelCase", "camelCaseOnly", "dashes", "dashesOnly"]
54
- --declarationMap Create sourcemaps for d.ts files [boolean] [default: true]
55
- --sassLoadPaths The option compatible with sass's `--load-path`. [array]
56
- --lessIncludePaths The option compatible with less's `--include-path`. [array]
57
- --webpackResolveAlias The option compatible with webpack's `resolve.alias`. [string]
58
- --postcssConfig The option compatible with postcss's `--config`. [string]
59
- --cache Only generate .d.ts and .d.ts.map for changed files. [boolean] [default: true]
60
- --cacheStrategy Strategy for the cache to use for detecting changed files.[choices: "content", "metadata"] [default: "content"]
61
- --logLevel What level of logs to report. [choices: "debug", "info", "silent"] [default: "info"]
62
- -h, --help Show help [boolean]
63
- -v, --version Show version number [boolean]
64
-
65
- Examples:
66
- hcm 'src/**/*.module.css' Generate .d.ts and .d.ts.map.
67
- hcm 'src/**/*.module.{css,scss,less}' Also generate files for sass and less.
68
- hcm 'src/**/*.module.css' --watch Watch for changes and generate .d.ts and .d.ts.map.
69
- hcm 'src/**/*.module.css' --declarationMap=false Generate .d.ts only.
70
- hcm 'src/**/*.module.css' --sassLoadPaths=src/style Run with sass's `--load-path`.
71
- hcm 'src/**/*.module.css' --lessIncludePaths=src/style Run with less's `--include-path`.
72
- hcm 'src/**/*.module.css' --webpackResolveAlias='{"@": "src"}' Run with webpack's `resolve.alias`.
73
- hcm 'src/**/*.module.css' --cache=false Disable cache.
74
- ```
75
-
76
- ## How docs definition jumps work?
77
-
78
- In addition to `.module.css.d.ts`, happy-css-modules also generates a `.module.css.d.ts.map` file (a.k.a. [Declaration Map](https://www.typescriptlang.org/tsconfig#declarationMap)). This file is a Source Map that contains code mapping information from generated (`.module.css.d.ts`) to source (`.module.css`).
79
-
80
- When tsserver (TypeScript Language Server for VSCode) tries to jump to the code on `.module.css.d.ts`, it restores the original location from this Source Map and redirects to the code on` .module.css`. happy-css-modules uses this mechanism to realize definition jump.
81
-
82
- ![Illustration of how definition jump works](docs/how-does-definition-jumps-work/basic/flow.drawio.svg)
83
-
84
- The case of multiple definitions is a bit more complicated. This is because the Source Map specification does not allow for a 1:N mapping of the generated:original locations. Therefore, happy-css-modules define multiple definitions of the same property type and map each property to a different location in `.module.css`.
85
-
86
- ![Illustration of a case with multiple definitions](docs/how-does-definition-jumps-work/multiple-definitions/flow.drawio.svg)
87
-
88
- ## Node.js API (Experimental)
89
-
90
- > **Warning**
91
- > This feature is experimental and may change significantly. The API is not stable and may have breaking changes even in minor or patch version updates.
92
-
93
- `happy-css-modules` provides Node.js API for programmatically generating .d.ts and .d.ts.map.
94
-
95
- See [src/index.ts](https://github.com/mizdra/happy-css-modules/blob/main/src/index.ts) for available API.
96
-
97
- ### Example: Custom `hcm` commands
98
-
99
- You can create your own customized `hcm` commands. We also provide a `parseArgv` utility that parses `process.argv` and extracts options.
100
-
101
- ```javascript
102
- #!/usr/bin/env ts-node
103
- // scripts/hcm.ts
104
-
105
- import { run, parseArgv } from 'happy-css-modules';
106
-
107
- // Write your code here...
108
-
109
- run({
110
- // Inherit default CLI options (e.g. --watch).
111
- ...parseArgv(process.argv),
112
- // Add custom CLI options.
113
- cwd: __dirname,
114
- }).catch((e) => {
115
- console.error(e);
116
- process.exit(1);
117
- });
118
- ```
119
-
120
- ### Example: Custom transformer
121
-
122
- With the `transformer` option, you can use AltCSS, which is not supported by `happy-css-modules`.
123
-
124
- ```typescript
125
- #!/usr/bin/env ts-node
126
-
127
- import { run, parseArgv, createDefaultTransformer, type Transformer } from 'happy-css-modules';
128
- import sass from 'sass';
129
- import { promisify } from 'util';
130
-
131
- const defaultTransformer = createDefaultTransformer();
132
- const render = promisify(sass.render);
133
-
134
- // The custom transformer supporting sass indented syntax
135
- const transformer: Transformer = async (source, options) => {
136
- if (from.endsWith('.sass')) {
137
- const result = await render({
138
- // Use indented syntax.
139
- // ref: https://sass-lang.com/documentation/syntax#the-indented-syntax
140
- indentedSyntax: true,
141
- data: source,
142
- file: options.from,
143
- outFile: 'DUMMY',
144
- // Output sourceMap.
145
- sourceMap: true,
146
- // Resolve import specifier using resolver.
147
- importer: (url, prev, done) => {
148
- options
149
- .resolver(url, { request: prev })
150
- .then((resolved) => done({ file: resolved }))
151
- .catch((e) => done(e));
152
- },
153
- });
154
- return { css: result.css, map: result.sourceMap!, dependencies: result.loadedUrls };
155
- }
156
- // Fallback to default transformer.
157
- return await defaultTransformer(source, from);
158
- };
159
-
160
- run({ ...parseArgv(process.argv), transformer }).catch((e) => {
161
- console.error(e);
162
- process.exit(1);
163
- });
164
- ```
165
-
166
- ### Example: Custom resolver
167
-
168
- With the `resolver` option, you can customize the resolution algorithm for import specifier (such as `@import "specifier"`).
169
-
170
- ```typescript
171
- #!/usr/bin/env ts-node
172
-
173
- import { run, parseArgv, createDefaultResolver, type Resolver } from 'happy-css-modules';
174
- import { exists } from 'fs/promises';
175
- import { resolve, join } from 'path';
176
-
177
- const cwd = process.cwd();
178
- const runnerOptions = parseArgv(process.argv);
179
- const { sassLoadPaths, lessIncludePaths, webpackResolveAlias } = runnerOptions;
180
- // Some runner options must be passed to the default resolver.
181
- const defaultResolver = createDefaultResolver({ cwd, sassLoadPaths, lessIncludePaths, webpackResolveAlias });
182
- const stylesDir = resolve(__dirname, 'src/styles');
183
-
184
- const resolver: Resolver = async (specifier, options) => {
185
- // If the default resolver cannot resolve, fallback to a customized resolve algorithm.
186
- const resolvedByDefaultResolver = await defaultResolver(specifier, options);
187
- if (resolvedByDefaultResolver === false) {
188
- // Search for files in `src/styles` directory.
189
- const path = join(stylesDir, specifier);
190
- if (await exists(path)) return path;
191
- }
192
- // Returns `false` if specifier cannot be resolved.
193
- return false;
194
- };
195
-
196
- run({ ...runnerOptions, resolver, cwd }).catch((e) => {
197
- console.error(e);
198
- process.exit(1);
199
- });
200
- ```
201
-
202
- ### Example: Get locations for selectors exported by CSS Modules
203
-
204
- `Locator` can be used to get location for selectors exported by CSS Modules.
205
-
206
- ```typescript
207
- import { Locator } from 'happy-css-modules';
208
- import { resolve } from 'path';
209
- import assert from 'assert';
210
-
211
- const locator = new Locator({
212
- // You can customize the transformer and resolver used by the locator.
213
- // transformer: createDefaultTransformer(),
214
- // resolver: createDefaultResolver(),
215
- });
216
-
217
- // Process https://github.com/mizdra/happy-css-modules/blob/main/example/02-import/2.css
218
- const filePath = resolve('example/02-import/2.css'); // Convert to absolute path
219
- const result = await locator.load(filePath);
220
-
221
- assert.deepEqual(result, {
222
- dependencies: ['/Users/mizdra/src/github.com/mizdra/happy-css-modules/example/02-import/3.css'],
223
- tokens: [
224
- {
225
- name: 'b',
226
- originalLocations: [
227
- {
228
- filePath: '/Users/mizdra/src/github.com/mizdra/happy-css-modules/example/02-import/3.css',
229
- start: { line: 1, column: 1 },
230
- end: { line: 1, column: 2 },
231
- },
232
- ],
233
- },
234
- {
235
- name: 'a',
236
- originalLocations: [
237
- {
238
- filePath: '/Users/mizdra/src/github.com/mizdra/happy-css-modules/example/02-import/2.css',
239
- start: { line: 3, column: 1 },
240
- end: { line: 3, column: 2 },
241
- },
242
- ],
243
- },
244
- ],
245
- });
246
- ```
247
-
248
- ## About the origins of this project
249
-
250
- This project was born as a PoC for [Quramy/typed-css-modules#177](https://github.com/Quramy/typed-css-modules/issues/177). That is why this project forks [`Quramy/typed-css-modules`](https://github.com/Quramy/typed-css-modules). Due to refactoring, only a small amount of code now comes from `Quramy/typed-css-modules`, but its contributions can still be found in the credits of the license.
251
-
252
- Thank you [@Quramy](https://github.com/Quramy)!
253
-
254
- ## Prior art
255
-
256
- There is a lot of excellent prior art.
257
-
258
- - ✅ Supported
259
- - 🔶 Partially supported
260
- - 🛑 Not supported
261
- - ❓ Unknown
262
-
263
- | Repository | Strict type checking | Definition jumps | Sass | Less | `resolve.alias` | How implemented |
264
- | :------------------------------------------------------------------------------------------------ | :------------------: | :--------------: | :--: | :--: | :-------------: | :---------------------------------------: |
265
- | [Quramy/typed-css-modules](https://github.com/Quramy/typed-css-modules) | ✅ | 🛑 | 🛑 | 🛑 | 🛑 | CLI Tool |
266
- | [skovy/typed-scss-modules](https://github.com/skovy/typed-scss-modules) | ✅ | 🛑 | ✅ | 🛑 | 🛑 | CLI Tool |
267
- | [qiniu/typed-less-modules](https://github.com/qiniu/typed-less-modules) | ✅ | 🛑 | 🛑 | ✅ | 🛑 | CLI Tool |
268
- | [mrmckeb/typescript-plugin-css-modules](https://github.com/mrmckeb/typescript-plugin-css-modules) | 🔶<sup>\*1</sup> | 🔶<sup>\*2</sup> | ✅ | ✅ | 🛑 | TypeScript Language Service<sup>\*3</sup> |
269
- | [clinyong/vscode-css-modules](https://github.com/clinyong/vscode-css-modules) | 🛑 | ✅ | ✅ | ✅ | 🛑 | VSCode Extension |
270
- | [Viijay-Kr/react-ts-css](https://github.com/Viijay-Kr/react-ts-css) | 🔶<sup>\*1</sup> | ✅ | ✅ | ✅ | ❓ | VSCode Extension |
271
- | [mizdra/happy-css-modules](https://github.com/mizdra/happy-css-modules) | ✅ | ✅ | ✅ | ✅ | ✅ | CLI Tool + Declaration Map |
272
-
273
- - \*1: Warnings are displayed in the editor, but not at compile time.
274
- - \*2: Not supported for `.less` definition jumps.
275
- - \*3: The TypeScript language service can display warnings in the editor, but not at compile time. It is also complicated to set up.
276
-
277
- Another known tool for generating `.css.d.ts` is [wix/stylable](https://github.com/wix/stylable) , which does not use CSS Modules.