├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml ├── renovate.json5 └── workflows │ └── gh-pages.yml ├── .gitignore ├── .node-version ├── .vscode ├── extensions.json └── settings.json ├── LICENSE ├── README.md ├── eslint.config.js ├── index.html ├── package.json ├── pnpm-lock.yaml ├── public └── CNAME ├── src ├── App.vue ├── assets │ └── logo.svg ├── auto-imports.d.ts ├── components.d.ts ├── components │ ├── Header.vue │ └── Settings.vue ├── composables │ └── store.ts ├── constants.ts ├── env.d.ts ├── main.ts ├── template │ ├── element-plus.js │ ├── main.vue │ ├── tsconfig.json │ └── welcome.vue └── utils │ ├── dependency.ts │ └── encode.ts ├── tsconfig.json ├── unocss.config.ts └── vite.config.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_size = 2 5 | end_of_line = lf 6 | insert_final_newline = true 7 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [sxzz, element-plus] 2 | -------------------------------------------------------------------------------- /.github/renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | extends: ['github>sxzz/renovate-config'], 3 | } 4 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: GitHub Pages 2 | on: 3 | push: 4 | branches: 5 | - main 6 | workflow_dispatch: {} 7 | jobs: 8 | deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | 13 | - name: Setup pnpm 14 | uses: pnpm/action-setup@v4.0.0 15 | 16 | - name: Setup Node 17 | uses: actions/setup-node@v4 18 | with: 19 | node-version-file: .node-version 20 | cache: pnpm 21 | 22 | - name: Install deps 23 | run: pnpm i --frozen-lockfile 24 | 25 | - name: Build 26 | run: pnpm run build 27 | 28 | - name: Deploy 29 | uses: peaceiris/actions-gh-pages@v4 30 | with: 31 | github_token: ${{ secrets.GITHUB_TOKEN }} 32 | publish_dir: ./dist 33 | force_orphan: true 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | *.log 5 | .eslintcache 6 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | lts/* 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["antfu.unocss"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "iconify.includes": ["ep"] 4 | } 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2021-PRESENT Element Plus (https://github.com/element-plus) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | # Element Plus Playground 6 | 7 | [![GitHub Pages](https://github.com/element-plus/element-plus-playground/actions/workflows/gh-pages.yml/badge.svg)](https://github.com/element-plus/element-plus-playground/actions/workflows/gh-pages.yml) 8 | 9 | You can go to [element-plus.run](https://element-plus.run/) to have a try! 😆 10 | 11 | ## Credits 12 | 13 | - [vuejs/repl](https://github.com/vuejs/repl) 14 | 15 | ## License 16 | 17 | [MIT](./LICENSE) License © 2021-PRESENT [三咲智子](https://github.com/sxzz) 18 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import { sxzz } from '@sxzz/eslint-config' 2 | export default sxzz() 3 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Element Plus Playground 9 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "element-plus-playground", 3 | "version": "2.5.1", 4 | "packageManager": "pnpm@10.2.0", 5 | "description": "Element Plus Playground", 6 | "type": "module", 7 | "engines": { 8 | "node": ">=20.10" 9 | }, 10 | "keywords": [ 11 | "element", 12 | "element-plus", 13 | "playground", 14 | "repl" 15 | ], 16 | "license": "MIT", 17 | "scripts": { 18 | "dev": "vite", 19 | "build": "vite build", 20 | "preview": "vite preview", 21 | "lint": "eslint --cache --max-warnings 0 .", 22 | "lint:fix": "pnpm run lint --fix", 23 | "typecheck": "vue-tsc --noEmit", 24 | "release": "bumpp", 25 | "format": "prettier --write --cache ." 26 | }, 27 | "dependencies": { 28 | "@unocss/reset": "^65.4.3", 29 | "@vue/repl": "^4.5.0", 30 | "@vueuse/core": "^12.5.0", 31 | "element-plus": "^2.9.3", 32 | "semver": "^7.7.1", 33 | "vue": "^3.5.13" 34 | }, 35 | "devDependencies": { 36 | "@iconify-json/ri": "^1.2.5", 37 | "@sxzz/eslint-config": "^5.0.1", 38 | "@sxzz/prettier-config": "^2.1.1", 39 | "@types/node": "^22.13.1", 40 | "@types/semver": "^7.5.8", 41 | "@unocss/eslint-plugin": "^65.4.3", 42 | "@unocss/transformer-directives": "^65.4.3", 43 | "@vitejs/plugin-vue": "^5.2.1", 44 | "@vue/tsconfig": "^0.7.0", 45 | "bumpp": "^10.0.1", 46 | "eslint": "^9.19.0", 47 | "prettier": "^3.4.2", 48 | "sass": "^1.83.4", 49 | "typescript": "^5.7.3", 50 | "unocss": "^65.4.3", 51 | "unplugin-auto-import": "^19.0.0", 52 | "unplugin-vue-components": "^28.0.0", 53 | "vite": "^6.0.11", 54 | "vite-plugin-inspect": "^10.1.0", 55 | "vite-plugin-mkcert": "^1.17.6", 56 | "vue-tsc": "^2.2.0" 57 | }, 58 | "prettier": "@sxzz/prettier-config" 59 | } 60 | -------------------------------------------------------------------------------- /public/CNAME: -------------------------------------------------------------------------------- 1 | element-plus.run 2 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 2 | 71 | 72 | 91 | 92 | 114 | -------------------------------------------------------------------------------- /src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/auto-imports.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* prettier-ignore */ 3 | // @ts-nocheck 4 | // noinspection JSUnusedGlobalSymbols 5 | // Generated by unplugin-auto-import 6 | export {} 7 | declare global { 8 | const EffectScope: typeof import('vue')['EffectScope'] 9 | const ElMessage: typeof import('element-plus/es')['ElMessage'] 10 | const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] 11 | const IMPORT_MAP: typeof import('./composables/store')['IMPORT_MAP'] 12 | const LEGACY_IMPORT_MAP: typeof import('./composables/store')['LEGACY_IMPORT_MAP'] 13 | const TSCONFIG: typeof import('./composables/store')['TSCONFIG'] 14 | const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] 15 | const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] 16 | const computed: typeof import('vue')['computed'] 17 | const computedAsync: typeof import('@vueuse/core')['computedAsync'] 18 | const computedEager: typeof import('@vueuse/core')['computedEager'] 19 | const computedInject: typeof import('@vueuse/core')['computedInject'] 20 | const computedWithControl: typeof import('@vueuse/core')['computedWithControl'] 21 | const controlledComputed: typeof import('@vueuse/core')['controlledComputed'] 22 | const controlledRef: typeof import('@vueuse/core')['controlledRef'] 23 | const createApp: typeof import('vue')['createApp'] 24 | const createEventHook: typeof import('@vueuse/core')['createEventHook'] 25 | const createGlobalState: typeof import('@vueuse/core')['createGlobalState'] 26 | const createInjectionState: typeof import('@vueuse/core')['createInjectionState'] 27 | const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn'] 28 | const createReusableTemplate: typeof import('@vueuse/core')['createReusableTemplate'] 29 | const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable'] 30 | const createTemplatePromise: typeof import('@vueuse/core')['createTemplatePromise'] 31 | const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn'] 32 | const customRef: typeof import('vue')['customRef'] 33 | const debouncedRef: typeof import('@vueuse/core')['debouncedRef'] 34 | const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch'] 35 | const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] 36 | const defineComponent: typeof import('vue')['defineComponent'] 37 | const eagerComputed: typeof import('@vueuse/core')['eagerComputed'] 38 | const effectScope: typeof import('vue')['effectScope'] 39 | const extendRef: typeof import('@vueuse/core')['extendRef'] 40 | const getCurrentInstance: typeof import('vue')['getCurrentInstance'] 41 | const getCurrentScope: typeof import('vue')['getCurrentScope'] 42 | const h: typeof import('vue')['h'] 43 | const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] 44 | const inject: typeof import('vue')['inject'] 45 | const injectLocal: typeof import('@vueuse/core')['injectLocal'] 46 | const isDefined: typeof import('@vueuse/core')['isDefined'] 47 | const isProxy: typeof import('vue')['isProxy'] 48 | const isReactive: typeof import('vue')['isReactive'] 49 | const isReadonly: typeof import('vue')['isReadonly'] 50 | const isRef: typeof import('vue')['isRef'] 51 | const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable'] 52 | const markRaw: typeof import('vue')['markRaw'] 53 | const nextTick: typeof import('vue')['nextTick'] 54 | const onActivated: typeof import('vue')['onActivated'] 55 | const onBeforeMount: typeof import('vue')['onBeforeMount'] 56 | const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] 57 | const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] 58 | const onClickOutside: typeof import('@vueuse/core')['onClickOutside'] 59 | const onDeactivated: typeof import('vue')['onDeactivated'] 60 | const onElementRemoval: typeof import('@vueuse/core')['onElementRemoval'] 61 | const onErrorCaptured: typeof import('vue')['onErrorCaptured'] 62 | const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke'] 63 | const onLongPress: typeof import('@vueuse/core')['onLongPress'] 64 | const onMounted: typeof import('vue')['onMounted'] 65 | const onRenderTracked: typeof import('vue')['onRenderTracked'] 66 | const onRenderTriggered: typeof import('vue')['onRenderTriggered'] 67 | const onScopeDispose: typeof import('vue')['onScopeDispose'] 68 | const onServerPrefetch: typeof import('vue')['onServerPrefetch'] 69 | const onStartTyping: typeof import('@vueuse/core')['onStartTyping'] 70 | const onUnmounted: typeof import('vue')['onUnmounted'] 71 | const onUpdated: typeof import('vue')['onUpdated'] 72 | const onWatcherCleanup: typeof import('vue')['onWatcherCleanup'] 73 | const pausableWatch: typeof import('@vueuse/core')['pausableWatch'] 74 | const provide: typeof import('vue')['provide'] 75 | const provideLocal: typeof import('@vueuse/core')['provideLocal'] 76 | const reactify: typeof import('@vueuse/core')['reactify'] 77 | const reactifyObject: typeof import('@vueuse/core')['reactifyObject'] 78 | const reactive: typeof import('vue')['reactive'] 79 | const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed'] 80 | const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit'] 81 | const reactivePick: typeof import('@vueuse/core')['reactivePick'] 82 | const readonly: typeof import('vue')['readonly'] 83 | const ref: typeof import('vue')['ref'] 84 | const refAutoReset: typeof import('@vueuse/core')['refAutoReset'] 85 | const refDebounced: typeof import('@vueuse/core')['refDebounced'] 86 | const refDefault: typeof import('@vueuse/core')['refDefault'] 87 | const refThrottled: typeof import('@vueuse/core')['refThrottled'] 88 | const refWithControl: typeof import('@vueuse/core')['refWithControl'] 89 | const resolveComponent: typeof import('vue')['resolveComponent'] 90 | const resolveRef: typeof import('@vueuse/core')['resolveRef'] 91 | const resolveUnref: typeof import('@vueuse/core')['resolveUnref'] 92 | const shallowReactive: typeof import('vue')['shallowReactive'] 93 | const shallowReadonly: typeof import('vue')['shallowReadonly'] 94 | const shallowRef: typeof import('vue')['shallowRef'] 95 | const syncRef: typeof import('@vueuse/core')['syncRef'] 96 | const syncRefs: typeof import('@vueuse/core')['syncRefs'] 97 | const templateRef: typeof import('@vueuse/core')['templateRef'] 98 | const throttledRef: typeof import('@vueuse/core')['throttledRef'] 99 | const throttledWatch: typeof import('@vueuse/core')['throttledWatch'] 100 | const toRaw: typeof import('vue')['toRaw'] 101 | const toReactive: typeof import('@vueuse/core')['toReactive'] 102 | const toRef: typeof import('vue')['toRef'] 103 | const toRefs: typeof import('vue')['toRefs'] 104 | const toValue: typeof import('vue')['toValue'] 105 | const triggerRef: typeof import('vue')['triggerRef'] 106 | const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount'] 107 | const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount'] 108 | const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted'] 109 | const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose'] 110 | const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted'] 111 | const unref: typeof import('vue')['unref'] 112 | const unrefElement: typeof import('@vueuse/core')['unrefElement'] 113 | const until: typeof import('@vueuse/core')['until'] 114 | const useActiveElement: typeof import('@vueuse/core')['useActiveElement'] 115 | const useAnimate: typeof import('@vueuse/core')['useAnimate'] 116 | const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference'] 117 | const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery'] 118 | const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter'] 119 | const useArrayFind: typeof import('@vueuse/core')['useArrayFind'] 120 | const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex'] 121 | const useArrayFindLast: typeof import('@vueuse/core')['useArrayFindLast'] 122 | const useArrayIncludes: typeof import('@vueuse/core')['useArrayIncludes'] 123 | const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin'] 124 | const useArrayMap: typeof import('@vueuse/core')['useArrayMap'] 125 | const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce'] 126 | const useArraySome: typeof import('@vueuse/core')['useArraySome'] 127 | const useArrayUnique: typeof import('@vueuse/core')['useArrayUnique'] 128 | const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue'] 129 | const useAsyncState: typeof import('@vueuse/core')['useAsyncState'] 130 | const useAttrs: typeof import('vue')['useAttrs'] 131 | const useBase64: typeof import('@vueuse/core')['useBase64'] 132 | const useBattery: typeof import('@vueuse/core')['useBattery'] 133 | const useBluetooth: typeof import('@vueuse/core')['useBluetooth'] 134 | const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints'] 135 | const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel'] 136 | const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation'] 137 | const useCached: typeof import('@vueuse/core')['useCached'] 138 | const useClipboard: typeof import('@vueuse/core')['useClipboard'] 139 | const useClipboardItems: typeof import('@vueuse/core')['useClipboardItems'] 140 | const useCloned: typeof import('@vueuse/core')['useCloned'] 141 | const useColorMode: typeof import('@vueuse/core')['useColorMode'] 142 | const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog'] 143 | const useCountdown: typeof import('@vueuse/core')['useCountdown'] 144 | const useCounter: typeof import('@vueuse/core')['useCounter'] 145 | const useCssModule: typeof import('vue')['useCssModule'] 146 | const useCssVar: typeof import('@vueuse/core')['useCssVar'] 147 | const useCssVars: typeof import('vue')['useCssVars'] 148 | const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement'] 149 | const useCycleList: typeof import('@vueuse/core')['useCycleList'] 150 | const useDark: typeof import('@vueuse/core')['useDark'] 151 | const useDateFormat: typeof import('@vueuse/core')['useDateFormat'] 152 | const useDebounce: typeof import('@vueuse/core')['useDebounce'] 153 | const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn'] 154 | const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory'] 155 | const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion'] 156 | const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation'] 157 | const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio'] 158 | const useDevicesList: typeof import('@vueuse/core')['useDevicesList'] 159 | const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia'] 160 | const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility'] 161 | const useDraggable: typeof import('@vueuse/core')['useDraggable'] 162 | const useDropZone: typeof import('@vueuse/core')['useDropZone'] 163 | const useElementBounding: typeof import('@vueuse/core')['useElementBounding'] 164 | const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint'] 165 | const useElementHover: typeof import('@vueuse/core')['useElementHover'] 166 | const useElementSize: typeof import('@vueuse/core')['useElementSize'] 167 | const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility'] 168 | const useEventBus: typeof import('@vueuse/core')['useEventBus'] 169 | const useEventListener: typeof import('@vueuse/core')['useEventListener'] 170 | const useEventSource: typeof import('@vueuse/core')['useEventSource'] 171 | const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper'] 172 | const useFavicon: typeof import('@vueuse/core')['useFavicon'] 173 | const useFetch: typeof import('@vueuse/core')['useFetch'] 174 | const useFileDialog: typeof import('@vueuse/core')['useFileDialog'] 175 | const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess'] 176 | const useFocus: typeof import('@vueuse/core')['useFocus'] 177 | const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin'] 178 | const useFps: typeof import('@vueuse/core')['useFps'] 179 | const useFullscreen: typeof import('@vueuse/core')['useFullscreen'] 180 | const useGamepad: typeof import('@vueuse/core')['useGamepad'] 181 | const useGeolocation: typeof import('@vueuse/core')['useGeolocation'] 182 | const useId: typeof import('vue')['useId'] 183 | const useIdle: typeof import('@vueuse/core')['useIdle'] 184 | const useImage: typeof import('@vueuse/core')['useImage'] 185 | const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll'] 186 | const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver'] 187 | const useInterval: typeof import('@vueuse/core')['useInterval'] 188 | const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn'] 189 | const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier'] 190 | const useLastChanged: typeof import('@vueuse/core')['useLastChanged'] 191 | const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage'] 192 | const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys'] 193 | const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory'] 194 | const useMediaControls: typeof import('@vueuse/core')['useMediaControls'] 195 | const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery'] 196 | const useMemoize: typeof import('@vueuse/core')['useMemoize'] 197 | const useMemory: typeof import('@vueuse/core')['useMemory'] 198 | const useModel: typeof import('vue')['useModel'] 199 | const useMounted: typeof import('@vueuse/core')['useMounted'] 200 | const useMouse: typeof import('@vueuse/core')['useMouse'] 201 | const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement'] 202 | const useMousePressed: typeof import('@vueuse/core')['useMousePressed'] 203 | const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver'] 204 | const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage'] 205 | const useNetwork: typeof import('@vueuse/core')['useNetwork'] 206 | const useNow: typeof import('@vueuse/core')['useNow'] 207 | const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl'] 208 | const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination'] 209 | const useOnline: typeof import('@vueuse/core')['useOnline'] 210 | const usePageLeave: typeof import('@vueuse/core')['usePageLeave'] 211 | const useParallax: typeof import('@vueuse/core')['useParallax'] 212 | const useParentElement: typeof import('@vueuse/core')['useParentElement'] 213 | const usePerformanceObserver: typeof import('@vueuse/core')['usePerformanceObserver'] 214 | const usePermission: typeof import('@vueuse/core')['usePermission'] 215 | const usePointer: typeof import('@vueuse/core')['usePointer'] 216 | const usePointerLock: typeof import('@vueuse/core')['usePointerLock'] 217 | const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe'] 218 | const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme'] 219 | const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast'] 220 | const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark'] 221 | const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages'] 222 | const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion'] 223 | const usePreferredReducedTransparency: typeof import('@vueuse/core')['usePreferredReducedTransparency'] 224 | const usePrevious: typeof import('@vueuse/core')['usePrevious'] 225 | const useRafFn: typeof import('@vueuse/core')['useRafFn'] 226 | const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] 227 | const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] 228 | const useSSRWidth: typeof import('@vueuse/core')['useSSRWidth'] 229 | const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation'] 230 | const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea'] 231 | const useScriptTag: typeof import('@vueuse/core')['useScriptTag'] 232 | const useScroll: typeof import('@vueuse/core')['useScroll'] 233 | const useScrollLock: typeof import('@vueuse/core')['useScrollLock'] 234 | const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage'] 235 | const useShare: typeof import('@vueuse/core')['useShare'] 236 | const useSlots: typeof import('vue')['useSlots'] 237 | const useSorted: typeof import('@vueuse/core')['useSorted'] 238 | const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition'] 239 | const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis'] 240 | const useStepper: typeof import('@vueuse/core')['useStepper'] 241 | const useStorage: typeof import('@vueuse/core')['useStorage'] 242 | const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync'] 243 | const useStore: typeof import('./composables/store')['useStore'] 244 | const useStyleTag: typeof import('@vueuse/core')['useStyleTag'] 245 | const useSupported: typeof import('@vueuse/core')['useSupported'] 246 | const useSwipe: typeof import('@vueuse/core')['useSwipe'] 247 | const useTemplateRef: typeof import('vue')['useTemplateRef'] 248 | const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList'] 249 | const useTextDirection: typeof import('@vueuse/core')['useTextDirection'] 250 | const useTextSelection: typeof import('@vueuse/core')['useTextSelection'] 251 | const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize'] 252 | const useThrottle: typeof import('@vueuse/core')['useThrottle'] 253 | const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn'] 254 | const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory'] 255 | const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo'] 256 | const useTimeout: typeof import('@vueuse/core')['useTimeout'] 257 | const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn'] 258 | const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll'] 259 | const useTimestamp: typeof import('@vueuse/core')['useTimestamp'] 260 | const useTitle: typeof import('@vueuse/core')['useTitle'] 261 | const useToNumber: typeof import('@vueuse/core')['useToNumber'] 262 | const useToString: typeof import('@vueuse/core')['useToString'] 263 | const useToggle: typeof import('@vueuse/core')['useToggle'] 264 | const useTransition: typeof import('@vueuse/core')['useTransition'] 265 | const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams'] 266 | const useUserMedia: typeof import('@vueuse/core')['useUserMedia'] 267 | const useVModel: typeof import('@vueuse/core')['useVModel'] 268 | const useVModels: typeof import('@vueuse/core')['useVModels'] 269 | const useVibrate: typeof import('@vueuse/core')['useVibrate'] 270 | const useVirtualList: typeof import('@vueuse/core')['useVirtualList'] 271 | const useWakeLock: typeof import('@vueuse/core')['useWakeLock'] 272 | const useWebNotification: typeof import('@vueuse/core')['useWebNotification'] 273 | const useWebSocket: typeof import('@vueuse/core')['useWebSocket'] 274 | const useWebWorker: typeof import('@vueuse/core')['useWebWorker'] 275 | const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn'] 276 | const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus'] 277 | const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll'] 278 | const useWindowSize: typeof import('@vueuse/core')['useWindowSize'] 279 | const watch: typeof import('vue')['watch'] 280 | const watchArray: typeof import('@vueuse/core')['watchArray'] 281 | const watchAtMost: typeof import('@vueuse/core')['watchAtMost'] 282 | const watchDebounced: typeof import('@vueuse/core')['watchDebounced'] 283 | const watchDeep: typeof import('@vueuse/core')['watchDeep'] 284 | const watchEffect: typeof import('vue')['watchEffect'] 285 | const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable'] 286 | const watchImmediate: typeof import('@vueuse/core')['watchImmediate'] 287 | const watchOnce: typeof import('@vueuse/core')['watchOnce'] 288 | const watchPausable: typeof import('@vueuse/core')['watchPausable'] 289 | const watchPostEffect: typeof import('vue')['watchPostEffect'] 290 | const watchSyncEffect: typeof import('vue')['watchSyncEffect'] 291 | const watchThrottled: typeof import('@vueuse/core')['watchThrottled'] 292 | const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable'] 293 | const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter'] 294 | const whenever: typeof import('@vueuse/core')['whenever'] 295 | } 296 | // for type re-export 297 | declare global { 298 | // @ts-ignore 299 | export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue' 300 | import('vue') 301 | } 302 | -------------------------------------------------------------------------------- /src/components.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // @ts-nocheck 3 | // Generated by unplugin-vue-components 4 | // Read more: https://github.com/vuejs/core/pull/3399 5 | export {} 6 | 7 | /* prettier-ignore */ 8 | declare module 'vue' { 9 | export interface GlobalComponents { 10 | ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] 11 | ElForm: typeof import('element-plus/es')['ElForm'] 12 | ElFormItem: typeof import('element-plus/es')['ElFormItem'] 13 | ElLink: typeof import('element-plus/es')['ElLink'] 14 | ElOption: typeof import('element-plus/es')['ElOption'] 15 | ElPopover: typeof import('element-plus/es')['ElPopover'] 16 | ElSelect: typeof import('element-plus/es')['ElSelect'] 17 | ElTag: typeof import('element-plus/es')['ElTag'] 18 | ElTooltip: typeof import('element-plus/es')['ElTooltip'] 19 | Header: typeof import('./components/Header.vue')['default'] 20 | Settings: typeof import('./components/Settings.vue')['default'] 21 | } 22 | export interface ComponentCustomProperties { 23 | vLoading: typeof import('element-plus/es')['ElLoadingDirective'] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/components/Header.vue: -------------------------------------------------------------------------------- 1 | 69 | 70 | 181 | 182 | 208 | -------------------------------------------------------------------------------- /src/components/Settings.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 16 | -------------------------------------------------------------------------------- /src/composables/store.ts: -------------------------------------------------------------------------------- 1 | import { 2 | compileFile, 3 | File, 4 | mergeImportMap, 5 | useStore as useReplStore, 6 | type ImportMap, 7 | type StoreState, 8 | } from '@vue/repl' 9 | import { objectOmit } from '@vueuse/core' 10 | import { IS_DEV } from '@/constants' 11 | import { 12 | genCdnLink, 13 | genCompilerSfcLink, 14 | genImportMap, 15 | } from '@/utils/dependency' 16 | import { atou, utoa } from '@/utils/encode' 17 | import elementPlusCode from '../template/element-plus.js?raw' 18 | import mainCode from '../template/main.vue?raw' 19 | import tsconfigCode from '../template/tsconfig.json?raw' 20 | import welcomeCode from '../template/welcome.vue?raw' 21 | 22 | export interface Initial { 23 | serializedState?: string 24 | initialized?: () => void 25 | } 26 | export type VersionKey = 'vue' | 'elementPlus' | 'typescript' 27 | export type Versions = Record 28 | export interface UserOptions { 29 | styleSource?: string 30 | showHidden?: boolean 31 | vueVersion?: string 32 | tsVersion?: string 33 | epVersion?: string 34 | } 35 | export type SerializeState = Record & { 36 | _o?: UserOptions 37 | } 38 | 39 | const MAIN_FILE = 'src/PlaygroundMain.vue' 40 | const APP_FILE = 'src/App.vue' 41 | const ELEMENT_PLUS_FILE = 'src/element-plus.js' 42 | const LEGACY_IMPORT_MAP = 'src/import_map.json' 43 | export const IMPORT_MAP = 'import-map.json' 44 | export const TSCONFIG = 'tsconfig.json' 45 | 46 | export const useStore = (initial: Initial) => { 47 | const saved: SerializeState | undefined = initial.serializedState 48 | ? deserialize(initial.serializedState) 49 | : undefined 50 | const pr = 51 | new URLSearchParams(location.search).get('pr') || 52 | saved?._o?.styleSource?.split('-', 2)[1] 53 | const prUrl = `https://preview-${pr}-element-plus.surge.sh/bundle/dist` 54 | 55 | const versions = reactive({ 56 | vue: saved?._o?.vueVersion ?? 'latest', 57 | elementPlus: pr ? 'preview' : (saved?._o?.epVersion ?? 'latest'), 58 | typescript: saved?._o?.tsVersion ?? 'latest', 59 | }) 60 | const userOptions: UserOptions = pr 61 | ? { 62 | showHidden: true, 63 | styleSource: `${prUrl}/index.css`, 64 | } 65 | : {} 66 | Object.assign(userOptions, { 67 | vueVersion: saved?._o?.vueVersion, 68 | tsVersion: saved?._o?.tsVersion, 69 | epVersion: saved?._o?.epVersion, 70 | }) 71 | const hideFile = !IS_DEV && !userOptions.showHidden 72 | 73 | const [nightly, toggleNightly] = useToggle(false) 74 | const builtinImportMap = computed(() => { 75 | let importMap = genImportMap(versions, nightly.value) 76 | if (pr) 77 | importMap = mergeImportMap(importMap, { 78 | imports: { 79 | 'element-plus': `${prUrl}/index.full.min.mjs`, 80 | 'element-plus/': 'unsupported', 81 | }, 82 | }) 83 | return importMap 84 | }) 85 | 86 | const storeState: Partial = toRefs( 87 | reactive({ 88 | files: initFiles(), 89 | mainFile: MAIN_FILE, 90 | activeFilename: APP_FILE, 91 | vueVersion: computed(() => versions.vue), 92 | typescriptVersion: versions.typescript, 93 | builtinImportMap, 94 | template: { 95 | welcomeSFC: mainCode, 96 | }, 97 | sfcOptions: { 98 | script: { 99 | propsDestructure: true, 100 | }, 101 | }, 102 | }), 103 | ) 104 | const store = useReplStore(storeState) 105 | store.files[ELEMENT_PLUS_FILE].hidden = hideFile 106 | store.files[MAIN_FILE].hidden = hideFile 107 | setVueVersion(versions.vue).then(() => { 108 | initial.initialized?.() 109 | }) 110 | 111 | watch( 112 | () => versions.elementPlus, 113 | (version) => { 114 | store.files[ELEMENT_PLUS_FILE].code = generateElementPlusCode( 115 | version, 116 | userOptions.styleSource, 117 | ).trim() 118 | compileFile(store, store.files[ELEMENT_PLUS_FILE]).then( 119 | (errs) => (store.errors = errs), 120 | ) 121 | }, 122 | ) 123 | watch( 124 | builtinImportMap, 125 | (newBuiltinImportMap) => { 126 | const importMap = JSON.parse(store.files[IMPORT_MAP].code) 127 | store.files[IMPORT_MAP].code = JSON.stringify( 128 | mergeImportMap(importMap, newBuiltinImportMap), 129 | undefined, 130 | 2, 131 | ) 132 | }, 133 | { deep: true }, 134 | ) 135 | 136 | function generateElementPlusCode(version: string, styleSource?: string) { 137 | const style = styleSource 138 | ? styleSource.replace('#VERSION#', version) 139 | : genCdnLink( 140 | nightly.value ? '@element-plus/nightly' : 'element-plus', 141 | version, 142 | '/dist/index.css', 143 | ) 144 | const darkStyle = style.replace( 145 | '/dist/index.css', 146 | '/theme-chalk/dark/css-vars.css', 147 | ) 148 | return elementPlusCode 149 | .replace('#STYLE#', style) 150 | .replace('#DARKSTYLE#', darkStyle) 151 | } 152 | function init() { 153 | watchEffect(() => { 154 | compileFile(store, store.activeFile).then((errs) => (store.errors = errs)) 155 | }) 156 | for (const [filename, file] of Object.entries(store.files)) { 157 | if (filename === store.activeFilename) continue 158 | compileFile(store, file).then((errs) => store.errors.push(...errs)) 159 | } 160 | 161 | watch( 162 | () => [ 163 | store.files[TSCONFIG]?.code, 164 | store.typescriptVersion, 165 | store.locale, 166 | store.dependencyVersion, 167 | store.vueVersion, 168 | ], 169 | useDebounceFn(() => store.reloadLanguageTools?.(), 300), 170 | { deep: true }, 171 | ) 172 | } 173 | function serialize() { 174 | const state: SerializeState = { ...store.getFiles() } 175 | state._o = userOptions 176 | return utoa(JSON.stringify(state)) 177 | } 178 | function deserialize(text: string): SerializeState { 179 | const state = JSON.parse(atou(text)) 180 | return state 181 | } 182 | function initFiles() { 183 | const files: Record = Object.create(null) 184 | if (saved) { 185 | for (let [filename, file] of Object.entries(objectOmit(saved, ['_o']))) { 186 | if ( 187 | ![IMPORT_MAP, TSCONFIG].includes(filename) && 188 | !filename.startsWith('src/') 189 | ) { 190 | filename = `src/${filename}` 191 | } 192 | if (filename === LEGACY_IMPORT_MAP) { 193 | filename = IMPORT_MAP 194 | } 195 | files[filename] = new File(filename, file as string) 196 | } 197 | } else { 198 | files[APP_FILE] = new File(APP_FILE, welcomeCode) 199 | } 200 | if (!files[ELEMENT_PLUS_FILE]) { 201 | files[ELEMENT_PLUS_FILE] = new File( 202 | ELEMENT_PLUS_FILE, 203 | generateElementPlusCode(versions.elementPlus, userOptions.styleSource), 204 | ) 205 | } 206 | if (!files[TSCONFIG]) { 207 | files[TSCONFIG] = new File(TSCONFIG, tsconfigCode) 208 | } 209 | return files 210 | } 211 | async function setVueVersion(version: string) { 212 | store.compiler = await import( 213 | /* @vite-ignore */ genCompilerSfcLink(version) 214 | ) 215 | versions.vue = version 216 | } 217 | async function setVersion(key: VersionKey, version: string) { 218 | switch (key) { 219 | case 'vue': 220 | userOptions.vueVersion = version 221 | await setVueVersion(version) 222 | break 223 | case 'elementPlus': 224 | versions.elementPlus = version 225 | userOptions.epVersion = version 226 | break 227 | case 'typescript': 228 | store.typescriptVersion = version 229 | userOptions.tsVersion = version 230 | break 231 | } 232 | } 233 | 234 | const utils = { 235 | versions, 236 | pr, 237 | setVersion, 238 | toggleNightly, 239 | serialize, 240 | init, 241 | } 242 | Object.assign(store, utils) 243 | 244 | return store as typeof store & typeof utils 245 | } 246 | 247 | export type Store = ReturnType 248 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | export const IS_DEV = import.meta.env.DEV 2 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from '@/App.vue' 3 | import '@unocss/reset/tailwind.css' 4 | import '@vue/repl/style.css' 5 | import 'element-plus/theme-chalk/dark/css-vars.css' 6 | import 'uno.css' 7 | 8 | // @ts-expect-error Custom window property 9 | window.VUE_DEVTOOLS_CONFIG = { 10 | defaultSelectedAppId: 'repl', 11 | } 12 | 13 | createApp(App).mount('#app') 14 | -------------------------------------------------------------------------------- /src/template/element-plus.js: -------------------------------------------------------------------------------- 1 | import ElementPlus from 'element-plus' 2 | import { getCurrentInstance } from 'vue' 3 | 4 | let installed = false 5 | await loadStyle() 6 | 7 | export function setupElementPlus() { 8 | if (installed) return 9 | const instance = getCurrentInstance() 10 | instance.appContext.app.use(ElementPlus) 11 | installed = true 12 | } 13 | 14 | export function loadStyle() { 15 | const styles = ['#STYLE#', '#DARKSTYLE#'].map((style) => { 16 | return new Promise((resolve, reject) => { 17 | const link = document.createElement('link') 18 | link.rel = 'stylesheet' 19 | link.href = style 20 | link.addEventListener('load', resolve) 21 | link.addEventListener('error', reject) 22 | document.body.append(link) 23 | }) 24 | }) 25 | return Promise.allSettled(styles) 26 | } 27 | -------------------------------------------------------------------------------- /src/template/main.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /src/template/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "jsx": "preserve", 5 | "module": "ESNext", 6 | "moduleResolution": "Bundler", 7 | "types": ["element-plus/global.d.ts"], 8 | "allowImportingTsExtensions": true, 9 | "allowJs": true, 10 | "checkJs": true 11 | }, 12 | "vueCompilerOptions": { 13 | "target": 3.3 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/template/welcome.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 18 | -------------------------------------------------------------------------------- /src/utils/dependency.ts: -------------------------------------------------------------------------------- 1 | import { gte } from 'semver' 2 | import type { Versions } from '@/composables/store' 3 | import type { ImportMap } from '@vue/repl' 4 | import type { MaybeRef } from '@vueuse/core' 5 | import type { Ref } from 'vue' 6 | 7 | export interface Dependency { 8 | pkg?: string 9 | version?: string 10 | path: string 11 | } 12 | 13 | export type Cdn = 'unpkg' | 'jsdelivr' | 'jsdelivr-fastly' 14 | export const cdn = useLocalStorage('setting-cdn', 'jsdelivr') 15 | 16 | export const genCdnLink = ( 17 | pkg: string, 18 | version: string | undefined, 19 | path: string, 20 | ) => { 21 | version = version ? `@${version}` : '' 22 | switch (cdn.value) { 23 | case 'jsdelivr': 24 | return `https://cdn.jsdelivr.net/npm/${pkg}${version}${path}` 25 | case 'jsdelivr-fastly': 26 | return `https://fastly.jsdelivr.net/npm/${pkg}${version}${path}` 27 | case 'unpkg': 28 | return `https://unpkg.com/${pkg}${version}${path}` 29 | } 30 | } 31 | 32 | export const genCompilerSfcLink = (version: string) => { 33 | return genCdnLink( 34 | '@vue/compiler-sfc', 35 | version, 36 | '/dist/compiler-sfc.esm-browser.js', 37 | ) 38 | } 39 | 40 | export const genImportMap = ( 41 | { vue, elementPlus }: Partial = {}, 42 | nightly: boolean, 43 | ): ImportMap => { 44 | const deps: Record = { 45 | vue: { 46 | pkg: '@vue/runtime-dom', 47 | version: vue, 48 | path: '/dist/runtime-dom.esm-browser.js', 49 | }, 50 | '@vue/shared': { 51 | version: vue, 52 | path: '/dist/shared.esm-bundler.js', 53 | }, 54 | 'element-plus': { 55 | pkg: nightly ? '@element-plus/nightly' : 'element-plus', 56 | version: elementPlus, 57 | path: '/dist/index.full.min.mjs', 58 | }, 59 | 'element-plus/': { 60 | pkg: 'element-plus', 61 | version: elementPlus, 62 | path: '/', 63 | }, 64 | '@element-plus/icons-vue': { 65 | version: '2', 66 | path: '/dist/index.min.js', 67 | }, 68 | } 69 | 70 | return { 71 | imports: Object.fromEntries( 72 | Object.entries(deps).map(([key, dep]) => [ 73 | key, 74 | genCdnLink(dep.pkg ?? key, dep.version, dep.path), 75 | ]), 76 | ), 77 | } 78 | } 79 | 80 | export const getVersions = (pkg: MaybeRef) => { 81 | const url = computed( 82 | () => `https://data.jsdelivr.com/v1/package/npm/${unref(pkg)}`, 83 | ) 84 | return useFetch(url, { 85 | initialData: [], 86 | afterFetch: (ctx) => ((ctx.data = ctx.data.versions), ctx), 87 | refetch: true, 88 | }).json().data as Ref 89 | } 90 | 91 | export const getSupportedVueVersions = () => { 92 | const versions = getVersions('vue') 93 | return computed(() => 94 | versions.value.filter((version) => gte(version, '3.2.0')), 95 | ) 96 | } 97 | 98 | export const getSupportedTSVersions = () => { 99 | const versions = getVersions('typescript') 100 | return computed(() => 101 | versions.value.filter( 102 | (version) => !version.includes('dev') && !version.includes('insiders'), 103 | ), 104 | ) 105 | } 106 | 107 | export const getSupportedEpVersions = (nightly: MaybeRef) => { 108 | const pkg = computed(() => 109 | unref(nightly) ? '@element-plus/nightly' : 'element-plus', 110 | ) 111 | const versions = getVersions(pkg) 112 | return computed(() => { 113 | if (unref(nightly)) return versions.value 114 | return versions.value.filter((version) => gte(version, '1.1.0-beta.18')) 115 | }) 116 | } 117 | -------------------------------------------------------------------------------- /src/utils/encode.ts: -------------------------------------------------------------------------------- 1 | // prefer old unicode hacks for backward compatibility 2 | // https://base64.guru/developers/javascript/examples/unicode-strings 3 | export function utoa(data: string): string { 4 | return btoa(unescape(encodeURIComponent(data))) 5 | } 6 | 7 | export function atou(base64: string): string { 8 | return decodeURIComponent(escape(atob(base64))) 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@/*": ["src/*"] 7 | }, 8 | "types": [], 9 | "skipLibCheck": true 10 | }, 11 | "include": ["src"], 12 | "exclude": ["src/template"] 13 | } 14 | -------------------------------------------------------------------------------- /unocss.config.ts: -------------------------------------------------------------------------------- 1 | import transformerDirective from '@unocss/transformer-directives' 2 | import { defineConfig, presetAttributify, presetIcons, presetUno } from 'unocss' 3 | 4 | export default defineConfig({ 5 | presets: [presetUno(), presetAttributify(), presetIcons()], 6 | transformers: [transformerDirective()], 7 | shortcuts: { 8 | 'color-primary': 'color-[var(--el-color-primary)]', 9 | }, 10 | }) 11 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs' 2 | import path from 'node:path' 3 | import vue from '@vitejs/plugin-vue' 4 | import replPkg from '@vue/repl/package.json' with { type: 'json' } 5 | import Unocss from 'unocss/vite' 6 | import AutoImport from 'unplugin-auto-import/vite' 7 | import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' 8 | import Components from 'unplugin-vue-components/vite' 9 | import { defineConfig } from 'vite' 10 | import Inspect from 'vite-plugin-inspect' 11 | import Mkcert from 'vite-plugin-mkcert' 12 | import pkg from './package.json' with { type: 'json' } 13 | 14 | const pathSrc = path.resolve(__dirname, 'src') 15 | 16 | export default defineConfig({ 17 | resolve: { 18 | alias: { 19 | '@': pathSrc, 20 | }, 21 | }, 22 | define: { 23 | 'import.meta.env.APP_VERSION': JSON.stringify(pkg.version), 24 | 'import.meta.env.REPL_VERSION': JSON.stringify(replPkg.version), 25 | }, 26 | build: { 27 | rollupOptions: { 28 | external: ['typescript'], 29 | }, 30 | }, 31 | server: { 32 | host: true, 33 | }, 34 | plugins: [ 35 | vue({ 36 | script: { 37 | defineModel: true, 38 | propsDestructure: true, 39 | fs: { 40 | fileExists: fs.existsSync, 41 | readFile: (file) => fs.readFileSync(file, 'utf-8'), 42 | }, 43 | }, 44 | }), 45 | AutoImport({ 46 | dirs: [path.resolve(pathSrc, 'composables')], 47 | imports: ['vue', '@vueuse/core'], 48 | resolvers: [ElementPlusResolver()], 49 | dts: path.resolve(pathSrc, 'auto-imports.d.ts'), 50 | }), 51 | Components({ 52 | dirs: [path.resolve(pathSrc, 'components')], 53 | resolvers: [ElementPlusResolver()], 54 | dts: path.resolve(pathSrc, 'components.d.ts'), 55 | }), 56 | Unocss(), 57 | Mkcert(), 58 | Inspect(), 59 | ], 60 | optimizeDeps: { 61 | exclude: ['@vue/repl'], 62 | }, 63 | }) 64 | --------------------------------------------------------------------------------