From 2a3defe9d0c5feca39d03dc942ea2d6e6b981f1d Mon Sep 17 00:00:00 2001 From: xiaoy <1003346758@qq.com> Date: Tue, 27 Feb 2024 10:11:40 +0800 Subject: [PATCH] feat(plugin): auto import plugin (#1397) feat(plugin): auto import plugin --- internals/unplugin-tiny-vue/.npmignore | 1 + internals/unplugin-tiny-vue/README.md | 26 ++++++++ .../unplugin-tiny-vue/example/index.html | 12 ++++ .../unplugin-tiny-vue/example/package.json | 23 +++++++ .../unplugin-tiny-vue/example/src/App.vue | 22 +++++++ .../unplugin-tiny-vue/example/src/main.js | 4 ++ .../unplugin-tiny-vue/example/vite.config.js | 15 +++++ internals/unplugin-tiny-vue/package.json | 46 ++++++++++++++ internals/unplugin-tiny-vue/src/index.ts | 62 +++++++++++++++++++ internals/unplugin-tiny-vue/tsconfig.json | 26 ++++++++ 10 files changed, 237 insertions(+) create mode 100644 internals/unplugin-tiny-vue/.npmignore create mode 100644 internals/unplugin-tiny-vue/README.md create mode 100644 internals/unplugin-tiny-vue/example/index.html create mode 100644 internals/unplugin-tiny-vue/example/package.json create mode 100644 internals/unplugin-tiny-vue/example/src/App.vue create mode 100644 internals/unplugin-tiny-vue/example/src/main.js create mode 100644 internals/unplugin-tiny-vue/example/vite.config.js create mode 100644 internals/unplugin-tiny-vue/package.json create mode 100644 internals/unplugin-tiny-vue/src/index.ts create mode 100644 internals/unplugin-tiny-vue/tsconfig.json diff --git a/internals/unplugin-tiny-vue/.npmignore b/internals/unplugin-tiny-vue/.npmignore new file mode 100644 index 000000000..4949f0980 --- /dev/null +++ b/internals/unplugin-tiny-vue/.npmignore @@ -0,0 +1 @@ +example/ \ No newline at end of file diff --git a/internals/unplugin-tiny-vue/README.md b/internals/unplugin-tiny-vue/README.md new file mode 100644 index 000000000..9817107b4 --- /dev/null +++ b/internals/unplugin-tiny-vue/README.md @@ -0,0 +1,26 @@ +# unplugin-tiny-vue + +A auto import plugin. Same function as [unplugin-vue-components](https://github.com/unplugin/unplugin-vue-components). +No import and component registration required. + +## Installation + +```bash +npm i @opentiny/unplugin-tiny-vue -D + +yarn i @opentiny/unplugin-tiny-vue -D +``` + +## Usage + +vite + +```js +// vite.config.js + +import autoImportPlugin from '@opentiny/unplugin-tiny-vue' + +export default { + plugins: [autoImportPlugin()] +} +``` diff --git a/internals/unplugin-tiny-vue/example/index.html b/internals/unplugin-tiny-vue/example/index.html new file mode 100644 index 000000000..f3845c632 --- /dev/null +++ b/internals/unplugin-tiny-vue/example/index.html @@ -0,0 +1,12 @@ + + + + + + Auto Import + + +
+ + + \ No newline at end of file diff --git a/internals/unplugin-tiny-vue/example/package.json b/internals/unplugin-tiny-vue/example/package.json new file mode 100644 index 000000000..aec2fa851 --- /dev/null +++ b/internals/unplugin-tiny-vue/example/package.json @@ -0,0 +1,23 @@ +{ + "name": "my-vue-app", + "description": "", + "author": "", + "version": "0.0.0", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "@opentiny/vue": "~3.12.1", + "@opentiny/vue-alert": "~3.13.0", + "@opentiny/vue-button-group": "~3.13.0", + "@opentiny/vue-icon": "^3.12.0", + "vue": "^3.3.9" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.1.0", + "vite": "link:../node_modules/vite", + "vite-plugin-inspect": "^0.8.3" + } +} diff --git a/internals/unplugin-tiny-vue/example/src/App.vue b/internals/unplugin-tiny-vue/example/src/App.vue new file mode 100644 index 000000000..35941f9e8 --- /dev/null +++ b/internals/unplugin-tiny-vue/example/src/App.vue @@ -0,0 +1,22 @@ + + + diff --git a/internals/unplugin-tiny-vue/example/src/main.js b/internals/unplugin-tiny-vue/example/src/main.js new file mode 100644 index 000000000..01433bca2 --- /dev/null +++ b/internals/unplugin-tiny-vue/example/src/main.js @@ -0,0 +1,4 @@ +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/internals/unplugin-tiny-vue/example/vite.config.js b/internals/unplugin-tiny-vue/example/vite.config.js new file mode 100644 index 000000000..115c87780 --- /dev/null +++ b/internals/unplugin-tiny-vue/example/vite.config.js @@ -0,0 +1,15 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import Inspect from 'vite-plugin-inspect' +import autoImportPlugin from '../dist/index.js' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue(), Inspect(), autoImportPlugin()], + define: { + 'process.env': { ...process.env, TINY_MODE: 'pc' } + }, + resolve: { + extensions: ['.js', '.jsx', '.vue', '.ts'] + } +}) diff --git a/internals/unplugin-tiny-vue/package.json b/internals/unplugin-tiny-vue/package.json new file mode 100644 index 000000000..78adefca1 --- /dev/null +++ b/internals/unplugin-tiny-vue/package.json @@ -0,0 +1,46 @@ +{ + "name": "@opentiny/unplugin-tiny-vue", + "version": "1.0.0", + "description": "A vite auto import plugin for TinyVue", + "main": "dist/index.cjs", + "module": "dist/index.js", + "typings": "dist/index.d.ts", + "exports": { + ".": { + "require": "./dist/index.cjs", + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } + }, + "scripts": { + "dev": "pnpm run build --watch --ignore-watch example", + "build": "rimraf dist && tsup src/index.ts --dts --format cjs,esm", + "prepublishOnly": "pnpm build" + }, + "type": "module", + "types": "dist/index.d.ts", + "author": "Tiny Vue Team", + "repository": { + "type": "git", + "url": "git@github.com:opentiny/tiny-vue.git" + }, + "keywords": [ + "vite-plugin", + "TinyVue", + "vite", + "auto-import" + ], + "license": "MIT", + "peerDependencies": { + "vite": ">=4" + }, + "dependencies": { + "magic-string": "^0.27.0" + }, + "devDependencies": { + "rimraf": "^5.0.5", + "tsup": "7.2.0", + "typescript": "^5.0.0", + "vite": "^4.3.8" + } +} diff --git a/internals/unplugin-tiny-vue/src/index.ts b/internals/unplugin-tiny-vue/src/index.ts new file mode 100644 index 000000000..7405f5d20 --- /dev/null +++ b/internals/unplugin-tiny-vue/src/index.ts @@ -0,0 +1,62 @@ +import MagicString from 'magic-string' +import type { Plugin } from 'vite' + +function pascalCase(str: string) { + const camelCaseStr = str.replace(/-(\w)/g, (_, c) => (c ? c.toUpperCase() : '')) + return camelCaseStr.charAt(0).toUpperCase() + camelCaseStr.slice(1) +} + +const resolveVue = (code: string, s: MagicString) => { + const results: any = [] + + for (const match of code.matchAll(/_resolveComponent[0-9]*\("(.+?)"\)/g)) { + const matchedName = match[1] + if (match.index != null && matchedName && !matchedName.startsWith('_')) { + const start = match.index + const end = start + match[0].length + results.push({ + rawName: matchedName, + replace: (resolved: string) => s.overwrite(start, end, resolved) + }) + } + } + + return results +} + +const findComponent = (rawName: string, name: string, s: MagicString) => { + if (!name.match(/^Tiny[a-zA-Z]/)) { + return + } + s.prepend(`import ${name} from '@opentiny/vue-${rawName.slice(5)}';\n`) +} + +const transformCode = (code) => { + const s = new MagicString(code) + const results = resolveVue(code, s) + + for (const { rawName, replace } of results) { + const name = pascalCase(rawName) + findComponent(rawName, name, s) + replace(name) + } + + const result = s.toString() + return result +} + +export default function vitePluginAutoImport(): Plugin { + return { + name: '@opentiny/auto-import', + + transform(code, id) { + // 不处理node_modules内的依赖 + if (/\.(?:vue)$/.test(id) && !/(node_modules)/.test(id)) { + return { + code: transformCode(code), + map: null + } + } + } + } +} diff --git a/internals/unplugin-tiny-vue/tsconfig.json b/internals/unplugin-tiny-vue/tsconfig.json new file mode 100644 index 000000000..83db8d40d --- /dev/null +++ b/internals/unplugin-tiny-vue/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "module": "ESNext", + "target": "esnext", + "moduleResolution": "node", + "strict": true, + "declaration": true, + "noUnusedLocals": true, + "esModuleInterop": true, + "outDir": "dist", + "lib": [ + "ESNext" + ], + "sourceMap": false, + "noEmitOnError": true, + "noImplicitAny": false + }, + "include": [ + "src/*", + "*.d.ts" + ], + "exclude": [ + "dist", + "node_modules" + ] +} \ No newline at end of file