├── .github └── workflows │ └── ci.yml ├── .gitignore ├── README.md ├── docs ├── .gitignore ├── docs │ ├── .vitepress │ │ └── config.ts │ └── index.md ├── package.json ├── scripts │ └── gh-pages-deploy.js ├── vite.config.ts └── yarn.lock ├── vue-dd ├── LICENSE ├── README.md ├── cypress.config.js ├── cypress │ └── support │ │ ├── common.ts │ │ ├── component-index.html │ │ ├── component.js │ │ └── router │ │ ├── About.vue │ │ ├── Home.vue │ │ ├── Page.vue │ │ └── routes.js ├── demo │ ├── App.vue │ ├── main.ts │ └── vite.config.ts ├── index.html ├── package.json ├── src │ ├── NodeComplex.vue │ ├── NodePrimitive.vue │ ├── VueDd.spec.js │ ├── VueDd.vue │ ├── XRay.vue │ ├── assets │ │ ├── eye-full.svg │ │ ├── eye.svg │ │ └── fonts │ │ │ ├── vue-dd-icons.eot │ │ │ ├── vue-dd-icons.svg │ │ │ ├── vue-dd-icons.ttf │ │ │ └── vue-dd-icons.woff │ ├── components │ │ ├── XRayCheckbox.vue │ │ └── XRaySelect.vue │ ├── css │ │ ├── VueDd.code.css │ │ └── VueDd.css │ ├── features │ │ ├── setupFormComponent.js │ │ └── uniqueId.js │ ├── helpers.js │ ├── highlight.js │ │ ├── core.min.js │ │ └── javascript.min.js │ ├── index.ts │ ├── shims-vue.d.ts │ └── types.ts ├── test │ ├── __snapshots__ │ │ └── basic.test.ts.snap │ ├── as-async.test.ts │ ├── async.test.ts │ ├── basic.test.ts │ ├── components │ │ ├── AsAsync.vue │ │ ├── AsyncComp.vue │ │ ├── AsyncWrapper.vue │ │ └── Hello.vue │ ├── imports.test.ts │ └── vue-dd.test.ts ├── tsconfig.json ├── vite-env.d.ts ├── vite.config.ts ├── vitest.config.ts └── yarn.lock ├── vue2 ├── .gitignore ├── README.md ├── babel.config.js ├── jsconfig.json ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.vue │ ├── assets │ │ └── logo.png │ ├── components │ │ └── VueDdTest.vue │ └── main.js ├── vue.config.js └── yarn.lock └── vue3 ├── .eslintrc.cjs ├── .gitignore ├── .prettierrc.json ├── .vscode └── extensions.json ├── README.md ├── cypress.config.ts ├── cypress ├── e2e │ ├── example.cy.ts │ └── tsconfig.json ├── fixtures │ └── example.json └── support │ ├── commands.ts │ └── e2e.ts ├── env.d.ts ├── index.html ├── package.json ├── public └── favicon.ico ├── src ├── App.vue ├── assets │ ├── base.css │ ├── logo.svg │ └── main.css ├── components │ ├── BaseCheckbox.vue │ ├── VueDdApiTest.vue │ ├── VueDdTest.vue │ ├── VueDdTest2.vue │ ├── __tests__ │ │ ├── HelloWorld.spec.ts │ │ ├── HelloWorld.vue │ │ └── WelcomeItem.vue │ └── icons │ │ ├── IconCommunity.vue │ │ ├── IconDocumentation.vue │ │ ├── IconEcosystem.vue │ │ ├── IconSupport.vue │ │ └── IconTooling.vue ├── features │ ├── setupFormComponent.js │ └── uniqueId.js ├── main.ts ├── router │ └── index.ts ├── stores │ └── counter.ts └── views │ ├── AboutView.vue │ └── HomeView.vue ├── tsconfig.app.json ├── tsconfig.config.json ├── tsconfig.json ├── tsconfig.vitest.json ├── vite.config.ts └── yarn.lock /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: [ push ] 3 | 4 | jobs: 5 | build: 6 | name: vitest 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | 11 | - name: Set Node.js 16.x 12 | uses: actions/setup-node@v3 13 | with: 14 | node-version: 16.x 15 | 16 | - name: yarn install 17 | uses: borales/actions-yarn@v4 18 | with: 19 | cmd: install # will run `yarn install` command 20 | dir: 'vue-dd' 21 | - name: vitest vue-dd 22 | uses: borales/actions-yarn@v4 23 | with: 24 | cmd: test # will run `yarn test` command 25 | dir: 'vue-dd' 26 | docs-deploy: 27 | name: deploy docs 28 | runs-on: ubuntu-latest 29 | steps: 30 | - uses: actions/checkout@v3 31 | 32 | - name: Set Node.js 16.x 33 | uses: actions/setup-node@v3 34 | with: 35 | node-version: 16.x 36 | 37 | - name: Setup git 38 | run: | 39 | git config user.name "Evgeny Kalashnikov" && git config user.email "ekalashnikov@gmail.com" 40 | - name: yarn install 41 | uses: borales/actions-yarn@v4 42 | with: 43 | cmd: install # will run `yarn install` command 44 | dir: 'docs' 45 | - name: deploy docs 46 | uses: borales/actions-yarn@v4 47 | with: 48 | cmd: deploy # will run `yarn deploy` command 49 | dir: 'docs' 50 | # docs-deploy: 51 | # name: Deploying to gh-pages 52 | # runs-on: ubuntu-latest 53 | # steps: 54 | # - name: Setup Node.js for use with actions 55 | # uses: actions/setup-node@v2 56 | # with: 57 | # version: 12.x 58 | # - name: Checkout branch 59 | # uses: actions/checkout@v2 60 | # 61 | # - name: Clean install dependencies 62 | # run: npm ci 63 | # 64 | # - name: Run deploy script 65 | # run: | 66 | # git config user.name "Evgeny Kalashnikov" && git config user.email "ekalashnikov@gmail.com" 67 | # 68 | # cmd: deploy 69 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | node_modules 4 | yarn-error.log 5 | .DS_Store 6 | /extras 7 | dist 8 | .vite -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## vue-dd — object viewer     [![npm](https://img.shields.io/npm/v/vue-dd.svg)](https://www.npmjs.com/package/vue-dd) [![build status](https://github.com/infinite-system/vue-dd/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/infinite-system/vue-dd/actions/workflows/ci.yml) 2 | 3 | **vue-dd** — pronounced *vúed* or *vue dd* — is a Vue 3 object viewer for displaying complex JavaScript objects, Vue Reactive and Ref objects, Functions, Maps, Sets, Symbols and all JavaScript Primitives in order to monitor their changes **live** with full reactivity. Inspired by the Laravels **dd()** debugging function. 4 | 5 | https://user-images.githubusercontent.com/150185/213549880-e6b645bd-11f0-461a-b1a9-29c70c52f2ad.mov 6 | 7 | https://user-images.githubusercontent.com/150185/213549905-360698e2-0c6b-4fd1-8023-803e22b68e27.mov 8 | 9 | Video example code in Vue 3 ` 5 | # Coming soon 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vitepress-project", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "dev": "vitepress dev docs", 7 | "build": "vitepress build docs", 8 | "serve": "vitepress serve docs", 9 | "deploy": "node scripts/gh-pages-deploy.js" 10 | }, 11 | "devDependencies": { 12 | "cpy-cli": "^4.2.0", 13 | "execa": "latest", 14 | "vitepress": "^1.0.0-rc.12", 15 | "vue": "3.2.44" 16 | }, 17 | "pnpm": { 18 | "peerDependencyRules": { 19 | "ignoreMissing": [ 20 | "@algolia/client-search" 21 | ] 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docs/scripts/gh-pages-deploy.js: -------------------------------------------------------------------------------- 1 | import { execa } from 'execa' 2 | // import fs from "fs" 3 | 4 | (async () => { 5 | try { 6 | var datetime = new Date(); 7 | 8 | // this will save potential changes that might get lost if you didn't commit them 9 | await execa("git", ["stash", "push", "-m", "before deploy on " + datetime]); 10 | await execa("git", ["checkout", "--orphan", "gh-pages"]); 11 | 12 | console.log("Building...") 13 | 14 | await execa("yarn", ["run", "build"]) 15 | // Understand if it's dist or build folder 16 | const folderName = "docs/.vitepress/dist" 17 | await execa("git", ["--work-tree", folderName, "add", "--all"]) 18 | await execa("git", ["--work-tree", folderName, "commit", "-m", "gh-pages"]) 19 | 20 | console.log("Pushing to gh-pages...") 21 | 22 | await execa("git", ["push", "origin", "HEAD:gh-pages", "--force"]) 23 | await execa("rm", ["-r", folderName]) 24 | await execa("git", ["fetch"]) 25 | await execa("git", ["checkout", "-f", "main"]) 26 | await execa("git", ["branch", "-D", "gh-pages"]) 27 | 28 | console.log("Successfully deployed") 29 | } catch (e) { 30 | 31 | console.log(e.message) 32 | process.exit(1) 33 | } 34 | })(); -------------------------------------------------------------------------------- /docs/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | 9 | resolve: { 10 | alias: { 11 | '@': fileURLToPath(new URL('./src', import.meta.url)) 12 | } 13 | }, 14 | server: { 15 | fs: { 16 | allow: ['..'] 17 | } 18 | }, 19 | 20 | }) 21 | -------------------------------------------------------------------------------- /vue-dd/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Evgeny Kalashnikov 2 | Copyright (c) 2017 Emanuel Buzek 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /vue-dd/README.md: -------------------------------------------------------------------------------- 1 | ## vue-dd — object viewer     [![npm](https://img.shields.io/npm/v/vue-dd.svg)](https://www.npmjs.com/package/vue-dd) [![build status](https://github.com/infinite-system/vue-dd/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/infinite-system/vue-dd/actions/workflows/ci.yml) 2 | 3 | **vue-dd** — pronounced *vúed* or *vue dd* — is a Vue 3 object viewer for displaying complex JavaScript objects, Vue Reactive and Ref objects, Functions, Maps, Sets, Symbols and all JavaScript Primitives in order to monitor their changes **live** with full reactivity. Inspired by the Laravels **dd()** debugging function. 4 | 5 | https://user-images.githubusercontent.com/150185/213549880-e6b645bd-11f0-461a-b1a9-29c70c52f2ad.mov 6 | 7 | https://user-images.githubusercontent.com/150185/213549905-360698e2-0c6b-4fd1-8023-803e22b68e27.mov 8 | 9 | Video example code in Vue 3 ` -------------------------------------------------------------------------------- /vue-dd/cypress/support/router/Home.vue: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /vue-dd/cypress/support/router/Page.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /vue-dd/cypress/support/router/routes.js: -------------------------------------------------------------------------------- 1 | import Home from './Home.vue' 2 | import Page from './Page.vue' 3 | import About from './About.vue' 4 | 5 | export const routes = [ 6 | { 7 | component: Home, 8 | name: 'home', 9 | path: '/', 10 | }, 11 | { 12 | component: Page, 13 | name: 'page', 14 | path: '/page', 15 | }, 16 | { 17 | component: About, 18 | name: 'about', 19 | path: '/about', 20 | } 21 | ]; 22 | -------------------------------------------------------------------------------- /vue-dd/demo/App.vue: -------------------------------------------------------------------------------- 1 | 105 | 121 | 122 | 123 | 130 | -------------------------------------------------------------------------------- /vue-dd/demo/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from "vue"; 2 | import { install } from "../src/index"; 3 | import App from "./App.vue"; 4 | 5 | const app = createApp(App); 6 | 7 | install(app); 8 | 9 | app.mount("#app"); 10 | -------------------------------------------------------------------------------- /vue-dd/demo/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import vue from "@vitejs/plugin-vue"; 3 | 4 | export const vueDocsPlugin = () => ({ 5 | name: "vue-docs", 6 | transform(code: any, id: any) { 7 | if (!/vue&type=docs/.test(id)) return; 8 | return `export default ''`; 9 | }, 10 | }); 11 | 12 | export default defineConfig({ 13 | root: "./", 14 | // keep the same name as your github repos 15 | mode: "production", 16 | plugins: [vue(), vueDocsPlugin()], 17 | build: { 18 | outDir: "./dist-demo", 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /vue-dd/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | MyComponent 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /vue-dd/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-dd", 3 | "version": "1.6.5", 4 | "description": "Vue.js component for displaying JavaScript objects with circular references, forked and ported to Vue 3", 5 | "exports": { 6 | ".": { 7 | "require": "./dist/index.umd.js", 8 | "import": "./dist/index.es.js", 9 | "types": "./dist/src/index.d.ts", 10 | "style": "./dist/style.css" 11 | } 12 | }, 13 | "main": "./dist/index.umd.js", 14 | "module": "./dist/index.es.js", 15 | "types": "./dist/src/index.d.ts", 16 | "style": "./dist/style.css", 17 | "scripts": { 18 | "dev": "vite dev --host", 19 | "test": "vitest", 20 | "coverage": "vitest run --coverage", 21 | "cypress": "cypress run --component", 22 | "cypress:headed": "cypress run --component --browser chrome --headed --no-exit", 23 | "build": "cpy ./README.md ../ --cwd=./ && vite build" 24 | }, 25 | "peerDependencies": { 26 | "vue": "^3.0.0" 27 | }, 28 | "devDependencies": { 29 | "@cypress/vite-dev-server": "^5.0.2", 30 | "@cypress/vue": "^5.0.3", 31 | "@vitejs/plugin-vue": "^4.0.0", 32 | "@vitest/coverage-c8": "^0.26.2", 33 | "@vue/test-utils": "^2.2.7", 34 | "cpy-cli": "^4.2.0", 35 | "cypress": "^12.3.0", 36 | "jsdom": "^21.0.0", 37 | "vite": "^4.0.4", 38 | "vite-plugin-dts": "^1.7.1", 39 | "vite-plugin-libcss": "^1.0.5", 40 | "vitest": "^0.27.1", 41 | "vue": "^3.2.45", 42 | "vue-router": "^4.1.6" 43 | }, 44 | "repository": { 45 | "type": "git", 46 | "url": "https://github.com/infinite-system/vue-dd" 47 | }, 48 | "homepage": "https://github.com/infinite-system/vue-dd", 49 | "bugs": { 50 | "url": "https://github.com/infinite-system/vue-dd/issues", 51 | "email": "ekalashnikov@gmail.com" 52 | }, 53 | "keywords": [ 54 | "Vue", 55 | "VueJs", 56 | "vue-dd", 57 | "dd", 58 | "object", 59 | "reactive", 60 | "tree", 61 | "view", 62 | "json", 63 | "viewer", 64 | "lazy", 65 | "circular", 66 | "inspector" 67 | ], 68 | "author": { 69 | "name": "Evgeny Kalashnikov", 70 | "email": "ekalashnikov@gmail.com" 71 | }, 72 | "license": "MIT" 73 | } 74 | -------------------------------------------------------------------------------- /vue-dd/src/NodePrimitive.vue: -------------------------------------------------------------------------------- 1 | 45 | 127 | -------------------------------------------------------------------------------- /vue-dd/src/VueDd.spec.js: -------------------------------------------------------------------------------- 1 | import VueDd from './VueDd.vue'; 2 | import { flushPromises } from '@vue/test-utils' 3 | 4 | import { routes } from '../cypress/support/router/routes.js' 5 | import { createMemoryHistory, createRouter, createWebHistory, useRoute } from 'vue-router' 6 | // beforeEach(() => { 7 | // cy.mount(VueDd); 8 | // }); 9 | 10 | // it('basic router', () => { 11 | // // cy.wrap(Cypress.router.push('/')) 12 | // // cy.getDataCy('home').should('not.be.visible'); 13 | // const name = 'test'; 14 | // 15 | // cy.mount(VueDd, { 16 | // props: { 17 | // modelValue: true, 18 | // name, 19 | // }, 20 | // }); 21 | // 22 | // // cy.log('test') 23 | // // cy.location('pathname').should('eq', '/'); 24 | // cy.get('div.vue-dd').should('have.text', name + ':true'); 25 | // }); 26 | 27 | it('router changed', async () => { 28 | // cy.wrap(Cypress.router.push('/')) 29 | // cy.getDataCy('home').should('not.be.visible'); 30 | const router = createRouter({ 31 | routes: routes, 32 | history: createWebHistory(), 33 | }) 34 | 35 | 36 | // Change location to `/login`, 37 | // and await on the promise with cy.wrap 38 | cy.wrap(router.push('/about')).then(() => { 39 | 40 | cy.log('currentRoute', JSON.stringify(router.currentRoute)) 41 | 42 | // Pass the already initialized router for use 43 | const name = 'test'; 44 | 45 | cy.mount(VueDd, { 46 | router, 47 | props: { 48 | modelValue: true, 49 | delimiter: '$', 50 | name, 51 | }, 52 | }); 53 | 54 | const route = useRoute() 55 | 56 | cy.log('route', JSON.stringify(route)) 57 | 58 | cy.log(JSON.stringify(window.location)) 59 | // cy.location('pathname').should('eq', '/'); 60 | cy.get('#dd_1').should('have.length', 1) 61 | cy.get('#dd_1').should('have.text', 'test:true') 62 | // cy.get('#_dd_1').contains(name); 63 | 64 | }) 65 | }); 66 | // 67 | // it('window', () => { 68 | // // cy.wrap(Cypress.router.push('/')) 69 | // // cy.location('pathname').should('eq', '/'); 70 | // // cy.getDataCy('home').should('not.be.visible'); 71 | // const name = 'test'; 72 | // 73 | // cy.mount(VueDd, { 74 | // props: { 75 | // modelValue: window, 76 | // name, 77 | // focus: 'crypto' 78 | // }, 79 | // }); 80 | // // cy.get('body').invoke('html').then((val) => console.log(JSON.stringify(val))) 81 | // console.log('yes') 82 | // cy.get(`#${CSS.escape('_dd_1.cypress')}`).should('be.visible'); 83 | // }); 84 | 85 | // 86 | // it('shows a navbar on board detail', () => { 87 | // // cy.wrap(Cypress.router.push('/board/1')); 88 | // // cy.location('pathname').should('eq', '/board/1'); 89 | // cy.getDataCy('home').should('be.visible'); 90 | // }); 91 | -------------------------------------------------------------------------------- /vue-dd/src/VueDd.vue: -------------------------------------------------------------------------------- 1 | 85 | 572 | 576 | -------------------------------------------------------------------------------- /vue-dd/src/XRay.vue: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /vue-dd/src/assets/eye-full.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-dd/src/assets/eye.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue-dd/src/assets/fonts/vue-dd-icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinite-system/vue-dd/fac5498a27bfdcc533601d1257c781deb1a6e34d/vue-dd/src/assets/fonts/vue-dd-icons.eot -------------------------------------------------------------------------------- /vue-dd/src/assets/fonts/vue-dd-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /vue-dd/src/assets/fonts/vue-dd-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinite-system/vue-dd/fac5498a27bfdcc533601d1257c781deb1a6e34d/vue-dd/src/assets/fonts/vue-dd-icons.ttf -------------------------------------------------------------------------------- /vue-dd/src/assets/fonts/vue-dd-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinite-system/vue-dd/fac5498a27bfdcc533601d1257c781deb1a6e34d/vue-dd/src/assets/fonts/vue-dd-icons.woff -------------------------------------------------------------------------------- /vue-dd/src/components/XRayCheckbox.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 48 | 112 | -------------------------------------------------------------------------------- /vue-dd/src/components/XRaySelect.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 72 | -------------------------------------------------------------------------------- /vue-dd/src/css/VueDd.code.css: -------------------------------------------------------------------------------- 1 | /* highlight.js styles */ 2 | 3 | .vue-dd .hljs { 4 | color: #abb2bf; 5 | background: #282c34; 6 | } 7 | 8 | .vue-dd .hljs-comment, .vue-dd .hljs-quote { 9 | color: #5c6370; 10 | font-style: italic; 11 | } 12 | 13 | .vue-dd .hljs-doctag, .vue-dd .hljs-formula, .vue-dd .hljs-keyword { 14 | color: #c678dd; 15 | } 16 | 17 | .vue-dd .hljs-deletion, .vue-dd .hljs-name, .vue-dd .hljs-section, .vue-dd .hljs-selector-tag, .vue-dd .hljs-subst { 18 | color: #e06c75; 19 | } 20 | 21 | .vue-dd .hljs-literal { 22 | color: #56b6c2; 23 | } 24 | 25 | .vue-dd .hljs-addition, .vue-dd .hljs-attribute, .vue-dd .hljs-meta .hljs-string, .vue-dd .hljs-regexp, .vue-dd .hljs-string { 26 | color: #98c379; 27 | } 28 | 29 | .vue-dd .hljs-attr, .vue-dd .hljs-number, .vue-dd .hljs-selector-attr, .vue-dd .hljs-selector-class, .vue-dd .hljs-selector-pseudo, .vue-dd .hljs-template-variable, .vue-dd .hljs-type, .vue-dd .hljs-variable { 30 | color: #d19a66; 31 | } 32 | 33 | .vue-dd .hljs-bullet, .vue-dd .hljs-link, .vue-dd .hljs-meta, .vue-dd .hljs-selector-id, .vue-dd .hljs-symbol, .vue-dd .hljs-title { 34 | color: #61aeee; 35 | } 36 | 37 | .vue-dd .hljs-built_in, .vue-dd .hljs-class .hljs-title, .vue-dd .hljs-title.class_ { 38 | color: #e6c07b; 39 | } 40 | 41 | .vue-dd .hljs-emphasis { 42 | font-style: italic; 43 | } 44 | 45 | .vue-dd .hljs-strong { 46 | font-weight: 700; 47 | } 48 | 49 | .vue-dd .hljs-link { 50 | text-decoration: underline; 51 | } 52 | -------------------------------------------------------------------------------- /vue-dd/src/css/VueDd.css: -------------------------------------------------------------------------------- 1 | .vue-dd { 2 | max-height: var(--vue-dd-maxHeight); 3 | max-width: var(--vue-dd-maxWidth); 4 | } 5 | 6 | 7 | .vue-dd, .vue-dd pre { 8 | font-family: var(--vue-dd-fontFamily); 9 | font-size: var(--vue-dd-fontSize); 10 | line-height: var(--vue-dd-lineHeight); 11 | } 12 | 13 | .vue-dd { 14 | position: relative; 15 | text-align: left; 16 | color: #4e5e6b; 17 | padding: 2px 5px 2px 3px; 18 | transition: 0.2s; 19 | margin-bottom: 2px; 20 | background: #f9ffff; 21 | border-radius: 3px; 22 | border: 1px solid #d2dbe8; 23 | overflow-y: auto; 24 | overflow-x: auto; 25 | scroll-behavior: smooth; 26 | /* firefox scrollbar */ 27 | scrollbar-color: rgba(0, 0, 0, 0.1) #f9ffff; 28 | scrollbar-width: thin; 29 | } 30 | 31 | .vue-dd div { 32 | /** 33 | * this is important for auto-scroll saveFocus positioning 34 | * some css frameworks set * { position: relative } and 35 | * vue 3 default main.css does as well, 36 | * position:relative on all (*) elements will break auto scroll in vue-dd 37 | * because the only relative element should be the root .vue-dd {} 38 | */ 39 | position: static !important; 40 | } 41 | 42 | .vue-dd-no-arrow { 43 | padding-left: 5px; 44 | } 45 | 46 | .vue-dd-body { 47 | transition: 0.1s; 48 | } 49 | 50 | .vue-dd-open { 51 | } 52 | 53 | .vue-dd-open.vue-dd-inline { 54 | display: block; 55 | } 56 | 57 | .vue-dd-inline:not(.vue-dd-open) { 58 | display: inline-block; 59 | margin-right: 3px; 60 | } 61 | 62 | .vue-dd.vue-dd-dark { 63 | background: #000; 64 | border: 1px solid #000; 65 | /* firefox scrollbar */ 66 | scrollbar-color: #111 #000; 67 | scrollbar-width: thin; 68 | } 69 | 70 | .vue-dd::-webkit-scrollbar { 71 | width: 4px; 72 | height: 4px; 73 | background: rgba(0, 0, 0, 0.05); 74 | } 75 | 76 | .vue-dd::-webkit-scrollbar-corner { 77 | background: rgba(0, 0, 0, 0.05); 78 | } 79 | 80 | .vue-dd::-webkit-scrollbar-thumb { 81 | border-radius: 5px; 82 | background: rgba(0, 0, 0, 0.1); 83 | } 84 | 85 | .vue-dd.vue-dd-dark::-webkit-scrollbar { 86 | background: rgba(255, 255, 255, 0.05); 87 | } 88 | 89 | .vue-dd.vue-dd-dark::-webkit-scrollbar-corner { 90 | background: rgba(255, 255, 255, 0.05); 91 | } 92 | 93 | .vue-dd.vue-dd-dark::-webkit-scrollbar-thumb { 94 | background: rgba(255, 255, 255, 0.2); 95 | } 96 | 97 | .vue-dd-box { 98 | display: block; 99 | overflow: visible; 100 | } 101 | 102 | .vue-dd-box > div { 103 | /*float: left;*/ 104 | display: block; 105 | overflow: visible; 106 | } 107 | 108 | .vue-dd-box > div > div { 109 | display: block; 110 | padding-left: var(--vue-dd-paddingLeft); 111 | } 112 | 113 | .vue-dd-box-closed, .vue-dd-box-closed div, .vue-dd-box-closed div div { 114 | display: inline-block; 115 | cursor: default; 116 | white-space: nowrap; 117 | } 118 | 119 | div.vue-dd-start { 120 | display: inline-block; 121 | } 122 | 123 | /** focus **/ 124 | 125 | @font-face { 126 | font-family: 'vue-dd-icons'; 127 | src: url('../assets/fonts/vue-dd-icons.eot?w48gck'); 128 | src: url('../assets/fonts/vue-dd-icons.eot?w48gck#iefix') format('embedded-opentype'), 129 | url('../assets/fonts/vue-dd-icons.ttf?w48gck') format('truetype'), 130 | url('../assets/fonts/vue-dd-icons.woff?w48gck') format('woff'), 131 | url('../assets/fonts/vue-dd-icons.svg?w48gck#vue-dd-icons') format('svg'); 132 | font-weight: normal; 133 | font-style: normal; 134 | font-display: block; 135 | } 136 | 137 | [class^="vue-dd-icon-"], [class*=" vue-dd-icon-"] { 138 | /* use !important to prevent issues with browser extensions that change fonts */ 139 | font-family: 'vue-dd-icons' !important; 140 | speak: never; 141 | font-style: normal; 142 | font-weight: normal; 143 | font-variant: normal; 144 | text-transform: none; 145 | font-size: 80%; 146 | line-height: 80%; 147 | 148 | /* Better Font Rendering =========== */ 149 | -webkit-font-smoothing: antialiased; 150 | -moz-osx-font-smoothing: grayscale; 151 | } 152 | 153 | .vue-dd-focus.vue-dd-icon-eye:before { 154 | content: "\e900"; 155 | } 156 | 157 | .vue-dd-focus.vue-dd-focus-selected.vue-dd-icon-eye:before { 158 | content: "\e901"; 159 | background: -webkit-linear-gradient(60deg, #00ff95, #116dea 90%); 160 | -webkit-background-clip: text; 161 | -webkit-text-fill-color: transparent; 162 | } 163 | 164 | .vue-dd-focus { 165 | color: #afafaf; 166 | margin: 0 2px 0 0; 167 | display: inline-block; 168 | font-size: 150%; 169 | vertical-align: middle; 170 | cursor: default; 171 | transition: 0.1s 172 | } 173 | 174 | .vue-dd-focus-hover { 175 | color: #555; 176 | } 177 | 178 | .vue-dd-focus-selected { 179 | color: #116dea; 180 | } 181 | 182 | /** dark focus **/ 183 | 184 | .vue-dd-dark .vue-dd-focus { 185 | color: #333; 186 | } 187 | 188 | .vue-dd-dark .vue-dd-focus-hover { 189 | color: #777; 190 | } 191 | 192 | .vue-dd-dark .vue-dd-focus-selected { 193 | color: #116dea; 194 | } 195 | 196 | span.vue-dd-expand { 197 | vertical-align: middle; 198 | background: none; 199 | border: 0; 200 | border-radius: 5px; 201 | 202 | padding: 3px 3px; 203 | font-size: 70%; 204 | line-height: 10px; 205 | cursor: default; 206 | color: grey; 207 | -webkit-user-select: none; 208 | user-select: none; 209 | letter-spacing: -0px; 210 | } 211 | 212 | span.vue-dd-expand:hover { 213 | background: rgba(0, 0, 0, 0.05); 214 | color: #21BA45; 215 | } 216 | 217 | .vue-dd-dark span.vue-dd-expand { 218 | /*background: rgba(19, 19, 19, 0.97);*/ 219 | } 220 | 221 | .vue-dd-dark span.vue-dd-expand:hover { 222 | background: rgba(255, 255, 255, 0.05); 223 | } 224 | 225 | .vue-dd-box-closed .vue-dd-expand { 226 | /*font-style: italic;*/ 227 | } 228 | /*.vue-dd-expand-more {*/ 229 | /*}*/ 230 | 231 | .vue-dd-size:has(+ .vue-dd-expand) { 232 | margin: 0; 233 | } 234 | 235 | span.vue-dd-expand:active { 236 | padding-top: 4px; 237 | padding-bottom: 2px !important; 238 | } 239 | 240 | .vue-dd-ref { 241 | -webkit-user-select: none; 242 | user-select: none; 243 | cursor: default; 244 | color: grey; 245 | font-family: Georgia, 'Courier', serif; 246 | font-size: 90%; 247 | font-style: italic; 248 | letter-spacing: -0.5px; 249 | display: inline-block; 250 | padding: 0 3px 0 0; 251 | } 252 | 253 | .vue-dd-r { 254 | -webkit-user-select: none; 255 | user-select: none; 256 | cursor: default; 257 | color: grey; 258 | font-family: Georgia, 'Courier', serif; 259 | font-size: 90%; 260 | font-style: italic; 261 | letter-spacing: -0.5px; 262 | display: inline-block; 263 | padding: 0 2px 0 0; 264 | } 265 | 266 | .vue-dd-getter { 267 | color: grey; 268 | font-style: italic; 269 | padding: 0 2px 0 0; 270 | cursor: pointer; 271 | border-radius: 3px; 272 | } 273 | 274 | .vue-dd-getter:hover { 275 | background: rgba(200,200,200,0.2) 276 | } 277 | 278 | .vue-dd-name + .vue-dd-r { 279 | padding-left: 2px; 280 | } 281 | 282 | 283 | .vue-dd-f { 284 | -webkit-user-select: none; 285 | user-select: none; 286 | cursor: default; 287 | color: grey; 288 | font-style: italic; 289 | font-family: Georgia, serif; 290 | font-size: 90%; 291 | letter-spacing: -1px; 292 | display: inline-block; 293 | padding: 0 5px 0 3px; 294 | } 295 | 296 | .vue-dd-f-inline { 297 | color: #4e5e6b; 298 | font-style: italic; 299 | } 300 | 301 | .vue-dd-f-start { 302 | display: inline; 303 | color: #55606a; 304 | } 305 | 306 | .vue-dd-dark pre.vue-dd-f-start { 307 | padding: 0; 308 | margin: 0; 309 | color: #cbeaff; 310 | } 311 | 312 | .vue-dd-dark pre.vue-dd-f-start .hljs-property { 313 | color: #6ec3ff; 314 | } 315 | 316 | .vue-dd-f-content { 317 | padding: 0; 318 | } 319 | 320 | .vue-dd-f-content pre { 321 | padding: 0; 322 | margin: 0; 323 | color: #333; 324 | } 325 | 326 | .vue-dd-dark .vue-dd-f-content pre .hljs-property { 327 | color: #6ec3ff; 328 | } 329 | 330 | .vue-dd-dark .vue-dd-f-content pre { 331 | padding: 0; 332 | margin: 0; 333 | color: #cbeaff; 334 | } 335 | 336 | span.vue-dd-arrow { 337 | border: none; 338 | display: inline-block; 339 | background: none; 340 | color: #8c9dad; 341 | cursor: default; 342 | -webkit-user-select: none; 343 | user-select: none; 344 | font-size: 80%; 345 | padding: 0 2px 0 2px; 346 | transition: 0.2s; 347 | vertical-align: middle; 348 | } 349 | 350 | span.vue-dd-arrow:hover { 351 | color: slategray; 352 | } 353 | 354 | span.vue-dd-arrow-collapsed { 355 | padding: 0 2px 0 2px; 356 | transform: rotate(-90deg); 357 | } 358 | 359 | .vue-dd-name { 360 | padding-right: 0px; 361 | cursor: default; 362 | color: #1b7ccf; 363 | } 364 | 365 | .vue-dd-dark .vue-dd-name { 366 | cursor: default; 367 | color: #09BAFF; 368 | } 369 | 370 | .vue-dd-name.vue-dd-f-name { 371 | color: #d114d1; 372 | font-weight: normal; 373 | } 374 | 375 | .vue-dd-instance { 376 | user-select: none; 377 | padding-left: 3px; 378 | font-style: italic; 379 | color: #21BA45; 380 | -webkit-user-select: none; 381 | } 382 | 383 | .vue-dd-dark .vue-dd-instance { 384 | 385 | } 386 | 387 | .vue-dd-instance + .vue-dd-size { 388 | margin-left: 2px; 389 | } 390 | 391 | .vue-dd-size { 392 | user-select: none; 393 | margin: 0 2px 0 0; 394 | padding: 3px; 395 | /*border-radius: 30px;*/ 396 | /*background: #eee;*/ 397 | color: #999; 398 | font-style: italic; 399 | font-size: 80%; 400 | line-height: 100%; 401 | } 402 | 403 | .vue-dd-dark .vue-dd-size { 404 | /*background: #131313;*/ 405 | color: #555; 406 | } 407 | 408 | .vue-dd-size-bracket { 409 | display: none; 410 | color: #4e5e6b; 411 | } 412 | 413 | .vue-dd-promise-prototype { 414 | padding-right: 5px; 415 | padding-left: 0; 416 | } 417 | 418 | .vue-dd-promise-content { 419 | -webkit-user-select: none; 420 | user-select: none; 421 | padding: 0 4px; 422 | font-style: italic; 423 | } 424 | 425 | .vue-dd-highlight { 426 | animation: vue-dd-highlight 1s; 427 | } 428 | 429 | .vue-dd-dark .vue-dd-highlight { 430 | animation: vue-dd-highlight-on-dark 1s; 431 | } 432 | 433 | @keyframes vue-dd-highlight-on-dark { 434 | from { 435 | background-color: #0f99cb; 436 | border-radius: 5px; 437 | } 438 | } 439 | 440 | @keyframes vue-dd-highlight { 441 | from { 442 | background-color: #83cb0f; 443 | border-radius: 5px; 444 | } 445 | } 446 | 447 | .vue-dd-null, .vue-dd-undefined { 448 | color: slategrey; 449 | } 450 | 451 | .vue-dd-boolean { 452 | font-weight: bold; 453 | color: green; 454 | } 455 | 456 | .vue-dd-number { 457 | color: #3863be; 458 | } 459 | 460 | .vue-dd-dark .vue-dd-number { 461 | color: #4067b2; 462 | } 463 | 464 | .vue-dd-bigint { 465 | color: #5a38be; 466 | } 467 | 468 | .vue-dd-dark .vue-dd-bigint { 469 | color: #7046e8; 470 | } 471 | 472 | .vue-dd-false { 473 | color: #f34747; 474 | } 475 | 476 | .vue-dd-dark .vue-dd-false { 477 | color: #f34747; 478 | } 479 | 480 | .vue-dd-unknown { 481 | color: #f34747; 482 | } 483 | 484 | .vue-dd-dark .vue-dd-unknown { 485 | color: #f34747; 486 | } 487 | 488 | .vue-dd-string { 489 | color: #d77702; 490 | word-break: break-word; 491 | } 492 | 493 | .vue-dd-dark .vue-dd-string { 494 | color: #ffcc00; 495 | } 496 | 497 | .vue-dd-symbol { 498 | color: #188379; 499 | } 500 | 501 | .vue-dd-dark .vue-dd-symbol { 502 | color: #00f7ff; 503 | word-break: break-word; 504 | } 505 | 506 | .vue-dd-key { 507 | color: #384e61; 508 | padding-left: 1px; 509 | padding-right: 0; 510 | font-weight: normal; 511 | } 512 | 513 | .vue-dd-dark .vue-dd-key { 514 | color: #c7e5fe; 515 | } 516 | 517 | .vue-dd-key-of-array { 518 | user-select: none; 519 | color: #ddd; 520 | } 521 | 522 | .vue-dd-dark .vue-dd-key-of-array { 523 | color: #333; 524 | } 525 | 526 | .vue-dd-colon { 527 | color: #555; 528 | } 529 | 530 | .vue-dd-dark .vue-dd-colon { 531 | color: #ccc; 532 | } 533 | 534 | .vue-dd-key-of-array .vue-dd-colon { 535 | user-select: none; 536 | color: #ccc; 537 | } 538 | 539 | .vue-dd-dark .vue-dd-key-of-array .vue-dd-colon { 540 | color: #333; 541 | } 542 | 543 | .vue-dd-box > div > div > div > span > .vue-dd-key { 544 | /*you can set extra padding for primitive keys here*/ 545 | /*padding-left: 0px;*/ 546 | } 547 | 548 | .vue-dd-forget { 549 | margin-left: 10px; 550 | cursor: pointer; 551 | font-size: 80%; 552 | margin-right: 10px; 553 | background: rgba(0, 0, 0, 0.1); 554 | border: 1px solid rgba(0, 0, 0, 0.1); 555 | padding: 2px 5px; 556 | border-radius: 10px; 557 | transition: 0.2; 558 | opacity: 0.8; 559 | } 560 | 561 | .vue-dd-forget:hover { 562 | opacity: 1; 563 | } 564 | 565 | .vue-dd-dark .vue-dd-forget { 566 | background: rgba(255, 255, 255, 0.1); 567 | border: 1px solid rgba(255, 255, 255, 0.1); 568 | } 569 | 570 | .vue-dd .vue-dd-forget-q-ask { 571 | border: 0; 572 | background: none; 573 | padding: 2px 0; 574 | cursor: default; 575 | } 576 | 577 | .vue-dd .vue-dd-forget-yes { 578 | margin-left: 0; 579 | } 580 | 581 | .vue-dd .vue-dd-forget-no { 582 | margin-left: 0; 583 | background: none; 584 | } 585 | 586 | .vue-dd-forget-cleared { 587 | font-size: 80%; 588 | margin-right: 10px; 589 | padding: 2px 5px; 590 | } 591 | 592 | .vue-dd-comma { 593 | color: #999; 594 | padding-right: 1px; 595 | } 596 | 597 | .vue-dd-dark .vue-dd-comma { 598 | color: #333; 599 | } 600 | 601 | .vue-dd-colon + .vue-dd-obj-char { 602 | padding: 0 2px; 603 | } 604 | 605 | .vue-dd-obj-char { 606 | color: #7490ab; 607 | padding: 0 0px; 608 | } 609 | 610 | .vue-dd-dark .vue-dd-obj-char { 611 | color: #555; 612 | } 613 | 614 | .vue-dd-name + .vue-dd-obj-char { 615 | padding-left: 2px; 616 | } 617 | 618 | .vue-dd-arr-char { 619 | color: #7490ab; 620 | padding: 0 1px; 621 | } 622 | 623 | .vue-dd-dark .vue-dd-arr-char { 624 | color: #555; 625 | } 626 | 627 | 628 | .vue-dd-obj-char-start { 629 | padding: 0 1px; 630 | } 631 | -------------------------------------------------------------------------------- /vue-dd/src/features/setupFormComponent.js: -------------------------------------------------------------------------------- 1 | export default function setupFormComponent (props, { emit }) { 2 | const updateValue = (event) => { 3 | let val = event.target.value 4 | 5 | if (event.target.type === 'select-one') val = JSON.parse(event.target.value) 6 | if (event.target.type === 'checkbox') val = event.target.checked 7 | if (event.target.type === 'radio') val = props.value 8 | 9 | emit('update:modelValue', val) 10 | } 11 | 12 | return { updateValue } 13 | } 14 | -------------------------------------------------------------------------------- /vue-dd/src/features/uniqueId.js: -------------------------------------------------------------------------------- 1 | let UUID = 1 2 | export default function uniqueId () { 3 | UUID++ 4 | return UUID 5 | } 6 | -------------------------------------------------------------------------------- /vue-dd/src/helpers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a hash code from a string 3 | * @param {String} str The string to hash. 4 | * @return {Number} A 32bit integer 5 | * @see http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/ 6 | */ 7 | export function hashCode (str) { 8 | let hash = 0; 9 | for (let i = 0, len = str.length; i < len; i++) { 10 | let chr = str.charCodeAt(i); 11 | hash = (hash << 5) - hash + chr; 12 | hash |= 0; // Convert to 32bit integer 13 | } 14 | return hash; 15 | } 16 | 17 | export function isObject (item) { 18 | return (item && typeof item === 'object' && !Array.isArray(item)); 19 | } 20 | 21 | export function isPromise (p) { 22 | return p !== null && 23 | typeof p === 'object' && 24 | typeof p.then === 'function' && 25 | typeof p.catch === 'function'; 26 | } 27 | 28 | export function makeId (id, name, window) { 29 | if (id !== '') { 30 | return id 31 | } else { 32 | // auto-generate id 33 | const locationHash = getLocationHash(window) 34 | return `${name}_${locationHash}` 35 | } 36 | } 37 | 38 | function getLocationHash (window) { 39 | 40 | // determine router type without importing vue-router package 41 | // by analyzing the urls 42 | // hash router will have a forward slash after the # sign #/about 43 | const isHashRouter = window.location.hash 44 | && typeof window.location.hash[1] !== 'undefined' 45 | && window.location.hash[1] === '/' 46 | 47 | let smartLocation = '' 48 | if (isHashRouter) { 49 | // use full route path 50 | smartLocation = window.location.href.toString() 51 | } else { 52 | // if hash is not a location hash 53 | const url = new URL(window.location.href) 54 | url.hash = "" // strip away hash 55 | smartLocation = url.toString() 56 | } 57 | 58 | return hashCode(smartLocation).toString(16).replace('-', '_') 59 | } 60 | 61 | export function onFrame(callback, timeout = 0) { 62 | setTimeout(() => { 63 | window.requestAnimationFrame(() => window.requestAnimationFrame(callback)) 64 | }, timeout) 65 | } 66 | -------------------------------------------------------------------------------- /vue-dd/src/highlight.js/core.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Highlight.js v11.7.0 (git: 82688fad18) 3 | (c) 2006-2022 undefined and other contributors 4 | License: BSD-3-Clause 5 | */ 6 | var e={exports:{}};function t(e){ 7 | return e instanceof Map?e.clear=e.delete=e.set=()=>{ 8 | throw Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=()=>{ 9 | throw Error("set is read-only") 10 | }),Object.freeze(e),Object.getOwnPropertyNames(e).forEach((n=>{var i=e[n] 11 | ;"object"!=typeof i||Object.isFrozen(i)||t(i)})),e} 12 | e.exports=t,e.exports.default=t;class n{constructor(e){ 13 | void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} 14 | ignoreMatch(){this.isMatchIgnored=!0}}function i(e){ 15 | return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") 16 | }function r(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] 17 | ;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n} 18 | const s=e=>!!e.scope||e.sublanguage&&e.language;class o{constructor(e,t){ 19 | this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ 20 | this.buffer+=i(e)}openNode(e){if(!s(e))return;let t="" 21 | ;t=e.sublanguage?"language-"+e.language:((e,{prefix:t})=>{if(e.includes(".")){ 22 | const n=e.split(".") 23 | ;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ") 24 | }return`${t}${e}`})(e.scope,{prefix:this.classPrefix}),this.span(t)} 25 | closeNode(e){s(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ 26 | this.buffer+=``}}const a=(e={})=>{const t={children:[]} 27 | ;return Object.assign(t,e),t};class c{constructor(){ 28 | this.rootNode=a(),this.stack=[this.rootNode]}get top(){ 29 | return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ 30 | this.top.children.push(e)}openNode(e){const t=a({scope:e}) 31 | ;this.add(t),this.stack.push(t)}closeNode(){ 32 | if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ 33 | for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} 34 | walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ 35 | return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), 36 | t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ 37 | "string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ 38 | c._collapse(e)})))}}class l extends c{constructor(e){super(),this.options=e} 39 | addKeyword(e,t){""!==e&&(this.openNode(t),this.addText(e),this.closeNode())} 40 | addText(e){""!==e&&this.add(e)}addSublanguage(e,t){const n=e.root 41 | ;n.sublanguage=!0,n.language=t,this.add(n)}toHTML(){ 42 | return new o(this,this.options).value()}finalize(){return!0}}function g(e){ 43 | return e?"string"==typeof e?e:e.source:null}function d(e){return p("(?=",e,")")} 44 | function u(e){return p("(?:",e,")*")}function h(e){return p("(?:",e,")?")} 45 | function p(...e){return e.map((e=>g(e))).join("")}function f(...e){const t=(e=>{ 46 | const t=e[e.length-1] 47 | ;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{} 48 | })(e);return"("+(t.capture?"":"?:")+e.map((e=>g(e))).join("|")+")"} 49 | function b(e){return RegExp(e.toString()+"|").exec("").length-1} 50 | const m=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ 51 | ;function E(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n 52 | ;let i=g(e),r="";for(;i.length>0;){const e=m.exec(i);if(!e){r+=i;break} 53 | r+=i.substring(0,e.index), 54 | i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?r+="\\"+(Number(e[1])+t):(r+=e[0], 55 | "("===e[0]&&n++)}return r})).map((e=>`(${e})`)).join(t)} 56 | const x="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",w={ 57 | begin:"\\\\[\\s\\S]",relevance:0},y={scope:"string",begin:"'",end:"'", 58 | illegal:"\\n",contains:[w]},_={scope:"string",begin:'"',end:'"',illegal:"\\n", 59 | contains:[w]},O=(e,t,n={})=>{const i=r({scope:"comment",begin:e,end:t, 60 | contains:[]},n);i.contains.push({scope:"doctag", 61 | begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", 62 | end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) 63 | ;const s=f("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/) 64 | ;return i.contains.push({begin:p(/[ ]+/,"(",s,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),i 65 | },v=O("//","$"),N=O("/\\*","\\*/"),k=O("#","$");var M=Object.freeze({ 66 | __proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:"[a-zA-Z]\\w*", 67 | UNDERSCORE_IDENT_RE:"[a-zA-Z_]\\w*",NUMBER_RE:"\\b\\d+(\\.\\d+)?",C_NUMBER_RE:x, 68 | BINARY_NUMBER_RE:"\\b(0b[01]+)", 69 | RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", 70 | SHEBANG:(e={})=>{const t=/^#![ ]*\// 71 | ;return e.binary&&(e.begin=p(t,/.*\b/,e.binary,/\b.*/)),r({scope:"meta",begin:t, 72 | end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)}, 73 | BACKSLASH_ESCAPE:w,APOS_STRING_MODE:y,QUOTE_STRING_MODE:_,PHRASAL_WORDS_MODE:{ 74 | begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ 75 | },COMMENT:O,C_LINE_COMMENT_MODE:v,C_BLOCK_COMMENT_MODE:N,HASH_COMMENT_MODE:k, 76 | NUMBER_MODE:{scope:"number",begin:"\\b\\d+(\\.\\d+)?",relevance:0}, 77 | C_NUMBER_MODE:{scope:"number",begin:x,relevance:0},BINARY_NUMBER_MODE:{ 78 | scope:"number",begin:"\\b(0b[01]+)",relevance:0},REGEXP_MODE:{ 79 | begin:/(?=\/[^/\n]*\/)/,contains:[{scope:"regexp",begin:/\//,end:/\/[gimuy]*/, 80 | illegal:/\n/,contains:[w,{begin:/\[/,end:/\]/,relevance:0,contains:[w]}]}]}, 81 | TITLE_MODE:{scope:"title",begin:"[a-zA-Z]\\w*",relevance:0}, 82 | UNDERSCORE_TITLE_MODE:{scope:"title",begin:"[a-zA-Z_]\\w*",relevance:0}, 83 | METHOD_GUARD:{begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0}, 84 | END_SAME_AS_BEGIN:e=>Object.assign(e,{"on:begin":(e,t)=>{t.data._beginMatch=e[1] 85 | },"on:end":(e,t)=>{t.data._beginMatch!==e[1]&&t.ignoreMatch()}})}) 86 | ;function S(e,t){"."===e.input[e.index-1]&&t.ignoreMatch()}function R(e,t){ 87 | void 0!==e.className&&(e.scope=e.className,delete e.className)}function A(e,t){ 88 | t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", 89 | e.__beforeBegin=S,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, 90 | void 0===e.relevance&&(e.relevance=0))}function j(e,t){ 91 | Array.isArray(e.illegal)&&(e.illegal=f(...e.illegal))}function I(e,t){ 92 | if(e.match){ 93 | if(e.begin||e.end)throw Error("begin & end are not supported with match") 94 | ;e.begin=e.match,delete e.match}}function T(e,t){ 95 | void 0===e.relevance&&(e.relevance=1)}const L=(e,t)=>{if(!e.beforeMatch)return 96 | ;if(e.starts)throw Error("beforeMatch cannot be used with starts") 97 | ;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t] 98 | })),e.keywords=n.keywords,e.begin=p(n.beforeMatch,d(n.begin)),e.starts={ 99 | relevance:0,contains:[Object.assign(n,{endsParent:!0})] 100 | },e.relevance=0,delete n.beforeMatch 101 | },B=["of","and","for","in","not","or","if","then","parent","list","value"] 102 | ;function D(e,t,n="keyword"){const i=Object.create(null) 103 | ;return"string"==typeof e?r(n,e.split(" ")):Array.isArray(e)?r(n,e):Object.keys(e).forEach((n=>{ 104 | Object.assign(i,D(e[n],t,n))})),i;function r(e,n){ 105 | t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|") 106 | ;i[n[0]]=[e,H(n[0],n[1])]}))}}function H(e,t){ 107 | return t?Number(t):(e=>B.includes(e.toLowerCase()))(e)?0:1}const P={},C=e=>{ 108 | console.error(e)},$=(e,...t)=>{console.log("WARN: "+e,...t)},U=(e,t)=>{ 109 | P[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),P[`${e}/${t}`]=!0) 110 | },z=Error();function K(e,t,{key:n}){let i=0;const r=e[n],s={},o={} 111 | ;for(let e=1;e<=t.length;e++)o[e+i]=r[e],s[e+i]=!0,i+=b(t[e-1]) 112 | ;e[n]=o,e[n]._emit=s,e[n]._multi=!0}function W(e){(e=>{ 113 | e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, 114 | delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ 115 | _wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope 116 | }),(e=>{if(Array.isArray(e.begin)){ 117 | if(e.skip||e.excludeBegin||e.returnBegin)throw C("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), 118 | z 119 | ;if("object"!=typeof e.beginScope||null===e.beginScope)throw C("beginScope must be object"), 120 | z;K(e,e.begin,{key:"beginScope"}),e.begin=E(e.begin,{joinWith:""})}})(e),(e=>{ 121 | if(Array.isArray(e.end)){ 122 | if(e.skip||e.excludeEnd||e.returnEnd)throw C("skip, excludeEnd, returnEnd not compatible with endScope: {}"), 123 | z 124 | ;if("object"!=typeof e.endScope||null===e.endScope)throw C("endScope must be object"), 125 | z;K(e,e.end,{key:"endScope"}),e.end=E(e.end,{joinWith:""})}})(e)}function X(e){ 126 | function t(t,n){ 127 | return RegExp(g(t),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(n?"g":"")) 128 | }class n{constructor(){ 129 | this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} 130 | addRule(e,t){ 131 | t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), 132 | this.matchAt+=b(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) 133 | ;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(E(e,{joinWith:"|" 134 | }),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex 135 | ;const t=this.matcherRe.exec(e);if(!t)return null 136 | ;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n] 137 | ;return t.splice(0,n),Object.assign(t,i)}}class i{constructor(){ 138 | this.rules=[],this.multiRegexes=[], 139 | this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ 140 | if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n 141 | ;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), 142 | t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ 143 | return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ 144 | this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ 145 | const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex 146 | ;let n=t.exec(e) 147 | ;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ 148 | const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} 149 | return n&&(this.regexIndex+=n.position+1, 150 | this.regexIndex===this.count&&this.considerAll()),n}} 151 | if(e.compilerExtensions||(e.compilerExtensions=[]), 152 | e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") 153 | ;return e.classNameAliases=r(e.classNameAliases||{}),function n(s,o){const a=s 154 | ;if(s.isCompiled)return a 155 | ;[R,I,W,L].forEach((e=>e(s,o))),e.compilerExtensions.forEach((e=>e(s,o))), 156 | s.__beforeBegin=null,[A,j,T].forEach((e=>e(s,o))),s.isCompiled=!0;let c=null 157 | ;return"object"==typeof s.keywords&&s.keywords.$pattern&&(s.keywords=Object.assign({},s.keywords), 158 | c=s.keywords.$pattern, 159 | delete s.keywords.$pattern),c=c||/\w+/,s.keywords&&(s.keywords=D(s.keywords,e.case_insensitive)), 160 | a.keywordPatternRe=t(c,!0), 161 | o&&(s.begin||(s.begin=/\B|\b/),a.beginRe=t(a.begin),s.end||s.endsWithParent||(s.end=/\B|\b/), 162 | s.end&&(a.endRe=t(a.end)), 163 | a.terminatorEnd=g(a.end)||"",s.endsWithParent&&o.terminatorEnd&&(a.terminatorEnd+=(s.end?"|":"")+o.terminatorEnd)), 164 | s.illegal&&(a.illegalRe=t(s.illegal)), 165 | s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>r(e,{ 166 | variants:null},t)))),e.cachedVariants?e.cachedVariants:Z(e)?r(e,{ 167 | starts:e.starts?r(e.starts):null 168 | }):Object.isFrozen(e)?r(e):e))("self"===e?s:e)))),s.contains.forEach((e=>{n(e,a) 169 | })),s.starts&&n(s.starts,o),a.matcher=(e=>{const t=new i 170 | ;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" 171 | }))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" 172 | }),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function Z(e){ 173 | return!!e&&(e.endsWithParent||Z(e.starts))}class G extends Error{ 174 | constructor(e,t){super(e),this.name="HTMLInjectionError",this.html=t}} 175 | const F=i,V=r,q=Symbol("nomatch");var J=(t=>{ 176 | const i=Object.create(null),r=Object.create(null),s=[];let o=!0 177 | ;const a="Could not find the language '{}', did you forget to load/include a language module?",c={ 178 | disableAutodetect:!0,name:"Plain text",contains:[]};let g={ 179 | ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, 180 | languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", 181 | cssSelector:"pre code",languages:null,__emitter:l};function b(e){ 182 | return g.noHighlightRe.test(e)}function m(e,t,n){let i="",r="" 183 | ;"object"==typeof t?(i=e, 184 | n=t.ignoreIllegals,r=t.language):(U("10.7.0","highlight(lang, code, ...args) has been deprecated."), 185 | U("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), 186 | r=e,i=t),void 0===n&&(n=!0);const s={code:i,language:r};k("before:highlight",s) 187 | ;const o=s.result?s.result:E(s.language,s.code,n) 188 | ;return o.code=s.code,k("after:highlight",o),o}function E(e,t,r,s){ 189 | const c=Object.create(null);function l(){if(!N.keywords)return void M.addText(S) 190 | ;let e=0;N.keywordPatternRe.lastIndex=0;let t=N.keywordPatternRe.exec(S),n="" 191 | ;for(;t;){n+=S.substring(e,t.index) 192 | ;const r=y.case_insensitive?t[0].toLowerCase():t[0],s=(i=r,N.keywords[i]);if(s){ 193 | const[e,i]=s 194 | ;if(M.addText(n),n="",c[r]=(c[r]||0)+1,c[r]<=7&&(R+=i),e.startsWith("_"))n+=t[0];else{ 195 | const n=y.classNameAliases[e]||e;M.addKeyword(t[0],n)}}else n+=t[0] 196 | ;e=N.keywordPatternRe.lastIndex,t=N.keywordPatternRe.exec(S)}var i 197 | ;n+=S.substring(e),M.addText(n)}function d(){null!=N.subLanguage?(()=>{ 198 | if(""===S)return;let e=null;if("string"==typeof N.subLanguage){ 199 | if(!i[N.subLanguage])return void M.addText(S) 200 | ;e=E(N.subLanguage,S,!0,k[N.subLanguage]),k[N.subLanguage]=e._top 201 | }else e=x(S,N.subLanguage.length?N.subLanguage:null) 202 | ;N.relevance>0&&(R+=e.relevance),M.addSublanguage(e._emitter,e.language) 203 | })():l(),S=""}function u(e,t){let n=1;const i=t.length-1;for(;n<=i;){ 204 | if(!e._emit[n]){n++;continue}const i=y.classNameAliases[e[n]]||e[n],r=t[n] 205 | ;i?M.addKeyword(r,i):(S=r,l(),S=""),n++}}function h(e,t){ 206 | return e.scope&&"string"==typeof e.scope&&M.openNode(y.classNameAliases[e.scope]||e.scope), 207 | e.beginScope&&(e.beginScope._wrap?(M.addKeyword(S,y.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), 208 | S=""):e.beginScope._multi&&(u(e.beginScope,t),S="")),N=Object.create(e,{parent:{ 209 | value:N}}),N}function p(e,t,i){let r=((e,t)=>{const n=e&&e.exec(t) 210 | ;return n&&0===n.index})(e.endRe,i);if(r){if(e["on:end"]){const i=new n(e) 211 | ;e["on:end"](t,i),i.isMatchIgnored&&(r=!1)}if(r){ 212 | for(;e.endsParent&&e.parent;)e=e.parent;return e}} 213 | if(e.endsWithParent)return p(e.parent,t,i)}function f(e){ 214 | return 0===N.matcher.regexIndex?(S+=e[0],1):(I=!0,0)}function b(e){ 215 | const n=e[0],i=t.substring(e.index),r=p(N,e,i);if(!r)return q;const s=N 216 | ;N.endScope&&N.endScope._wrap?(d(), 217 | M.addKeyword(n,N.endScope._wrap)):N.endScope&&N.endScope._multi?(d(), 218 | u(N.endScope,e)):s.skip?S+=n:(s.returnEnd||s.excludeEnd||(S+=n), 219 | d(),s.excludeEnd&&(S=n));do{ 220 | N.scope&&M.closeNode(),N.skip||N.subLanguage||(R+=N.relevance),N=N.parent 221 | }while(N!==r.parent);return r.starts&&h(r.starts,e),s.returnEnd?0:n.length} 222 | let m={};function w(i,s){const a=s&&s[0];if(S+=i,null==a)return d(),0 223 | ;if("begin"===m.type&&"end"===s.type&&m.index===s.index&&""===a){ 224 | if(S+=t.slice(s.index,s.index+1),!o){const t=Error(`0 width match regex (${e})`) 225 | ;throw t.languageName=e,t.badRule=m.rule,t}return 1} 226 | if(m=s,"begin"===s.type)return(e=>{ 227 | const t=e[0],i=e.rule,r=new n(i),s=[i.__beforeBegin,i["on:begin"]] 228 | ;for(const n of s)if(n&&(n(e,r),r.isMatchIgnored))return f(t) 229 | ;return i.skip?S+=t:(i.excludeBegin&&(S+=t), 230 | d(),i.returnBegin||i.excludeBegin||(S=t)),h(i,e),i.returnBegin?0:t.length})(s) 231 | ;if("illegal"===s.type&&!r){ 232 | const e=Error('Illegal lexeme "'+a+'" for mode "'+(N.scope||"")+'"') 233 | ;throw e.mode=N,e}if("end"===s.type){const e=b(s);if(e!==q)return e} 234 | if("illegal"===s.type&&""===a)return 1 235 | ;if(j>1e5&&j>3*s.index)throw Error("potential infinite loop, way more iterations than matches") 236 | ;return S+=a,a.length}const y=O(e) 237 | ;if(!y)throw C(a.replace("{}",e)),Error('Unknown language: "'+e+'"') 238 | ;const _=X(y);let v="",N=s||_;const k={},M=new g.__emitter(g);(()=>{const e=[] 239 | ;for(let t=N;t!==y;t=t.parent)t.scope&&e.unshift(t.scope) 240 | ;e.forEach((e=>M.openNode(e)))})();let S="",R=0,A=0,j=0,I=!1;try{ 241 | for(N.matcher.considerAll();;){ 242 | j++,I?I=!1:N.matcher.considerAll(),N.matcher.lastIndex=A 243 | ;const e=N.matcher.exec(t);if(!e)break;const n=w(t.substring(A,e.index),e) 244 | ;A=e.index+n} 245 | return w(t.substring(A)),M.closeAllNodes(),M.finalize(),v=M.toHTML(),{ 246 | language:e,value:v,relevance:R,illegal:!1,_emitter:M,_top:N}}catch(n){ 247 | if(n.message&&n.message.includes("Illegal"))return{language:e,value:F(t), 248 | illegal:!0,relevance:0,_illegalBy:{message:n.message,index:A, 249 | context:t.slice(A-100,A+100),mode:n.mode,resultSoFar:v},_emitter:M};if(o)return{ 250 | language:e,value:F(t),illegal:!1,relevance:0,errorRaised:n,_emitter:M,_top:N} 251 | ;throw n}}function x(e,t){t=t||g.languages||Object.keys(i);const n=(e=>{ 252 | const t={value:F(e),illegal:!1,relevance:0,_top:c,_emitter:new g.__emitter(g)} 253 | ;return t._emitter.addText(e),t})(e),r=t.filter(O).filter(N).map((t=>E(t,e,!1))) 254 | ;r.unshift(n);const s=r.sort(((e,t)=>{ 255 | if(e.relevance!==t.relevance)return t.relevance-e.relevance 256 | ;if(e.language&&t.language){if(O(e.language).supersetOf===t.language)return 1 257 | ;if(O(t.language).supersetOf===e.language)return-1}return 0})),[o,a]=s,l=o 258 | ;return l.secondBest=a,l}function w(e){let t=null;const n=(e=>{ 259 | let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"" 260 | ;const n=g.languageDetectRe.exec(t);if(n){const t=O(n[1]) 261 | ;return t||($(a.replace("{}",n[1])), 262 | $("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"} 263 | return t.split(/\s+/).find((e=>b(e)||O(e)))})(e);if(b(n))return 264 | ;if(k("before:highlightElement",{el:e,language:n 265 | }),e.children.length>0&&(g.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), 266 | console.warn("https://github.com/highlightjs/highlight.js/wiki/security"), 267 | console.warn("The element with unescaped HTML:"), 268 | console.warn(e)),g.throwUnescapedHTML))throw new G("One of your code blocks includes unescaped HTML.",e.innerHTML) 269 | ;t=e;const i=t.textContent,s=n?m(i,{language:n,ignoreIllegals:!0}):x(i) 270 | ;e.innerHTML=s.value,((e,t,n)=>{const i=t&&r[t]||n 271 | ;e.classList.add("hljs"),e.classList.add("language-"+i) 272 | })(e,n,s.language),e.result={language:s.language,re:s.relevance, 273 | relevance:s.relevance},s.secondBest&&(e.secondBest={ 274 | language:s.secondBest.language,relevance:s.secondBest.relevance 275 | }),k("after:highlightElement",{el:e,result:s,text:i})}let y=!1;function _(){ 276 | "loading"!==document.readyState?document.querySelectorAll(g.cssSelector).forEach(w):y=!0 277 | }function O(e){return e=(e||"").toLowerCase(),i[e]||i[r[e]]} 278 | function v(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ 279 | r[e.toLowerCase()]=t}))}function N(e){const t=O(e) 280 | ;return t&&!t.disableAutodetect}function k(e,t){const n=e;s.forEach((e=>{ 281 | e[n]&&e[n](t)}))} 282 | "undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{ 283 | y&&_()}),!1),Object.assign(t,{highlight:m,highlightAuto:x,highlightAll:_, 284 | highlightElement:w, 285 | highlightBlock:e=>(U("10.7.0","highlightBlock will be removed entirely in v12.0"), 286 | U("10.7.0","Please use highlightElement now."),w(e)),configure:e=>{g=V(g,e)}, 287 | initHighlighting:()=>{ 288 | _(),U("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, 289 | initHighlightingOnLoad:()=>{ 290 | _(),U("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") 291 | },registerLanguage:(e,n)=>{let r=null;try{r=n(t)}catch(t){ 292 | if(C("Language definition for '{}' could not be registered.".replace("{}",e)), 293 | !o)throw t;C(t),r=c} 294 | r.name||(r.name=e),i[e]=r,r.rawDefinition=n.bind(null,t),r.aliases&&v(r.aliases,{ 295 | languageName:e})},unregisterLanguage:e=>{delete i[e] 296 | ;for(const t of Object.keys(r))r[t]===e&&delete r[t]}, 297 | listLanguages:()=>Object.keys(i),getLanguage:O,registerAliases:v, 298 | autoDetection:N,inherit:V,addPlugin:e=>{(e=>{ 299 | e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{ 300 | e["before:highlightBlock"](Object.assign({block:t.el},t)) 301 | }),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{ 302 | e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),s.push(e)} 303 | }),t.debugMode=()=>{o=!1},t.safeMode=()=>{o=!0 304 | },t.versionString="11.7.0",t.regex={concat:p,lookahead:d,either:f,optional:h, 305 | anyNumberOfTimes:u};for(const t in M)"object"==typeof M[t]&&e.exports(M[t]) 306 | ;return Object.assign(t,M),t})({});export{J as default}; 307 | -------------------------------------------------------------------------------- /vue-dd/src/highlight.js/javascript.min.js: -------------------------------------------------------------------------------- 1 | /*! `javascript` grammar compiled for Highlight.js 11.7.0 */ 2 | var hljsGrammar=(()=>{"use strict" 3 | ;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","module","global"],i=[].concat(r,t,s) 4 | ;return o=>{const l=o.regex,b=e,d={begin:/<[A-Za-z0-9\\._:-]+/, 5 | end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ 6 | const a=e[0].length+e.index,t=e.input[a] 7 | ;if("<"===t||","===t)return void n.ignoreMatch();let s 8 | ;">"===t&&(((e,{after:n})=>{const a="",M={ 52 | match:[/const|var|let/,/\s+/,b,/\s*/,/=\s*/,/(async\s*)?/,l.lookahead(C)], 53 | keywords:"async",className:{1:"keyword",3:"title.function"},contains:[S]} 54 | ;return{name:"Javascript",aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{ 55 | PARAMS_CONTAINS:p,CLASS_REFERENCE:R},illegal:/#(?![$_A-z])/, 56 | contains:[o.SHEBANG({label:"shebang",binary:"node",relevance:5}),{ 57 | label:"use_strict",className:"meta",relevance:10, 58 | begin:/^\s*['"]use (strict|asm)['"]/ 59 | },o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,y,h,N,_,{match:/\$\d+/},E,R,{ 60 | className:"attr",begin:b+l.lookahead(":"),relevance:0},M,{ 61 | begin:"("+o.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*", 62 | keywords:"return throw case",relevance:0,contains:[_,o.REGEXP_MODE,{ 63 | className:"function",begin:C,returnBegin:!0,end:"\\s*=>",contains:[{ 64 | className:"params",variants:[{begin:o.UNDERSCORE_IDENT_RE,relevance:0},{ 65 | className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0, 66 | excludeEnd:!0,keywords:g,contains:p}]}]},{begin:/,/,relevance:0},{match:/\s+/, 67 | relevance:0},{variants:[{begin:"<>",end:""},{ 68 | match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:d.begin, 69 | "on:begin":d.isTrulyOpeningTag,end:d.end}],subLanguage:"xml",contains:[{ 70 | begin:d.begin,end:d.end,skip:!0,contains:["self"]}]}]},O,{ 71 | beginKeywords:"while if switch catch for"},{ 72 | begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", 73 | returnBegin:!0,label:"func.def",contains:[S,o.inherit(o.TITLE_MODE,{begin:b, 74 | className:"title.function"})]},{match:/\.\.\./,relevance:0},x,{match:"\\$"+b, 75 | relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"}, 76 | contains:[S]},k,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/, 77 | className:"variable.constant"},w,T,{match:/\$[(.]/}]}}})() 78 | ;export default hljsGrammar; 79 | -------------------------------------------------------------------------------- /vue-dd/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { App } from "vue"; 2 | 3 | import VueDd from "./VueDd.vue"; 4 | import XRay from "./XRay.vue"; 5 | 6 | function install(app: App) { 7 | // Base entities 8 | app.component("VueDd", VueDd); 9 | app.component("XRay", XRay); 10 | } 11 | 12 | export { 13 | install, 14 | // Base entities 15 | VueDd, 16 | XRay 17 | }; 18 | -------------------------------------------------------------------------------- /vue-dd/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.vue" { 2 | import type { DefineComponent } from "vue"; 3 | const component: DefineComponent< 4 | Record, 5 | Record, 6 | unknown 7 | >; 8 | export default component; 9 | } 10 | -------------------------------------------------------------------------------- /vue-dd/src/types.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinite-system/vue-dd/fac5498a27bfdcc533601d1257c781deb1a6e34d/vue-dd/src/types.ts -------------------------------------------------------------------------------- /vue-dd/test/__snapshots__/basic.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1 2 | 3 | exports[`mount component 1`] = ` 4 | "
4 x 2 = 8
5 | " 6 | `; 7 | -------------------------------------------------------------------------------- /vue-dd/test/as-async.test.ts: -------------------------------------------------------------------------------- 1 | import { flushPromises, mount } from '@vue/test-utils' 2 | import AsAsync from './components/AsAsync.vue' 3 | 4 | test('mount component', async () => { 5 | expect(AsAsync).toBeTruthy() 6 | 7 | const wrapper = mount(AsAsync) 8 | 9 | await wrapper.find('button').trigger('click') 10 | 11 | await flushPromises() // start loading, so vitest started loading 12 | await vi.dynamicImportSettled() 13 | 14 | expect(wrapper.html()).toContain('1 x 2 = 2') 15 | }) 16 | -------------------------------------------------------------------------------- /vue-dd/test/async.test.ts: -------------------------------------------------------------------------------- 1 | import { nextTick } from 'vue' 2 | import { flushPromises, mount } from '@vue/test-utils' 3 | import AsyncWrapper from './components/AsyncWrapper.vue' 4 | 5 | test('async component with suspense', async () => { 6 | expect(AsyncWrapper).toBeTruthy() 7 | 8 | let resolve: Function 9 | 10 | const promise = new Promise(_resolve => resolve = _resolve) 11 | const wrapper = mount(AsyncWrapper, { 12 | props: { 13 | promise, 14 | }, 15 | }) 16 | 17 | await nextTick() 18 | 19 | expect(wrapper.text()).toContain('fallback') 20 | 21 | resolve() 22 | 23 | await flushPromises() 24 | await nextTick() 25 | await nextTick() 26 | 27 | const text = wrapper.text() 28 | expect(text).toContain('resolved') 29 | }) 30 | -------------------------------------------------------------------------------- /vue-dd/test/basic.test.ts: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils' 2 | import Hello from './components/Hello.vue' 3 | 4 | test('mount component', async () => { 5 | expect(Hello).toBeTruthy() 6 | 7 | const wrapper = mount(Hello, { 8 | props: { 9 | count: 4, 10 | }, 11 | }) 12 | 13 | expect(wrapper.text()).toContain('4 x 2 = 8') 14 | expect(wrapper.html()).toMatchSnapshot() 15 | 16 | await wrapper.get('button').trigger('click') 17 | 18 | expect(wrapper.text()).toContain('4 x 3 = 12') 19 | 20 | await wrapper.get('button').trigger('click') 21 | 22 | expect(wrapper.text()).toContain('4 x 4 = 16') 23 | }) 24 | -------------------------------------------------------------------------------- /vue-dd/test/components/AsAsync.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 21 | -------------------------------------------------------------------------------- /vue-dd/test/components/AsyncComp.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /vue-dd/test/components/AsyncWrapper.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /vue-dd/test/components/Hello.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /vue-dd/test/imports.test.ts: -------------------------------------------------------------------------------- 1 | describe('import vue components', () => { 2 | test('normal imports as expected', async () => { 3 | const cmp = await import('./components/Hello.vue') 4 | expect(cmp).toBeDefined() 5 | }) 6 | 7 | test('template string imports as expected', async () => { 8 | // eslint-disable-next-line @typescript-eslint/quotes 9 | const cmp = await import(`./components/Hello.vue`) 10 | expect(cmp).toBeDefined() 11 | }) 12 | 13 | test('dynamic imports as expected', async () => { 14 | const name = 'Hello' 15 | const cmp = await import(`./components/${name}.vue`) 16 | expect(cmp).toBeDefined() 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /vue-dd/test/vue-dd.test.ts: -------------------------------------------------------------------------------- 1 | import { nextTick, ref } from 'vue' 2 | import { flushPromises, mount } from '@vue/test-utils' 3 | import VueDd from '../src/VueDd.vue' 4 | 5 | export default function sleep (ms) { 6 | return new Promise(resolve => setTimeout(resolve, ms)); 7 | } 8 | 9 | const defaults = { 10 | arrow: true, 11 | arrowOpen: '-', 12 | arrowClosed: '+', 13 | } 14 | 15 | describe('vue dd init', () => { 16 | 17 | test('import', () => { 18 | expect(VueDd).toBeTruthy() 19 | }) 20 | 21 | describe('primitives', () => { 22 | 23 | test('null', async () => { 24 | 25 | const modelValue = null 26 | 27 | const wrapper = mount(VueDd, { 28 | props: { ...defaults, modelValue } 29 | }) 30 | 31 | await nextTick() 32 | 33 | const text = wrapper.text() 34 | 35 | expect(text).toContain('null') 36 | }) 37 | 38 | test('undefined', async () => { 39 | 40 | const modelValue = undefined 41 | // const promise = new Promise(_resolve => resolve = _resolve) 42 | const wrapper = mount(VueDd, { 43 | props: { ...defaults, modelValue } 44 | }) 45 | 46 | await nextTick() 47 | 48 | const text = wrapper.text() 49 | 50 | // console.log(text) 51 | expect(text).toContain('undefined') 52 | }) 53 | 54 | test('string', async () => { 55 | 56 | const modelValue = 'string' 57 | // const promise = new Promise(_resolve => resolve = _resolve) 58 | const wrapper = mount(VueDd, { 59 | props: { ...defaults, modelValue } 60 | }) 61 | 62 | await nextTick() 63 | 64 | const text = wrapper.text() 65 | console.log(text) 66 | 67 | expect(text).toContain('string') 68 | }) 69 | 70 | test('number', async () => { 71 | 72 | const modelValue = 1000 73 | 74 | const wrapper = mount(VueDd, { 75 | props: { ...defaults, modelValue } 76 | }) 77 | 78 | await nextTick() 79 | 80 | const text = wrapper.text() 81 | 82 | // console.log(text) 83 | 84 | expect(text).toContain(modelValue) 85 | }) 86 | 87 | describe('complex', () => { 88 | 89 | test('object', async () => { 90 | 91 | const modelValue = { test: 1 } 92 | 93 | const wrapper = mount(VueDd, { 94 | props: { ...defaults, modelValue } 95 | }) 96 | 97 | await nextTick() 98 | 99 | const text = wrapper.text() 100 | 101 | expect(text).toContain('test:1') 102 | }) 103 | 104 | test('array', async () => { 105 | 106 | const modelValue = ['test'] 107 | 108 | const wrapper = mount(VueDd, { 109 | props: { ...defaults, modelValue } 110 | }) 111 | 112 | await nextTick() 113 | 114 | const text = wrapper.text() 115 | 116 | console.log(text) 117 | expect(text).toContain('test') 118 | }) 119 | // 120 | // test('array of objects: test', async () => { 121 | // 122 | // const modelValue = Object.freeze([{ obj: { subobj: 'hello', unreachableObjectContent: { unreachable: true } } }, { obj: 2 }]) 123 | // 124 | // const level = 3; 125 | // 126 | // const wrapper = mount(VueDd, { 127 | // props: { 128 | // ...defaults, 129 | // modelValue, 130 | // openLevel: level, 131 | // preview: 0 //disable previews to test for level 4 opening 132 | // }, 133 | // }) 134 | // 135 | // await nextTick() 136 | // await sleep(34 * level * 3) 137 | // 138 | // const text = wrapper.text() 139 | // 140 | // console.log('array of objects test') 141 | // console.log(text) 142 | // 143 | // expect(text).toContain('+unreachableObjectContent:{...}') 144 | // 145 | // }) 146 | }) 147 | 148 | // test('array of objects with refs', async () => { 149 | // 150 | // const modelValue = ref([22, { obj: ref(false) }, { obj: ref(true) }]) 151 | // 152 | // // console.log(modelValue) 153 | // const level = 1 154 | // const wrapper = mount(VueDd, { 155 | // props: { 156 | // ...defaults, 157 | // modelValue, 158 | // openLevel: level, 159 | // openSpecific: ['_rawValue.1', '_rawValue.2'], 160 | // // preview: 5 161 | // }, 162 | // }) 163 | // 164 | // await nextTick() 165 | // 166 | // await sleep(34 * 1 * 3) 167 | // const text = wrapper.text() 168 | // 169 | // console.log(text) 170 | // expect(text).toContain('_value:R[[3]22,+R{...},+R{...}]') 171 | // // expect(text).toContain('_value:true') 172 | // 173 | // }) 174 | 175 | }) 176 | 177 | }) 178 | 179 | 180 | -------------------------------------------------------------------------------- /vue-dd/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "module": "ESNext", 5 | "target": "es2016", 6 | "lib": ["DOM", "ESNext"], 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "incremental": false, 10 | "skipLibCheck": true, 11 | "moduleResolution": "node", 12 | "resolveJsonModule": true, 13 | "noUnusedLocals": true, 14 | "strictNullChecks": true, 15 | "allowJs": true, 16 | "noEmit": true, 17 | "forceConsistentCasingInFileNames": true, 18 | "types": ["vitest/globals"], 19 | "paths": { 20 | "~/*": ["src/*"] 21 | } 22 | }, 23 | "exclude": ["dist", "node_modules"] 24 | } 25 | -------------------------------------------------------------------------------- /vue-dd/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import type { DefineComponent } from 'vue' 5 | const component: DefineComponent<{}, {}, any> 6 | export default component 7 | } 8 | -------------------------------------------------------------------------------- /vue-dd/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | import dts from "vite-plugin-dts"; 6 | import pkg from "./package.json"; 7 | import libCss from 'vite-plugin-libcss'; 8 | 9 | export const vueDocsPlugin = () => ({ 10 | name: "vue-docs", 11 | transform (code: any, id: any) { 12 | if (!/vue&type=docs/.test(id)) return; 13 | return `export default ''`; 14 | } 15 | }); 16 | 17 | // https://vitejs.dev/config/ 18 | export default defineConfig({ 19 | resolve: { 20 | alias: { 21 | '@': fileURLToPath(new URL('./src', import.meta.url)) 22 | } 23 | }, 24 | server: { 25 | fs: { 26 | allow: ['..'] 27 | } 28 | }, 29 | plugins: [ 30 | vue({ 31 | css: true 32 | }), 33 | dts({ 34 | cleanVueFileName: true, 35 | }), 36 | vueDocsPlugin(), 37 | libCss() 38 | ], 39 | build: { 40 | cssCodeSplit: true, 41 | lib: { 42 | entry: "./src/index.ts", 43 | formats: ["es", "umd"], 44 | // the name expose in umd mode 45 | name: pkg.name, 46 | fileName: (format) => `index.${format}.js`, 47 | }, 48 | rollupOptions: { 49 | external: ["vue"], 50 | output: { 51 | globals: { 52 | vue: "Vue" 53 | }, 54 | }, 55 | }, 56 | }, 57 | }) 58 | -------------------------------------------------------------------------------- /vue-dd/vitest.config.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { defineConfig } from 'vite' 4 | import Vue from '@vitejs/plugin-vue' 5 | 6 | export default defineConfig({ 7 | plugins: [ 8 | Vue(), 9 | ], 10 | test: { 11 | globals: true, 12 | environment: 'jsdom', 13 | include: ["test/*.test.ts"], 14 | }, 15 | }) 16 | -------------------------------------------------------------------------------- /vue2/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /vue2/README.md: -------------------------------------------------------------------------------- 1 | # vue2 2 | 3 | ## Project setup 4 | ``` 5 | yarn install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | yarn serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | yarn build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | yarn lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /vue2/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /vue2/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "esnext", 5 | "baseUrl": "./", 6 | "moduleResolution": "node", 7 | "paths": { 8 | "@/*": [ 9 | "src/*" 10 | ] 11 | }, 12 | "lib": [ 13 | "esnext", 14 | "dom", 15 | "dom.iterable", 16 | "scripthost" 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /vue2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue2", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "core-js": "^3.8.3", 12 | "vue": "^2.7.5", 13 | "vue-dd": "^1.2.0-dev.0" 14 | }, 15 | "devDependencies": { 16 | "@babel/core": "^7.12.16", 17 | "@babel/eslint-parser": "^7.12.16", 18 | "@vue/cli-plugin-babel": "~5.0.0", 19 | "@vue/cli-plugin-eslint": "~5.0.0", 20 | "@vue/cli-service": "~5.0.0", 21 | "eslint": "^7.32.0", 22 | "eslint-plugin-vue": "^8.0.3", 23 | "vue-template-compiler": "^2.6.14" 24 | }, 25 | "eslintConfig": { 26 | "root": true, 27 | "env": { 28 | "node": true 29 | }, 30 | "extends": [ 31 | "plugin:vue/essential", 32 | "eslint:recommended" 33 | ], 34 | "parserOptions": { 35 | "parser": "@babel/eslint-parser" 36 | }, 37 | "rules": {} 38 | }, 39 | "browserslist": [ 40 | "> 1%", 41 | "last 2 versions", 42 | "not dead" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /vue2/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinite-system/vue-dd/fac5498a27bfdcc533601d1257c781deb1a6e34d/vue2/public/favicon.ico -------------------------------------------------------------------------------- /vue2/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /vue2/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 27 | -------------------------------------------------------------------------------- /vue2/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinite-system/vue-dd/fac5498a27bfdcc533601d1257c781deb1a6e34d/vue2/src/assets/logo.png -------------------------------------------------------------------------------- /vue2/src/components/VueDdTest.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 25 | 26 | 27 | 43 | -------------------------------------------------------------------------------- /vue2/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | // import VueDd from 'vue-dd' 4 | // import VueDd from '../../vue-dd/src/VueDd.vue' 5 | import { VueDd } from 'vue-dd' 6 | 7 | Vue.config.productionTip = false 8 | 9 | new Vue({ 10 | render: h => h(App) 11 | }).$mount('#app') 12 | 13 | Vue.component('VueDd', VueDd) 14 | // Vue.component('VueDdNpm', VueDdNpm) -------------------------------------------------------------------------------- /vue2/vue.config.js: -------------------------------------------------------------------------------- 1 | const { defineConfig } = require('@vue/cli-service') 2 | module.exports = defineConfig({ 3 | transpileDependencies: true 4 | }) 5 | -------------------------------------------------------------------------------- /vue3/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | require('@rushstack/eslint-patch/modern-module-resolution') 3 | 4 | module.exports = { 5 | root: true, 6 | 'extends': [ 7 | 'plugin:vue/vue3-essential', 8 | 'eslint:recommended', 9 | '@vue/eslint-config-typescript', 10 | // '@vue/eslint-config-prettier' 11 | ], 12 | // "rules": { 13 | // "eqeqeq": "off", 14 | // "no-console": "off" 15 | // }, 16 | overrides: [ 17 | { 18 | files: [ 19 | 'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}' 20 | ], 21 | 'extends': [ 22 | 'plugin:cypress/recommended' 23 | ] 24 | } 25 | ], 26 | parserOptions: { 27 | ecmaVersion: 'latest' 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /vue3/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? -------------------------------------------------------------------------------- /vue3/.prettierrc.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /vue3/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /vue3/README.md: -------------------------------------------------------------------------------- 1 | # vue3 2 | 3 | This template should help get you started developing with Vue 3 in Vite. 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). 8 | 9 | ## Type Support for `.vue` Imports in TS 10 | 11 | TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. 12 | 13 | If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: 14 | 15 | 1. Disable the built-in TypeScript Extension 16 | 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette 17 | 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` 18 | 2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. 19 | 20 | ## Customize configuration 21 | 22 | See [Vite Configuration Reference](https://vitejs.dev/config/). 23 | 24 | ## Project Setup 25 | 26 | ```sh 27 | yarn 28 | ``` 29 | 30 | ### Compile and Hot-Reload for Development 31 | 32 | ```sh 33 | yarn dev 34 | ``` 35 | 36 | ### Type-Check, Compile and Minify for Production 37 | 38 | ```sh 39 | yarn build 40 | ``` 41 | 42 | ### Run Unit Tests with [Vitest](https://vitest.dev/) 43 | 44 | ```sh 45 | yarn test:unit 46 | ``` 47 | 48 | ### Run End-to-End Tests with [Cypress](https://www.cypress.io/) 49 | 50 | ```sh 51 | yarn test:e2e:dev 52 | ``` 53 | 54 | This runs the end-to-end tests against the Vite development server. 55 | It is much faster than the production build. 56 | 57 | But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): 58 | 59 | ```sh 60 | yarn build 61 | yarn test:e2e 62 | ``` 63 | 64 | ### Lint with [ESLint](https://eslint.org/) 65 | 66 | ```sh 67 | yarn lint 68 | ``` 69 | -------------------------------------------------------------------------------- /vue3/cypress.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'cypress' 2 | 3 | export default defineConfig({ 4 | e2e: { 5 | specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', 6 | baseUrl: 'http://localhost:5173' 7 | } 8 | }) 9 | -------------------------------------------------------------------------------- /vue3/cypress/e2e/example.cy.ts: -------------------------------------------------------------------------------- 1 | // https://docs.cypress.io/api/introduction/api.html 2 | 3 | describe('My First Test', () => { 4 | it('visits the app root url', () => { 5 | cy.visit('/') 6 | cy.contains('span', 'window') 7 | }) 8 | }) 9 | -------------------------------------------------------------------------------- /vue3/cypress/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.web.json", 3 | "include": ["./**/*", "../support/**/*"], 4 | "compilerOptions": { 5 | "isolatedModules": false, 6 | "target": "es5", 7 | "lib": ["es5", "dom"], 8 | "types": ["cypress"] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vue3/cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } 6 | -------------------------------------------------------------------------------- /vue3/cypress/support/commands.ts: -------------------------------------------------------------------------------- 1 | /// 2 | // *********************************************** 3 | // This example commands.ts shows you how to 4 | // create various custom commands and overwrite 5 | // existing commands. 6 | // 7 | // For more comprehensive examples of custom 8 | // commands please read more here: 9 | // https://on.cypress.io/custom-commands 10 | // *********************************************** 11 | // 12 | // 13 | // -- This is a parent command -- 14 | // Cypress.Commands.add('login', (email, password) => { ... }) 15 | // 16 | // 17 | // -- This is a child command -- 18 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) 19 | // 20 | // 21 | // -- This is a dual command -- 22 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) 23 | // 24 | // 25 | // -- This will overwrite an existing command -- 26 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) 27 | // 28 | // declare global { 29 | // namespace Cypress { 30 | // interface Chainable { 31 | // login(email: string, password: string): Chainable 32 | // drag(subject: string, options?: Partial): Chainable 33 | // dismiss(subject: string, options?: Partial): Chainable 34 | // visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable 35 | // } 36 | // } 37 | // } 38 | 39 | export {} 40 | -------------------------------------------------------------------------------- /vue3/cypress/support/e2e.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands' 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /vue3/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /vue3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /vue3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue3", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "run-p type-check build-only", 8 | "preview": "vite preview", 9 | "test:unit": "vitest --environment jsdom --root src/", 10 | "test:e2e": "start-server-and-test preview :4173 'cypress run --e2e'", 11 | "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' :4173 'cypress open --e2e'", 12 | "build-only": "vite build", 13 | "type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false", 14 | "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore" 15 | }, 16 | "dependencies": { 17 | "pinia": "^2.0.28", 18 | "vue": "^3.2.45", 19 | "vue-dd": "^1.3.4", 20 | "vue-router": "^4.1.6" 21 | }, 22 | "devDependencies": { 23 | "@rushstack/eslint-patch": "^1.1.4", 24 | "@types/jsdom": "^20.0.1", 25 | "@types/node": "^18.11.12", 26 | "@vitejs/plugin-vue": "^4.0.0", 27 | "@vue/eslint-config-prettier": "^7.0.0", 28 | "@vue/eslint-config-typescript": "^11.0.0", 29 | "@vue/test-utils": "^2.2.6", 30 | "@vue/tsconfig": "^0.1.3", 31 | "cypress": "^12.0.2", 32 | "eslint": "^8.22.0", 33 | "eslint-plugin-cypress": "^2.12.1", 34 | "eslint-plugin-vue": "^9.3.0", 35 | "highlight.js": "^11.7.0", 36 | "jsdom": "^20.0.3", 37 | "npm-run-all": "^4.1.5", 38 | "prettier": "^2.7.1", 39 | "start-server-and-test": "^1.15.2", 40 | "typescript": "~4.7.4", 41 | "vite": "^4.0.0", 42 | "vitest": "^0.25.6", 43 | "vue-tsc": "^1.0.12" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /vue3/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/infinite-system/vue-dd/fac5498a27bfdcc533601d1257c781deb1a6e34d/vue3/public/favicon.ico -------------------------------------------------------------------------------- /vue3/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 21 | 22 | 85 | -------------------------------------------------------------------------------- /vue3/src/assets/base.css: -------------------------------------------------------------------------------- 1 | /* color palette from */ 2 | :root { 3 | --vt-c-white: #ffffff; 4 | --vt-c-white-soft: #f8f8f8; 5 | --vt-c-white-mute: #f2f2f2; 6 | 7 | --vt-c-black: #181818; 8 | --vt-c-black-soft: #222222; 9 | --vt-c-black-mute: #282828; 10 | 11 | --vt-c-indigo: #2c3e50; 12 | 13 | --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); 14 | --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); 15 | --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); 16 | --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); 17 | 18 | --vt-c-text-light-1: var(--vt-c-indigo); 19 | --vt-c-text-light-2: rgba(60, 60, 60, 0.66); 20 | --vt-c-text-dark-1: var(--vt-c-white); 21 | --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); 22 | } 23 | 24 | /* semantic color variables for this project */ 25 | :root { 26 | --color-background: var(--vt-c-white); 27 | --color-background-soft: var(--vt-c-white-soft); 28 | --color-background-mute: var(--vt-c-white-mute); 29 | 30 | --color-border: var(--vt-c-divider-light-2); 31 | --color-border-hover: var(--vt-c-divider-light-1); 32 | 33 | --color-heading: var(--vt-c-text-light-1); 34 | --color-text: var(--vt-c-text-light-1); 35 | 36 | --section-gap: 160px; 37 | } 38 | 39 | @media (prefers-color-scheme: dark) { 40 | :root { 41 | --color-background: var(--vt-c-black); 42 | --color-background-soft: var(--vt-c-black-soft); 43 | --color-background-mute: var(--vt-c-black-mute); 44 | 45 | --color-border: var(--vt-c-divider-dark-2); 46 | --color-border-hover: var(--vt-c-divider-dark-1); 47 | 48 | --color-heading: var(--vt-c-text-dark-1); 49 | --color-text: var(--vt-c-text-dark-2); 50 | } 51 | } 52 | 53 | *, 54 | *::before, 55 | *::after { 56 | box-sizing: border-box; 57 | margin: 0; 58 | position: relative; 59 | } 60 | 61 | body { 62 | min-height: 100vh; 63 | color: var(--color-text); 64 | background: var(--color-background); 65 | transition: color 0.5s, background-color 0.5s; 66 | line-height: 1.6; 67 | font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 68 | Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 69 | font-size: 15px; 70 | text-rendering: optimizeLegibility; 71 | -webkit-font-smoothing: antialiased; 72 | -moz-osx-font-smoothing: grayscale; 73 | } 74 | -------------------------------------------------------------------------------- /vue3/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vue3/src/assets/main.css: -------------------------------------------------------------------------------- 1 | @import './base.css'; 2 | 3 | #app { 4 | max-width: 1280px; 5 | margin: 0 auto; 6 | padding: 2rem; 7 | 8 | font-weight: normal; 9 | } 10 | 11 | a, 12 | .green { 13 | text-decoration: none; 14 | color: hsla(160, 100%, 37%, 1); 15 | transition: 0.4s; 16 | } 17 | 18 | @media (hover: hover) { 19 | a:hover { 20 | background-color: hsla(160, 100%, 37%, 0.2); 21 | } 22 | } 23 | 24 | @media (min-width: 1024px) { 25 | body { 26 | /*display: flex;*/ 27 | /*place-items: center;*/ 28 | } 29 | 30 | #app { 31 | /*display: grid;*/ 32 | /*grid-template-columns: 1fr 1fr;*/ 33 | /*padding: 0 2rem;*/ 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /vue3/src/components/BaseCheckbox.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 44 | -------------------------------------------------------------------------------- /vue3/src/components/VueDdApiTest.vue: -------------------------------------------------------------------------------- 1 | 112 | 113 | 212 | 213 | 292 | -------------------------------------------------------------------------------- /vue3/src/components/VueDdTest.vue: -------------------------------------------------------------------------------- 1 | 111 | 112 | 141 | -------------------------------------------------------------------------------- /vue3/src/components/VueDdTest2.vue: -------------------------------------------------------------------------------- 1 | 84 | 85 | 110 | -------------------------------------------------------------------------------- /vue3/src/components/__tests__/HelloWorld.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest' 2 | 3 | import { mount } from '@vue/test-utils' 4 | import HelloWorld from './HelloWorld.vue' 5 | 6 | describe('HelloWorld', () => { 7 | it('renders properly', () => { 8 | const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) 9 | expect(wrapper.text()).toContain('Hello Vitest') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /vue3/src/components/__tests__/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 22 | 23 | 46 | -------------------------------------------------------------------------------- /vue3/src/components/__tests__/WelcomeItem.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 87 | -------------------------------------------------------------------------------- /vue3/src/components/icons/IconCommunity.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /vue3/src/components/icons/IconDocumentation.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /vue3/src/components/icons/IconEcosystem.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /vue3/src/components/icons/IconSupport.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /vue3/src/components/icons/IconTooling.vue: -------------------------------------------------------------------------------- 1 | 2 | 20 | -------------------------------------------------------------------------------- /vue3/src/features/setupFormComponent.js: -------------------------------------------------------------------------------- 1 | export default function setupFormComponent (props, { emit }) { 2 | const updateValue = (event) => { 3 | let val = event.target.value 4 | 5 | if (event.target.type === 'checkbox') val = event.target.checked 6 | if (event.target.type === 'radio') val = props.value 7 | 8 | emit('update:modelValue', val) 9 | } 10 | 11 | return { updateValue } 12 | } 13 | -------------------------------------------------------------------------------- /vue3/src/features/uniqueId.js: -------------------------------------------------------------------------------- 1 | let UUID = 1 2 | export default function uniqueId () { 3 | UUID++ 4 | return UUID 5 | } 6 | -------------------------------------------------------------------------------- /vue3/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import { createPinia } from 'pinia' 3 | 4 | 5 | import App from './App.vue' 6 | import router from './router' 7 | // 8 | import './assets/main.css' 9 | 10 | const app = createApp(App) 11 | 12 | app.use(createPinia()) 13 | app.use(router) 14 | 15 | 16 | // const npm = false 17 | // let VueDd = await import(npm ? `../node_modules/vue-dd/dist/index.es.js` : `../../vue-dd/src/VueDd.vue`) 18 | // VueDd = npm ? VueDd.VueDd : VueDd.default 19 | // 20 | // app.component('VueDd', VueDd) 21 | 22 | app.mount('#app') 23 | -------------------------------------------------------------------------------- /vue3/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router' 2 | import HomeView from '../views/HomeView.vue' 3 | import VueDdTest from '../components/VueDdTest.vue' 4 | import VueDdTest2 from '../components/VueDdTest2.vue' 5 | import VueDdApiTest from '../components/VueDdApiTest.vue' 6 | 7 | const router = createRouter({ 8 | history: createWebHistory(import.meta.env.BASE_URL), 9 | routes: [ 10 | { 11 | path: '/', 12 | name: 'home', 13 | component: HomeView, 14 | children: [ 15 | { 16 | path: '', 17 | name: 'vue-dd', 18 | component: VueDdTest 19 | }, 20 | { 21 | path: 'test-2', 22 | name: 'vue-dd-test-2', 23 | component: VueDdTest2 24 | }, 25 | { 26 | path: 'api', 27 | name: 'vue-dd-api', 28 | component: VueDdApiTest 29 | } 30 | ] 31 | }, 32 | { 33 | path: '/api', 34 | name: 'api', 35 | // route level code-splitting 36 | // this generates a separate chunk (About.[hash].js) for this route 37 | // which is lazy-loaded when the route is visited. 38 | component: VueDdApiTest 39 | } 40 | ] 41 | }) 42 | 43 | export default router 44 | -------------------------------------------------------------------------------- /vue3/src/stores/counter.ts: -------------------------------------------------------------------------------- 1 | import { ref, computed } from 'vue' 2 | import { defineStore } from 'pinia' 3 | 4 | export const useCounterStore = defineStore('counter', () => { 5 | const count = ref(0) 6 | const doubleCount = computed(() => count.value * 2) 7 | function increment() { 8 | count.value++ 9 | } 10 | 11 | return { count, doubleCount, increment } 12 | }) 13 | -------------------------------------------------------------------------------- /vue3/src/views/AboutView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /vue3/src/views/HomeView.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /vue3/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.web.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "baseUrl": ".", 8 | "paths": { 9 | "@/*": ["./src/*"] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vue3/tsconfig.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.node.json", 3 | "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"], 4 | "compilerOptions": { 5 | "composite": true, 6 | "types": ["node"] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /vue3/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.config.json" 6 | }, 7 | { 8 | "path": "./tsconfig.app.json" 9 | }, 10 | { 11 | "path": "./tsconfig.vitest.json" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /vue3/tsconfig.vitest.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.app.json", 3 | "exclude": [], 4 | "compilerOptions": { 5 | "composite": true, 6 | "lib": [], 7 | "types": ["node", "jsdom"] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /vue3/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [vue()], 9 | resolve: { 10 | alias: { 11 | '@': fileURLToPath(new URL('./src', import.meta.url)) 12 | } 13 | }, 14 | server: { 15 | fs: { 16 | allow: ['..'] 17 | } 18 | }, 19 | 20 | }) 21 | --------------------------------------------------------------------------------