diff --git a/packages/vite-plugin/dist/config.d.ts b/packages/vite-plugin/dist/config.d.ts index 4274bea..46b14b5 100644 --- a/packages/vite-plugin/dist/config.d.ts +++ b/packages/vite-plugin/dist/config.d.ts @@ -1,5 +1,6 @@ +import type { Type } from "../types"; export declare const config: { - type: string; + type: Type; reqUrl: string; demo: boolean; nameTag: boolean; diff --git a/packages/vite-plugin/dist/eps/flatten.d.ts b/packages/vite-plugin/dist/eps/flatten.d.ts new file mode 100644 index 0000000..8aba397 --- /dev/null +++ b/packages/vite-plugin/dist/eps/flatten.d.ts @@ -0,0 +1,7 @@ +/** + * 将模板字符串扁平化处理,转换为 Service 类型定义 + * @param template - 包含 Service 类型定义的模板字符串 + * @returns 处理后的 Service 类型定义字符串 + * @throws {Error} 当模板中找不到 Service 类型定义时抛出错误 + */ +export declare function flatten(template: string): string; diff --git a/packages/vite-plugin/dist/eps/index.d.ts b/packages/vite-plugin/dist/eps/index.d.ts index 4eb40d8..a3719cf 100644 --- a/packages/vite-plugin/dist/eps/index.d.ts +++ b/packages/vite-plugin/dist/eps/index.d.ts @@ -1,10 +1,18 @@ import type { Eps } from "../../types"; +/** + * 主入口:创建 eps 相关文件和 service + */ export declare function createEps(): Promise<{ service: {}; + serviceCode: { + content: string; + types: string[]; + }; list: Eps.Entity[]; isUpdate: boolean; } | { service: {}; list: never[]; + serviceCode?: undefined; isUpdate?: undefined; }>; diff --git a/packages/vite-plugin/dist/index.d.ts b/packages/vite-plugin/dist/index.d.ts index f20d679..007de2c 100644 --- a/packages/vite-plugin/dist/index.d.ts +++ b/packages/vite-plugin/dist/index.d.ts @@ -1,2 +1,2 @@ import type { Config } from "../types"; -export declare function cool(options: Config.Options): (import("vite").Plugin | Promise> | import("vite").Plugin[])[]; +export declare function cool(options: Config.Options): (import("vite").Plugin | Promise> | Promise[]>)[]; diff --git a/packages/vite-plugin/dist/index.js b/packages/vite-plugin/dist/index.js index 27f43a2..a3c902c 100644 --- a/packages/vite-plugin/dist/index.js +++ b/packages/vite-plugin/dist/index.js @@ -41,6 +41,10 @@ type: "BigInt", test: ["bigint"], }, + { + type: "any", + test: ["json"], + }, ], }, svg: { @@ -136,9 +140,311 @@ console.log("\x1B[31m%s\x1B[0m", message); } + /** + * 将模板字符串扁平化处理,转换为 Service 类型定义 + * @param template - 包含 Service 类型定义的模板字符串 + * @returns 处理后的 Service 类型定义字符串 + * @throws {Error} 当模板中找不到 Service 类型定义时抛出错误 + */ + function flatten(template) { + // 查找 Service 类型定义的起始位置 + const startIndex = template.indexOf("export type Service = {"); + // 保留 Service 类型定义前的内容 + let header = template.substring(0, startIndex); + // 获取 Service 类型定义及其内容,去除换行和制表符 + const serviceContent = template.substring(startIndex).replace(/\n|\t/g, ""); + let interfaces = ""; + let serviceFields = ""; + // 解析内容并生成接口定义 + parse(serviceContent).forEach(({ key, content, level }) => { + interfaces += `\nexport interface ${firstUpperCase(key)}Interface {${content}}\n`; + serviceFields += `${key}: ${firstUpperCase(key)}Interface;`; + }); + return `${header}${interfaces}\nexport type Service = {${serviceFields}}`; + } + /** + * 查找匹配的右花括号位置 + * @param str - 要搜索的字符串 + * @param startIndex - 开始搜索的位置 + * @returns 匹配的右花括号位置 + * @throws {Error} 当找不到匹配的右花括号时抛出错误 + */ + function findClosingBrace(str, startIndex) { + let braceCount = 1; + let currentIndex = startIndex; + while (currentIndex < str.length && braceCount > 0) { + if (str[currentIndex] === "{") + braceCount++; + if (str[currentIndex] === "}") + braceCount--; + currentIndex++; + } + if (braceCount !== 0) { + throw new Error("Unmatched braces in the template"); + } + return currentIndex - 1; + } + /** + * 解析内容中的嵌套结构 + * @param content - 要解析的内容字符串 + * @returns 解析结果数组,包含解析出的键值对 + */ + function parse(content, level = 0) { + // 匹配形如 xxx: { ... } 的结构 + const interfacePattern = /(\w+)\s*:\s*\{/g; + const result = []; + let match; + while ((match = interfacePattern.exec(content)) !== null) { + const startIndex = match.index + match[0].length; + const endIndex = findClosingBrace(content, startIndex); + if (endIndex > startIndex) { + let parsedContent = content.substring(startIndex, endIndex).trim(); + // 处理嵌套结构 + if (parsedContent.includes("{") && parsedContent.includes("}")) { + const nestedInterfaces = parse(parsedContent, level + 1); + // 替换嵌套的内容为接口引用 + if (nestedInterfaces.length > 0) { + nestedInterfaces.forEach((nestedInterface) => { + const pattern = `${nestedInterface.key}: {${nestedInterface.content}};`; + const replacement = `${nestedInterface.key}: ${firstUpperCase(nestedInterface.key)}Interface`; + parsedContent = parsedContent.replace(pattern, replacement); + }); + } + } + // 将解析结果添加到数组开头 + result.unshift({ + key: match[1], + level, + content: parsedContent, + }); + } + } + return result; + } + + /** + * 获取动态类名 + */ + const getDynamicClassNames = (value) => { + const names = new Set(); + // 匹配数组中的字符串元素(如 'text-center') + const arrayRegex = /['"](.*?)['"]/g; + let arrayMatch; + while ((arrayMatch = arrayRegex.exec(value)) !== null) { + arrayMatch[1].trim() && names.add(arrayMatch[1]); + } + // 匹配对象键(如 { 'text-a': 1 }) + const objKeyRegex = /[{,]\s*['"](.*?)['"]\s*:/g; + let objKeyMatch; + while ((objKeyMatch = objKeyRegex.exec(value)) !== null) { + objKeyMatch[1].trim() && names.add(objKeyMatch[1]); + } + // 匹配三元表达式中的字符串(如 'dark' 和 'light') + const ternaryRegex = /(\?|:)\s*['"](.*?)['"]/g; + let ternaryMatch; + while ((ternaryMatch = ternaryRegex.exec(value)) !== null) { + ternaryMatch[2].trim() && names.add(ternaryMatch[2]); + } + return Array.from(names); + }; + /** + * 获取类名 + */ + function getClassNames(html) { + const classRegex = /(?:class|:class)\s*=\s*(["'])([\s\S]*?)\1/gi; + const classNames = new Set(); + let match; + while ((match = classRegex.exec(html)) !== null) { + const isStaticClass = match[0].startsWith("class"); + const value = match[2].trim(); + if (isStaticClass) { + // 处理静态 class + value.split(/\s+/).forEach((name) => name && classNames.add(name)); + } + else { + // 处理动态 :class + getDynamicClassNames(value).forEach((name) => classNames.add(name)); + } + } + return Array.from(classNames); + } + /** + * 获取 class 内容 + */ + function getClassContent(html) { + const regex = /(?:class|:class)\s*=\s*(['"])([\s\S]*?)\1/g; + const texts = []; + let match; + while ((match = regex.exec(html)) !== null) { + texts.push(match[2]); + } + return texts; + } + /** + * 获取节点 + */ + function getNodes(code) { + const nodes = []; + const templateMatch = /