diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index bda19fdc0..b1fc4ba85 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,7 +1,6 @@ name: Bug Report description: Report a bug -title: "(Bug report) " -labels: "Type: Bug" +type: "Bug" body: - type: textarea attributes: diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index cee77701b..92473b1b9 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,12 +1,11 @@ name: Feature Request description: Ask for a new feature to be added -title: "(Feature request) " -labels: "Type: Enhancement" +type: "Feature" body: - type: textarea attributes: label: Describe feature - description: A clear and concise description of what you want to be added.. + description: A clear and concise description of what you want to be added. validations: required: true - type: textarea diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index f040eeecb..2378d9f46 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -92,7 +92,16 @@ jobs: asset_content_type: application/zip # required by GitHub API nightly-server: name: Deploy server nightly - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + arch: [x64, arm64] + include: + - arch: x64 + runs-on: ubuntu-latest + - arch: arm64 + runs-on: ubuntu-24.04-arm + runs-on: ${{ matrix.runs-on }} steps: - uses: actions/checkout@v4 - name: Set up node & dependencies @@ -102,22 +111,21 @@ jobs: cache: "npm" - name: Install dependencies run: npm ci - - name: Run Linux server build (x86_64) + - name: Run Linux server build + env: + MATRIX_ARCH: ${{ matrix.arch }} run: | npm run update-build-info - npm run ci-update-nightly-version ./bin/build-server.sh - name: Prepare artifacts - if: runner.os != 'windows' run: | mkdir -p upload file=$(find dist -name '*.tar.xz' -print -quit) - cp "$file" "upload/TriliumNextNotes-linux-x64-${{ github.ref_name }}.tar.xz" + cp "$file" "upload/TriliumNextNotes-linux-${{ matrix.arch }}-${{ github.ref_name }}.tar.xz" - uses: actions/upload-artifact@v4 with: - name: TriliumNextNotes linux server x64 - path: upload/TriliumNextNotes-linux-x64-${{ github.ref_name }}.tar.xz - overwrite: true + name: TriliumNextNotes linux server ${{ matrix.arch }} + path: upload/TriliumNextNotes-linux-${{ matrix.arch }}-${{ github.ref_name }}.tar.xz - name: Deploy release uses: WebFreak001/deploy-nightly@v3.2.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0e1239625..8ea938236 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -66,8 +66,17 @@ jobs: fail_on_unmatched_files: true files: upload/*.* build_linux_server-x64: - name: Build Linux Server x86_64 - runs-on: ubuntu-latest + name: Build Linux Server + strategy: + fail-fast: false + matrix: + arch: [x64, arm64] + include: + - arch: x64 + runs-on: ubuntu-latest + - arch: arm64 + runs-on: ubuntu-24.04-arm + runs-on: ${{ matrix.runs-on }} steps: - uses: actions/checkout@v4 - name: Set up node & dependencies @@ -77,16 +86,17 @@ jobs: cache: "npm" - name: Install dependencies run: npm ci - - name: Run Linux server build (x86_64) + - name: Run Linux server build + env: + MATRIX_ARCH: ${{ matrix.arch }} run: | npm run update-build-info ./bin/build-server.sh - name: Prepare artifacts - if: runner.os != 'windows' run: | mkdir -p upload file=$(find dist -name '*.tar.xz' -print -quit) - cp "$file" "upload/TriliumNextNotes-${{ github.ref_name }}-server-linux-x64.tar.xz" + cp "$file" "upload/TriliumNextNotes-linux-${{ matrix.arch }}-${{ github.ref_name }}.tar.xz" - name: Publish release uses: softprops/action-gh-release@v2 with: diff --git a/.npmrc b/.npmrc index a00d1ad82..31dcbb1a6 100644 --- a/.npmrc +++ b/.npmrc @@ -1,2 +1 @@ save-prefix = '' -legacy-peer-deps = true \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 068d094e3..959c244a9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build stage -FROM node:22.13.0-bullseye-slim AS builder +FROM node:22.13.1-bullseye-slim AS builder # Configure build dependencies in a single layer RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -28,7 +28,6 @@ RUN cp -R build/src/* src/. && \ npm run webpack && \ npm prune --omit=dev && \ npm cache clean --force && \ - cp src/public/app/share.js src/public/app-dist/. && \ cp -r src/public/app/doc_notes src/public/app-dist/. && \ rm -rf src/public/app/* && \ mkdir -p src/public/app/services && \ @@ -37,7 +36,7 @@ RUN cp -R build/src/* src/. && \ rm -r build # Runtime stage -FROM node:22.13.0-bullseye-slim +FROM node:22.13.1-bullseye-slim # Install only runtime dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/Dockerfile.alpine b/Dockerfile.alpine index a3ad94631..f7b49b94c 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -1,5 +1,5 @@ # Build stage -FROM node:22.13.0-alpine AS builder +FROM node:22.13.1-alpine AS builder # Configure build dependencies RUN apk add --no-cache --virtual .build-dependencies \ @@ -27,7 +27,6 @@ RUN cp -R build/src/* src/. && \ npm run webpack && \ npm prune --omit=dev && \ npm cache clean --force && \ - cp src/public/app/share.js src/public/app-dist/. && \ cp -r src/public/app/doc_notes src/public/app-dist/. && \ rm -rf src/public/app && \ mkdir -p src/public/app/services && \ @@ -36,7 +35,7 @@ RUN cp -R build/src/* src/. && \ rm -r build # Runtime stage -FROM node:22.13.0-alpine +FROM node:22.13.1-alpine # Install runtime dependencies RUN apk add --no-cache su-exec shadow diff --git a/bin/copy-trilium.sh b/bin/copy-trilium.sh index a9961847e..221e8a0ea 100755 --- a/bin/copy-trilium.sh +++ b/bin/copy-trilium.sh @@ -68,7 +68,6 @@ find $DIR -name "*.ts" -type f -delete d="$DIR"/src/public [[ -d "$d"/app-dist ]] || mkdir -pv "$d"/app-dist -cp "$d"/app/share.js "$d"/app-dist/ cp -r "$d"/app/doc_notes "$d"/app-dist/ rm -rf "$d"/app diff --git a/config-sample.ini b/config-sample.ini index d419ed473..90c7fa17e 100644 --- a/config-sample.ini +++ b/config-sample.ini @@ -27,3 +27,8 @@ keyPath= # once set, expressjs will use the X-Forwarded-For header set by the rev. proxy to determinate the real IPs of clients. # expressjs shortcuts are supported: loopback(127.0.0.1/8, ::1/128), linklocal(169.254.0.0/16, fe80::/10), uniquelocal(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7) trustedReverseProxy=false + +[Sync] +#syncServerHost= +#syncServerTimeout= +#syncServerProxy= \ No newline at end of file diff --git a/db/image-deleted.png b/db/image-deleted.png index 8af4fdd9c..74b6b540d 100644 Binary files a/db/image-deleted.png and b/db/image-deleted.png differ diff --git a/docker_healthcheck.ts b/docker_healthcheck.ts index 2a2635db2..262dc3ef2 100755 --- a/docker_healthcheck.ts +++ b/docker_healthcheck.ts @@ -1,8 +1,5 @@ import http from "http"; -import ini from "ini"; -import fs from "fs"; -import dataDir from "./src/services/data_dir.js"; -const config = ini.parse(fs.readFileSync(dataDir.CONFIG_INI_PATH, "utf-8")); +import config from "./src/services/config.js"; if (config.Network.https) { // built-in TLS (terminated by trilium) is not supported yet, PRs are welcome diff --git a/docs/api/attachments/27Z989bSFWAc/image/image.png b/docs/api/attachments/27Z989bSFWAc/image/image.png index 5eacee569..b483c3eb1 100644 Binary files a/docs/api/attachments/27Z989bSFWAc/image/image.png and b/docs/api/attachments/27Z989bSFWAc/image/image.png differ diff --git a/docs/api/attachments/XEUUvzBxh89z/image/image.png b/docs/api/attachments/XEUUvzBxh89z/image/image.png index 2f13f1647..a149bd18b 100644 Binary files a/docs/api/attachments/XEUUvzBxh89z/image/image.png and b/docs/api/attachments/XEUUvzBxh89z/image/image.png differ diff --git a/images/app-icons/ios/apple-touch-icon.png b/images/app-icons/ios/apple-touch-icon.png index 1592471d9..4952f5913 100644 Binary files a/images/app-icons/ios/apple-touch-icon.png and b/images/app-icons/ios/apple-touch-icon.png differ diff --git a/images/app-icons/png/1000x1000.png b/images/app-icons/png/1000x1000.png index c41e1acb2..6261492fa 100644 Binary files a/images/app-icons/png/1000x1000.png and b/images/app-icons/png/1000x1000.png differ diff --git a/images/app-icons/png/1024x1024.png b/images/app-icons/png/1024x1024.png index f3b656710..6fe302c15 100644 Binary files a/images/app-icons/png/1024x1024.png and b/images/app-icons/png/1024x1024.png differ diff --git a/images/app-icons/png/128x128.png b/images/app-icons/png/128x128.png index df8b50614..0be3230aa 100644 Binary files a/images/app-icons/png/128x128.png and b/images/app-icons/png/128x128.png differ diff --git a/images/app-icons/png/256x256-dev.png b/images/app-icons/png/256x256-dev.png index 4067a2691..f554c01e9 100644 Binary files a/images/app-icons/png/256x256-dev.png and b/images/app-icons/png/256x256-dev.png differ diff --git a/images/app-icons/png/256x256.png b/images/app-icons/png/256x256.png index 6be8fd393..b3139ca16 100644 Binary files a/images/app-icons/png/256x256.png and b/images/app-icons/png/256x256.png differ diff --git a/images/app-icons/png/512x512.png b/images/app-icons/png/512x512.png index ffab7b513..f420f5839 100644 Binary files a/images/app-icons/png/512x512.png and b/images/app-icons/png/512x512.png differ diff --git a/images/app-icons/win/setup-banner.gif b/images/app-icons/win/setup-banner.gif index 4d3b86f10..dc442eeb5 100644 Binary files a/images/app-icons/win/setup-banner.gif and b/images/app-icons/win/setup-banner.gif differ diff --git a/issue_template.md b/issue_template.md deleted file mode 100644 index 70c4c8e9a..000000000 --- a/issue_template.md +++ /dev/null @@ -1,5 +0,0 @@ -For bug reports, **PLEASE mention version of Trilium you're using** and also include **log files** from following location: - -* `/home/[user]/.local/share/trilium-data/log` for Linux -* `C:\Users\[user]\AppData\Roaming\trilium-data\log` for Windows Vista and up -* `/Users/[user]/Library/Application Support/trilium-data/log` for Mac OS \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a13fd2c86..e4b36b972 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "trilium", - "version": "0.91.2-beta", + "version": "0.91.4-beta", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "trilium", - "version": "0.91.2-beta", + "version": "0.91.4-beta", "license": "AGPL-3.0-only", "dependencies": { "@braintree/sanitize-url": "7.1.1", @@ -14,7 +14,7 @@ "@excalidraw/excalidraw": "0.17.6", "@highlightjs/cdn-assets": "11.11.1", "@mermaid-js/layout-elk": "0.1.7", - "@mind-elixir/node-menu": "1.0.3", + "@mind-elixir/node-menu": "1.0.4", "@triliumnext/express-partial-content": "1.0.1", "@types/leaflet": "1.9.16", "@types/react-dom": "18.3.5", @@ -52,9 +52,9 @@ "html2plaintext": "2.1.4", "http-proxy-agent": "7.0.2", "https-proxy-agent": "7.0.6", - "i18next": "24.2.1", + "i18next": "24.2.2", "i18next-fs-backend": "2.6.0", - "i18next-http-backend": "3.0.1", + "i18next-http-backend": "3.0.2", "image-type": "5.2.0", "ini": "5.0.0", "is-animated": "2.0.2", @@ -106,14 +106,14 @@ "trilium": "src/main.js" }, "devDependencies": { - "@electron-forge/cli": "7.6.0", - "@electron-forge/maker-deb": "7.6.0", - "@electron-forge/maker-dmg": "7.6.0", - "@electron-forge/maker-squirrel": "7.6.0", - "@electron-forge/maker-zip": "7.6.0", - "@electron-forge/plugin-auto-unpack-natives": "7.6.0", + "@electron-forge/cli": "7.6.1", + "@electron-forge/maker-deb": "7.6.1", + "@electron-forge/maker-dmg": "7.6.1", + "@electron-forge/maker-squirrel": "7.6.1", + "@electron-forge/maker-zip": "7.6.1", + "@electron-forge/plugin-auto-unpack-natives": "7.6.1", "@electron/rebuild": "3.7.1", - "@playwright/test": "1.49.1", + "@playwright/test": "1.50.0", "@types/archiver": "6.0.3", "@types/better-sqlite3": "7.6.12", "@types/bootstrap": "5.2.10", @@ -135,7 +135,7 @@ "@types/jsdom": "21.1.7", "@types/mime-types": "2.1.4", "@types/multer": "1.4.12", - "@types/node": "22.10.7", + "@types/node": "22.12.0", "@types/react": "18.3.18", "@types/safe-compare": "1.1.2", "@types/sanitize-html": "2.13.0", @@ -147,12 +147,12 @@ "@types/stream-throttle": "0.1.4", "@types/tmp": "0.2.6", "@types/turndown": "5.0.5", - "@types/ws": "8.5.13", + "@types/ws": "8.5.14", "@types/xml2js": "0.4.14", "@types/yargs": "17.0.33", - "@vitest/coverage-v8": "3.0.3", + "@vitest/coverage-v8": "3.0.4", "cross-env": "7.0.3", - "electron": "34.0.0", + "electron": "34.0.1", "esm": "3.2.25", "jasmine": "5.5.0", "jsdoc": "4.0.4", @@ -165,7 +165,7 @@ "tsx": "4.19.2", "typedoc": "0.27.6", "typescript": "5.7.3", - "vitest": "3.0.3", + "vitest": "3.0.4", "webpack": "5.97.1", "webpack-cli": "6.0.1", "webpack-dev-middleware": "7.4.2" @@ -478,9 +478,9 @@ } }, "node_modules/@electron-forge/cli": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/cli/-/cli-7.6.0.tgz", - "integrity": "sha512-5G7rBbvTb4HJDiCuhncBzNaRj1e1dEmrk6jExpziqv4Y8p9b+nxfdOjsjWu0hvAl4k2V65Rnm1uEkAA7MmlZOQ==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/cli/-/cli-7.6.1.tgz", + "integrity": "sha512-Z9OwK5cAVDOj7MWWt9Gw0/4OJO/db+rshLSXg0I+ySv4xrJmZK1w6QEeOrm7eHjuAqKA+gzIaHsRsT0klCL2lg==", "dev": true, "funding": [ { @@ -494,8 +494,8 @@ ], "license": "MIT", "dependencies": { - "@electron-forge/core": "7.6.0", - "@electron-forge/shared-types": "7.6.0", + "@electron-forge/core": "7.6.1", + "@electron-forge/shared-types": "7.6.1", "@electron/get": "^3.0.0", "chalk": "^4.0.0", "commander": "^4.1.1", @@ -542,9 +542,9 @@ } }, "node_modules/@electron-forge/core": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/core/-/core-7.6.0.tgz", - "integrity": "sha512-DgkjpoK+SPExNTLZL1v81zl0RswQWvMXkMnMqZYf0/S/KHKTXWsoE9KTzr8fDGpiG3nUJXWMqHyny9zLoUdKXQ==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/core/-/core-7.6.1.tgz", + "integrity": "sha512-gODx2GcBl6Y6ls1DeBidhKC0nmI2/xfx89WcSEDa5M3NKm/bBQo1EPjpwG6F+2r4e8KDkY/KrRbIli+wL1zQ7w==", "dev": true, "funding": [ { @@ -558,23 +558,24 @@ ], "license": "MIT", "dependencies": { - "@electron-forge/core-utils": "7.6.0", - "@electron-forge/maker-base": "7.6.0", - "@electron-forge/plugin-base": "7.6.0", - "@electron-forge/publisher-base": "7.6.0", - "@electron-forge/shared-types": "7.6.0", - "@electron-forge/template-base": "7.6.0", - "@electron-forge/template-vite": "7.6.0", - "@electron-forge/template-vite-typescript": "7.6.0", - "@electron-forge/template-webpack": "7.6.0", - "@electron-forge/template-webpack-typescript": "7.6.0", - "@electron-forge/tracer": "7.6.0", + "@electron-forge/core-utils": "7.6.1", + "@electron-forge/maker-base": "7.6.1", + "@electron-forge/plugin-base": "7.6.1", + "@electron-forge/publisher-base": "7.6.1", + "@electron-forge/shared-types": "7.6.1", + "@electron-forge/template-base": "7.6.1", + "@electron-forge/template-vite": "7.6.1", + "@electron-forge/template-vite-typescript": "7.6.1", + "@electron-forge/template-webpack": "7.6.1", + "@electron-forge/template-webpack-typescript": "7.6.1", + "@electron-forge/tracer": "7.6.1", "@electron/get": "^3.0.0", "@electron/packager": "^18.3.5", "@electron/rebuild": "^3.7.0", "@malept/cross-spawn-promise": "^2.0.0", "chalk": "^4.0.0", "debug": "^4.3.1", + "detect-package-manager": "^3.0.2", "fast-glob": "^3.2.7", "filenamify": "^4.1.0", "find-up": "^5.0.0", @@ -585,36 +586,34 @@ "lodash": "^4.17.20", "log-symbols": "^4.0.0", "node-fetch": "^2.6.7", - "progress": "^2.0.3", "rechoir": "^0.8.0", "resolve-package": "^1.0.1", "semver": "^7.2.1", "source-map-support": "^0.5.13", "sudo-prompt": "^9.1.1", - "username": "^5.1.0", - "yarn-or-npm": "^3.0.1" + "username": "^5.1.0" }, "engines": { "node": ">= 16.4.0" } }, "node_modules/@electron-forge/core-utils": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/core-utils/-/core-utils-7.6.0.tgz", - "integrity": "sha512-7XVKHPI87p558kVen280yB1UC2cVGHvrMfnPFv4zm3TQHEVaKWKW+5y+UZsKUnGAukNlahHWuHF/1S8dRCJNEg==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/core-utils/-/core-utils-7.6.1.tgz", + "integrity": "sha512-RGA3azq0r5bGk8DDmVDP1EML071JEa44hpZEgSsv9zmdC86aTh0cANyDE6sVarAwLx4LQ+zrFE3KSb63j1HD5w==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.6.0", + "@electron-forge/shared-types": "7.6.1", "@electron/rebuild": "^3.7.0", "@malept/cross-spawn-promise": "^2.0.0", "chalk": "^4.0.0", "debug": "^4.3.1", + "detect-package-manager": "^3.0.2", "find-up": "^5.0.0", "fs-extra": "^10.0.0", "log-symbols": "^4.0.0", - "semver": "^7.2.1", - "yarn-or-npm": "^3.0.1" + "semver": "^7.2.1" }, "engines": { "node": ">= 16.4.0" @@ -677,13 +676,13 @@ } }, "node_modules/@electron-forge/maker-base": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-base/-/maker-base-7.6.0.tgz", - "integrity": "sha512-GrVYhiA/g0NXrI13LcXrT+JKLlq8kkYyO6w0jQORqDFeRSLRoLhrru5w0msg0wINGugBe+/NwyAyFZ2KaQ6o4g==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-base/-/maker-base-7.6.1.tgz", + "integrity": "sha512-kA6k0z4fFbqfjV++bbYVC46TckiqyqIo/gTW/QexsT6xlutXUbnNevhoRPVfGigftSAjE6T26DwTogC9hNDkwg==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.6.0", + "@electron-forge/shared-types": "7.6.1", "fs-extra": "^10.0.0", "which": "^2.0.2" }, @@ -720,14 +719,14 @@ } }, "node_modules/@electron-forge/maker-deb": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-deb/-/maker-deb-7.6.0.tgz", - "integrity": "sha512-vTg/wJwfdWM4Hm1NlU0g30ODn6z3NBukQdWOS2xXJQ/Y0KnQRVN7ThSlxxzWJy0tI6hGAlpziJjpXozTfhM/Nw==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-deb/-/maker-deb-7.6.1.tgz", + "integrity": "sha512-8pqwxwlMPddH6anfNL8vYE5v2mlPia+z9YcpnLlMbMjWo9ksRcxmrg2t3El9jvk1TkiPoqVcQzCNaQqYQaMoiw==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.6.0", - "@electron-forge/shared-types": "7.6.0" + "@electron-forge/maker-base": "7.6.1", + "@electron-forge/shared-types": "7.6.1" }, "engines": { "node": ">= 16.4.0" @@ -737,14 +736,14 @@ } }, "node_modules/@electron-forge/maker-dmg": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-dmg/-/maker-dmg-7.6.0.tgz", - "integrity": "sha512-Wa4XG9r4RldF5uy7vef5/BR8o/P+BmltZIbZulnFwhOYEu4Quj+SDF1bet7y3tM2i1am/sEocFcBHXC7CRk8xg==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-dmg/-/maker-dmg-7.6.1.tgz", + "integrity": "sha512-D7cJRE6CGeovLZhu2dRqUm3w/AlkTURYJYgFuUsgwpBuviQKgJd8quZar6IeZ/l83y4Z1dghKb8D3aAj+bRvNQ==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.6.0", - "@electron-forge/shared-types": "7.6.0", + "@electron-forge/maker-base": "7.6.1", + "@electron-forge/shared-types": "7.6.1", "fs-extra": "^10.0.0" }, "engines": { @@ -783,14 +782,14 @@ } }, "node_modules/@electron-forge/maker-squirrel": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-squirrel/-/maker-squirrel-7.6.0.tgz", - "integrity": "sha512-8tqsJBRAe37YZSKv1fPc1tijQljkSlUQCaeun37ZOM/viurSeydt5nu2M+UDmJHAfD/PRZMjnYvCCWH+08wGVg==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-squirrel/-/maker-squirrel-7.6.1.tgz", + "integrity": "sha512-7EMLcl0QM5GfdY+enfauEqV6ZW14A1S6Eqoev812FXGTm88G8Ik0tPRw6SsIaI8R++YqxsbdCGTQjzdJWY0bJA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.6.0", - "@electron-forge/shared-types": "7.6.0", + "@electron-forge/maker-base": "7.6.1", + "@electron-forge/shared-types": "7.6.1", "fs-extra": "^10.0.0" }, "engines": { @@ -829,14 +828,14 @@ } }, "node_modules/@electron-forge/maker-zip": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-zip/-/maker-zip-7.6.0.tgz", - "integrity": "sha512-sDPQoEs6CnkxsydvnfZByBGf+RREky2xqiusWCvaPnUoLRpq96SFaBb1BRCS6tQKQHKkaEUXEC5pBdrYGLHPVg==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/maker-zip/-/maker-zip-7.6.1.tgz", + "integrity": "sha512-omoBwoY99DpsgabVIu6Qva+r8kwCY04zDV+P60WN6x+JX/MF+Bk3zI271aH6raZaB+YSbvaed/LDG1QmEM9cTA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/maker-base": "7.6.0", - "@electron-forge/shared-types": "7.6.0", + "@electron-forge/maker-base": "7.6.1", + "@electron-forge/shared-types": "7.6.1", "cross-zip": "^4.0.0", "fs-extra": "^10.0.0", "got": "^11.8.5" @@ -874,53 +873,53 @@ } }, "node_modules/@electron-forge/plugin-auto-unpack-natives": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/plugin-auto-unpack-natives/-/plugin-auto-unpack-natives-7.6.0.tgz", - "integrity": "sha512-rSWRLJinRIxtlkLke0uJzOLksRnXszu3hZrzlgOWChDuMFM298yb6gxWAjYh94VoNxXrUHl9Cd4ia/5+wgPwwg==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/plugin-auto-unpack-natives/-/plugin-auto-unpack-natives-7.6.1.tgz", + "integrity": "sha512-sPFSVhlJBvEA70e0QNbYno5AYc8nvmKCgs4YqTwc24ONhIX0TwGAzjuJ7AZBOj88rhhY9+9Rkl9cONVa5GGZvA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/plugin-base": "7.6.0", - "@electron-forge/shared-types": "7.6.0" + "@electron-forge/plugin-base": "7.6.1", + "@electron-forge/shared-types": "7.6.1" }, "engines": { "node": ">= 16.4.0" } }, "node_modules/@electron-forge/plugin-base": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/plugin-base/-/plugin-base-7.6.0.tgz", - "integrity": "sha512-9llu4algWZJAJFVVZtd/Xa71c0QVxRmoMrpHX2SB+XJ+ZlFVdXrlnhn2hc/CnM0by9cBElyAL3cx3533OKS7lA==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/plugin-base/-/plugin-base-7.6.1.tgz", + "integrity": "sha512-RWt+a8At55dVwEgr8BnnmBN05QzZq+DbOHNPeSJEM2d4ZyLUZXTkkwSF+ZMVk5mQCfIf75l+6BEzkXOcVvti2Q==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.6.0" + "@electron-forge/shared-types": "7.6.1" }, "engines": { "node": ">= 16.4.0" } }, "node_modules/@electron-forge/publisher-base": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/publisher-base/-/publisher-base-7.6.0.tgz", - "integrity": "sha512-IL9bbIb/4J4I1bfW53RAmE/Al835XJsOwFXTLUnxnaGtbWg5jz7eiyw9Vl8XvvfHN1Dpoa9f94to8keU2MXgDg==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/publisher-base/-/publisher-base-7.6.1.tgz", + "integrity": "sha512-VE0DJJYcMRGMxEbeC20q+ynCpra9oqkM6oXd8O1jRyTit9F+PZlscT/p5vLANrTW5vGrV6CXLyyloPxWxOf8DA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.6.0" + "@electron-forge/shared-types": "7.6.1" }, "engines": { "node": ">= 16.4.0" } }, "node_modules/@electron-forge/shared-types": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/shared-types/-/shared-types-7.6.0.tgz", - "integrity": "sha512-qpJRaPo/tx/+t3iFdUWnK4Tk/elo+Izk3yS+BhzfaF0XOK8wS+NNYW4vycK6eVMxN3Yu7/924MQFtPlCKlWHvA==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/shared-types/-/shared-types-7.6.1.tgz", + "integrity": "sha512-i6VdZGG8SYEBirpk+FP7bEMYtCNf9wBkK81IcPco8LP0KbsvgR8y7aUSVxG8DLoVwYB5yr0N9MYXOfNp1gkQ7A==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/tracer": "7.6.0", + "@electron-forge/tracer": "7.6.1", "@electron/packager": "^18.3.5", "@electron/rebuild": "^3.7.0", "listr2": "^7.0.2" @@ -930,13 +929,13 @@ } }, "node_modules/@electron-forge/template-base": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/template-base/-/template-base-7.6.0.tgz", - "integrity": "sha512-lhvab8a/knuGnpzep8BMOEkgnkHGr11QELGBzslEnA6rwZi9DDyEgmMCk6VWOVQNHMeuEqh5XlgjVqJmjW6nIQ==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/template-base/-/template-base-7.6.1.tgz", + "integrity": "sha512-Pk65CIe6jYJa/hv25o0ueyuAOrRTi3qz92g5cYnj+YZzndNmrem1sNQvNKkavw0w0TKEUC5Y0EZ4ejLSYhVIQA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.6.0", + "@electron-forge/shared-types": "7.6.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "fs-extra": "^10.0.0", @@ -975,14 +974,14 @@ } }, "node_modules/@electron-forge/template-vite": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/template-vite/-/template-vite-7.6.0.tgz", - "integrity": "sha512-C0V0dGDO1hLXnAM9lGnZU0esNOTbxwcgILWJXv0mYErBkmputAIi3HM1Is3h3JdSijXgVbRWcIQxFxJlOCpB/A==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/template-vite/-/template-vite-7.6.1.tgz", + "integrity": "sha512-DxRBCXgnpFQHueG3M6yDN1x2pTYDycHXIddLExUydA9bsrxVwlu8Oo7Mm5XOEltebITD/bZ0iQniOVkzUov37g==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.6.0", - "@electron-forge/template-base": "7.6.0", + "@electron-forge/shared-types": "7.6.1", + "@electron-forge/template-base": "7.6.1", "fs-extra": "^10.0.0" }, "engines": { @@ -990,14 +989,14 @@ } }, "node_modules/@electron-forge/template-vite-typescript": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.6.0.tgz", - "integrity": "sha512-i2Bt5Hehoq2CNNrUQjl8DQX7VatBMQ6mv+CCa+m+EV92nUYxXsoFva62/5ITpc3gFAGd1upw/S7dTbHV6GOwsA==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.6.1.tgz", + "integrity": "sha512-7aMq7/woR2xUNbCYCRa/dwinnjoYKuamn17hYBwmyRNJ+YKV9btVK6lq+WR4sJmFM5Fv3qOJlUwrNyxH+HoUCQ==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.6.0", - "@electron-forge/template-base": "7.6.0", + "@electron-forge/shared-types": "7.6.1", + "@electron-forge/template-base": "7.6.1", "fs-extra": "^10.0.0" }, "engines": { @@ -1061,14 +1060,14 @@ } }, "node_modules/@electron-forge/template-webpack": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack/-/template-webpack-7.6.0.tgz", - "integrity": "sha512-+HEf0ryUfLpHvl27TXSdP2Ob69+ktNtr5EnmroZGGIxhSAtEs4HloPtDF9PSfBzm38pZhQBZn78kY9LbITTGjg==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack/-/template-webpack-7.6.1.tgz", + "integrity": "sha512-8HXJ7eh5mjphC2tBfBOroEfM71DsWt3yrkEQMGzW6Lc5u2itkCQrEAINm3nuLscWrqLRk4ZsfT1f1VzdwAraXg==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.6.0", - "@electron-forge/template-base": "7.6.0", + "@electron-forge/shared-types": "7.6.1", + "@electron-forge/template-base": "7.6.1", "fs-extra": "^10.0.0" }, "engines": { @@ -1076,14 +1075,14 @@ } }, "node_modules/@electron-forge/template-webpack-typescript": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.6.0.tgz", - "integrity": "sha512-fDj4DkGxJJjGL8lpowFnkX7PvV9koLHKJuyusK8p8ayVMGoHpHrIcVCrV06tKYOvhFrL/ahW+CKKvjlxF8niEg==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.6.1.tgz", + "integrity": "sha512-ECEd70QOAi7r2ZibIU2U9rh0CVND7oJP5BnKRCP20uUCxdQdO7RTMRDXesm41VTRa1uZ+64pRdOQTDFHB6xitA==", "dev": true, "license": "MIT", "dependencies": { - "@electron-forge/shared-types": "7.6.0", - "@electron-forge/template-base": "7.6.0", + "@electron-forge/shared-types": "7.6.1", + "@electron-forge/template-base": "7.6.1", "fs-extra": "^10.0.0" }, "engines": { @@ -1147,9 +1146,9 @@ } }, "node_modules/@electron-forge/tracer": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@electron-forge/tracer/-/tracer-7.6.0.tgz", - "integrity": "sha512-Rn76RHqNhLyZDnu+xY/X73+bv+Q09XKaZBL/WvlYBbvrrHe26NOHJ3IHXxkWRokSWd4B7lOGLGKm3j1Il8dVbQ==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@electron-forge/tracer/-/tracer-7.6.1.tgz", + "integrity": "sha512-nZzVzXT4xdueWYoSbgStS5LfcifW/e/WJj9VOt6xYpFxYOsQHpLkkCAc6nH0gxn+60kiU4FMU0p2kSQ2eQhWuA==", "dev": true, "license": "MIT", "dependencies": { @@ -1358,9 +1357,9 @@ } }, "node_modules/@electron/osx-sign": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz", - "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.2.tgz", + "integrity": "sha512-KqVlm9WMWq19lBpCXQoThC/Koaiji2zotUDYwZDaZlZZym+FXY9mQW8wN6sUQ93nkVc42f3TQ1S/XN9S1kjM5Q==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -2579,7 +2578,6 @@ "version": "0.3.8", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -2594,7 +2592,6 @@ "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2605,7 +2602,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -2615,7 +2611,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -2625,7 +2620,6 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -2636,7 +2630,6 @@ "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2647,7 +2640,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, "license": "MIT" }, "node_modules/@jsdoc/salty": { @@ -2766,11 +2758,11 @@ } }, "node_modules/@mind-elixir/node-menu": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@mind-elixir/node-menu/-/node-menu-1.0.3.tgz", - "integrity": "sha512-iRGl280bja8CDevceHaxlpagIJnGS7oNrzfYdzwWgq4AMUq+pTEZWWHmEma1d/VG+UOB0jT3XrLLWZT9Tz+y0g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@mind-elixir/node-menu/-/node-menu-1.0.4.tgz", + "integrity": "sha512-xEwBakXEyVCfb8NFYmuvoXSZugxWZUa/s/bxLI8lxTKzTqhHOX4cJdp3B77ojUfnW4KvYJChlo7zkepijsmn0Q==", "peerDependencies": { - "mind-elixir": "^2.0.1" + "mind-elixir": ">2.0.1" } }, "node_modules/@mixmark-io/domino": { @@ -2887,13 +2879,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.49.1.tgz", - "integrity": "sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.50.0.tgz", + "integrity": "sha512-ZGNXbt+d65EGjBORQHuYKj+XhCewlwpnSd/EDuLPZGSiEWmgOJB5RmMCCYGy5aMfTs9wx61RivfDKi8H/hcMvw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.49.1" + "playwright": "1.50.0" }, "bin": { "playwright": "cli.js" @@ -2906,7 +2898,6 @@ "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "dev": true, "license": "MIT", "funding": { "type": "opencollective", @@ -3212,7 +3203,6 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -3225,7 +3215,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, "license": "MIT", "dependencies": { "defer-to-connect": "^2.0.0" @@ -3321,7 +3310,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, "license": "MIT", "dependencies": { "@types/http-cache-semantics": "*", @@ -3665,7 +3653,6 @@ "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "*", @@ -3676,7 +3663,6 @@ "version": "3.7.7", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, "license": "MIT", "dependencies": { "@types/eslint": "*", @@ -3687,7 +3673,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, "license": "MIT" }, "node_modules/@types/express": { @@ -3776,7 +3761,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "dev": true, "license": "MIT" }, "node_modules/@types/http-errors": { @@ -3826,7 +3810,6 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, "license": "MIT" }, "node_modules/@types/jsonfile": { @@ -3843,7 +3826,6 @@ "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -3916,10 +3898,9 @@ } }, "node_modules/@types/node": { - "version": "22.10.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz", - "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==", - "dev": true, + "version": "22.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.12.0.tgz", + "integrity": "sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==", "license": "MIT", "dependencies": { "undici-types": "~6.20.0" @@ -3929,7 +3910,6 @@ "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", - "dev": true, "license": "MIT" }, "node_modules/@types/qs": { @@ -3950,7 +3930,6 @@ "version": "18.3.18", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -3980,7 +3959,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -4127,9 +4105,9 @@ "license": "MIT" }, "node_modules/@types/ws": { - "version": "8.5.13", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", - "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz", + "integrity": "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==", "dev": true, "license": "MIT", "dependencies": { @@ -4167,7 +4145,6 @@ "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -4175,9 +4152,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.3.tgz", - "integrity": "sha512-uVbJ/xhImdNtzPnLyxCZJMTeTIYdgcC2nWtBBBpR1H6z0w8m7D+9/zrDIx2nNxgMg9r+X8+RY2qVpUDeW2b3nw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.4.tgz", + "integrity": "sha512-f0twgRCHgbs24Dp8cLWagzcObXMcuKtAwgxjJV/nnysPAJJk1JiKu/W0gIehZLmkljhJXU/E0/dmuQzsA/4jhA==", "dev": true, "license": "MIT", "dependencies": { @@ -4198,8 +4175,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.0.3", - "vitest": "3.0.3" + "@vitest/browser": "3.0.4", + "vitest": "3.0.4" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -4208,14 +4185,14 @@ } }, "node_modules/@vitest/expect": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.3.tgz", - "integrity": "sha512-SbRCHU4qr91xguu+dH3RUdI5dC86zm8aZWydbp961aIR7G8OYNN6ZiayFuf9WAngRbFOfdrLHCGgXTj3GtoMRQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.4.tgz", + "integrity": "sha512-Nm5kJmYw6P2BxhJPkO3eKKhGYKRsnqJqf+r0yOGRKpEP+bSCBDsjXgiu1/5QFrnPMEgzfC38ZEjvCFgaNBC0Eg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.3", - "@vitest/utils": "3.0.3", + "@vitest/spy": "3.0.4", + "@vitest/utils": "3.0.4", "chai": "^5.1.2", "tinyrainbow": "^2.0.0" }, @@ -4224,13 +4201,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.3.tgz", - "integrity": "sha512-XT2XBc4AN9UdaxJAeIlcSZ0ILi/GzmG5G8XSly4gaiqIvPV3HMTSIDZWJVX6QRJ0PX1m+W8Cy0K9ByXNb/bPIA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.4.tgz", + "integrity": "sha512-gEef35vKafJlfQbnyOXZ0Gcr9IBUsMTyTLXsEQwuyYAerpHqvXhzdBnDFuHLpFqth3F7b6BaFr4qV/Cs1ULx5A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.3", + "@vitest/spy": "3.0.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -4251,9 +4228,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.3.tgz", - "integrity": "sha512-gCrM9F7STYdsDoNjGgYXKPq4SkSxwwIU5nkaQvdUxiQ0EcNlez+PdKOVIsUJvh9P9IeIFmjn4IIREWblOBpP2Q==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.4.tgz", + "integrity": "sha512-ts0fba+dEhK2aC9PFuZ9LTpULHpY/nd6jhAQ5IMU7Gaj7crPCTdCFfgvXxruRBLFS+MLraicCuFXxISEq8C93g==", "dev": true, "license": "MIT", "dependencies": { @@ -4264,14 +4241,14 @@ } }, "node_modules/@vitest/runner": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.3.tgz", - "integrity": "sha512-Rgi2kOAk5ZxWZlwPguRJFOBmWs6uvvyAAR9k3MvjRvYrG7xYvKChZcmnnpJCS98311CBDMqsW9MzzRFsj2gX3g==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.4.tgz", + "integrity": "sha512-dKHzTQ7n9sExAcWH/0sh1elVgwc7OJ2lMOBrAm73J7AH6Pf9T12Zh3lNE1TETZaqrWFXtLlx3NVrLRb5hCK+iw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.3", - "pathe": "^2.0.1" + "@vitest/utils": "3.0.4", + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" @@ -4285,15 +4262,15 @@ "license": "MIT" }, "node_modules/@vitest/snapshot": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.3.tgz", - "integrity": "sha512-kNRcHlI4txBGztuJfPEJ68VezlPAXLRT1u5UCx219TU3kOG2DplNxhWLwDf2h6emwmTPogzLnGVwP6epDaJN6Q==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.4.tgz", + "integrity": "sha512-+p5knMLwIk7lTQkM3NonZ9zBewzVp9EVkVpvNta0/PlFWpiqLaRcF4+33L1it3uRUCh0BGLOaXPPGEjNKfWb4w==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.3", + "@vitest/pretty-format": "3.0.4", "magic-string": "^0.30.17", - "pathe": "^2.0.1" + "pathe": "^2.0.2" }, "funding": { "url": "https://opencollective.com/vitest" @@ -4307,9 +4284,9 @@ "license": "MIT" }, "node_modules/@vitest/spy": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.3.tgz", - "integrity": "sha512-7/dgux8ZBbF7lEIKNnEqQlyRaER9nkAL9eTmdKJkDO3hS8p59ATGwKOCUDHcBLKr7h/oi/6hP+7djQk8049T2A==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.4.tgz", + "integrity": "sha512-sXIMF0oauYyUy2hN49VFTYodzEAu744MmGcPR3ZBsPM20G+1/cSW/n1U+3Yu/zHxX2bIDe1oJASOkml+osTU6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4320,13 +4297,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.3.tgz", - "integrity": "sha512-f+s8CvyzPtMFY1eZKkIHGhPsQgYo5qCm6O8KZoim9qm1/jT64qBgGpO5tHscNH6BzRHM+edLNOP+3vO8+8pE/A==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.4.tgz", + "integrity": "sha512-8BqC1ksYsHtbWH+DfpOAKrFw3jl3Uf9J7yeFh85Pz52IWuh1hBBtyfEbRNNZNjl8H8A5yMLH9/t+k7HIKzQcZQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.3", + "@vitest/pretty-format": "3.0.4", "loupe": "^3.1.2", "tinyrainbow": "^2.0.0" }, @@ -4338,7 +4315,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", @@ -4349,28 +4325,24 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", @@ -4382,14 +4354,12 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.14.1", @@ -4402,7 +4372,6 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" @@ -4412,7 +4381,6 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" @@ -4422,14 +4390,12 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.14.1", @@ -4446,7 +4412,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.14.1", @@ -4460,7 +4425,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.14.1", @@ -4473,7 +4437,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.14.1", @@ -4488,7 +4451,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.14.1", @@ -4562,14 +4524,12 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, "license": "Apache-2.0" }, "node_modules/abbrev": { @@ -4674,7 +4634,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -4691,7 +4650,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, "license": "MIT", "dependencies": { "ajv": "^8.0.0" @@ -4709,7 +4667,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -4726,14 +4683,12 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, "license": "MIT" }, "node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" @@ -5332,7 +5287,6 @@ "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, "license": "MIT", "optional": true }, @@ -5445,7 +5399,6 @@ "version": "4.24.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5719,7 +5672,6 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.6.0" @@ -5729,7 +5681,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, "license": "MIT", "dependencies": { "clone-response": "^1.0.2", @@ -5748,7 +5699,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "license": "MIT", "dependencies": { "pump": "^3.0.0" @@ -5793,7 +5743,6 @@ "version": "1.0.30001689", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001689.tgz", "integrity": "sha512-CmeR2VBycfa+5/jOfnp/NpWPGd06nf1XYiefUvhXFfZE4GkRc9jv+eGPS4nT558WS/8lYCzV8SlANCIPvbWP1g==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5994,7 +5943,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0" @@ -6194,7 +6142,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, "license": "MIT", "dependencies": { "mimic-response": "^1.0.0" @@ -6696,7 +6643,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, "license": "MIT" }, "node_modules/cytoscape": { @@ -7367,7 +7313,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -7377,7 +7322,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -7396,7 +7340,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -7479,10 +7422,72 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, "license": "MIT", "optional": true }, + "node_modules/detect-package-manager": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/detect-package-manager/-/detect-package-manager-3.0.2.tgz", + "integrity": "sha512-8JFjJHutStYrfWwzfretQoyNGoZVW1Fsrp4JO9spa7h/fBfwgTMEIy4/LBzRDGsxwVPHU0q+T9YvwLDJoOApLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/detect-package-manager/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/detect-package-manager/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/detect-package-manager/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-passive-events": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/detect-passive-events/-/detect-passive-events-1.0.5.tgz", @@ -7641,10 +7646,9 @@ } }, "node_modules/electron": { - "version": "34.0.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-34.0.0.tgz", - "integrity": "sha512-fpaPb0lifoUJ6UJa4Lk8/0B2Ku/xDZWdc1Gkj67jbygTCrvSon0qquju6Ltx1Kz23GRqqlIHXiy9EvrjpY7/Wg==", - "dev": true, + "version": "34.0.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-34.0.1.tgz", + "integrity": "sha512-aArw5tAM80i3CKwEREnyZSM1SkARf5Jd1yBMTIdOL4pB1M+p/oDeyWSFI9Dl+vujyfJKiK4SS5+j19wna1onMw==", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -8072,7 +8076,6 @@ "version": "1.5.74", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.74.tgz", "integrity": "sha512-ck3//9RC+6oss/1Bh9tiAVFy5vfSKbRHAFh7Z3/eTRkEqJeWgymloShB17Vg3Z4nmDNp35vAd1BZ6CMW4Wt6Iw==", - "dev": true, "license": "ISC" }, "node_modules/electron-window-state": { @@ -8141,7 +8144,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", - "dev": true, "license": "MIT", "dependencies": { "debug": "^4.1.1", @@ -8160,10 +8162,9 @@ } }, "node_modules/electron/node_modules/@types/node": { - "version": "20.17.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.13.tgz", - "integrity": "sha512-RNf+4dEeV69PIvyp++4IKM2vnLXtmp/JovfeQm5P5+qpKb6wHoH7INywLdZ7z+gVX46kgBP/fwJJvZYaHxtdyw==", - "dev": true, + "version": "20.17.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.14.tgz", + "integrity": "sha512-w6qdYetNL5KRBiSClK/KWai+2IMEJuAj+EujKCumalFOwXtvOXaEan9AuwcRID2IcOIAWSIfR495hBtgKlx2zg==", "license": "MIT", "dependencies": { "undici-types": "~6.19.2" @@ -8173,7 +8174,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", @@ -8188,7 +8188,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -8198,14 +8197,12 @@ "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true, "license": "MIT" }, "node_modules/electron/node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 4.0.0" @@ -8253,7 +8250,6 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -8311,7 +8307,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -8369,7 +8364,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", - "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { @@ -8388,7 +8382,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, "license": "MIT", "optional": true }, @@ -8436,7 +8429,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -8486,7 +8478,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" @@ -8499,7 +8490,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -8892,7 +8882,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", @@ -8913,7 +8902,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, "license": "MIT", "engines": { "node": "*" @@ -8923,7 +8911,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "license": "MIT", "dependencies": { "pump": "^3.0.0" @@ -8939,7 +8926,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3", @@ -8950,7 +8936,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-fifo": { @@ -8993,14 +8978,12 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, "license": "MIT" }, "node_modules/fast-uri": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/fast-xml-parser": { @@ -9049,7 +9032,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, "license": "MIT", "dependencies": { "pend": "~1.2.0" @@ -9723,14 +9705,12 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/global-agent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "dev": true, "license": "BSD-3-Clause", "optional": true, "dependencies": { @@ -9801,7 +9781,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -9831,7 +9810,6 @@ "version": "11.8.6", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, "license": "MIT", "dependencies": { "@sindresorhus/is": "^4.0.0", @@ -9878,7 +9856,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -10174,7 +10151,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/http-proxy-agent": { @@ -10194,7 +10170,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, "license": "MIT", "dependencies": { "quick-lru": "^5.1.1", @@ -10217,6 +10192,16 @@ "node": ">= 14" } }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -10238,9 +10223,9 @@ } }, "node_modules/i18next": { - "version": "24.2.1", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.1.tgz", - "integrity": "sha512-Q2wC1TjWcSikn1VAJg13UGIjc+okpFxQTxjVAymOnSA3RpttBQNMPf2ovcgoFVsV4QNxTfNZMAxorXZXsk4fBA==", + "version": "24.2.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.2.tgz", + "integrity": "sha512-NE6i86lBCKRYZa5TaUDkU5S4HFgLIEJRLr3Whf2psgaxBleQ2LC1YW1Vc+SCgkAW7VEzndT6al6+CzegSUHcTQ==", "funding": [ { "type": "individual", @@ -10275,9 +10260,9 @@ "license": "MIT" }, "node_modules/i18next-http-backend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.1.tgz", - "integrity": "sha512-XT2lYSkbAtDE55c6m7CtKxxrsfuRQO3rUfHzj8ZyRtY9CkIX3aRGwXGTkUhpGWce+J8n7sfu3J0f2wTzo7Lw0A==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.2.tgz", + "integrity": "sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==", "license": "MIT", "dependencies": { "cross-fetch": "4.0.0" @@ -10984,7 +10969,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", @@ -10999,7 +10983,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -11215,28 +11198,24 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, "license": "MIT" }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, "license": "ISC", "optional": true }, @@ -11329,7 +11308,6 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, "license": "MIT", "dependencies": { "json-buffer": "3.0.1" @@ -11507,7 +11485,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.11.5" @@ -11561,6 +11538,7 @@ "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", "dev": true, "license": "MIT" }, @@ -11651,7 +11629,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -11861,7 +11838,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -11944,7 +11920,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, "license": "MIT" }, "node_modules/merge2": { @@ -12075,7 +12050,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -12323,7 +12297,6 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, "license": "MIT" }, "node_modules/ngraph.events": { @@ -12407,7 +12380,6 @@ "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, "license": "MIT" }, "node_modules/nodemon": { @@ -12571,7 +12543,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -12652,7 +12623,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, "license": "MIT", "optional": true, "engines": { @@ -12798,7 +12768,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -13343,13 +13312,13 @@ } }, "node_modules/playwright": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.49.1.tgz", - "integrity": "sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.0.tgz", + "integrity": "sha512-+GinGfGTrd2IfX1TA4N2gNmeIksSb+IAe589ZH+FlmpV3MYTx6+buChGIuDLQwrGNCw2lWibqV50fU510N7S+w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.49.1" + "playwright-core": "1.50.0" }, "bin": { "playwright": "cli.js" @@ -13362,9 +13331,9 @@ } }, "node_modules/playwright-core": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.49.1.tgz", - "integrity": "sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.0.tgz", + "integrity": "sha512-CXkSSlr4JaZs2tZHI40DsZUN/NIwgaUPsyLuOAaIZp2CyF2sN5MM5NJsyB188lFSSozFxQ5fPT4qM+f0tH/6wQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -13566,7 +13535,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -13720,7 +13688,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -13763,7 +13730,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" @@ -14240,7 +14206,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -14296,7 +14261,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true, "license": "MIT" }, "node_modules/resolve-cwd": { @@ -14370,7 +14334,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, "license": "MIT", "dependencies": { "lowercase-keys": "^2.0.0" @@ -14550,7 +14513,6 @@ "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, "license": "BSD-3-Clause", "optional": true, "dependencies": { @@ -14747,7 +14709,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", @@ -14778,7 +14739,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, "license": "MIT", "optional": true }, @@ -14871,7 +14831,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -14888,7 +14847,6 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, "license": "(MIT OR CC0-1.0)", "optional": true, "engines": { @@ -14902,7 +14860,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" @@ -15355,9 +15312,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "version": "3.0.21", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", + "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", "dev": true, "license": "CC0-1.0" }, @@ -15371,7 +15328,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, + "devOptional": true, "license": "BSD-3-Clause" }, "node_modules/ssri": { @@ -15605,6 +15562,16 @@ "node": ">=0.10.0" } }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -15688,7 +15655,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, "license": "Apache-2.0", "dependencies": { "debug": "^4.1.0" @@ -15871,7 +15837,6 @@ "version": "5.37.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -15890,7 +15855,6 @@ "version": "5.3.11", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz", "integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", @@ -15925,7 +15889,6 @@ "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -15936,7 +15899,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -15953,7 +15915,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" @@ -15966,14 +15927,12 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, "license": "MIT" }, "node_modules/terser-webpack-plugin/node_modules/schema-utils": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", - "dev": true, "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", @@ -15993,7 +15952,6 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, "license": "MIT" }, "node_modules/test-exclude": { @@ -16525,7 +16483,6 @@ "version": "5.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -16574,9 +16531,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.0.tgz", - "integrity": "sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==", + "version": "6.21.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz", + "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==", "license": "MIT", "engines": { "node": ">=18.17" @@ -16586,7 +16543,6 @@ "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true, "license": "MIT" }, "node_modules/unescape": { @@ -16706,7 +16662,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -16737,7 +16692,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -16833,9 +16787,9 @@ } }, "node_modules/vite": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.7.tgz", - "integrity": "sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==", + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", + "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", "dev": true, "license": "MIT", "dependencies": { @@ -16905,16 +16859,16 @@ } }, "node_modules/vite-node": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.3.tgz", - "integrity": "sha512-0sQcwhwAEw/UJGojbhOrnq3HtiZ3tC7BzpAa0lx3QaTX0S3YX70iGcik25UBdB96pmdwjyY2uyKNYruxCDmiEg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.4.tgz", + "integrity": "sha512-7JZKEzcYV2Nx3u6rlvN8qdo3QV7Fxyt6hx+CCKz9fbWxdX5IvUOmTWEAxMrWxaiSf7CKGLJQ5rFu8prb/jBjOA==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", "debug": "^4.4.0", "es-module-lexer": "^1.6.0", - "pathe": "^2.0.1", + "pathe": "^2.0.2", "vite": "^5.0.0 || ^6.0.0" }, "bin": { @@ -17399,31 +17353,31 @@ } }, "node_modules/vitest": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.3.tgz", - "integrity": "sha512-dWdwTFUW9rcnL0LyF2F+IfvNQWB0w9DERySCk8VMG75F8k25C7LsZoh6XfCjPvcR8Nb+Lqi9JKr6vnzH7HSrpQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.4.tgz", + "integrity": "sha512-6XG8oTKy2gnJIFTHP6LD7ExFeNLxiTkK3CfMvT7IfR8IN+BYICCf0lXUQmX7i7JoxUP8QmeP4mTnWXgflu4yjw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.0.3", - "@vitest/mocker": "3.0.3", - "@vitest/pretty-format": "^3.0.3", - "@vitest/runner": "3.0.3", - "@vitest/snapshot": "3.0.3", - "@vitest/spy": "3.0.3", - "@vitest/utils": "3.0.3", + "@vitest/expect": "3.0.4", + "@vitest/mocker": "3.0.4", + "@vitest/pretty-format": "^3.0.4", + "@vitest/runner": "3.0.4", + "@vitest/snapshot": "3.0.4", + "@vitest/spy": "3.0.4", + "@vitest/utils": "3.0.4", "chai": "^5.1.2", "debug": "^4.4.0", "expect-type": "^1.1.0", "magic-string": "^0.30.17", - "pathe": "^2.0.1", + "pathe": "^2.0.2", "std-env": "^3.8.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.3", + "vite-node": "3.0.4", "why-is-node-running": "^2.3.0" }, "bin": { @@ -17437,9 +17391,10 @@ }, "peerDependencies": { "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.3", - "@vitest/ui": "3.0.3", + "@vitest/browser": "3.0.4", + "@vitest/ui": "3.0.4", "happy-dom": "*", "jsdom": "*" }, @@ -17447,6 +17402,9 @@ "@edge-runtime/vm": { "optional": true }, + "@types/debug": { + "optional": true + }, "@types/node": { "optional": true }, @@ -17545,7 +17503,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dev": true, "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", @@ -17578,7 +17535,6 @@ "version": "5.97.1", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", - "dev": true, "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", @@ -17780,7 +17736,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" @@ -17790,7 +17745,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -17804,7 +17758,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -18219,97 +18172,6 @@ "node": ">=8" } }, - "node_modules/yarn-or-npm": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/yarn-or-npm/-/yarn-or-npm-3.0.1.tgz", - "integrity": "sha512-fTiQP6WbDAh5QZAVdbMQkecZoahnbOjClTQhzv74WX5h2Uaidj1isf9FDes11TKtsZ0/ZVfZsqZ+O3x6aLERHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^6.0.5", - "pkg-dir": "^4.2.0" - }, - "bin": { - "yarn-or-npm": "bin/index.js", - "yon": "bin/index.js" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/yarn-or-npm/node_modules/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/yarn-or-npm/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/yarn-or-npm/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/yarn-or-npm/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yarn-or-npm/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yarn-or-npm/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/yauzl": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.2.0.tgz", diff --git a/package.json b/package.json index b033ebdd4..97e5cd270 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "trilium", "productName": "TriliumNext Notes", "description": "Build your personal knowledge base with TriliumNext Notes", - "version": "0.91.2-beta", + "version": "0.91.4-beta", "license": "AGPL-3.0-only", "main": "./dist/electron-main.js", "author": { @@ -26,9 +26,9 @@ "start-test-server": "npm run switch-server && rimraf ./data-test && cross-env TRILIUM_DATA_DIR=./data-test TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev TRILIUM_PORT=9999 nodemon src/main.ts", "qstart-server": "npm run switch-server && npm run start-server", "start-electron": "npm run prepare-dist && cross-env TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev electron ./dist/electron-main.js --inspect=5858 .", - "start-electron-nix": "npm run prepare-dist && cross-env TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./dist/electron-main.js --inspect=5858 .\"", + "start-electron-nix": "electron-rebuild --version 33.3.1 && npm run prepare-dist && cross-env TRILIUM_DATA_DIR=./data TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./dist/electron-main.js --inspect=5858 .\"", "start-electron-no-dir": "npm run prepare-dist && cross-env TRILIUM_ENV=dev electron --inspect=5858 .", - "start-electron-no-dir-nix": "npm run prepare-dist && cross-env TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./dist/electron-main.js --inspect=5858 .\"", + "start-electron-no-dir-nix": "electron-rebuild --version 33.3.1 && npm run prepare-dist && cross-env TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./dist/electron-main.js --inspect=5858 .\"", "qstart-electron": "npm run switch-electron && npm run start-electron", "switch-server": "rimraf ./node_modules/better-sqlite3 && npm install", "switch-electron": "electron-rebuild", @@ -59,7 +59,7 @@ "@excalidraw/excalidraw": "0.17.6", "@highlightjs/cdn-assets": "11.11.1", "@mermaid-js/layout-elk": "0.1.7", - "@mind-elixir/node-menu": "1.0.3", + "@mind-elixir/node-menu": "1.0.4", "@triliumnext/express-partial-content": "1.0.1", "@types/leaflet": "1.9.16", "@types/react-dom": "18.3.5", @@ -97,9 +97,9 @@ "html2plaintext": "2.1.4", "http-proxy-agent": "7.0.2", "https-proxy-agent": "7.0.6", - "i18next": "24.2.1", + "i18next": "24.2.2", "i18next-fs-backend": "2.6.0", - "i18next-http-backend": "3.0.1", + "i18next-http-backend": "3.0.2", "image-type": "5.2.0", "ini": "5.0.0", "is-animated": "2.0.2", @@ -148,14 +148,14 @@ "yauzl": "3.2.0" }, "devDependencies": { - "@electron-forge/cli": "7.6.0", - "@electron-forge/maker-deb": "7.6.0", - "@electron-forge/maker-dmg": "7.6.0", - "@electron-forge/maker-squirrel": "7.6.0", - "@electron-forge/maker-zip": "7.6.0", - "@electron-forge/plugin-auto-unpack-natives": "7.6.0", + "@electron-forge/cli": "7.6.1", + "@electron-forge/maker-deb": "7.6.1", + "@electron-forge/maker-dmg": "7.6.1", + "@electron-forge/maker-squirrel": "7.6.1", + "@electron-forge/maker-zip": "7.6.1", + "@electron-forge/plugin-auto-unpack-natives": "7.6.1", "@electron/rebuild": "3.7.1", - "@playwright/test": "1.49.1", + "@playwright/test": "1.50.0", "@types/archiver": "6.0.3", "@types/better-sqlite3": "7.6.12", "@types/bootstrap": "5.2.10", @@ -177,7 +177,7 @@ "@types/jsdom": "21.1.7", "@types/mime-types": "2.1.4", "@types/multer": "1.4.12", - "@types/node": "22.10.7", + "@types/node": "22.12.0", "@types/react": "18.3.18", "@types/safe-compare": "1.1.2", "@types/sanitize-html": "2.13.0", @@ -189,12 +189,12 @@ "@types/stream-throttle": "0.1.4", "@types/tmp": "0.2.6", "@types/turndown": "5.0.5", - "@types/ws": "8.5.13", + "@types/ws": "8.5.14", "@types/xml2js": "0.4.14", "@types/yargs": "17.0.33", - "@vitest/coverage-v8": "3.0.3", + "@vitest/coverage-v8": "3.0.4", "cross-env": "7.0.3", - "electron": "34.0.0", + "electron": "34.0.1", "esm": "3.2.25", "jasmine": "5.5.0", "jsdoc": "4.0.4", @@ -207,7 +207,7 @@ "tsx": "4.19.2", "typedoc": "0.27.6", "typescript": "5.7.3", - "vitest": "3.0.3", + "vitest": "3.0.4", "webpack": "5.97.1", "webpack-cli": "6.0.1", "webpack-dev-middleware": "7.4.2" diff --git a/src/becca/similarity.ts b/src/becca/similarity.ts index 66af0ac61..5b031df35 100644 --- a/src/becca/similarity.ts +++ b/src/becca/similarity.ts @@ -36,6 +36,12 @@ interface DateLimits { maxDate: string; } +interface SimilarNote { + score: number; + notePath: string[]; + noteId: string; +} + function filterUrlValue(value: string) { return value .replace(/https?:\/\//gi, "") @@ -247,7 +253,7 @@ function hasConnectingRelation(sourceNote: BNote, targetNote: BNote) { return sourceNote.getAttributes().find((attr) => attr.type === "relation" && ["includenotelink", "imagelink"].includes(attr.name) && attr.value === targetNote.noteId); } -async function findSimilarNotes(noteId: string) { +async function findSimilarNotes(noteId: string): Promise { const results = []; let i = 0; @@ -417,6 +423,7 @@ async function findSimilarNotes(noteId: string) { // this takes care of note hoisting if (!notePath) { + // TODO: This return is suspicious, it should probably be continue return; } diff --git a/src/public/app/components/app_context.ts b/src/public/app/components/app_context.ts index 992b6a2a0..072977695 100644 --- a/src/public/app/components/app_context.ts +++ b/src/public/app/components/app_context.ts @@ -71,7 +71,7 @@ export interface ExecuteCommandData extends CommandData { export type CommandMappings = { "api-log-messages": CommandData; focusTree: CommandData, - focusOnDetail: Required; + focusOnDetail: CommandData; focusOnSearchDefinition: Required; searchNotes: CommandData & { searchString?: string; @@ -104,6 +104,8 @@ export type CommandMappings = { openNoteInNewTab: CommandData; openNoteInNewSplit: CommandData; openNoteInNewWindow: CommandData; + hideLeftPane: CommandData; + showLeftPane: CommandData; openInTab: ContextMenuCommandData; openNoteInSplit: ContextMenuCommandData; @@ -236,6 +238,9 @@ type EventMappings = { beforeNoteSwitch: { noteContext: NoteContext; }; + beforeNoteContextRemove: { + ntxIds: string[]; + }; noteSwitched: { noteContext: NoteContext; notePath: string | null; @@ -286,6 +291,9 @@ type EventMappings = { tabReorder: { ntxIdsInOrder: string[] }; + refreshNoteList: { + noteId: string; + } }; export type EventListener = { diff --git a/src/public/app/components/component.ts b/src/public/app/components/component.ts index 3bb389589..0ab812bbf 100644 --- a/src/public/app/components/component.ts +++ b/src/public/app/components/component.ts @@ -46,7 +46,7 @@ export class TypedComponent> { return this; } - handleEvent(name: T, data: EventData): Promise | null { + handleEvent(name: T, data: EventData): Promise | null | undefined { try { const callMethodPromise = this.initialized ? this.initialized.then(() => this.callMethod((this as any)[`${name}Event`], data)) : this.callMethod((this as any)[`${name}Event`], data); diff --git a/src/public/app/desktop.js b/src/public/app/desktop.ts similarity index 76% rename from src/public/app/desktop.js rename to src/public/app/desktop.ts index 60dd8fe5d..e6eca440d 100644 --- a/src/public/app/desktop.js +++ b/src/public/app/desktop.ts @@ -9,6 +9,8 @@ import electronContextMenu from "./menus/electron_context_menu.js"; import glob from "./services/glob.js"; import { t } from "./services/i18n.js"; import options from "./services/options.js"; +import type ElectronRemote from "@electron/remote"; +import type Electron from "electron"; await appContext.earlyInit(); @@ -44,10 +46,9 @@ if (utils.isElectron()) { } function initOnElectron() { - const electron = utils.dynamicRequire("electron"); + const electron: typeof Electron = utils.dynamicRequire("electron"); electron.ipcRenderer.on("globalShortcut", async (event, actionName) => appContext.triggerCommand(actionName)); - - const electronRemote = utils.dynamicRequire("@electron/remote"); + const electronRemote: typeof ElectronRemote = utils.dynamicRequire("@electron/remote"); const currentWindow = electronRemote.getCurrentWindow(); const style = window.getComputedStyle(document.body); @@ -58,7 +59,7 @@ function initOnElectron() { } } -function initTitleBarButtons(style, currentWindow) { +function initTitleBarButtons(style: CSSStyleDeclaration, currentWindow: Electron.BrowserWindow) { if (window.glob.platform === "win32") { const applyWindowsOverlay = () => { const color = style.getPropertyValue("--native-titlebar-background"); @@ -81,9 +82,14 @@ function initTitleBarButtons(style, currentWindow) { } } -function initTransparencyEffects(style, currentWindow) { +function initTransparencyEffects(style: CSSStyleDeclaration, currentWindow: Electron.BrowserWindow) { if (window.glob.platform === "win32") { const material = style.getPropertyValue("--background-material"); - currentWindow.setBackgroundMaterial(material); + // TriliumNextTODO: find a nicer way to make TypeScript happy – unfortunately TS did not like Array.includes here + const bgMaterialOptions = ["auto", "none", "mica", "acrylic", "tabbed"] as const; + const foundBgMaterialOption = bgMaterialOptions.find((bgMaterialOption) => material === bgMaterialOption); + if (foundBgMaterialOption) { + currentWindow.setBackgroundMaterial(foundBgMaterialOption); + } } } diff --git a/src/public/app/entities/fnote.ts b/src/public/app/entities/fnote.ts index 053ac6be5..2e0293112 100644 --- a/src/public/app/entities/fnote.ts +++ b/src/public/app/entities/fnote.ts @@ -36,12 +36,12 @@ const NOTE_TYPE_ICONS = { * end user. Those types should be used only for checking against, they are * not for direct use. */ -type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code" | "mindMap" | "geoMap"; +export type NoteType = "file" | "image" | "search" | "noteMap" | "launcher" | "doc" | "contentWidget" | "text" | "relationMap" | "render" | "canvas" | "mermaid" | "book" | "webView" | "code" | "mindMap" | "geoMap"; -interface NotePathRecord { +export interface NotePathRecord { isArchived: boolean; isInHoistedSubTree: boolean; - isSearch: boolean; + isSearch?: boolean; notePath: string[]; isHidden: boolean; } @@ -402,14 +402,14 @@ class FNote { return notePaths; } - getSortedNotePathRecords(hoistedNoteId = "root") { + getSortedNotePathRecords(hoistedNoteId = "root"): NotePathRecord[] { const isHoistedRoot = hoistedNoteId === "root"; - const notePaths = this.getAllNotePaths().map((path) => ({ + const notePaths: NotePathRecord[] = this.getAllNotePaths().map((path) => ({ notePath: path, isInHoistedSubTree: isHoistedRoot || path.includes(hoistedNoteId), isArchived: path.some((noteId) => froca.notes[noteId].isArchived), - isSearch: path.find((noteId) => froca.notes[noteId].type === "search"), + isSearch: path.some((noteId) => froca.notes[noteId].type === "search"), isHidden: path.includes("_hidden") })); diff --git a/src/public/app/mobile.js b/src/public/app/mobile.ts similarity index 100% rename from src/public/app/mobile.js rename to src/public/app/mobile.ts diff --git a/src/public/app/services/load_results.ts b/src/public/app/services/load_results.ts index 0f96cee93..f87f62ea2 100644 --- a/src/public/app/services/load_results.ts +++ b/src/public/app/services/load_results.ts @@ -8,6 +8,7 @@ interface NoteRow { } interface BranchRow { + noteId?: string; branchId: string; componentId: string; parentNoteId?: string; @@ -157,7 +158,7 @@ export default class LoadResults { return Object.keys(this.noteIdToComponentId); } - isNoteReloaded(noteId: string, componentId = null) { + isNoteReloaded(noteId: string | undefined, componentId: string | null = null) { if (!noteId) { return false; } diff --git a/src/public/app/services/utils.ts b/src/public/app/services/utils.ts index 7c7e47b31..527caf55d 100644 --- a/src/public/app/services/utils.ts +++ b/src/public/app/services/utils.ts @@ -124,6 +124,10 @@ function escapeHtml(str: string) { return str.replace(/[&<>"'`=\/]/g, (s) => entityMap[s]); } +export function escapeQuotes(value: string) { + return value.replaceAll("\"", """); +} + function formatSize(size: number) { size = Math.max(Math.round(size / 1024), 1); diff --git a/src/public/app/share.js b/src/public/app/share.ts similarity index 73% rename from src/public/app/share.js rename to src/public/app/share.ts index 3c3282497..912154986 100644 --- a/src/public/app/share.js +++ b/src/public/app/share.ts @@ -3,7 +3,7 @@ * * @param noteId of the given note to be fetched. If false, fetches current note. */ -async function fetchNote(noteId = null) { +async function fetchNote(noteId: string | null = null) { if (!noteId) { noteId = document.body.getAttribute("data-note-id"); } @@ -25,3 +25,9 @@ document.addEventListener( }, false ); + +// workaround to prevent webpack from removing "fetchNote" as dead code: +// add fetchNote as property to the window object +Object.defineProperty(window, "fetchNote", { + value: fetchNote +}); \ No newline at end of file diff --git a/src/public/app/types.d.ts b/src/public/app/types.d.ts index 4c53d181f..b1750afb4 100644 --- a/src/public/app/types.d.ts +++ b/src/public/app/types.d.ts @@ -43,6 +43,7 @@ interface CustomGlobals { appCssNoteIds: string[]; triliumVersion: string; TRILIUM_SAFE_MODE: boolean; + platform?: typeof process.platform; } type RequireMethod = (moduleName: string) => any; diff --git a/src/public/app/widgets/attribute_widgets/attribute_editor.ts b/src/public/app/widgets/attribute_widgets/attribute_editor.ts index 622da6ca9..1547de085 100644 --- a/src/public/app/widgets/attribute_widgets/attribute_editor.ts +++ b/src/public/app/widgets/attribute_widgets/attribute_editor.ts @@ -14,6 +14,7 @@ import type AttributeDetailWidget from "./attribute_detail.js"; import type { CommandData, EventData, EventListener, FilteredCommandNames } from "../../components/app_context.js"; import type { default as FAttribute, AttributeType } from "../../entities/fattribute.js"; import type FNote from "../../entities/fnote.js"; +import { escapeQuotes } from "../../services/utils.js"; const HELP_TEXT = `

${t("attribute_editor.help_text_body1")}

@@ -76,8 +77,8 @@ const TPL = `
-
-
+
+
diff --git a/src/public/app/widgets/basic_widget.ts b/src/public/app/widgets/basic_widget.ts index ec10acde6..46d3b06b9 100644 --- a/src/public/app/widgets/basic_widget.ts +++ b/src/public/app/widgets/basic_widget.ts @@ -193,7 +193,7 @@ export class TypedBasicWidget> extends TypedCompon * Indicates if the widget is enabled. Widgets are enabled by default. Generally setting this to `false` will cause the widget not to be displayed, however it will still be available on the DOM but hidden. * @returns whether the widget is enabled. */ - isEnabled() { + isEnabled(): boolean | null | undefined { return true; } @@ -205,7 +205,7 @@ export class TypedBasicWidget> extends TypedCompon */ doRender() {} - toggleInt(show: boolean) { + toggleInt(show: boolean | null | undefined) { this.$widget.toggleClass("hidden-int", !show); } diff --git a/src/public/app/widgets/buttons/left_pane_toggle.js b/src/public/app/widgets/buttons/left_pane_toggle.ts similarity index 86% rename from src/public/app/widgets/buttons/left_pane_toggle.js rename to src/public/app/widgets/buttons/left_pane_toggle.ts index a5bf2d37e..f8869ad13 100644 --- a/src/public/app/widgets/buttons/left_pane_toggle.js +++ b/src/public/app/widgets/buttons/left_pane_toggle.ts @@ -2,9 +2,11 @@ import options from "../../services/options.js"; import splitService from "../../services/resizer.js"; import CommandButtonWidget from "./command_button.js"; import { t } from "../../services/i18n.js"; +import type { EventData } from "../../components/app_context.js"; export default class LeftPaneToggleWidget extends CommandButtonWidget { - constructor(isHorizontalLayout) { + + constructor(isHorizontalLayout: boolean) { super(); this.class(isHorizontalLayout ? "toggle-button" : "launcher-button"); @@ -32,7 +34,7 @@ export default class LeftPaneToggleWidget extends CommandButtonWidget { splitService.setupLeftPaneResizer(options.is("leftPaneVisible")); } - entitiesReloadedEvent({ loadResults }) { + entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { if (loadResults.isOptionReloaded("leftPaneVisible")) { this.refreshIcon(); } diff --git a/src/public/app/widgets/containers/ribbon_container.js b/src/public/app/widgets/containers/ribbon_container.ts similarity index 78% rename from src/public/app/widgets/containers/ribbon_container.js rename to src/public/app/widgets/containers/ribbon_container.ts index b9517be15..b3ed7fd35 100644 --- a/src/public/app/widgets/containers/ribbon_container.js +++ b/src/public/app/widgets/containers/ribbon_container.ts @@ -1,6 +1,10 @@ import NoteContextAwareWidget from "../note_context_aware_widget.js"; import keyboardActionsService from "../../services/keyboard_actions.js"; import attributeService from "../../services/attributes.js"; +import type CommandButtonWidget from "../buttons/command_button.js"; +import type FNote from "../../entities/fnote.js"; +import type { NoteType } from "../../entities/fnote.js"; +import type { EventData, EventNames } from "../../components/app_context.js"; const TPL = `
@@ -8,11 +12,11 @@ const TPL = ` .ribbon-container { margin-bottom: 5px; } - + .ribbon-top-row { display: flex; } - + .ribbon-tab-container { display: flex; flex-direction: row; @@ -21,10 +25,10 @@ const TPL = ` flex-grow: 1; flex-flow: row wrap; } - + .ribbon-tab-title { color: var(--muted-text-color); - border-bottom: 1px solid var(--main-border-color); + border-bottom: 1px solid var(--main-border-color); min-width: 24px; flex-basis: 24px; max-width: max-content; @@ -36,7 +40,7 @@ const TPL = ` position: relative; top: 3px; } - + .ribbon-tab-title.active { color: var(--main-text-color); border-bottom: 3px solid var(--main-text-color); @@ -44,7 +48,7 @@ const TPL = ` overflow: hidden; text-overflow: ellipsis; } - + .ribbon-tab-title:hover { cursor: pointer; } @@ -52,11 +56,11 @@ const TPL = ` .ribbon-tab-title:hover { color: var(--main-text-color); } - + .ribbon-tab-title:first-of-type { padding-left: 10px; } - + .ribbon-tab-spacer { flex-basis: 0; min-width: 0; @@ -64,41 +68,41 @@ const TPL = ` flex-grow: 1; border-bottom: 1px solid var(--main-border-color); } - + .ribbon-tab-spacer:last-of-type { flex-grow: 1; flex-basis: 0; min-width: 0; max-width: 10000px; } - + .ribbon-button-container { display: flex; - border-bottom: 1px solid var(--main-border-color); + border-bottom: 1px solid var(--main-border-color); margin-right: 5px; } - + .ribbon-button-container > * { position: relative; top: -3px; margin-left: 10px; } - + .ribbon-body { display: none; border-bottom: 1px solid var(--main-border-color); margin-left: 10px; margin-right: 5px; /* needs to have this value so that the bottom border is the same width as the top one */ } - + .ribbon-body.active { display: block; } - + .ribbon-tab-title-label { display: none; } - + .ribbon-tab-title.active .ribbon-tab-title-label { display: inline; } @@ -108,11 +112,21 @@ const TPL = `
- +
`; export default class RibbonContainer extends NoteContextAwareWidget { + + private lastActiveComponentId?: string | null; + private lastNoteType?: NoteType; + + private ribbonWidgets: NoteContextAwareWidget[]; + private buttonWidgets: CommandButtonWidget[]; + private $tabContainer!: JQuery; + private $buttonContainer!: JQuery; + private $bodyContainer!: JQuery; + constructor() { super(); @@ -122,10 +136,10 @@ export default class RibbonContainer extends NoteContextAwareWidget { } isEnabled() { - return super.isEnabled() && this.noteContext.viewScope.viewMode === "default"; + return super.isEnabled() && this.noteContext?.viewScope?.viewMode === "default"; } - ribbon(widget) { + ribbon(widget: NoteContextAwareWidget) { // TODO: Base class super.child(widget); this.ribbonWidgets.push(widget); @@ -133,7 +147,7 @@ export default class RibbonContainer extends NoteContextAwareWidget { return this; } - button(widget) { + button(widget: CommandButtonWidget) { super.child(widget); this.buttonWidgets.push(widget); @@ -163,7 +177,7 @@ export default class RibbonContainer extends NoteContextAwareWidget { }); } - toggleRibbonTab($ribbonTitle, refreshActiveTab = true) { + toggleRibbonTab($ribbonTitle: JQuery, refreshActiveTab = true) { const activate = !$ribbonTitle.hasClass("active"); this.$tabContainer.find(".ribbon-tab-title").removeClass("active"); @@ -181,14 +195,15 @@ export default class RibbonContainer extends NoteContextAwareWidget { const activeChild = this.getActiveRibbonWidget(); - if (activeChild && (refreshActiveTab || !wasAlreadyActive)) { + if (activeChild && (refreshActiveTab || !wasAlreadyActive) && this.noteContext && this.notePath) { const handleEventPromise = activeChild.handleEvent("noteSwitched", { noteContext: this.noteContext, notePath: this.notePath }); if (refreshActiveTab) { if (handleEventPromise) { - handleEventPromise.then(() => activeChild.focus?.()); + handleEventPromise.then(() => (activeChild as any).focus()); // TODO: Base class } else { - activeChild.focus?.(); + // TODO: Base class + (activeChild as any)?.focus(); } } } @@ -203,7 +218,7 @@ export default class RibbonContainer extends NoteContextAwareWidget { await super.noteSwitched(); } - async refreshWithNote(note, noExplicitActivation = false) { + async refreshWithNote(note: FNote, noExplicitActivation = false) { this.lastNoteType = note.type; let $ribbonTabToActivate, $lastActiveRibbon; @@ -211,7 +226,8 @@ export default class RibbonContainer extends NoteContextAwareWidget { this.$tabContainer.empty(); for (const ribbonWidget of this.ribbonWidgets) { - const ret = await ribbonWidget.getTitle(note); + // TODO: Base class for ribbon widget + const ret = await (ribbonWidget as any).getTitle(note); if (!ret.show) { continue; @@ -219,8 +235,8 @@ export default class RibbonContainer extends NoteContextAwareWidget { const $ribbonTitle = $('
') .attr("data-ribbon-component-id", ribbonWidget.componentId) - .attr("data-ribbon-component-name", ribbonWidget.name) - .append($('').addClass(ret.icon).attr("title", ret.title).attr("data-toggle-command", ribbonWidget.toggleCommand)) + .attr("data-ribbon-component-name", (ribbonWidget as any).name as string) // TODO: base class for ribbon widgets + .append($('').addClass(ret.icon).attr("title", ret.title).attr("data-toggle-command", (ribbonWidget as any).toggleCommand)) // TODO: base class .append(" ") .append($('').text(ret.title)); @@ -238,7 +254,7 @@ export default class RibbonContainer extends NoteContextAwareWidget { keyboardActionsService.getActions().then((actions) => { this.$tabContainer.find(".ribbon-tab-title-icon").tooltip({ - title: function () { + title: () => { const toggleCommandName = $(this).attr("data-toggle-command"); const action = actions.find((act) => act.actionName === toggleCommandName); const title = $(this).attr("data-title"); @@ -246,7 +262,7 @@ export default class RibbonContainer extends NoteContextAwareWidget { if (action && action.effectiveShortcuts.length > 0) { return `${title} (${action.effectiveShortcuts.join(", ")})`; } else { - return title; + return title ?? ""; } } }); @@ -263,27 +279,27 @@ export default class RibbonContainer extends NoteContextAwareWidget { } } - isRibbonTabActive(name) { + isRibbonTabActive(name: string) { const $ribbonComponent = this.$widget.find(`.ribbon-tab-title[data-ribbon-component-name='${name}']`); return $ribbonComponent.hasClass("active"); } - ensureOwnedAttributesAreOpen(ntxId) { - if (this.isNoteContext(ntxId) && !this.isRibbonTabActive("ownedAttributes")) { + ensureOwnedAttributesAreOpen(ntxId: string | null | undefined) { + if (ntxId && this.isNoteContext(ntxId) && !this.isRibbonTabActive("ownedAttributes")) { this.toggleRibbonTabWithName("ownedAttributes", ntxId); } } - addNewLabelEvent({ ntxId }) { + addNewLabelEvent({ ntxId }: EventData<"addNewLabel">) { this.ensureOwnedAttributesAreOpen(ntxId); } - addNewRelationEvent({ ntxId }) { + addNewRelationEvent({ ntxId }: EventData<"addNewRelation">) { this.ensureOwnedAttributesAreOpen(ntxId); } - toggleRibbonTabWithName(name, ntxId) { + toggleRibbonTabWithName(name: string, ntxId?: string) { if (!this.isNoteContext(ntxId)) { return false; } @@ -295,23 +311,23 @@ export default class RibbonContainer extends NoteContextAwareWidget { } } - handleEvent(name, data) { + handleEvent(name: T, data: EventData) { const PREFIX = "toggleRibbonTab"; if (name.startsWith(PREFIX)) { let componentName = name.substr(PREFIX.length); componentName = componentName[0].toLowerCase() + componentName.substr(1); - this.toggleRibbonTabWithName(componentName, data.ntxId); + this.toggleRibbonTabWithName(componentName, (data as any).ntxId); } else { return super.handleEvent(name, data); } } - async handleEventInChildren(name, data) { + async handleEventInChildren(name: T, data: EventData) { if (["activeContextChanged", "setNoteContext"].includes(name)) { // won't trigger .refresh(); - await super.handleEventInChildren("setNoteContext", data); + await super.handleEventInChildren("setNoteContext", data as EventData<"activeContextChanged" | "setNoteContext">); } else if (this.isEnabled() || name === "initialRenderComplete") { const activeRibbonWidget = this.getActiveRibbonWidget(); @@ -326,8 +342,12 @@ export default class RibbonContainer extends NoteContextAwareWidget { } } - entitiesReloadedEvent({ loadResults }) { - if (loadResults.isNoteReloaded(this.noteId) && this.lastNoteType !== this.note.type) { + entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { + if (!this.note) { + return; + } + + if (this.noteId && loadResults.isNoteReloaded(this.noteId) && this.lastNoteType !== this.note.type) { // note type influences the list of available ribbon tabs the most // check for the type is so that we don't update on each title rename this.lastNoteType = this.note.type; @@ -338,7 +358,7 @@ export default class RibbonContainer extends NoteContextAwareWidget { } } - noteTypeMimeChangedEvent() { + async noteTypeMimeChangedEvent() { // We are ignoring the event which triggers a refresh since it is usually already done by a different // event and causing a race condition in which the items appear twice. } diff --git a/src/public/app/widgets/dialogs/import.js b/src/public/app/widgets/dialogs/import.js index 236c9d57f..5057115e5 100644 --- a/src/public/app/widgets/dialogs/import.js +++ b/src/public/app/widgets/dialogs/import.js @@ -1,4 +1,4 @@ -import utils from "../../services/utils.js"; +import utils, { escapeQuotes } from "../../services/utils.js"; import treeService from "../../services/tree.js"; import importService from "../../services/import.js"; import options from "../../services/options.js"; @@ -27,21 +27,21 @@ const TPL = ` ${t("import.options")}:
-
-
-
diff --git a/src/public/app/widgets/dialogs/upload_attachments.js b/src/public/app/widgets/dialogs/upload_attachments.js index 5bf9661b1..c59afb635 100644 --- a/src/public/app/widgets/dialogs/upload_attachments.js +++ b/src/public/app/widgets/dialogs/upload_attachments.js @@ -1,5 +1,5 @@ import { t } from "../../services/i18n.js"; -import utils from "../../services/utils.js"; +import utils, { escapeQuotes } from "../../services/utils.js"; import treeService from "../../services/tree.js"; import importService from "../../services/import.js"; import options from "../../services/options.js"; @@ -24,7 +24,7 @@ const TPL = `
${t("upload_attachments.options")}:
-
diff --git a/src/public/app/widgets/editability_select.js b/src/public/app/widgets/editability_select.ts similarity index 78% rename from src/public/app/widgets/editability_select.js rename to src/public/app/widgets/editability_select.ts index 43551413f..04243c015 100644 --- a/src/public/app/widgets/editability_select.js +++ b/src/public/app/widgets/editability_select.ts @@ -1,6 +1,10 @@ import attributeService from "../services/attributes.js"; import NoteContextAwareWidget from "./note_context_aware_widget.js"; import { t } from "../services/i18n.js"; +import type FNote from "../entities/fnote.js"; +import type { EventData } from "../components/app_context.js"; + +type Editability = "auto" | "readOnly" | "autoReadOnlyDisabled"; const TPL = ` `; +// TODO: Deduplicate with server +interface Backlink { + noteId: string; + relationName?: string; + excerpts?: string[]; +} + export default class BacklinksWidget extends NoteContextAwareWidget { + + private $count!: JQuery; + private $items!: JQuery; + private $ticker!: JQuery; + doRender() { this.$widget = $(TPL); this.$count = this.$widget.find(".backlinks-count"); @@ -73,7 +86,7 @@ export default class BacklinksWidget extends NoteContextAwareWidget { this.$count.on("click", () => { this.$items.toggle(); - this.$items.css("max-height", $(window).height() - this.$items.offset().top - 10); + this.$items.css("max-height", ($(window).height() ?? 0) - (this.$items.offset()?.top ?? 0) - 10); if (this.$items.is(":visible")) { this.renderBacklinks(); @@ -83,7 +96,7 @@ export default class BacklinksWidget extends NoteContextAwareWidget { this.contentSized(); } - async refreshWithNote(note) { + async refreshWithNote(note: FNote) { this.clearItems(); if (this.noteContext?.viewScope?.viewMode !== "default") { @@ -92,7 +105,8 @@ export default class BacklinksWidget extends NoteContextAwareWidget { } // can't use froca since that would count only relations from loaded notes - const resp = await server.get(`note-map/${this.noteId}/backlink-count`); + // TODO: Deduplicate response type + const resp = await server.get<{ count: number }>(`note-map/${this.noteId}/backlink-count`); if (!resp || !resp.count) { this.toggle(false); @@ -106,7 +120,7 @@ export default class BacklinksWidget extends NoteContextAwareWidget { ); } - toggle(show) { + toggle(show: boolean) { this.$widget.toggleClass("hidden-no-content", !show); } @@ -121,7 +135,7 @@ export default class BacklinksWidget extends NoteContextAwareWidget { this.$items.empty(); - const backlinks = await server.get(`note-map/${this.noteId}/backlinks`); + const backlinks = await server.get(`note-map/${this.noteId}/backlinks`); if (!backlinks.length) { return; @@ -143,7 +157,7 @@ export default class BacklinksWidget extends NoteContextAwareWidget { if (backlink.relationName) { $item.append($("

").text(`${t("zpetne_odkazy.relation")}: ${backlink.relationName}`)); } else { - $item.append(...backlink.excerpts); + $item.append(...backlink.excerpts ?? []); } this.$items.append($item); diff --git a/src/public/app/widgets/geo_map.ts b/src/public/app/widgets/geo_map.ts index 46fb2e414..f2fcfe7b9 100644 --- a/src/public/app/widgets/geo_map.ts +++ b/src/public/app/widgets/geo_map.ts @@ -40,7 +40,7 @@ export default class GeoMapWidget extends NoteContextAwareWidget { const L = (await import("leaflet")).default; const map = L.map(this.$container[0], { - + worldCopyJump: true }); this.map = map; diff --git a/src/public/app/widgets/note_context_aware_widget.ts b/src/public/app/widgets/note_context_aware_widget.ts index 4684c3079..9f9d2448b 100644 --- a/src/public/app/widgets/note_context_aware_widget.ts +++ b/src/public/app/widgets/note_context_aware_widget.ts @@ -10,9 +10,9 @@ import type NoteContext from "../components/note_context.js"; class NoteContextAwareWidget extends BasicWidget { protected noteContext?: NoteContext; - isNoteContext(ntxId: string | null | undefined) { + isNoteContext(ntxId: string | string[] | null | undefined) { if (Array.isArray(ntxId)) { - return this.noteContext && ntxId.includes(this.noteContext.ntxId); + return this.noteContext && this.noteContext.ntxId && ntxId.includes(this.noteContext.ntxId); } else { return this.noteContext && this.noteContext.ntxId === ntxId; } @@ -54,7 +54,7 @@ class NoteContextAwareWidget extends BasicWidget { * * @returns true when an active note exists */ - isEnabled() { + isEnabled(): boolean | null | undefined { return !!this.note; } diff --git a/src/public/app/widgets/note_detail.js b/src/public/app/widgets/note_detail.js index 6ffed4514..3fad9f138 100644 --- a/src/public/app/widgets/note_detail.js +++ b/src/public/app/widgets/note_detail.js @@ -147,11 +147,14 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { */ checkFullHeight() { // https://github.com/zadam/trilium/issues/2522 - this.$widget.toggleClass( - "full-height", - (!this.noteContext.hasNoteList() && ["canvas", "webView", "noteMap", "mindMap", "geoMap"].includes(this.type) && this.mime !== "text/x-sqlite;schema=trilium") || - this.noteContext.viewScope.viewMode === "attachments" - ); + const isBackendNote = this.noteContext?.noteId === "_backendLog"; + const isSqlNote = this.mime === "text/x-sqlite;schema=trilium"; + const isFullHeightNoteType = ["canvas", "webView", "noteMap", "mindMap", "geoMap"].includes(this.type); + const isFullHeight = (!this.noteContext.hasNoteList() && isFullHeightNoteType && !isSqlNote) + || this.noteContext.viewScope.viewMode === "attachments" + || isBackendNote; + + this.$widget.toggleClass("full-height", isFullHeight); } getTypeWidget() { diff --git a/src/public/app/widgets/note_list.js b/src/public/app/widgets/note_list.ts similarity index 72% rename from src/public/app/widgets/note_list.js rename to src/public/app/widgets/note_list.ts index c202bc523..97fd19bef 100644 --- a/src/public/app/widgets/note_list.js +++ b/src/public/app/widgets/note_list.ts @@ -1,5 +1,7 @@ import NoteContextAwareWidget from "./note_context_aware_widget.js"; import NoteListRenderer from "../services/note_list_renderer.js"; +import type FNote from "../entities/fnote.js"; +import type { EventData } from "../components/app_context.js"; const TPL = `

@@ -8,19 +10,25 @@ const TPL = ` min-height: 0; overflow: auto; } - + .note-list-widget .note-list { padding: 10px; } - +
`; export default class NoteListWidget extends NoteContextAwareWidget { + + private $content!: JQuery; + private isIntersecting?: boolean; + private noteIdRefreshed?: string; + private shownNoteId?: string | null; + isEnabled() { - return super.isEnabled() && this.noteContext.hasNoteList(); + return super.isEnabled() && this.noteContext?.hasNoteList(); } doRender() { @@ -50,13 +58,13 @@ export default class NoteListWidget extends NoteContextAwareWidget { // console.log(`${this.noteIdRefreshed} === ${this.noteId}`, this.noteIdRefreshed === this.noteId); // console.log("this.shownNoteId !== this.noteId", this.shownNoteId !== this.noteId); - if (this.isIntersecting && this.noteIdRefreshed === this.noteId && this.shownNoteId !== this.noteId) { + if (this.note && this.isIntersecting && this.noteIdRefreshed === this.noteId && this.shownNoteId !== this.noteId) { this.shownNoteId = this.noteId; this.renderNoteList(this.note); } } - async renderNoteList(note) { + async renderNoteList(note: FNote) { const noteListRenderer = new NoteListRenderer(this.$content, note, note.getChildNoteIds()); await noteListRenderer.renderList(); } @@ -67,8 +75,8 @@ export default class NoteListWidget extends NoteContextAwareWidget { await super.refresh(); } - async refreshNoteListEvent({ noteId }) { - if (this.isNote(noteId)) { + async refreshNoteListEvent({ noteId }: EventData<"refreshNoteList">) { + if (this.isNote(noteId) && this.note) { await this.renderNoteList(this.note); } } @@ -78,7 +86,7 @@ export default class NoteListWidget extends NoteContextAwareWidget { * If it's evaluated before note detail, then it's clearly intersected (visible) although after note detail load * it is not intersected (visible) anymore. */ - noteDetailRefreshedEvent({ ntxId }) { + noteDetailRefreshedEvent({ ntxId }: EventData<"noteDetailRefreshed">) { if (!this.isNoteContext(ntxId)) { return; } @@ -88,14 +96,14 @@ export default class NoteListWidget extends NoteContextAwareWidget { setTimeout(() => this.checkRenderStatus(), 100); } - notesReloadedEvent({ noteIds }) { - if (noteIds.includes(this.noteId)) { + notesReloadedEvent({ noteIds }: EventData<"notesReloaded">) { + if (this.noteId && noteIds.includes(this.noteId)) { this.refresh(); } } - entitiesReloadedEvent({ loadResults }) { - if (loadResults.getAttributeRows().find((attr) => attr.noteId === this.noteId && ["viewType", "expanded", "pageSize"].includes(attr.name))) { + entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { + if (loadResults.getAttributeRows().find((attr) => attr.noteId === this.noteId && attr.name && ["viewType", "expanded", "pageSize"].includes(attr.name))) { this.shownNoteId = null; // force render this.checkRenderStatus(); diff --git a/src/public/app/widgets/note_map.ts b/src/public/app/widgets/note_map.ts index 51401294d..f8c34f9d5 100644 --- a/src/public/app/widgets/note_map.ts +++ b/src/public/app/widgets/note_map.ts @@ -163,7 +163,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget { private themeStyle!: string; private $container!: JQuery; private $styleResolver!: JQuery; - private graph!: ForceGraph; + graph!: ForceGraph; private noteIdToSizeMap!: Record; private zoomLevel!: number; private nodes!: Node[]; diff --git a/src/public/app/widgets/note_title.js b/src/public/app/widgets/note_title.ts similarity index 76% rename from src/public/app/widgets/note_title.js rename to src/public/app/widgets/note_title.ts index 570b38b56..8cb333af9 100644 --- a/src/public/app/widgets/note_title.js +++ b/src/public/app/widgets/note_title.ts @@ -3,10 +3,11 @@ import NoteContextAwareWidget from "./note_context_aware_widget.js"; import protectedSessionHolder from "../services/protected_session_holder.js"; import server from "../services/server.js"; import SpacedUpdate from "../services/spaced_update.js"; -import appContext from "../components/app_context.js"; +import appContext, { type EventData } from "../components/app_context.js"; import branchService from "../services/branches.js"; import shortcutService from "../services/shortcuts.js"; import utils from "../services/utils.js"; +import type FNote from "../entities/fnote.js"; const TPL = `
@@ -33,13 +34,20 @@ const TPL = `
`; export default class NoteTitleWidget extends NoteContextAwareWidget { + + private $noteTitle!: JQuery; + private deleteNoteOnEscape: boolean; + private spacedUpdate: SpacedUpdate; + constructor() { super(); this.spacedUpdate = new SpacedUpdate(async () => { const title = this.$noteTitle.val(); - protectedSessionHolder.touchProtectedSessionIfNecessary(this.note); + if (this.note) { + protectedSessionHolder.touchProtectedSessionIfNecessary(this.note); + } await server.put(`notes/${this.noteId}/title`, { title }, this.componentId); }); @@ -62,37 +70,36 @@ export default class NoteTitleWidget extends NoteContextAwareWidget { }); shortcutService.bindElShortcut(this.$noteTitle, "esc", () => { - if (this.deleteNoteOnEscape && this.noteContext.isActive()) { + if (this.deleteNoteOnEscape && this.noteContext?.isActive() && this.noteContext?.note) { branchService.deleteNotes(Object.values(this.noteContext.note.parentToBranch)); } }); shortcutService.bindElShortcut(this.$noteTitle, "return", () => { - this.triggerCommand("focusOnDetail", { ntxId: this.noteContext.ntxId }); + this.triggerCommand("focusOnDetail", { ntxId: this.noteContext?.ntxId }); }); } - async refreshWithNote(note) { - const isReadOnly = (note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable()) || utils.isLaunchBarConfig(note.noteId) || this.noteContext.viewScope.viewMode !== "default"; + async refreshWithNote(note: FNote) { + const isReadOnly = (note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable()) || utils.isLaunchBarConfig(note.noteId) || this.noteContext?.viewScope?.viewMode !== "default"; - this.$noteTitle.val(isReadOnly ? await this.noteContext.getNavigationTitle() : note.title); + this.$noteTitle.val(isReadOnly ? await this.noteContext?.getNavigationTitle() || "" : note.title); this.$noteTitle.prop("readonly", isReadOnly); this.setProtectedStatus(note); } - /** @param {FNote} note */ - setProtectedStatus(note) { + setProtectedStatus(note: FNote) { this.$noteTitle.toggleClass("protected", !!note.isProtected); } - async beforeNoteSwitchEvent({ noteContext }) { + async beforeNoteSwitchEvent({ noteContext }: EventData<"beforeNoteSwitch">) { if (this.isNoteContext(noteContext.ntxId)) { await this.spacedUpdate.updateNowIfNecessary(); } } - async beforeNoteContextRemoveEvent({ ntxIds }) { + async beforeNoteContextRemoveEvent({ ntxIds }: EventData<"beforeNoteContextRemove">) { if (this.isNoteContext(ntxIds)) { await this.spacedUpdate.updateNowIfNecessary(); } @@ -112,8 +119,8 @@ export default class NoteTitleWidget extends NoteContextAwareWidget { } } - entitiesReloadedEvent({ loadResults }) { - if (loadResults.isNoteReloaded(this.noteId)) { + entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { + if (loadResults.isNoteReloaded(this.noteId) && this.note) { // not updating the title specifically since the synced title might be older than what the user is currently typing this.setProtectedStatus(this.note); } diff --git a/src/public/app/widgets/note_type.js b/src/public/app/widgets/note_type.js index dbf0008d5..150acf4a9 100644 --- a/src/public/app/widgets/note_type.js +++ b/src/public/app/widgets/note_type.js @@ -21,6 +21,7 @@ const NOTE_TYPES = [ { type: "mermaid", mime: "text/mermaid", title: t("note_types.mermaid-diagram"), selectable: true }, { type: "book", mime: "", title: t("note_types.book"), selectable: true }, { type: "webView", mime: "", title: t("note_types.web-view"), selectable: true }, + { type: "geoMap", mime: "application/json", title: t("note_types.geo-map"), selectable: true }, { type: "code", mime: "text/plain", title: t("note_types.code"), selectable: true } ]; diff --git a/src/public/app/widgets/ribbon_widgets/note_info_widget.js b/src/public/app/widgets/ribbon_widgets/note_info_widget.ts similarity index 75% rename from src/public/app/widgets/ribbon_widgets/note_info_widget.js rename to src/public/app/widgets/ribbon_widgets/note_info_widget.ts index 5d5c47bf0..de24c5f33 100644 --- a/src/public/app/widgets/ribbon_widgets/note_info_widget.js +++ b/src/public/app/widgets/ribbon_widgets/note_info_widget.ts @@ -3,6 +3,8 @@ import { t } from "../../services/i18n.js"; import NoteContextAwareWidget from "../note_context_aware_widget.js"; import server from "../../services/server.js"; import utils from "../../services/utils.js"; +import type { EventData } from "../../components/app_context.js"; +import type FNote from "../../entities/fnote.js"; const TPL = `
@@ -10,18 +12,18 @@ const TPL = ` .note-info-widget { padding: 12px; } - + .note-info-widget-table { - max-width: 100%; + max-width: 100%; display: block; overflow-x: auto; white-space: nowrap; - } - + } + .note-info-widget-table td, .note-info-widget-table th { padding: 5px; } - + .note-info-mime { max-width: 13em; overflow: hidden; @@ -61,7 +63,33 @@ const TPL = `
`; +// TODO: Deduplicate with server +interface NoteSizeResponse { + noteSize: number; +} + +interface SubtreeSizeResponse { + subTreeNoteCount: number; + subTreeSize: number; +} + +interface MetadataResponse { + dateCreated: number; + dateModified: number; +} + export default class NoteInfoWidget extends NoteContextAwareWidget { + + private $noteId!: JQuery; + private $dateCreated!: JQuery; + private $dateModified!: JQuery; + private $type!: JQuery; + private $mime!: JQuery; + private $noteSizesWrapper!: JQuery; + private $noteSize!: JQuery; + private $subTreeSize!: JQuery; + private $calculateButton!: JQuery; + get name() { return "noteInfo"; } @@ -71,7 +99,7 @@ export default class NoteInfoWidget extends NoteContextAwareWidget { } isEnabled() { - return this.note; + return !!this.note; } getTitle() { @@ -104,10 +132,10 @@ export default class NoteInfoWidget extends NoteContextAwareWidget { this.$noteSize.empty().append($('')); this.$subTreeSize.empty().append($('')); - const noteSizeResp = await server.get(`stats/note-size/${this.noteId}`); + const noteSizeResp = await server.get(`stats/note-size/${this.noteId}`); this.$noteSize.text(utils.formatSize(noteSizeResp.noteSize)); - const subTreeResp = await server.get(`stats/subtree-size/${this.noteId}`); + const subTreeResp = await server.get(`stats/subtree-size/${this.noteId}`); if (subTreeResp.subTreeNoteCount > 1) { this.$subTreeSize.text(t("note_info_widget.subtree_size", { size: utils.formatSize(subTreeResp.subTreeSize), count: subTreeResp.subTreeNoteCount })); @@ -117,8 +145,8 @@ export default class NoteInfoWidget extends NoteContextAwareWidget { }); } - async refreshWithNote(note) { - const metadata = await server.get(`notes/${this.noteId}/metadata`); + async refreshWithNote(note: FNote) { + const metadata = await server.get(`notes/${this.noteId}/metadata`); this.$noteId.text(note.noteId); this.$dateCreated.text(formatDateTime(metadata.dateCreated)).attr("title", metadata.dateCreated); @@ -137,8 +165,8 @@ export default class NoteInfoWidget extends NoteContextAwareWidget { this.$noteSizesWrapper.hide(); } - entitiesReloadedEvent({ loadResults }) { - if (loadResults.isNoteReloaded(this.noteId) || loadResults.isNoteContentReloaded(this.noteId)) { + entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { + if (this.noteId && (loadResults.isNoteReloaded(this.noteId) || loadResults.isNoteContentReloaded(this.noteId))) { this.refresh(); } } diff --git a/src/public/app/widgets/ribbon_widgets/note_map.js b/src/public/app/widgets/ribbon_widgets/note_map.ts similarity index 86% rename from src/public/app/widgets/ribbon_widgets/note_map.js rename to src/public/app/widgets/ribbon_widgets/note_map.ts index e9b8a6e05..911636b2d 100644 --- a/src/public/app/widgets/ribbon_widgets/note_map.js +++ b/src/public/app/widgets/ribbon_widgets/note_map.ts @@ -8,18 +8,18 @@ const TPL = ` .note-map-ribbon-widget { position: relative; } - + .note-map-ribbon-widget .note-map-container { height: 300px; } - + .open-full-button, .collapse-button { position: absolute; right: 5px; bottom: 5px; z-index: 1000; } - + .style-resolver { color: var(--muted-text-color); display: none; @@ -33,6 +33,13 @@ const TPL = `
`; export default class NoteMapRibbonWidget extends NoteContextAwareWidget { + + private openState!: "small" | "full"; + private noteMapWidget: NoteMapWidget; + private $container!: JQuery; + private $openFullButton!: JQuery; + private $collapseButton!: JQuery; + constructor() { super(); @@ -106,7 +113,7 @@ export default class NoteMapRibbonWidget extends NoteContextAwareWidget { setSmallSize() { const SMALL_SIZE_HEIGHT = 300; - const width = this.$widget.width(); + const width = this.$widget.width() ?? 0; this.$widget.find(".note-map-container").height(SMALL_SIZE_HEIGHT).width(width); } @@ -114,9 +121,11 @@ export default class NoteMapRibbonWidget extends NoteContextAwareWidget { setFullHeight() { const { top } = this.$widget[0].getBoundingClientRect(); - const height = $(window).height() - top; - const width = this.$widget.width(); + const height = ($(window).height() ?? 0) - top; + const width = (this.$widget.width() ?? 0); - this.$widget.find(".note-map-container").height(height).width(width); + this.$widget.find(".note-map-container") + .height(height) + .width(width); } } diff --git a/src/public/app/widgets/ribbon_widgets/note_paths.js b/src/public/app/widgets/ribbon_widgets/note_paths.ts similarity index 84% rename from src/public/app/widgets/ribbon_widgets/note_paths.js rename to src/public/app/widgets/ribbon_widgets/note_paths.ts index a537303f9..1bb95cf73 100644 --- a/src/public/app/widgets/ribbon_widgets/note_paths.js +++ b/src/public/app/widgets/ribbon_widgets/note_paths.ts @@ -2,6 +2,9 @@ import NoteContextAwareWidget from "../note_context_aware_widget.js"; import treeService from "../../services/tree.js"; import linkService from "../../services/link.js"; import { t } from "../../services/i18n.js"; +import type FNote from "../../entities/fnote.js"; +import type { NotePathRecord } from "../../entities/fnote.js"; +import type { EventData } from "../../components/app_context.js"; const TPL = `
@@ -37,6 +40,10 @@ const TPL = `
`; export default class NotePathsWidget extends NoteContextAwareWidget { + + private $notePathIntro!: JQuery; + private $notePathList!: JQuery; + get name() { return "notePaths"; } @@ -59,13 +66,12 @@ export default class NotePathsWidget extends NoteContextAwareWidget { this.$notePathIntro = this.$widget.find(".note-path-intro"); this.$notePathList = this.$widget.find(".note-path-list"); - this.$widget.on("show.bs.dropdown", () => this.renderDropdown()); } - async refreshWithNote(note) { + async refreshWithNote(note: FNote) { this.$notePathList.empty(); - if (this.noteId === "root") { + if (!this.note || this.noteId === "root") { this.$notePathList.empty().append(await this.getRenderedPath("root")); return; @@ -90,7 +96,7 @@ export default class NotePathsWidget extends NoteContextAwareWidget { this.$notePathList.empty().append(...renderedPaths); } - async getRenderedPath(notePath, notePathRecord = null) { + async getRenderedPath(notePath: string, notePathRecord: NotePathRecord | null = null) { const title = await treeService.getNotePathTitle(notePath); const $noteLink = await linkService.createLink(notePath, { title }); @@ -128,8 +134,9 @@ export default class NotePathsWidget extends NoteContextAwareWidget { return $("
  • ").append($noteLink); } - entitiesReloadedEvent({ loadResults }) { - if (loadResults.getBranchRows().find((branch) => branch.noteId === this.noteId) || loadResults.isNoteReloaded(this.noteId)) { + entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { + if (loadResults.getBranchRows().find((branch) => branch.noteId === this.noteId) || + (this.noteId != null && loadResults.isNoteReloaded(this.noteId))) { this.refresh(); } } diff --git a/src/public/app/widgets/ribbon_widgets/similar_notes.js b/src/public/app/widgets/ribbon_widgets/similar_notes.ts similarity index 76% rename from src/public/app/widgets/ribbon_widgets/similar_notes.js rename to src/public/app/widgets/ribbon_widgets/similar_notes.ts index 7603a7518..f169b559d 100644 --- a/src/public/app/widgets/ribbon_widgets/similar_notes.js +++ b/src/public/app/widgets/ribbon_widgets/similar_notes.ts @@ -3,10 +3,12 @@ import linkService from "../../services/link.js"; import server from "../../services/server.js"; import froca from "../../services/froca.js"; import NoteContextAwareWidget from "../note_context_aware_widget.js"; +import type FNote from "../../entities/fnote.js"; +import type { EventData } from "../../components/app_context.js"; const TPL = `
    -
    - + + data-bs-toggle="tooltip" + title="${escapeQuotes(t("sync_status.connected_with_changes"))}"> - + + data-bs-toggle="tooltip" + title="${escapeQuotes(t("sync_status.disconnected_with_changes"))}"> - + title="${escapeQuotes(t("sync_status.disconnected_no_changes"))}"> - + title="${escapeQuotes(t("sync_status.in_progress"))}">
    diff --git a/src/public/icon.png b/src/public/icon.png index ee21c7ed7..2d4da35c4 100644 Binary files a/src/public/icon.png and b/src/public/icon.png differ diff --git a/src/public/stylesheets/print.css b/src/public/stylesheets/print.css index d9674458e..d40396259 100644 --- a/src/public/stylesheets/print.css +++ b/src/public/stylesheets/print.css @@ -26,6 +26,11 @@ border-radius: 2pt !important; } + span[style] { + print-color-adjust: exact; + -webkit-print-color-adjust: exact; + } + /* Fix visibility of checkbox checkmarks see https://github.com/TriliumNext/Notes/issues/901 */ .ck-editor__editable.ck-content .todo-list .todo-list__label > span[contenteditable="false"] > input[checked]::after { diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css index 325872819..24cfee62f 100644 --- a/src/public/stylesheets/style.css +++ b/src/public/stylesheets/style.css @@ -396,6 +396,10 @@ body.desktop .dropdown-menu { color: var(--dropdown-item-icon-destructive-color); } +.dropdown-item > span:not([class]) { + width: 100%; +} + .CodeMirror { height: 100%; background: inherit; diff --git a/src/public/stylesheets/theme-next/notes/text.css b/src/public/stylesheets/theme-next/notes/text.css index baaf207c9..4100564d1 100644 --- a/src/public/stylesheets/theme-next/notes/text.css +++ b/src/public/stylesheets/theme-next/notes/text.css @@ -31,6 +31,7 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child { padding: 0px 10px; letter-spacing: 0.5px; font-weight: bold; + top: 0; } .attachment-content-wrapper pre code, diff --git a/src/public/stylesheets/theme-next/shell.css b/src/public/stylesheets/theme-next/shell.css index 65787bed1..d5a19af97 100644 --- a/src/public/stylesheets/theme-next/shell.css +++ b/src/public/stylesheets/theme-next/shell.css @@ -1339,7 +1339,7 @@ body .calendar-dropdown-widget .calendar-body a:hover { } /* Item title for deleted notes */ -.recent-changes-content ul li.deleted-note .note-title { +.recent-changes-content ul li.deleted-note .note-title > .note-title { text-decoration: line-through; } diff --git a/src/public/translations/de/translation.json b/src/public/translations/de/translation.json index 838cd50f6..b0c9a91c6 100644 --- a/src/public/translations/de/translation.json +++ b/src/public/translations/de/translation.json @@ -1350,7 +1350,7 @@ "mermaid-diagram": "Mermaid Diagram", "canvas": "Canvas", "web-view": "Webansicht", - "mind-map": "Mind Map (Beta)", + "mind-map": "Mind Map", "file": "Datei", "image": "Bild", "launcher": "Launcher", diff --git a/src/public/translations/en/translation.json b/src/public/translations/en/translation.json index b49188285..d58f0fd56 100644 --- a/src/public/translations/en/translation.json +++ b/src/public/translations/en/translation.json @@ -1403,7 +1403,7 @@ "mermaid-diagram": "Mermaid Diagram", "canvas": "Canvas", "web-view": "Web View", - "mind-map": "Mind Map (Beta)", + "mind-map": "Mind Map", "file": "File", "image": "Image", "launcher": "Launcher", diff --git a/src/public/translations/es/translation.json b/src/public/translations/es/translation.json index 92dffc5cc..8499975a8 100644 --- a/src/public/translations/es/translation.json +++ b/src/public/translations/es/translation.json @@ -1403,7 +1403,7 @@ "mermaid-diagram": "Diagrama Mermaid", "canvas": "Lienzo", "web-view": "Vista Web", - "mind-map": "Mapa Mental (beta)", + "mind-map": "Mapa Mental", "file": "Archivo", "image": "Imagen", "launcher": "Lanzador", diff --git a/src/public/translations/fr/translation.json b/src/public/translations/fr/translation.json index c3a080092..7a680560d 100644 --- a/src/public/translations/fr/translation.json +++ b/src/public/translations/fr/translation.json @@ -1351,7 +1351,7 @@ "mermaid-diagram": "Diagramme Mermaid", "canvas": "Canevas", "web-view": "Affichage Web", - "mind-map": "Carte mentale (Beta)", + "mind-map": "Carte mentale", "file": "Fichier", "image": "Image", "launcher": "Raccourci", diff --git a/src/public/translations/ro/translation.json b/src/public/translations/ro/translation.json index 9ffb158fd..87be0aa79 100644 --- a/src/public/translations/ro/translation.json +++ b/src/public/translations/ro/translation.json @@ -1367,7 +1367,7 @@ "canvas": "Schiță", "code": "Cod sursă", "mermaid-diagram": "Diagramă Mermaid", - "mind-map": "Hartă mentală (beta)", + "mind-map": "Hartă mentală", "note-map": "Hartă notițe", "relation-map": "Hartă relații", "render-note": "Randare notiță", diff --git a/src/routes/api/note_map.ts b/src/routes/api/note_map.ts index b08c03d1f..684227009 100644 --- a/src/routes/api/note_map.ts +++ b/src/routes/api/note_map.ts @@ -6,6 +6,12 @@ import type BNote from "../../becca/entities/bnote.js"; import type BAttribute from "../../becca/entities/battribute.js"; import type { Request } from "express"; +interface Backlink { + noteId: string; + relationName?: string; + excerpts?: string[]; +} + function buildDescendantCountMap(noteIdsToCount: string[]) { if (!Array.isArray(noteIdsToCount)) { throw new Error("noteIdsToCount: type error"); @@ -325,7 +331,7 @@ function findExcerpts(sourceNote: BNote, referencedNoteId: string) { return excerpts; } -function getFilteredBacklinks(note: BNote) { +function getFilteredBacklinks(note: BNote): BAttribute[] { return ( note .getTargetRelations() @@ -344,7 +350,7 @@ function getBacklinkCount(req: Request) { }; } -function getBacklinks(req: Request) { +function getBacklinks(req: Request): Backlink[] { const { noteId } = req.params; const note = becca.getNoteOrThrow(noteId); diff --git a/src/services/config.ts b/src/services/config.ts index 43ecc39da..dbbf644b5 100644 --- a/src/services/config.ts +++ b/src/services/config.ts @@ -5,6 +5,7 @@ import fs from "fs"; import dataDir from "./data_dir.js"; import path from "path"; import resourceDir from "./resource_dir.js"; +import { envToBoolean } from "./utils.js"; const configSampleFilePath = path.resolve(resourceDir.RESOURCE_DIR, "config-sample.ini"); @@ -14,6 +15,79 @@ if (!fs.existsSync(dataDir.CONFIG_INI_PATH)) { fs.writeFileSync(dataDir.CONFIG_INI_PATH, configSample); } -const config = ini.parse(fs.readFileSync(dataDir.CONFIG_INI_PATH, "utf-8")); +const iniConfig = ini.parse(fs.readFileSync(dataDir.CONFIG_INI_PATH, "utf-8")); + +export interface TriliumConfig { + General: { + instanceName: string; + noAuthentication: boolean; + noBackup: boolean; + noDesktopIcon: boolean; + }; + Network: { + host: string; + port: string; + https: boolean; + certPath: string; + keyPath: string; + trustedReverseProxy: boolean | string; + }; + Sync: { + syncServerHost: string; + syncServerTimeout: string; + syncProxy: string; + }; +} + +//prettier-ignore +const config: TriliumConfig = { + + General: { + instanceName: + process.env.TRILIUM_GENERAL_INSTANCENAME || iniConfig.General.instanceName || "", + + noAuthentication: + envToBoolean(process.env.TRILIUM_GENERAL_NOAUTHENTICATION) || iniConfig.General.noAuthentication || false, + + noBackup: + envToBoolean(process.env.TRILIUM_GENERAL_NOBACKUP) || iniConfig.General.noBackup || false, + + noDesktopIcon: + envToBoolean(process.env.TRILIUM_GENERAL_NODESKTOPICON) || iniConfig.General.noDesktopIcon || false + }, + + Network: { + host: + process.env.TRILIUM_NETWORK_HOST || iniConfig.Network.host || "0.0.0.0", + + port: + process.env.TRILIUM_NETWORK_PORT || iniConfig.Network.port || "3000", + + https: + envToBoolean(process.env.TRILIUM_NETWORK_HTTPS) || iniConfig.Network.https || false, + + certPath: + process.env.TRILIUM_NETWORK_CERTPATH || iniConfig.Network.certPath || "", + + keyPath: + process.env.TRILIUM_NETWORK_KEYPATH || iniConfig.Network.keyPath || "", + + trustedReverseProxy: + process.env.TRILIUM_NETWORK_TRUSTEDREVERSEPROXY || iniConfig.Network.trustedReverseProxy || false + }, + + Sync: { + syncServerHost: + process.env.TRILIUM_SYNC_SERVER_HOST || iniConfig?.Sync?.syncServerHost || "", + + syncServerTimeout: + process.env.TRILIUM_SYNC_SERVER_TIMEOUT || iniConfig?.Sync?.syncServerTimeout || "120000", + + syncProxy: + // additionally checking in iniConfig for inconsistently named syncProxy for backwards compatibility + process.env.TRILIUM_SYNC_SERVER_PROXY || iniConfig?.Sync?.syncProxy || iniConfig?.Sync?.syncServerProxy || "" + } + +}; export default config; diff --git a/src/services/import/utils.spec.ts b/src/services/import/utils.spec.ts new file mode 100644 index 000000000..abd33e025 --- /dev/null +++ b/src/services/import/utils.spec.ts @@ -0,0 +1,103 @@ +import { describe, it, expect } from "vitest"; +import importUtils from "./utils.js"; + +type TestCase any> = [desc: string, fnParams: Parameters, expected: ReturnType]; + +describe("#extractHtmlTitle", () => { + const htmlWithNoTitle = ` + + +
    abc
    + + `; + + const htmlWithTitle = ` + + Test Title + + +
    abc
    + + `; + + const htmlWithTitleWOpeningBracket = ` + + Test < Title + + +
    abc
    + + `; + + // prettier-ignore + const testCases: TestCase[] = [ + [ + "w/ existing tag, it should return the content of the title tag", + [htmlWithTitle], + "Test Title" + ], + [ + // @TriliumNextTODO: this seems more like an unwanted behaviour to me – check if this needs rather fixing + "with existing <title> tag, that includes an opening HTML tag '<', it should return null", + [htmlWithTitleWOpeningBracket], + null + ], + [ + "w/o an existing <title> tag, it should reutrn null", + [htmlWithNoTitle], + null + ], + [ + "w/ empty string content, it should return null", + [""], + null + ] + ]; + + testCases.forEach((testCase) => { + const [desc, fnParams, expected] = testCase; + return it(desc, () => { + const actual = importUtils.extractHtmlTitle(...fnParams); + expect(actual).toStrictEqual(expected); + }); + }); +}); + +describe("#handleH1", () => { + // prettier-ignore + const testCases: TestCase<typeof importUtils.handleH1>[] = [ + [ + "w/ single <h1> tag w/ identical text content as the title tag: the <h1> tag should be stripped", + ["<h1>Title</h1>", "Title"], + "" + ], + [ + "w/ multiple <h1> tags, with the fist matching the title tag: the first <h1> tag should be stripped and subsequent tags converted to <h2>", + ["<h1>Title</h1><h1>Header 1</h1><h1>Header 2</h1>", "Title"], + "<h2>Header 1</h2><h2>Header 2</h2>" + ], + [ + "w/ no <h1> tag and only <h2> tags, it should not cause any changes and return the same content", + ["<h2>Heading 1</h2><h2>Heading 2</h2>", "Title"], + "<h2>Heading 1</h2><h2>Heading 2</h2>" + ], + [ + "w/ multiple <h1> tags, and the 1st matching the title tag, it should strip ONLY the very first occurence of the <h1> tags in the returned content", + ["<h1>Topic ABC</h1><h1>Heading 1</h1><h1>Topic ABC</h1>", "Topic ABC"], + "<h2>Heading 1</h2><h2>Topic ABC</h2>" + ], + [ + "w/ multiple <h1> tags, and the 1st matching NOT the title tag, it should NOT strip any other <h1> tags", + ["<h1>Introduction</h1><h1>Topic ABC</h1><h1>Summary</h1>", "Topic ABC"], + "<h2>Introduction</h2><h2>Topic ABC</h2><h2>Summary</h2>" + ] + ]; + + testCases.forEach((testCase) => { + const [desc, fnParams, expected] = testCase; + return it(desc, () => { + const actual = importUtils.handleH1(...fnParams); + expect(actual).toStrictEqual(expected); + }); + }); +}); diff --git a/src/services/import/utils.ts b/src/services/import/utils.ts index ec4bbf35a..41c42ae22 100644 --- a/src/services/import/utils.ts +++ b/src/services/import/utils.ts @@ -1,14 +1,19 @@ "use strict"; function handleH1(content: string, title: string) { - content = content.replace(/<h1[^>]*>([^<]*)<\/h1>/gi, (match, text) => { - if (title.trim() === text.trim()) { - return ""; // remove whole H1 tag - } else { - return `<h2>${text}</h2>`; + let isFirstH1Handled = false; + + return content.replace(/<h1[^>]*>([^<]*)<\/h1>/gi, (match, text) => { + const convertedContent = `<h2>${text}</h2>`; + + // strip away very first found h1 tag, if it matches the title + if (!isFirstH1Handled) { + isFirstH1Handled = true; + return title.trim() === text.trim() ? "" : convertedContent; } + + return convertedContent; }); - return content; } function extractHtmlTitle(content: string): string | null { diff --git a/src/services/scheduler.ts b/src/services/scheduler.ts index 17edfe6f1..2c0151887 100644 --- a/src/services/scheduler.ts +++ b/src/services/scheduler.ts @@ -19,7 +19,7 @@ function getRunAtHours(note: BNote): number[] { } function runNotesWithLabel(runAttrValue: string) { - const instanceName = config.General ? config.General.instanceName : null; + const instanceName = config.General.instanceName; const currentHours = new Date().getHours(); const notes = attributeService.getNotesWithLabel("run", runAttrValue); diff --git a/src/services/sync_options.ts b/src/services/sync_options.ts index b7dc7f091..ade405f46 100644 --- a/src/services/sync_options.ts +++ b/src/services/sync_options.ts @@ -1,7 +1,6 @@ "use strict"; import optionService from "./options.js"; -import type { OptionNames } from "./options_interface.js"; import config from "./config.js"; /* @@ -11,14 +10,14 @@ import config from "./config.js"; * to live sync server. */ -function get(name: OptionNames) { - return (config["Sync"] && config["Sync"][name]) || optionService.getOption(name); +function get(name: keyof typeof config.Sync) { + return (config["Sync"] && config["Sync"][name]) || optionService.getOption(name); } export default { // env variable is the easiest way to guarantee we won't overwrite prod data during development // after copying prod document/data directory - getSyncServerHost: () => process.env.TRILIUM_SYNC_SERVER_HOST || get("syncServerHost"), + getSyncServerHost: () => get("syncServerHost"), isSyncSetup: () => { const syncServerHost = get("syncServerHost"); diff --git a/src/services/utils.ts b/src/services/utils.ts index 4d4f42936..9b05e2199 100644 --- a/src/services/utils.ts +++ b/src/services/utils.ts @@ -295,6 +295,18 @@ export function isString(x: any) { return Object.prototype.toString.call(x) === "[object String]"; } +// try to turn 'true' and 'false' strings from process.env variables into boolean values or undefined +export function envToBoolean(val: string | undefined) { + if (val === undefined || typeof val !== "string") return undefined; + + const valLc = val.toLowerCase().trim(); + + if (valLc === "true") return true; + if (valLc === "false") return false; + + return undefined; +} + /** * Returns the directory for resources. On Electron builds this corresponds to the `resources` subdirectory inside the distributable package. * On development builds, this simply refers to the root directory of the application. @@ -352,5 +364,6 @@ export default { isString, getResourceDir, isMac, - isWindows + isWindows, + envToBoolean }; diff --git a/src/services/ws.ts b/src/services/ws.ts index 1439e4555..aa24e65a2 100644 --- a/src/services/ws.ts +++ b/src/services/ws.ts @@ -1,4 +1,4 @@ -import WebSocket from "ws"; +import { WebSocketServer as WebSocketServer, WebSocket } from "ws"; import { isElectron, randomString } from "./utils.js"; import log from "./log.js"; import sql from "./sql.js"; @@ -10,7 +10,7 @@ import becca from "../becca/becca.js"; import AbstractBeccaEntity from "../becca/entities/abstract_becca_entity.js"; import env from "./env.js"; -import type { IncomingMessage, Server } from "http"; +import type { IncomingMessage, Server as HttpServer } from "http"; import type { EntityChange } from "./entity_changes_interface.js"; if (env.isDev()) { @@ -24,7 +24,7 @@ if (env.isDev()) { .on("unlink", debouncedReloadFrontend); } -let webSocketServer!: WebSocket.Server; +let webSocketServer!: WebSocketServer; let lastSyncedPush: number | null = null; interface Message { @@ -58,8 +58,8 @@ interface Message { } type SessionParser = (req: IncomingMessage, params: {}, cb: () => void) => void; -function init(httpServer: Server, sessionParser: SessionParser) { - webSocketServer = new WebSocket.Server({ +function init(httpServer: HttpServer, sessionParser: SessionParser) { + webSocketServer = new WebSocketServer({ verifyClient: (info, done) => { sessionParser(info.req, {}, () => { const allowed = isElectron() || (info.req as any).session.loggedIn || (config.General && config.General.noAuthentication); diff --git a/webpack.config.ts b/webpack.config.ts index b8c787118..f867f1e5b 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -1,14 +1,16 @@ import { fileURLToPath } from "url"; import path from "path"; import assetPath from "./src/services/asset_path.js"; +import type { Configuration } from "webpack"; const rootDir = path.dirname(fileURLToPath(import.meta.url)); -export default { +const config: Configuration = { mode: "production", entry: { setup: "./src/public/app/setup.js", mobile: "./src/public/app/mobile.js", - desktop: "./src/public/app/desktop.js" + desktop: "./src/public/app/desktop.js", + share: "./src/public/app/share.js" }, output: { publicPath: `${assetPath}/app-dist/`, @@ -42,3 +44,5 @@ export default { devtool: "source-map", target: "electron-renderer" }; + +export default config; \ No newline at end of file