diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index a40d39c8a..02054a7ee 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -93,7 +93,8 @@ export default defineConfig({ { text: 'Stubs and Shallow Mount', link: '/guide/advanced/stubs-shallow-mount' - } + }, + { text: 'Server-side rendering', link: '/guide/advanced/ssr' } ] }, { diff --git a/docs/api/index.md b/docs/api/index.md index 2cc8c3b3c..6bb67bfa5 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -1797,6 +1797,12 @@ await wrapper.trigger('keydown', { keyCode: 65 }) You should use `await` when you call `trigger` to ensure that Vue updates the DOM before you make an assertion. ::: +::: warning +Some events, like clicking on a checkbox to change its `v-model`, +will only work if the test uses `attachTo: document.body`. +Otherwise, the `change` event will not be triggered, and the `v-model` value does not change. +::: + ### unmount Unmount the application from the DOM. @@ -1886,7 +1892,7 @@ function shallowMount(Component, options?: MountingOptions): VueWrapper **Signature:** ```ts -enableAutoUnmount(hook: Function)); +enableAutoUnmount(hook: (callback: () => void) => void); disableAutoUnmount(): void; ``` diff --git a/docs/guide/advanced/ssr.md b/docs/guide/advanced/ssr.md new file mode 100644 index 000000000..9cebb7e0e --- /dev/null +++ b/docs/guide/advanced/ssr.md @@ -0,0 +1,42 @@ +# Testing Server-side Rendering + +Vue Test Utils provides `renderToString` to test Vue applications that use server-side rendering (SSR). +This guide will walk you through the process of testing a Vue application that uses SSR. + +## `renderToString` + +`renderToString` is a function that renders a Vue component to a string. +It is an asynchronous function that returns a Promise, +and accepts the same parameters as `mount` or `shallowMount`. + +Let's consider a simple component that uses the `onServerPrefetch` hook: + +```ts +function fakeFetch(text: string) { + return Promise.resolve(text) +} + +const Component = defineComponent({ + template: '
{{ text }}
', + setup() { + const text = ref(null) + + onServerPrefetch(async () => { + text.value = await fakeFetch('onServerPrefetch') + }) + + return { text } + } +}) +``` + +You can write a test for this component using `renderToString`: + +```ts +import { renderToString } from '@vue/test-utils' + +it('renders the value returned by onServerPrefetch', async () => { + const contents = await renderToString(Component) + expect(contents).toBe('
onServerPrefetch
') +}) +``` diff --git a/docs/guide/advanced/v-model.md b/docs/guide/advanced/v-model.md index 50dfcbc06..604e11980 100644 --- a/docs/guide/advanced/v-model.md +++ b/docs/guide/advanced/v-model.md @@ -16,6 +16,7 @@ const Editor = { label: String, modelValue: String }, + emits: ['update:modelValue'], template: `
@@ -30,7 +31,7 @@ const App { components: { Editor }, - template: `` + template: ``, data(){ return { text: 'test' @@ -69,7 +70,8 @@ const MoneyEditor = {
`, - props: ['currency', 'modelValue'] + props: ['currency', 'modelValue'], + emits: ['update:currency', 'update:modelValue'] } ``` diff --git a/package.json b/package.json index b8a05449e..132a30201 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@vue/test-utils", - "version": "2.2.10", + "version": "2.3.0", "license": "MIT", "main": "dist/vue-test-utils.cjs.js", "unpkg": "dist/vue-test-utils.browser.js", @@ -31,44 +31,47 @@ "@rollup/plugin-replace": "5.0.2", "@rollup/plugin-typescript": "11.0.0", "@types/js-beautify": "1.13.3", - "@types/node": "18.11.18", - "@typescript-eslint/eslint-plugin": "5.50.0", - "@typescript-eslint/parser": "5.50.0", + "@types/node": "18.13.0", + "@typescript-eslint/eslint-plugin": "5.52.0", + "@typescript-eslint/parser": "5.52.0", "@vitejs/plugin-vue": "4.0.0", "@vitejs/plugin-vue-jsx": "3.0.0", - "@vitest/coverage-c8": "0.28.3", + "@vitest/coverage-c8": "0.28.5", "@vue/compat": "3.2.47", "@vue/compiler-dom": "3.2.47", "@vue/compiler-sfc": "3.2.47", + "@vue/server-renderer": "3.2.47", "c8": "7.12.0", - "eslint": "8.33.0", + "eslint": "8.34.0", "eslint-config-prettier": "8.6.0", "eslint-plugin-prettier": "4.2.1", "husky": "8.0.3", "jsdom": "21.1.0", "jsdom-global": "3.0.2", - "lint-staged": "13.1.0", - "prettier": "2.8.3", + "lint-staged": "13.1.2", + "prettier": "2.8.4", "reflect-metadata": "0.1.13", - "rollup": "3.12.1", + "rollup": "3.15.0", "tslib": "2.5.0", "typescript": "4.9.5", - "unplugin-vue-components": "0.23.0", + "unplugin-vue-components": "0.24.0", "vite": "4.1.1", "vitepress": "0.22.4", - "vitest": "0.28.3", + "vitest": "0.28.5", "vue": "3.2.47", "vue-class-component": "8.0.0-rc.1", "vue-router": "4.1.6", - "vue-tsc": "1.0.24", + "vue-tsc": "1.1.0", "vuex": "4.1.0" }, "peerDependencies": { "@vue/compiler-dom": "^3.0.1", + "@vue/server-renderer": "^3.0.1", "vue": "^3.0.1" }, "optionalDependencies": { - "@vue/compiler-dom": "^3.0.1" + "@vue/compiler-dom": "^3.0.1", + "@vue/server-renderer": "^3.0.1" }, "author": { "name": "Lachlan Miller", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 85a872462..ef051497b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,81 +7,83 @@ specifiers: '@rollup/plugin-replace': 5.0.2 '@rollup/plugin-typescript': 11.0.0 '@types/js-beautify': 1.13.3 - '@types/node': 18.11.18 - '@typescript-eslint/eslint-plugin': 5.50.0 - '@typescript-eslint/parser': 5.50.0 + '@types/node': 18.13.0 + '@typescript-eslint/eslint-plugin': 5.52.0 + '@typescript-eslint/parser': 5.52.0 '@vitejs/plugin-vue': 4.0.0 '@vitejs/plugin-vue-jsx': 3.0.0 - '@vitest/coverage-c8': 0.28.3 + '@vitest/coverage-c8': 0.28.5 '@vue/compat': 3.2.47 '@vue/compiler-dom': ^3.0.1 '@vue/compiler-sfc': 3.2.47 + '@vue/server-renderer': ^3.0.1 c8: 7.12.0 - eslint: 8.33.0 + eslint: 8.34.0 eslint-config-prettier: 8.6.0 eslint-plugin-prettier: 4.2.1 husky: 8.0.3 js-beautify: 1.14.6 jsdom: 21.1.0 jsdom-global: 3.0.2 - lint-staged: 13.1.0 - prettier: 2.8.3 + lint-staged: 13.1.2 + prettier: 2.8.4 reflect-metadata: 0.1.13 - rollup: 3.12.1 + rollup: 3.15.0 tslib: 2.5.0 typescript: 4.9.5 - unplugin-vue-components: 0.23.0 + unplugin-vue-components: 0.24.0 vite: 4.1.1 vitepress: 0.22.4 - vitest: 0.28.3 + vitest: 0.28.5 vue: 3.2.47 vue-class-component: 8.0.0-rc.1 vue-router: 4.1.6 - vue-tsc: 1.0.24 + vue-tsc: 1.1.0 vuex: 4.1.0 dependencies: js-beautify: 1.14.6 optionalDependencies: - '@vue/compiler-dom': 3.2.45 + '@vue/compiler-dom': 3.2.47 + '@vue/server-renderer': 3.2.47_vue@3.2.47 devDependencies: - '@rollup/plugin-commonjs': 24.0.1_rollup@3.12.1 - '@rollup/plugin-json': 6.0.0_rollup@3.12.1 - '@rollup/plugin-node-resolve': 15.0.1_rollup@3.12.1 - '@rollup/plugin-replace': 5.0.2_rollup@3.12.1 - '@rollup/plugin-typescript': 11.0.0_dacjhltxvpiymvk442t6rtzddq + '@rollup/plugin-commonjs': 24.0.1_rollup@3.15.0 + '@rollup/plugin-json': 6.0.0_rollup@3.15.0 + '@rollup/plugin-node-resolve': 15.0.1_rollup@3.15.0 + '@rollup/plugin-replace': 5.0.2_rollup@3.15.0 + '@rollup/plugin-typescript': 11.0.0_fvqkzcb4hs3uargqzossetbx6u '@types/js-beautify': 1.13.3 - '@types/node': 18.11.18 - '@typescript-eslint/eslint-plugin': 5.50.0_go4drrxstycfikanvu45pi4vgq - '@typescript-eslint/parser': 5.50.0_4vsywjlpuriuw3tl5oq6zy5a64 + '@types/node': 18.13.0 + '@typescript-eslint/eslint-plugin': 5.52.0_6cfvjsbua5ptj65675bqcn6oza + '@typescript-eslint/parser': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm '@vitejs/plugin-vue': 4.0.0_vite@4.1.1+vue@3.2.47 '@vitejs/plugin-vue-jsx': 3.0.0_vite@4.1.1+vue@3.2.47 - '@vitest/coverage-c8': 0.28.3_jsdom@21.1.0 + '@vitest/coverage-c8': 0.28.5_jsdom@21.1.0 '@vue/compat': 3.2.47_vue@3.2.47 '@vue/compiler-sfc': 3.2.47 c8: 7.12.0 - eslint: 8.33.0 - eslint-config-prettier: 8.6.0_eslint@8.33.0 - eslint-plugin-prettier: 4.2.1_jqplj6qf3uqpxpu4gdyhwwasnq + eslint: 8.34.0 + eslint-config-prettier: 8.6.0_eslint@8.34.0 + eslint-plugin-prettier: 4.2.1_u5wnrdwibbfomslmnramz52buy husky: 8.0.3 jsdom: 21.1.0 jsdom-global: 3.0.2_jsdom@21.1.0 - lint-staged: 13.1.0 - prettier: 2.8.3 + lint-staged: 13.1.2 + prettier: 2.8.4 reflect-metadata: 0.1.13 - rollup: 3.12.1 + rollup: 3.15.0 tslib: 2.5.0 typescript: 4.9.5 - unplugin-vue-components: 0.23.0_rollup@3.12.1+vue@3.2.47 - vite: 4.1.1_@types+node@18.11.18 + unplugin-vue-components: 0.24.0_rollup@3.15.0+vue@3.2.47 + vite: 4.1.1_@types+node@18.13.0 vitepress: 0.22.4 - vitest: 0.28.3_jsdom@21.1.0 + vitest: 0.28.5_jsdom@21.1.0 vue: 3.2.47 vue-class-component: 8.0.0-rc.1_vue@3.2.47 vue-router: 4.1.6_vue@3.2.47 - vue-tsc: 1.0.24_typescript@4.9.5 + vue-tsc: 1.1.0_typescript@4.9.5 vuex: 4.1.0_vue@3.2.47 packages: @@ -252,18 +254,18 @@ packages: dependencies: '@ampproject/remapping': 2.2.0 '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.5 - '@babel/helper-compilation-targets': 7.20.0_@babel+core@7.20.5 - '@babel/helper-module-transforms': 7.20.2 - '@babel/helpers': 7.20.6 + '@babel/generator': 7.20.14 + '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.20.5 + '@babel/helper-module-transforms': 7.20.11 + '@babel/helpers': 7.20.13 '@babel/parser': 7.20.13 - '@babel/template': 7.18.10 - '@babel/traverse': 7.20.5 - '@babel/types': 7.20.5 + '@babel/template': 7.20.7 + '@babel/traverse': 7.20.13 + '@babel/types': 7.20.7 convert-source-map: 1.8.0 debug: 4.3.4 gensync: 1.0.0-beta.2 - json5: 2.2.1 + json5: 2.2.3 semver: 6.3.0 transitivePeerDependencies: - supports-color @@ -278,15 +280,6 @@ packages: jsesc: 2.5.2 dev: true - /@babel/generator/7.20.5: - resolution: {integrity: sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.7 - '@jridgewell/gen-mapping': 0.3.2 - jsesc: 2.5.2 - dev: true - /@babel/helper-annotate-as-pure/7.18.6: resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} engines: {node: '>=6.9.0'} @@ -294,27 +287,28 @@ packages: '@babel/types': 7.20.7 dev: true - /@babel/helper-compilation-targets/7.20.0_@babel+core@7.20.5: - resolution: {integrity: sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==} + /@babel/helper-compilation-targets/7.20.7_@babel+core@7.20.12: + resolution: {integrity: sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/compat-data': 7.20.5 - '@babel/core': 7.20.5 + '@babel/core': 7.20.12 '@babel/helper-validator-option': 7.18.6 browserslist: 4.21.4 + lru-cache: 5.1.1 semver: 6.3.0 dev: true - /@babel/helper-compilation-targets/7.20.7_@babel+core@7.20.12: + /@babel/helper-compilation-targets/7.20.7_@babel+core@7.20.5: resolution: {integrity: sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/compat-data': 7.20.5 - '@babel/core': 7.20.12 + '@babel/core': 7.20.5 '@babel/helper-validator-option': 7.18.6 browserslist: 4.21.4 lru-cache: 5.1.1 @@ -389,22 +383,6 @@ packages: - supports-color dev: true - /@babel/helper-module-transforms/7.20.2: - resolution: {integrity: sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-module-imports': 7.18.6 - '@babel/helper-simple-access': 7.20.2 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.19.1 - '@babel/template': 7.20.7 - '@babel/traverse': 7.20.13 - '@babel/types': 7.20.7 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/helper-optimise-call-expression/7.18.6: resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} engines: {node: '>=6.9.0'} @@ -468,17 +446,6 @@ packages: - supports-color dev: true - /@babel/helpers/7.20.6: - resolution: {integrity: sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.20.7 - '@babel/traverse': 7.20.13 - '@babel/types': 7.20.7 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/highlight/7.18.6: resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} engines: {node: '>=6.9.0'} @@ -534,15 +501,6 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/template/7.18.10: - resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/parser': 7.20.13 - '@babel/types': 7.20.7 - dev: true - /@babel/template/7.20.7: resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} engines: {node: '>=6.9.0'} @@ -570,33 +528,6 @@ packages: - supports-color dev: true - /@babel/traverse/7.20.5: - resolution: {integrity: sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.20.14 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 - '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.20.13 - '@babel/types': 7.20.7 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types/7.20.5: - resolution: {integrity: sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - dev: true - /@babel/types/7.20.7: resolution: {integrity: sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==} engines: {node: '>=6.9.0'} @@ -946,18 +877,18 @@ packages: fastq: 1.13.0 dev: true - /@nuxt/kit/3.1.1_rollup@3.12.1: - resolution: {integrity: sha512-wmqVCIuD/te6BKf3YiqWyMumKI5JIpkiv0li/1Y3QHnTkoxyIhLkbFgNcQHuBxJ3eMlk2UjAjAqWiqBHTX54vQ==} + /@nuxt/kit/3.2.0_rollup@3.15.0: + resolution: {integrity: sha512-Otb1S/08tDxbpeQYLMynjr2TX7ssU1ynbWDpVzFzLBdfHkGWHXpIhJr+0u3LdnPUBw6C/xPXe7fd7RuXI9avoA==} engines: {node: ^14.16.0 || ^16.10.0 || ^17.0.0 || ^18.0.0 || ^19.0.0} dependencies: - '@nuxt/schema': 3.1.1_rollup@3.12.1 + '@nuxt/schema': 3.2.0_rollup@3.15.0 c12: 1.1.0 consola: 2.15.3 defu: 6.1.2 globby: 13.1.3 hash-sum: 2.0.0 ignore: 5.2.4 - jiti: 1.16.2 + jiti: 1.17.0 knitwork: 1.0.0 lodash.template: 4.5.0 mlly: 1.1.0 @@ -966,36 +897,36 @@ packages: scule: 1.0.0 semver: 7.3.8 unctx: 2.1.1 - unimport: 2.1.0_rollup@3.12.1 + unimport: 2.2.4_rollup@3.15.0 untyped: 1.2.2 transitivePeerDependencies: - rollup - supports-color dev: true - /@nuxt/schema/3.1.1_rollup@3.12.1: - resolution: {integrity: sha512-/KuoCDVGrLD9W7vwuYhu4HbdT/BpbrhA4Pm9dGn7Jah40kHDGqUnJxugvMjt+4suq53rLQyTA0LRDWfFxfxAOQ==} + /@nuxt/schema/3.2.0_rollup@3.15.0: + resolution: {integrity: sha512-tz9RandI5LgbT9BQ8dE8n4kItV7+4OUgbX42YemcGbtORVJAWJJvQyHGikJ5akUgiTFYTV8tjV6pRPH9Txx0Pg==} engines: {node: ^14.16.0 || ^16.10.0 || ^17.0.0 || ^18.0.0 || ^19.0.0} dependencies: c12: 1.1.0 create-require: 1.1.1 defu: 6.1.2 hookable: 5.4.2 - jiti: 1.16.2 + jiti: 1.17.0 pathe: 1.1.0 pkg-types: 1.0.1 postcss-import-resolver: 2.0.0 scule: 1.0.0 - std-env: 3.3.1 + std-env: 3.3.2 ufo: 1.0.1 - unimport: 2.1.0_rollup@3.12.1 + unimport: 2.2.4_rollup@3.15.0 untyped: 1.2.2 transitivePeerDependencies: - rollup - supports-color dev: true - /@rollup/plugin-commonjs/24.0.1_rollup@3.12.1: + /@rollup/plugin-commonjs/24.0.1_rollup@3.15.0: resolution: {integrity: sha512-15LsiWRZk4eOGqvrJyu3z3DaBu5BhXIMeWnijSRvd8irrrg9SHpQ1pH+BUK4H6Z9wL9yOxZJMTLU+Au86XHxow==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1004,16 +935,16 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.12.1 + '@rollup/pluginutils': 5.0.2_rollup@3.15.0 commondir: 1.0.1 estree-walker: 2.0.2 glob: 8.0.3 is-reference: 1.2.1 magic-string: 0.27.0 - rollup: 3.12.1 + rollup: 3.15.0 dev: true - /@rollup/plugin-json/6.0.0_rollup@3.12.1: + /@rollup/plugin-json/6.0.0_rollup@3.15.0: resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1022,11 +953,11 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.12.1 - rollup: 3.12.1 + '@rollup/pluginutils': 5.0.2_rollup@3.15.0 + rollup: 3.15.0 dev: true - /@rollup/plugin-node-resolve/15.0.1_rollup@3.12.1: + /@rollup/plugin-node-resolve/15.0.1_rollup@3.15.0: resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1035,16 +966,16 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.12.1 + '@rollup/pluginutils': 5.0.2_rollup@3.15.0 '@types/resolve': 1.20.2 deepmerge: 4.2.2 is-builtin-module: 3.2.0 is-module: 1.0.0 resolve: 1.22.1 - rollup: 3.12.1 + rollup: 3.15.0 dev: true - /@rollup/plugin-replace/5.0.2_rollup@3.12.1: + /@rollup/plugin-replace/5.0.2_rollup@3.15.0: resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1053,12 +984,12 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.12.1 + '@rollup/pluginutils': 5.0.2_rollup@3.15.0 magic-string: 0.27.0 - rollup: 3.12.1 + rollup: 3.15.0 dev: true - /@rollup/plugin-typescript/11.0.0_dacjhltxvpiymvk442t6rtzddq: + /@rollup/plugin-typescript/11.0.0_fvqkzcb4hs3uargqzossetbx6u: resolution: {integrity: sha512-goPyCWBiimk1iJgSTgsehFD5OOFHiAknrRJjqFCudcW8JtWiBlK284Xnn4flqMqg6YAjVG/EE+3aVzrL5qNSzQ==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1071,14 +1002,14 @@ packages: tslib: optional: true dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.12.1 + '@rollup/pluginutils': 5.0.2_rollup@3.15.0 resolve: 1.22.1 - rollup: 3.12.1 + rollup: 3.15.0 tslib: 2.5.0 typescript: 4.9.5 dev: true - /@rollup/pluginutils/5.0.2_rollup@3.12.1: + /@rollup/pluginutils/5.0.2_rollup@3.15.0: resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1090,7 +1021,7 @@ packages: '@types/estree': 1.0.0 estree-walker: 2.0.2 picomatch: 2.3.1 - rollup: 3.12.1 + rollup: 3.15.0 dev: true /@tootallnate/once/2.0.0: @@ -1124,8 +1055,8 @@ packages: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} dev: true - /@types/node/18.11.18: - resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} + /@types/node/18.13.0: + resolution: {integrity: sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==} dev: true /@types/resolve/1.20.2: @@ -1136,8 +1067,8 @@ packages: resolution: {integrity: sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==} dev: true - /@typescript-eslint/eslint-plugin/5.50.0_go4drrxstycfikanvu45pi4vgq: - resolution: {integrity: sha512-vwksQWSFZiUhgq3Kv7o1Jcj0DUNylwnIlGvKvLLYsq8pAWha6/WCnXUeaSoNNha/K7QSf2+jvmkxggC1u3pIwQ==} + /@typescript-eslint/eslint-plugin/5.52.0_6cfvjsbua5ptj65675bqcn6oza: + resolution: {integrity: sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: '@typescript-eslint/parser': ^5.0.0 @@ -1147,12 +1078,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.50.0_4vsywjlpuriuw3tl5oq6zy5a64 - '@typescript-eslint/scope-manager': 5.50.0 - '@typescript-eslint/type-utils': 5.50.0_4vsywjlpuriuw3tl5oq6zy5a64 - '@typescript-eslint/utils': 5.50.0_4vsywjlpuriuw3tl5oq6zy5a64 + '@typescript-eslint/parser': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm + '@typescript-eslint/scope-manager': 5.52.0 + '@typescript-eslint/type-utils': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm + '@typescript-eslint/utils': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm debug: 4.3.4 - eslint: 8.33.0 + eslint: 8.34.0 grapheme-splitter: 1.0.4 ignore: 5.2.4 natural-compare-lite: 1.4.0 @@ -1164,8 +1095,8 @@ packages: - supports-color dev: true - /@typescript-eslint/parser/5.50.0_4vsywjlpuriuw3tl5oq6zy5a64: - resolution: {integrity: sha512-KCcSyNaogUDftK2G9RXfQyOCt51uB5yqC6pkUYqhYh8Kgt+DwR5M0EwEAxGPy/+DH6hnmKeGsNhiZRQxjH71uQ==} + /@typescript-eslint/parser/5.52.0_7kw3g6rralp5ps6mg3uyzz6azm: + resolution: {integrity: sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -1174,26 +1105,26 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.50.0 - '@typescript-eslint/types': 5.50.0 - '@typescript-eslint/typescript-estree': 5.50.0_typescript@4.9.5 + '@typescript-eslint/scope-manager': 5.52.0 + '@typescript-eslint/types': 5.52.0 + '@typescript-eslint/typescript-estree': 5.52.0_typescript@4.9.5 debug: 4.3.4 - eslint: 8.33.0 + eslint: 8.34.0 typescript: 4.9.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager/5.50.0: - resolution: {integrity: sha512-rt03kaX+iZrhssaT974BCmoUikYtZI24Vp/kwTSy841XhiYShlqoshRFDvN1FKKvU2S3gK+kcBW1EA7kNUrogg==} + /@typescript-eslint/scope-manager/5.52.0: + resolution: {integrity: sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.50.0 - '@typescript-eslint/visitor-keys': 5.50.0 + '@typescript-eslint/types': 5.52.0 + '@typescript-eslint/visitor-keys': 5.52.0 dev: true - /@typescript-eslint/type-utils/5.50.0_4vsywjlpuriuw3tl5oq6zy5a64: - resolution: {integrity: sha512-dcnXfZ6OGrNCO7E5UY/i0ktHb7Yx1fV6fnQGGrlnfDhilcs6n19eIRcvLBqx6OQkrPaFlDPk3OJ0WlzQfrV0bQ==} + /@typescript-eslint/type-utils/5.52.0_7kw3g6rralp5ps6mg3uyzz6azm: + resolution: {integrity: sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -1202,23 +1133,23 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.50.0_typescript@4.9.5 - '@typescript-eslint/utils': 5.50.0_4vsywjlpuriuw3tl5oq6zy5a64 + '@typescript-eslint/typescript-estree': 5.52.0_typescript@4.9.5 + '@typescript-eslint/utils': 5.52.0_7kw3g6rralp5ps6mg3uyzz6azm debug: 4.3.4 - eslint: 8.33.0 + eslint: 8.34.0 tsutils: 3.21.0_typescript@4.9.5 typescript: 4.9.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/types/5.50.0: - resolution: {integrity: sha512-atruOuJpir4OtyNdKahiHZobPKFvZnBnfDiyEaBf6d9vy9visE7gDjlmhl+y29uxZ2ZDgvXijcungGFjGGex7w==} + /@typescript-eslint/types/5.52.0: + resolution: {integrity: sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree/5.50.0_typescript@4.9.5: - resolution: {integrity: sha512-Gq4zapso+OtIZlv8YNAStFtT6d05zyVCK7Fx3h5inlLBx2hWuc/0465C2mg/EQDDU2LKe52+/jN4f0g9bd+kow==} + /@typescript-eslint/typescript-estree/5.52.0_typescript@4.9.5: + resolution: {integrity: sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' @@ -1226,8 +1157,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.50.0 - '@typescript-eslint/visitor-keys': 5.50.0 + '@typescript-eslint/types': 5.52.0 + '@typescript-eslint/visitor-keys': 5.52.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -1238,31 +1169,31 @@ packages: - supports-color dev: true - /@typescript-eslint/utils/5.50.0_4vsywjlpuriuw3tl5oq6zy5a64: - resolution: {integrity: sha512-v/AnUFImmh8G4PH0NDkf6wA8hujNNcrwtecqW4vtQ1UOSNBaZl49zP1SHoZ/06e+UiwzHpgb5zP5+hwlYYWYAw==} + /@typescript-eslint/utils/5.52.0_7kw3g6rralp5ps6mg3uyzz6azm: + resolution: {integrity: sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: '@types/json-schema': 7.0.11 '@types/semver': 7.3.12 - '@typescript-eslint/scope-manager': 5.50.0 - '@typescript-eslint/types': 5.50.0 - '@typescript-eslint/typescript-estree': 5.50.0_typescript@4.9.5 - eslint: 8.33.0 + '@typescript-eslint/scope-manager': 5.52.0 + '@typescript-eslint/types': 5.52.0 + '@typescript-eslint/typescript-estree': 5.52.0_typescript@4.9.5 + eslint: 8.34.0 eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.33.0 + eslint-utils: 3.0.0_eslint@8.34.0 semver: 7.3.8 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/visitor-keys/5.50.0: - resolution: {integrity: sha512-cdMeD9HGu6EXIeGOh2yVW6oGf9wq8asBgZx7nsR/D36gTfQ0odE5kcRYe5M81vjEFAcPeugXrHg78Imu55F6gg==} + /@typescript-eslint/visitor-keys/5.52.0: + resolution: {integrity: sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.50.0 + '@typescript-eslint/types': 5.52.0 eslint-visitor-keys: 3.3.0 dev: true @@ -1276,7 +1207,7 @@ packages: '@babel/core': 7.20.5 '@babel/plugin-transform-typescript': 7.20.2_@babel+core@7.20.5 '@vue/babel-plugin-jsx': 1.1.1_@babel+core@7.20.5 - vite: 4.1.1_@types+node@18.11.18 + vite: 4.1.1_@types+node@18.13.0 vue: 3.2.47 transitivePeerDependencies: - supports-color @@ -1300,17 +1231,17 @@ packages: vite: ^4.0.0 vue: ^3.2.25 dependencies: - vite: 4.1.1_@types+node@18.11.18 + vite: 4.1.1_@types+node@18.13.0 vue: 3.2.47 dev: true - /@vitest/coverage-c8/0.28.3_jsdom@21.1.0: - resolution: {integrity: sha512-3Toi4flNyxwSSYohhV3/euFSyrHjaD9vJVwFVcy84lcRHMEkv0W7pxlqZZeCvPdktN+WETbNazx3WWBs0jqhVQ==} + /@vitest/coverage-c8/0.28.5_jsdom@21.1.0: + resolution: {integrity: sha512-zCNyurjudoG0BAqAgknvlBhkV2V9ZwyYLWOAGtHSDhL/St49MJT+V2p1G0yPaoqBbKOTATVnP5H2p1XL15H75g==} dependencies: c8: 7.12.0 picocolors: 1.0.0 std-env: 3.3.1 - vitest: 0.28.3_jsdom@21.1.0 + vitest: 0.28.5_jsdom@21.1.0 transitivePeerDependencies: - '@edge-runtime/vm' - '@vitest/browser' @@ -1325,30 +1256,30 @@ packages: - terser dev: true - /@vitest/expect/0.28.3: - resolution: {integrity: sha512-dnxllhfln88DOvpAK1fuI7/xHwRgTgR4wdxHldPaoTaBu6Rh9zK5b//v/cjTkhOfNP/AJ8evbNO8H7c3biwd1g==} + /@vitest/expect/0.28.5: + resolution: {integrity: sha512-gqTZwoUTwepwGIatnw4UKpQfnoyV0Z9Czn9+Lo2/jLIt4/AXLTn+oVZxlQ7Ng8bzcNkR+3DqLJ08kNr8jRmdNQ==} dependencies: - '@vitest/spy': 0.28.3 - '@vitest/utils': 0.28.3 + '@vitest/spy': 0.28.5 + '@vitest/utils': 0.28.5 chai: 4.3.7 dev: true - /@vitest/runner/0.28.3: - resolution: {integrity: sha512-P0qYbATaemy1midOLkw7qf8jraJszCoEvjQOSlseiXZyEDaZTZ50J+lolz2hWiWv6RwDu1iNseL9XLsG0Jm2KQ==} + /@vitest/runner/0.28.5: + resolution: {integrity: sha512-NKkHtLB+FGjpp5KmneQjTcPLWPTDfB7ie+MmF1PnUBf/tGe2OjGxWyB62ySYZ25EYp9krR5Bw0YPLS/VWh1QiA==} dependencies: - '@vitest/utils': 0.28.3 + '@vitest/utils': 0.28.5 p-limit: 4.0.0 pathe: 1.1.0 dev: true - /@vitest/spy/0.28.3: - resolution: {integrity: sha512-jULA6suS6CCr9VZfr7/9x97pZ0hC55prnUNHNrg5/q16ARBY38RsjsfhuUXt6QOwvIN3BhSS0QqPzyh5Di8g6w==} + /@vitest/spy/0.28.5: + resolution: {integrity: sha512-7if6rsHQr9zbmvxN7h+gGh2L9eIIErgf8nSKYDlg07HHimCxp4H6I/X/DPXktVPPLQfiZ1Cw2cbDIx9fSqDjGw==} dependencies: tinyspy: 1.0.2 dev: true - /@vitest/utils/0.28.3: - resolution: {integrity: sha512-YHiQEHQqXyIbhDqETOJUKx9/psybF7SFFVCNfOvap0FvyUqbzTSDCa3S5lL4C0CLXkwVZttz9xknDoyHMguFRQ==} + /@vitest/utils/0.28.5: + resolution: {integrity: sha512-UyZdYwdULlOa4LTUSwZ+Paz7nBHGTT72jKwdFSV4IjHF1xsokp+CabMdhjvVhYwkLfO88ylJT46YMilnkSARZA==} dependencies: cli-truncate: 3.1.0 diff: 5.1.0 @@ -1357,43 +1288,43 @@ packages: pretty-format: 27.5.1 dev: true - /@volar/language-core/1.0.24: - resolution: {integrity: sha512-vTN+alJiWwK0Pax6POqrmevbtFW2dXhjwWiW/MW4f48eDYPLdyURWcr8TixO7EN/nHsUBj2udT7igFKPtjyAKg==} + /@volar/language-core/1.2.0-alpha.11: + resolution: {integrity: sha512-OfbPmmFa4LUA8kJCg77V9ud4NASjJ3VKJ79QCQSfHa5SwXeZ5w7lvQe2yILFBjZ3JDB5EfFnHZUSct6ziK3x5Q==} dependencies: - '@volar/source-map': 1.0.24 - muggle-string: 0.1.0 + '@volar/source-map': 1.2.0-alpha.11 dev: true - /@volar/source-map/1.0.24: - resolution: {integrity: sha512-Qsv/tkplx18pgBr8lKAbM1vcDqgkGKQzbChg6NW+v0CZc3G7FLmK+WrqEPzKlN7Cwdc6XVL559Nod8WKAfKr4A==} + /@volar/source-map/1.2.0-alpha.11: + resolution: {integrity: sha512-GCRqcq2bn8Gf9N/qbdl8GgfGbmYuuSIB8arhl+gRZfCIWvT5NhIRVlG5GX0lkgpp02lA8ZYWZ0GLGOkwz7+DMQ==} dependencies: - muggle-string: 0.1.0 + muggle-string: 0.2.2 dev: true - /@volar/typescript/1.0.24: - resolution: {integrity: sha512-f8hCSk+PfKR1/RQHxZ79V1NpDImHoivqoizK+mstphm25tn/YJ/JnKNjZHB+o21fuW0yKlI26NV3jkVb2Cc/7A==} + /@volar/typescript/1.2.0-alpha.11: + resolution: {integrity: sha512-tJ20326E/Xi1lvvuWX57boVJtzhStNF3HjBu4orjl9PqCXUbhqWwP+jRYzyb+nLbHqGPmEBvHKYjAO3GsJ/YXg==} dependencies: - '@volar/language-core': 1.0.24 + '@volar/language-core': 1.2.0-alpha.11 dev: true - /@volar/vue-language-core/1.0.24: - resolution: {integrity: sha512-2NTJzSgrwKu6uYwPqLiTMuAzi7fAY3yFy5PJ255bGJc82If0Xr+cW8pC80vpjG0D/aVLmlwAdO4+Ya2BI8GdDg==} + /@volar/vue-language-core/1.1.0: + resolution: {integrity: sha512-1zTAyeGiyNKYE9s+i3dUpmuvY/Cz1U7LjIh9d5FX3p0NWpaBrzYvSh0gQY+nRaz67or7Y9qYSUCaHLKOmeolzg==} dependencies: - '@volar/language-core': 1.0.24 - '@volar/source-map': 1.0.24 + '@volar/language-core': 1.2.0-alpha.11 + '@volar/source-map': 1.2.0-alpha.11 '@vue/compiler-dom': 3.2.47 '@vue/compiler-sfc': 3.2.47 - '@vue/reactivity': 3.2.45 + '@vue/reactivity': 3.2.47 '@vue/shared': 3.2.47 - minimatch: 5.1.1 + minimatch: 6.2.0 + muggle-string: 0.2.2 vue-template-compiler: 2.7.14 dev: true - /@volar/vue-typescript/1.0.24: - resolution: {integrity: sha512-9a25oHDvGaNC0okRS47uqJI6FxY4hUQZUsxeOUFHcqVxZEv8s17LPuP/pMMXyz7jPygrZubB/qXqHY5jEu/akA==} + /@volar/vue-typescript/1.1.0: + resolution: {integrity: sha512-smtfaePuNpVzXEypJayORtl8muvBdtV1FDWjces1WLYbbtcnmfWtdACW9xY0dkVk0LoE/LZTEmLBCQrRJ6hS1w==} dependencies: - '@volar/typescript': 1.0.24 - '@volar/vue-language-core': 1.0.24 + '@volar/typescript': 1.2.0-alpha.11 + '@volar/vue-language-core': 1.1.0 dev: true /@vue/babel-helper-vue-transform-on/1.0.2: @@ -1405,9 +1336,9 @@ packages: dependencies: '@babel/helper-module-imports': 7.18.6 '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.20.5 - '@babel/template': 7.18.10 - '@babel/traverse': 7.20.5 - '@babel/types': 7.20.5 + '@babel/template': 7.20.7 + '@babel/traverse': 7.20.13 + '@babel/types': 7.20.7 '@vue/babel-helper-vue-transform-on': 1.0.2 camelcase: 6.3.0 html-tags: 3.2.0 @@ -1428,16 +1359,6 @@ packages: vue: 3.2.47 dev: true - /@vue/compiler-core/3.2.45: - resolution: {integrity: sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==} - dependencies: - '@babel/parser': 7.20.13 - '@vue/shared': 3.2.45 - estree-walker: 2.0.2 - source-map: 0.6.1 - dev: false - optional: true - /@vue/compiler-core/3.2.47: resolution: {integrity: sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==} dependencies: @@ -1445,23 +1366,13 @@ packages: '@vue/shared': 3.2.47 estree-walker: 2.0.2 source-map: 0.6.1 - dev: true - - /@vue/compiler-dom/3.2.45: - resolution: {integrity: sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==} - requiresBuild: true - dependencies: - '@vue/compiler-core': 3.2.45 - '@vue/shared': 3.2.45 - dev: false - optional: true /@vue/compiler-dom/3.2.47: resolution: {integrity: sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==} + requiresBuild: true dependencies: '@vue/compiler-core': 3.2.47 '@vue/shared': 3.2.47 - dev: true /@vue/compiler-sfc/3.2.47: resolution: {integrity: sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==} @@ -1476,14 +1387,12 @@ packages: magic-string: 0.25.9 postcss: 8.4.20 source-map: 0.6.1 - dev: true /@vue/compiler-ssr/3.2.47: resolution: {integrity: sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==} dependencies: '@vue/compiler-dom': 3.2.47 '@vue/shared': 3.2.47 - dev: true /@vue/devtools-api/6.2.0: resolution: {integrity: sha512-pF1G4wky+hkifDiZSWn8xfuLOJI1ZXtuambpBEYaf7Xaf6zC/pM29rvAGpd3qaGXnr4BAXU1Pxz/VfvBGwexGA==} @@ -1501,26 +1410,17 @@ packages: '@vue/shared': 3.2.47 estree-walker: 2.0.2 magic-string: 0.25.9 - dev: true - - /@vue/reactivity/3.2.45: - resolution: {integrity: sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==} - dependencies: - '@vue/shared': 3.2.45 - dev: true /@vue/reactivity/3.2.47: resolution: {integrity: sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==} dependencies: '@vue/shared': 3.2.47 - dev: true /@vue/runtime-core/3.2.47: resolution: {integrity: sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==} dependencies: '@vue/reactivity': 3.2.47 '@vue/shared': 3.2.47 - dev: true /@vue/runtime-dom/3.2.47: resolution: {integrity: sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==} @@ -1528,7 +1428,6 @@ packages: '@vue/runtime-core': 3.2.47 '@vue/shared': 3.2.47 csstype: 2.6.20 - dev: true /@vue/server-renderer/3.2.47_vue@3.2.47: resolution: {integrity: sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==} @@ -1538,14 +1437,9 @@ packages: '@vue/compiler-ssr': 3.2.47 '@vue/shared': 3.2.47 vue: 3.2.47 - dev: true - - /@vue/shared/3.2.45: - resolution: {integrity: sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==} /@vue/shared/3.2.47: resolution: {integrity: sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==} - dev: true /abab/2.0.6: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} @@ -1558,16 +1452,16 @@ packages: /acorn-globals/7.0.1: resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} dependencies: - acorn: 8.8.1 + acorn: 8.8.2 acorn-walk: 8.2.0 dev: true - /acorn-jsx/5.3.2_acorn@8.8.1: + /acorn-jsx/5.3.2_acorn@8.8.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - acorn: 8.8.1 + acorn: 8.8.2 dev: true /acorn-walk/8.2.0: @@ -1581,6 +1475,12 @@ packages: hasBin: true dev: true + /acorn/8.8.2: + resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + /agent-base/6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} @@ -1750,7 +1650,7 @@ packages: defu: 6.1.2 dotenv: 16.0.3 giget: 1.0.0 - jiti: 1.16.2 + jiti: 1.17.0 mlly: 1.1.0 pathe: 1.1.0 pkg-types: 1.0.1 @@ -1987,7 +1887,6 @@ packages: /csstype/2.6.20: resolution: {integrity: sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==} - dev: true /data-urls/3.0.2: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} @@ -2396,16 +2295,16 @@ packages: source-map: 0.6.1 dev: true - /eslint-config-prettier/8.6.0_eslint@8.33.0: + /eslint-config-prettier/8.6.0_eslint@8.34.0: resolution: {integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.33.0 + eslint: 8.34.0 dev: true - /eslint-plugin-prettier/4.2.1_jqplj6qf3uqpxpu4gdyhwwasnq: + /eslint-plugin-prettier/4.2.1_u5wnrdwibbfomslmnramz52buy: resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -2416,9 +2315,9 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 8.33.0 - eslint-config-prettier: 8.6.0_eslint@8.33.0 - prettier: 2.8.3 + eslint: 8.34.0 + eslint-config-prettier: 8.6.0_eslint@8.34.0 + prettier: 2.8.4 prettier-linter-helpers: 1.0.0 dev: true @@ -2438,13 +2337,13 @@ packages: estraverse: 5.3.0 dev: true - /eslint-utils/3.0.0_eslint@8.33.0: + /eslint-utils/3.0.0_eslint@8.34.0: resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: - eslint: 8.33.0 + eslint: 8.34.0 eslint-visitor-keys: 2.1.0 dev: true @@ -2458,8 +2357,8 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint/8.33.0: - resolution: {integrity: sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==} + /eslint/8.34.0: + resolution: {integrity: sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: @@ -2474,7 +2373,7 @@ packages: doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.1.1 - eslint-utils: 3.0.0_eslint@8.33.0 + eslint-utils: 3.0.0_eslint@8.34.0 eslint-visitor-keys: 3.3.0 espree: 9.4.0 esquery: 1.4.0 @@ -2485,7 +2384,7 @@ packages: glob-parent: 6.0.2 globals: 13.19.0 grapheme-splitter: 1.0.4 - ignore: 5.2.0 + ignore: 5.2.4 import-fresh: 3.3.0 imurmurhash: 0.1.4 is-glob: 4.0.3 @@ -2510,8 +2409,8 @@ packages: resolution: {integrity: sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.8.1 - acorn-jsx: 5.3.2_acorn@8.8.1 + acorn: 8.8.2 + acorn-jsx: 5.3.2_acorn@8.8.2 eslint-visitor-keys: 3.3.0 dev: true @@ -2882,11 +2781,6 @@ packages: safer-buffer: 2.1.2 dev: true - /ignore/5.2.0: - resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} - engines: {node: '>= 4'} - dev: true - /ignore/5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} @@ -3024,8 +2918,8 @@ packages: istanbul-lib-report: 3.0.0 dev: true - /jiti/1.16.2: - resolution: {integrity: sha512-OKBOVWmU3FxDt/UH4zSwiKPuc1nihFZiOD722FuJlngvLz2glX1v2/TJIgoA4+mrpnXxHV6dSAoCvPcYQtoG5A==} + /jiti/1.17.0: + resolution: {integrity: sha512-CByzPgFqYoB9odEeef7GNmQ3S5THIBOtzRYoSCya2Sv27AuQxy2jgoFjQ6VTF53xsq1MXRm+YWNvOoDHUAteOw==} hasBin: true dev: true @@ -3118,12 +3012,6 @@ packages: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true - /json5/2.2.1: - resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} - engines: {node: '>=6'} - hasBin: true - dev: true - /json5/2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -3159,8 +3047,8 @@ packages: engines: {node: '>=10'} dev: true - /lint-staged/13.1.0: - resolution: {integrity: sha512-pn/sR8IrcF/T0vpWLilih8jmVouMlxqXxKuAojmbiGX5n/gDnz+abdPptlj0vYnbfE0SQNl3CY/HwtM0+yfOVQ==} + /lint-staged/13.1.2: + resolution: {integrity: sha512-K9b4FPbWkpnupvK3WXZLbgu9pchUJ6N7TtVZjbaPsoizkqFUDkUReUL25xdrCljJs7uLUF3tZ7nVPeo/6lp+6w==} engines: {node: ^14.13.1 || >=16.0.0} hasBin: true dependencies: @@ -3201,11 +3089,6 @@ packages: wrap-ansi: 7.0.0 dev: true - /local-pkg/0.4.2: - resolution: {integrity: sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==} - engines: {node: '>=14'} - dev: true - /local-pkg/0.4.3: resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} engines: {node: '>=14'} @@ -3279,7 +3162,6 @@ packages: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} dependencies: sourcemap-codec: 1.4.8 - dev: true /magic-string/0.26.7: resolution: {integrity: sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==} @@ -3295,6 +3177,13 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: true + /magic-string/0.29.0: + resolution: {integrity: sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + /make-dir/3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -3361,8 +3250,8 @@ packages: dependencies: brace-expansion: 2.0.1 - /minimatch/6.1.6: - resolution: {integrity: sha512-6bR3UIeh/DF8+p6A9Spyuy67ShOq42rOkHWi7eUe3Ua99Zo5lZfGC6lJJWkeoK4k9jQFT3Pl7czhTXimG2XheA==} + /minimatch/6.2.0: + resolution: {integrity: sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg==} engines: {node: '>=10'} dependencies: brace-expansion: 2.0.1 @@ -3397,7 +3286,7 @@ packages: /mlly/1.1.0: resolution: {integrity: sha512-cwzBrBfwGC1gYJyfcy8TcZU1f+dbH/T+TuOhtYP2wLv/Fb51/uV7HJQfBPtEupZ2ORLRU1EKFS/QfS3eo9+kBQ==} dependencies: - acorn: 8.8.1 + acorn: 8.8.2 pathe: 1.1.0 pkg-types: 1.0.1 ufo: 1.0.1 @@ -3412,15 +3301,14 @@ packages: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true - /muggle-string/0.1.0: - resolution: {integrity: sha512-Tr1knR3d2mKvvWthlk7202rywKbiOm4rVFLsfAaSIhJ6dt9o47W4S+JMtWhd/PW9Wrdew2/S2fSvhz3E2gkfEg==} + /muggle-string/0.2.2: + resolution: {integrity: sha512-YVE1mIJ4VpUMqZObFndk9CJu6DBJR/GB13p3tXuNbwD4XExaI5EOuRl6BHeIDxIqXZVxSfAC+y6U1Z/IxCfKUg==} dev: true /nanoid/3.3.4: resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - dev: true /natural-compare-lite/1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} @@ -3589,7 +3477,6 @@ packages: /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true /picomatch/2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -3623,7 +3510,6 @@ packages: nanoid: 3.3.4 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: true /postcss/8.4.21: resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} @@ -3655,8 +3541,8 @@ packages: fast-diff: 1.2.0 dev: true - /prettier/2.8.3: - resolution: {integrity: sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==} + /prettier/2.8.4: + resolution: {integrity: sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==} engines: {node: '>=10.13.0'} hasBin: true dev: true @@ -3803,8 +3689,8 @@ packages: fsevents: 2.3.2 dev: true - /rollup/3.12.1: - resolution: {integrity: sha512-t9elERrz2i4UU9z7AwISj3CQcXP39cWxgRWLdf4Tm6aKm1eYrqHIgjzXBgb67GNY1sZckTFFi0oMozh3/S++Ig==} + /rollup/3.15.0: + resolution: {integrity: sha512-F9hrCAhnp5/zx/7HYmftvsNBkMfLfk/dXUh73hPSM2E3CRgap65orDNJbLetoiUFwSAk6iHPLvBrZ5iHYvzqsg==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: @@ -3923,7 +3809,6 @@ packages: /source-map-js/1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - dev: true /source-map-support/0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -3939,7 +3824,6 @@ packages: /sourcemap-codec/1.4.8: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} deprecated: Please use @jridgewell/sourcemap-codec instead - dev: true /stackback/0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -3949,6 +3833,10 @@ packages: resolution: {integrity: sha512-3H20QlwQsSm2OvAxWIYhs+j01MzzqwMwGiiO1NQaJYZgJZFPuAbf95/DiKRBSTYIJ2FeGUc+B/6mPGcWP9dO3Q==} dev: true + /std-env/3.3.2: + resolution: {integrity: sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==} + dev: true + /string-argv/0.3.1: resolution: {integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==} engines: {node: '>=0.6.19'} @@ -4005,7 +3893,7 @@ packages: /strip-literal/1.0.0: resolution: {integrity: sha512-5o4LsH1lzBzO9UFH63AJ2ad2/S2AVx6NtjOcaz+VTT2h1RiRvbipW72z8M/lxEhcPHDBQwpDrnTF7sXy/7OwCQ==} dependencies: - acorn: 8.8.1 + acorn: 8.8.2 dev: true /supports-color/5.5.0: @@ -4171,16 +4059,16 @@ packages: /unctx/2.1.1: resolution: {integrity: sha512-RffJlpvLOtolWsn0fxXsuSDfwiWcR6cyuykw2e0+zAggvGW1SesXt9WxIWlWpJhwVCZD/WlxxLqKLS50Q0CkWA==} dependencies: - acorn: 8.8.1 + acorn: 8.8.2 estree-walker: 3.0.3 magic-string: 0.26.7 - unplugin: 1.0.1 + unplugin: 1.1.0 dev: true - /unimport/2.1.0_rollup@3.12.1: - resolution: {integrity: sha512-GDVIxATluUquX8EqelT6DtnmnZaXGID1jsO9IXwlnxb0OIEqKAxTOnTlnGmHbseoGTh+ZC9kcNDaO18HYQj9KA==} + /unimport/2.2.4_rollup@3.15.0: + resolution: {integrity: sha512-qMgmeEGqqrrmEtm0dqxMG37J6xBtrriqxq9hILvDb+e6l2F0yTnJomLoCCp0eghLR7bYGeBsUU5Y0oyiUYhViw==} dependencies: - '@rollup/pluginutils': 5.0.2_rollup@3.12.1 + '@rollup/pluginutils': 5.0.2_rollup@3.15.0 escape-string-regexp: 5.0.0 fast-glob: 3.2.12 local-pkg: 0.4.3 @@ -4190,7 +4078,7 @@ packages: pkg-types: 1.0.1 scule: 1.0.0 strip-literal: 1.0.0 - unplugin: 1.0.1 + unplugin: 1.1.0 transitivePeerDependencies: - rollup dev: true @@ -4200,8 +4088,8 @@ packages: engines: {node: '>= 4.0.0'} dev: true - /unplugin-vue-components/0.23.0_rollup@3.12.1+vue@3.2.47: - resolution: {integrity: sha512-JAJ+BGvjHvi9P7lICwOzDx2Av+OcI6ZTzvySmjXDNGCNVPrt2NQQmbcp7cW027CR1mRugIX5G//awm3doHyqkg==} + /unplugin-vue-components/0.24.0_rollup@3.15.0+vue@3.2.47: + resolution: {integrity: sha512-U+Pr5StEhlD1LzsJC63f3FoTje3IbqRuSIui9RBnOokowzMM2uK2jZkc1ccLWmhLa8P9qJwEdj93LE/NG83eiw==} engines: {node: '>=14'} peerDependencies: '@babel/parser': ^7.15.8 @@ -4211,26 +4099,26 @@ packages: optional: true dependencies: '@antfu/utils': 0.7.2 - '@nuxt/kit': 3.1.1_rollup@3.12.1 - '@rollup/pluginutils': 5.0.2_rollup@3.12.1 + '@nuxt/kit': 3.2.0_rollup@3.15.0 + '@rollup/pluginutils': 5.0.2_rollup@3.15.0 chokidar: 3.5.3 debug: 4.3.4 fast-glob: 3.2.12 local-pkg: 0.4.3 - magic-string: 0.27.0 - minimatch: 6.1.6 + magic-string: 0.29.0 + minimatch: 6.2.0 resolve: 1.22.1 - unplugin: 1.0.1 + unplugin: 1.1.0 vue: 3.2.47 transitivePeerDependencies: - rollup - supports-color dev: true - /unplugin/1.0.1: - resolution: {integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==} + /unplugin/1.1.0: + resolution: {integrity: sha512-I8obQ8Rs/hnkxokRV6g8JKOQFgYNnTd9DL58vcSt5IJ9AkK8wbrtsnzD5hi4BJlvcY536JzfEXj9L6h7j559/A==} dependencies: - acorn: 8.8.1 + acorn: 8.8.2 chokidar: 3.5.3 webpack-sources: 3.2.3 webpack-virtual-modules: 0.5.0 @@ -4284,8 +4172,8 @@ packages: convert-source-map: 1.8.0 dev: true - /vite-node/0.28.3_@types+node@18.11.18: - resolution: {integrity: sha512-uJJAOkgVwdfCX8PUQhqLyDOpkBS5+j+FdbsXoPVPDlvVjRkb/W/mLYQPSL6J+t8R0UV8tJSe8c9VyxVQNsDSyg==} + /vite-node/0.28.5_@types+node@18.13.0: + resolution: {integrity: sha512-LmXb9saMGlrMZbXTvOveJKwMTBTNUH66c8rJnQ0ZPNX+myPEol64+szRzXtV5ORb0Hb/91yq+/D3oERoyAt6LA==} engines: {node: '>=v14.16.0'} hasBin: true dependencies: @@ -4296,7 +4184,7 @@ packages: picocolors: 1.0.0 source-map: 0.6.1 source-map-support: 0.5.21 - vite: 4.1.1_@types+node@18.11.18 + vite: 4.1.1_@types+node@18.13.0 transitivePeerDependencies: - '@types/node' - less @@ -4331,7 +4219,7 @@ packages: fsevents: 2.3.2 dev: true - /vite/4.1.1_@types+node@18.11.18: + /vite/4.1.1_@types+node@18.13.0: resolution: {integrity: sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -4356,11 +4244,11 @@ packages: terser: optional: true dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 esbuild: 0.16.17 postcss: 8.4.21 resolve: 1.22.1 - rollup: 3.12.1 + rollup: 3.15.0 optionalDependencies: fsevents: 2.3.2 dev: true @@ -4386,8 +4274,8 @@ packages: - stylus dev: true - /vitest/0.28.3_jsdom@21.1.0: - resolution: {integrity: sha512-N41VPNf3VGJlWQizGvl1P5MGyv3ZZA2Zvh+2V8L6tYBAAuqqDK4zExunT1Cdb6dGfZ4gr+IMrnG8d4Z6j9ctPw==} + /vitest/0.28.5_jsdom@21.1.0: + resolution: {integrity: sha512-pyCQ+wcAOX7mKMcBNkzDwEHRGqQvHUl0XnoHR+3Pb1hytAHISgSxv9h0gUiSiYtISXUU3rMrKiKzFYDrI6ZIHA==} engines: {node: '>=v14.16.0'} hasBin: true peerDependencies: @@ -4410,18 +4298,18 @@ packages: dependencies: '@types/chai': 4.3.4 '@types/chai-subset': 1.3.3 - '@types/node': 18.11.18 - '@vitest/expect': 0.28.3 - '@vitest/runner': 0.28.3 - '@vitest/spy': 0.28.3 - '@vitest/utils': 0.28.3 + '@types/node': 18.13.0 + '@vitest/expect': 0.28.5 + '@vitest/runner': 0.28.5 + '@vitest/spy': 0.28.5 + '@vitest/utils': 0.28.5 acorn: 8.8.1 acorn-walk: 8.2.0 cac: 6.7.14 chai: 4.3.7 debug: 4.3.4 jsdom: 21.1.0 - local-pkg: 0.4.2 + local-pkg: 0.4.3 pathe: 1.1.0 picocolors: 1.0.0 source-map: 0.6.1 @@ -4430,8 +4318,8 @@ packages: tinybench: 2.3.1 tinypool: 0.3.1 tinyspy: 1.0.2 - vite: 4.1.1_@types+node@18.11.18 - vite-node: 0.28.3_@types+node@18.11.18 + vite: 4.1.1_@types+node@18.13.0 + vite-node: 0.28.5_@types+node@18.13.0 why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -4466,14 +4354,14 @@ packages: he: 1.2.0 dev: true - /vue-tsc/1.0.24_typescript@4.9.5: - resolution: {integrity: sha512-mmU1s5SAqE1nByQAiQnao9oU4vX+mSdsgI8H57SfKH6UVzq/jP9+Dbi2GaV+0b4Cn361d2ln8m6xeU60ApiEXg==} + /vue-tsc/1.1.0_typescript@4.9.5: + resolution: {integrity: sha512-+JqTcuScA6OfyaVH3ezeCh2i2wRgzUScZ6EdTZ3AW69Nb+rmRyOAxmAjL6MPam8YCdwmmdfAUhmN/BNGVp5vQg==} hasBin: true peerDependencies: typescript: '*' dependencies: - '@volar/vue-language-core': 1.0.24 - '@volar/vue-typescript': 1.0.24 + '@volar/vue-language-core': 1.1.0 + '@volar/vue-typescript': 1.1.0 typescript: 4.9.5 dev: true @@ -4485,7 +4373,6 @@ packages: '@vue/runtime-dom': 3.2.47 '@vue/server-renderer': 3.2.47_vue@3.2.47 '@vue/shared': 3.2.47 - dev: true /vuex/4.1.0_vue@3.2.47: resolution: {integrity: sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==} diff --git a/rollup.config.ts b/rollup.config.ts index a161cdc2a..247378b21 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -25,7 +25,10 @@ function createEntry(options) { 'vue', isEsmBrowser ? '@vue/compiler-dom/dist/compiler-dom.esm-browser' - : '@vue/compiler-dom' + : '@vue/compiler-dom', + isEsmBrowser + ? '@vue/server-renderer/dist/compiler-dom.esm-browser' + : '@vue/server-renderer' ], plugins: [ replace({ @@ -47,7 +50,8 @@ function createEntry(options) { format, globals: { vue: 'Vue', - '@vue/compiler-dom': 'VueCompilerDOM' + '@vue/compiler-dom': 'VueCompilerDOM', + '@vue/server-renderer': 'VueServerRenderer' } } } diff --git a/src/createInstance.ts b/src/createInstance.ts new file mode 100644 index 000000000..0a2779574 --- /dev/null +++ b/src/createInstance.ts @@ -0,0 +1,367 @@ +import { + h, + createApp, + defineComponent, + reactive, + shallowReactive, + isRef, + ref, + AppConfig, + ComponentOptions, + ConcreteComponent, + DefineComponent, + transformVNodeArgs +} from 'vue' + +import { MountingOptions, Slot } from './types' +import { + getComponentsFromStubs, + getDirectivesFromStubs, + isFunctionalComponent, + isObject, + isObjectComponent, + isScriptSetup, + mergeGlobalProperties +} from './utils' +import { processSlot } from './utils/compileSlots' +import { attachEmitListener } from './emit' +import { registerStub } from './stubs' +import { + isLegacyFunctionalComponent, + unwrapLegacyVueExtendComponent +} from './utils/vueCompatSupport' +import { createVNodeTransformer } from './vnodeTransformers/util' +import { + addToDoNotStubComponents, + createStubComponentsTransformer +} from './vnodeTransformers/stubComponentsTransformer' +import { createStubDirectivesTransformer } from './vnodeTransformers/stubDirectivesTransformer' + +const MOUNT_OPTIONS: ReadonlyArray> = [ + 'attachTo', + 'attrs', + 'data', + 'props', + 'slots', + 'global', + 'shallow' +] as const + +function getInstanceOptions( + options: MountingOptions & Record +): Record { + if (options.methods) { + console.warn( + "Passing a `methods` option to mount was deprecated on Vue Test Utils v1, and it won't have any effect on v2. For additional info: https://vue-test-utils.vuejs.org/upgrading-to-v1/#setmethods-and-mountingoptions-methods" + ) + delete options.methods + } + + const resultOptions = { ...options } + for (const key of Object.keys(options)) { + if (MOUNT_OPTIONS.includes(key as keyof MountingOptions)) { + delete resultOptions[key] + } + } + return resultOptions +} + +// implementation +export function createInstance( + inputComponent: DefineComponent<{}, {}, any>, + options?: MountingOptions & Record +) { + // normalize the incoming component + const originalComponent = unwrapLegacyVueExtendComponent(inputComponent) + let component: ConcreteComponent + const instanceOptions = getInstanceOptions(options ?? {}) + + if ( + isFunctionalComponent(originalComponent) || + isLegacyFunctionalComponent(originalComponent) + ) { + component = defineComponent({ + compatConfig: { + MODE: 3, + INSTANCE_LISTENERS: false, + INSTANCE_ATTRS_CLASS_STYLE: false, + COMPONENT_FUNCTIONAL: isLegacyFunctionalComponent(originalComponent) + ? 'suppress-warning' + : false + }, + props: originalComponent.props || {}, + setup: + (props, { attrs, slots }) => + () => + h(originalComponent, { ...props, ...attrs }, slots), + ...instanceOptions + }) + addToDoNotStubComponents(originalComponent) + } else if (isObjectComponent(originalComponent)) { + component = { ...originalComponent, ...instanceOptions } + } else { + component = originalComponent + } + + addToDoNotStubComponents(component) + // We've just replaced our component with its copy + // Let's register it as a stub so user can find it + registerStub({ source: originalComponent, stub: component }) + + const el = document.createElement('div') + + if (options?.attachTo) { + let to: Element | null + if (typeof options.attachTo === 'string') { + to = document.querySelector(options.attachTo) + if (!to) { + throw new Error( + `Unable to find the element matching the selector ${options.attachTo} given as the \`attachTo\` option` + ) + } + } else { + to = options.attachTo + } + + to.appendChild(el) + } + + function slotToFunction(slot: Slot) { + switch (typeof slot) { + case 'function': + return slot + case 'object': + return () => h(slot) + case 'string': + return processSlot(slot) + default: + throw Error(`Invalid slot received.`) + } + } + + // handle any slots passed via mounting options + const slots = + options?.slots && + Object.entries(options.slots).reduce( + ( + acc: { [key: string]: Function }, + [name, slot]: [string, Slot] + ): { [key: string]: Function } => { + if (Array.isArray(slot)) { + const normalized = slot.map(slotToFunction) + acc[name] = (args: unknown) => normalized.map((f) => f(args)) + return acc + } + + acc[name] = slotToFunction(slot) + return acc + }, + {} + ) + + // override component data with mounting options data + if (options?.data) { + const providedData = options.data() + if (isObjectComponent(originalComponent)) { + // component is guaranteed to be the same type as originalComponent + const objectComponent = component as ComponentOptions + const originalDataFn = originalComponent.data || (() => ({})) + objectComponent.data = (vm) => ({ + ...originalDataFn.call(vm, vm), + ...providedData + }) + } else { + throw new Error( + 'data() option is not supported on functional and class components' + ) + } + } + + const MOUNT_COMPONENT_REF = 'VTU_COMPONENT' + // we define props as reactive so that way when we update them with `setProps` + // Vue's reactivity system will cause a rerender. + const refs = shallowReactive>({}) + const props = reactive>({}) + + Object.entries({ + ...options?.attrs, + ...options?.propsData, + ...options?.props, + ref: MOUNT_COMPONENT_REF + }).forEach(([k, v]) => { + if (isRef(v)) { + refs[k] = v + } else { + props[k] = v + } + }) + + const global = mergeGlobalProperties(options?.global) + if (isObjectComponent(component)) { + component.components = { ...component.components, ...global.components } + } + + const componentRef = ref(null) + // create the wrapper component + const Parent = defineComponent({ + name: 'VTU_ROOT', + setup() { + return { + [MOUNT_COMPONENT_REF]: componentRef + } + }, + render() { + return h(component as ComponentOptions, { ...props, ...refs }, slots) + } + }) + + // create the app + const app = createApp(Parent) + // the Parent type must not be stubbed + // but we can't add it directly, as createApp creates a copy + // and store it in app._component (since v3.2.32) + // So we store this one instead + addToDoNotStubComponents(app._component) + + // add tracking for emitted events + // this must be done after `createApp`: https://github.com/vuejs/test-utils/issues/436 + attachEmitListener() + + // global mocks mixin + if (global?.mocks) { + const mixin = defineComponent({ + beforeCreate() { + // we need to differentiate components that are or not not `script setup` + // otherwise we run into a proxy set error + // due to https://github.com/vuejs/core/commit/f73925d76a76ee259749b8b48cb68895f539a00f#diff-ea4d1ddabb7e22e17e80ada458eef70679af4005df2a1a6b73418fec897603ceR404 + // introduced in Vue v3.2.45 + // Also ensures not to include option API components in this block + // since they can also have setup state but need to be patched using + // the regular method. + if (isScriptSetup(this)) { + // add the mocks to setupState + for (const [k, v] of Object.entries( + global.mocks as { [key: string]: any } + )) { + // we do this in a try/catch, as some properties might be read-only + try { + this.$.setupState[k] = v + // eslint-disable-next-line no-empty + } catch (e) {} + } + // also intercept the proxy calls to make the mocks available on the instance + // (useful when a template access a global function like $t and the developer wants to mock it) + ;(this.$ as any).proxy = new Proxy((this.$ as any).proxy, { + get(target, key) { + if (key in global.mocks) { + return global.mocks[key as string] + } + return target[key] + } + }) + } else { + for (const [k, v] of Object.entries( + global.mocks as { [key: string]: any } + )) { + ;(this as any)[k] = v + } + } + } + }) + + app.mixin(mixin) + } + + // AppConfig + if (global.config) { + for (const [k, v] of Object.entries(global.config) as [ + keyof Omit, + any + ][]) { + app.config[k] = isObject(app.config[k]) + ? Object.assign(app.config[k]!, v) + : v + } + } + + // use and plugins from mounting options + if (global.plugins) { + for (const plugin of global.plugins) { + if (Array.isArray(plugin)) { + app.use(plugin[0], ...plugin.slice(1)) + continue + } + app.use(plugin) + } + } + + // use any mixins from mounting options + if (global.mixins) { + for (const mixin of global.mixins) app.mixin(mixin) + } + + if (global.components) { + for (const key of Object.keys(global.components)) { + // avoid registering components that are stubbed twice + if (!(key in global.stubs)) { + app.component(key, global.components[key]) + } + } + } + + if (global.directives) { + for (const key of Object.keys(global.directives)) + app.directive(key, global.directives[key]) + } + + // provide any values passed via provides mounting option + if (global.provide) { + for (const key of Reflect.ownKeys(global.provide)) { + // @ts-ignore: https://github.com/microsoft/TypeScript/issues/1863 + app.provide(key, global.provide[key]) + } + } + + // stubs + // even if we are using `mount`, we will still + // stub out Transition and Transition Group by default. + transformVNodeArgs( + createVNodeTransformer({ + transformers: [ + createStubComponentsTransformer({ + stubs: getComponentsFromStubs(global.stubs), + shallow: options?.shallow, + renderStubDefaultSlot: global.renderStubDefaultSlot + }), + createStubDirectivesTransformer({ + directives: getDirectivesFromStubs(global.stubs) + }) + ] + }) + ) + + // users expect stubs to work with globally registered + // components so we register stubs as global components to avoid + // warning about not being able to resolve component + // + // component implementation provided here will never be called + // but we need name to make sure that stubComponents will + // properly stub this later by matching stub name + // + // ref: https://github.com/vuejs/test-utils/issues/249 + // ref: https://github.com/vuejs/test-utils/issues/425 + if (global?.stubs) { + for (const name of Object.keys(getComponentsFromStubs(global.stubs))) { + if (!app.component(name)) { + app.component(name, { name }) + } + } + } + + return { + app, + el, + props, + componentRef + } +} diff --git a/src/index.ts b/src/index.ts index fa21e292a..7985faf29 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ import { DOMWrapper } from './domWrapper' import { VueWrapper } from './vueWrapper' import BaseWrapper from './baseWrapper' import { mount, shallowMount } from './mount' +import { renderToString } from './renderToString' import { MountingOptions } from './types' import { RouterLinkStub } from './components/RouterLinkStub' import { createWrapperError } from './errorWrapper' @@ -12,6 +13,7 @@ import { enableAutoUnmount, disableAutoUnmount } from './utils/autoUnmount' export { mount, shallowMount, + renderToString, enableAutoUnmount, disableAutoUnmount, RouterLinkStub, diff --git a/src/mount.ts b/src/mount.ts index f8206294f..f74163eb6 100644 --- a/src/mount.ts +++ b/src/mount.ts @@ -1,17 +1,10 @@ import { - h, - createApp, - defineComponent, - reactive, - shallowReactive, - isRef, FunctionalComponent, ComponentPublicInstance, ComponentOptionsWithObjectProps, ComponentOptionsWithArrayProps, ComponentOptionsWithoutProps, ExtractPropTypes, - AppConfig, VNodeProps, ComponentOptionsMixin, DefineComponent, @@ -22,70 +15,15 @@ import { EmitsOptions, ComputedOptions, ComponentPropsOptions, - ComponentOptions, - ConcreteComponent, - Prop, - transformVNodeArgs, - ref + Prop } from 'vue' - -import { MountingOptions, Slot } from './types' -import { - getComponentsFromStubs, - getDirectivesFromStubs, - isScriptSetup, - isFunctionalComponent, - isObject, - isObjectComponent, - mergeGlobalProperties -} from './utils' -import { processSlot } from './utils/compileSlots' +import { MountingOptions } from './types' import { VueWrapper } from './vueWrapper' -import { attachEmitListener } from './emit' -import { createVNodeTransformer } from './vnodeTransformers/util' -import { - createStubComponentsTransformer, - addToDoNotStubComponents -} from './vnodeTransformers/stubComponentsTransformer' -import { createStubDirectivesTransformer } from './vnodeTransformers/stubDirectivesTransformer' -import { - isLegacyFunctionalComponent, - unwrapLegacyVueExtendComponent -} from './utils/vueCompatSupport' import { trackInstance } from './utils/autoUnmount' import { createVueWrapper } from './wrapperFactory' -import { registerStub } from './stubs' +import { createInstance } from './createInstance' // NOTE this should come from `vue` -const MOUNT_OPTIONS: Array> = [ - 'attachTo', - 'attrs', - 'data', - 'props', - 'slots', - 'global', - 'shallow' -] - -function getInstanceOptions( - options: MountingOptions & Record -): Record { - if (options.methods) { - console.warn( - "Passing a `methods` option to mount was deprecated on Vue Test Utils v1, and it won't have any effect on v2. For additional info: https://vue-test-utils.vuejs.org/upgrading-to-v1/#setmethods-and-mountingoptions-methods" - ) - delete options.methods - } - - const resultOptions = { ...options } - for (const key of Object.keys(options)) { - if (MOUNT_OPTIONS.includes(key as keyof MountingOptions)) { - delete resultOptions[key] - } - } - return resultOptions -} - type PublicProps = VNodeProps & AllowedComponentProps & ComponentCustomProps type ComponentMountingOptions = T extends DefineComponent< @@ -310,149 +248,10 @@ export function mount( inputComponent: any, options?: MountingOptions & Record ): VueWrapper { - // normalize the incoming component - const originalComponent = unwrapLegacyVueExtendComponent(inputComponent) - let component: ConcreteComponent - const instanceOptions = getInstanceOptions(options ?? {}) - - if ( - isFunctionalComponent(originalComponent) || - isLegacyFunctionalComponent(originalComponent) - ) { - component = defineComponent({ - compatConfig: { - MODE: 3, - INSTANCE_LISTENERS: false, - INSTANCE_ATTRS_CLASS_STYLE: false, - COMPONENT_FUNCTIONAL: isLegacyFunctionalComponent(originalComponent) - ? 'suppress-warning' - : false - }, - props: originalComponent.props || {}, - setup: - (props, { attrs, slots }) => - () => - h(originalComponent, { ...props, ...attrs }, slots), - ...instanceOptions - }) - addToDoNotStubComponents(originalComponent) - } else if (isObjectComponent(originalComponent)) { - component = { ...originalComponent, ...instanceOptions } - } else { - component = originalComponent - } - - addToDoNotStubComponents(component) - // We've just replaced our component with its copy - // Let's register it as a stub so user can find it - registerStub({ source: originalComponent, stub: component }) - - const el = document.createElement('div') - - if (options?.attachTo) { - let to: Element | null - if (typeof options.attachTo === 'string') { - to = document.querySelector(options.attachTo) - if (!to) { - throw new Error( - `Unable to find the element matching the selector ${options.attachTo} given as the \`attachTo\` option` - ) - } - } else { - to = options.attachTo - } - - to.appendChild(el) - } - - function slotToFunction(slot: Slot) { - switch (typeof slot) { - case 'function': - return slot - case 'object': - return () => h(slot) - case 'string': - return processSlot(slot) - default: - throw Error(`Invalid slot received.`) - } - } - - // handle any slots passed via mounting options - const slots = - options?.slots && - Object.entries(options.slots).reduce( - ( - acc: { [key: string]: Function }, - [name, slot]: [string, Slot] - ): { [key: string]: Function } => { - if (Array.isArray(slot)) { - const normalized = slot.map(slotToFunction) - acc[name] = (args: unknown) => normalized.map((f) => f(args)) - return acc - } - - acc[name] = slotToFunction(slot) - return acc - }, - {} - ) - - // override component data with mounting options data - if (options?.data) { - const providedData = options.data() - if (isObjectComponent(originalComponent)) { - // component is guaranteed to be the same type as originalComponent - const objectComponent = component as ComponentOptions - const originalDataFn = originalComponent.data || (() => ({})) - objectComponent.data = (vm) => ({ - ...originalDataFn.call(vm, vm), - ...providedData - }) - } else { - throw new Error( - 'data() option is not supported on functional and class components' - ) - } - } - - const MOUNT_COMPONENT_REF = 'VTU_COMPONENT' - // we define props as reactive so that way when we update them with `setProps` - // Vue's reactivity system will cause a rerender. - const refs = shallowReactive>({}) - const props = reactive>({}) - - Object.entries({ - ...options?.attrs, - ...options?.propsData, - ...options?.props, - ref: MOUNT_COMPONENT_REF - }).forEach(([k, v]) => { - if (isRef(v)) { - refs[k] = v - } else { - props[k] = v - } - }) - - const global = mergeGlobalProperties(options?.global) - if (isObjectComponent(component)) { - component.components = { ...component.components, ...global.components } - } - - const componentRef = ref(null) - // create the wrapper component - const Parent = defineComponent({ - name: 'VTU_ROOT', - setup() { - return { - [MOUNT_COMPONENT_REF]: componentRef - } - }, - render() { - return h(component as ComponentOptions, { ...props, ...refs }, slots) - } - }) + const { app, props, el, componentRef } = createInstance( + inputComponent, + options + ) const setProps = (newProps: Record) => { for (const [k, v] of Object.entries(newProps)) { @@ -462,149 +261,6 @@ export function mount( return vm.$nextTick() } - // create the app - const app = createApp(Parent) - // the Parent type must not be stubbed - // but we can't add it directly, as createApp creates a copy - // and store it in app._component (since v3.2.32) - // So we store this one instead - addToDoNotStubComponents(app._component) - - // add tracking for emitted events - // this must be done after `createApp`: https://github.com/vuejs/test-utils/issues/436 - attachEmitListener() - - // global mocks mixin - if (global?.mocks) { - const mixin = defineComponent({ - beforeCreate() { - // we need to differentiate components that are or not not `script setup` - // otherwise we run into a proxy set error - // due to https://github.com/vuejs/core/commit/f73925d76a76ee259749b8b48cb68895f539a00f#diff-ea4d1ddabb7e22e17e80ada458eef70679af4005df2a1a6b73418fec897603ceR404 - // introduced in Vue v3.2.45 - // Also ensures not to include option API components in this block - // since they can also have setup state but need to be patched using - // the regular method. - if (isScriptSetup(this)) { - // add the mocks to setupState - for (const [k, v] of Object.entries( - global.mocks as { [key: string]: any } - )) { - // we do this in a try/catch, as some properties might be read-only - try { - this.$.setupState[k] = v - // eslint-disable-next-line no-empty - } catch (e) {} - } - // also intercept the proxy calls to make the mocks available on the instance - // (useful when a template access a global function like $t and the developer wants to mock it) - ;(this.$ as any).proxy = new Proxy((this.$ as any).proxy, { - get(target, key) { - if (key in global.mocks) { - return global.mocks[key as string] - } - return target[key] - } - }) - } else { - for (const [k, v] of Object.entries( - global.mocks as { [key: string]: any } - )) { - ;(this as any)[k] = v - } - } - } - }) - - app.mixin(mixin) - } - - // AppConfig - if (global.config) { - for (const [k, v] of Object.entries(global.config) as [ - keyof Omit, - any - ][]) { - app.config[k] = isObject(app.config[k]) - ? Object.assign(app.config[k]!, v) - : v - } - } - - // use and plugins from mounting options - if (global.plugins) { - for (const plugin of global.plugins) { - if (Array.isArray(plugin)) { - app.use(plugin[0], ...plugin.slice(1)) - continue - } - app.use(plugin) - } - } - - // use any mixins from mounting options - if (global.mixins) { - for (const mixin of global.mixins) app.mixin(mixin) - } - - if (global.components) { - for (const key of Object.keys(global.components)) { - // avoid registering components that are stubbed twice - if (!(key in global.stubs)) { - app.component(key, global.components[key]) - } - } - } - - if (global.directives) { - for (const key of Object.keys(global.directives)) - app.directive(key, global.directives[key]) - } - - // provide any values passed via provides mounting option - if (global.provide) { - for (const key of Reflect.ownKeys(global.provide)) { - // @ts-ignore: https://github.com/microsoft/TypeScript/issues/1863 - app.provide(key, global.provide[key]) - } - } - - // stubs - // even if we are using `mount`, we will still - // stub out Transition and Transition Group by default. - transformVNodeArgs( - createVNodeTransformer({ - transformers: [ - createStubComponentsTransformer({ - stubs: getComponentsFromStubs(global.stubs), - shallow: options?.shallow, - renderStubDefaultSlot: global.renderStubDefaultSlot - }), - createStubDirectivesTransformer({ - directives: getDirectivesFromStubs(global.stubs) - }) - ] - }) - ) - - // users expect stubs to work with globally registered - // components so we register stubs as global components to avoid - // warning about not being able to resolve component - // - // component implementation provided here will never be called - // but we need name to make sure that stubComponents will - // properly stub this later by matching stub name - // - // ref: https://github.com/vuejs/test-utils/issues/249 - // ref: https://github.com/vuejs/test-utils/issues/425 - if (global?.stubs) { - for (const name of Object.keys(getComponentsFromStubs(global.stubs))) { - if (!app.component(name)) { - app.component(name, { name }) - } - } - } - // Workaround for https://github.com/vuejs/core/issues/7020 const originalErrorHandler = app.config.errorHandler diff --git a/src/renderToString.ts b/src/renderToString.ts new file mode 100644 index 000000000..c8aaa335f --- /dev/null +++ b/src/renderToString.ts @@ -0,0 +1,217 @@ +import { renderToString as baseRenderToString } from '@vue/server-renderer' +import { + FunctionalComponent, + ComponentOptionsWithObjectProps, + ComponentOptionsWithArrayProps, + ComponentOptionsWithoutProps, + ExtractPropTypes, + VNodeProps, + ComponentOptionsMixin, + DefineComponent, + MethodOptions, + AllowedComponentProps, + ComponentCustomProps, + ExtractDefaultPropTypes, + EmitsOptions, + ComputedOptions, + ComponentPropsOptions, + Prop +} from 'vue' + +import { MountingOptions } from './types' +import { createInstance } from './createInstance' + +// NOTE this should come from `vue` +type PublicProps = VNodeProps & AllowedComponentProps & ComponentCustomProps + +type ComponentMountingOptions = T extends DefineComponent< + infer PropsOrPropOptions, + any, + infer D, + any, + any +> + ? MountingOptions< + Partial> & + Omit< + Readonly> & PublicProps, + keyof ExtractDefaultPropTypes + >, + D + > & + Record + : MountingOptions + +// Class component (without vue-class-component) - no props +export function renderToString( + originalComponent: { + new (...args: any[]): V + __vccOpts: any + }, + options?: MountingOptions & Record +): Promise + +// Class component (without vue-class-component) - props +export function renderToString( + originalComponent: { + new (...args: any[]): V + __vccOpts: any + defaultProps?: Record> | string[] + }, + options?: MountingOptions

& Record +): Promise + +// Class component - no props +export function renderToString( + originalComponent: { + new (...args: any[]): V + registerHooks(keys: string[]): void + }, + options?: MountingOptions & Record +): Promise + +// Class component - props +export function renderToString( + originalComponent: { + new (...args: any[]): V + props(Props: P): any + registerHooks(keys: string[]): void + }, + options?: MountingOptions

& Record +): Promise + +// Functional component with emits +export function renderToString( + originalComponent: FunctionalComponent, + options?: MountingOptions & Record +): Promise + +// Component declared with defineComponent +export function renderToString< + PropsOrPropOptions = {}, + RawBindings = {}, + D = {}, + C extends ComputedOptions = ComputedOptions, + M extends MethodOptions = MethodOptions, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends EmitsOptions = Record, + EE extends string = string, + PP = PublicProps, + Props = Readonly>, + Defaults extends {} = ExtractDefaultPropTypes +>( + component: DefineComponent< + PropsOrPropOptions, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE, + PP, + Props, + Defaults + >, + options?: MountingOptions< + Partial & Omit, + D + > & + Record +): Promise + +// component declared by vue-tsc ScriptSetup +export function renderToString< + T extends DefineComponent +>(component: T, options?: ComponentMountingOptions): Promise + +// Component declared with no props +export function renderToString< + Props = {}, + RawBindings = {}, + D extends {} = {}, + C extends ComputedOptions = {}, + M extends Record = {}, + E extends EmitsOptions = Record, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + EE extends string = string +>( + componentOptions: ComponentOptionsWithoutProps< + Props, + RawBindings, + D, + C, + M, + E, + Mixin, + Extends, + EE + >, + options?: MountingOptions +): Promise + +// Component declared with { props: [] } +export function renderToString< + PropNames extends string, + RawBindings, + D extends {}, + C extends ComputedOptions = {}, + M extends Record = {}, + E extends EmitsOptions = Record, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + EE extends string = string, + Props extends Readonly<{ [key in PropNames]?: any }> = Readonly<{ + [key in PropNames]?: any + }> +>( + componentOptions: ComponentOptionsWithArrayProps< + PropNames, + RawBindings, + D, + C, + M, + E, + Mixin, + Extends, + EE, + Props + >, + options?: MountingOptions +): Promise + +// Component declared with { props: { ... } } +export function renderToString< + // the Readonly constraint allows TS to treat the type of { required: true } + // as constant instead of boolean. + PropsOptions extends Readonly, + RawBindings, + D extends {}, + C extends ComputedOptions = {}, + M extends Record = {}, + E extends EmitsOptions = Record, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + EE extends string = string +>( + componentOptions: ComponentOptionsWithObjectProps< + PropsOptions, + RawBindings, + D, + C, + M, + E, + Mixin, + Extends, + EE + >, + options?: MountingOptions & PublicProps, D> +): Promise + +export function renderToString(component: any, options?: any): Promise { + const { app } = createInstance(component, options) + return baseRenderToString(app) +} diff --git a/src/utils/autoUnmount.ts b/src/utils/autoUnmount.ts index 5b81fa998..4ce24cd4e 100644 --- a/src/utils/autoUnmount.ts +++ b/src/utils/autoUnmount.ts @@ -9,7 +9,7 @@ export function disableAutoUnmount() { wrapperInstances.length = 0 } -export function enableAutoUnmount(hook: Function) { +export function enableAutoUnmount(hook: (callback: () => void) => void) { if (isEnabled) { throw new Error('enableAutoUnmount cannot be called more than once') } diff --git a/test-dts/renderToString.d-test.ts b/test-dts/renderToString.d-test.ts new file mode 100644 index 000000000..02c8a3361 --- /dev/null +++ b/test-dts/renderToString.d-test.ts @@ -0,0 +1,107 @@ +import { expectError, expectType } from './index' +import { defineComponent } from 'vue' +import { Options, Vue } from 'vue-class-component' +import { renderToString } from '../src' + +const AppWithDefine = defineComponent({ + props: { + a: { + type: String, + required: true + }, + b: Number + }, + template: '' +}) + +// accept props +let html = renderToString(AppWithDefine, { + props: { a: 'Hello', b: 2 } +}) +// html is properly typed +expectType>(html) + +// allow extra props, like using `h()` +renderToString(AppWithDefine, { + props: { a: 'Hello', c: 2 } +}) + +expectError( + // @ts-expect-error wrong prop type should not compile + renderToString(AppWithDefine, { + props: { a: 2 } + }) +) + +const AppWithProps = { + props: { + a: { + type: String, + required: true + } + }, + template: '' +} + +// accept props +expectType>( + renderToString(AppWithProps, { + props: { a: 'Hello' } + }) +) + +// allow extra props, like using `h()` +renderToString(AppWithProps, { + props: { a: 'Hello', b: 2 } +}) + +expectError( + renderToString(AppWithProps, { + // @ts-expect-error wrong prop type should not compile + props: { a: 2 } + }) +) + +const AppWithArrayProps = { + props: ['a'], + template: '' +} + +// accept props +html = renderToString(AppWithArrayProps, { + props: { a: 'Hello' } +}) +expectType>(html) + +// can receive extra props +// as they are declared as `string[]` +renderToString(AppWithArrayProps, { + props: { a: 'Hello', b: 2 } +}) + +const AppWithoutProps = { + template: '' +} + +// allow extra props, like using `h()` +html = renderToString(AppWithoutProps, { + props: { b: 'Hello' } +}) + +// class component +@Options({ + props: { + msg: String + } +}) +class ClassComponent extends Vue { + dataText = '' + get computedMsg(): string { + return `Message: ${(this.$props as any).msg}` + } + + changeMessage(text: string): void { + this.dataText = 'Updated' + } +} +expectType>(renderToString(ClassComponent)) diff --git a/tests/renderToString.spec.ts b/tests/renderToString.spec.ts new file mode 100644 index 000000000..eb1669fae --- /dev/null +++ b/tests/renderToString.spec.ts @@ -0,0 +1,59 @@ +import { describe, it, expect } from 'vitest' +import { defineComponent, onMounted, onServerPrefetch, ref } from 'vue' +import { renderToString } from '../src' + +describe('renderToString', () => { + it('returns a promise', async () => { + const Component = defineComponent({ + template: '

{{ text }}
', + setup() { + return { text: 'Text content' } + } + }) + + const wrapper = await renderToString(Component) + + expect(wrapper).toMatchInlineSnapshot(`"
Text content
"`) + }) + + it('returns correct html on multi root nodes', async () => { + const Component = defineComponent({ + template: '
foo
bar
' + }) + + const wrapper = await renderToString(Component) + + expect(wrapper).toMatchInlineSnapshot( + `"
foo
bar
"` + ) + }) + + it('returns correct html with pre-fetched data on server', async () => { + function fakeFetch(text: string) { + return Promise.resolve(text) + } + + const Component = defineComponent({ + template: '
{{ text }}
', + setup() { + const text = ref(null) + + onServerPrefetch(async () => { + text.value = await fakeFetch('onServerPrefetch') + }) + + onMounted(async () => { + if (!text.value) { + text.value = await fakeFetch('onMounted') + } + }) + + return { text } + } + }) + + const contents = await renderToString(Component) + + expect(contents).toBe('
onServerPrefetch
') + }) +}) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy