happy-css-modules 4.0.0 → 5.0.0

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 (114) hide show
  1. package/LICENSE.txt +23 -0
  2. package/README.md +307 -2
  3. package/bin/hcm.js +1 -1
  4. package/dist/cli.d.ts +0 -4
  5. package/dist/cli.js +111 -118
  6. package/dist/cli.js.map +1 -1
  7. package/dist/emitter/dts.js +3 -4
  8. package/dist/emitter/dts.js.map +1 -1
  9. package/dist/emitter/dts.test.js +12 -12
  10. package/dist/emitter/file-system.js +2 -2
  11. package/dist/emitter/file-system.js.map +1 -1
  12. package/dist/emitter/file-system.test.js +1 -1
  13. package/dist/emitter/file-system.test.js.map +1 -1
  14. package/dist/emitter/index.js +1 -1
  15. package/dist/emitter/index.js.map +1 -1
  16. package/dist/emitter/index.test.js +1 -2
  17. package/dist/emitter/index.test.js.map +1 -1
  18. package/dist/emitter/source-map.js +1 -1
  19. package/dist/emitter/source-map.js.map +1 -1
  20. package/dist/emitter/source-map.test.js +1 -1
  21. package/dist/emitter/source-map.test.js.map +1 -1
  22. package/dist/integration-test/go-to-definition.test.js +403 -105
  23. package/dist/integration-test/go-to-definition.test.js.map +1 -1
  24. package/dist/locator/index.js +10 -8
  25. package/dist/locator/index.js.map +1 -1
  26. package/dist/locator/index.test.js +303 -169
  27. package/dist/locator/index.test.js.map +1 -1
  28. package/dist/locator/postcss.js +2 -3
  29. package/dist/locator/postcss.js.map +1 -1
  30. package/dist/locator/postcss.test.js +317 -73
  31. package/dist/locator/postcss.test.js.map +1 -1
  32. package/dist/logger.js +7 -6
  33. package/dist/logger.js.map +1 -1
  34. package/dist/regression-test/issue-168.test.js +2 -3
  35. package/dist/regression-test/issue-168.test.js.map +1 -1
  36. package/dist/resolver/index.d.ts +1 -1
  37. package/dist/resolver/index.js +3 -3
  38. package/dist/resolver/index.js.map +1 -1
  39. package/dist/resolver/node-resolver.js +1 -1
  40. package/dist/resolver/node-resolver.js.map +1 -1
  41. package/dist/resolver/relative-resolver.js +1 -1
  42. package/dist/resolver/relative-resolver.js.map +1 -1
  43. package/dist/resolver/webpack-resolver.d.ts +1 -1
  44. package/dist/resolver/webpack-resolver.js +4 -4
  45. package/dist/resolver/webpack-resolver.js.map +1 -1
  46. package/dist/runner.js +50 -18
  47. package/dist/runner.js.map +1 -1
  48. package/dist/runner.test.js +47 -32
  49. package/dist/runner.test.js.map +1 -1
  50. package/dist/test-util/line-column.d.ts +9 -0
  51. package/dist/test-util/line-column.js +16 -0
  52. package/dist/test-util/line-column.js.map +1 -0
  53. package/dist/test-util/line-column.test.d.ts +1 -0
  54. package/dist/test-util/line-column.test.js +21 -0
  55. package/dist/test-util/line-column.test.js.map +1 -0
  56. package/dist/test-util/tsserver.js +11 -12
  57. package/dist/test-util/tsserver.js.map +1 -1
  58. package/dist/test-util/util.d.ts +6 -0
  59. package/dist/test-util/util.js +22 -5
  60. package/dist/test-util/util.js.map +1 -1
  61. package/dist/transformer/index.js +1 -1
  62. package/dist/transformer/index.js.map +1 -1
  63. package/dist/transformer/index.test.js +17 -17
  64. package/dist/transformer/index.test.js.map +1 -1
  65. package/dist/transformer/less-transformer.js +4 -4
  66. package/dist/transformer/less-transformer.js.map +1 -1
  67. package/dist/transformer/less-transformer.test.js +75 -49
  68. package/dist/transformer/less-transformer.test.js.map +1 -1
  69. package/dist/transformer/postcss-transformer.test.js +56 -50
  70. package/dist/transformer/postcss-transformer.test.js.map +1 -1
  71. package/dist/transformer/scss-transformer.js +0 -1
  72. package/dist/transformer/scss-transformer.js.map +1 -1
  73. package/dist/transformer/scss-transformer.test.js +105 -52
  74. package/dist/transformer/scss-transformer.test.js.map +1 -1
  75. package/dist/util.js +6 -8
  76. package/dist/util.js.map +1 -1
  77. package/dist/util.test.js +2 -2
  78. package/dist/util.test.js.map +1 -1
  79. package/package.json +58 -34
  80. package/src/cli.ts +119 -117
  81. package/src/emitter/dts.test.ts +12 -12
  82. package/src/emitter/dts.ts +25 -26
  83. package/src/emitter/file-system.test.ts +1 -1
  84. package/src/emitter/file-system.ts +2 -2
  85. package/src/emitter/index.test.ts +1 -2
  86. package/src/emitter/index.ts +1 -1
  87. package/src/emitter/source-map.test.ts +1 -1
  88. package/src/emitter/source-map.ts +1 -1
  89. package/src/integration-test/go-to-definition.test.ts +405 -105
  90. package/src/locator/index.test.ts +303 -169
  91. package/src/locator/index.ts +6 -6
  92. package/src/locator/postcss.test.ts +317 -73
  93. package/src/locator/postcss.ts +2 -3
  94. package/src/logger.ts +6 -6
  95. package/src/regression-test/issue-168.test.ts +2 -3
  96. package/src/resolver/index.ts +4 -4
  97. package/src/resolver/node-resolver.ts +1 -1
  98. package/src/resolver/relative-resolver.ts +1 -1
  99. package/src/resolver/webpack-resolver.ts +5 -5
  100. package/src/runner.test.ts +54 -32
  101. package/src/runner.ts +51 -19
  102. package/src/test-util/line-column.test.ts +21 -0
  103. package/src/test-util/line-column.ts +15 -0
  104. package/src/test-util/tsserver.ts +11 -12
  105. package/src/test-util/util.ts +23 -5
  106. package/src/transformer/index.test.ts +17 -17
  107. package/src/transformer/index.ts +1 -1
  108. package/src/transformer/less-transformer.test.ts +73 -45
  109. package/src/transformer/less-transformer.ts +1 -3
  110. package/src/transformer/postcss-transformer.test.ts +56 -50
  111. package/src/transformer/scss-transformer.test.ts +107 -52
  112. package/src/transformer/scss-transformer.ts +0 -1
  113. package/src/util.test.ts +2 -2
  114. package/src/util.ts +6 -8
package/package.json CHANGED
@@ -1,53 +1,73 @@
1
1
  {
2
2
  "name": "happy-css-modules",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Creates .d.ts files from CSS Modules .css files",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
8
- "scripts": {
9
- "build": "tsc -p tsconfig.build.json"
10
- },
11
- "bin": {
12
- "hcm": "bin/hcm.js"
13
- },
14
- "repository": {
15
- "type": "git",
16
- "url": "https://github.com/mizdra/happy-css-modules.git",
17
- "directory": "packages/happy-css-modules"
18
- },
19
5
  "keywords": [
20
6
  "css-modules",
21
7
  "typescript"
22
8
  ],
9
+ "license": "MIT",
10
+ "author": "mizdra",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/mizdra/happy-css-modules.git"
14
+ },
15
+ "bin": {
16
+ "hcm": "bin/hcm.js"
17
+ },
23
18
  "files": [
24
19
  "bin",
25
20
  "src",
26
21
  "dist"
27
22
  ],
28
- "author": "mizdra",
29
- "license": "MIT",
30
- "engines": {
31
- "node": ">=18.0.0"
23
+ "type": "module",
24
+ "main": "dist/index.js",
25
+ "types": "dist/index.d.ts",
26
+ "scripts": {
27
+ "update-example": "cd example && node ../bin/hcm.js '*-*/*.{css,scss,less}' --no-cache",
28
+ "dev": "npm run build && npm run update-example",
29
+ "build": "tsc -p tsconfig.build.json",
30
+ "lint": "run-s -c lint:*",
31
+ "lint:oxfmt": "oxfmt --check",
32
+ "lint:oxlint": "oxlint --type-aware",
33
+ "lint:tsc": "tsc -p tsconfig.json",
34
+ "test": "vitest run"
32
35
  },
33
36
  "dependencies": {
34
37
  "@file-cache/core": "^2.0.0",
35
38
  "@file-cache/npm": "^2.0.0",
36
- "async-mutex": "^0.5.0",
37
- "camelcase": "^8.0.0",
38
- "chalk": "^5.3.0",
39
- "chokidar": "^3.6.0",
40
- "enhanced-resolve": "^5.16.1",
41
- "glob": "^10.3.15",
42
- "import-meta-resolve": "^4.1.0",
43
- "minimatch": "^9.0.4",
44
- "postcss": "^8.4.38",
45
- "postcss-load-config": "^5.1.0",
46
- "postcss-modules": "^6.0.0",
47
- "postcss-selector-parser": "^6.0.16",
39
+ "camelcase": "^9.0.0",
40
+ "chokidar": "^5.0.0",
41
+ "enhanced-resolve": "^5.22.2",
42
+ "import-meta-resolve": "^4.2.0",
43
+ "postcss": "^8.5.15",
44
+ "postcss-load-config": "^6.0.1",
45
+ "postcss-modules": "^6.0.1",
46
+ "postcss-selector-parser": "^7.1.1",
48
47
  "postcss-value-parser": "^4.2.0",
49
- "source-map": "^0.7.4",
50
- "yargs": "^17.7.2"
48
+ "source-map": "^0.7.6"
49
+ },
50
+ "devDependencies": {
51
+ "@mizdra/oxfmt-config": "^0.2.0",
52
+ "@mizdra/oxlint-config": "^0.5.0",
53
+ "@types/dedent": "^0.7.2",
54
+ "@types/less": "^3.0.8",
55
+ "@types/node": "^22.19.19",
56
+ "@typescript/server-harness": "^0.3.5",
57
+ "dedent": "^1.7.2",
58
+ "less": "^4.6.4",
59
+ "less-3": "npm:less@^3.13.1",
60
+ "less-4": "npm:less@^4.6.4",
61
+ "npm-run-all2": "^9.0.1",
62
+ "oxfmt": "^0.53.0",
63
+ "oxlint": "^1.68.0",
64
+ "oxlint-tsgolint": "^0.23.0",
65
+ "postcss-import": "^16.1.1",
66
+ "postcss-simple-vars": "^7.0.1",
67
+ "sass": "^1.100.0",
68
+ "typescript": "^6.0.3",
69
+ "vite": "^8.0.16",
70
+ "vitest": "^4.1.8"
51
71
  },
52
72
  "peerDependencies": {
53
73
  "less": "^3.0.0 || ^4.0.0",
@@ -61,5 +81,9 @@
61
81
  "less": {
62
82
  "optional": true
63
83
  }
64
- }
84
+ },
85
+ "engines": {
86
+ "node": "^22.20.0 || ^24.8.0 || >=26.0.0"
87
+ },
88
+ "packageManager": "npm@11.16.0"
65
89
  }
package/src/cli.ts CHANGED
@@ -1,126 +1,128 @@
1
- import yargs from 'yargs';
2
- import { hideBin } from 'yargs/helpers';
1
+ import { parseArgs } from 'node:util';
3
2
  import { DEFAULT_ARBITRARY_EXTENSIONS } from './config.js';
4
3
  import { type RunnerOptions } from './runner.js';
5
4
  import { getPackageJson } from './util.js';
6
5
 
7
- /**
8
- * Parse command line arguments.
9
- * @returns Runner options.
10
- */
6
+ const HELP_TEXT = `
7
+ Generate .d.ts and .d.ts.map for CSS modules.
8
+
9
+ Usage: hcm [options] <glob>
10
+
11
+ Options:
12
+ -w, --[no-]watch Watch input directory's css files or pattern (default: false)
13
+ --localsConvention Style of exported class names.
14
+ [choices: camelCase, camelCaseOnly, dashes, dashesOnly]
15
+ --[no-]declarationMap Create sourcemaps for d.ts files (default: true)
16
+ --sassLoadPaths The option compatible with sass's \`--load-path\`.
17
+ --lessIncludePaths The option compatible with less's \`--include-path\`.
18
+ --webpackResolveAlias The option compatible with webpack's \`resolve.alias\`.
19
+ --postcssConfig The option compatible with postcss's \`--config\`.
20
+ --[no-]arbitraryExtensions Generate \`.d.css.ts\` instead of \`.css.d.ts\` (default: false)
21
+ --[no-]cache Only generate .d.ts and .d.ts.map for changed files (default: true)
22
+ --cacheStrategy Strategy for the cache to use for detecting changed files.
23
+ [choices: content, metadata] (default: content)
24
+ --logLevel What level of logs to report.
25
+ [choices: debug, info, silent] (default: info)
26
+ -o, --outDir Output directory for generated files.
27
+ -h, --help Show help
28
+ -v, --version Show version number
29
+
30
+ Examples:
31
+ hcm 'src/**/*.module.css'
32
+ hcm 'src/**/*.module.{css,scss,less}'
33
+ hcm 'src/**/*.module.css' --watch
34
+ hcm 'src/**/*.module.css' --no-declarationMap
35
+ hcm 'src/**/*.module.css' --sassLoadPaths src/style
36
+ hcm 'src/**/*.module.css' --lessIncludePaths src/style
37
+ hcm 'src/**/*.module.css' --webpackResolveAlias '{"@": "src"}'
38
+ hcm 'src/**/*.module.css' --no-cache
39
+ `.trim();
40
+
11
41
  export function parseArgv(argv: string[]): RunnerOptions {
12
42
  const pkgJson = getPackageJson();
13
- const parsedArgv = yargs(hideBin(argv))
14
- .wrap(Math.min(140, process.stdout.columns))
15
- .scriptName('hcm')
16
- .usage('Generate .d.ts and .d.ts.map for CSS modules.\n\n$0 [options] <glob>')
17
- .example("$0 'src/**/*.module.css'", 'Generate .d.ts and .d.ts.map.')
18
- .example("$0 'src/**/*.module.{css,scss,less}'", 'Also generate files for sass and less.')
19
- .example("$0 'src/**/*.module.css' --watch", 'Watch for changes and generate .d.ts and .d.ts.map.')
20
- .example("$0 'src/**/*.module.css' --declarationMap=false", 'Generate .d.ts only.')
21
- .example("$0 'src/**/*.module.css' --sassLoadPaths=src/style", "Run with sass's `--load-path`.")
22
- .example("$0 'src/**/*.module.css' --lessIncludePaths=src/style", "Run with less's `--include-path`.")
23
- .example('$0 \'src/**/*.module.css\' --webpackResolveAlias=\'{"@": "src"}\'', "Run with webpack's `resolve.alias`.")
24
- .example("$0 'src/**/*.module.css' --cache=false", 'Disable cache.')
25
- .detectLocale(false)
26
- .option('watch', {
27
- type: 'boolean',
28
- alias: 'w',
29
- default: false,
30
- describe: "Watch input directory's css files or pattern",
31
- })
32
- .option('localsConvention', {
33
- choices: ['camelCase', 'camelCaseOnly', 'dashes', 'dashesOnly'] as const,
34
- describe: 'Style of exported class names.',
35
- })
36
- .option('declarationMap', {
37
- type: 'boolean',
38
- default: true,
39
- describe: 'Create sourcemaps for d.ts files',
40
- })
41
- .option('sassLoadPaths', {
42
- array: true,
43
- nargs: 1,
44
- describe: "The option compatible with sass's `--load-path`.",
45
- })
46
- .option('lessIncludePaths', {
47
- array: true,
48
- nargs: 1,
49
- describe: "The option compatible with less's `--include-path`.",
50
- })
51
- .option('webpackResolveAlias', {
52
- string: true,
53
- describe: "The option compatible with webpack's `resolve.alias`.",
54
- })
55
- // TODO: Support --noPostcssConfig option.
56
- .option('postcssConfig', {
57
- string: true,
58
- describe: "The option compatible with postcss's `--config`.",
59
- })
60
- .option('arbitraryExtensions', {
61
- type: 'boolean',
62
- default: DEFAULT_ARBITRARY_EXTENSIONS,
63
- describe: 'Generate `.d.css.ts` instead of `.css.d.ts`.',
64
- })
65
- .option('cache', {
66
- type: 'boolean',
67
- default: true,
68
- describe: 'Only generate .d.ts and .d.ts.map for changed files.',
69
- })
70
- .option('cacheStrategy', {
71
- choices: ['content', 'metadata'] as const,
72
- // NOTE: This is a workaround for `parsedArgv.cacheStrategy` type breaks.
73
- default: 'content' as RunnerOptions['cacheStrategy'],
74
- describe: 'Strategy for the cache to use for detecting changed files.',
75
- })
76
- .option('logLevel', {
77
- choices: ['debug', 'info', 'silent'] as const,
78
- default: 'info' as RunnerOptions['logLevel'],
79
- describe: 'What level of logs to report.',
80
- })
81
- .option('outDir', {
82
- type: 'string',
83
- alias: 'o',
84
- describe: 'Output directory for generated files.',
85
- })
86
- .alias('h', 'help')
87
- .alias('v', 'version')
88
- .version(pkgJson.version)
89
- .check((argv) => {
90
- const patterns = argv._;
91
- // TODO: support multiple patterns
92
- if (patterns.length !== 1) throw new Error('Only one pattern is allowed.');
93
- if (argv.webpackResolveAlias) {
94
- let parsedWebpackResolveAlias: unknown;
95
- try {
96
- parsedWebpackResolveAlias = JSON.parse(argv.webpackResolveAlias);
97
- } catch (e) {
98
- throw new Error('--webpackResolveAlias must be a valid JSON string.');
99
- }
100
- if (typeof parsedWebpackResolveAlias !== 'object' || parsedWebpackResolveAlias === null)
101
- throw new Error('--webpackResolveAlias must be an object');
102
- if (!Object.keys(parsedWebpackResolveAlias).every((key) => typeof key === 'string'))
103
- throw new Error('--webpackResolveAlias must be an object of string keys');
104
- if (!Object.values(parsedWebpackResolveAlias).every((value) => typeof value === 'string'))
105
- throw new Error('--webpackResolveAlias must be an object of string values');
106
- }
107
- return true;
108
- })
109
- .parseSync();
110
- const patterns: string[] = parsedArgv._.map((pattern) => pattern.toString());
43
+
44
+ const { values, positionals } = parseArgs({
45
+ args: argv.slice(2),
46
+ options: {
47
+ watch: { type: 'boolean', short: 'w', default: false },
48
+ localsConvention: { type: 'string' },
49
+ declarationMap: { type: 'boolean', default: true },
50
+ sassLoadPaths: { type: 'string', multiple: true },
51
+ lessIncludePaths: { type: 'string', multiple: true },
52
+ webpackResolveAlias: { type: 'string' },
53
+ postcssConfig: { type: 'string' },
54
+ arbitraryExtensions: { type: 'boolean', default: DEFAULT_ARBITRARY_EXTENSIONS },
55
+ cache: { type: 'boolean', default: true },
56
+ cacheStrategy: { type: 'string', default: 'content' },
57
+ logLevel: { type: 'string', default: 'info' },
58
+ outDir: { type: 'string', short: 'o' },
59
+ help: { type: 'boolean', short: 'h' },
60
+ version: { type: 'boolean', short: 'v' },
61
+ },
62
+ allowPositionals: true,
63
+ allowNegative: true,
64
+ });
65
+
66
+ if (values.help) {
67
+ // oxlint-disable-next-line no-console
68
+ console.log(HELP_TEXT);
69
+ // oxlint-disable-next-line unicorn/no-process-exit
70
+ process.exit(0);
71
+ }
72
+
73
+ if (values.version) {
74
+ // oxlint-disable-next-line no-console
75
+ console.log(pkgJson.version);
76
+ // oxlint-disable-next-line unicorn/no-process-exit
77
+ process.exit(0);
78
+ }
79
+
80
+ if (positionals.length !== 1) throw new Error('Only one pattern is allowed.');
81
+
82
+ const validLocalsConventions = ['camelCase', 'camelCaseOnly', 'dashes', 'dashesOnly'];
83
+ if (values.localsConvention !== undefined && !validLocalsConventions.includes(values.localsConvention)) {
84
+ throw new Error(`--localsConvention must be one of: ${validLocalsConventions.join(', ')}`);
85
+ }
86
+
87
+ const validCacheStrategies = ['content', 'metadata'];
88
+ if (!validCacheStrategies.includes(values.cacheStrategy)) {
89
+ throw new Error(`--cacheStrategy must be one of: ${validCacheStrategies.join(', ')}`);
90
+ }
91
+
92
+ const validLogLevels = ['debug', 'info', 'silent'];
93
+ if (!validLogLevels.includes(values.logLevel)) {
94
+ throw new Error(`--logLevel must be one of: ${validLogLevels.join(', ')}`);
95
+ }
96
+
97
+ let webpackResolveAlias: Record<string, string> | undefined;
98
+ if (values.webpackResolveAlias) {
99
+ let parsed: unknown;
100
+ try {
101
+ parsed = JSON.parse(values.webpackResolveAlias);
102
+ } catch {
103
+ throw new Error('--webpackResolveAlias must be a valid JSON string.');
104
+ }
105
+ if (typeof parsed !== 'object' || parsed === null) throw new Error('--webpackResolveAlias must be an object');
106
+ if (!Object.keys(parsed).every((key) => typeof key === 'string'))
107
+ throw new Error('--webpackResolveAlias must be an object of string keys');
108
+ if (!Object.values(parsed).every((value) => typeof value === 'string'))
109
+ throw new Error('--webpackResolveAlias must be an object of string values');
110
+ webpackResolveAlias = parsed as Record<string, string>;
111
+ }
112
+
111
113
  return {
112
- pattern: patterns[0]!,
113
- watch: parsedArgv.watch,
114
- localsConvention: parsedArgv.localsConvention,
115
- declarationMap: parsedArgv.declarationMap,
116
- sassLoadPaths: parsedArgv.sassLoadPaths?.map((item) => item.toString()),
117
- lessIncludePaths: parsedArgv.lessIncludePaths?.map((item) => item.toString()),
118
- webpackResolveAlias: parsedArgv.webpackResolveAlias ? JSON.parse(parsedArgv.webpackResolveAlias) : undefined,
119
- postcssConfig: parsedArgv.postcssConfig,
120
- arbitraryExtensions: parsedArgv.arbitraryExtensions,
121
- cache: parsedArgv.cache,
122
- cacheStrategy: parsedArgv.cacheStrategy,
123
- logLevel: parsedArgv.logLevel,
124
- outDir: parsedArgv.outDir,
114
+ pattern: positionals[0]!,
115
+ watch: values.watch,
116
+ localsConvention: values.localsConvention as RunnerOptions['localsConvention'],
117
+ declarationMap: values.declarationMap,
118
+ sassLoadPaths: values.sassLoadPaths,
119
+ lessIncludePaths: values.lessIncludePaths,
120
+ webpackResolveAlias,
121
+ postcssConfig: values.postcssConfig,
122
+ arbitraryExtensions: values.arbitraryExtensions,
123
+ cache: values.cache,
124
+ cacheStrategy: values.cacheStrategy as RunnerOptions['cacheStrategy'],
125
+ logLevel: values.logLevel as RunnerOptions['logLevel'],
126
+ outDir: values.outDir,
125
127
  };
126
128
  }
@@ -28,17 +28,17 @@ describe('generateDtsContentWithSourceMap', () => {
28
28
  test('generate dts content with source map', async () => {
29
29
  createFixtures({
30
30
  '/test/1.css': dedent`
31
- @import './2.css';
32
- .a {}
33
- .b {}
34
- .b {}
31
+ @import './2.css';
32
+ .a {}
33
+ .b {}
34
+ .b {}
35
35
  `,
36
36
  '/test/2.css': dedent`
37
- @import './3.css';
38
- .c {}
37
+ @import './3.css';
38
+ .c {}
39
39
  `,
40
40
  '/test/3.css': dedent`
41
- .d {}
41
+ .d {}
42
42
  `,
43
43
  });
44
44
  const result = await locator.load(filePath);
@@ -91,8 +91,8 @@ describe('generateDtsContentWithSourceMap', () => {
91
91
  async function getResult(filePath: string) {
92
92
  createFixtures({
93
93
  '/test/1.css': dedent`
94
- .foo-bar {}
95
- .foo_bar {}
94
+ .foo-bar {}
95
+ .foo_bar {}
96
96
  `,
97
97
  });
98
98
  return locator.load(filePath);
@@ -238,9 +238,9 @@ describe('generateDtsContentWithSourceMap', () => {
238
238
  test('treats imported tokens from external files the same as local tokens', async () => {
239
239
  createFixtures({
240
240
  '/test/1.css': dedent`
241
- @import './2.css';
242
- @import './3.css';
243
- .a {}
241
+ @import './2.css';
242
+ @import './3.css';
243
+ .a {}
244
244
  `,
245
245
  '/test/2.css': `.b {}`,
246
246
  '/test/3.css': `.c {}`,
@@ -1,5 +1,5 @@
1
- import { EOL } from 'os';
2
- import path, { basename, parse, join } from 'path';
1
+ import { EOL } from 'node:os';
2
+ import path, { basename, parse, join } from 'node:path';
3
3
  import camelcase from 'camelcase';
4
4
  import { SourceNode, type CodeWithSourceMap } from 'source-map';
5
5
  import { type Token } from '../locator/index.js';
@@ -34,7 +34,7 @@ export function getDtsFilePath(
34
34
  }
35
35
 
36
36
  function dashesCamelCase(str: string): string {
37
- return str.replace(/-+(\w)/gu, (match, firstLetter) => {
37
+ return str.replace(/-+(\w)/gu, (_match, firstLetter) => {
38
38
  return firstLetter.toUpperCase();
39
39
  });
40
40
  }
@@ -107,35 +107,34 @@ function generateTokenDeclarations(
107
107
  ': string }>',
108
108
  ])
109
109
  : typeof token.importedName === 'string'
110
- ? new SourceNode(null, null, null, [
111
- `& Readonly<{ `,
112
- new SourceNode(
113
- originalLocation.start.line,
114
- // The SourceNode's column is 0-based, but the originalLocation's column is 1-based.
115
- originalLocation.start.column - 1,
116
- getRelativePath(sourceMapFilePath, originalLocation.filePath),
110
+ ? new SourceNode(null, null, null, [
111
+ `& Readonly<{ `,
112
+ new SourceNode(
113
+ originalLocation.start.line,
114
+ // The SourceNode's column is 0-based, but the originalLocation's column is 1-based.
115
+ originalLocation.start.column - 1,
116
+ getRelativePath(sourceMapFilePath, originalLocation.filePath),
117
+ `"${token.name}"`,
118
+ token.name,
119
+ ),
120
+ `: (typeof import(`,
121
+ `"${getRelativePath(filePath, originalLocation.filePath)}"`,
122
+ `))["default"]["${token.importedName}"] }>`,
123
+ ])
124
+ : // Imported tokens in non-external files are typed by dynamic import.
125
+ // See https://github.com/mizdra/happy-css-modules/issues/106.
126
+ new SourceNode(null, null, null, [
127
+ '& Readonly<Pick<(typeof import(',
128
+ `"${getRelativePath(filePath, originalLocation.filePath)}"`,
129
+ '))["default"], ',
117
130
  `"${token.name}"`,
118
- token.name,
119
- ),
120
- `: (typeof import(`,
121
- `"${getRelativePath(filePath, originalLocation.filePath)}"`,
122
- `))["default"]["${token.importedName}"] }>`,
123
- ])
124
- : // Imported tokens in non-external files are typed by dynamic import.
125
- // See https://github.com/mizdra/happy-css-modules/issues/106.
126
- new SourceNode(null, null, null, [
127
- '& Readonly<Pick<(typeof import(',
128
- `"${getRelativePath(filePath, originalLocation.filePath)}"`,
129
- '))["default"], ',
130
- `"${token.name}"`,
131
- '>>',
132
- ]),
131
+ '>>',
132
+ ]),
133
133
  );
134
134
  }
135
135
  return result;
136
136
  }
137
137
 
138
- // eslint-disable-next-line max-params
139
138
  export function generateDtsContentWithSourceMap(
140
139
  filePath: string,
141
140
  dtsFilePath: string,
@@ -1,4 +1,4 @@
1
- import { readFile, rm, stat } from 'fs/promises';
1
+ import { readFile, rm, stat } from 'node:fs/promises';
2
2
  import { createFixtures, getFixturePath } from '../test-util/util.js';
3
3
  import { writeFileIfChanged } from './file-system.js';
4
4
 
@@ -1,5 +1,5 @@
1
- import { mkdir, readFile, writeFile } from 'fs/promises';
2
- import { dirname } from 'path';
1
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
+ import { dirname } from 'node:path';
3
3
  import { isSystemError } from '../util.js';
4
4
 
5
5
  /**
@@ -1,8 +1,7 @@
1
- import { readFile, stat } from 'fs/promises';
1
+ import { readFile, stat } from 'node:fs/promises';
2
2
  import { createFixtures, exists, fakeToken, getFixturePath, waitForAsyncTask } from '../test-util/util.js';
3
3
  import { emitGeneratedFiles, getRelativePath, isSubDirectoryFile } from './index.js';
4
4
 
5
- // eslint-disable-next-line @typescript-eslint/no-empty-function
6
5
  const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
7
6
 
8
7
  beforeEach(() => {
@@ -1,4 +1,4 @@
1
- import { dirname, isAbsolute, relative } from 'path';
1
+ import { dirname, isAbsolute, relative } from 'node:path';
2
2
  import { DEFAULT_ARBITRARY_EXTENSIONS } from '../config.js';
3
3
  import { type Token } from '../locator/index.js';
4
4
  import { type LocalsConvention } from '../runner.js';
@@ -1,4 +1,4 @@
1
- import { EOL } from 'os';
1
+ import { EOL } from 'node:os';
2
2
  import { getSourceMapFilePath, generateSourceMappingURLComment } from './source-map.js';
3
3
 
4
4
  test('getSourceMapFilePath', () => {
@@ -1,4 +1,4 @@
1
- import { EOL } from 'os';
1
+ import { EOL } from 'node:os';
2
2
  import { getDtsFilePath } from './dts.js';
3
3
  import type { OutDirOptions } from './index.js';
4
4
  import { getRelativePath } from './index.js';