From 1fabf99aadad2b9df992c6cbf5eb506318812cf5 Mon Sep 17 00:00:00 2001 From: "HOMEDO\\zhangjiayun" Date: Thu, 11 Aug 2022 17:35:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8A=A0=E4=B8=8Aunplugin-vue-componen?= =?UTF-8?q?ts=E8=87=AA=E5=8A=A8=E5=BC=95=E5=85=A5=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-zh-cn.md | 43 +++++++++-- README.md | 43 ++++++++--- package.json | 4 +- src/index.ts | 98 +++++++++++++++--------- test/components/{adavs => cdd}/Index.vue | 0 test/package.json | 16 ++++ test/store/module.ts | 1 - test/store/modules/info.ts | 1 - test/types/components.d.ts | 4 +- test/vite.config.js | 14 ++-- 10 files changed, 160 insertions(+), 64 deletions(-) rename test/components/{adavs => cdd}/Index.vue (100%) create mode 100644 test/package.json delete mode 100644 test/store/modules/info.ts diff --git a/README-zh-cn.md b/README-zh-cn.md index 09ad5f2..a07b9d1 100644 --- a/README-zh-cn.md +++ b/README-zh-cn.md @@ -5,15 +5,13 @@ vite 自动生成 引入文件插件 ## 快速开始 1. 安装 - - vite2: - `npm i vite-plugin-autogeneration-import-file@">=1.0.0 < 2.0.0" -D` - - - vite3: - `npm i vite-plugin-autogeneration-import-file@">=2.0.0 < 3.0.0" -D` - + + `npm i vite-plugin-autogeneration-import-file -D` 2. vite.config.js中使用 - + +- package.json type module ``` +//vite.config.js import {default as autogenerationImportFile,getName} from 'vite-plugin-autogeneration-import-file'; import { defineConfig } from 'vite' export default defineConfig({ @@ -41,6 +39,37 @@ export default defineConfig({ ])] }); ``` +- package.json type commonjs + +``` +//vite.config.js +import autoImport from 'vite-plugin-autogeneration-import-file'; +import { defineConfig } from 'vite' +export default defineConfig({ + root:'./index.html', + plugins: [autoImport.default([ + { + pattern:['**/*.{ts,js}','*.{ts,js}'], + dir:'test/store/modules', + toFile:'test/store/module.ts', + name:(name)=>{ + name = autoImport.getName(name); + return name[0].toUpperCase()+name.slice(1)+'Store'; + } + }, + { + pattern:['**/{Index.vue,index.ts,index.js}','*.{vue,ts,js}'], + dir:'test/components', + toFile:'test/types/components.d.ts', + template:'//import code\ndeclare module "@vue/runtime-core" {\n interface GlobalComponents {\n //key code\n }\n}\nexport {};', + codeTemplates:[ + {key:'//import code\n',template:'import {{name}} from "{{path}}"\n'}, + {key:' //key code\n',template:' {{name}}:typeof {{name}}\n'}, + ] + } + ])] +}); +``` ## 插件配置说明(dirOptions) ``` diff --git a/README.md b/README.md index c84c55f..0461600 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,15 @@ # vite-plugin-autogeneration-import-file Vite automatically generates import file plug-ins. -Support vite2 and vite^3.0.0-beta. +Support vite2 and vite3. ## 中文文档: [README-zh-cn.md](./README-zh-cn.md). ## Fast Start 1. Install - - vite2: - `npm i vite-plugin-autogeneration-import-file@">=1.0.0 < 2.0.0" -D` - - - vite3: - `npm i vite-plugin-autogeneration-import-file@">=2.0.0 < 3.0.0" -D` - + `npm i vite-plugin-autogeneration-import-file -D` 2. Example - +- package.json type module ``` //vite.config.js import {default as autogenerationImportFile,getName} from 'vite-plugin-autogeneration-import-file'; @@ -44,7 +39,37 @@ export default defineConfig({ ])] }); ``` - +- package.json type commonjs + +``` +//vite.config.js +import autoImport from 'vite-plugin-autogeneration-import-file'; +import { defineConfig } from 'vite' +export default defineConfig({ + root:'./index.html', + plugins: [autoImport.default([ + { + pattern:['**/*.{ts,js}','*.{ts,js}'], + dir:'test/store/modules', + toFile:'test/store/module.ts', + name:(name)=>{ + name = autoImport.getName(name); + return name[0].toUpperCase()+name.slice(1)+'Store'; + } + }, + { + pattern:['**/{Index.vue,index.ts,index.js}','*.{vue,ts,js}'], + dir:'test/components', + toFile:'test/types/components.d.ts', + template:'//import code\ndeclare module "@vue/runtime-core" {\n interface GlobalComponents {\n //key code\n }\n}\nexport {};', + codeTemplates:[ + {key:'//import code\n',template:'import {{name}} from "{{path}}"\n'}, + {key:' //key code\n',template:' {{name}}:typeof {{name}}\n'}, + ] + } + ])] +}); +``` ## Configuration Description(dirOptions) ``` interface codeTemplate { //Code Templates diff --git a/package.json b/package.json index 0333d3b..2d82e61 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "dist" ], "scripts": { - "test": "npm run build && vite --config ./test/vite.config.js", + "test": "npm run build && cd ./test && npm run dev", "clean": "rimraf dist", "build": "npm run clean && microbundle -f esm,cjs", "release": "release-it", @@ -47,6 +47,6 @@ "micromatch": "^4.0.5" }, "peerDependencies": { - "vite": "^3.0.0-beta" + "vite": ">2.0.2" } } diff --git a/src/index.ts b/src/index.ts index eefb82b..ca3eb4d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,16 +4,19 @@ import * as fs from 'fs'; import * as path from "path"; import { normalizePath } from 'vite'; let isServer = false; -let loadFiles: string[] = []; -let tmpRemoves: string[] = []; +let loadFiles: {fileName:string,name:string,dir:string}[][] = []; +let tmpRemovePaths: string[] = []; const toFileContents: Map = new Map(); //path转驼峰变量名并剔除最后的index/Index -export const getName = function (fileName: string, nameTemplate = '{{name}}'): string { +export const getName = function (fileName: string, nameTemplate:string | ((name: string) => string) = '{{name}}'): string { + if (typeof nameTemplate == 'function') { + return nameTemplate(fileName); + } const index = fileName.lastIndexOf('.'); if (index > 0) { fileName = fileName.slice(0, index); } - let fileNameArr = nameTemplate.replace(/\{\{name\}}/g, fileName.replace(/\\/g, '/')).replace(/\//g, '_').split('_'); + let fileNameArr = nameTemplate.replace(/\{\{name\}}/g, fileName.replace(/\\/g, '/')).replace(/[\/-]/g, '_').split('_'); if (fileNameArr[fileNameArr.length - 1] == 'index' || fileNameArr[fileNameArr.length - 1] == 'Index') { fileNameArr.pop(); } @@ -46,7 +49,7 @@ const getFileImportPath = function (dir: string, fileName: string): string { if (fileName.endsWith('.ts')) { fileName = fileName.slice(0, -3); } - return normalizePath(fileName); + return fileName; } //获取导入文件代码 @@ -60,13 +63,7 @@ const getCode = function (dir: string, if (!relativePath.startsWith('../')) { relativePath = './' + relativePath; } - if (typeof name == 'function') { - fileName = name(getName(fileName)); - - } else { - fileName = getName(fileName, name); - } - + fileName = getName(fileName, name); let codeTemplate: codeTemplate[] = JSON.parse(JSON.stringify(codeTemplates)); if (!codeTemplate.length) { codeTemplate.push({ @@ -80,7 +77,9 @@ const getCode = function (dir: string, return codeTemplate; } -const loadPath = async function (dir: string, +const loadPath = async function ( + optionIndex:number, + dir: string, toFile: string, pattern: fg.Pattern | fg.Pattern[], options: fg.Options, @@ -89,13 +88,11 @@ const loadPath = async function (dir: string, codeTemplates: codeTemplate[] = []) { const entries = await fg(pattern, Object.assign({ cwd: dir, dot: true }, options)); let str = template ? template : '//当前文件由vite-plugin-autogeneration-import-file自动生成\n//code'; - entries.forEach((fileName: string) => { + entries.forEach((fileName) => { getCode(dir, fileName, toFile, name, codeTemplates).forEach((item) => { str = str.replace(item.key, item.value + item.key); }); - if (isServer) { - loadFiles.push(fileName); - } + loadFiles[optionIndex].push({fileName,name:getName(fileName,name),dir}); }); str && fs.writeFileSync(toFile, str); console.log(`mk ${toFile} success\n`) @@ -110,11 +107,34 @@ export function readFileSync(...args: Parameters): Retur } } +export function resolvers(options={include:[0]}){ + return [ + { + type: 'component', + resolve: async (componentName: string) => { + for(const index of options.include) + { + let componentInfo = loadFiles[index].find(({name})=>name == componentName); + if(componentInfo){ + return path.resolve(componentInfo.dir, componentInfo.fileName) + } + } + }, + }, + // { + // type: 'directive', + // resolve: async (name: string) => { + // return resolveDirective(name, await resolveOptions()) + // }, + // }, + ] +} + export default function loadPathsPlugin(dirOptions: dirOptions) { return { name: 'load-path-ts', configureServer() {//服务器启动时被调用 - dirOptions.forEach(item => { + dirOptions.forEach((item,index) => { isServer = true; fs.watch(item.dir, { recursive: true }, function (eventType: fs.WatchEventType, fileName: string) { @@ -130,9 +150,9 @@ export default function loadPathsPlugin(dirOptions: dirOptions) { if (micromatch.isMatch(fileName, item.pattern)) { changeFiles = [fileName]; } - } else if (tmpRemoves.length && fs.existsSync(path.resolve(filePath, tmpRemoves[0]))) { + } else if (tmpRemovePaths.length && fs.existsSync(path.resolve(filePath, tmpRemovePaths[0]))) { //如果是重命名文件夹 - changeFiles = tmpRemoves; + changeFiles = tmpRemovePaths; prefix = fileName + '/'; } changeFiles.forEach(fileName => { @@ -140,46 +160,54 @@ export default function loadPathsPlugin(dirOptions: dirOptions) { code.forEach((codeItem) => { str = str.replace(codeItem.key, codeItem.value + codeItem.key); }); - loadFiles.push(prefix + fileName); + loadFiles[index].push({fileName:prefix + fileName,name:getName(prefix + fileName,item.name),dir:item.dir}); }) if (changeFiles.length) { toFileContents.set(item.toFile, str); fs.writeFileSync(item.toFile, str); console.log(item.toFile + ' add code'); } - tmpRemoves = []; + tmpRemovePaths = []; } else {//不存在文件 - let changeFiles = loadFiles.filter(name => name.startsWith(fileName + '/') || name == fileName); - changeFiles.forEach(fileName => { - const code = getCode(item.dir, fileName, item.toFile, item.name, item.codeTemplates); - code.forEach((codeItem) => { - str = str.replace(codeItem.value, ''); - }); - loadFiles.slice(loadFiles.indexOf(fileName), 1); - }); + let changeFiles:string[] = [] + loadFiles[index].slice(0).forEach((val,k)=>{ + if(val.fileName.startsWith(fileName + '/') || val.fileName == fileName){ + const code = getCode(item.dir, val.fileName, item.toFile, item.name, item.codeTemplates); + code.forEach((codeItem) => { + str = str.replace(codeItem.value, ''); + }); + loadFiles[index].slice(k, 1); + changeFiles.push(val.fileName) + } + }) if (changeFiles.length) { toFileContents.set(item.toFile, str); fs.writeFileSync(item.toFile, str); - if (changeFiles[0] !== fileName) { - tmpRemoves = changeFiles.map(name => name.slice(fileName.length + 1)); + if (changeFiles[0] !== fileName) {//代表是文件夹改变 + tmpRemovePaths = changeFiles.map(name => name.slice(fileName.length + 1)); } else { - tmpRemoves = []; + tmpRemovePaths = []; } console.log(item.toFile + ' remove code'); } } } + console.log('loadFiles',loadFiles) }); }) }, async buildStart() { let proArr: Promise[] = []; - dirOptions.forEach(item => { - proArr.push(loadPath(item.dir, item.toFile, item.pattern, item.options || {}, item.name, item.template, item.codeTemplates)); + dirOptions.forEach((item,index) => { + loadFiles[index] = []; + proArr.push(loadPath(index,item.dir, item.toFile, item.pattern, item.options || {}, item.name, item.template, item.codeTemplates)); }) await Promise.allSettled(proArr); + console.log('loadFiles',JSON.stringify(loadFiles)) if (isServer) { + console.log(11111); dirOptions.forEach(item => { + toFileContents.set(item.toFile, readFileSync(item.toFile, 'utf8') as string); fs.watch(item.toFile, {}, function (eventType: fs.WatchEventType, fileName: string) { const content = toFileContents.get(item.toFile); if (content !== undefined && content !== readFileSync(item.toFile, 'utf8')) { diff --git a/test/components/adavs/Index.vue b/test/components/cdd/Index.vue similarity index 100% rename from test/components/adavs/Index.vue rename to test/components/cdd/Index.vue diff --git a/test/package.json b/test/package.json new file mode 100644 index 0000000..32ca320 --- /dev/null +++ b/test/package.json @@ -0,0 +1,16 @@ +{ + "name": "test", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "dev":"vite", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "vite": "^3.0.5", + "vite-plugin-autogeneration-import-file": "file:.." + } +} diff --git a/test/store/module.ts b/test/store/module.ts index 8a9b2b8..5efc7a6 100644 --- a/test/store/module.ts +++ b/test/store/module.ts @@ -1,3 +1,2 @@ //当前文件由vite-plugin-autogeneration-import-file自动生成 -export { default as InfoStore } from "./modules/info" //code \ No newline at end of file diff --git a/test/store/modules/info.ts b/test/store/modules/info.ts deleted file mode 100644 index e338731..0000000 --- a/test/store/modules/info.ts +++ /dev/null @@ -1 +0,0 @@ -export default 'b'; \ No newline at end of file diff --git a/test/types/components.d.ts b/test/types/components.d.ts index f1b2ffe..a293c24 100644 --- a/test/types/components.d.ts +++ b/test/types/components.d.ts @@ -1,12 +1,12 @@ import a from "../components/a.vue" import b from "../components/b.vue" -import adavs from "../components/adavs/Index.vue" +import cdd from "../components/cdd/Index.vue" //import code declare module "@vue/runtime-core" { interface GlobalComponents { a:typeof a b:typeof b - adavs:typeof adavs + cdd:typeof cdd //key code } } diff --git a/test/vite.config.js b/test/vite.config.js index 1244f3c..9fd2e35 100644 --- a/test/vite.config.js +++ b/test/vite.config.js @@ -1,21 +1,21 @@ -import {default as autogenerationImportFile,getName} from '../dist/index.js'; +import autoImport from 'vite-plugin-autogeneration-import-file'; import { defineConfig } from 'vite' export default defineConfig({ root:'./index.html', - plugins: [autogenerationImportFile([ + plugins: [autoImport.default([ { pattern:['**/*.{ts,js}','*.{ts,js}'], - dir:'test/store/modules', - toFile:'test/store/module.ts', + dir:'./store/modules', + toFile:'./store/module.ts', name:(name)=>{ - name = getName(name); + name = autoImport.getName(name); return name[0].toUpperCase()+name.slice(1)+'Store'; } }, { pattern:['**/{Index.vue,index.ts,index.js}','*.{vue,ts,js}'], - dir:'test/components', - toFile:'test/types/components.d.ts', + dir:'./components', + toFile:'./types/components.d.ts', template:'//import code\ndeclare module "@vue/runtime-core" {\n interface GlobalComponents {\n //key code\n }\n}\nexport {};', codeTemplates:[ {key:'//import code\n',template:'import {{name}} from "{{path}}"\n'},