happy-css-modules 0.2.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 (154) hide show
  1. package/LICENSE.txt +23 -0
  2. package/README.md +124 -0
  3. package/bin/hcm.js +9 -0
  4. package/dist/cli.d.ts +6 -0
  5. package/dist/cli.js +69 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/cli.test.d.ts +1 -0
  8. package/dist/cli.test.js +34 -0
  9. package/dist/cli.test.js.map +1 -0
  10. package/dist/emitter/dts.d.ts +14 -0
  11. package/dist/emitter/dts.js +106 -0
  12. package/dist/emitter/dts.js.map +1 -0
  13. package/dist/emitter/dts.test.d.ts +1 -0
  14. package/dist/emitter/dts.test.js +205 -0
  15. package/dist/emitter/dts.test.js.map +1 -0
  16. package/dist/emitter/file-system.d.ts +6 -0
  17. package/dist/emitter/file-system.js +26 -0
  18. package/dist/emitter/file-system.js.map +1 -0
  19. package/dist/emitter/file-system.test.d.ts +1 -0
  20. package/dist/emitter/file-system.test.js +34 -0
  21. package/dist/emitter/file-system.test.js.map +1 -0
  22. package/dist/emitter/index.d.ts +34 -0
  23. package/dist/emitter/index.js +42 -0
  24. package/dist/emitter/index.js.map +1 -0
  25. package/dist/emitter/index.test.d.ts +1 -0
  26. package/dist/emitter/index.test.js +118 -0
  27. package/dist/emitter/index.test.js.map +1 -0
  28. package/dist/emitter/source-map.d.ts +9 -0
  29. package/dist/emitter/source-map.js +16 -0
  30. package/dist/emitter/source-map.js.map +1 -0
  31. package/dist/emitter/source-map.test.d.ts +1 -0
  32. package/dist/emitter/source-map.test.js +13 -0
  33. package/dist/emitter/source-map.test.js.map +1 -0
  34. package/dist/index.d.ts +3 -0
  35. package/dist/index.js +3 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/integration-test/go-to-definition.test.d.ts +1 -0
  38. package/dist/integration-test/go-to-definition.test.js +367 -0
  39. package/dist/integration-test/go-to-definition.test.js.map +1 -0
  40. package/dist/library/source-map/index.d.ts +8 -0
  41. package/dist/library/source-map/index.js +5 -0
  42. package/dist/library/source-map/index.js.map +1 -0
  43. package/dist/loader/index.d.ts +42 -0
  44. package/dist/loader/index.js +145 -0
  45. package/dist/loader/index.js.map +1 -0
  46. package/dist/loader/index.test.d.ts +1 -0
  47. package/dist/loader/index.test.js +290 -0
  48. package/dist/loader/index.test.js.map +1 -0
  49. package/dist/loader/postcss.d.ts +60 -0
  50. package/dist/loader/postcss.js +209 -0
  51. package/dist/loader/postcss.js.map +1 -0
  52. package/dist/loader/postcss.test.d.ts +1 -0
  53. package/dist/loader/postcss.test.js +236 -0
  54. package/dist/loader/postcss.test.js.map +1 -0
  55. package/dist/resolver/index.d.ts +20 -0
  56. package/dist/resolver/index.js +39 -0
  57. package/dist/resolver/index.js.map +1 -0
  58. package/dist/resolver/index.test.d.ts +1 -0
  59. package/dist/resolver/index.test.js +16 -0
  60. package/dist/resolver/index.test.js.map +1 -0
  61. package/dist/resolver/node-resolver.d.ts +2 -0
  62. package/dist/resolver/node-resolver.js +6 -0
  63. package/dist/resolver/node-resolver.js.map +1 -0
  64. package/dist/resolver/node-resolver.test.d.ts +1 -0
  65. package/dist/resolver/node-resolver.test.js +25 -0
  66. package/dist/resolver/node-resolver.test.js.map +1 -0
  67. package/dist/resolver/relative-resolver.d.ts +2 -0
  68. package/dist/resolver/relative-resolver.js +5 -0
  69. package/dist/resolver/relative-resolver.js.map +1 -0
  70. package/dist/resolver/relative-resolver.test.d.ts +1 -0
  71. package/dist/resolver/relative-resolver.test.js +12 -0
  72. package/dist/resolver/relative-resolver.test.js.map +1 -0
  73. package/dist/resolver/webpack-resolver.d.ts +2 -0
  74. package/dist/resolver/webpack-resolver.js +69 -0
  75. package/dist/resolver/webpack-resolver.js.map +1 -0
  76. package/dist/resolver/webpack-resolver.test.d.ts +1 -0
  77. package/dist/resolver/webpack-resolver.test.js +26 -0
  78. package/dist/resolver/webpack-resolver.test.js.map +1 -0
  79. package/dist/runner.d.ts +33 -0
  80. package/dist/runner.js +75 -0
  81. package/dist/runner.js.map +1 -0
  82. package/dist/runner.test.d.ts +1 -0
  83. package/dist/runner.test.js +113 -0
  84. package/dist/runner.test.js.map +1 -0
  85. package/dist/test/jest/resolver.cjs +30 -0
  86. package/dist/test/jest/resolver.cjs.map +1 -0
  87. package/dist/test/jest/resolver.d.cts +30 -0
  88. package/dist/test/tsserver.d.ts +27 -0
  89. package/dist/test/tsserver.js +104 -0
  90. package/dist/test/tsserver.js.map +1 -0
  91. package/dist/test/util.d.ts +29 -0
  92. package/dist/test/util.js +78 -0
  93. package/dist/test/util.js.map +1 -0
  94. package/dist/transformer/index.d.ts +23 -0
  95. package/dist/transformer/index.js +19 -0
  96. package/dist/transformer/index.js.map +1 -0
  97. package/dist/transformer/less-transformer.d.ts +2 -0
  98. package/dist/transformer/less-transformer.js +43 -0
  99. package/dist/transformer/less-transformer.js.map +1 -0
  100. package/dist/transformer/less-transformer.test.d.ts +1 -0
  101. package/dist/transformer/less-transformer.test.js +126 -0
  102. package/dist/transformer/less-transformer.test.js.map +1 -0
  103. package/dist/transformer/scss-transformer.d.ts +2 -0
  104. package/dist/transformer/scss-transformer.js +84 -0
  105. package/dist/transformer/scss-transformer.js.map +1 -0
  106. package/dist/transformer/scss-transformer.test.d.ts +1 -0
  107. package/dist/transformer/scss-transformer.test.js +132 -0
  108. package/dist/transformer/scss-transformer.test.js.map +1 -0
  109. package/dist/util.d.ts +19 -0
  110. package/dist/util.js +52 -0
  111. package/dist/util.js.map +1 -0
  112. package/dist/util.test.d.ts +1 -0
  113. package/dist/util.test.js +75 -0
  114. package/dist/util.test.js.map +1 -0
  115. package/package.json +106 -0
  116. package/src/__snapshots__/runner.test.ts.snap +34 -0
  117. package/src/cli.test.ts +38 -0
  118. package/src/cli.ts +70 -0
  119. package/src/emitter/dts.test.ts +266 -0
  120. package/src/emitter/dts.ts +134 -0
  121. package/src/emitter/file-system.test.ts +36 -0
  122. package/src/emitter/file-system.ts +24 -0
  123. package/src/emitter/index.test.ts +130 -0
  124. package/src/emitter/index.ts +92 -0
  125. package/src/emitter/source-map.test.ts +20 -0
  126. package/src/emitter/source-map.ts +17 -0
  127. package/src/index.ts +3 -0
  128. package/src/integration-test/go-to-definition.test.ts +371 -0
  129. package/src/library/README.md +3 -0
  130. package/src/library/source-map/index.ts +26 -0
  131. package/src/loader/index.test.ts +306 -0
  132. package/src/loader/index.ts +199 -0
  133. package/src/loader/postcss.test.ts +336 -0
  134. package/src/loader/postcss.ts +239 -0
  135. package/src/resolver/index.test.ts +17 -0
  136. package/src/resolver/index.ts +48 -0
  137. package/src/resolver/node-resolver.test.ts +26 -0
  138. package/src/resolver/node-resolver.ts +7 -0
  139. package/src/resolver/relative-resolver.test.ts +13 -0
  140. package/src/resolver/relative-resolver.ts +6 -0
  141. package/src/resolver/webpack-resolver.test.ts +33 -0
  142. package/src/resolver/webpack-resolver.ts +71 -0
  143. package/src/runner.test.ts +122 -0
  144. package/src/runner.ts +105 -0
  145. package/src/test/jest/resolver.cjs +30 -0
  146. package/src/test/tsserver.ts +176 -0
  147. package/src/test/util.ts +100 -0
  148. package/src/transformer/index.ts +44 -0
  149. package/src/transformer/less-transformer.test.ts +135 -0
  150. package/src/transformer/less-transformer.ts +55 -0
  151. package/src/transformer/scss-transformer.test.ts +142 -0
  152. package/src/transformer/scss-transformer.ts +94 -0
  153. package/src/util.test.ts +89 -0
  154. package/src/util.ts +67 -0
package/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
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 ADDED
@@ -0,0 +1,124 @@
1
+ <p align="center">
2
+ <img alt="Cover image" src="./docs/cover.svg" />
3
+ </p>
4
+
5
+ <h2 align="center">The Collection of tools to make CSS Modules happy :)</h2>
6
+
7
+ <p align="center">
8
+ <em>Typed, definition jumps, and unused variable detection!</em>
9
+ </p>
10
+
11
+ https://user-images.githubusercontent.com/9639995/189538880-872ad38d-2c9d-4c19-b257-521018963eec.mov
12
+
13
+ This is an experimental project aimed at PoC for https://github.com/Quramy/typed-css-modules/issues/177.
14
+
15
+ ## Installation
16
+
17
+ ```console
18
+ $ npm i -D happy-css-modules
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```console
24
+ $ hcm --help
25
+ Create .d.ts and .d.ts.map from CSS modules *.css files.
26
+
27
+ hcm [options] <glob>
28
+
29
+ Options:
30
+ --outDir Output directory [string]
31
+ -w, --watch Watch input directory's css files or pattern
32
+ [boolean] [default: false]
33
+ --localsConvention Style of exported class names.
34
+ [choices: "camelCase", "camelCaseOnly", "dashes", "dashesOnly"]
35
+ --declarationMap Create sourcemaps for d.ts files
36
+ [boolean] [default: true]
37
+ --silent Silent output. Do not show "files written" messages
38
+ [boolean] [default: false]
39
+ -h, --help Show help [boolean]
40
+ -v, --version Show version number [boolean]
41
+
42
+ Examples:
43
+ hcm 'src/**/*.module.css' Generate .d.ts and .d.ts.map.
44
+ hcm 'src/**/*.module.{css,scss,less}' Also generate files for sass and les
45
+ s.
46
+ hcm 'src/**/*.module.css' --watch Watch for changes and generate .d.ts
47
+ and .d.ts.map.
48
+ hcm 'src/**/*.module.css' --declaration Generate .d.ts only.
49
+ Map=false
50
+ ```
51
+
52
+ ## Node.js API (Experimental)
53
+
54
+ > **Warning**
55
+ > 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.
56
+
57
+ `happy-css-modules` provides Node.js API for programmatically generating .d.ts and .d.ts.map.
58
+
59
+ See [src/index.ts](https://github.com/mizdra/happy-css-modules/blob/main/src/index.ts) for available API.
60
+
61
+ ### Example
62
+
63
+ With the `transformer` option, you can use AltCSS, which is not supported by `happy-css-modules`.
64
+
65
+ ```javascript
66
+ // @ts-check
67
+
68
+ import { run } from 'happy-css-modules';
69
+ import { readFile } from 'fs/promises';
70
+ import { fileURLToPath, pathToFileURL } from 'url';
71
+ import sass from 'sass';
72
+
73
+ // The custom transpiler supporting sass indented syntax
74
+ /** @type {import('happy-css-modules').Transformer} */
75
+ const transformer = async (source, from) => {
76
+ if (from.endsWith('.sass')) {
77
+ const result = await sass.compileStringAsync(source, {
78
+ // Use indented syntax
79
+ // ref: https://sass-lang.com/documentation/syntax#the-indented-syntax
80
+ syntax: 'indented',
81
+ url: pathToFileURL(from),
82
+ sourceMap: true,
83
+ });
84
+ return { css: result.css, map: result.sourceMap!, dependencies: result.loadedUrls };
85
+ }
86
+ return false;
87
+ };
88
+
89
+ run({
90
+ pattern: 'src/**/*.css';
91
+ watch: false;
92
+ transformer,
93
+ }).catch((e) => {
94
+ console.error(e);
95
+ process.exit(1);
96
+ });
97
+ ```
98
+
99
+ You can also 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 node
103
+ // scripts/hcm.js
104
+ // @ts-check
105
+
106
+ import { run, parseArgv } from 'happy-css-modules';
107
+
108
+ // ...
109
+
110
+ run({
111
+ ...parseArgv(process.argv), // Inherit default CLI options (e.g. --watch)
112
+ transformer,
113
+ }).catch((e) => {
114
+ console.error(e);
115
+ process.exit(1);
116
+ });
117
+ ```
118
+
119
+ ## TODO
120
+
121
+ - [x] Add more tests
122
+ - [x] Support non-inline source maps
123
+ - [x] Implement an interface for easy use by scss/less users
124
+ - [ ] Implement stylelint rule to detect unused CSS ruleset from JavaScript
package/bin/hcm.js ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ // @ts-check
3
+
4
+ import { run, parseArgv } from '../dist/index.js';
5
+
6
+ run(parseArgv(process.argv)).catch((e) => {
7
+ console.error(e);
8
+ process.exit(1);
9
+ });
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { type RunnerOptions } from './runner.js';
2
+ /**
3
+ * Parse command line arguments.
4
+ * @returns Runner options.
5
+ */
6
+ export declare function parseArgv(argv: string[]): RunnerOptions;
package/dist/cli.js ADDED
@@ -0,0 +1,69 @@
1
+ import { readFileSync } from 'fs';
2
+ import { dirname, resolve } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import yargs from 'yargs';
5
+ import { hideBin } from 'yargs/helpers';
6
+ const pkgJson = JSON.parse(readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'), 'utf-8'));
7
+ /**
8
+ * Parse command line arguments.
9
+ * @returns Runner options.
10
+ */
11
+ export function parseArgv(argv) {
12
+ const parsedArgv = yargs(hideBin(argv))
13
+ .parserConfiguration({
14
+ // workaround for https://github.com/yargs/yargs/issues/1318
15
+ 'duplicate-arguments-array': false,
16
+ })
17
+ .scriptName('hcm')
18
+ .usage('Create .d.ts and .d.ts.map from CSS modules *.css files.\n\n$0 [options] <glob>')
19
+ .example("$0 'src/**/*.module.css'", 'Generate .d.ts and .d.ts.map.')
20
+ .example("$0 'src/**/*.module.{css,scss,less}'", 'Also generate files for sass and less.')
21
+ .example("$0 'src/**/*.module.css' --watch", 'Watch for changes and generate .d.ts and .d.ts.map.')
22
+ .example("$0 'src/**/*.module.css' --declarationMap=false", 'Generate .d.ts only.')
23
+ .detectLocale(false)
24
+ .option('outDir', {
25
+ type: 'string',
26
+ describe: 'Output directory',
27
+ })
28
+ .option('watch', {
29
+ type: 'boolean',
30
+ alias: 'w',
31
+ default: false,
32
+ describe: "Watch input directory's css files or pattern",
33
+ })
34
+ .option('localsConvention', {
35
+ choices: ['camelCase', 'camelCaseOnly', 'dashes', 'dashesOnly'],
36
+ describe: 'Style of exported class names.',
37
+ })
38
+ .option('declarationMap', {
39
+ type: 'boolean',
40
+ default: true,
41
+ describe: 'Create sourcemaps for d.ts files',
42
+ })
43
+ .option('silent', {
44
+ type: 'boolean',
45
+ default: false,
46
+ describe: 'Silent output. Do not show "files written" messages',
47
+ })
48
+ .alias('h', 'help')
49
+ .alias('v', 'version')
50
+ .version(pkgJson.version)
51
+ .check((argv) => {
52
+ const patterns = argv._;
53
+ // TODO: support multiple patterns
54
+ if (patterns.length !== 1)
55
+ throw new Error('Only one pattern is allowed.');
56
+ return true;
57
+ })
58
+ .parseSync();
59
+ const patterns = parsedArgv._.map((pattern) => pattern.toString());
60
+ return {
61
+ pattern: patterns[0],
62
+ outDir: parsedArgv.outDir,
63
+ watch: parsedArgv.watch,
64
+ localsConvention: parsedArgv.localsConvention,
65
+ declarationMap: parsedArgv.declarationMap,
66
+ silent: parsedArgv.silent,
67
+ };
68
+ }
69
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGxC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvH;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAc;IACtC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;SACpC,mBAAmB,CAAC;QACnB,4DAA4D;QAC5D,2BAA2B,EAAE,KAAK;KACnC,CAAC;SACD,UAAU,CAAC,KAAK,CAAC;SACjB,KAAK,CAAC,iFAAiF,CAAC;SACxF,OAAO,CAAC,0BAA0B,EAAE,+BAA+B,CAAC;SACpE,OAAO,CAAC,sCAAsC,EAAE,wCAAwC,CAAC;SACzF,OAAO,CAAC,kCAAkC,EAAE,qDAAqD,CAAC;SAClG,OAAO,CAAC,iDAAiD,EAAE,sBAAsB,CAAC;SAClF,YAAY,CAAC,KAAK,CAAC;SACnB,MAAM,CAAC,QAAQ,EAAE;QAChB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,kBAAkB;KAC7B,CAAC;SACD,MAAM,CAAC,OAAO,EAAE;QACf,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,GAAG;QACV,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,8CAA8C;KACzD,CAAC;SACD,MAAM,CAAC,kBAAkB,EAAE;QAC1B,OAAO,EAAE,CAAC,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,CAAU;QACxE,QAAQ,EAAE,gCAAgC;KAC3C,CAAC;SACD,MAAM,CAAC,gBAAgB,EAAE;QACxB,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,kCAAkC;KAC7C,CAAC;SACD,MAAM,CAAC,QAAQ,EAAE;QAChB,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,qDAAqD;KAChE,CAAC;SACD,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC;SAClB,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC;SACrB,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;SACxB,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;QACd,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC;QACxB,kCAAkC;QAClC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC3E,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;SACD,SAAS,EAAE,CAAC;IACf,MAAM,QAAQ,GAAa,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7E,OAAO;QACL,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAE;QACrB,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,gBAAgB,EAAE,UAAU,CAAC,gBAAgB;QAC7C,cAAc,EAAE,UAAU,CAAC,cAAc;QACzC,MAAM,EAAE,UAAU,CAAC,MAAM;KAC1B,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,34 @@
1
+ import { parseArgv } from './cli.js';
2
+ const baseArgs = ['node', 'hcm'];
3
+ describe('parseArgv', () => {
4
+ test('pattern', () => {
5
+ expect(parseArgv([...baseArgs, 'foo']).pattern).toStrictEqual('foo');
6
+ expect(parseArgv([...baseArgs, '1']).pattern).toStrictEqual('1');
7
+ // TODO: Support multiple patterns
8
+ // parseArgv([...baseArgs, 'foo', 'bar']);
9
+ });
10
+ test('--outDir', () => {
11
+ expect(parseArgv([...baseArgs, '1.css', '--outDir', 'foo']).outDir).toStrictEqual('foo');
12
+ expect(parseArgv([...baseArgs, '1.css', '--outDir', '1']).outDir).toStrictEqual('1');
13
+ });
14
+ test('--watch', () => {
15
+ expect(parseArgv([...baseArgs, '1.css', '--watch']).watch).toBe(true);
16
+ expect(parseArgv([...baseArgs, '1.css', '--no-watch']).watch).toBe(false);
17
+ });
18
+ test('--localsConvention', () => {
19
+ expect(parseArgv([...baseArgs, '1.css']).localsConvention).toBe(undefined);
20
+ expect(parseArgv([...baseArgs, '1.css', '--localsConvention', 'camelCaseOnly']).localsConvention).toBe('camelCaseOnly');
21
+ expect(parseArgv([...baseArgs, '1.css', '--localsConvention', 'camelCase']).localsConvention).toBe('camelCase');
22
+ expect(parseArgv([...baseArgs, '1.css', '--localsConvention', 'dashesOnly']).localsConvention).toBe('dashesOnly');
23
+ expect(parseArgv([...baseArgs, '1.css', '--localsConvention', 'dashes']).localsConvention).toBe('dashes');
24
+ });
25
+ test('--declarationMap', () => {
26
+ expect(parseArgv([...baseArgs, '1.css', '--declarationMap']).declarationMap).toBe(true);
27
+ expect(parseArgv([...baseArgs, '1.css', '--no-declarationMap']).declarationMap).toBe(false);
28
+ });
29
+ test('--silent', () => {
30
+ expect(parseArgv([...baseArgs, '1.css', '--silent']).silent).toBe(true);
31
+ expect(parseArgv([...baseArgs, '1.css', '--no-silent']).silent).toBe(false);
32
+ });
33
+ });
34
+ //# sourceMappingURL=cli.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.test.js","sourceRoot":"","sources":["../src/cli.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type CodeWithSourceMap } from '../library/source-map/index.js';
2
+ import { type Token } from '../loader/index.js';
3
+ import { type DistOptions, type DtsFormatOptions } from './index.js';
4
+ /**
5
+ * Get .d.ts file path.
6
+ * @param filePath The path to the source file (i.e. `/dir/foo.css`). It is absolute.
7
+ * @param distOptions The distribution option.
8
+ * @returns The path to the .d.ts file. It is absolute.
9
+ */
10
+ export declare function getDtsFilePath(filePath: string, distOptions: DistOptions | undefined): string;
11
+ export declare function generateDtsContentWithSourceMap(filePath: string, dtsFilePath: string, sourceMapFilePath: string, tokens: Token[], dtsFormatOptions: DtsFormatOptions | undefined, isExternalFile: (filePath: string) => boolean): {
12
+ dtsContent: CodeWithSourceMap['code'];
13
+ sourceMap: CodeWithSourceMap['map'];
14
+ };
@@ -0,0 +1,106 @@
1
+ import { EOL } from 'os';
2
+ import { join, relative, basename } from 'path';
3
+ import camelcase from 'camelcase';
4
+ import { SourceNode } from '../library/source-map/index.js';
5
+ import { getRelativePath, isSubDirectoryFile } from './index.js';
6
+ /**
7
+ * Get .d.ts file path.
8
+ * @param filePath The path to the source file (i.e. `/dir/foo.css`). It is absolute.
9
+ * @param distOptions The distribution option.
10
+ * @returns The path to the .d.ts file. It is absolute.
11
+ */
12
+ export function getDtsFilePath(filePath, distOptions) {
13
+ if (distOptions) {
14
+ if (!isSubDirectoryFile(distOptions.rootDir, filePath))
15
+ throw new Error(`The filePath(${filePath}) is not a subdirectory of rootDir(${distOptions.rootDir}).`);
16
+ if (!isSubDirectoryFile(distOptions.rootDir, distOptions.outDir))
17
+ throw new Error(`The outDir(${distOptions.outDir}) is not a subdirectory of rootDir(${distOptions.rootDir}).`);
18
+ return join(distOptions.outDir, relative(distOptions.rootDir, filePath) + '.d.ts');
19
+ }
20
+ else {
21
+ return filePath + '.d.ts';
22
+ }
23
+ }
24
+ function dashesCamelCase(str) {
25
+ return str.replace(/-+(\w)/g, function (match, firstLetter) {
26
+ return firstLetter.toUpperCase();
27
+ });
28
+ }
29
+ function formatTokens(tokens, localsConvention) {
30
+ const result = [];
31
+ for (const token of tokens) {
32
+ if (localsConvention === 'camelCaseOnly') {
33
+ result.push({ ...token, name: camelcase(token.name) });
34
+ }
35
+ else if (localsConvention === 'camelCase') {
36
+ result.push(token);
37
+ result.push({ ...token, name: camelcase(token.name) });
38
+ }
39
+ else if (localsConvention === 'dashesOnly') {
40
+ result.push({ ...token, name: dashesCamelCase(token.name) });
41
+ }
42
+ else if (localsConvention === 'dashes') {
43
+ result.push(token);
44
+ result.push({ ...token, name: dashesCamelCase(token.name) });
45
+ }
46
+ else {
47
+ result.push(token); // asIs
48
+ }
49
+ }
50
+ return result;
51
+ }
52
+ function generateTokenDeclarations(filePath, sourceMapFilePath, tokens, dtsFormatOptions, isExternalFile) {
53
+ var _a, _b;
54
+ const formattedTokens = formatTokens(tokens, dtsFormatOptions === null || dtsFormatOptions === void 0 ? void 0 : dtsFormatOptions.localsConvention);
55
+ const result = [];
56
+ for (const token of formattedTokens) {
57
+ // Only one original position can be associated with one generated position.
58
+ // This is due to the sourcemap specification. Therefore, we output multiple type definitions
59
+ // with the same name and assign a separate original position to each.
60
+ for (const originalLocation of token.originalLocations) {
61
+ result.push(originalLocation.filePath === filePath || isExternalFile(originalLocation.filePath)
62
+ ? new SourceNode(null, null, null, [
63
+ '& Readonly<{ ',
64
+ new SourceNode((_a = originalLocation.start.line) !== null && _a !== void 0 ? _a : null,
65
+ // The SourceNode's column is 0-based, but the originalLocation's column is 1-based.
66
+ (_b = originalLocation.start.column - 1) !== null && _b !== void 0 ? _b : null, getRelativePath(sourceMapFilePath, originalLocation.filePath), `"${token.name}"`, token.name),
67
+ ': string }>',
68
+ ])
69
+ : // Imported tokens in non-external files are typed by dynamic import.
70
+ // See https://github.com/mizdra/happy-css-modules/issues/106.
71
+ new SourceNode(null, null, null, [
72
+ '& Readonly<Pick<(typeof import(',
73
+ `"${getRelativePath(filePath, originalLocation.filePath)}"`,
74
+ '))["default"], ',
75
+ `"${token.name}"`,
76
+ '>>',
77
+ ]));
78
+ }
79
+ }
80
+ return result;
81
+ }
82
+ export function generateDtsContentWithSourceMap(filePath, dtsFilePath, sourceMapFilePath, tokens, dtsFormatOptions, isExternalFile) {
83
+ const tokenDeclarations = generateTokenDeclarations(filePath, sourceMapFilePath, tokens, dtsFormatOptions, isExternalFile);
84
+ let sourceNode;
85
+ if (!tokenDeclarations || !tokenDeclarations.length) {
86
+ sourceNode = new SourceNode(null, null, null, '');
87
+ }
88
+ else {
89
+ sourceNode = new SourceNode(1, 0, getRelativePath(sourceMapFilePath, filePath), [
90
+ 'declare const styles:' + EOL,
91
+ ...tokenDeclarations.map((tokenDeclaration) => [' ', tokenDeclaration, EOL]),
92
+ ';' + EOL,
93
+ 'export default styles;' + EOL,
94
+ ]);
95
+ }
96
+ const codeWithSourceMap = sourceNode.toStringWithSourceMap({
97
+ // Since sourcemap and type definitions are in the same directory, they can be referenced by relative paths.
98
+ file: basename(dtsFilePath),
99
+ sourceRoot: '',
100
+ });
101
+ return {
102
+ dtsContent: codeWithSourceMap.code,
103
+ sourceMap: codeWithSourceMap.map,
104
+ };
105
+ }
106
+ //# sourceMappingURL=dts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dts.js","sourceRoot":"","sources":["../../src/emitter/dts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,205 @@
1
+ import dedent from 'dedent';
2
+ import { SourceMapConsumer } from 'source-map';
3
+ import { Loader } from '../loader/index.js';
4
+ import { getFixturePath, createFixtures } from '../test/util.js';
5
+ import { generateDtsContentWithSourceMap, getDtsFilePath } from './dts.js';
6
+ const loader = new Loader();
7
+ const isExternalFile = () => false;
8
+ test('getDtsFilePath', () => {
9
+ expect(getDtsFilePath('/app/src/dir/1.css', undefined)).toBe('/app/src/dir/1.css.d.ts');
10
+ expect(getDtsFilePath('/app/src/dir/1.css', { rootDir: '/app', outDir: '/app/dist' })).toBe('/app/dist/src/dir/1.css.d.ts');
11
+ expect(() => getDtsFilePath('/tmp/src/dir/1.css', { rootDir: '/app', outDir: '/app/dist' })).toThrow();
12
+ expect(() => getDtsFilePath('/app/src/dir/1.css', { rootDir: '/app', outDir: '/tmp/dist' })).toThrow();
13
+ });
14
+ describe('generateDtsContentWithSourceMap', () => {
15
+ const filePath = getFixturePath('/test/1.css');
16
+ const dtsFilePath = getFixturePath('/test/1.css.d.ts');
17
+ const sourceMapFilePath = getFixturePath('/test/1.css.map');
18
+ const dtsFormatOptions = {
19
+ localsConvention: undefined,
20
+ };
21
+ test('generate dts content with source map', async () => {
22
+ createFixtures({
23
+ '/test/1.css': dedent `
24
+ @import './2.css';
25
+ .a {}
26
+ .b {}
27
+ .b {}
28
+ `,
29
+ '/test/2.css': dedent `
30
+ @import './3.css';
31
+ .c {}
32
+ `,
33
+ '/test/3.css': dedent `
34
+ .d {}
35
+ `,
36
+ });
37
+ const result = await loader.load(filePath);
38
+ const { dtsContent, sourceMap } = generateDtsContentWithSourceMap(filePath, dtsFilePath, sourceMapFilePath, result.tokens, dtsFormatOptions, isExternalFile);
39
+ expect(dtsContent).toMatchInlineSnapshot(`
40
+ "declare const styles:
41
+ & Readonly<Pick<(typeof import("./3.css"))["default"], "d">>
42
+ & Readonly<Pick<(typeof import("./2.css"))["default"], "c">>
43
+ & Readonly<{ "a": string }>
44
+ & Readonly<{ "b": string }>
45
+ & Readonly<{ "b": string }>
46
+ ;
47
+ export default styles;
48
+ "
49
+ `);
50
+ const smc = await new SourceMapConsumer(sourceMap.toJSON());
51
+ expect(smc.originalPositionFor({ line: 4, column: 15 })).toMatchInlineSnapshot(`
52
+ {
53
+ "column": 0,
54
+ "line": 2,
55
+ "name": "a",
56
+ "source": "1.css",
57
+ }
58
+ `);
59
+ expect(smc.originalPositionFor({ line: 5, column: 15 })).toMatchInlineSnapshot(`
60
+ {
61
+ "column": 0,
62
+ "line": 3,
63
+ "name": "b",
64
+ "source": "1.css",
65
+ }
66
+ `);
67
+ expect(smc.originalPositionFor({ line: 6, column: 15 })).toMatchInlineSnapshot(`
68
+ {
69
+ "column": 0,
70
+ "line": 4,
71
+ "name": "b",
72
+ "source": "1.css",
73
+ }
74
+ `);
75
+ });
76
+ describe('format case', () => {
77
+ async function getResult(filePath) {
78
+ createFixtures({
79
+ '/test/1.css': dedent `
80
+ .foo-bar {}
81
+ .foo_bar {}
82
+ `,
83
+ });
84
+ return await loader.load(filePath);
85
+ }
86
+ test('undefined', async () => {
87
+ const result = await getResult(filePath);
88
+ const { dtsContent } = generateDtsContentWithSourceMap(filePath, dtsFilePath, sourceMapFilePath, result.tokens, {
89
+ ...dtsFormatOptions,
90
+ localsConvention: undefined,
91
+ }, isExternalFile);
92
+ expect(dtsContent).toMatchInlineSnapshot(`
93
+ "declare const styles:
94
+ & Readonly<{ "foo-bar": string }>
95
+ & Readonly<{ "foo_bar": string }>
96
+ ;
97
+ export default styles;
98
+ "
99
+ `);
100
+ });
101
+ test('camelCaseOnly', async () => {
102
+ const result = await getResult(filePath);
103
+ const { dtsContent } = generateDtsContentWithSourceMap(filePath, dtsFilePath, sourceMapFilePath, result.tokens, {
104
+ ...dtsFormatOptions,
105
+ localsConvention: 'camelCaseOnly',
106
+ }, isExternalFile);
107
+ expect(dtsContent).toMatchInlineSnapshot(`
108
+ "declare const styles:
109
+ & Readonly<{ "fooBar": string }>
110
+ & Readonly<{ "fooBar": string }>
111
+ ;
112
+ export default styles;
113
+ "
114
+ `);
115
+ });
116
+ test('camelCase', async () => {
117
+ const result = await getResult(filePath);
118
+ const { dtsContent } = generateDtsContentWithSourceMap(filePath, dtsFilePath, sourceMapFilePath, result.tokens, {
119
+ ...dtsFormatOptions,
120
+ localsConvention: 'camelCase',
121
+ }, isExternalFile);
122
+ expect(dtsContent).toMatchInlineSnapshot(`
123
+ "declare const styles:
124
+ & Readonly<{ "foo-bar": string }>
125
+ & Readonly<{ "fooBar": string }>
126
+ & Readonly<{ "foo_bar": string }>
127
+ & Readonly<{ "fooBar": string }>
128
+ ;
129
+ export default styles;
130
+ "
131
+ `);
132
+ });
133
+ test('dashesOnly', async () => {
134
+ const result = await getResult(filePath);
135
+ const { dtsContent } = generateDtsContentWithSourceMap(filePath, dtsFilePath, sourceMapFilePath, result.tokens, {
136
+ ...dtsFormatOptions,
137
+ localsConvention: 'dashesOnly',
138
+ }, isExternalFile);
139
+ expect(dtsContent).toMatchInlineSnapshot(`
140
+ "declare const styles:
141
+ & Readonly<{ "fooBar": string }>
142
+ & Readonly<{ "foo_bar": string }>
143
+ ;
144
+ export default styles;
145
+ "
146
+ `);
147
+ });
148
+ test('dashes', async () => {
149
+ const result = await getResult(filePath);
150
+ const { dtsContent } = generateDtsContentWithSourceMap(filePath, dtsFilePath, sourceMapFilePath, result.tokens, {
151
+ ...dtsFormatOptions,
152
+ localsConvention: 'dashes',
153
+ }, isExternalFile);
154
+ expect(dtsContent).toMatchInlineSnapshot(`
155
+ "declare const styles:
156
+ & Readonly<{ "foo-bar": string }>
157
+ & Readonly<{ "fooBar": string }>
158
+ & Readonly<{ "foo_bar": string }>
159
+ & Readonly<{ "foo_bar": string }>
160
+ ;
161
+ export default styles;
162
+ "
163
+ `);
164
+ });
165
+ });
166
+ test('emit other directory', async () => {
167
+ createFixtures({
168
+ '/test/1.css': `.a {}`,
169
+ });
170
+ const result = await loader.load(filePath);
171
+ const { dtsContent, sourceMap } = generateDtsContentWithSourceMap(getFixturePath('/test/src/1.css'), getFixturePath('/test/dist/1.css.d.ts'), getFixturePath('/test/dist/1.css.d.ts.map'), result.tokens, dtsFormatOptions, isExternalFile);
172
+ expect(dtsContent).toMatchInlineSnapshot(`
173
+ "declare const styles:
174
+ & Readonly<Pick<(typeof import("../1.css"))["default"], "a">>
175
+ ;
176
+ export default styles;
177
+ "
178
+ `);
179
+ expect(sourceMap.toJSON().sources).toStrictEqual(['../src/1.css']);
180
+ expect(sourceMap.toJSON().file).toStrictEqual('1.css.d.ts');
181
+ });
182
+ test('treats imported tokens from external files the same as local tokens', async () => {
183
+ createFixtures({
184
+ '/test/1.css': dedent `
185
+ @import './2.css';
186
+ @import './3.css';
187
+ .a {}
188
+ `,
189
+ '/test/2.css': `.b {}`,
190
+ '/test/3.css': `.c {}`,
191
+ });
192
+ const result = await loader.load(filePath);
193
+ const { dtsContent } = generateDtsContentWithSourceMap(filePath, dtsFilePath, sourceMapFilePath, result.tokens, dtsFormatOptions, (filePath) => filePath.endsWith('3.css'));
194
+ expect(dtsContent).toMatchInlineSnapshot(`
195
+ "declare const styles:
196
+ & Readonly<Pick<(typeof import("./2.css"))["default"], "b">>
197
+ & Readonly<{ "c": string }>
198
+ & Readonly<{ "a": string }>
199
+ ;
200
+ export default styles;
201
+ "
202
+ `);
203
+ });
204
+ });
205
+ //# sourceMappingURL=dts.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dts.test.js","sourceRoot":"","sources":["../../src/emitter/dts.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Write a file if it doesn't exist or is changed.
3
+ * @param filePath The file path.
4
+ * @param newContent The new content of the file.
5
+ */
6
+ export declare function writeFileIfChanged(filePath: string, newContent: string): Promise<void>;