diff --git a/.github/workflows/docker-nightly-release.yml b/.github/workflows/docker-nightly-release.yml index 8126d02c..c75d9281 100644 --- a/.github/workflows/docker-nightly-release.yml +++ b/.github/workflows/docker-nightly-release.yml @@ -6,8 +6,26 @@ on: - cron: '0 0 * * *' jobs: + check_date: + runs-on: ubuntu-latest + name: Check latest commit + outputs: + should_run: ${{ steps.should_run.outputs.should_run }} + steps: + - uses: actions/checkout@v2 + - name: print latest_commit + run: echo ${{ github.sha }} + + - id: should_run + continue-on-error: true + name: check latest commit is less than a day + if: ${{ github.event_name == 'schedule' }} + run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "::set-output name=should_run::false" + ci: runs-on: ubuntu-latest + needs: check_date + if: ${{ needs.check_date.outputs.should_run != 'false' }} steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 00000000..13d09495 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,23 @@ +name: E2E tests +on: + pull_request: + push: + branches: + - main +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: corepack enable + - uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'pnpm' + - name: Install dependencies + run: pnpm install + - name: Install Playwright Browsers + run: pnpm exec playwright install --with-deps + - name: Run Playwright tests + run: pnpm exec playwright test diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml new file mode 100644 index 00000000..91306c70 --- /dev/null +++ b/.github/workflows/releases.yml @@ -0,0 +1,48 @@ +name: Release new versions + +on: + push: + tags: + - 'v*.*.*' + +jobs: + docker-release: + runs-on: ubuntu-latest + steps: + - name: Get release version + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV + + - name: Checkout + uses: actions/checkout@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Build and push + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: | + corentinth/it-tools:latest + corentinth/it-tools:${{ env.RELEASE_VERSION }} + ghcr.io/corentinth/it-tools:latest + ghcr.io/corentinth/it-tools:${{ env.RELEASE_VERSION}} diff --git a/.gitignore b/.gitignore index cd1e2011..2cfe718a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,7 @@ coverage *.sln *.sw? -.env \ No newline at end of file +.env +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/README.md b/README.md index 9fdf82be..2f8ee8c2 100644 --- a/README.md +++ b/README.md @@ -10,16 +10,25 @@ You have an idea of a tool? Submit a [feature request](https://github.com/Corent ## Self host -Self host your own version of it-tools in your homelab with docker: +Self host solutions for your homelab + +**From docker hub:** ```sh -docker run -d \ - --name it-tools \ - --restart unless-stopped \ - -p 8080:80 \ - corentinth/it-tools:latest +docker run -d --name it-tools --restart unless-stopped -p 8080:80 corentinth/it-tools:latest ``` +**From github packages:** + +```sh +docker run -d --name it-tools --restart unless-stopped -p 8080:80 ghcr.io/corentinth/it-tools:latest +``` + +**Other solutions:** + +- [Tipi](https://www.runtipi.io/docs/apps-available) +- [Unraid](https://unraid.net/community/apps?q=it-tools) + ## Contribute ### Recommended IDE Setup diff --git a/components.d.ts b/components.d.ts index 8fa004ea..e9290ef4 100644 --- a/components.d.ts +++ b/components.d.ts @@ -12,6 +12,7 @@ declare module '@vue/runtime-core' { CollapsibleToolMenu: typeof import('./src/components/CollapsibleToolMenu.vue')['default'] ColoredCard: typeof import('./src/components/ColoredCard.vue')['default'] FavoriteButton: typeof import('./src/components/FavoriteButton.vue')['default'] + FormatTransformer: typeof import('./src/components/FormatTransformer.vue')['default'] InputCopyable: typeof import('./src/components/InputCopyable.vue')['default'] MenuIconItem: typeof import('./src/components/MenuIconItem.vue')['default'] MenuLayout: typeof import('./src/components/MenuLayout.vue')['default'] diff --git a/package.json b/package.json index bcbb3a07..49148be5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "it-tools", - "version": "2.19.0", + "version": "2023.4.13-dce9ff9", "description": "Collection of handy online tools for developers, with great UX. ", "keywords": [ "productivity", @@ -25,6 +25,7 @@ "preview": "vite preview --port 5050", "test": "npm run test:unit", "test:unit": "vitest --environment jsdom", + "test:e2e": "playwright test", "coverage": "vitest run --coverage", "typecheck": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false", "lint": "eslint src --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --ignore-path .gitignore", @@ -48,7 +49,7 @@ "colord": "^2.9.3", "composerize-ts": "^0.6.2", "cron-validator": "^1.3.1", - "cronstrue": "^2.24.0", + "cronstrue": "^2.26.0", "crypto-js": "^4.1.1", "date-fns": "^2.29.3", "figue": "^1.2.0", @@ -62,8 +63,8 @@ "naive-ui": "^2.34.3", "netmask": "^2.0.2", "node-forge": "^1.3.1", - "oui": "^12.0.51", - "pinia": "^2.0.33", + "oui": "^12.0.52", + "pinia": "^2.0.34", "plausible-tracker": "^0.3.8", "qrcode": "^1.5.1", "randombytes": "^2.1.0", @@ -72,9 +73,11 @@ "ua-parser-js": "^1.0.35", "uuid": "^8.3.2", "vue": "^3.2.47", - "vue-router": "^4.1.6" + "vue-router": "^4.1.6", + "yaml": "^2.2.1" }, "devDependencies": { + "@playwright/test": "^1.32.3", "@rushstack/eslint-patch": "^1.2.0", "@types/bcryptjs": "^2.4.2", "@types/crypto-js": "^4.1.1", @@ -82,15 +85,15 @@ "@types/lodash": "^4.14.192", "@types/mime-types": "^2.1.1", "@types/netmask": "^2.0.0", - "@types/node": "^16.18.22", - "@types/node-forge": "^1.3.1", + "@types/node": "^16.18.23", + "@types/node-forge": "^1.3.2", "@types/prettier": "^2.7.2", "@types/qrcode": "^1.5.0", "@types/randombytes": "^2.0.0", "@types/ua-parser-js": "^0.7.36", "@types/uuid": "^8.3.4", - "@typescript-eslint/parser": "^5.57.0", - "@unocss/eslint-config": "^0.50.6", + "@typescript-eslint/parser": "^5.58.0", + "@unocss/eslint-config": "^0.50.8", "@vitejs/plugin-vue": "^2.3.4", "@vitejs/plugin-vue-jsx": "^1.3.10", "@vue/eslint-config-prettier": "^7.1.0", @@ -98,9 +101,9 @@ "@vue/test-utils": "^2.3.2", "@vue/tsconfig": "^0.1.3", "c8": "^7.13.0", - "eslint": "^8.36.0", + "eslint": "^8.38.0", "eslint-config-prettier": "^8.8.0", - "eslint-import-resolver-typescript": "^3.5.3", + "eslint-import-resolver-typescript": "^3.5.5", "eslint-plugin-import": "^2.27.5", "eslint-plugin-vue": "^8.7.1", "jsdom": "^19.0.0", @@ -109,7 +112,7 @@ "standard-version": "^9.5.0", "start-server-and-test": "^1.15.4", "typescript": "~4.5.5", - "unocss": "^0.50.6", + "unocss": "^0.50.8", "unplugin-auto-import": "^0.15.2", "unplugin-vue-components": "^0.24.1", "vite": "^2.9.15", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 00000000..a445d2d6 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,82 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './src', + testMatch: /.*\.e2e\.(spec\.)?ts/, + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + testIdAttribute: 'data-test-id', + locale: 'en-GB', + timezoneId: 'Europe/Paris', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ..devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'npm run dev', + url: 'http://127.0.0.1:3000', + reuseExistingServer: !process.env.CI, + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f07788b1..f0db977e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,8 +50,8 @@ dependencies: specifier: ^1.3.1 version: 1.3.1 cronstrue: - specifier: ^2.24.0 - version: 2.24.0 + specifier: ^2.26.0 + version: 2.26.0 crypto-js: specifier: ^4.1.1 version: 4.1.1 @@ -92,11 +92,11 @@ dependencies: specifier: ^1.3.1 version: 1.3.1 oui: - specifier: ^12.0.51 - version: 12.0.51 + specifier: ^12.0.52 + version: 12.0.52 pinia: - specifier: ^2.0.33 - version: 2.0.33(typescript@4.5.5)(vue@3.2.47) + specifier: ^2.0.34 + version: 2.0.34(typescript@4.5.5)(vue@3.2.47) plausible-tracker: specifier: ^0.3.8 version: 0.3.8 @@ -124,8 +124,14 @@ dependencies: vue-router: specifier: ^4.1.6 version: 4.1.6(vue@3.2.47) + yaml: + specifier: ^2.2.1 + version: 2.2.1 devDependencies: + '@playwright/test': + specifier: ^1.32.3 + version: 1.32.3 '@rushstack/eslint-patch': specifier: ^1.2.0 version: 1.2.0 @@ -148,11 +154,11 @@ devDependencies: specifier: ^2.0.0 version: 2.0.0 '@types/node': - specifier: ^16.18.22 - version: 16.18.22 + specifier: ^16.18.23 + version: 16.18.23 '@types/node-forge': - specifier: ^1.3.1 - version: 1.3.1 + specifier: ^1.3.2 + version: 1.3.2 '@types/prettier': specifier: ^2.7.2 version: 2.7.2 @@ -169,11 +175,11 @@ devDependencies: specifier: ^8.3.4 version: 8.3.4 '@typescript-eslint/parser': - specifier: ^5.57.0 - version: 5.57.0(eslint@8.36.0)(typescript@4.5.5) + specifier: ^5.58.0 + version: 5.58.0(eslint@8.38.0)(typescript@4.5.5) '@unocss/eslint-config': - specifier: ^0.50.6 - version: 0.50.6(eslint@8.36.0)(typescript@4.5.5) + specifier: ^0.50.8 + version: 0.50.8(eslint@8.38.0)(typescript@4.5.5) '@vitejs/plugin-vue': specifier: ^2.3.4 version: 2.3.4(vite@2.9.15)(vue@3.2.47) @@ -182,34 +188,34 @@ devDependencies: version: 1.3.10 '@vue/eslint-config-prettier': specifier: ^7.1.0 - version: 7.1.0(eslint@8.36.0)(prettier@2.8.7) + version: 7.1.0(eslint@8.38.0)(prettier@2.8.7) '@vue/eslint-config-typescript': specifier: ^10.0.0 - version: 10.0.0(eslint-plugin-vue@8.7.1)(eslint@8.36.0)(typescript@4.5.5) + version: 10.0.0(eslint-plugin-vue@8.7.1)(eslint@8.38.0)(typescript@4.5.5) '@vue/test-utils': specifier: ^2.3.2 version: 2.3.2(vue@3.2.47) '@vue/tsconfig': specifier: ^0.1.3 - version: 0.1.3(@types/node@16.18.22) + version: 0.1.3(@types/node@16.18.23) c8: specifier: ^7.13.0 version: 7.13.0 eslint: - specifier: ^8.36.0 - version: 8.36.0 + specifier: ^8.38.0 + version: 8.38.0 eslint-config-prettier: specifier: ^8.8.0 - version: 8.8.0(eslint@8.36.0) + version: 8.8.0(eslint@8.38.0) eslint-import-resolver-typescript: - specifier: ^3.5.3 - version: 3.5.3(eslint-plugin-import@2.27.5)(eslint@8.36.0) + specifier: ^3.5.5 + version: 3.5.5(@typescript-eslint/parser@5.58.0)(eslint-plugin-import@2.27.5)(eslint@8.38.0) eslint-plugin-import: specifier: ^2.27.5 - version: 2.27.5(@typescript-eslint/parser@5.57.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) + version: 2.27.5(@typescript-eslint/parser@5.58.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.38.0) eslint-plugin-vue: specifier: ^8.7.1 - version: 8.7.1(eslint@8.36.0) + version: 8.7.1(eslint@8.38.0) jsdom: specifier: ^19.0.0 version: 19.0.0 @@ -229,8 +235,8 @@ devDependencies: specifier: ~4.5.5 version: 4.5.5 unocss: - specifier: ^0.50.6 - version: 0.50.6(postcss@8.4.21)(rollup@2.79.1)(vite@2.9.15) + specifier: ^0.50.8 + version: 0.50.8(postcss@8.4.21)(rollup@2.79.1)(vite@2.9.15) unplugin-auto-import: specifier: ^0.15.2 version: 0.15.2(@vueuse/core@8.9.4)(rollup@2.79.1) @@ -261,12 +267,12 @@ devDependencies: packages: - /@ampproject/remapping@2.2.0: - resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} engines: {node: '>=6.0.0'} dependencies: - '@jridgewell/gen-mapping': 0.1.1 - '@jridgewell/trace-mapping': 0.3.17 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 dev: true /@antfu/install-pkg@0.1.1: @@ -312,7 +318,7 @@ packages: resolution: {integrity: sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==} engines: {node: '>=6.9.0'} dependencies: - '@ampproject/remapping': 2.2.0 + '@ampproject/remapping': 2.2.1 '@babel/code-frame': 7.21.4 '@babel/generator': 7.21.4 '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.21.4) @@ -336,8 +342,8 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.21.4 - '@jridgewell/gen-mapping': 0.3.2 - '@jridgewell/trace-mapping': 0.3.17 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 jsesc: 2.5.2 dev: true @@ -410,7 +416,7 @@ packages: '@babel/helper-plugin-utils': 7.20.2 debug: 4.3.4 lodash.debounce: 4.0.8 - resolve: 1.22.1 + resolve: 1.22.2 semver: 6.3.0 transitivePeerDependencies: - supports-color @@ -1417,7 +1423,7 @@ packages: babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.4) babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.21.4) babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.21.4) - core-js-compat: 3.29.1 + core-js-compat: 3.30.0 semver: 6.3.0 transitivePeerDependencies: - supports-color @@ -1530,13 +1536,13 @@ packages: dev: true optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.36.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.38.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.36.0 + eslint: 8.38.0 eslint-visitor-keys: 3.4.0 dev: true @@ -1562,8 +1568,8 @@ packages: - supports-color dev: true - /@eslint/js@8.36.0: - resolution: {integrity: sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==} + /@eslint/js@8.38.0: + resolution: {integrity: sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true @@ -1635,21 +1641,13 @@ packages: resolution: {integrity: sha512-hvPn0mDkbJvA6jDxV3Xw+MIermq+QyrQpUq86KkZXaWLfCIDnLVp3hBmdxpxU4NIckXj5/7eeVg5CvW0kpQBTw==} dev: false - /@jridgewell/gen-mapping@0.1.1: - resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} engines: {node: '>=6.0.0'} dependencies: '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - - /@jridgewell/gen-mapping@0.3.2: - resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.17 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.18 dev: true /@jridgewell/resolve-uri@3.1.0: @@ -1662,19 +1660,23 @@ packages: engines: {node: '>=6.0.0'} dev: true - /@jridgewell/source-map@0.3.2: - resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==} + /@jridgewell/source-map@0.3.3: + resolution: {integrity: sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==} dependencies: - '@jridgewell/gen-mapping': 0.3.2 - '@jridgewell/trace-mapping': 0.3.17 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 dev: true /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} dev: true - /@jridgewell/trace-mapping@0.3.17: - resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.18: + resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} dependencies: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 @@ -1721,6 +1723,17 @@ packages: tslib: 2.5.0 dev: true + /@playwright/test@1.32.3: + resolution: {integrity: sha512-BvWNvK0RfBriindxhLVabi8BRe3X0J9EVjKlcmhxjg4giWBD/xleLcg2dz7Tx0agu28rczjNIPQWznwzDwVsZQ==} + engines: {node: '>=14'} + hasBin: true + dependencies: + '@types/node': 16.18.23 + playwright-core: 1.32.3 + optionalDependencies: + fsevents: 2.3.2 + dev: true + /@polka/url@1.0.0-next.21: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} dev: true @@ -1789,7 +1802,7 @@ packages: builtin-modules: 3.3.0 deepmerge: 4.3.1 is-module: 1.0.0 - resolve: 1.22.1 + resolve: 1.22.2 rollup: 2.79.1 dev: true @@ -2178,7 +2191,7 @@ packages: /@types/jsdom@16.2.15: resolution: {integrity: sha512-nwF87yjBKuX/roqGYerZZM0Nv1pZDMAT5YhOHYeM/72Fic+VEqJh4nyoqoapzJnW3pUlfxPY5FhgsJtM+dRnQQ==} dependencies: - '@types/node': 16.18.22 + '@types/node': 16.18.23 '@types/parse5': 6.0.3 '@types/tough-cookie': 4.0.2 dev: true @@ -2231,14 +2244,14 @@ packages: resolution: {integrity: sha512-6LjGn0BPF0gOHGuRuJ0hGfdBJLz/9K8Ikz+oRThTNc2w7CGLvwqdjAP7/CydsUeL4cxBBXAHLFfC9bMs74757Q==} dev: true - /@types/node-forge@1.3.1: - resolution: {integrity: sha512-hvQ7Wav8I0j9amPXJtGqI/Yx70zeF62UKlAYq8JPm0nHzjKKzZvo9iR3YI2MiOghZRlOI+tQ2f6D+G6vVf4V2Q==} + /@types/node-forge@1.3.2: + resolution: {integrity: sha512-TzX3ahoi9xbmaoT58smrBu7oa6dQXb/+PTNCslZyD/55tlJ/osofIMClzZsoo6buDFrg7e4DvVGkZqVgv6OLxw==} dependencies: - '@types/node': 16.18.22 + '@types/node': 16.18.23 dev: true - /@types/node@16.18.22: - resolution: {integrity: sha512-LJSIirgASa1LicFGTUFwDY7BfKDtLIbijqDLkH47LxEo/jtdrtiZ4/kLPD99bEQhTcPcuh6KhDllHqRxygJD2w==} + /@types/node@16.18.23: + resolution: {integrity: sha512-XAMpaw1s1+6zM+jn2tmw8MyaRDIJfXxqmIQIS0HfoGYPuf7dUWeiUKopwq13KFX9lEp1+THGtlaaYx39Nxr58g==} dev: true /@types/normalize-package-data@2.4.1: @@ -2264,19 +2277,19 @@ packages: /@types/qrcode@1.5.0: resolution: {integrity: sha512-x5ilHXRxUPIMfjtM+1vf/GPTRWZ81nqscursm5gMznJeK9M0YnZ1c3bEvRLQ0zSSgedLx1J6MGL231ObQGGhaA==} dependencies: - '@types/node': 16.18.22 + '@types/node': 16.18.23 dev: true /@types/randombytes@2.0.0: resolution: {integrity: sha512-bz8PhAVlwN72vqefzxa14DKNT8jK/mV66CSjwdVQM/k3Th3EPKfUtdMniwZgMedQTFuywAsfjnZsg+pEnltaMA==} dependencies: - '@types/node': 16.18.22 + '@types/node': 16.18.23 dev: true /@types/resolve@1.17.1: resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: - '@types/node': 16.18.22 + '@types/node': 16.18.23 dev: true /@types/semver@7.3.13: @@ -2306,8 +2319,8 @@ packages: /@types/web-bluetooth@0.0.14: resolution: {integrity: sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A==} - /@typescript-eslint/eslint-plugin@5.57.0(@typescript-eslint/parser@5.57.0)(eslint@8.36.0)(typescript@4.5.5): - resolution: {integrity: sha512-itag0qpN6q2UMM6Xgk6xoHa0D0/P+M17THnr4SVgqn9Rgam5k/He33MA7/D7QoJcdMxHFyX7U9imaBonAX/6qA==} + /@typescript-eslint/eslint-plugin@5.58.0(@typescript-eslint/parser@5.58.0)(eslint@8.38.0)(typescript@4.5.5): + resolution: {integrity: sha512-vxHvLhH0qgBd3/tW6/VccptSfc8FxPQIkmNTVLWcCOVqSBvqpnKkBTYrhcGlXfSnd78azwe+PsjYFj0X34/njA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: '@typescript-eslint/parser': ^5.0.0 @@ -2318,24 +2331,24 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.5.0 - '@typescript-eslint/parser': 5.57.0(eslint@8.36.0)(typescript@4.5.5) - '@typescript-eslint/scope-manager': 5.57.0 - '@typescript-eslint/type-utils': 5.57.0(eslint@8.36.0)(typescript@4.5.5) - '@typescript-eslint/utils': 5.57.0(eslint@8.36.0)(typescript@4.5.5) + '@typescript-eslint/parser': 5.58.0(eslint@8.38.0)(typescript@4.5.5) + '@typescript-eslint/scope-manager': 5.58.0 + '@typescript-eslint/type-utils': 5.58.0(eslint@8.38.0)(typescript@4.5.5) + '@typescript-eslint/utils': 5.58.0(eslint@8.38.0)(typescript@4.5.5) debug: 4.3.4 - eslint: 8.36.0 + eslint: 8.38.0 grapheme-splitter: 1.0.4 ignore: 5.2.4 natural-compare-lite: 1.4.0 - semver: 7.3.8 + semver: 7.4.0 tsutils: 3.21.0(typescript@4.5.5) typescript: 4.5.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@5.57.0(eslint@8.36.0)(typescript@4.5.5): - resolution: {integrity: sha512-orrduvpWYkgLCyAdNtR1QIWovcNZlEm6yL8nwH/eTxWLd8gsP+25pdLHYzL2QdkqrieaDwLpytHqycncv0woUQ==} + /@typescript-eslint/parser@5.58.0(eslint@8.38.0)(typescript@4.5.5): + resolution: {integrity: sha512-ixaM3gRtlfrKzP8N6lRhBbjTow1t6ztfBvQNGuRM8qH1bjFFXIJ35XY+FC0RRBKn3C6cT+7VW1y8tNm7DwPHDQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -2344,26 +2357,26 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.57.0 - '@typescript-eslint/types': 5.57.0 - '@typescript-eslint/typescript-estree': 5.57.0(typescript@4.5.5) + '@typescript-eslint/scope-manager': 5.58.0 + '@typescript-eslint/types': 5.58.0 + '@typescript-eslint/typescript-estree': 5.58.0(typescript@4.5.5) debug: 4.3.4 - eslint: 8.36.0 + eslint: 8.38.0 typescript: 4.5.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager@5.57.0: - resolution: {integrity: sha512-NANBNOQvllPlizl9LatX8+MHi7bx7WGIWYjPHDmQe5Si/0YEYfxSljJpoTyTWFTgRy3X8gLYSE4xQ2U+aCozSw==} + /@typescript-eslint/scope-manager@5.58.0: + resolution: {integrity: sha512-b+w8ypN5CFvrXWQb9Ow9T4/6LC2MikNf1viLkYTiTbkQl46CnR69w7lajz1icW0TBsYmlpg+mRzFJ4LEJ8X9NA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.57.0 - '@typescript-eslint/visitor-keys': 5.57.0 + '@typescript-eslint/types': 5.58.0 + '@typescript-eslint/visitor-keys': 5.58.0 dev: true - /@typescript-eslint/type-utils@5.57.0(eslint@8.36.0)(typescript@4.5.5): - resolution: {integrity: sha512-kxXoq9zOTbvqzLbdNKy1yFrxLC6GDJFE2Yuo3KqSwTmDOFjUGeWSakgoXT864WcK5/NAJkkONCiKb1ddsqhLXQ==} + /@typescript-eslint/type-utils@5.58.0(eslint@8.38.0)(typescript@4.5.5): + resolution: {integrity: sha512-FF5vP/SKAFJ+LmR9PENql7fQVVgGDOS+dq3j+cKl9iW/9VuZC/8CFmzIP0DLKXfWKpRHawJiG70rVH+xZZbp8w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -2372,23 +2385,23 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.57.0(typescript@4.5.5) - '@typescript-eslint/utils': 5.57.0(eslint@8.36.0)(typescript@4.5.5) + '@typescript-eslint/typescript-estree': 5.58.0(typescript@4.5.5) + '@typescript-eslint/utils': 5.58.0(eslint@8.38.0)(typescript@4.5.5) debug: 4.3.4 - eslint: 8.36.0 + eslint: 8.38.0 tsutils: 3.21.0(typescript@4.5.5) typescript: 4.5.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/types@5.57.0: - resolution: {integrity: sha512-mxsod+aZRSyLT+jiqHw1KK6xrANm19/+VFALVFP5qa/aiJnlP38qpyaTd0fEKhWvQk6YeNZ5LGwI1pDpBRBhtQ==} + /@typescript-eslint/types@5.58.0: + resolution: {integrity: sha512-JYV4eITHPzVQMnHZcYJXl2ZloC7thuUHrcUmxtzvItyKPvQ50kb9QXBkgNAt90OYMqwaodQh2kHutWZl1fc+1g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree@5.57.0(typescript@4.5.5): - resolution: {integrity: sha512-LTzQ23TV82KpO8HPnWuxM2V7ieXW8O142I7hQTxWIHDcCEIjtkat6H96PFkYBQqGFLW/G/eVVOB9Z8rcvdY/Vw==} + /@typescript-eslint/typescript-estree@5.58.0(typescript@4.5.5): + resolution: {integrity: sha512-cRACvGTodA+UxnYM2uwA2KCwRL7VAzo45syNysqlMyNyjw0Z35Icc9ihPJZjIYuA5bXJYiJ2YGUB59BqlOZT1Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' @@ -2396,67 +2409,67 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.57.0 - '@typescript-eslint/visitor-keys': 5.57.0 + '@typescript-eslint/types': 5.58.0 + '@typescript-eslint/visitor-keys': 5.58.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.3.8 + semver: 7.4.0 tsutils: 3.21.0(typescript@4.5.5) typescript: 4.5.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@5.57.0(eslint@8.36.0)(typescript@4.5.5): - resolution: {integrity: sha512-ps/4WohXV7C+LTSgAL5CApxvxbMkl9B9AUZRtnEFonpIxZDIT7wC1xfvuJONMidrkB9scs4zhtRyIwHh4+18kw==} + /@typescript-eslint/utils@5.58.0(eslint@8.38.0)(typescript@4.5.5): + resolution: {integrity: sha512-gAmLOTFXMXOC+zP1fsqm3VceKSBQJNzV385Ok3+yzlavNHZoedajjS4UyS21gabJYcobuigQPs/z71A9MdJFqQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.36.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.38.0) '@types/json-schema': 7.0.11 '@types/semver': 7.3.13 - '@typescript-eslint/scope-manager': 5.57.0 - '@typescript-eslint/types': 5.57.0 - '@typescript-eslint/typescript-estree': 5.57.0(typescript@4.5.5) - eslint: 8.36.0 + '@typescript-eslint/scope-manager': 5.58.0 + '@typescript-eslint/types': 5.58.0 + '@typescript-eslint/typescript-estree': 5.58.0(typescript@4.5.5) + eslint: 8.38.0 eslint-scope: 5.1.1 - semver: 7.3.8 + semver: 7.4.0 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/visitor-keys@5.57.0: - resolution: {integrity: sha512-ery2g3k0hv5BLiKpPuwYt9KBkAp2ugT6VvyShXdLOkax895EC55sP0Tx5L0fZaQueiK3fBLvHVvEl3jFS5ia+g==} + /@typescript-eslint/visitor-keys@5.58.0: + resolution: {integrity: sha512-/fBraTlPj0jwdyTwLyrRTxv/3lnU2H96pNTVM6z3esTWLtA5MZ9ghSMJ7Rb+TtUAdtEw9EyJzJ0EydIMKxQ9gA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.57.0 + '@typescript-eslint/types': 5.58.0 eslint-visitor-keys: 3.4.0 dev: true - /@unocss/astro@0.50.6(rollup@2.79.1)(vite@2.9.15): - resolution: {integrity: sha512-gSGQIh+hBCor7KbAylu4wBQaMZp3AkT8dW9E6jrecpluVxzGGdar93a79Wqs76OlWiu7hr8zOyRbSDgfkwDung==} + /@unocss/astro@0.50.8(rollup@2.79.1)(vite@2.9.15): + resolution: {integrity: sha512-kphNlr0PWGzvkCgKx7RaZWQ45khieCCt9OffUnxbRRft+jodsVXIwzHn+bOhGtIKpEpZiOzxRzTYjfW/R6XnTw==} dependencies: - '@unocss/core': 0.50.6 - '@unocss/reset': 0.50.6 - '@unocss/vite': 0.50.6(rollup@2.79.1)(vite@2.9.15) + '@unocss/core': 0.50.8 + '@unocss/reset': 0.50.8 + '@unocss/vite': 0.50.8(rollup@2.79.1)(vite@2.9.15) transitivePeerDependencies: - rollup - vite dev: true - /@unocss/cli@0.50.6(rollup@2.79.1): - resolution: {integrity: sha512-La/KeZCpI7WxuqiUj37K7k/mh08oIGm15u8pkHUs2z+XtFWLemjWPeu84NK3cLgyUGlO2nwpDm2Awye4G1GgCg==} + /@unocss/cli@0.50.8(rollup@2.79.1): + resolution: {integrity: sha512-LBLt8oxGQSfTubOreXs8L7cxHvuYt4wA1MZ45jf4GT/C4moS8cqL7QFX66+MN/cNwvojqXSXQ2HtRJ1IZojfgA==} engines: {node: '>=14'} hasBin: true dependencies: - '@ampproject/remapping': 2.2.0 + '@ampproject/remapping': 2.2.1 '@rollup/pluginutils': 5.0.2(rollup@2.79.1) - '@unocss/config': 0.50.6 - '@unocss/core': 0.50.6 - '@unocss/preset-uno': 0.50.6 + '@unocss/config': 0.50.8 + '@unocss/core': 0.50.8 + '@unocss/preset-uno': 0.50.8 cac: 6.7.14 chokidar: 3.5.3 colorette: 2.0.19 @@ -2469,36 +2482,36 @@ packages: - rollup dev: true - /@unocss/config@0.50.6: - resolution: {integrity: sha512-/IdnXyU4NOQCXBryZsEv9GYAnTvCZ/wmm5mv5ZIPXrS1ZClVbCbnwUxIW08t4EHIX/E9gSFClzXJ52pLBFkZ7g==} + /@unocss/config@0.50.8: + resolution: {integrity: sha512-+Hzl99klLiIq7Lcc5EirTSfBqUH+5NOCmEkXXWcYKYyAk3BLnBU9Fk76P7HxchDwQ5zdwpC4Cq++LQlqbAw/Uw==} engines: {node: '>=14'} dependencies: - '@unocss/core': 0.50.6 + '@unocss/core': 0.50.8 unconfig: 0.3.7 dev: true - /@unocss/core@0.50.6: - resolution: {integrity: sha512-WMIp8xr7YSlID2whqfRGLwagp59e6u4ckPACEpoDOW8sTeSPRZm54hxPhuWXD1SQuqcwHPMtM9nzGD8UOnqQxA==} + /@unocss/core@0.50.8: + resolution: {integrity: sha512-rWmyeNE0Na8dJPDynLVar0X22qMHFNhO+/F2FZDpG4tubTavXJJo9uvhZr/D381kiWxt+XZ38y6EAD4UMdBqMA==} dev: true - /@unocss/eslint-config@0.50.6(eslint@8.36.0)(typescript@4.5.5): - resolution: {integrity: sha512-rhTa88ObLSz+yXXRfR2q9Mzqcm0kzZq/Qqav7P5OOWqKlm1aHz0kBaZKI1uc7EnUpEU0oZcXUzAkxlmMFqgt6g==} + /@unocss/eslint-config@0.50.8(eslint@8.38.0)(typescript@4.5.5): + resolution: {integrity: sha512-dZyXT/LaIioHH1zpHXMo+LyvDNVJq2ZuqhB5x8O70qlhz9jqExiIkTRZyYu68r8SEgZFqjcEBsExTdeuO0Cs3g==} engines: {node: '>=14'} dependencies: - '@unocss/eslint-plugin': 0.50.6(eslint@8.36.0)(typescript@4.5.5) + '@unocss/eslint-plugin': 0.50.8(eslint@8.38.0)(typescript@4.5.5) transitivePeerDependencies: - eslint - supports-color - typescript dev: true - /@unocss/eslint-plugin@0.50.6(eslint@8.36.0)(typescript@4.5.5): - resolution: {integrity: sha512-DIMiHCFxIe0NbXKtfN51q18Ia3NoU79I28rL6uJee4lbcTPfcoPY7VRFihtk8ba+jOjl668yiNgdUMCijg370w==} + /@unocss/eslint-plugin@0.50.8(eslint@8.38.0)(typescript@4.5.5): + resolution: {integrity: sha512-ks8qyPlGHAec96QA6WjTXkpUHs+sgwE5OA7To4MbKrpnKZXdkA7OvNKykkYi/pogV7GKlfQvbKUqELeTig53gQ==} engines: {node: '>=14'} dependencies: - '@typescript-eslint/utils': 5.57.0(eslint@8.36.0)(typescript@4.5.5) - '@unocss/config': 0.50.6 - '@unocss/core': 0.50.6 + '@typescript-eslint/utils': 5.58.0(eslint@8.38.0)(typescript@4.5.5) + '@unocss/config': 0.50.8 + '@unocss/core': 0.50.8 magic-string: 0.30.0 synckit: 0.8.5 transitivePeerDependencies: @@ -2507,129 +2520,135 @@ packages: - typescript dev: true - /@unocss/inspector@0.50.6: - resolution: {integrity: sha512-6nX1YtaL67ohn/PfSSBv3npJ8qZcdc7S9X2zE6PUD/xhwtz7Bohx9I/KtmFdjJz5WeeGR7di0uYC6xsAcFLndQ==} + /@unocss/inspector@0.50.8: + resolution: {integrity: sha512-M963+B9iYGDI7m8KONppJ9EvrDowKWnzzmMLGf+D+qEXmXdnSztMZxEnOdg/caYyHJMw+4jlftyYRZB0VXnAGA==} dependencies: gzip-size: 6.0.0 sirv: 2.0.2 dev: true - /@unocss/postcss@0.50.6(postcss@8.4.21): - resolution: {integrity: sha512-pRPBVPmwjsVu3v1T0hQuqq3L4K74Wobo6pGDypvK/MuzWdWDhHiktWwmXGNxlYSWK7mGJBIa+vI10pp4e15OUw==} + /@unocss/postcss@0.50.8(postcss@8.4.21): + resolution: {integrity: sha512-UbFD+25EkmBonZggKuQdunAU+1O6O83NcnMqSalhn4vhsr4yHeD4P+Omr+CnBcuOxkP4h2JYHzfzdpe4DZxKYg==} engines: {node: '>=14'} peerDependencies: postcss: ^8.4.21 dependencies: - '@unocss/config': 0.50.6 - '@unocss/core': 0.50.6 + '@unocss/config': 0.50.8 + '@unocss/core': 0.50.8 css-tree: 2.3.1 fast-glob: 3.2.12 magic-string: 0.30.0 postcss: 8.4.21 dev: true - /@unocss/preset-attributify@0.50.6: - resolution: {integrity: sha512-hLxBoOnwMLILhJ5fM2AtnjSWej2GffIjTdrAHIBctEy8sLssou5lIbSukDptuGRTSwkishuvQhH020dptB3YJw==} + /@unocss/preset-attributify@0.50.8: + resolution: {integrity: sha512-aSL+I8OSjnom4RpvUcxIRjYETFhW5n51TA56yB9+ex78z5/EhIzOSS5PytGxJWj4hKUY5W9cZ7sCuUs0eaQ6VA==} dependencies: - '@unocss/core': 0.50.6 + '@unocss/core': 0.50.8 dev: true - /@unocss/preset-icons@0.50.6: - resolution: {integrity: sha512-ADnvX8JCThEr2DBiDprTh2q4bfvULbCg9hL5DZIuP9/31FvzNqpAI8xo9KpsCPBoQMksg+GVoXhj1CN2IxLhtg==} + /@unocss/preset-icons@0.50.8: + resolution: {integrity: sha512-tQ05aP7ZRRP39+egB16gFMK6fkEdS8ob4rJeqUG6vEXiiAFWVbotI/NbHQapqk3wRthmyI3d9rUtxClJ2micvw==} dependencies: '@iconify/utils': 2.1.5 - '@unocss/core': 0.50.6 + '@unocss/core': 0.50.8 ofetch: 1.0.1 transitivePeerDependencies: - supports-color dev: true - /@unocss/preset-mini@0.50.6: - resolution: {integrity: sha512-Ejgib688uvzCVgT/DHAOyXxKcM8vX55mxh8m3GAEx1H1pxg0IBfJO4QCKa3uAnasxj27XescBbvqv04dWi+jEQ==} + /@unocss/preset-mini@0.50.8: + resolution: {integrity: sha512-/4sbOdyaqJMvFkw1xzo2+h6bZJHw6WCYw1mF+f0ydHzj8ruvwaj9ClDDOweW5cdrk3wzDzRZ6NPRahKqLwv6/Q==} dependencies: - '@unocss/core': 0.50.6 + '@unocss/core': 0.50.8 dev: true - /@unocss/preset-tagify@0.50.6: - resolution: {integrity: sha512-ZyG/SJMobn4GZMbgrZOxT59ARp22LwgJGArCwJVosh3rraRVlb+B4x6ctMl6JOiLG5B1lHT9vZ92//u51Y0WTw==} + /@unocss/preset-tagify@0.50.8: + resolution: {integrity: sha512-CNm9wEmDGEsCvBgWTBOPhH5ts5iobQh5mBeZyH2uCKuQNX+Vc21tXLX78bCk2V4yJ7mpqUWokDNqgTaNhTZjnw==} dependencies: - '@unocss/core': 0.50.6 + '@unocss/core': 0.50.8 dev: true - /@unocss/preset-typography@0.50.6: - resolution: {integrity: sha512-5WBsvHHVBBNJVoh38GwkJpcfS+JTdi0KuQuTsz6SvhQg+xuth3a6ebhAlrEpdS2G9BL5lpMwBd9SbgvpkE75Og==} + /@unocss/preset-typography@0.50.8: + resolution: {integrity: sha512-jraHusTmbJq9UHgQ43ifzVJobTyoJLuGzeGqBzgLNac+V4BltzqHghup6obA09asQio7xe+crFkTV4IXWNK1lA==} dependencies: - '@unocss/core': 0.50.6 - '@unocss/preset-mini': 0.50.6 + '@unocss/core': 0.50.8 + '@unocss/preset-mini': 0.50.8 dev: true - /@unocss/preset-uno@0.50.6: - resolution: {integrity: sha512-MTuTd49mU8CfKGP/SVMqxNBDEXJmJPes+K6uwZnOsoEwySh1ZrGdApwmIeJurlDEsBiQFQfaSHKHQ25JWVPg3A==} + /@unocss/preset-uno@0.50.8: + resolution: {integrity: sha512-BVgGpv+G9dauX6oRuno8ATOx6bjykiTGuy9NWZCG+/0vux0wplylQm/nSWYsEZZoxRwGOaAoNx93TeOPoofrXQ==} dependencies: - '@unocss/core': 0.50.6 - '@unocss/preset-mini': 0.50.6 - '@unocss/preset-wind': 0.50.6 + '@unocss/core': 0.50.8 + '@unocss/preset-mini': 0.50.8 + '@unocss/preset-wind': 0.50.8 dev: true - /@unocss/preset-web-fonts@0.50.6: - resolution: {integrity: sha512-81meQMAq2lOy7k5qHQZ2EGWN5iJQUJOLl8dc9dxIo1eZPgiZQruxTVr4AkNVH5LRFcjHs/1sDb2CYxAiakwTVg==} + /@unocss/preset-web-fonts@0.50.8: + resolution: {integrity: sha512-diGJVTC3W2lovRL9hlV7h4mdzKjoyJD1rlLai2QMZP/+UCsEwDcL9JFF0lZTlEN5GtcbgvcyPRZKB1/ituvjdg==} dependencies: - '@unocss/core': 0.50.6 + '@unocss/core': 0.50.8 ofetch: 1.0.1 dev: true - /@unocss/preset-wind@0.50.6: - resolution: {integrity: sha512-LU5fAad+okonKfP1eHY5Q63uhoiSstQf4lU7CZ97eZdduqN1ODLzeBegjMGHHi1K2112AvzN/Au0WEPjQFgf7Q==} + /@unocss/preset-wind@0.50.8: + resolution: {integrity: sha512-lF6MAJm2HVF8GJoBIIus1cpZL1ybisj8fl3KYEzVUFUWCwmNnxG4rr+CGnck3bDRYk2zmEvTwX+cISTCwq2u1Q==} dependencies: - '@unocss/core': 0.50.6 - '@unocss/preset-mini': 0.50.6 + '@unocss/core': 0.50.8 + '@unocss/preset-mini': 0.50.8 dev: true - /@unocss/reset@0.50.6: - resolution: {integrity: sha512-e1fuSEgp1p7FgpsIZKNejOKgq4gyZcDGDvi+6544x458hInM6MfiMQNP95UBJEG4JZXq6qCZ8t7tRVWS2m5IXg==} + /@unocss/reset@0.50.8: + resolution: {integrity: sha512-2WoM6O9VyuHDPAnvCXr7LBJQ8ZRHDnuQAFsL1dWXp561Iq2l9whdNtPuMcozLGJGUUrFfVBXIrHY4sfxxScgWg==} dev: true - /@unocss/scope@0.50.6: - resolution: {integrity: sha512-ep1RRJzA3xbVmEcsBYvY8i/LQIfoCFaw1bx9hvGLhdCIdboy58sL4R4GigOukBJiufykKkrLNzFmlIsi3EfJWg==} + /@unocss/scope@0.50.8: + resolution: {integrity: sha512-QA4G9JYK8jrnU02qi1WBi45S+V0HKNUY0u6h5drYqRkcUho2YrpcfMagYi1A5XGg5ykmtP9e6vx1D9lij+JGnQ==} dev: true - /@unocss/transformer-attributify-jsx@0.50.6: - resolution: {integrity: sha512-nXt9Kj9L72ehiDwkzjzxXV4QcV7VS60kP4PXuf+Gp70wE3/19iZl3K3Um/lGo3WHgAYvr91hxBkcyxYBOLUIFA==} + /@unocss/transformer-attributify-jsx-babel@0.50.8: + resolution: {integrity: sha512-Eyt0irFRspHpngj+mDbREuVoqJ49csIhcls6NqerqrZKAI4/jYGNLFy99jyM1ry2L3sHwLP7rbT7AoFrWuLnvA==} dependencies: - '@unocss/core': 0.50.6 + '@unocss/core': 0.50.8 dev: true - /@unocss/transformer-compile-class@0.50.6: - resolution: {integrity: sha512-MWpxO94bq28+HWxniED4BP26aIs5hGhTnaTBkTrisiF8T9xyNPwXaSUobuYkjP1s3ojrXHha8ic0uIXy5OC5nw==} + /@unocss/transformer-attributify-jsx@0.50.8: + resolution: {integrity: sha512-Ht2SfxWbkkFgZQE8KEicmOvxk2INQccuiH4gdyycj3y1tkOXU+Xm1QFruJT7+BPHr0QJp257nA0XmQD/Bhd1kA==} dependencies: - '@unocss/core': 0.50.6 + '@unocss/core': 0.50.8 dev: true - /@unocss/transformer-directives@0.50.6: - resolution: {integrity: sha512-deUJMZDDYQ/kGRFdGe3JrmnbiScs9Smc5Vj35Pr/MNMAM9pItbMwCgZLc+EcHgYNvO5tp0qfA9prPAIs4YpRbg==} + /@unocss/transformer-compile-class@0.50.8: + resolution: {integrity: sha512-2himb5VinZcx7d72nauoqLGk4niC0sFFK/09lmJxFj1jnZqqYBMS48V0PyUypabA5W+bHQ1TJwqcv95wMHIIzA==} dependencies: - '@unocss/core': 0.50.6 + '@unocss/core': 0.50.8 + dev: true + + /@unocss/transformer-directives@0.50.8: + resolution: {integrity: sha512-x/OdR5lK7Gy1Y4r6cOLG2LccWGWDyflz9cDv4DkZKg7pQShcjNFZ3UMAO+74fJO6Jvhvl9iDYpeTZo8009wr7A==} + dependencies: + '@unocss/core': 0.50.8 css-tree: 2.3.1 dev: true - /@unocss/transformer-variant-group@0.50.6: - resolution: {integrity: sha512-eAbJ2Ho1lYaFvpKexqUqixh2TvzcE/DNSIHncr/9Ezo9s06kkHxw4KeIxw//TF26zYP7IJx8l5F58HoSjdKwbQ==} + /@unocss/transformer-variant-group@0.50.8: + resolution: {integrity: sha512-UjDsa3K3Bv11u3q8BYZ4ZrdMhlu937hiQct6sXzFIQcSnOwqOokr/h6V/8aB3hFiPWX/yQuIIQnQJjYTVWZYxw==} dependencies: - '@unocss/core': 0.50.6 + '@unocss/core': 0.50.8 dev: true - /@unocss/vite@0.50.6(rollup@2.79.1)(vite@2.9.15): - resolution: {integrity: sha512-BBfNHWRTD69ToNX4NlYdORFG6uH51HCjX+vZ8HAVgYHpSeVWziG3srnGYOk5IS0pKPzQGoLBlz8rstMsGhrAjA==} + /@unocss/vite@0.50.8(rollup@2.79.1)(vite@2.9.15): + resolution: {integrity: sha512-pHk7D0jHAlBUKSp0y0dMuKesLSSv1O0fTNewUAz1NUpISTno3zizuKSpRs8OzCFInta6QeAVSaWe8K69PcfFog==} peerDependencies: vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 dependencies: - '@ampproject/remapping': 2.2.0 + '@ampproject/remapping': 2.2.1 '@rollup/pluginutils': 5.0.2(rollup@2.79.1) - '@unocss/config': 0.50.6 - '@unocss/core': 0.50.6 - '@unocss/inspector': 0.50.6 - '@unocss/scope': 0.50.6 - '@unocss/transformer-directives': 0.50.6 + '@unocss/config': 0.50.8 + '@unocss/core': 0.50.8 + '@unocss/inspector': 0.50.8 + '@unocss/scope': 0.50.8 + '@unocss/transformer-directives': 0.50.8 chokidar: 3.5.3 fast-glob: 3.2.12 magic-string: 0.30.0 @@ -2726,7 +2745,7 @@ packages: /@vscode/emmet-helper@2.8.6: resolution: {integrity: sha512-IIB8jbiKy37zN8bAIHx59YmnIelY78CGHtThnibD/d3tQOKRY83bYVi9blwmZVUZh6l9nfkYH3tvReaiNxY9EQ==} dependencies: - emmet: 2.4.1 + emmet: 2.4.2 jsonc-parser: 2.3.1 vscode-languageserver-textdocument: 1.0.8 vscode-languageserver-types: 3.17.3 @@ -2747,7 +2766,7 @@ packages: '@babel/types': 7.21.4 '@vue/babel-helper-vue-transform-on': 1.0.2 camelcase: 6.3.0 - html-tags: 3.3.0 + html-tags: 3.3.1 svg-tags: 1.0.0 transitivePeerDependencies: - '@babel/core' @@ -2792,19 +2811,19 @@ packages: resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} dev: false - /@vue/eslint-config-prettier@7.1.0(eslint@8.36.0)(prettier@2.8.7): + /@vue/eslint-config-prettier@7.1.0(eslint@8.38.0)(prettier@2.8.7): resolution: {integrity: sha512-Pv/lVr0bAzSIHLd9iz0KnvAr4GKyCEl+h52bc4e5yWuDVtLgFwycF7nrbWTAQAS+FU6q1geVd07lc6EWfJiWKQ==} peerDependencies: eslint: '>= 7.28.0' prettier: '>= 2.0.0' dependencies: - eslint: 8.36.0 - eslint-config-prettier: 8.8.0(eslint@8.36.0) - eslint-plugin-prettier: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.36.0)(prettier@2.8.7) + eslint: 8.38.0 + eslint-config-prettier: 8.8.0(eslint@8.38.0) + eslint-plugin-prettier: 4.2.1(eslint-config-prettier@8.8.0)(eslint@8.38.0)(prettier@2.8.7) prettier: 2.8.7 dev: true - /@vue/eslint-config-typescript@10.0.0(eslint-plugin-vue@8.7.1)(eslint@8.36.0)(typescript@4.5.5): + /@vue/eslint-config-typescript@10.0.0(eslint-plugin-vue@8.7.1)(eslint@8.38.0)(typescript@4.5.5): resolution: {integrity: sha512-F94cL8ug3FaYXlCfU5/wiGjk1qeadmoBpRGAOBq+qre3Smdupa59dd6ZJrsfRODpsMPyTG7330juMDsUvpZ3Rw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -2815,12 +2834,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/eslint-plugin': 5.57.0(@typescript-eslint/parser@5.57.0)(eslint@8.36.0)(typescript@4.5.5) - '@typescript-eslint/parser': 5.57.0(eslint@8.36.0)(typescript@4.5.5) - eslint: 8.36.0 - eslint-plugin-vue: 8.7.1(eslint@8.36.0) + '@typescript-eslint/eslint-plugin': 5.58.0(@typescript-eslint/parser@5.58.0)(eslint@8.38.0)(typescript@4.5.5) + '@typescript-eslint/parser': 5.58.0(eslint@8.38.0)(typescript@4.5.5) + eslint: 8.38.0 + eslint-plugin-vue: 8.7.1(eslint@8.38.0) typescript: 4.5.5 - vue-eslint-parser: 8.3.0(eslint@8.36.0) + vue-eslint-parser: 8.3.0(eslint@8.38.0) transitivePeerDependencies: - supports-color dev: true @@ -2876,7 +2895,7 @@ packages: '@vue/server-renderer': 3.2.47(vue@3.2.47) dev: true - /@vue/tsconfig@0.1.3(@types/node@16.18.22): + /@vue/tsconfig@0.1.3(@types/node@16.18.23): resolution: {integrity: sha512-kQVsh8yyWPvHpb8gIc9l/HIDiiVUy1amynLNpCy8p+FoCiZXCo6fQos5/097MmnNZc9AtseDsCrfkhqCrJ8Olg==} peerDependencies: '@types/node': '*' @@ -2884,7 +2903,7 @@ packages: '@types/node': optional: true dependencies: - '@types/node': 16.18.22 + '@types/node': 16.18.23 dev: true /@vueuse/core@8.9.4(vue@3.2.47): @@ -3211,7 +3230,7 @@ packages: dependencies: '@babel/core': 7.21.4 '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.21.4) - core-js-compat: 3.29.1 + core-js-compat: 3.30.0 transitivePeerDependencies: - supports-color dev: true @@ -3282,8 +3301,8 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001473 - electron-to-chromium: 1.4.348 + caniuse-lite: 1.0.30001478 + electron-to-chromium: 1.4.360 node-releases: 2.0.10 update-browserslist-db: 1.0.10(browserslist@4.21.5) dev: true @@ -3358,8 +3377,8 @@ packages: engines: {node: '>=10'} dev: true - /caniuse-lite@1.0.30001473: - resolution: {integrity: sha512-ewDad7+D2vlyy+E4UJuVfiBsU69IL+8oVmTuZnH5Q6CIUbxNfI50uVpRHbUPDD6SUaN2o0Lh4DhTrvLG/Tn1yg==} + /caniuse-lite@1.0.30001478: + resolution: {integrity: sha512-gMhDyXGItTHipJj2ApIvR+iVB5hd0KP3svMWWXDvZOmjzJJassGLMfxRkQCSYgGd2gtdL/ReeiyvMSFD1Ss6Mw==} dev: true /capital-case@1.0.4: @@ -3541,7 +3560,7 @@ packages: hasBin: true dependencies: commander: 10.0.0 - deepmerge-ts: 5.0.0 + deepmerge-ts: 5.1.0 flex-js: 1.0.5 ip-cidr: 3.1.0 set-value: 4.1.0 @@ -3762,8 +3781,8 @@ packages: is-what: 3.14.1 dev: true - /core-js-compat@3.29.1: - resolution: {integrity: sha512-QmchCua884D8wWskMX8tW5ydINzd8oSJVx38lx/pVkFGqztxt73GYre3pm/hyYq8bPf+MW5In4I/uRShFDsbrA==} + /core-js-compat@3.30.0: + resolution: {integrity: sha512-P5A2h/9mRYZFIAP+5Ab8ns6083IyVpSclU74UNvbGVQ8VM7n3n3/g2yF3AkKQ9NXz2O+ioxLbEWKnDtgsFamhg==} dependencies: browserslist: 4.21.5 dev: true @@ -3787,8 +3806,8 @@ packages: resolution: {integrity: sha512-C1HsxuPCY/5opR55G5/WNzyEGDWFVG+6GLrA+fW/sCTcP6A6NTjUP2AK7B8n2PyFs90kDG2qzwm8LMheADku6A==} dev: false - /cronstrue@2.24.0: - resolution: {integrity: sha512-A1of24mAGz+OWrdGsxT9BOnDqn2ba182hie8Jx0UcEC2t+ZKtfAJxaFntKUgR7sIisU297fgHBSlNhMIfvAkSA==} + /cronstrue@2.26.0: + resolution: {integrity: sha512-M1VdV3hpBAsd1Zzvqcvf63wgDpcwCuS4WiNEVFpJ0s33MGO2sVDTfswYq0EPypCmESrCzmgL8h68DTzJuSDbVA==} hasBin: true dev: false @@ -3970,8 +3989,8 @@ packages: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true - /deepmerge-ts@5.0.0: - resolution: {integrity: sha512-esq9xUO8+CQCG63IlpkoOBNlpm1m4WBm0NRLFrGL/dcgzqWi1tmTLfG7QTvffqYt6T+dS+xaxrHxdexqGWkV1g==} + /deepmerge-ts@5.1.0: + resolution: {integrity: sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==} engines: {node: '>=16.0.0'} dev: false @@ -4127,12 +4146,12 @@ packages: jake: 10.8.5 dev: true - /electron-to-chromium@1.4.348: - resolution: {integrity: sha512-gM7TdwuG3amns/1rlgxMbeeyNoBFPa+4Uu0c7FeROWh4qWmvSOnvcslKmWy51ggLKZ2n/F/4i2HJ+PVNxH9uCQ==} + /electron-to-chromium@1.4.360: + resolution: {integrity: sha512-EP/jdF15S+l3iSSzgUpUqeazvkbVFXNuVxwwLMVUSie3lUeH1HH70gKe0IS7TASB/0h5QPG2bLMzv2jelSztIQ==} dev: true - /emmet@2.4.1: - resolution: {integrity: sha512-8rZn/3b0WRT21UeGjQ+bzUqg3up6xBKqRjeWRZA1mrzHokNf4brqPx88XQ53+s9lK2p/pWI2VlTIu1S59OwDtA==} + /emmet@2.4.2: + resolution: {integrity: sha512-YgmsMkhUgzhJMgH5noGudfxqrQn1bapvF0y7C1e7A0jWFImsRrrvVslzyZz0919NED/cjFOpVWx7c973V+2S/w==} dependencies: '@emmetio/abbreviation': 2.3.1 '@emmetio/css-abbreviation': 2.1.6 @@ -4488,27 +4507,27 @@ packages: source-map: 0.6.1 dev: true - /eslint-config-prettier@8.8.0(eslint@8.36.0): + /eslint-config-prettier@8.8.0(eslint@8.38.0): resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.36.0 + eslint: 8.38.0 dev: true /eslint-import-resolver-node@0.3.7: resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} dependencies: debug: 3.2.7 - is-core-module: 2.11.0 - resolve: 1.22.1 + is-core-module: 2.12.0 + resolve: 1.22.2 transitivePeerDependencies: - supports-color dev: true - /eslint-import-resolver-typescript@3.5.3(eslint-plugin-import@2.27.5)(eslint@8.36.0): - resolution: {integrity: sha512-njRcKYBc3isE42LaTcJNVANR3R99H9bAxBDMNDr2W7yq5gYPxbU3MkdhsQukxZ/Xg9C2vcyLlDsbKfRDg0QvCQ==} + /eslint-import-resolver-typescript@3.5.5(@typescript-eslint/parser@5.58.0)(eslint-plugin-import@2.27.5)(eslint@8.38.0): + resolution: {integrity: sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -4516,18 +4535,22 @@ packages: dependencies: debug: 4.3.4 enhanced-resolve: 5.12.0 - eslint: 8.36.0 - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.57.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) + eslint: 8.38.0 + eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.58.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.38.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.58.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.38.0) get-tsconfig: 4.5.0 - globby: 13.1.3 - is-core-module: 2.11.0 + globby: 13.1.4 + is-core-module: 2.12.0 is-glob: 4.0.3 synckit: 0.8.5 transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack - supports-color dev: true - /eslint-module-utils@2.7.4(@typescript-eslint/parser@5.57.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0): + /eslint-module-utils@2.7.4(@typescript-eslint/parser@5.58.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.38.0): resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} engines: {node: '>=4'} peerDependencies: @@ -4548,16 +4571,16 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.57.0(eslint@8.36.0)(typescript@4.5.5) + '@typescript-eslint/parser': 5.58.0(eslint@8.38.0)(typescript@4.5.5) debug: 3.2.7 - eslint: 8.36.0 + eslint: 8.38.0 eslint-import-resolver-node: 0.3.7 - eslint-import-resolver-typescript: 3.5.3(eslint-plugin-import@2.27.5)(eslint@8.36.0) + eslint-import-resolver-typescript: 3.5.5(@typescript-eslint/parser@5.58.0)(eslint-plugin-import@2.27.5)(eslint@8.38.0) transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.57.0)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0): + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.58.0)(eslint-import-resolver-typescript@3.5.5)(eslint@8.38.0): resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} engines: {node: '>=4'} peerDependencies: @@ -4567,21 +4590,21 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.57.0(eslint@8.36.0)(typescript@4.5.5) + '@typescript-eslint/parser': 5.58.0(eslint@8.38.0)(typescript@4.5.5) array-includes: 3.1.6 array.prototype.flat: 1.3.1 array.prototype.flatmap: 1.3.1 debug: 3.2.7 doctrine: 2.1.0 - eslint: 8.36.0 + eslint: 8.38.0 eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.57.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.3)(eslint@8.36.0) + eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.58.0)(eslint-import-resolver-node@0.3.7)(eslint-import-resolver-typescript@3.5.5)(eslint@8.38.0) has: 1.0.3 - is-core-module: 2.11.0 + is-core-module: 2.12.0 is-glob: 4.0.3 minimatch: 3.1.2 object.values: 1.1.6 - resolve: 1.22.1 + resolve: 1.22.2 semver: 6.3.0 tsconfig-paths: 3.14.2 transitivePeerDependencies: @@ -4590,7 +4613,7 @@ packages: - supports-color dev: true - /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.8.0)(eslint@8.36.0)(prettier@2.8.7): + /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.8.0)(eslint@8.38.0)(prettier@2.8.7): resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -4601,25 +4624,25 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 8.36.0 - eslint-config-prettier: 8.8.0(eslint@8.36.0) + eslint: 8.38.0 + eslint-config-prettier: 8.8.0(eslint@8.38.0) prettier: 2.8.7 prettier-linter-helpers: 1.0.0 dev: true - /eslint-plugin-vue@8.7.1(eslint@8.36.0): + /eslint-plugin-vue@8.7.1(eslint@8.38.0): resolution: {integrity: sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 dependencies: - eslint: 8.36.0 - eslint-utils: 3.0.0(eslint@8.36.0) + eslint: 8.38.0 + eslint-utils: 3.0.0(eslint@8.38.0) natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.0.11 - semver: 7.3.8 - vue-eslint-parser: 8.3.0(eslint@8.36.0) + semver: 7.4.0 + vue-eslint-parser: 8.3.0(eslint@8.38.0) transitivePeerDependencies: - supports-color dev: true @@ -4640,13 +4663,13 @@ packages: estraverse: 5.3.0 dev: true - /eslint-utils@3.0.0(eslint@8.36.0): + /eslint-utils@3.0.0(eslint@8.38.0): resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: - eslint: 8.36.0 + eslint: 8.38.0 eslint-visitor-keys: 2.1.0 dev: true @@ -4660,15 +4683,15 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint@8.36.0: - resolution: {integrity: sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==} + /eslint@8.38.0: + resolution: {integrity: sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.36.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.38.0) '@eslint-community/regexpp': 4.5.0 '@eslint/eslintrc': 2.0.2 - '@eslint/js': 8.36.0 + '@eslint/js': 8.38.0 '@humanwhocodes/config-array': 0.11.8 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 @@ -5166,8 +5189,8 @@ packages: slash: 3.0.0 dev: true - /globby@13.1.3: - resolution: {integrity: sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==} + /globby@13.1.4: + resolution: {integrity: sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: dir-glob: 3.0.1 @@ -5312,8 +5335,8 @@ packages: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} dev: true - /html-tags@3.3.0: - resolution: {integrity: sha512-mH3dWNbvfCKcAEysbpD7wvtIJ6ImPog8aFhfzqog9gCN8CJFhKjLDtjpohG3IxYRLqHMJ1PWpBvnSMkFJBQ6Jg==} + /html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} engines: {node: '>=8'} dev: true @@ -5486,8 +5509,8 @@ packages: engines: {node: '>= 0.4'} dev: true - /is-core-module@2.11.0: - resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + /is-core-module@2.12.0: + resolution: {integrity: sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==} dependencies: has: 1.0.3 dev: true @@ -5728,7 +5751,7 @@ packages: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 16.18.22 + '@types/node': 16.18.23 merge-stream: 2.0.0 supports-color: 7.2.0 dev: true @@ -5817,7 +5840,7 @@ packages: http-proxy-agent: 5.0.0 https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.2 + nwsapi: 2.2.3 parse5: 6.0.1 saxes: 5.0.1 symbol-tree: 3.2.4 @@ -6113,7 +6136,7 @@ packages: resolution: {integrity: sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==} engines: {node: '>=12'} dependencies: - '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/sourcemap-codec': 1.4.15 dev: true /make-dir@2.1.0: @@ -6274,8 +6297,8 @@ packages: brace-expansion: 2.0.1 dev: true - /minimatch@7.4.5: - resolution: {integrity: sha512-OzOamaOmNBJZUv2qqY1OSWa+++4YPpOkLgkc0w30Oov5ufKlWWXnFUl0l4dgmSv5Shq/zRVkEOXAe2NaqO4l5Q==} + /minimatch@7.4.6: + resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} engines: {node: '>=10'} dependencies: brace-expansion: 2.0.1 @@ -6424,7 +6447,7 @@ packages: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} dependencies: hosted-git-info: 2.8.9 - resolve: 1.22.1 + resolve: 1.22.2 semver: 5.7.1 validate-npm-package-license: 3.0.4 dev: true @@ -6434,8 +6457,8 @@ packages: engines: {node: '>=10'} dependencies: hosted-git-info: 4.1.0 - is-core-module: 2.11.0 - semver: 7.3.8 + is-core-module: 2.12.0 + semver: 7.4.0 validate-npm-package-license: 3.0.4 dev: true @@ -6457,8 +6480,8 @@ packages: boolbase: 1.0.0 dev: true - /nwsapi@2.2.2: - resolution: {integrity: sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==} + /nwsapi@2.2.3: + resolution: {integrity: sha512-jscxIO4/VKScHlbmFBdV1Z6LXnLO+ZR4VMtypudUdfwtKxUN3TQcNFIHLwKtrUbDyHN4/GycY9+oRGZ2XMXYPw==} dev: true /object-assign@4.1.1: @@ -6565,8 +6588,8 @@ packages: resolution: {integrity: sha512-/pIFexOm6S70EPdznemIz3BQZoJ4VTFrhqzu0ACBqBgeLsLxq8e6Jim63ImIfwW/zAD1AlXpRMlOv3aghmo4dA==} dev: false - /oui@12.0.51: - resolution: {integrity: sha512-Orgdrz/wnnwYd9uAA6Dh4dpL7lIDgDKmRtS1vLV37FxbL265u7bESZjxc5ns/OPwcUHYWu9AZVvVcZWKbbpgXQ==} + /oui@12.0.52: + resolution: {integrity: sha512-LqU1oQeGUpMrJ1ZUi7bQKrADD6CMkEe0wpviX/stOZTw4kzEy+yKXVprtVO5O6G4+S6XiTb6BOx6p8fh2o5vyw==} hasBin: true dependencies: char-spinner: 1.0.1 @@ -6769,8 +6792,8 @@ packages: dev: true optional: true - /pinia@2.0.33(typescript@4.5.5)(vue@3.2.47): - resolution: {integrity: sha512-HOj1yVV2itw6rNIrR2f7+MirGNxhORjrULL8GWgRwXsGSvEqIQ+SE0MYt6cwtpegzCda3i+rVTZM+AM7CG+kRg==} + /pinia@2.0.34(typescript@4.5.5)(vue@3.2.47): + resolution: {integrity: sha512-cgOoGUiyqX0SSgX8XelK9+Ri4XA2/YyNtgjogwfzIx1g7iZTaZPxm7/bZYMCLU2qHRiHhxG7SuQO0eBacFNc2Q==} peerDependencies: '@vue/composition-api': ^1.4.0 typescript: '>=4.4.4' @@ -6800,6 +6823,12 @@ packages: engines: {node: '>=10'} dev: false + /playwright-core@1.32.3: + resolution: {integrity: sha512-SB+cdrnu74ZIn5Ogh/8278ngEh9NEEV0vR4sJFmK04h2iZpybfbqBY0bX6+BLYWVdV12JLLI+JEFtSnYgR+mWg==} + engines: {node: '>=14'} + hasBin: true + dev: true + /pngjs@5.0.0: resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} engines: {node: '>=10.13.0'} @@ -7063,7 +7092,7 @@ packages: jstransformer: 1.0.0 pug-error: 2.0.0 pug-walk: 2.0.0 - resolve: 1.22.1 + resolve: 1.22.2 dev: true /pug-lexer@5.0.1: @@ -7308,11 +7337,11 @@ packages: engines: {node: '>=4'} dev: true - /resolve@1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + /resolve@1.22.2: + resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} hasBin: true dependencies: - is-core-module: 2.11.0 + is-core-module: 2.12.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 dev: true @@ -7339,7 +7368,7 @@ packages: jest-worker: 26.6.2 rollup: 2.79.1 serialize-javascript: 4.0.0 - terser: 5.16.8 + terser: 5.16.9 dev: true /rollup@2.77.3: @@ -7435,8 +7464,8 @@ packages: hasBin: true dev: true - /semver@7.3.8: - resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + /semver@7.4.0: + resolution: {integrity: sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==} engines: {node: '>=10'} hasBin: true dependencies: @@ -7624,7 +7653,7 @@ packages: figures: 3.2.0 find-up: 5.0.0 git-semver-tags: 4.1.1 - semver: 7.3.8 + semver: 7.4.0 stringify-package: 1.0.1 yargs: 16.2.0 dev: true @@ -7837,12 +7866,12 @@ packages: unique-string: 2.0.0 dev: true - /terser@5.16.8: - resolution: {integrity: sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA==} + /terser@5.16.9: + resolution: {integrity: sha512-HPa/FdTB9XGI2H1/keLFZHxl6WNvAI4YalHGtDQTlMnJcoqSab1UwL4l1hGEhs6/GmLHBZIg/YgB++jcbzoOEg==} engines: {node: '>=10'} hasBin: true dependencies: - '@jridgewell/source-map': 0.3.2 + '@jridgewell/source-map': 0.3.3 acorn: 8.8.2 commander: 2.20.3 source-map-support: 0.5.21 @@ -8169,33 +8198,34 @@ packages: engines: {node: '>= 10.0.0'} dev: true - /unocss@0.50.6(postcss@8.4.21)(rollup@2.79.1)(vite@2.9.15): - resolution: {integrity: sha512-7cKiIB/ssAPvCDUcFMs0jm0FzIyQKfgIjUzBYZ5dVFthOvN5dcFh7bCZE9dIM862n7oW8FjbkTxwdTbRqqJQVQ==} + /unocss@0.50.8(postcss@8.4.21)(rollup@2.79.1)(vite@2.9.15): + resolution: {integrity: sha512-3yqKkSm/SKCKxFolXNR12Mi64lr4PW95LSHKZ/a9Yzlf2PT1NirAn8/uJ8KoJJBNR2YWobtkLi4UplFz/8IAYA==} engines: {node: '>=14'} peerDependencies: - '@unocss/webpack': 0.50.6 + '@unocss/webpack': 0.50.8 peerDependenciesMeta: '@unocss/webpack': optional: true dependencies: - '@unocss/astro': 0.50.6(rollup@2.79.1)(vite@2.9.15) - '@unocss/cli': 0.50.6(rollup@2.79.1) - '@unocss/core': 0.50.6 - '@unocss/postcss': 0.50.6(postcss@8.4.21) - '@unocss/preset-attributify': 0.50.6 - '@unocss/preset-icons': 0.50.6 - '@unocss/preset-mini': 0.50.6 - '@unocss/preset-tagify': 0.50.6 - '@unocss/preset-typography': 0.50.6 - '@unocss/preset-uno': 0.50.6 - '@unocss/preset-web-fonts': 0.50.6 - '@unocss/preset-wind': 0.50.6 - '@unocss/reset': 0.50.6 - '@unocss/transformer-attributify-jsx': 0.50.6 - '@unocss/transformer-compile-class': 0.50.6 - '@unocss/transformer-directives': 0.50.6 - '@unocss/transformer-variant-group': 0.50.6 - '@unocss/vite': 0.50.6(rollup@2.79.1)(vite@2.9.15) + '@unocss/astro': 0.50.8(rollup@2.79.1)(vite@2.9.15) + '@unocss/cli': 0.50.8(rollup@2.79.1) + '@unocss/core': 0.50.8 + '@unocss/postcss': 0.50.8(postcss@8.4.21) + '@unocss/preset-attributify': 0.50.8 + '@unocss/preset-icons': 0.50.8 + '@unocss/preset-mini': 0.50.8 + '@unocss/preset-tagify': 0.50.8 + '@unocss/preset-typography': 0.50.8 + '@unocss/preset-uno': 0.50.8 + '@unocss/preset-web-fonts': 0.50.8 + '@unocss/preset-wind': 0.50.8 + '@unocss/reset': 0.50.8 + '@unocss/transformer-attributify-jsx': 0.50.8 + '@unocss/transformer-attributify-jsx-babel': 0.50.8 + '@unocss/transformer-compile-class': 0.50.8 + '@unocss/transformer-directives': 0.50.8 + '@unocss/transformer-variant-group': 0.50.8 + '@unocss/vite': 0.50.8(rollup@2.79.1)(vite@2.9.15) transitivePeerDependencies: - postcss - rollup @@ -8220,7 +8250,7 @@ packages: '@vueuse/core': 8.9.4(vue@3.2.47) local-pkg: 0.4.3 magic-string: 0.30.0 - minimatch: 7.4.5 + minimatch: 7.4.6 unimport: 3.0.6(rollup@2.79.1) unplugin: 1.3.1 transitivePeerDependencies: @@ -8247,8 +8277,8 @@ packages: fast-glob: 3.2.12 local-pkg: 0.4.3 magic-string: 0.30.0 - minimatch: 7.4.5 - resolve: 1.22.1 + minimatch: 7.4.6 + resolve: 1.22.2 unplugin: 1.3.1 vue: 3.2.47 transitivePeerDependencies: @@ -8324,7 +8354,7 @@ packages: resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==} engines: {node: '>=10.12.0'} dependencies: - '@jridgewell/trace-mapping': 0.3.17 + '@jridgewell/trace-mapping': 0.3.18 '@types/istanbul-lib-coverage': 2.0.4 convert-source-map: 1.9.0 dev: true @@ -8403,7 +8433,7 @@ packages: esbuild: 0.14.54 less: 4.1.3 postcss: 8.4.21 - resolve: 1.22.1 + resolve: 1.22.2 rollup: 2.77.3 optionalDependencies: fsevents: 2.3.2 @@ -8530,7 +8560,7 @@ packages: deprecated: 'WARNING: This project has been renamed to @volar/typescript-language-service. Install using @volar/typescript-language-service instead.' dependencies: '@volar/shared': 0.31.4 - semver: 7.3.8 + semver: 7.4.0 upath: 2.0.1 vscode-languageserver-protocol: 3.17.3 vscode-languageserver-textdocument: 1.0.8 @@ -8582,20 +8612,20 @@ packages: dependencies: vue: 3.2.47 - /vue-eslint-parser@8.3.0(eslint@8.36.0): + /vue-eslint-parser@8.3.0(eslint@8.38.0): resolution: {integrity: sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=6.0.0' dependencies: debug: 4.3.4 - eslint: 8.36.0 + eslint: 8.38.0 eslint-scope: 7.1.1 eslint-visitor-keys: 3.4.0 espree: 9.5.1 esquery: 1.5.0 lodash: 4.17.21 - semver: 7.3.8 + semver: 7.4.0 transitivePeerDependencies: - supports-color dev: true @@ -9009,6 +9039,11 @@ packages: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true + /yaml@2.2.1: + resolution: {integrity: sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==} + engines: {node: '>= 14'} + dev: false + /yamljs@0.3.0: resolution: {integrity: sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==} hasBin: true diff --git a/scripts/create-tool.mjs b/scripts/create-tool.mjs index 36a20d8e..a6e16f33 100644 --- a/scripts/create-tool.mjs +++ b/scripts/create-tool.mjs @@ -5,6 +5,7 @@ import { fileURLToPath } from 'url'; const currentDirname = dirname(fileURLToPath(import.meta.url)); const toolsDir = join(currentDirname, '..', 'src', 'tools'); +// eslint-disable-next-line no-undef const toolName = process.argv[2]; if (!toolName) { @@ -73,6 +74,28 @@ import { expect, describe, it } from 'vitest'; `, ); +createToolFile( + `${toolName}.e2e.spec.ts`, + ` +import { test, expect } from '@playwright/test'; + +test.describe('Tool - ${toolNameTitleCase}', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/${toolName}'); + }); + + test('Has correct title', async ({ page }) => { + await expect(page).toHaveTitle('${toolNameTitleCase} - IT Tools'); + }); + + test('', async ({ page }) => { + + }); +}); + +`, +); + const toolsIndex = join(toolsDir, 'index.ts'); const indexContent = await readFile(toolsIndex, { encoding: 'utf-8' }).then((r) => r.split('\n')); diff --git a/src/components/FormatTransformer.vue b/src/components/FormatTransformer.vue new file mode 100644 index 00000000..dea5d56a --- /dev/null +++ b/src/components/FormatTransformer.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/src/components/TextareaCopyable.vue b/src/components/TextareaCopyable.vue index 9ad7cf8a..c2a8bdd8 100644 --- a/src/components/TextareaCopyable.vue +++ b/src/components/TextareaCopyable.vue @@ -7,13 +7,13 @@ :style="height ? `min-height: ${height - 40 /* card padding */ + 10 /* negative margin compensation */}px` : ''" > - + diff --git a/src/tools/otp-code-generator-and-validator/otp-code-generator.e2e.spec.ts b/src/tools/otp-code-generator-and-validator/otp-code-generator.e2e.spec.ts new file mode 100644 index 00000000..6188f82f --- /dev/null +++ b/src/tools/otp-code-generator-and-validator/otp-code-generator.e2e.spec.ts @@ -0,0 +1,48 @@ +import { test, expect } from '@playwright/test'; + +test.describe('Tool - OTP code generator', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/otp-generator'); + }); + + test('Has title', async ({ page }) => { + await expect(page).toHaveTitle('OTP code generator - IT Tools'); + }); + + test('Secret hexa value is computed from provided secret', async ({ page }) => { + await page.getByPlaceholder('Paste your TOTP secret...').fill('ITTOOLS'); + + const secretInHex = await page.getByPlaceholder('Secret in hex will be displayed here').inputValue(); + + expect(secretInHex).toEqual('44e6e72e02'); + }); + + test('OTP a generated from the provided secret', async ({ page }) => { + page.evaluate(() => { + Date.now = () => 1609477200000; //Jan 1, 2021 + }); + + await page.getByPlaceholder('Paste your TOTP secret...').fill('ITTOOLS'); + + const previousOtp = await page.getByTestId('previous-otp').innerText(); + const currentOtp = await page.getByTestId('current-otp').innerText(); + const nextOtp = await page.getByTestId('next-otp').innerText(); + + expect(previousOtp.trim()).toEqual('028034'); + expect(currentOtp.trim()).toEqual('162195'); + expect(nextOtp.trim()).toEqual('452815'); + }); + + test('You can generate a new random secret', async ({ page }) => { + const initialSecret = await page.getByPlaceholder('Paste your TOTP secret...').inputValue(); + await page + .locator('div') + .filter({ hasText: /^Secret$/ }) + .getByRole('button') + .click(); + + const newSecret = await page.getByPlaceholder('Paste your TOTP secret...').inputValue(); + + expect(newSecret).not.toEqual(initialSecret); + }); +}); diff --git a/src/tools/otp-code-generator-and-validator/token-display.vue b/src/tools/otp-code-generator-and-validator/token-display.vue index 6ead65c8..ce11ccd5 100644 --- a/src/tools/otp-code-generator-and-validator/token-display.vue +++ b/src/tools/otp-code-generator-and-validator/token-display.vue @@ -8,13 +8,21 @@
{{ previousCopied ? 'Copied !' : 'Copy previous OTP' }}
@@ -22,7 +30,9 @@
{{ nextCopied ? 'Copied !' : 'Copy next OTP' }}
diff --git a/src/tools/roman-numeral-converter/roman-numeral-converter.service.test.ts b/src/tools/roman-numeral-converter/roman-numeral-converter.service.test.ts index 21a747cf..5ec9dd47 100644 --- a/src/tools/roman-numeral-converter/roman-numeral-converter.service.test.ts +++ b/src/tools/roman-numeral-converter/roman-numeral-converter.service.test.ts @@ -13,14 +13,17 @@ describe('roman-numeral-converter', () => { expect(arabicToRoman(0.9)).toEqual(''); }); + it('should convert numbers greater than 3999 to empty string', () => { + expect(arabicToRoman(3999.1)).toEqual(''); + expect(arabicToRoman(4000)).toEqual(''); + expect(arabicToRoman(10000)).toEqual(''); + }); + it('should convert floating points number to the lower integer in roman version', () => { - expect(arabicToRoman(-100)).toEqual(''); - expect(arabicToRoman(-42)).toEqual(''); - expect(arabicToRoman(-26)).toEqual(''); - expect(arabicToRoman(-10)).toEqual(''); - expect(arabicToRoman(0)).toEqual(''); - expect(arabicToRoman(0.5)).toEqual(''); - expect(arabicToRoman(0.9)).toEqual(''); + expect(arabicToRoman(1.1)).toEqual('I'); + expect(arabicToRoman(1.9)).toEqual('I'); + expect(arabicToRoman(17.6)).toEqual('XVII'); + expect(arabicToRoman(29.999)).toEqual('XXIX'); }); it('should convert positive integers to roman numbers', () => { @@ -67,7 +70,6 @@ describe('roman-numeral-converter', () => { expect(arabicToRoman(999)).toEqual('CMXCIX'); expect(arabicToRoman(1000)).toEqual('M'); expect(arabicToRoman(2000)).toEqual('MM'); - expect(arabicToRoman(9000)).toEqual('MMMMMMMMM'); }); }); }); diff --git a/src/tools/roman-numeral-converter/roman-numeral-converter.service.ts b/src/tools/roman-numeral-converter/roman-numeral-converter.service.ts index df2408a0..98afec67 100644 --- a/src/tools/roman-numeral-converter/roman-numeral-converter.service.ts +++ b/src/tools/roman-numeral-converter/roman-numeral-converter.service.ts @@ -1,5 +1,7 @@ +export const MIN_ARABIC_TO_ROMAN = 1; +export const MAX_ARABIC_TO_ROMAN = 3999; export function arabicToRoman(num: number) { - if (num < 1) return ''; + if (num < MIN_ARABIC_TO_ROMAN || num > MAX_ARABIC_TO_ROMAN) return ''; const lookup: { [key: string]: number } = { M: 1000, @@ -26,7 +28,16 @@ export function arabicToRoman(num: number) { return roman; } +const ROMAN_NUMBER_REGEX = new RegExp(/^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/); + +export function isValidRomanNumber(romanNumber: string) { + return ROMAN_NUMBER_REGEX.test(romanNumber); +} + export function romanToArabic(s: string) { + if (!isValidRomanNumber(s)) { + return null; + } const map: { [key: string]: number } = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 }; return [...s].reduce((r, c, i, s) => (map[s[i + 1]] > map[c] ? r - map[c] : r + map[c]), 0); } diff --git a/src/tools/roman-numeral-converter/roman-numeral-converter.vue b/src/tools/roman-numeral-converter/roman-numeral-converter.vue index c55380d0..609b46c4 100644 --- a/src/tools/roman-numeral-converter/roman-numeral-converter.vue +++ b/src/tools/roman-numeral-converter/roman-numeral-converter.vue @@ -2,21 +2,29 @@
- + + +
{{ outputRoman }}
- Copy + + Copy +

- + + +
{{ outputNumeral }}
- Copy + + Copy +
@@ -25,14 +33,41 @@ diff --git a/src/tools/token-generator/token-generator.e2e.spec.ts b/src/tools/token-generator/token-generator.e2e.spec.ts new file mode 100644 index 00000000..905a81cc --- /dev/null +++ b/src/tools/token-generator/token-generator.e2e.spec.ts @@ -0,0 +1,19 @@ +import { test, expect } from '@playwright/test'; + +test.describe('Tool - Token generator', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/token-generator'); + }); + + test('Has title', async ({ page }) => { + await expect(page).toHaveTitle('Token generator - IT Tools'); + }); + + test('New token on refresh', async ({ page }) => { + const initialToken = await page.getByPlaceholder('The token...').inputValue(); + await page.getByRole('button', { name: 'Refresh' }).click(); + const newToken = await page.getByPlaceholder('The token...').inputValue(); + + expect(newToken).not.toEqual(initialToken); + }); +}); diff --git a/src/tools/tool.ts b/src/tools/tool.ts index a5d157e9..3bf4e4cc 100644 --- a/src/tools/tool.ts +++ b/src/tools/tool.ts @@ -1,17 +1,10 @@ -import { config } from '@/config'; import { isAfter, subWeeks } from 'date-fns'; import type { Tool } from './tools.types'; type WithOptional = Omit & Partial>; -export function defineTool( - tool: WithOptional, - { newTools }: { newTools: string[] } = { newTools: config.tools.newTools }, -) { - const isInNewToolConfig = newTools.includes(tool.name); - const isRecentTool = tool.createdAt ? isAfter(tool.createdAt, subWeeks(new Date(), 2)) : false; - - const isNew = isInNewToolConfig || isRecentTool; +export function defineTool(tool: WithOptional) { + const isNew = tool.createdAt ? isAfter(tool.createdAt, subWeeks(new Date(), 2)) : false; return { isNew, diff --git a/src/tools/yaml-to-json-converter/index.ts b/src/tools/yaml-to-json-converter/index.ts new file mode 100644 index 00000000..724ecdb7 --- /dev/null +++ b/src/tools/yaml-to-json-converter/index.ts @@ -0,0 +1,12 @@ +import { AlignJustified } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'YAML to JSON converter', + path: '/yaml-to-json-converter', + description: 'Simply convert YAML to JSON with this live online converter.', + keywords: ['yaml', 'to', 'json'], + component: () => import('./yaml-to-json.vue'), + icon: AlignJustified, + createdAt: new Date('2023-04-10'), +}); diff --git a/src/tools/yaml-to-json-converter/yaml-to-json.e2e.spec.ts b/src/tools/yaml-to-json-converter/yaml-to-json.e2e.spec.ts new file mode 100644 index 00000000..10db4495 --- /dev/null +++ b/src/tools/yaml-to-json-converter/yaml-to-json.e2e.spec.ts @@ -0,0 +1,31 @@ +import { test, expect } from '@playwright/test'; + +test.describe('Tool - Yaml to json', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/yaml-to-json-converter'); + }); + + test('Has correct title', async ({ page }) => { + await expect(page).toHaveTitle('YAML to JSON converter - IT Tools'); + }); + + test('Yaml is parsed and output clean json', async ({ page }) => { + await page.getByTestId('input').fill('foo: bar\nlist:\n - item\n - key: value'); + + const generatedJson = await page.getByTestId('area-content').innerText(); + + expect(generatedJson.trim()).toEqual( + ` +{ + "foo": "bar", + "list": [ + "item", + { + "key": "value" + } + ] +} + `.trim(), + ); + }); +}); diff --git a/src/tools/yaml-to-json-converter/yaml-to-json.vue b/src/tools/yaml-to-json-converter/yaml-to-json.vue new file mode 100644 index 00000000..c066bdd5 --- /dev/null +++ b/src/tools/yaml-to-json-converter/yaml-to-json.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/utils/macAddress.ts b/src/utils/macAddress.ts new file mode 100644 index 00000000..ff6000cb --- /dev/null +++ b/src/utils/macAddress.ts @@ -0,0 +1,16 @@ +import { useValidation } from '@/composable/validation'; +import type { Ref } from 'vue'; + +function macAddressValidation(value: Ref) { + return useValidation({ + source: value, + rules: [ + { + message: 'Invalid MAC address', + validator: (value) => value.trim().match(/^([0-9A-Fa-f]{2}[:-]){2,5}([0-9A-Fa-f]{2})$/), + }, + ], + }); +} + +export { macAddressValidation }; diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 00000000..1c0d1e52 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,13 @@ +import { configDefaults, defineConfig } from 'vitest/config'; +import path from 'path'; + +export default defineConfig({ + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, + test: { + exclude: [...configDefaults.exclude, '**/*.e2e.spec.ts'], + }, +});