@css-modules-kit/ts-plugin 0.0.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/LICENSE +21 -0
  2. package/README.md +95 -0
  3. package/dist/applicable-refactor.d.ts +3 -0
  4. package/dist/applicable-refactor.d.ts.map +1 -0
  5. package/dist/applicable-refactor.js +9 -0
  6. package/dist/applicable-refactor.js.map +1 -0
  7. package/dist/ast.d.ts +6 -0
  8. package/dist/ast.d.ts.map +1 -0
  9. package/dist/ast.js +27 -0
  10. package/dist/ast.js.map +1 -0
  11. package/dist/file-text-change.d.ts +4 -0
  12. package/dist/file-text-change.d.ts.map +1 -0
  13. package/dist/file-text-change.js +29 -0
  14. package/dist/file-text-change.js.map +1 -0
  15. package/dist/index.d.ts +3 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +43 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/language-plugin.d.ts +19 -0
  20. package/dist/language-plugin.d.ts.map +1 -0
  21. package/dist/language-plugin.js +72 -0
  22. package/dist/language-plugin.js.map +1 -0
  23. package/dist/language-service/feature/code-fix.d.ts +5 -0
  24. package/dist/language-service/feature/code-fix.d.ts.map +1 -0
  25. package/dist/language-service/feature/code-fix.js +83 -0
  26. package/dist/language-service/feature/code-fix.js.map +1 -0
  27. package/dist/language-service/feature/completion.d.ts +3 -0
  28. package/dist/language-service/feature/completion.d.ts.map +1 -0
  29. package/dist/language-service/feature/completion.js +46 -0
  30. package/dist/language-service/feature/completion.js.map +1 -0
  31. package/dist/language-service/feature/refactor.d.ts +12 -0
  32. package/dist/language-service/feature/refactor.d.ts.map +1 -0
  33. package/dist/language-service/feature/refactor.js +43 -0
  34. package/dist/language-service/feature/refactor.js.map +1 -0
  35. package/dist/language-service/feature/semantic-diagnostic.d.ts +5 -0
  36. package/dist/language-service/feature/semantic-diagnostic.d.ts.map +1 -0
  37. package/dist/language-service/feature/semantic-diagnostic.js +43 -0
  38. package/dist/language-service/feature/semantic-diagnostic.js.map +1 -0
  39. package/dist/language-service/feature/syntactic-diagnostic.d.ts +4 -0
  40. package/dist/language-service/feature/syntactic-diagnostic.d.ts.map +1 -0
  41. package/dist/language-service/feature/syntactic-diagnostic.js +38 -0
  42. package/dist/language-service/feature/syntactic-diagnostic.js.map +1 -0
  43. package/dist/language-service/proxy.d.ts +5 -0
  44. package/dist/language-service/proxy.d.ts.map +1 -0
  45. package/dist/language-service/proxy.js +35 -0
  46. package/dist/language-service/proxy.js.map +1 -0
  47. package/dist/language-service.d.ts +4 -0
  48. package/dist/language-service.d.ts.map +1 -0
  49. package/dist/language-service.js +125 -0
  50. package/dist/language-service.js.map +1 -0
  51. package/dist/util.d.ts +5 -0
  52. package/dist/util.d.ts.map +1 -0
  53. package/dist/util.js +25 -0
  54. package/dist/util.js.map +1 -0
  55. package/package.json +47 -0
  56. package/src/index.ts +53 -0
  57. package/src/language-plugin.ts +88 -0
  58. package/src/language-service/feature/code-fix.ts +109 -0
  59. package/src/language-service/feature/completion.ts +48 -0
  60. package/src/language-service/feature/refactor.ts +52 -0
  61. package/src/language-service/feature/semantic-diagnostic.ts +49 -0
  62. package/src/language-service/feature/syntactic-diagnostic.ts +39 -0
  63. package/src/language-service/proxy.ts +51 -0
  64. package/src/util.ts +19 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 mizdra
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.
package/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # `@css-modules-kit/ts-plugin`
2
+
3
+ A TypeScript Language Service Plugin for CSS Modules
4
+
5
+ ## Features
6
+
7
+ <details>
8
+ <summary>Go to Definition</summary>
9
+
10
+ https://github.com/user-attachments/assets/bdeb2c8a-d615-4223-bae4-e7446f62d353
11
+
12
+ </details>
13
+
14
+ <details>
15
+ <summary>Rename class names or `@value`</summary>
16
+
17
+ https://github.com/user-attachments/assets/db39a95e-2fc8-42a6-a64d-02f2822afbfe
18
+
19
+ </details>
20
+
21
+ <details>
22
+ <summary>Find all references</summary>
23
+
24
+ https://github.com/user-attachments/assets/df1e2feb-2a1a-4bf5-ae70-1cac36d90409
25
+
26
+ </details>
27
+
28
+ <details>
29
+ <summary>Automatically update import statements when moving `*.module.css`</summary>
30
+
31
+ https://github.com/user-attachments/assets/4af168fa-357d-44e1-b010-3053802bf1a2
32
+
33
+ </details>
34
+
35
+ <details>
36
+ <summary>Create CSS Module file for current file.</summary>
37
+
38
+ If there is no CSS Module file corresponding to `xxx.tsx`, create one.
39
+
40
+ https://github.com/user-attachments/assets/05f9e839-9617-43dc-a519-d5a20adf1146
41
+
42
+ </details>
43
+
44
+ <details>
45
+ <summary>Complete `className={...}` instead of `className="..."`</summary>
46
+
47
+ In projects where CSS Modules are used, the element is styled with `className={styles.xxx}`. However, when you type `className`, `className="..."` is completed. This is annoying to the user.
48
+
49
+ So, instead of `className="..."` instead of `className={...}` instead of `className="..."`.
50
+
51
+ https://github.com/user-attachments/assets/b3609c8a-123f-4f4b-af8c-3c8bf7ab4363
52
+
53
+ </details>
54
+
55
+ <details>
56
+ <summary>Prioritize the `styles' import for the current component file</summary>
57
+
58
+ When you request `styles` completion, the CSS Module file `styles` will be suggested. If there are many CSS Module files in the project, more items will be suggested. This can be confusing to the user.
59
+
60
+ So I have made it so that the `styles` of the CSS Module file corresponding to the current file is shown first.
61
+
62
+ <img width="821" alt="image" src="https://github.com/user-attachments/assets/413373ec-1258-484d-9248-bc173e4f6d4a" />
63
+
64
+ </details>
65
+
66
+ <details>
67
+ <summary>Add missing CSS rule</summary>
68
+
69
+ If you are trying to use a class name that is not defined, you can add it with Quick Fixes.
70
+
71
+ https://github.com/user-attachments/assets/3502150a-985d-45f3-9912-bbc183e41c03
72
+
73
+ </details>
74
+
75
+ ## Installation
76
+
77
+ ```bash
78
+ npm i -D @css-modules-kit/ts-plugin
79
+ ```
80
+
81
+ ## Usage
82
+
83
+ Add the "plugin" option to your tsconfig.json file. For example:
84
+
85
+ ```jsonc
86
+ {
87
+ "compilerOptions": {
88
+ "plugins": [{ "name": "@css-modules-kit/ts-plugin" }],
89
+ },
90
+ }
91
+ ```
92
+
93
+ ## Options
94
+
95
+ See [css-modules-kit's README](https://github.com/mizdra/css-modules-kit?tab=readme-ov-file#options).
@@ -0,0 +1,3 @@
1
+ import type ts from 'typescript';
2
+ export declare const createCssModuleFileRefactor: ts.ApplicableRefactorInfo;
3
+ //# sourceMappingURL=applicable-refactor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applicable-refactor.d.ts","sourceRoot":"","sources":["../src/applicable-refactor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,eAAO,MAAM,2BAA2B,EAAE,EAAE,CAAC,sBAI5C,CAAC"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCssModuleFileRefactor = void 0;
4
+ exports.createCssModuleFileRefactor = {
5
+ name: 'Create CSS Module file',
6
+ description: 'Create CSS Module file',
7
+ actions: [{ name: 'Create CSS Module file', description: 'Create CSS Module file for current file' }],
8
+ };
9
+ //# sourceMappingURL=applicable-refactor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applicable-refactor.js","sourceRoot":"","sources":["../src/applicable-refactor.ts"],"names":[],"mappings":";;;AAEa,QAAA,2BAA2B,GAA8B;IACpE,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,wBAAwB;IACrC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,wBAAwB,EAAE,WAAW,EAAE,yCAAyC,EAAE,CAAC;CACtG,CAAC"}
package/dist/ast.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import ts from 'typescript/lib/tsserverlibrary';
2
+ /**
3
+ * Get the `styles` property access expression at the specified position or range. (e.g. `styles.foo`)
4
+ */
5
+ export declare function getStylesPropertyAccessExpression(sourceFile: ts.SourceFile, positionOrRange: number | ts.TextRange, stylesImportName: string): ts.PropertyAccessExpression | undefined;
6
+ //# sourceMappingURL=ast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../src/ast.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAMhD;;GAEG;AACH,wBAAgB,iCAAiC,CAC/C,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,eAAe,EAAE,MAAM,GAAG,EAAE,CAAC,SAAS,EACtC,gBAAgB,EAAE,MAAM,GACvB,EAAE,CAAC,wBAAwB,GAAG,SAAS,CAczC"}
package/dist/ast.js ADDED
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getStylesPropertyAccessExpression = getStylesPropertyAccessExpression;
7
+ const tsserverlibrary_1 = __importDefault(require("typescript/lib/tsserverlibrary"));
8
+ function positionOrRangeToIndex(positionOrRange) {
9
+ return typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.pos;
10
+ }
11
+ /**
12
+ * Get the `styles` property access expression at the specified position or range. (e.g. `styles.foo`)
13
+ */
14
+ function getStylesPropertyAccessExpression(sourceFile, positionOrRange, stylesImportName) {
15
+ const index = positionOrRangeToIndex(positionOrRange);
16
+ function getStylesPropertyAccessExpressionImpl(node) {
17
+ if (node.pos <= index &&
18
+ index <= node.end &&
19
+ tsserverlibrary_1.default.isPropertyAccessExpression(node) &&
20
+ node.expression.getText() === stylesImportName) {
21
+ return tsserverlibrary_1.default.forEachChild(node, getStylesPropertyAccessExpressionImpl) ?? node;
22
+ }
23
+ return tsserverlibrary_1.default.forEachChild(node, getStylesPropertyAccessExpressionImpl);
24
+ }
25
+ return getStylesPropertyAccessExpressionImpl(sourceFile);
26
+ }
27
+ //# sourceMappingURL=ast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.js","sourceRoot":"","sources":["../src/ast.ts"],"names":[],"mappings":";;;;;AASA,8EAkBC;AA3BD,qFAAgD;AAEhD,SAAS,sBAAsB,CAAC,eAAsC;IACpE,OAAO,OAAO,eAAe,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC;AACrF,CAAC;AAED;;GAEG;AACH,SAAgB,iCAAiC,CAC/C,UAAyB,EACzB,eAAsC,EACtC,gBAAwB;IAExB,MAAM,KAAK,GAAG,sBAAsB,CAAC,eAAe,CAAC,CAAC;IACtD,SAAS,qCAAqC,CAAC,IAAa;QAC1D,IACE,IAAI,CAAC,GAAG,IAAI,KAAK;YACjB,KAAK,IAAI,IAAI,CAAC,GAAG;YACjB,yBAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC;YACnC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,gBAAgB,EAC9C,CAAC;YACD,OAAO,yBAAE,CAAC,YAAY,CAAC,IAAI,EAAE,qCAAqC,CAAC,IAAI,IAAI,CAAC;QAC9E,CAAC;QACD,OAAO,yBAAE,CAAC,YAAY,CAAC,IAAI,EAAE,qCAAqC,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,qCAAqC,CAAC,UAAU,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type ts from 'typescript';
2
+ export declare function createNewCssModuleFileTextChange(cssFilename: string): ts.FileTextChanges;
3
+ export declare function createInsertRuleFileTextChange(cssFilename: string, className: string, project: ts.server.Project): ts.FileTextChanges;
4
+ //# sourceMappingURL=file-text-change.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-text-change.d.ts","sourceRoot":"","sources":["../src/file-text-change.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,wBAAgB,gCAAgC,CAAC,WAAW,EAAE,MAAM,GAAG,EAAE,CAAC,eAAe,CAMxF;AAED,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,GACzB,EAAE,CAAC,eAAe,CAepB"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNewCssModuleFileTextChange = createNewCssModuleFileTextChange;
4
+ exports.createInsertRuleFileTextChange = createInsertRuleFileTextChange;
5
+ function createNewCssModuleFileTextChange(cssFilename) {
6
+ return {
7
+ fileName: cssFilename,
8
+ textChanges: [{ span: { start: 0, length: 0 }, newText: '' }],
9
+ isNewFile: true,
10
+ };
11
+ }
12
+ function createInsertRuleFileTextChange(cssFilename, className, project) {
13
+ const sourceFile = project.getSourceFile(project.projectService.toPath(cssFilename));
14
+ if (sourceFile) {
15
+ return {
16
+ fileName: cssFilename,
17
+ textChanges: [{ span: { start: sourceFile.end, length: 0 }, newText: `\n.${className} {\n \n}` }],
18
+ isNewFile: false,
19
+ };
20
+ }
21
+ else {
22
+ return {
23
+ fileName: cssFilename,
24
+ textChanges: [{ span: { start: 0, length: 0 }, newText: `.${className} {\n \n}\n\n` }],
25
+ isNewFile: true,
26
+ };
27
+ }
28
+ }
29
+ //# sourceMappingURL=file-text-change.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-text-change.js","sourceRoot":"","sources":["../src/file-text-change.ts"],"names":[],"mappings":";;AAEA,4EAMC;AAED,wEAmBC;AA3BD,SAAgB,gCAAgC,CAAC,WAAmB;IAClE,OAAO;QACL,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC7D,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC;AAED,SAAgB,8BAA8B,CAC5C,WAAmB,EACnB,SAAiB,EACjB,OAA0B;IAE1B,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;IACrF,IAAI,UAAU,EAAE,CAAC;QACf,OAAO;YACL,QAAQ,EAAE,WAAW;YACrB,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,SAAS,WAAW,EAAE,CAAC;YAClG,SAAS,EAAE,KAAK;SACjB,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO;YACL,QAAQ,EAAE,WAAW;YACrB,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,SAAS,eAAe,EAAE,CAAC;YACvF,SAAS,EAAE,IAAI;SAChB,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const plugin: import("typescript").server.PluginModuleFactory;
2
+ export = plugin;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,QAAA,MAAM,MAAM,iDA2CV,CAAC;AAEH,SAAS,MAAM,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ const createLanguageServicePlugin_js_1 = require("@volar/typescript/lib/quickstart/createLanguageServicePlugin.js");
3
+ const core_1 = require("@css-modules-kit/core");
4
+ const core_2 = require("@css-modules-kit/core");
5
+ const language_plugin_js_1 = require("./language-plugin.js");
6
+ const proxy_js_1 = require("./language-service/proxy.js");
7
+ const plugin = (0, createLanguageServicePlugin_js_1.createLanguageServicePlugin)((ts, info) => {
8
+ if (info.project.projectKind !== ts.server.ProjectKind.Configured) {
9
+ info.project.projectService.logger.info(`[@css-modules-kit/ts-plugin] info: Project is not configured`);
10
+ return { languagePlugins: [] };
11
+ }
12
+ let config;
13
+ try {
14
+ config = (0, core_1.readConfigFile)(info.project.getProjectName());
15
+ // TODO: Report diagnostics
16
+ info.project.projectService.logger.info(`[@css-modules-kit/ts-plugin] info: Config file is found '${config.configFileName}'`);
17
+ }
18
+ catch (error) {
19
+ // If the config file is not found, disable the plugin.
20
+ if (error instanceof core_2.TsConfigFileNotFoundError) {
21
+ return { languagePlugins: [] };
22
+ }
23
+ else {
24
+ let msg = `[@css-modules-kit/ts-plugin] error: Fail to read config file`;
25
+ if (error instanceof Error) {
26
+ msg += `\n: ${error.message}`;
27
+ msg += `\n${error.stack}`;
28
+ }
29
+ info.project.projectService.logger.info(msg);
30
+ return { languagePlugins: [] };
31
+ }
32
+ }
33
+ const resolver = (0, core_1.createResolver)(config.paths);
34
+ const matchesPattern = (0, core_1.createMatchesPattern)(config);
35
+ return {
36
+ languagePlugins: [(0, language_plugin_js_1.createCSSModuleLanguagePlugin)(config, resolver, matchesPattern)],
37
+ setup: (language) => {
38
+ info.languageService = (0, proxy_js_1.proxyLanguageService)(language, info.languageService, info.project, resolver, matchesPattern);
39
+ },
40
+ };
41
+ });
42
+ module.exports = plugin;
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,oHAA8G;AAE9G,gDAA6F;AAC7F,gDAAkE;AAClE,6DAAqE;AACrE,0DAAmE;AAEnE,MAAM,MAAM,GAAG,IAAA,4DAA2B,EAAC,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;IACtD,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;QAClE,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;QACxG,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IACjC,CAAC;IAED,IAAI,MAAiB,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,GAAG,IAAA,qBAAc,EAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;QACvD,2BAA2B;QAC3B,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CACrC,4DAA4D,MAAM,CAAC,cAAc,GAAG,CACrF,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uDAAuD;QACvD,IAAI,KAAK,YAAY,gCAAyB,EAAE,CAAC;YAC/C,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,GAAG,8DAA8D,CAAC;YACzE,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,GAAG,IAAI,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC9B,GAAG,IAAI,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;YAC5B,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC7C,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;QACjC,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,IAAA,qBAAc,EAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,cAAc,GAAG,IAAA,2BAAoB,EAAC,MAAM,CAAC,CAAC;IAEpD,OAAO;QACL,eAAe,EAAE,CAAC,IAAA,kDAA6B,EAAC,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;QAClF,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE;YAClB,IAAI,CAAC,eAAe,GAAG,IAAA,+BAAoB,EACzC,QAAQ,EACR,IAAI,CAAC,eAAe,EACpB,IAAI,CAAC,OAAO,EACZ,QAAQ,EACR,cAAc,CACf,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,iBAAS,MAAM,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { LanguagePlugin, SourceScript, VirtualCode } from '@volar/language-core';
2
+ import type { CSSModule, CMKConfig, MatchesPattern, Resolver, SyntacticDiagnostic } from '@css-modules-kit/core';
3
+ export declare const LANGUAGE_ID = "css-module";
4
+ export declare const CMK_DATA_KEY: unique symbol;
5
+ interface CSSModuleVirtualCode extends VirtualCode {
6
+ [CMK_DATA_KEY]: {
7
+ cssModule: CSSModule;
8
+ diagnostics: SyntacticDiagnostic[];
9
+ };
10
+ }
11
+ export interface CSSModuleScript extends SourceScript<string> {
12
+ generated: SourceScript<string>['generated'] & {
13
+ root: CSSModuleVirtualCode;
14
+ };
15
+ }
16
+ export declare function createCSSModuleLanguagePlugin(config: CMKConfig, resolver: Resolver, matchesPattern: MatchesPattern): LanguagePlugin<string, VirtualCode>;
17
+ export declare function isCSSModuleScript(script: SourceScript<string> | undefined): script is CSSModuleScript;
18
+ export {};
19
+ //# sourceMappingURL=language-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"language-plugin.d.ts","sourceRoot":"","sources":["../src/language-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEtF,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAIjH,eAAO,MAAM,WAAW,eAAe,CAAC;AAExC,eAAO,MAAM,YAAY,eAAiC,CAAC;AAE3D,UAAU,oBAAqB,SAAQ,WAAW;IAChD,CAAC,YAAY,CAAC,EAAE;QACd,SAAS,EAAE,SAAS,CAAC;QACrB,WAAW,EAAE,mBAAmB,EAAE,CAAC;KACpC,CAAC;CACH;AAED,MAAM,WAAW,eAAgB,SAAQ,YAAY,CAAC,MAAM,CAAC;IAC3D,SAAS,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,GAAG;QAC7C,IAAI,EAAE,oBAAoB,CAAC;KAC5B,CAAC;CACH;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,cAAc,GAC7B,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAsDrC;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,IAAI,eAAe,CAIrG"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CMK_DATA_KEY = exports.LANGUAGE_ID = void 0;
7
+ exports.createCSSModuleLanguagePlugin = createCSSModuleLanguagePlugin;
8
+ exports.isCSSModuleScript = isCSSModuleScript;
9
+ const core_1 = require("@css-modules-kit/core");
10
+ const typescript_1 = __importDefault(require("typescript"));
11
+ exports.LANGUAGE_ID = 'css-module';
12
+ exports.CMK_DATA_KEY = Symbol('css-modules-kit-data');
13
+ function createCSSModuleLanguagePlugin(config, resolver, matchesPattern) {
14
+ return {
15
+ getLanguageId(scriptId) {
16
+ if (!matchesPattern(scriptId))
17
+ return undefined;
18
+ return exports.LANGUAGE_ID;
19
+ },
20
+ createVirtualCode(scriptId, languageId, snapshot) {
21
+ if (languageId !== exports.LANGUAGE_ID)
22
+ return undefined;
23
+ const length = snapshot.getLength();
24
+ const cssModuleCode = snapshot.getText(0, length);
25
+ const { cssModule, diagnostics } = (0, core_1.parseCSSModule)(cssModuleCode, {
26
+ fileName: scriptId,
27
+ dashedIdents: config.dashedIdents,
28
+ // The CSS in the process of being written in an editor often contains invalid syntax.
29
+ // So, ts-plugin uses a fault-tolerant Parser to parse CSS.
30
+ safe: true,
31
+ });
32
+ const { text, mapping, linkedCodeMapping } = (0, core_1.createDts)(cssModule, { resolver, matchesPattern });
33
+ return {
34
+ id: 'main',
35
+ languageId: exports.LANGUAGE_ID,
36
+ snapshot: {
37
+ getText: (start, end) => text.slice(start, end),
38
+ getLength: () => text.length,
39
+ getChangeRange: () => undefined,
40
+ },
41
+ // `mappings` are required to support "Go to Definition" and renaming
42
+ mappings: [{ ...mapping, data: { navigation: true } }],
43
+ // `linkedCodeMappings` are required to support "Go to Definition" and renaming for the imported tokens
44
+ linkedCodeMappings: [{ ...linkedCodeMapping, data: undefined }],
45
+ [exports.CMK_DATA_KEY]: {
46
+ cssModule,
47
+ diagnostics,
48
+ },
49
+ };
50
+ },
51
+ typescript: {
52
+ extraFileExtensions: [
53
+ {
54
+ extension: 'css',
55
+ isMixedContent: true,
56
+ scriptKind: typescript_1.default.ScriptKind.TS,
57
+ },
58
+ ],
59
+ getServiceScript(root) {
60
+ return {
61
+ code: root,
62
+ extension: typescript_1.default.Extension.Ts,
63
+ scriptKind: typescript_1.default.ScriptKind.TS,
64
+ };
65
+ },
66
+ },
67
+ };
68
+ }
69
+ function isCSSModuleScript(script) {
70
+ return (!!script && script.languageId === exports.LANGUAGE_ID && !!script.generated?.root && exports.CMK_DATA_KEY in script.generated.root);
71
+ }
72
+ //# sourceMappingURL=language-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"language-plugin.js","sourceRoot":"","sources":["../src/language-plugin.ts"],"names":[],"mappings":";;;;;;AAuBA,sEA0DC;AAED,8CAIC;AApFD,gDAAkE;AAClE,4DAA4B;AAEf,QAAA,WAAW,GAAG,YAAY,CAAC;AAE3B,QAAA,YAAY,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAe3D,SAAgB,6BAA6B,CAC3C,MAAiB,EACjB,QAAkB,EAClB,cAA8B;IAE9B,OAAO;QACL,aAAa,CAAC,QAAQ;YACpB,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC;gBAAE,OAAO,SAAS,CAAC;YAChD,OAAO,mBAAW,CAAC;QACrB,CAAC;QACD,iBAAiB,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ;YAC9C,IAAI,UAAU,KAAK,mBAAW;gBAAE,OAAO,SAAS,CAAC;YAEjD,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC;YACpC,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YAClD,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,IAAA,qBAAc,EAAC,aAAa,EAAE;gBAC/D,QAAQ,EAAE,QAAQ;gBAClB,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,sFAAsF;gBACtF,2DAA2D;gBAC3D,IAAI,EAAE,IAAI;aACX,CAAC,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,IAAA,gBAAS,EAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;YAChG,OAAO;gBACL,EAAE,EAAE,MAAM;gBACV,UAAU,EAAE,mBAAW;gBACvB,QAAQ,EAAE;oBACR,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC;oBAC/C,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM;oBAC5B,cAAc,EAAE,GAAG,EAAE,CAAC,SAAS;iBAChC;gBACD,qEAAqE;gBACrE,QAAQ,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;gBACtD,uGAAuG;gBACvG,kBAAkB,EAAE,CAAC,EAAE,GAAG,iBAAiB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;gBAC/D,CAAC,oBAAY,CAAC,EAAE;oBACd,SAAS;oBACT,WAAW;iBACZ;aACF,CAAC;QACJ,CAAC;QACD,UAAU,EAAE;YACV,mBAAmB,EAAE;gBACnB;oBACE,SAAS,EAAE,KAAK;oBAChB,cAAc,EAAE,IAAI;oBACpB,UAAU,EAAE,oBAAE,CAAC,UAAU,CAAC,EAAE;iBAC7B;aACF;YACD,gBAAgB,CAAC,IAAI;gBACnB,OAAO;oBACL,IAAI,EAAE,IAAI;oBACV,SAAS,EAAE,oBAAE,CAAC,SAAS,CAAC,EAAE;oBAC1B,UAAU,EAAE,oBAAE,CAAC,UAAU,CAAC,EAAE;iBAC7B,CAAC;YACJ,CAAC;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAgB,iBAAiB,CAAC,MAAwC;IACxE,OAAO,CACL,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,mBAAW,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,IAAI,oBAAY,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,CACnH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Language } from '@volar/language-core';
2
+ import ts from 'typescript';
3
+ export declare const PROPERTY_DOES_NOT_EXIST_ERROR_CODE = 2339;
4
+ export declare function getCodeFixesAtPosition(language: Language<string>, languageService: ts.LanguageService, project: ts.server.Project): ts.LanguageService['getCodeFixesAtPosition'];
5
+ //# sourceMappingURL=code-fix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-fix.d.ts","sourceRoot":"","sources":["../../../src/language-service/feature/code-fix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5B,eAAO,MAAM,kCAAkC,OAAO,CAAC;AAEvD,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC1B,eAAe,EAAE,EAAE,CAAC,eAAe,EACnC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,GACzB,EAAE,CAAC,eAAe,CAAC,wBAAwB,CAAC,CAuB9C"}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PROPERTY_DOES_NOT_EXIST_ERROR_CODE = void 0;
7
+ exports.getCodeFixesAtPosition = getCodeFixesAtPosition;
8
+ const core_1 = require("@css-modules-kit/core");
9
+ const typescript_1 = __importDefault(require("typescript"));
10
+ const language_plugin_js_1 = require("../../language-plugin.js");
11
+ // ref: https://github.com/microsoft/TypeScript/blob/220706eb0320ff46fad8bf80a5e99db624ee7dfb/src/compiler/diagnosticMessages.json#L2051-L2054
12
+ exports.PROPERTY_DOES_NOT_EXIST_ERROR_CODE = 2339;
13
+ function getCodeFixesAtPosition(language, languageService, project) {
14
+ // eslint-disable-next-line max-params
15
+ return (fileName, start, end, errorCodes, formatOptions, preferences) => {
16
+ const prior = Array.from(languageService.getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences) ?? []);
17
+ if ((0, core_1.isComponentFileName)(fileName)) {
18
+ // If a user is trying to use a non-existent token (e.g. `styles.nonExistToken`), provide a code fix to add the token.
19
+ if (errorCodes.includes(exports.PROPERTY_DOES_NOT_EXIST_ERROR_CODE)) {
20
+ const tokenConsumer = getTokenConsumerAtPosition(fileName, start, language, languageService, project);
21
+ if (tokenConsumer) {
22
+ prior.push({
23
+ fixName: 'fixMissingCSSRule',
24
+ description: `Add missing CSS rule '.${tokenConsumer.tokenName}'`,
25
+ changes: [createInsertRuleFileChange(tokenConsumer.from, tokenConsumer.tokenName, language)],
26
+ });
27
+ }
28
+ }
29
+ }
30
+ return prior;
31
+ };
32
+ }
33
+ /**
34
+ * Get the token consumer at the specified position.
35
+ * If the position is at `styles.foo`, it returns `{ tokenName: 'foo', from: '/path/to/a.module.css' }`.
36
+ */
37
+ function getTokenConsumerAtPosition(fileName, position, language, languageService, project) {
38
+ const sourceFile = project.getSourceFile(project.projectService.toPath(fileName));
39
+ if (!sourceFile)
40
+ return undefined;
41
+ const propertyAccessExpression = getPropertyAccessExpressionAtPosition(sourceFile, position);
42
+ if (!propertyAccessExpression)
43
+ return undefined;
44
+ // Check if the expression of property access expression (e.g. `styles` in `styles.foo`) is imported from a CSS module.
45
+ // `expression` is the expression of the property access expression (e.g. `styles` in `styles.foo`).
46
+ const expression = propertyAccessExpression.expression;
47
+ const definitions = languageService.getDefinitionAtPosition(fileName, expression.getStart());
48
+ if (definitions && definitions[0]) {
49
+ const script = language.scripts.get(definitions[0].fileName);
50
+ if ((0, language_plugin_js_1.isCSSModuleScript)(script)) {
51
+ return { tokenName: propertyAccessExpression.name.text, from: definitions[0].fileName };
52
+ }
53
+ }
54
+ return undefined;
55
+ }
56
+ /** Get the property access expression at the specified position. (e.g. `obj.foo`, `styles.foo`) */
57
+ function getPropertyAccessExpressionAtPosition(sourceFile, position) {
58
+ function getPropertyAccessExpressionImpl(node) {
59
+ if (node.pos <= position && position <= node.end && typescript_1.default.isPropertyAccessExpression(node)) {
60
+ return node;
61
+ }
62
+ return typescript_1.default.forEachChild(node, getPropertyAccessExpressionImpl);
63
+ }
64
+ return getPropertyAccessExpressionImpl(sourceFile);
65
+ }
66
+ function createInsertRuleFileChange(cssModuleFileName, className, language) {
67
+ const script = language.scripts.get(cssModuleFileName);
68
+ if (script) {
69
+ return {
70
+ fileName: cssModuleFileName,
71
+ textChanges: [{ span: { start: script.snapshot.getLength(), length: 0 }, newText: `\n.${className} {\n \n}` }],
72
+ isNewFile: false,
73
+ };
74
+ }
75
+ else {
76
+ return {
77
+ fileName: cssModuleFileName,
78
+ textChanges: [{ span: { start: 0, length: 0 }, newText: `.${className} {\n \n}\n\n` }],
79
+ isNewFile: true,
80
+ };
81
+ }
82
+ }
83
+ //# sourceMappingURL=code-fix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-fix.js","sourceRoot":"","sources":["../../../src/language-service/feature/code-fix.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import ts from 'typescript';
2
+ export declare function getCompletionsAtPosition(languageService: ts.LanguageService): ts.LanguageService['getCompletionsAtPosition'];
3
+ //# sourceMappingURL=completion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../../src/language-service/feature/completion.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,wBAAgB,wBAAwB,CACtC,eAAe,EAAE,EAAE,CAAC,eAAe,GAClC,EAAE,CAAC,eAAe,CAAC,0BAA0B,CAAC,CAmBhD"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getCompletionsAtPosition = getCompletionsAtPosition;
7
+ const core_1 = require("@css-modules-kit/core");
8
+ const typescript_1 = __importDefault(require("typescript"));
9
+ function getCompletionsAtPosition(languageService) {
10
+ return (fileName, position, options, formattingSettings) => {
11
+ const prior = languageService.getCompletionsAtPosition(fileName, position, options, formattingSettings);
12
+ if ((0, core_1.isComponentFileName)(fileName) && prior) {
13
+ const cssModuleFileName = (0, core_1.getCssModuleFileName)(fileName);
14
+ for (const entry of prior.entries) {
15
+ if (isStylesEntryForCSSModuleFile(entry, cssModuleFileName)) {
16
+ // Prioritize the completion of the `styles' import for the current .ts file for usability.
17
+ // NOTE: This is a hack to make the completion item appear at the top
18
+ entry.sortText = '0';
19
+ }
20
+ else if (isClassNamePropEntry(entry)) {
21
+ // Complete `className={...}` instead of `className="..."` for usability.
22
+ entry.insertText = 'className={$1}';
23
+ }
24
+ }
25
+ }
26
+ return prior;
27
+ };
28
+ }
29
+ /**
30
+ * Check if the completion entry is the `styles` entry for the CSS module file.
31
+ */
32
+ function isStylesEntryForCSSModuleFile(entry, cssModuleFileName) {
33
+ return (entry.name === core_1.STYLES_EXPORT_NAME &&
34
+ entry.data &&
35
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
36
+ entry.data.exportName === typescript_1.default.InternalSymbolName.Default &&
37
+ entry.data.fileName &&
38
+ entry.data.fileName === cssModuleFileName);
39
+ }
40
+ function isClassNamePropEntry(entry) {
41
+ return (entry.name === 'className' &&
42
+ entry.kind === typescript_1.default.ScriptElementKind.memberVariableElement &&
43
+ entry.insertText === 'className="$1"' &&
44
+ entry.isSnippet);
45
+ }
46
+ //# sourceMappingURL=completion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.js","sourceRoot":"","sources":["../../../src/language-service/feature/completion.ts"],"names":[],"mappings":";;;;;AAGA,4DAqBC;AAxBD,gDAAsG;AACtG,4DAA4B;AAE5B,SAAgB,wBAAwB,CACtC,eAAmC;IAEnC,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,kBAAkB,EAAE,EAAE;QACzD,MAAM,KAAK,GAAG,eAAe,CAAC,wBAAwB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC;QAExG,IAAI,IAAA,0BAAmB,EAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC;YAC3C,MAAM,iBAAiB,GAAG,IAAA,2BAAoB,EAAC,QAAQ,CAAC,CAAC;YACzD,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBAClC,IAAI,6BAA6B,CAAC,KAAK,EAAE,iBAAiB,CAAC,EAAE,CAAC;oBAC5D,2FAA2F;oBAC3F,qEAAqE;oBACrE,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAC;gBACvB,CAAC;qBAAM,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;oBACvC,yEAAyE;oBACzE,KAAK,CAAC,UAAU,GAAG,gBAAgB,CAAC;gBACtC,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,6BAA6B,CAAC,KAAyB,EAAE,iBAAyB;IACzF,OAAO,CACL,KAAK,CAAC,IAAI,KAAK,yBAAkB;QACjC,KAAK,CAAC,IAAI;QACV,wEAAwE;QACxE,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,oBAAE,CAAC,kBAAkB,CAAC,OAAO;QACvD,KAAK,CAAC,IAAI,CAAC,QAAQ;QACnB,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,iBAAiB,CAC1C,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAyB;IACrD,OAAO,CACL,KAAK,CAAC,IAAI,KAAK,WAAW;QAC1B,KAAK,CAAC,IAAI,KAAK,oBAAE,CAAC,iBAAiB,CAAC,qBAAqB;QACzD,KAAK,CAAC,UAAU,KAAK,gBAAgB;QACrC,KAAK,CAAC,SAAS,CAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type ts from 'typescript';
2
+ export declare const createCssModuleFileRefactor: {
3
+ readonly name: "Create CSS Module file";
4
+ readonly description: "Create CSS Module file";
5
+ readonly actions: [{
6
+ readonly name: "Create CSS Module file";
7
+ readonly description: "Create CSS Module file for current file";
8
+ }];
9
+ };
10
+ export declare function getApplicableRefactors(languageService: ts.LanguageService, project: ts.server.Project): ts.LanguageService['getApplicableRefactors'];
11
+ export declare function getEditsForRefactor(languageService: ts.LanguageService): ts.LanguageService['getEditsForRefactor'];
12
+ //# sourceMappingURL=refactor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refactor.d.ts","sourceRoot":"","sources":["../../../src/language-service/feature/refactor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,eAAO,MAAM,2BAA2B;;;;;;;CAIM,CAAC;AAE/C,wBAAgB,sBAAsB,CACpC,eAAe,EAAE,EAAE,CAAC,eAAe,EACnC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,GACzB,EAAE,CAAC,eAAe,CAAC,wBAAwB,CAAC,CAW9C;AAED,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,EAAE,CAAC,eAAe,GAAG,EAAE,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAkBlH"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCssModuleFileRefactor = void 0;
4
+ exports.getApplicableRefactors = getApplicableRefactors;
5
+ exports.getEditsForRefactor = getEditsForRefactor;
6
+ const core_1 = require("@css-modules-kit/core");
7
+ exports.createCssModuleFileRefactor = {
8
+ name: 'Create CSS Module file',
9
+ description: 'Create CSS Module file',
10
+ actions: [{ name: 'Create CSS Module file', description: 'Create CSS Module file for current file' }],
11
+ };
12
+ function getApplicableRefactors(languageService, project) {
13
+ return (fileName, positionOrRange, preferences) => {
14
+ const prior = languageService.getApplicableRefactors(fileName, positionOrRange, preferences) ?? [];
15
+ if ((0, core_1.isComponentFileName)(fileName)) {
16
+ // If the CSS Module file does not exist, provide a refactor to create it.
17
+ if (!project.fileExists((0, core_1.getCssModuleFileName)(fileName))) {
18
+ prior.push(exports.createCssModuleFileRefactor);
19
+ }
20
+ }
21
+ return prior;
22
+ };
23
+ }
24
+ function getEditsForRefactor(languageService) {
25
+ // eslint-disable-next-line max-params
26
+ return (fileName, formatOptions, positionOrRange, refactorName, actionName, preferences) => {
27
+ const prior = languageService.getEditsForRefactor(fileName, formatOptions, positionOrRange, refactorName, actionName, preferences) ?? { edits: [] };
28
+ if ((0, core_1.isComponentFileName)(fileName)) {
29
+ if (refactorName === exports.createCssModuleFileRefactor.name) {
30
+ prior.edits.push(createNewCssModuleFileChange((0, core_1.getCssModuleFileName)(fileName)));
31
+ }
32
+ }
33
+ return prior;
34
+ };
35
+ }
36
+ function createNewCssModuleFileChange(cssFilename) {
37
+ return {
38
+ fileName: cssFilename,
39
+ textChanges: [{ span: { start: 0, length: 0 }, newText: '' }],
40
+ isNewFile: true,
41
+ };
42
+ }
43
+ //# sourceMappingURL=refactor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refactor.js","sourceRoot":"","sources":["../../../src/language-service/feature/refactor.ts"],"names":[],"mappings":";;;AASA,wDAcC;AAED,kDAkBC;AA3CD,gDAAkF;AAGrE,QAAA,2BAA2B,GAAG;IACzC,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,wBAAwB;IACrC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,wBAAwB,EAAE,WAAW,EAAE,yCAAyC,EAAE,CAAC;CACzD,CAAC;AAE/C,SAAgB,sBAAsB,CACpC,eAAmC,EACnC,OAA0B;IAE1B,OAAO,CAAC,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,EAAE;QAChD,MAAM,KAAK,GAAG,eAAe,CAAC,sBAAsB,CAAC,QAAQ,EAAE,eAAe,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC;QACnG,IAAI,IAAA,0BAAmB,EAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,0EAA0E;YAC1E,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAA,2BAAoB,EAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;gBACxD,KAAK,CAAC,IAAI,CAAC,mCAA2B,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,mBAAmB,CAAC,eAAmC;IACrE,sCAAsC;IACtC,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE;QACzF,MAAM,KAAK,GAAG,eAAe,CAAC,mBAAmB,CAC/C,QAAQ,EACR,aAAa,EACb,eAAe,EACf,YAAY,EACZ,UAAU,EACV,WAAW,CACZ,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QACnB,IAAI,IAAA,0BAAmB,EAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,IAAI,YAAY,KAAK,mCAA2B,CAAC,IAAI,EAAE,CAAC;gBACtD,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,IAAA,2BAAoB,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,4BAA4B,CAAC,WAAmB;IACvD,OAAO;QACL,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC7D,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Language } from '@volar/language-core';
2
+ import type { CSSModule, ExportBuilder, MatchesPattern, Resolver } from '@css-modules-kit/core';
3
+ import ts from 'typescript';
4
+ export declare function getSemanticDiagnostics(language: Language<string>, languageService: ts.LanguageService, exportBuilder: ExportBuilder, resolver: Resolver, matchesPattern: MatchesPattern, getCSSModule: (path: string) => CSSModule | undefined): ts.LanguageService['getSemanticDiagnostics'];
5
+ //# sourceMappingURL=semantic-diagnostic.d.ts.map