@weapp-vite/volar 0.0.2 → 1.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.
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # @weapp-vite/volar
2
+
3
+ > 为 weapp-vite 提供 VSCode 智能提示和类型检查的 Volar 插件
4
+
5
+ ## 安装
6
+
7
+ 此包已作为 `weapp-vite` 的依赖自动安装,**无需单独安装**。
8
+
9
+ 如果你确实需要单独安装:
10
+
11
+ ```bash
12
+ npm install -D @weapp-vite/volar
13
+ # or
14
+ pnpm add -D @weapp-vite/volar
15
+ # or
16
+ yarn add -D @weapp-vite/volar
17
+ ```
18
+
19
+ ## 使用方法
20
+
21
+ **推荐方式:** 通过 weapp-vite 使用,插件会自动启用。
22
+
23
+ 详细使用文档请参考:[weapp-vite Volar 文档](../weapp-vite/docs/volar.md)
24
+
25
+ ## 功能特性
26
+
27
+ - ✅ **配置文件智能提示** - 为 `<json>` 代码块提供完整的类型检查和自动补全
28
+ - ✅ **JSON Schema 支持** - 支持 JSON Schema 验证和自动补全
29
+ - ✅ **TypeScript 类型检查** - 利用 TypeScript 类型系统确保配置正确性
30
+ - ✅ **自动推断配置类型** - 根据文件路径自动推断是 App/Page/Component 配置
31
+ - ✅ **多模式支持** - 支持 JSON 模式和 TypeScript 模式
32
+
33
+ ## 开发
34
+
35
+ ```bash
36
+ # 安装依赖
37
+ pnpm install
38
+
39
+ # 开发模式
40
+ pnpm dev
41
+
42
+ # 构建
43
+ pnpm build
44
+
45
+ # 测试
46
+ pnpm test
47
+ ```
48
+
49
+ ## 相关文档
50
+
51
+ - [weapp-vite 文档](../weapp-vite)
52
+ - [weapp-vite Volar 使用指南](../weapp-vite/docs/volar.md)
53
+ - [Vue 3 文档](https://vuejs.org/)
54
+ - [微信小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/framework/)
55
+
56
+ ## License
57
+
58
+ MIT
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});// ../../node_modules/.pnpm/tsup@8.5.0_@swc+core@1.14.0_jiti@2.6.1_postcss@8.5.6_tsx@4.20.6_typescript@5.9.3_yaml@2.8.1/node_modules/tsup/assets/cjs_shims.js
2
- var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// ../../node_modules/.pnpm/tsup@8.5.1_@swc+core@1.15.8_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/cjs_shims.js
2
+ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
3
3
  var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
4
4
 
5
5
  // src/index.ts
@@ -8,11 +8,24 @@ var _module = require('module');
8
8
  // package.json
9
9
  var name = "@weapp-vite/volar";
10
10
 
11
+ // src/schema.ts
12
+ var _schematics = require('@weapp-core/schematics');
13
+ function getSchemaForType(type) {
14
+ const definition = _schematics.JSON_SCHEMA_DEFINITIONS.find((d) => d.typeName === type);
15
+ if (!definition) {
16
+ return null;
17
+ }
18
+ return definition.schema;
19
+ }
20
+
11
21
  // src/index.ts
12
- var BLOCK_TYPE = "config";
22
+ var BLOCK_TYPE = "json";
23
+ var JS_LANG = "js";
24
+ var JSONC_LANG = "jsonc";
13
25
  var JSON_LANG = "json";
14
- var TS_LANG = "ts";
26
+ var JSON5_LANG = "json5";
15
27
  var PLUGIN_VERSION = 2.2;
28
+ var TS_LANG = "ts";
16
29
  var FULL_CAPABILITIES = {
17
30
  verification: true,
18
31
  completion: true,
@@ -37,15 +50,6 @@ try {
37
50
  } catch (e) {
38
51
  hasSchematicsTypes = false;
39
52
  }
40
- function normalizeLang(lang) {
41
- if (!lang) {
42
- return JSON_LANG;
43
- }
44
- if (lang === "txt") {
45
- return JSON_LANG;
46
- }
47
- return lang;
48
- }
49
53
  function normalizeFilename(filename) {
50
54
  if (!filename) {
51
55
  return "";
@@ -71,7 +75,77 @@ function inferConfigType(filename) {
71
75
  }
72
76
  return "Page";
73
77
  }
74
- var plugin = () => {
78
+ function normalizeLang(lang) {
79
+ if (!lang) {
80
+ return JSON_LANG;
81
+ }
82
+ const lower = lang.toLowerCase();
83
+ if (lower === "txt") {
84
+ return JSON_LANG;
85
+ }
86
+ return lower;
87
+ }
88
+ function findExportDefaultExpression(code, tsModule, lang) {
89
+ const scriptKind = lang === TS_LANG ? tsModule.ScriptKind.TS : tsModule.ScriptKind.JS;
90
+ const sourceFile = tsModule.createSourceFile(
91
+ `config.${lang}`,
92
+ code,
93
+ tsModule.ScriptTarget.Latest,
94
+ true,
95
+ scriptKind
96
+ );
97
+ for (const statement of sourceFile.statements) {
98
+ if (tsModule.isExportAssignment(statement)) {
99
+ const expressionStart = statement.expression.getStart(sourceFile);
100
+ const expressionEnd = statement.expression.getEnd();
101
+ const leading = code.slice(0, statement.getStart(sourceFile));
102
+ const expression = code.slice(expressionStart, expressionEnd);
103
+ const trailing = code.slice(statement.getEnd());
104
+ return {
105
+ expression,
106
+ expressionStart,
107
+ expressionEnd,
108
+ leading,
109
+ trailing
110
+ };
111
+ }
112
+ }
113
+ return null;
114
+ }
115
+ function injectSchemaIntoJsonObject(content, schemaId) {
116
+ const trimmed = content.trim();
117
+ if (!trimmed.startsWith("{")) {
118
+ return content;
119
+ }
120
+ const leftBraceIndex = content.indexOf("{");
121
+ if (leftBraceIndex < 0) {
122
+ return content;
123
+ }
124
+ const afterLeft = content.slice(leftBraceIndex + 1);
125
+ const firstNonSpace = afterLeft.match(/\S/);
126
+ const nextCharIndex = firstNonSpace ? leftBraceIndex + 1 + firstNonSpace.index : -1;
127
+ const isEmptyObject = nextCharIndex >= 0 && content[nextCharIndex] === "}";
128
+ const schemaLine = ` "$schema": "${schemaId}"`;
129
+ const injected = isEmptyObject ? `{
130
+ ${schemaLine}
131
+ }` : `{
132
+ ${schemaLine},${content.slice(leftBraceIndex + 1)}`;
133
+ if (trimmed === content) {
134
+ return injected;
135
+ }
136
+ const leading = content.slice(0, content.indexOf(trimmed));
137
+ const trailing = content.slice(content.indexOf(trimmed) + trimmed.length);
138
+ return `${leading}${injected}${trailing}`;
139
+ }
140
+ var plugin = (ctx) => {
141
+ let tsModule = _optionalChain([ctx, 'optionalAccess', _2 => _2.modules, 'optionalAccess', _3 => _3.typescript]);
142
+ if (!tsModule) {
143
+ try {
144
+ tsModule = require2("typescript");
145
+ } catch (e2) {
146
+ tsModule = void 0;
147
+ }
148
+ }
75
149
  return {
76
150
  name,
77
151
  version: PLUGIN_VERSION,
@@ -81,8 +155,13 @@ var plugin = () => {
81
155
  const block = sfc.customBlocks[i];
82
156
  if (block.type === BLOCK_TYPE) {
83
157
  const normalizedLang = normalizeLang(block.lang);
84
- const lang = hasSchematicsTypes ? TS_LANG : normalizedLang;
85
- names.push({ id: `${BLOCK_TYPE}_${i}`, lang });
158
+ const isJsLike = normalizedLang === JS_LANG || normalizedLang === TS_LANG;
159
+ if (isJsLike) {
160
+ names.push({ id: `${BLOCK_TYPE}_${i}`, lang: TS_LANG });
161
+ continue;
162
+ }
163
+ const embeddedLang = normalizedLang === JSON_LANG || normalizedLang === JSONC_LANG || normalizedLang === JSON5_LANG ? JSONC_LANG : JSON_LANG;
164
+ names.push({ id: `${BLOCK_TYPE}_${i}`, lang: embeddedLang });
86
165
  }
87
166
  }
88
167
  return names;
@@ -97,6 +176,8 @@ var plugin = () => {
97
176
  if (!block) {
98
177
  return;
99
178
  }
179
+ const normalizedLang = normalizeLang(block.lang);
180
+ const configType = inferConfigType(fileName);
100
181
  if (!hasSchematicsTypes) {
101
182
  embeddedCode.content.push([
102
183
  block.content,
@@ -106,29 +187,79 @@ var plugin = () => {
106
187
  ]);
107
188
  return;
108
189
  }
109
- const configType = inferConfigType(fileName);
110
- const prefix = `import type { ${configType} as __WeappConfig } from '@weapp-core/schematics'
111
-
112
- export default `;
113
- const suffix = " satisfies __WeappConfig\n";
114
- embeddedCode.content.push([
115
- prefix,
116
- void 0,
117
- 0,
118
- VOID_CAPABILITIES
119
- ]);
190
+ const userWantsJs = normalizedLang === JS_LANG || normalizedLang === TS_LANG;
191
+ if (userWantsJs) {
192
+ const parsed = tsModule && findExportDefaultExpression(block.content, tsModule, normalizedLang);
193
+ if (parsed && hasSchematicsTypes) {
194
+ const typeImport = `import type { ${configType} as __WeappConfig } from '@weapp-core/schematics'
195
+ `;
196
+ const helper = "const __weapp_defineConfig = <T extends __WeappConfig>(config: T) => config\n\n";
197
+ embeddedCode.content.push([
198
+ `${typeImport}${helper}`,
199
+ void 0,
200
+ 0,
201
+ VOID_CAPABILITIES
202
+ ]);
203
+ if (parsed.leading) {
204
+ embeddedCode.content.push([
205
+ parsed.leading,
206
+ block.name,
207
+ 0,
208
+ FULL_CAPABILITIES
209
+ ]);
210
+ }
211
+ embeddedCode.content.push([
212
+ "export default __weapp_defineConfig(",
213
+ void 0,
214
+ parsed.expressionStart,
215
+ VOID_CAPABILITIES
216
+ ]);
217
+ embeddedCode.content.push([
218
+ parsed.expression,
219
+ block.name,
220
+ parsed.expressionStart,
221
+ FULL_CAPABILITIES
222
+ ]);
223
+ embeddedCode.content.push([
224
+ ")",
225
+ void 0,
226
+ parsed.expressionEnd,
227
+ VOID_CAPABILITIES
228
+ ]);
229
+ if (parsed.trailing) {
230
+ embeddedCode.content.push([
231
+ parsed.trailing,
232
+ block.name,
233
+ parsed.expressionEnd,
234
+ FULL_CAPABILITIES
235
+ ]);
236
+ }
237
+ return;
238
+ }
239
+ embeddedCode.content.push([
240
+ block.content,
241
+ block.name,
242
+ 0,
243
+ FULL_CAPABILITIES
244
+ ]);
245
+ return;
246
+ }
247
+ const schema = getSchemaForType(configType);
248
+ if (schema && schema.$id && !block.content.includes("$schema")) {
249
+ embeddedCode.content.push([
250
+ injectSchemaIntoJsonObject(block.content, schema.$id),
251
+ block.name,
252
+ 0,
253
+ FULL_CAPABILITIES
254
+ ]);
255
+ return;
256
+ }
120
257
  embeddedCode.content.push([
121
258
  block.content,
122
259
  block.name,
123
260
  0,
124
261
  FULL_CAPABILITIES
125
262
  ]);
126
- embeddedCode.content.push([
127
- suffix,
128
- void 0,
129
- block.content.length,
130
- VOID_CAPABILITIES
131
- ]);
132
263
  }
133
264
  };
134
265
  };
package/dist/index.mjs CHANGED
@@ -4,11 +4,24 @@ import { createRequire } from "module";
4
4
  // package.json
5
5
  var name = "@weapp-vite/volar";
6
6
 
7
+ // src/schema.ts
8
+ import { JSON_SCHEMA_DEFINITIONS } from "@weapp-core/schematics";
9
+ function getSchemaForType(type) {
10
+ const definition = JSON_SCHEMA_DEFINITIONS.find((d) => d.typeName === type);
11
+ if (!definition) {
12
+ return null;
13
+ }
14
+ return definition.schema;
15
+ }
16
+
7
17
  // src/index.ts
8
- var BLOCK_TYPE = "config";
18
+ var BLOCK_TYPE = "json";
19
+ var JS_LANG = "js";
20
+ var JSONC_LANG = "jsonc";
9
21
  var JSON_LANG = "json";
10
- var TS_LANG = "ts";
22
+ var JSON5_LANG = "json5";
11
23
  var PLUGIN_VERSION = 2.2;
24
+ var TS_LANG = "ts";
12
25
  var FULL_CAPABILITIES = {
13
26
  verification: true,
14
27
  completion: true,
@@ -33,15 +46,6 @@ try {
33
46
  } catch {
34
47
  hasSchematicsTypes = false;
35
48
  }
36
- function normalizeLang(lang) {
37
- if (!lang) {
38
- return JSON_LANG;
39
- }
40
- if (lang === "txt") {
41
- return JSON_LANG;
42
- }
43
- return lang;
44
- }
45
49
  function normalizeFilename(filename) {
46
50
  if (!filename) {
47
51
  return "";
@@ -67,7 +71,77 @@ function inferConfigType(filename) {
67
71
  }
68
72
  return "Page";
69
73
  }
70
- var plugin = () => {
74
+ function normalizeLang(lang) {
75
+ if (!lang) {
76
+ return JSON_LANG;
77
+ }
78
+ const lower = lang.toLowerCase();
79
+ if (lower === "txt") {
80
+ return JSON_LANG;
81
+ }
82
+ return lower;
83
+ }
84
+ function findExportDefaultExpression(code, tsModule, lang) {
85
+ const scriptKind = lang === TS_LANG ? tsModule.ScriptKind.TS : tsModule.ScriptKind.JS;
86
+ const sourceFile = tsModule.createSourceFile(
87
+ `config.${lang}`,
88
+ code,
89
+ tsModule.ScriptTarget.Latest,
90
+ true,
91
+ scriptKind
92
+ );
93
+ for (const statement of sourceFile.statements) {
94
+ if (tsModule.isExportAssignment(statement)) {
95
+ const expressionStart = statement.expression.getStart(sourceFile);
96
+ const expressionEnd = statement.expression.getEnd();
97
+ const leading = code.slice(0, statement.getStart(sourceFile));
98
+ const expression = code.slice(expressionStart, expressionEnd);
99
+ const trailing = code.slice(statement.getEnd());
100
+ return {
101
+ expression,
102
+ expressionStart,
103
+ expressionEnd,
104
+ leading,
105
+ trailing
106
+ };
107
+ }
108
+ }
109
+ return null;
110
+ }
111
+ function injectSchemaIntoJsonObject(content, schemaId) {
112
+ const trimmed = content.trim();
113
+ if (!trimmed.startsWith("{")) {
114
+ return content;
115
+ }
116
+ const leftBraceIndex = content.indexOf("{");
117
+ if (leftBraceIndex < 0) {
118
+ return content;
119
+ }
120
+ const afterLeft = content.slice(leftBraceIndex + 1);
121
+ const firstNonSpace = afterLeft.match(/\S/);
122
+ const nextCharIndex = firstNonSpace ? leftBraceIndex + 1 + firstNonSpace.index : -1;
123
+ const isEmptyObject = nextCharIndex >= 0 && content[nextCharIndex] === "}";
124
+ const schemaLine = ` "$schema": "${schemaId}"`;
125
+ const injected = isEmptyObject ? `{
126
+ ${schemaLine}
127
+ }` : `{
128
+ ${schemaLine},${content.slice(leftBraceIndex + 1)}`;
129
+ if (trimmed === content) {
130
+ return injected;
131
+ }
132
+ const leading = content.slice(0, content.indexOf(trimmed));
133
+ const trailing = content.slice(content.indexOf(trimmed) + trimmed.length);
134
+ return `${leading}${injected}${trailing}`;
135
+ }
136
+ var plugin = (ctx) => {
137
+ let tsModule = ctx?.modules?.typescript;
138
+ if (!tsModule) {
139
+ try {
140
+ tsModule = require2("typescript");
141
+ } catch {
142
+ tsModule = void 0;
143
+ }
144
+ }
71
145
  return {
72
146
  name,
73
147
  version: PLUGIN_VERSION,
@@ -77,8 +151,13 @@ var plugin = () => {
77
151
  const block = sfc.customBlocks[i];
78
152
  if (block.type === BLOCK_TYPE) {
79
153
  const normalizedLang = normalizeLang(block.lang);
80
- const lang = hasSchematicsTypes ? TS_LANG : normalizedLang;
81
- names.push({ id: `${BLOCK_TYPE}_${i}`, lang });
154
+ const isJsLike = normalizedLang === JS_LANG || normalizedLang === TS_LANG;
155
+ if (isJsLike) {
156
+ names.push({ id: `${BLOCK_TYPE}_${i}`, lang: TS_LANG });
157
+ continue;
158
+ }
159
+ const embeddedLang = normalizedLang === JSON_LANG || normalizedLang === JSONC_LANG || normalizedLang === JSON5_LANG ? JSONC_LANG : JSON_LANG;
160
+ names.push({ id: `${BLOCK_TYPE}_${i}`, lang: embeddedLang });
82
161
  }
83
162
  }
84
163
  return names;
@@ -93,6 +172,8 @@ var plugin = () => {
93
172
  if (!block) {
94
173
  return;
95
174
  }
175
+ const normalizedLang = normalizeLang(block.lang);
176
+ const configType = inferConfigType(fileName);
96
177
  if (!hasSchematicsTypes) {
97
178
  embeddedCode.content.push([
98
179
  block.content,
@@ -102,29 +183,79 @@ var plugin = () => {
102
183
  ]);
103
184
  return;
104
185
  }
105
- const configType = inferConfigType(fileName);
106
- const prefix = `import type { ${configType} as __WeappConfig } from '@weapp-core/schematics'
107
-
108
- export default `;
109
- const suffix = " satisfies __WeappConfig\n";
110
- embeddedCode.content.push([
111
- prefix,
112
- void 0,
113
- 0,
114
- VOID_CAPABILITIES
115
- ]);
186
+ const userWantsJs = normalizedLang === JS_LANG || normalizedLang === TS_LANG;
187
+ if (userWantsJs) {
188
+ const parsed = tsModule && findExportDefaultExpression(block.content, tsModule, normalizedLang);
189
+ if (parsed && hasSchematicsTypes) {
190
+ const typeImport = `import type { ${configType} as __WeappConfig } from '@weapp-core/schematics'
191
+ `;
192
+ const helper = "const __weapp_defineConfig = <T extends __WeappConfig>(config: T) => config\n\n";
193
+ embeddedCode.content.push([
194
+ `${typeImport}${helper}`,
195
+ void 0,
196
+ 0,
197
+ VOID_CAPABILITIES
198
+ ]);
199
+ if (parsed.leading) {
200
+ embeddedCode.content.push([
201
+ parsed.leading,
202
+ block.name,
203
+ 0,
204
+ FULL_CAPABILITIES
205
+ ]);
206
+ }
207
+ embeddedCode.content.push([
208
+ "export default __weapp_defineConfig(",
209
+ void 0,
210
+ parsed.expressionStart,
211
+ VOID_CAPABILITIES
212
+ ]);
213
+ embeddedCode.content.push([
214
+ parsed.expression,
215
+ block.name,
216
+ parsed.expressionStart,
217
+ FULL_CAPABILITIES
218
+ ]);
219
+ embeddedCode.content.push([
220
+ ")",
221
+ void 0,
222
+ parsed.expressionEnd,
223
+ VOID_CAPABILITIES
224
+ ]);
225
+ if (parsed.trailing) {
226
+ embeddedCode.content.push([
227
+ parsed.trailing,
228
+ block.name,
229
+ parsed.expressionEnd,
230
+ FULL_CAPABILITIES
231
+ ]);
232
+ }
233
+ return;
234
+ }
235
+ embeddedCode.content.push([
236
+ block.content,
237
+ block.name,
238
+ 0,
239
+ FULL_CAPABILITIES
240
+ ]);
241
+ return;
242
+ }
243
+ const schema = getSchemaForType(configType);
244
+ if (schema && schema.$id && !block.content.includes("$schema")) {
245
+ embeddedCode.content.push([
246
+ injectSchemaIntoJsonObject(block.content, schema.$id),
247
+ block.name,
248
+ 0,
249
+ FULL_CAPABILITIES
250
+ ]);
251
+ return;
252
+ }
116
253
  embeddedCode.content.push([
117
254
  block.content,
118
255
  block.name,
119
256
  0,
120
257
  FULL_CAPABILITIES
121
258
  ]);
122
- embeddedCode.content.push([
123
- suffix,
124
- void 0,
125
- block.content.length,
126
- VOID_CAPABILITIES
127
- ]);
128
259
  }
129
260
  };
130
261
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@weapp-vite/volar",
3
- "version": "0.0.2",
4
- "description": "tsup(esbuild) build package template",
3
+ "version": "1.0.0",
4
+ "description": "Volar plugin for weapp-vite - Provides IntelliSense and type checking for WeChat mini-program config blocks",
5
5
  "author": "ice breaker <1324318532@qq.com>",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -12,7 +12,16 @@
12
12
  "bugs": {
13
13
  "url": "https://github.com/weapp-vite/weapp-vite/issues"
14
14
  },
15
- "keywords": [],
15
+ "keywords": [
16
+ "volar",
17
+ "vue",
18
+ "wechat",
19
+ "miniprogram",
20
+ "weapp",
21
+ "intellisense",
22
+ "typescript",
23
+ "json-schema"
24
+ ],
16
25
  "sideEffects": false,
17
26
  "exports": {
18
27
  ".": {
@@ -31,7 +40,7 @@
31
40
  "dist"
32
41
  ],
33
42
  "dependencies": {
34
- "@weapp-core/schematics": "4.0.0"
43
+ "@weapp-core/schematics": "5.0.0"
35
44
  },
36
45
  "scripts": {
37
46
  "dev": "tsup --watch --sourcemap",