translime-sdk 1.0.1 → 1.0.3

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.
@@ -1,15 +1,24 @@
1
1
  import { fileURLToPath } from "url";
2
2
  import { dirname, resolve } from "path";
3
3
  import { readFileSync } from "fs";
4
- const __filename$1 = fileURLToPath(import.meta.url);
5
- const __dirname$1 = dirname(__filename$1);
6
- const VIRTUAL_PREVIEW_ENTRY = "virtual:translime-preview-entry";
7
- const RESOLVED_VIRTUAL_PREVIEW_ENTRY = `\0${VIRTUAL_PREVIEW_ENTRY}`;
4
+ //#region src/vite-plugin.js
5
+ var currentDir = dirname(fileURLToPath(import.meta.url));
6
+ var VIRTUAL_PREVIEW_ENTRY = "virtual:translime-preview-entry";
7
+ var RESOLVED_VIRTUAL_PREVIEW_ENTRY = `\0${VIRTUAL_PREVIEW_ENTRY}`;
8
+ /**
9
+ * 获取 Preview 模式的 Vuetify 样式配置文件路径
10
+ * @description 用于 vite-plugin-vuetify 的 styles.configFile 配置
11
+ * @returns {string} 绝对路径
12
+ */
8
13
  function getPreviewSettingsPath() {
9
- return resolve(__dirname$1, "preview/settings.scss");
14
+ return resolve(currentDir, "preview/settings.scss");
10
15
  }
16
+ /**
17
+ * 内联的 HTML 模板
18
+ * @description 当项目目录下找不到 preview-template.html 时使用的默认模板
19
+ */
11
20
  function getInlineTemplate() {
12
- return `<!DOCTYPE html>
21
+ return `<!DOCTYPE html>
13
22
  <html lang="zh-CN">
14
23
  <head>
15
24
  <meta charset="UTF-8">
@@ -23,173 +32,126 @@ function getInlineTemplate() {
23
32
  </body>
24
33
  </html>`;
25
34
  }
35
+ /**
36
+ * Translime SDK Vite Plugin
37
+ *
38
+ * 功能:
39
+ * 1. **自动组件导入**: 扫描 Vue/JS 文件,自动从 `window.vuetify$.components` 注入使用到的 Vuetify 组件,
40
+ * 避免在插件源码中手动 import Vuetify 组件 (减小插件体积).
41
+ * 2. **Preview 模式支持**: 提供完整的本地预览环境,包含 HMR、Mock API 和样式注入.
42
+ *
43
+ * @param {Object} options - 插件选项
44
+ * @param {string} [options.previewComponent] - Preview 模式下的入口组件路径 (默认为 build.lib.entry)
45
+ * @returns {import('vite').Plugin}
46
+ */
26
47
  function translimeSdk(options = {}) {
27
- let isPreviewMode = false;
28
- let resolvedPreviewComponent = "";
29
- return {
30
- name: "translime-sdk-plugin",
31
- enforce: "pre",
32
- // 确保在核心插件之前执行
33
- // ----------------------------------------------------------------------
34
- // Config Hook
35
- // ----------------------------------------------------------------------
36
- config(config, { mode, command }) {
37
- isPreviewMode = mode === "preview";
38
- if (options.previewComponent) {
39
- resolvedPreviewComponent = options.previewComponent;
40
- } else if (config.build?.lib?.entry) {
41
- resolvedPreviewComponent = config.build.lib.entry;
42
- }
43
- if (resolvedPreviewComponent && !resolvedPreviewComponent.startsWith("./") && !resolvedPreviewComponent.startsWith("/")) {
44
- resolvedPreviewComponent = `./${resolvedPreviewComponent}`;
45
- }
46
- const baseConfig = {
47
- define: {
48
- __TRANSLIME_PREVIEW__: isPreviewMode
49
- // 注入全局变量供代码判断环境
50
- },
51
- build: {
52
- rollupOptions: {
53
- external: ["electron"],
54
- // 永远排除 electron
55
- output: {
56
- globals: {
57
- electron: "window.electron"
58
- }
59
- }
60
- }
61
- }
62
- };
63
- if (isPreviewMode && command === "serve") {
64
- const settingsPath = resolve(__dirname$1, "preview/settings.scss");
65
- return {
66
- ...baseConfig,
67
- // 切换为 SPA 模式 (非库模式)
68
- build: {
69
- lib: void 0,
70
- rollupOptions: {
71
- external: []
72
- // Preview 模式下需要打包所有依赖
73
- }
74
- },
75
- // 启用现代 Sass 编译器 (消除 Deprecation Warning)
76
- css: {
77
- preprocessorOptions: {
78
- sass: { api: "modern-compiler" },
79
- scss: { api: "modern-compiler" }
80
- }
81
- },
82
- // 优化依赖: 排除 vuetify (使用我们注入的 mock/core)
83
- optimizeDeps: {
84
- exclude: ["vuetify"]
85
- },
86
- // 向下游插件传递配置 ( vite-plugin-vuetify)
87
- __translimeSdkPreview: {
88
- settingsPath
89
- }
90
- };
91
- }
92
- return baseConfig;
93
- },
94
- // ----------------------------------------------------------------------
95
- // Configure Server (Preview Middleware)
96
- // ----------------------------------------------------------------------
97
- configureServer(server) {
98
- if (!isPreviewMode) return;
99
- server.middlewares.use((req, res, next) => {
100
- if (req.url === "/" || req.url === "/index.html") {
101
- const templatePath = resolve(__dirname$1, "../preview-template.html");
102
- let html;
103
- try {
104
- html = readFileSync(templatePath, "utf-8");
105
- } catch (e) {
106
- html = getInlineTemplate();
107
- }
108
- html = html.replace("/__PREVIEW_ENTRY__", `/@id/${VIRTUAL_PREVIEW_ENTRY}`);
109
- res.setHeader("Content-Type", "text/html");
110
- res.end(html);
111
- return;
112
- }
113
- next();
114
- });
115
- },
116
- // ----------------------------------------------------------------------
117
- // Resolve Id (Virtual Entry)
118
- // ----------------------------------------------------------------------
119
- resolveId(id) {
120
- if (id === VIRTUAL_PREVIEW_ENTRY) {
121
- return RESOLVED_VIRTUAL_PREVIEW_ENTRY;
122
- }
123
- return null;
124
- },
125
- // ----------------------------------------------------------------------
126
- // Load (Virtual Entry Content)
127
- // ----------------------------------------------------------------------
128
- load(id) {
129
- if (id === RESOLVED_VIRTUAL_PREVIEW_ENTRY) {
130
- const componentPath = resolvedPreviewComponent || "./src/ui/ui.vue";
131
- return `import { startPreview } from 'translime-sdk/preview';
132
- import PluginComponent from '${componentPath}';
48
+ let isPreviewMode = false;
49
+ let resolvedPreviewComponent = "";
50
+ return {
51
+ name: "translime-sdk-plugin",
52
+ enforce: "pre",
53
+ config(config, { mode, command }) {
54
+ isPreviewMode = mode === "preview";
55
+ if (options.previewComponent) resolvedPreviewComponent = options.previewComponent;
56
+ else if (config.build?.lib?.entry) resolvedPreviewComponent = config.build.lib.entry;
57
+ if (resolvedPreviewComponent && !resolvedPreviewComponent.startsWith("./") && !resolvedPreviewComponent.startsWith("/")) resolvedPreviewComponent = `./${resolvedPreviewComponent}`;
58
+ const baseConfig = {
59
+ define: { __TRANSLIME_PREVIEW__: isPreviewMode },
60
+ build: { rolldownOptions: {
61
+ external: ["electron"],
62
+ output: { globals: { electron: "window.electron" } }
63
+ } }
64
+ };
65
+ if (isPreviewMode && command === "serve") {
66
+ const settingsPath = resolve(__dirname, "preview/settings.scss");
67
+ return {
68
+ ...baseConfig,
69
+ build: {
70
+ lib: void 0,
71
+ rolldownOptions: { external: [] }
72
+ },
73
+ css: { preprocessorOptions: {
74
+ sass: { api: "modern-compiler" },
75
+ scss: { api: "modern-compiler" }
76
+ } },
77
+ optimizeDeps: { exclude: ["vuetify"] },
78
+ __translimeSdkPreview: { settingsPath }
79
+ };
80
+ }
81
+ return baseConfig;
82
+ },
83
+ configureServer(server) {
84
+ if (!isPreviewMode) return;
85
+ server.middlewares.use((req, res, next) => {
86
+ if (req.url === "/" || req.url === "/index.html") {
87
+ const templatePath = resolve(currentDir, "../preview-template.html");
88
+ let html;
89
+ try {
90
+ html = readFileSync(templatePath, "utf-8");
91
+ } catch (e) {
92
+ html = getInlineTemplate();
93
+ }
94
+ html = html.replace("/__PREVIEW_ENTRY__", `/@id/${VIRTUAL_PREVIEW_ENTRY}`);
95
+ res.setHeader("Content-Type", "text/html");
96
+ res.end(html);
97
+ return;
98
+ }
99
+ next();
100
+ });
101
+ },
102
+ resolveId(id) {
103
+ if (id === VIRTUAL_PREVIEW_ENTRY) return RESOLVED_VIRTUAL_PREVIEW_ENTRY;
104
+ return null;
105
+ },
106
+ load(id) {
107
+ if (id === RESOLVED_VIRTUAL_PREVIEW_ENTRY) return `import { startPreview } from 'translime-sdk/preview';
108
+ import PluginComponent from '${resolvedPreviewComponent || "./src/ui/ui.vue"}';
133
109
  startPreview(PluginComponent);
134
110
  `;
135
- }
136
- return null;
137
- },
138
- // ----------------------------------------------------------------------
139
- // Transform (Auto-Import Components)
140
- // ----------------------------------------------------------------------
141
- transform(code, id) {
142
- if (id.includes("node_modules") || id.startsWith("\0")) return null;
143
- if (!/\.(js|ts|vue)$/.test(id)) return null;
144
- const matches = /* @__PURE__ */ new Set();
145
- const componentRegex = /\b(V[A-Z][\w$]+)\b/g;
146
- let match;
147
- while ((match = componentRegex.exec(code)) !== null) {
148
- matches.add(match[1]);
149
- }
150
- if (id.endsWith(".vue")) {
151
- const templateTagRegex = /<v-([a-z0-9-]+)\b/g;
152
- while ((match = templateTagRegex.exec(code)) !== null) {
153
- const name = `V${match[1].split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("")}`;
154
- matches.add(name);
155
- }
156
- }
157
- if (matches.size === 0) return null;
158
- const used = Array.from(matches).filter((name) => {
159
- if (new RegExp(`import\\s+{[^}]*\\b${name}\\b[^}]*}\\s+from`, "m").test(code)) return false;
160
- if (new RegExp(`(const|let|var|function|class|import)\\s+\\b${name}\\b`, "m").test(code)) return false;
161
- if (new RegExp(`\\.\\b${name}\\b`).test(code)) return false;
162
- return true;
163
- });
164
- if (used.length === 0) return null;
165
- const injection = `
166
- /* auto-injected by translime-sdk */
167
- const { ${used.join(", ")} } = (typeof window !== 'undefined' && window.vuetify$?.components || {});
168
- `;
169
- let newCode = code;
170
- if (id.endsWith(".vue")) {
171
- if (code.includes("<script setup")) {
172
- newCode = code.replace(/<script\s+setup[^>]*>/, `$&${injection}`);
173
- } else if (code.includes("<script")) {
174
- newCode = code.replace(/<script[^>]*>/, `$&${injection}`);
175
- } else {
176
- newCode = `<script setup>${injection}<\/script>
177
- ${code}`;
178
- }
179
- } else {
180
- newCode = injection + code;
181
- }
182
- return {
183
- code: newCode,
184
- map: null
185
- // 可选:生成 sourcemap
186
- };
187
- }
188
- };
111
+ return null;
112
+ },
113
+ transform(code, id) {
114
+ if (id.includes("node_modules") || id.startsWith("\0")) return null;
115
+ if (!/\.(js|ts|vue)$/.test(id)) return null;
116
+ const matches = /* @__PURE__ */ new Set();
117
+ const componentRegex = /\b(V[A-Z][\w$]+)\b/g;
118
+ let match;
119
+ match = componentRegex.exec(code);
120
+ while (match !== null) {
121
+ matches.add(match[1]);
122
+ match = componentRegex.exec(code);
123
+ }
124
+ if (id.endsWith(".vue")) {
125
+ const templateTagRegex = /<v-([a-z0-9-]+)\b/g;
126
+ match = templateTagRegex.exec(code);
127
+ while (match !== null) {
128
+ const name = `V${match[1].split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("")}`;
129
+ matches.add(name);
130
+ match = templateTagRegex.exec(code);
131
+ }
132
+ }
133
+ if (matches.size === 0) return null;
134
+ const used = Array.from(matches).filter((name) => {
135
+ if (new RegExp(`import\\s+{[^}]*\\b${name}\\b[^}]*}\\s+from`, "m").test(code)) return false;
136
+ if (new RegExp(`(const|let|var|function|class|import)\\s+\\b${name}\\b`, "m").test(code)) return false;
137
+ if (new RegExp(`\\.\\b${name}\\b`).test(code)) return false;
138
+ return true;
139
+ });
140
+ if (used.length === 0) return null;
141
+ const injection = `\n/* auto-injected by translime-sdk */\nconst { ${used.join(", ")} } = (typeof window !== 'undefined' && window.vuetify$?.components || {});\n`;
142
+ let newCode = code;
143
+ if (id.endsWith(".vue")) if (code.includes("<script setup")) newCode = code.replace(/<script\s+setup[^>]*>/, `$&${injection}`);
144
+ else if (code.includes("<script")) newCode = code.replace(/<script[^>]*>/, `$&${injection}`);
145
+ else newCode = `<script setup>${injection}<\/script>\n${code}`;
146
+ else newCode = injection + code;
147
+ return {
148
+ code: newCode,
149
+ map: null
150
+ };
151
+ }
152
+ };
189
153
  }
190
- export {
191
- translimeSdk as default,
192
- getPreviewSettingsPath,
193
- translimeSdk
194
- };
195
- //# sourceMappingURL=vite-plugin.js.map
154
+ //#endregion
155
+ export { translimeSdk as default, translimeSdk, getPreviewSettingsPath };
156
+
157
+ //# sourceMappingURL=vite-plugin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"vite-plugin.js","sources":["../src/vite-plugin.js"],"sourcesContent":["import { fileURLToPath } from 'url';\nimport { dirname, resolve } from 'path';\nimport { readFileSync } from 'fs';\n\n// 获取当前模块所在目录\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// ----------------------------------------------------------------------\n// Constants\n// ----------------------------------------------------------------------\n\nconst VIRTUAL_PREVIEW_ENTRY = 'virtual:translime-preview-entry';\nconst RESOLVED_VIRTUAL_PREVIEW_ENTRY = `\\0${VIRTUAL_PREVIEW_ENTRY}`;\n\n// ----------------------------------------------------------------------\n// Helpers\n// ----------------------------------------------------------------------\n\n/**\n * 获取 Preview 模式的 Vuetify 样式配置文件路径\n * @description 用于 vite-plugin-vuetify 的 styles.configFile 配置\n * @returns {string} 绝对路径\n */\nexport function getPreviewSettingsPath() {\n return resolve(__dirname, 'preview/settings.scss');\n}\n\n/**\n * 内联的 HTML 模板\n * @description 当项目目录下找不到 preview-template.html 时使用的默认模板\n */\nfunction getInlineTemplate() {\n return `<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Plugin Preview</title>\n <link href=\"https://fonts.googleapis.com/icon?family=Material+Icons\" rel=\"stylesheet\">\n</head>\n<body>\n <div id=\"app\"></div>\n <script type=\"module\" src=\"/__PREVIEW_ENTRY__\"></script>\n</body>\n</html>`;\n}\n\n// ----------------------------------------------------------------------\n// Main Plugin\n// ----------------------------------------------------------------------\n\n/**\n * Translime SDK Vite Plugin\n *\n * 功能:\n * 1. **自动组件导入**: 扫描 Vue/JS 文件,自动从 `window.vuetify$.components` 注入使用到的 Vuetify 组件,\n * 避免在插件源码中手动 import Vuetify 组件 (减小插件体积).\n * 2. **Preview 模式支持**: 提供完整的本地预览环境,包含 HMR、Mock API 和样式注入.\n *\n * @param {Object} options - 插件选项\n * @param {string} [options.previewComponent] - Preview 模式下的入口组件路径 (默认为 build.lib.entry)\n * @returns {import('vite').Plugin}\n */\nexport function translimeSdk(options = {}) {\n let isPreviewMode = false;\n let resolvedPreviewComponent = '';\n\n return {\n name: 'translime-sdk-plugin',\n enforce: 'pre', // 确保在核心插件之前执行\n\n // ----------------------------------------------------------------------\n // Config Hook\n // ----------------------------------------------------------------------\n config(config, { mode, command }) {\n isPreviewMode = mode === 'preview';\n\n // 确定 Preview 入口组件路径\n if (options.previewComponent) {\n resolvedPreviewComponent = options.previewComponent;\n } else if (config.build?.lib?.entry) {\n // 尝试从 lib entry 推断\n resolvedPreviewComponent = config.build.lib.entry;\n }\n\n // 规范化路径 (Vite 需要 ./ 或 / 开头)\n if (resolvedPreviewComponent && !resolvedPreviewComponent.startsWith('./') && !resolvedPreviewComponent.startsWith('/')) {\n resolvedPreviewComponent = `./${resolvedPreviewComponent}`;\n }\n\n // 基础配置 (通用)\n const baseConfig = {\n define: {\n __TRANSLIME_PREVIEW__: isPreviewMode, // 注入全局变量供代码判断环境\n },\n build: {\n rollupOptions: {\n external: ['electron'], // 永远排除 electron\n output: {\n globals: {\n electron: 'window.electron',\n },\n },\n },\n },\n };\n\n // Preview 模式特殊配置 (仅在 serve 阶段生效)\n if (isPreviewMode && command === 'serve') {\n const settingsPath = resolve(__dirname, 'preview/settings.scss');\n\n return {\n ...baseConfig,\n // 切换为 SPA 模式 (非库模式)\n build: {\n lib: undefined,\n rollupOptions: {\n external: [], // Preview 模式下需要打包所有依赖\n },\n },\n // 启用现代 Sass 编译器 (消除 Deprecation Warning)\n css: {\n preprocessorOptions: {\n sass: { api: 'modern-compiler' },\n scss: { api: 'modern-compiler' },\n },\n },\n // 优化依赖: 排除 vuetify (使用我们注入的 mock/core)\n optimizeDeps: {\n exclude: ['vuetify'],\n },\n // 向下游插件传递配置 (如 vite-plugin-vuetify)\n __translimeSdkPreview: {\n settingsPath,\n },\n };\n }\n\n return baseConfig;\n },\n\n // ----------------------------------------------------------------------\n // Configure Server (Preview Middleware)\n // ----------------------------------------------------------------------\n configureServer(server) {\n if (!isPreviewMode) return;\n\n // 拦截 index.html 请求,提供 Preview 模板\n server.middlewares.use((req, res, next) => {\n if (req.url === '/' || req.url === '/index.html') {\n const templatePath = resolve(__dirname, '../preview-template.html');\n let html;\n try {\n html = readFileSync(templatePath, 'utf-8');\n } catch (e) {\n html = getInlineTemplate();\n }\n\n // 注入虚拟入口\n html = html.replace('/__PREVIEW_ENTRY__', `/@id/${VIRTUAL_PREVIEW_ENTRY}`);\n\n res.setHeader('Content-Type', 'text/html');\n res.end(html);\n return;\n }\n next();\n });\n },\n\n // ----------------------------------------------------------------------\n // Resolve Id (Virtual Entry)\n // ----------------------------------------------------------------------\n resolveId(id) {\n if (id === VIRTUAL_PREVIEW_ENTRY) {\n return RESOLVED_VIRTUAL_PREVIEW_ENTRY;\n }\n return null;\n },\n\n // ----------------------------------------------------------------------\n // Load (Virtual Entry Content)\n // ----------------------------------------------------------------------\n load(id) {\n if (id === RESOLVED_VIRTUAL_PREVIEW_ENTRY) {\n // 生成引导代码:导入 Preview 框架 + 用户插件组件\n const componentPath = resolvedPreviewComponent || './src/ui/ui.vue';\n return `import { startPreview } from 'translime-sdk/preview';\nimport PluginComponent from '${componentPath}';\nstartPreview(PluginComponent);\n`;\n }\n return null;\n },\n\n // ----------------------------------------------------------------------\n // Transform (Auto-Import Components)\n // ----------------------------------------------------------------------\n transform(code, id) {\n // 忽略不需要处理的文件\n if (id.includes('node_modules') || id.startsWith('\\0')) return null;\n if (!/\\.(js|ts|vue)$/.test(id)) return null;\n\n const matches = new Set();\n\n // 扫描 JS/TS 中的组件名 (e.g. VBtn, VCard)\n const componentRegex = /\\b(V[A-Z][\\w$]+)\\b/g;\n let match;\n while ((match = componentRegex.exec(code)) !== null) {\n matches.add(match[1]);\n }\n\n // 扫描 Vue 模板中的 kebab-case 标签 (e.g. <v-btn>)\n if (id.endsWith('.vue')) {\n const templateTagRegex = /<v-([a-z0-9-]+)\\b/g;\n while ((match = templateTagRegex.exec(code)) !== null) {\n // camelCase 转换: v-btn -> VBtn\n const name = `V${match[1].split('-').map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join('')}`;\n matches.add(name);\n }\n }\n\n if (matches.size === 0) return null;\n\n // 过滤掉已从其他地方导入或定义的变量\n const used = Array.from(matches).filter((name) => {\n // 检查 import 语句\n if (new RegExp(`import\\\\s+{[^}]*\\\\b${name}\\\\b[^}]*}\\\\s+from`, 'm').test(code)) return false;\n // 检查局部变量定义 (const, let, function, class)\n if (new RegExp(`(const|let|var|function|class|import)\\\\s+\\\\b${name}\\\\b`, 'm').test(code)) return false;\n // 检查属性访问 (e.g. something.VBtn)\n if (new RegExp(`\\\\.\\\\b${name}\\\\b`).test(code)) return false;\n return true;\n });\n\n if (used.length === 0) return null;\n\n // 注入代码\n // 如果运行在 Render 进程 (有 window.vuetify$),则从中解构;否则为空对象\n const injection = `\\n/* auto-injected by translime-sdk */\\nconst { ${used.join(', ')} } = (typeof window !== 'undefined' && window.vuetify$?.components || {});\\n`;\n\n let newCode = code;\n if (id.endsWith('.vue')) {\n if (code.includes('<script setup')) {\n newCode = code.replace(/<script\\s+setup[^>]*>/, `$&${injection}`);\n } else if (code.includes('<script')) {\n newCode = code.replace(/<script[^>]*>/, `$&${injection}`);\n } else {\n // 无 script 标签时,创建 <script setup> (常见于纯模板 Vue 文件)\n newCode = `<script setup>${injection}</script>\\n${code}`;\n }\n } else {\n newCode = injection + code;\n }\n\n return {\n code: newCode,\n map: null, // 可选:生成 sourcemap\n };\n },\n };\n}\n\nexport default translimeSdk;\n\n"],"names":["__filename","__dirname"],"mappings":";;;AAKA,MAAMA,eAAa,cAAc,YAAY,GAAG;AAChD,MAAMC,cAAY,QAAQD,YAAU;AAMpC,MAAM,wBAAwB;AAC9B,MAAM,iCAAiC,KAAK,qBAAqB;AAW1D,SAAS,yBAAyB;AACvC,SAAO,QAAQC,aAAW,uBAAuB;AACnD;AAMA,SAAS,oBAAoB;AAC3B,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaT;AAkBO,SAAS,aAAa,UAAU,IAAI;AACzC,MAAI,gBAAgB;AACpB,MAAI,2BAA2B;AAE/B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,IAKT,OAAO,QAAQ,EAAE,MAAM,QAAO,GAAI;AAChC,sBAAgB,SAAS;AAGzB,UAAI,QAAQ,kBAAkB;AAC5B,mCAA2B,QAAQ;AAAA,MACrC,WAAW,OAAO,OAAO,KAAK,OAAO;AAEnC,mCAA2B,OAAO,MAAM,IAAI;AAAA,MAC9C;AAGA,UAAI,4BAA4B,CAAC,yBAAyB,WAAW,IAAI,KAAK,CAAC,yBAAyB,WAAW,GAAG,GAAG;AACvH,mCAA2B,KAAK,wBAAwB;AAAA,MAC1D;AAGA,YAAM,aAAa;AAAA,QACjB,QAAQ;AAAA,UACN,uBAAuB;AAAA;AAAA,QACjC;AAAA,QACQ,OAAO;AAAA,UACL,eAAe;AAAA,YACb,UAAU,CAAC,UAAU;AAAA;AAAA,YACrB,QAAQ;AAAA,cACN,SAAS;AAAA,gBACP,UAAU;AAAA,cAC1B;AAAA,YACA;AAAA,UACA;AAAA,QACA;AAAA,MACA;AAGM,UAAI,iBAAiB,YAAY,SAAS;AACxC,cAAM,eAAe,QAAQA,aAAW,uBAAuB;AAE/D,eAAO;AAAA,UACL,GAAG;AAAA;AAAA,UAEH,OAAO;AAAA,YACL,KAAK;AAAA,YACL,eAAe;AAAA,cACb,UAAU,CAAA;AAAA;AAAA,YACxB;AAAA,UACA;AAAA;AAAA,UAEU,KAAK;AAAA,YACH,qBAAqB;AAAA,cACnB,MAAM,EAAE,KAAK,kBAAiB;AAAA,cAC9B,MAAM,EAAE,KAAK,kBAAiB;AAAA,YAC5C;AAAA,UACA;AAAA;AAAA,UAEU,cAAc;AAAA,YACZ,SAAS,CAAC,SAAS;AAAA,UAC/B;AAAA;AAAA,UAEU,uBAAuB;AAAA,YACrB;AAAA,UACZ;AAAA,QACA;AAAA,MACM;AAEA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA,IAKA,gBAAgB,QAAQ;AACtB,UAAI,CAAC,cAAe;AAGpB,aAAO,YAAY,IAAI,CAAC,KAAK,KAAK,SAAS;AACzC,YAAI,IAAI,QAAQ,OAAO,IAAI,QAAQ,eAAe;AAChD,gBAAM,eAAe,QAAQA,aAAW,0BAA0B;AAClE,cAAI;AACJ,cAAI;AACF,mBAAO,aAAa,cAAc,OAAO;AAAA,UAC3C,SAAS,GAAG;AACV,mBAAO,kBAAiB;AAAA,UAC1B;AAGA,iBAAO,KAAK,QAAQ,sBAAsB,QAAQ,qBAAqB,EAAE;AAEzE,cAAI,UAAU,gBAAgB,WAAW;AACzC,cAAI,IAAI,IAAI;AACZ;AAAA,QACF;AACA,aAAI;AAAA,MACN,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA,IAKA,UAAU,IAAI;AACZ,UAAI,OAAO,uBAAuB;AAChC,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA,IAKA,KAAK,IAAI;AACP,UAAI,OAAO,gCAAgC;AAEzC,cAAM,gBAAgB,4BAA4B;AAClD,eAAO;AAAA,+BACgB,aAAa;AAAA;AAAA;AAAA,MAGtC;AACA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA,IAKA,UAAU,MAAM,IAAI;AAElB,UAAI,GAAG,SAAS,cAAc,KAAK,GAAG,WAAW,IAAI,EAAG,QAAO;AAC/D,UAAI,CAAC,iBAAiB,KAAK,EAAE,EAAG,QAAO;AAEvC,YAAM,UAAU,oBAAI,IAAG;AAGvB,YAAM,iBAAiB;AACvB,UAAI;AACJ,cAAQ,QAAQ,eAAe,KAAK,IAAI,OAAO,MAAM;AACnD,gBAAQ,IAAI,MAAM,CAAC,CAAC;AAAA,MACtB;AAGA,UAAI,GAAG,SAAS,MAAM,GAAG;AACvB,cAAM,mBAAmB;AACzB,gBAAQ,QAAQ,iBAAiB,KAAK,IAAI,OAAO,MAAM;AAErD,gBAAM,OAAO,IAAI,MAAM,CAAC,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAW,IAAK,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;AAChG,kBAAQ,IAAI,IAAI;AAAA,QAClB;AAAA,MACF;AAEA,UAAI,QAAQ,SAAS,EAAG,QAAO;AAG/B,YAAM,OAAO,MAAM,KAAK,OAAO,EAAE,OAAO,CAAC,SAAS;AAEhD,YAAI,IAAI,OAAO,sBAAsB,IAAI,qBAAqB,GAAG,EAAE,KAAK,IAAI,EAAG,QAAO;AAEtF,YAAI,IAAI,OAAO,+CAA+C,IAAI,OAAO,GAAG,EAAE,KAAK,IAAI,EAAG,QAAO;AAEjG,YAAI,IAAI,OAAO,SAAS,IAAI,KAAK,EAAE,KAAK,IAAI,EAAG,QAAO;AACtD,eAAO;AAAA,MACT,CAAC;AAED,UAAI,KAAK,WAAW,EAAG,QAAO;AAI9B,YAAM,YAAY;AAAA;AAAA,UAAmD,KAAK,KAAK,IAAI,CAAC;AAAA;AAEpF,UAAI,UAAU;AACd,UAAI,GAAG,SAAS,MAAM,GAAG;AACvB,YAAI,KAAK,SAAS,eAAe,GAAG;AAClC,oBAAU,KAAK,QAAQ,yBAAyB,KAAK,SAAS,EAAE;AAAA,QAClE,WAAW,KAAK,SAAS,SAAS,GAAG;AACnC,oBAAU,KAAK,QAAQ,iBAAiB,KAAK,SAAS,EAAE;AAAA,QAC1D,OAAO;AAEL,oBAAU,iBAAiB,SAAS;AAAA,EAAc,IAAI;AAAA,QACxD;AAAA,MACF,OAAO;AACL,kBAAU,YAAY;AAAA,MACxB;AAEA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,KAAK;AAAA;AAAA,MACb;AAAA,IACI;AAAA,EACJ;AACA;"}
1
+ {"version":3,"file":"vite-plugin.js","names":[],"sources":["../src/vite-plugin.js"],"sourcesContent":["import { fileURLToPath } from 'url';\r\nimport { dirname, resolve } from 'path';\r\nimport { readFileSync } from 'fs';\r\n\r\n// 获取当前模块所在目录\r\nconst filename = fileURLToPath(import.meta.url);\r\nconst currentDir = dirname(filename);\r\n\r\n// ----------------------------------------------------------------------\r\n// Constants\r\n// ----------------------------------------------------------------------\r\n\r\nconst VIRTUAL_PREVIEW_ENTRY = 'virtual:translime-preview-entry';\r\nconst RESOLVED_VIRTUAL_PREVIEW_ENTRY = `\\0${VIRTUAL_PREVIEW_ENTRY}`;\r\n\r\n// ----------------------------------------------------------------------\r\n// Helpers\r\n// ----------------------------------------------------------------------\r\n\r\n/**\r\n * 获取 Preview 模式的 Vuetify 样式配置文件路径\r\n * @description 用于 vite-plugin-vuetify 的 styles.configFile 配置\r\n * @returns {string} 绝对路径\r\n */\r\nexport function getPreviewSettingsPath() {\r\n return resolve(currentDir, 'preview/settings.scss');\r\n}\r\n\r\n/**\r\n * 内联的 HTML 模板\r\n * @description 当项目目录下找不到 preview-template.html 时使用的默认模板\r\n */\r\nfunction getInlineTemplate() {\r\n return `<!DOCTYPE html>\r\n<html lang=\"zh-CN\">\r\n<head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n <title>Plugin Preview</title>\r\n <link href=\"https://fonts.googleapis.com/icon?family=Material+Icons\" rel=\"stylesheet\">\r\n</head>\r\n<body>\r\n <div id=\"app\"></div>\r\n <script type=\"module\" src=\"/__PREVIEW_ENTRY__\"></script>\r\n</body>\r\n</html>`;\r\n}\r\n\r\n// ----------------------------------------------------------------------\r\n// Main Plugin\r\n// ----------------------------------------------------------------------\r\n\r\n/**\r\n * Translime SDK Vite Plugin\r\n *\r\n * 功能:\r\n * 1. **自动组件导入**: 扫描 Vue/JS 文件,自动从 `window.vuetify$.components` 注入使用到的 Vuetify 组件,\r\n * 避免在插件源码中手动 import Vuetify 组件 (减小插件体积).\r\n * 2. **Preview 模式支持**: 提供完整的本地预览环境,包含 HMR、Mock API 和样式注入.\r\n *\r\n * @param {Object} options - 插件选项\r\n * @param {string} [options.previewComponent] - Preview 模式下的入口组件路径 (默认为 build.lib.entry)\r\n * @returns {import('vite').Plugin}\r\n */\r\nexport function translimeSdk(options = {}) {\r\n let isPreviewMode = false;\r\n let resolvedPreviewComponent = '';\r\n\r\n return {\r\n name: 'translime-sdk-plugin',\r\n enforce: 'pre', // 确保在核心插件之前执行\r\n\r\n // ----------------------------------------------------------------------\r\n // Config Hook\r\n // ----------------------------------------------------------------------\r\n config(config, { mode, command }) {\r\n isPreviewMode = mode === 'preview';\r\n\r\n // 确定 Preview 入口组件路径\r\n if (options.previewComponent) {\r\n resolvedPreviewComponent = options.previewComponent;\r\n } else if (config.build?.lib?.entry) {\r\n // 尝试从 lib entry 推断\r\n resolvedPreviewComponent = config.build.lib.entry;\r\n }\r\n\r\n // 规范化路径 (Vite 需要 ./ 或 / 开头)\r\n if (resolvedPreviewComponent && !resolvedPreviewComponent.startsWith('./') && !resolvedPreviewComponent.startsWith('/')) {\r\n resolvedPreviewComponent = `./${resolvedPreviewComponent}`;\r\n }\r\n\r\n // 基础配置 (通用)\r\n const baseConfig = {\r\n define: {\r\n __TRANSLIME_PREVIEW__: isPreviewMode, // 注入全局变量供代码判断环境\r\n },\r\n build: {\r\n rolldownOptions: {\r\n external: ['electron'], // 永远排除 electron\r\n output: {\r\n globals: {\r\n electron: 'window.electron',\r\n },\r\n },\r\n },\r\n },\r\n };\r\n\r\n // Preview 模式特殊配置 (仅在 serve 阶段生效)\r\n if (isPreviewMode && command === 'serve') {\r\n const settingsPath = resolve(__dirname, 'preview/settings.scss');\r\n\r\n return {\r\n ...baseConfig,\r\n // 切换为 SPA 模式 (非库模式)\r\n build: {\r\n lib: undefined,\r\n rolldownOptions: {\r\n external: [], // Preview 模式下需要打包所有依赖\r\n },\r\n },\r\n // 启用现代 Sass 编译器 (消除 Deprecation Warning)\r\n css: {\r\n preprocessorOptions: {\r\n sass: { api: 'modern-compiler' },\r\n scss: { api: 'modern-compiler' },\r\n },\r\n },\r\n // 优化依赖: 排除 vuetify (使用我们注入的 mock/core)\r\n optimizeDeps: {\r\n exclude: ['vuetify'],\r\n },\r\n // 向下游插件传递配置 (如 vite-plugin-vuetify)\r\n __translimeSdkPreview: {\r\n settingsPath,\r\n },\r\n };\r\n }\r\n\r\n return baseConfig;\r\n },\r\n\r\n // ----------------------------------------------------------------------\r\n // Configure Server (Preview Middleware)\r\n // ----------------------------------------------------------------------\r\n configureServer(server) {\r\n if (!isPreviewMode) return;\r\n\r\n // 拦截 index.html 请求,提供 Preview 模板\r\n server.middlewares.use((req, res, next) => {\r\n if (req.url === '/' || req.url === '/index.html') {\r\n const templatePath = resolve(currentDir, '../preview-template.html');\r\n let html;\r\n try {\r\n html = readFileSync(templatePath, 'utf-8');\r\n } catch (e) {\r\n html = getInlineTemplate();\r\n }\r\n\r\n // 注入虚拟入口\r\n html = html.replace('/__PREVIEW_ENTRY__', `/@id/${VIRTUAL_PREVIEW_ENTRY}`);\r\n\r\n res.setHeader('Content-Type', 'text/html');\r\n res.end(html);\r\n return;\r\n }\r\n next();\r\n });\r\n },\r\n\r\n // ----------------------------------------------------------------------\r\n // Resolve Id (Virtual Entry)\r\n // ----------------------------------------------------------------------\r\n resolveId(id) {\r\n if (id === VIRTUAL_PREVIEW_ENTRY) {\r\n return RESOLVED_VIRTUAL_PREVIEW_ENTRY;\r\n }\r\n return null;\r\n },\r\n\r\n // ----------------------------------------------------------------------\r\n // Load (Virtual Entry Content)\r\n // ----------------------------------------------------------------------\r\n load(id) {\r\n if (id === RESOLVED_VIRTUAL_PREVIEW_ENTRY) {\r\n // 生成引导代码:导入 Preview 框架 + 用户插件组件\r\n const componentPath = resolvedPreviewComponent || './src/ui/ui.vue';\r\n return `import { startPreview } from 'translime-sdk/preview';\r\nimport PluginComponent from '${componentPath}';\r\nstartPreview(PluginComponent);\r\n`;\r\n }\r\n return null;\r\n },\r\n\r\n // ----------------------------------------------------------------------\r\n // Transform (Auto-Import Components)\r\n // ----------------------------------------------------------------------\r\n transform(code, id) {\r\n // 忽略不需要处理的文件\r\n if (id.includes('node_modules') || id.startsWith('\\0')) return null;\r\n if (!/\\.(js|ts|vue)$/.test(id)) return null;\r\n\r\n const matches = new Set();\r\n\r\n // 扫描 JS/TS 中的组件名 (e.g. VBtn, VCard)\r\n const componentRegex = /\\b(V[A-Z][\\w$]+)\\b/g;\r\n let match;\r\n match = componentRegex.exec(code);\r\n while (match !== null) {\r\n matches.add(match[1]);\r\n match = componentRegex.exec(code);\r\n }\r\n\r\n // 扫描 Vue 模板中的 kebab-case 标签 (e.g. <v-btn>)\r\n if (id.endsWith('.vue')) {\r\n const templateTagRegex = /<v-([a-z0-9-]+)\\b/g;\r\n match = templateTagRegex.exec(code);\r\n while (match !== null) {\r\n // camelCase 转换: v-btn -> VBtn\r\n const name = `V${match[1].split('-').map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join('')}`;\r\n matches.add(name);\r\n match = templateTagRegex.exec(code);\r\n }\r\n }\r\n\r\n if (matches.size === 0) return null;\r\n\r\n // 过滤掉已从其他地方导入或定义的变量\r\n const used = Array.from(matches).filter((name) => {\r\n // 检查 import 语句\r\n if (new RegExp(`import\\\\s+{[^}]*\\\\b${name}\\\\b[^}]*}\\\\s+from`, 'm').test(code)) return false;\r\n // 检查局部变量定义 (const, let, function, class)\r\n if (new RegExp(`(const|let|var|function|class|import)\\\\s+\\\\b${name}\\\\b`, 'm').test(code)) return false;\r\n // 检查属性访问 (e.g. something.VBtn)\r\n if (new RegExp(`\\\\.\\\\b${name}\\\\b`).test(code)) return false;\r\n return true;\r\n });\r\n\r\n if (used.length === 0) return null;\r\n\r\n // 注入代码\r\n // 如果运行在 Render 进程 (有 window.vuetify$),则从中解构;否则为空对象\r\n const injection = `\\n/* auto-injected by translime-sdk */\\nconst { ${used.join(', ')} } = (typeof window !== 'undefined' && window.vuetify$?.components || {});\\n`;\r\n\r\n let newCode = code;\r\n if (id.endsWith('.vue')) {\r\n if (code.includes('<script setup')) {\r\n newCode = code.replace(/<script\\s+setup[^>]*>/, `$&${injection}`);\r\n } else if (code.includes('<script')) {\r\n newCode = code.replace(/<script[^>]*>/, `$&${injection}`);\r\n } else {\r\n // 无 script 标签时,创建 <script setup> (常见于纯模板 Vue 文件)\r\n newCode = `<script setup>${injection}</script>\\n${code}`;\r\n }\r\n } else {\r\n newCode = injection + code;\r\n }\r\n\r\n return {\r\n code: newCode,\r\n map: null, // 可选:生成 sourcemap\r\n };\r\n },\r\n };\r\n}\r\n\r\nexport default translimeSdk;\r\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "translime-sdk",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "SDK for Translime plugins",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -55,12 +55,6 @@
55
55
  "plugin",
56
56
  "preview"
57
57
  ],
58
- "scripts": {
59
- "lint": "eslint src --ext .js,.vue --fix",
60
- "lint:style": "stylelint src/**/*.{vue,scss} --fix",
61
- "build": "vite build && node scripts/post-build.mjs",
62
- "prepublishOnly": "npm run build"
63
- },
64
58
  "engines": {
65
59
  "node": ">=16.0.0"
66
60
  },
@@ -82,8 +76,7 @@
82
76
  "@stylistic/stylelint-plugin": "^3.0.0",
83
77
  "@vitejs/plugin-vue": "^6.0.3",
84
78
  "eslint": "^9.0.0",
85
- "eslint-config-airbnb-base": "^15.0.0",
86
- "eslint-plugin-import": "^2.31.0",
79
+ "eslint-config-airbnb-extended": "^3.0.1",
87
80
  "eslint-plugin-vue": "^10.0.0",
88
81
  "globals": "^16.0.0",
89
82
  "postcss-html": "^1.5.0",
@@ -92,8 +85,13 @@
92
85
  "stylelint-config-recommended-vue": "^1.5.0",
93
86
  "stylelint-config-standard-scss": "^14.0.0",
94
87
  "stylelint-scss": "^6.0.0",
95
- "vite": "^7.3.1",
88
+ "vite": "^8.0.0",
96
89
  "vite-plugin-vuetify": "^2.1.1",
97
90
  "vuetify": "^3.11.6"
91
+ },
92
+ "scripts": {
93
+ "lint": "eslint src --ext .js,.vue --fix",
94
+ "lint:style": "stylelint src/**/*.{vue,scss} --fix",
95
+ "build": "vite build && node scripts/post-build.mjs"
98
96
  }
99
97
  }