diff --git a/bin/build-server.sh b/bin/build-server.sh index 47bfe9397..ff2912470 100755 --- a/bin/build-server.sh +++ b/bin/build-server.sh @@ -66,8 +66,6 @@ chmod 755 $PKG_DIR/trilium.sh cp bin/tpl/anonymize-database.sql $PKG_DIR/ cp -r translations $PKG_DIR/ -cp -r dump-db $PKG_DIR/ -rm -rf $PKG_DIR/dump-db/node_modules VERSION=`jq -r ".version" package.json` diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 000000000..55ad4d9a2 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,43 @@ +import eslint from "@eslint/js"; +import tseslint from "typescript-eslint"; + +export default tseslint.config( + eslint.configs.recommended, + tseslint.configs.recommended, + // consider using rules below, once we have a full TS codebase and can be more strict + // tseslint.configs.strictTypeChecked, + // tseslint.configs.stylisticTypeChecked, + // tseslint.configs.recommendedTypeChecked, + { + languageOptions: { + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname + } + } + }, + { + rules: { + // add rule overrides here + "no-undef": "off", + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_", + } + ] + } + }, + { + ignores: [ + "build/*", + "dist/*", + "docs/*", + "libraries/*", + "src/public/app-dist/*", + "src/public/app/doc_notes/*" + ] + } +); diff --git a/package-lock.json b/package-lock.json index 4da028900..1e6c3d38d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,7 +49,6 @@ "express-session": "1.18.1", "force-graph": "1.49.2", "fs-extra": "11.3.0", - "happy-dom": "17.1.8", "helmet": "8.0.0", "html": "1.0.0", "html2plaintext": "2.1.4", @@ -69,7 +68,6 @@ "jsdom": "26.0.0", "jsplumb": "2.15.6", "katex": "0.16.21", - "knockout": "3.5.1", "leaflet": "1.9.4", "leaflet-gpx": "2.1.2", "mark.js": "8.11.1", @@ -96,7 +94,6 @@ "striptags": "3.2.0", "swagger-ui-express": "5.0.1", "tmp": "0.2.3", - "ts-loader": "9.5.2", "turndown": "7.2.0", "unescape": "1.0.1", "vanilla-js-wheel-zoom": "9.0.4", @@ -117,6 +114,7 @@ "@electron-forge/maker-zip": "7.7.0", "@electron-forge/plugin-auto-unpack-natives": "7.7.0", "@electron/rebuild": "3.7.1", + "@eslint/js": "9.21.0", "@playwright/test": "1.50.1", "@popperjs/core": "2.11.8", "@types/archiver": "6.0.3", @@ -165,9 +163,12 @@ "cross-env": "7.0.3", "css-loader": "7.1.2", "electron": "34.3.0", + "eslint": "9.21.0", "esm": "3.2.25", + "happy-dom": "17.2.2", "i18next-http-backend": "3.0.2", "jsdoc": "4.0.4", + "knockout": "3.5.1", "lorem-ipsum": "2.0.8", "mini-css-extract-plugin": "2.9.2", "nodemon": "3.1.9", @@ -180,10 +181,12 @@ "split.js": "1.6.5", "supertest": "7.0.0", "swagger-jsdoc": "6.2.8", + "ts-loader": "9.5.2", "tslib": "2.8.1", "tsx": "4.19.3", "typedoc": "0.27.9", "typescript": "5.8.2", + "typescript-eslint": "8.26.0", "vitest": "3.0.7", "webpack": "5.98.0", "webpack-cli": "6.0.1", @@ -2127,6 +2130,158 @@ "node": ">=18" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", + "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", + "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", + "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "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", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/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/@eslint/js": { + "version": "9.21.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz", + "integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", + "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.12.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@excalidraw/excalidraw": { "version": "0.17.6", "resolved": "https://registry.npmjs.org/@excalidraw/excalidraw/-/excalidraw-0.17.6.tgz", @@ -2202,6 +2357,72 @@ "node": ">=12.0.0" } }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@iconify/types": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", @@ -2749,6 +2970,7 @@ "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", @@ -2763,6 +2985,7 @@ "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", @@ -2773,6 +2996,7 @@ "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" @@ -2782,6 +3006,7 @@ "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" @@ -2791,6 +3016,7 @@ "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", @@ -2801,6 +3027,7 @@ "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", @@ -2811,6 +3038,7 @@ "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/@jsdevtools/ono": { @@ -4366,6 +4594,7 @@ "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": "*", @@ -4376,6 +4605,7 @@ "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": "*", @@ -4386,6 +4616,7 @@ "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": { @@ -4523,6 +4754,7 @@ "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": { @@ -4913,6 +5145,212 @@ "@types/node": "*" } }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.0.tgz", + "integrity": "sha512-cLr1J6pe56zjKYajK6SSSre6nl1Gj6xDp1TY0trpgPzjVbgDwd09v2Ws37LABxzkicmUjhEeg/fAUjPJJB1v5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.26.0", + "@typescript-eslint/type-utils": "8.26.0", + "@typescript-eslint/utils": "8.26.0", + "@typescript-eslint/visitor-keys": "8.26.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.26.0.tgz", + "integrity": "sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.26.0", + "@typescript-eslint/types": "8.26.0", + "@typescript-eslint/typescript-estree": "8.26.0", + "@typescript-eslint/visitor-keys": "8.26.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.0.tgz", + "integrity": "sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.26.0", + "@typescript-eslint/visitor-keys": "8.26.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.26.0.tgz", + "integrity": "sha512-ruk0RNChLKz3zKGn2LwXuVoeBcUMh+jaqzN461uMMdxy5H9epZqIBtYj7UiPXRuOpaALXGbmRuZQhmwHhaS04Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.26.0", + "@typescript-eslint/utils": "8.26.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.0.tgz", + "integrity": "sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.0.tgz", + "integrity": "sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.26.0", + "@typescript-eslint/visitor-keys": "8.26.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.0.tgz", + "integrity": "sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.26.0", + "@typescript-eslint/types": "8.26.0", + "@typescript-eslint/typescript-estree": "8.26.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.0.tgz", + "integrity": "sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.26.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@vitest/coverage-v8": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.0.7.tgz", @@ -5077,6 +5515,7 @@ "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", @@ -5087,24 +5526,28 @@ "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", @@ -5116,12 +5559,14 @@ "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", @@ -5134,6 +5579,7 @@ "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" @@ -5143,6 +5589,7 @@ "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" @@ -5152,12 +5599,14 @@ "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", @@ -5174,6 +5623,7 @@ "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", @@ -5187,6 +5637,7 @@ "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", @@ -5199,6 +5650,7 @@ "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", @@ -5213,6 +5665,7 @@ "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", @@ -5286,12 +5739,14 @@ "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": { @@ -5356,6 +5811,16 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/agent-base": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", @@ -5396,6 +5861,7 @@ "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", @@ -5412,6 +5878,7 @@ "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" @@ -5429,6 +5896,7 @@ "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" @@ -6175,6 +6643,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -6187,6 +6656,7 @@ "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", @@ -6548,6 +7018,7 @@ "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", @@ -6754,6 +7225,7 @@ "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" @@ -8212,6 +8684,13 @@ "node": ">=4.0.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -9167,6 +9646,7 @@ "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": { @@ -9374,6 +9854,7 @@ "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -9456,6 +9937,7 @@ "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": { @@ -9539,6 +10021,7 @@ "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" @@ -9574,10 +10057,71 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint": { + "version": "9.21.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.21.0.tgz", + "integrity": "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.2", + "@eslint/core": "^0.12.0", + "@eslint/eslintrc": "^3.3.0", + "@eslint/js": "9.21.0", + "@eslint/plugin-kit": "^0.2.7", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, "node_modules/eslint-scope": { "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", @@ -9591,11 +10135,66 @@ "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" } }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "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", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/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/esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -9606,10 +10205,42 @@ "node": ">=6" } }, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/esrecurse": { "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" @@ -9622,6 +10253,7 @@ "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" @@ -10065,6 +10697,7 @@ "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": { @@ -10103,6 +10736,20 @@ "node": ">= 6" } }, + "node_modules/fast-json-stable-stringify": { + "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-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-safe-stringify": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", @@ -10114,6 +10761,7 @@ "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": { @@ -10167,6 +10815,19 @@ "pend": "~1.2.0" } }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/file-type": { "version": "18.7.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.7.0.tgz", @@ -10252,6 +10913,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -10320,6 +10982,27 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, "node_modules/float-tooltip": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.3.tgz", @@ -10850,10 +11533,24 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/glob-to-regexp": { "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": { @@ -10900,6 +11597,19 @@ "node": ">=10" } }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globalthis": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", @@ -10960,6 +11670,13 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/hachure-fill": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", @@ -10967,9 +11684,10 @@ "license": "MIT" }, "node_modules/happy-dom": { - "version": "17.1.8", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-17.1.8.tgz", - "integrity": "sha512-Yxbq/FG79z1rhAf/iB6YM8wO2JB/JDQBy99RiLSs+2siEAi5J05x9eW1nnASHZJbpldjJE2KuFLsLZ+AzX/IxA==", + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-17.2.2.tgz", + "integrity": "sha512-3I1/CrNi780sdOhuhUnFtgTWhloSc3quSZwsylI41jycx8o97M6Y4aQAu0phSexGusT7+59BxATh4L4xiY0HcA==", + "dev": true, "license": "MIT", "dependencies": { "webidl-conversions": "^7.0.0", @@ -10983,6 +11701,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -11446,6 +12165,16 @@ ], "license": "BSD-3-Clause" }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -11818,6 +12547,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -12051,6 +12781,7 @@ "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": "*", @@ -12065,6 +12796,7 @@ "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" @@ -12301,12 +13033,21 @@ "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": "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/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, "license": "MIT" }, "node_modules/json-stringify-safe": { @@ -12439,6 +13180,7 @@ "version": "3.5.1", "resolved": "https://registry.npmjs.org/knockout/-/knockout-3.5.1.tgz", "integrity": "sha512-wRJ9I4az0QcsH7A4v4l0enUpkS++MBx0BnL/68KaLzJg7x1qmbjSlwEoCNol7KTYZ+pmtI7Eh2J0Nu6/2Z5J/Q==", + "dev": true, "license": "MIT" }, "node_modules/kolorist": { @@ -12535,6 +13277,20 @@ "integrity": "sha512-lKoEPlAWel9KXn9keg6Dmyt7gmj5IYyD8CKuxivN+77GpZr2bpKliwFvZJxLUHmNu4fICmCySyxhm5qjZuvvQg==", "license": "BSD-2-Clause" }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/limiter": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", @@ -12605,6 +13361,7 @@ "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" @@ -12670,6 +13427,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.mergewith": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", @@ -13055,6 +13819,7 @@ "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": { @@ -13120,6 +13885,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -13440,6 +14206,13 @@ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "license": "MIT" }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, "node_modules/negotiator": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", @@ -13453,6 +14226,7 @@ "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": { @@ -13548,6 +14322,7 @@ "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": { @@ -13867,6 +14642,24 @@ "license": "MIT", "peer": true }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -14372,6 +15165,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -14775,6 +15569,16 @@ "node": ">=10" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prettier": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", @@ -15015,6 +15819,7 @@ "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" @@ -15491,6 +16296,7 @@ "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" @@ -16038,6 +16844,7 @@ "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", @@ -16190,6 +16997,7 @@ "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" @@ -17167,6 +17975,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -17306,6 +18115,7 @@ "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", @@ -17324,6 +18134,7 @@ "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", @@ -17358,6 +18169,7 @@ "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", @@ -17368,6 +18180,7 @@ "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": { @@ -17597,6 +18410,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -17705,6 +18519,19 @@ "utf8-byte-length": "^1.0.1" } }, + "node_modules/ts-api-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", + "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, "node_modules/ts-dedent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", @@ -17718,6 +18545,7 @@ "version": "9.5.2", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.2.tgz", "integrity": "sha512-Qo4piXvOTWcMGIgRiuFa6nHNm+54HbYaZCKqc9eeZCLRy3XqafQgwX2F7mofrbJG3g7EEb+lkiR+z2Lic2s3Zw==", + "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.0", @@ -17738,6 +18566,7 @@ "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">= 8" @@ -17805,6 +18634,19 @@ "@mixmark-io/domino": "^2.2.0" } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", @@ -17899,6 +18741,7 @@ "version": "5.8.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -17908,6 +18751,29 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.26.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.26.0.tgz", + "integrity": "sha512-PtVz9nAnuNJuAVeUFvwztjuUgSnJInODAUx47VDwWPXzd5vismPOtPtt83tzNXyOjVQbPRp786D6WFW/M2koIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.26.0", + "@typescript-eslint/parser": "8.26.0", + "@typescript-eslint/utils": "8.26.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, "node_modules/uc.micro": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", @@ -18079,6 +18945,7 @@ "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", @@ -18105,6 +18972,16 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "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" + } + }, "node_modules/username": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/username/-/username-5.1.0.tgz", @@ -18472,6 +19349,7 @@ "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", @@ -18504,6 +19382,7 @@ "version": "5.98.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz", "integrity": "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==", + "dev": true, "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", @@ -18648,6 +19527,7 @@ "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" @@ -18738,7 +19618,6 @@ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">=0.10.0" } diff --git a/package.json b/package.json index a10dd0d95..ba636bc6d 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,8 @@ "dev:watch-dist": "tsx ./bin/watch-dist.ts", "dev:prettier-check": "prettier . --check", "dev:prettier-fix": "prettier . --write", + "dev:linter-check": "eslint .", + "dev:linter-fix": "eslint . --fix", "chore:update-build-info": "tsx bin/update-build-info.ts", "chore:ci-update-nightly-version": "tsx ./bin/update-nightly-version.ts", "chore:generate-document": "cross-env nodemon ./bin/generate_document.ts 1000", @@ -103,7 +105,6 @@ "express-session": "1.18.1", "force-graph": "1.49.2", "fs-extra": "11.3.0", - "happy-dom": "17.1.8", "helmet": "8.0.0", "html": "1.0.0", "html2plaintext": "2.1.4", @@ -123,7 +124,6 @@ "jsdom": "26.0.0", "jsplumb": "2.15.6", "katex": "0.16.21", - "knockout": "3.5.1", "leaflet": "1.9.4", "leaflet-gpx": "2.1.2", "mark.js": "8.11.1", @@ -150,7 +150,6 @@ "striptags": "3.2.0", "swagger-ui-express": "5.0.1", "tmp": "0.2.3", - "ts-loader": "9.5.2", "turndown": "7.2.0", "unescape": "1.0.1", "vanilla-js-wheel-zoom": "9.0.4", @@ -168,6 +167,7 @@ "@electron-forge/maker-zip": "7.7.0", "@electron-forge/plugin-auto-unpack-natives": "7.7.0", "@electron/rebuild": "3.7.1", + "@eslint/js": "9.21.0", "@playwright/test": "1.50.1", "@popperjs/core": "2.11.8", "@types/archiver": "6.0.3", @@ -216,9 +216,12 @@ "cross-env": "7.0.3", "css-loader": "7.1.2", "electron": "34.3.0", + "eslint": "9.21.0", "esm": "3.2.25", + "happy-dom": "17.2.2", "i18next-http-backend": "3.0.2", "jsdoc": "4.0.4", + "knockout": "3.5.1", "lorem-ipsum": "2.0.8", "mini-css-extract-plugin": "2.9.2", "nodemon": "3.1.9", @@ -231,10 +234,12 @@ "split.js": "1.6.5", "supertest": "7.0.0", "swagger-jsdoc": "6.2.8", + "ts-loader": "9.5.2", "tslib": "2.8.1", "tsx": "4.19.3", "typedoc": "0.27.9", "typescript": "5.8.2", + "typescript-eslint": "8.26.0", "vitest": "3.0.7", "webpack": "5.98.0", "webpack-cli": "6.0.1", diff --git a/src/public/app/components/app_context.ts b/src/public/app/components/app_context.ts index 69b153661..bafeaaa60 100644 --- a/src/public/app/components/app_context.ts +++ b/src/public/app/components/app_context.ts @@ -22,6 +22,7 @@ import type LoadResults from "../services/load_results.js"; import type { Attribute } from "../services/attribute_parser.js"; import type NoteTreeWidget from "../widgets/note_tree.js"; import type { default as NoteContext, GetTextEditorCallback } from "./note_context.js"; +import type { ContextMenuEvent } from "../menus/context_menu.js"; import type TypeWidget from "../widgets/type_widgets/type_widget.js"; import type EditableTextTypeWidget from "../widgets/type_widgets/editable_text.js"; @@ -56,8 +57,8 @@ export interface ContextMenuCommandData extends CommandData { } export interface NoteCommandData extends CommandData { - notePath?: string | null; - hoistedNoteId?: string | null; + notePath?: string; + hoistedNoteId?: string; viewScope?: ViewScope; } @@ -172,9 +173,9 @@ export type CommandMappings = { callback: (value: NoteDetailWidget | PromiseLike) => void; }; executeWithTextEditor: CommandData & - ExecuteCommandData & { - callback?: GetTextEditorCallback; - }; + ExecuteCommandData & { + callback?: GetTextEditorCallback; + }; executeWithCodeEditor: CommandData & ExecuteCommandData; /** * Called upon when attempting to retrieve the content element of a {@link NoteContext}. @@ -326,7 +327,7 @@ type EventMappings = { ntxId: string | null; }; contextsReopenedEvent: { - mainNtxId: string | null; + mainNtxId: string; tabPosition: number; }; noteDetailRefreshed: { @@ -340,7 +341,7 @@ type EventMappings = { newNoteContextCreated: { noteContext: NoteContext; }; - noteContextRemoved: { + noteContextRemovedEvent: { ntxIds: string[]; }; exportSvg: { @@ -366,6 +367,7 @@ type EventMappings = { textTypeWidget: EditableTextTypeWidget; text: string; }; + }; export type EventListener = { diff --git a/src/public/app/components/entrypoints.ts b/src/public/app/components/entrypoints.ts index 21761ba16..69651de17 100644 --- a/src/public/app/components/entrypoints.ts +++ b/src/public/app/components/entrypoints.ts @@ -66,13 +66,12 @@ export default class Entrypoints extends Component { } async toggleNoteHoistingCommand({ noteId = appContext.tabManager.getActiveContextNoteId() }) { - const activeNoteContext = appContext.tabManager.getActiveContext(); - - if (!activeNoteContext || !noteId) { + if (!noteId) { return; } const noteToHoist = await froca.getNote(noteId); + const activeNoteContext = appContext.tabManager.getActiveContext(); if (noteToHoist?.noteId === activeNoteContext.hoistedNoteId) { await activeNoteContext.unhoist(); @@ -84,11 +83,6 @@ export default class Entrypoints extends Component { async hoistNoteCommand({ noteId }: { noteId: string }) { const noteContext = appContext.tabManager.getActiveContext(); - if (!noteContext) { - logError("hoistNoteCommand: noteContext is null"); - return; - } - if (noteContext.hoistedNoteId !== noteId) { await noteContext.setHoistedNoteId(noteId); } @@ -180,11 +174,7 @@ export default class Entrypoints extends Component { } async runActiveNoteCommand() { - const noteContext = appContext.tabManager.getActiveContext(); - if (!noteContext) { - return; - } - const { ntxId, note } = noteContext; + const { ntxId, note } = appContext.tabManager.getActiveContext(); // ctrl+enter is also used elsewhere, so make sure we're running only when appropriate if (!note || note.type !== "code") { diff --git a/src/public/app/components/tab_manager.ts b/src/public/app/components/tab_manager.js similarity index 71% rename from src/public/app/components/tab_manager.ts rename to src/public/app/components/tab_manager.js index b441c7819..46a0f9d96 100644 --- a/src/public/app/components/tab_manager.ts +++ b/src/public/app/components/tab_manager.js @@ -4,40 +4,23 @@ import server from "../services/server.js"; import options from "../services/options.js"; import froca from "../services/froca.js"; import treeService from "../services/tree.js"; +import utils from "../services/utils.js"; import NoteContext from "./note_context.js"; import appContext from "./app_context.js"; import Mutex from "../utils/mutex.js"; import linkService from "../services/link.js"; -import type { EventData } from "./app_context.js"; -import type FNote from "../entities/fnote.js"; - -interface TabState { - contexts: NoteContext[]; - position: number; -} - -interface NoteContextState { - ntxId: string; - mainNtxId: string | null; - notePath: string | null; - hoistedNoteId: string; - active: boolean; - viewScope: Record; -} export default class TabManager extends Component { - public children: NoteContext[]; - public mutex: Mutex; - public activeNtxId: string | null; - public recentlyClosedTabs: TabState[]; - public tabsUpdate: SpacedUpdate; - constructor() { super(); + /** @property {NoteContext[]} */ this.children = []; this.mutex = new Mutex(); + this.activeNtxId = null; + + // elements are arrays of {contexts, position}, storing note contexts for each tab (one main context + subcontexts [splits]), and the original position of the tab this.recentlyClosedTabs = []; this.tabsUpdate = new SpacedUpdate(async () => { @@ -45,9 +28,7 @@ export default class TabManager extends Component { return; } - const openNoteContexts = this.noteContexts - .map((nc) => nc.getPojoState()) - .filter((t) => !!t); + const openNoteContexts = this.noteContexts.map((nc) => nc.getPojoState()).filter((t) => !!t); await server.put("options", { openNoteContexts: JSON.stringify(openNoteContexts) @@ -57,11 +38,13 @@ export default class TabManager extends Component { appContext.addBeforeUnloadListener(this); } - get noteContexts(): NoteContext[] { + /** @returns {NoteContext[]} */ + get noteContexts() { return this.children; } - get mainNoteContexts(): NoteContext[] { + /** @type {NoteContext[]} */ + get mainNoteContexts() { return this.noteContexts.filter((nc) => !nc.mainNtxId); } @@ -70,12 +53,11 @@ export default class TabManager extends Component { const noteContextsToOpen = (appContext.isMainWindow && options.getJson("openNoteContexts")) || []; // preload all notes at once - await froca.getNotes([...noteContextsToOpen.flatMap((tab: NoteContextState) => - [treeService.getNoteIdFromUrl(tab.notePath), tab.hoistedNoteId])], true); + await froca.getNotes([...noteContextsToOpen.flatMap((tab) => [treeService.getNoteIdFromUrl(tab.notePath), tab.hoistedNoteId])], true); - const filteredNoteContexts = noteContextsToOpen.filter((openTab: NoteContextState) => { + const filteredNoteContexts = noteContextsToOpen.filter((openTab) => { const noteId = treeService.getNoteIdFromUrl(openTab.notePath); - if (noteId && !(noteId in froca.notes)) { + if (!(noteId in froca.notes)) { // note doesn't exist so don't try to open tab for it return false; } @@ -98,10 +80,9 @@ export default class TabManager extends Component { ntxId: parsedFromUrl.ntxId, active: true, hoistedNoteId: parsedFromUrl.hoistedNoteId || "root", - viewScope: parsedFromUrl.viewScope || {}, - mainNtxId: null + viewScope: parsedFromUrl.viewScope || {} }); - } else if (!filteredNoteContexts.find((tab: NoteContextState) => tab.active)) { + } else if (!filteredNoteContexts.find((tab) => tab.active)) { filteredNoteContexts[0].active = true; } @@ -120,30 +101,21 @@ export default class TabManager extends Component { // if there's a notePath in the URL, make sure it's open and active // (useful, for e.g., opening clipped notes from clipper or opening link in an extra window) if (parsedFromUrl.notePath) { - await appContext.tabManager.switchToNoteContext( - parsedFromUrl.ntxId, - parsedFromUrl.notePath, - parsedFromUrl.viewScope, - parsedFromUrl.hoistedNoteId - ); + await appContext.tabManager.switchToNoteContext(parsedFromUrl.ntxId, parsedFromUrl.notePath, parsedFromUrl.viewScope, parsedFromUrl.hoistedNoteId); } else if (parsedFromUrl.searchString) { await appContext.triggerCommand("searchNotes", { searchString: parsedFromUrl.searchString }); } - } catch (e: unknown) { - if (e instanceof Error) { - logError(`Loading note contexts '${options.get("openNoteContexts")}' failed: ${e.message} ${e.stack}`); - } else { - logError(`Loading note contexts '${options.get("openNoteContexts")}' failed: ${String(e)}`); - } + } catch (e) { + logError(`Loading note contexts '${options.get("openNoteContexts")}' failed: ${e.message} ${e.stack}`); // try to recover await this.openEmptyTab(); } } - noteSwitchedEvent({ noteContext }: EventData<"noteSwitched">) { + noteSwitchedEvent({ noteContext }) { if (noteContext.isActive()) { this.setCurrentNavigationStateToHash(); } @@ -163,10 +135,10 @@ export default class TabManager extends Component { const activeNoteContext = this.getActiveContext(); this.updateDocumentTitle(activeNoteContext); - this.triggerEvent("activeNoteChangedEvent", {}); // trigger this even in on popstate event + this.triggerEvent("activeNoteChanged"); // trigger this even in on popstate event } - calculateHash(): string { + calculateHash() { const activeNoteContext = this.getActiveContext(); if (!activeNoteContext) { return ""; @@ -180,15 +152,21 @@ export default class TabManager extends Component { }); } - getNoteContexts(): NoteContext[] { + /** @returns {NoteContext[]} */ + getNoteContexts() { return this.noteContexts; } - getMainNoteContexts(): NoteContext[] { + /** + * Main context is essentially a tab (children are splits), so this returns tabs. + * @returns {NoteContext[]} + */ + getMainNoteContexts() { return this.noteContexts.filter((nc) => nc.isMainContext()); } - getNoteContextById(ntxId: string | null): NoteContext { + /** @returns {NoteContext} */ + getNoteContextById(ntxId) { const noteContext = this.noteContexts.find((nc) => nc.ntxId === ntxId); if (!noteContext) { @@ -198,47 +176,58 @@ export default class TabManager extends Component { return noteContext; } - getActiveContext(): NoteContext | null { + /** + * Get active context which represents the visible split with focus. Active context can, but doesn't have to be "main". + * + * @returns {NoteContext} + */ + getActiveContext() { return this.activeNtxId ? this.getNoteContextById(this.activeNtxId) : null; } - getActiveMainContext(): NoteContext | null { + /** + * Get active main context which corresponds to the active tab. + * + * @returns {NoteContext} + */ + getActiveMainContext() { return this.activeNtxId ? this.getNoteContextById(this.activeNtxId).getMainContext() : null; } - getActiveContextNotePath(): string | null { + /** @returns {string|null} */ + getActiveContextNotePath() { const activeContext = this.getActiveContext(); - return activeContext?.notePath ?? null; + return activeContext ? activeContext.notePath : null; } - getActiveContextNote(): FNote | null { + /** @returns {FNote} */ + getActiveContextNote() { const activeContext = this.getActiveContext(); return activeContext ? activeContext.note : null; } - getActiveContextNoteId(): string | null { + /** @returns {string|null} */ + getActiveContextNoteId() { const activeNote = this.getActiveContextNote(); + return activeNote ? activeNote.noteId : null; } - getActiveContextNoteType(): string | null { + /** @returns {string|null} */ + getActiveContextNoteType() { const activeNote = this.getActiveContextNote(); + return activeNote ? activeNote.type : null; } - - getActiveContextNoteMime(): string | null { + /** @returns {string|null} */ + getActiveContextNoteMime() { const activeNote = this.getActiveContextNote(); + return activeNote ? activeNote.mime : null; } - async switchToNoteContext( - ntxId: string | null, - notePath: string, - viewScope: Record = {}, - hoistedNoteId: string | null = null - ) { - const noteContext = this.noteContexts.find((nc) => nc.ntxId === ntxId) || - await this.openEmptyTab(); + async switchToNoteContext(ntxId, notePath, viewScope = {}, hoistedNoteId = null) { + const noteContext = this.noteContexts.find((nc) => nc.ntxId === ntxId) || (await this.openEmptyTab()); await this.activateNoteContext(noteContext.ntxId); @@ -253,21 +242,20 @@ export default class TabManager extends Component { async openAndActivateEmptyTab() { const noteContext = await this.openEmptyTab(); + await this.activateNoteContext(noteContext.ntxId); - noteContext.setEmpty(); + + await noteContext.setEmpty(); } - async openEmptyTab( - ntxId: string | null = null, - hoistedNoteId: string = "root", - mainNtxId: string | null = null - ): Promise { + async openEmptyTab(ntxId = null, hoistedNoteId = "root", mainNtxId) { const noteContext = new NoteContext(ntxId, hoistedNoteId, mainNtxId); const existingNoteContext = this.children.find((nc) => nc.ntxId === noteContext.ntxId); if (existingNoteContext) { await existingNoteContext.setHoistedNoteId(hoistedNoteId); + return existingNoteContext; } @@ -278,40 +266,29 @@ export default class TabManager extends Component { return noteContext; } - async openInNewTab(targetNoteId: string, hoistedNoteId: string | null = null) { - const noteContext = await this.openEmptyTab( - null, - hoistedNoteId || this.getActiveContext()?.hoistedNoteId - ); + async openInNewTab(targetNoteId, hoistedNoteId = null) { + const noteContext = await this.openEmptyTab(null, hoistedNoteId || this.getActiveContext().hoistedNoteId); await noteContext.setNote(targetNoteId); } - async openInSameTab(targetNoteId: string, hoistedNoteId: string | null = null) { + async openInSameTab(targetNoteId, hoistedNoteId = null) { const activeContext = this.getActiveContext(); - if (!activeContext) return; - await activeContext.setHoistedNoteId(hoistedNoteId || activeContext.hoistedNoteId); await activeContext.setNote(targetNoteId); } - async openTabWithNoteWithHoisting( - notePath: string, - opts: { - activate?: boolean | null; - ntxId?: string | null; - mainNtxId?: string | null; - hoistedNoteId?: string | null; - viewScope?: Record | null; - } = {} - ): Promise { + /** + * If the requested notePath is within current note hoisting scope then keep the note hoisting also for the new tab. + */ + async openTabWithNoteWithHoisting(notePath, opts = {}) { const noteContext = this.getActiveContext(); let hoistedNoteId = "root"; if (noteContext) { const resolvedNotePath = await treeService.resolveNotePath(notePath, noteContext.hoistedNoteId); - if (resolvedNotePath?.includes(noteContext.hoistedNoteId) || resolvedNotePath?.includes("_hidden")) { + if (resolvedNotePath.includes(noteContext.hoistedNoteId) || resolvedNotePath.includes("_hidden")) { hoistedNoteId = noteContext.hoistedNoteId; } } @@ -321,16 +298,7 @@ export default class TabManager extends Component { return this.openContextWithNote(notePath, opts); } - async openContextWithNote( - notePath: string | null, - opts: { - activate?: boolean | null; - ntxId?: string | null; - mainNtxId?: string | null; - hoistedNoteId?: string | null; - viewScope?: Record | null; - } = {} - ): Promise { + async openContextWithNote(notePath, opts = {}) { const activate = !!opts.activate; const ntxId = opts.ntxId || null; const mainNtxId = opts.mainNtxId || null; @@ -347,10 +315,10 @@ export default class TabManager extends Component { }); } - if (activate && noteContext.notePath) { + if (activate) { this.activateNoteContext(noteContext.ntxId, false); - await this.triggerEvent("noteSwitchedAndActivatedEvent", { + await this.triggerEvent("noteSwitchedAndActivated", { noteContext, notePath: noteContext.notePath // resolved note path }); @@ -359,24 +327,21 @@ export default class TabManager extends Component { return noteContext; } - async activateOrOpenNote(noteId: string) { + async activateOrOpenNote(noteId) { for (const noteContext of this.getNoteContexts()) { if (noteContext.note && noteContext.note.noteId === noteId) { this.activateNoteContext(noteContext.ntxId); + return; } } // if no tab with this note has been found we'll create new tab + await this.openContextWithNote(noteId, { activate: true }); } - async activateNoteContext(ntxId: string | null, triggerEvent: boolean = true) { - if (!ntxId) { - logError("activateNoteContext: ntxId is null"); - return; - } - + async activateNoteContext(ntxId, triggerEvent = true) { if (ntxId === this.activeNtxId) { return; } @@ -394,7 +359,11 @@ export default class TabManager extends Component { this.setCurrentNavigationStateToHash(); } - async removeNoteContext(ntxId: string | null) { + /** + * @param ntxId + * @returns {Promise} true if note context has been removed, false otherwise + */ + async removeNoteContext(ntxId) { // removing note context is an async process which can take some time, if users presses CTRL-W quickly, two // close events could interleave which would then lead to attempting to activate already removed context. return await this.mutex.runExclusively(async () => { @@ -404,7 +373,7 @@ export default class TabManager extends Component { noteContextToRemove = this.getNoteContextById(ntxId); } catch { // note context not found - return; + return false; } if (noteContextToRemove.isMainContext()) { @@ -414,7 +383,7 @@ export default class TabManager extends Component { if (noteContextToRemove.isEmpty()) { // this is already the empty note context, no point in closing it and replacing with another // empty tab - return; + return false; } await this.openEmptyTab(); @@ -430,7 +399,7 @@ export default class TabManager extends Component { const noteContextsToRemove = noteContextToRemove.getSubContexts(); const ntxIdsToRemove = noteContextsToRemove.map((nc) => nc.ntxId); - await this.triggerEvent("beforeNoteContextRemove", { ntxIds: ntxIdsToRemove.filter((id) => id !== null) }); + await this.triggerEvent("beforeNoteContextRemove", { ntxIds: ntxIdsToRemove }); if (!noteContextToRemove.isMainContext()) { const siblings = noteContextToRemove.getMainContext().getSubContexts(); @@ -452,10 +421,12 @@ export default class TabManager extends Component { } this.removeNoteContexts(noteContextsToRemove); + + return true; }); } - removeNoteContexts(noteContextsToRemove: NoteContext[]) { + removeNoteContexts(noteContextsToRemove) { const ntxIdsToRemove = noteContextsToRemove.map((nc) => nc.ntxId); const position = this.noteContexts.findIndex((nc) => ntxIdsToRemove.includes(nc.ntxId)); @@ -464,12 +435,12 @@ export default class TabManager extends Component { this.addToRecentlyClosedTabs(noteContextsToRemove, position); - this.triggerEvent("noteContextRemoved", { ntxIds: ntxIdsToRemove.filter((id) => id !== null) }); + this.triggerEvent("noteContextRemoved", { ntxIds: ntxIdsToRemove }); this.tabsUpdate.scheduleUpdate(); } - addToRecentlyClosedTabs(noteContexts: NoteContext[], position: number) { + addToRecentlyClosedTabs(noteContexts, position) { if (noteContexts.length === 1 && noteContexts[0].isEmpty()) { return; } @@ -477,42 +448,26 @@ export default class TabManager extends Component { this.recentlyClosedTabs.push({ contexts: noteContexts, position: position }); } - tabReorderEvent({ ntxIdsInOrder }: { ntxIdsInOrder: string[] }) { - const order: Record = {}; + tabReorderEvent({ ntxIdsInOrder }) { + const order = {}; let i = 0; for (const ntxId of ntxIdsInOrder) { for (const noteContext of this.getNoteContextById(ntxId).getSubContexts()) { - if (noteContext.ntxId) { - order[noteContext.ntxId] = i++; - } + order[noteContext.ntxId] = i++; } } - this.children.sort((a, b) => { - if (!a.ntxId || !b.ntxId) return 0; - return (order[a.ntxId] ?? 0) < (order[b.ntxId] ?? 0) ? -1 : 1; - }); + this.children.sort((a, b) => (order[a.ntxId] < order[b.ntxId] ? -1 : 1)); this.tabsUpdate.scheduleUpdate(); } - noteContextReorderEvent({ - ntxIdsInOrder, - oldMainNtxId, - newMainNtxId - }: { - ntxIdsInOrder: string[]; - oldMainNtxId?: string; - newMainNtxId?: string; - }) { + noteContextReorderEvent({ ntxIdsInOrder, oldMainNtxId, newMainNtxId }) { const order = Object.fromEntries(ntxIdsInOrder.map((v, i) => [v, i])); - this.children.sort((a, b) => { - if (!a.ntxId || !b.ntxId) return 0; - return (order[a.ntxId] ?? 0) < (order[b.ntxId] ?? 0) ? -1 : 1; - }); + this.children.sort((a, b) => (order[a.ntxId] < order[b.ntxId] ? -1 : 1)); if (oldMainNtxId && newMainNtxId) { this.children.forEach((c) => { @@ -530,8 +485,7 @@ export default class TabManager extends Component { } async activateNextTabCommand() { - const activeMainNtxId = this.getActiveMainContext()?.ntxId; - if (!activeMainNtxId) return; + const activeMainNtxId = this.getActiveMainContext().ntxId; const oldIdx = this.mainNoteContexts.findIndex((nc) => nc.ntxId === activeMainNtxId); const newActiveNtxId = this.mainNoteContexts[oldIdx === this.mainNoteContexts.length - 1 ? 0 : oldIdx + 1].ntxId; @@ -540,8 +494,7 @@ export default class TabManager extends Component { } async activatePreviousTabCommand() { - const activeMainNtxId = this.getActiveMainContext()?.ntxId; - if (!activeMainNtxId) return; + const activeMainNtxId = this.getActiveMainContext().ntxId; const oldIdx = this.mainNoteContexts.findIndex((nc) => nc.ntxId === activeMainNtxId); const newActiveNtxId = this.mainNoteContexts[oldIdx === 0 ? this.mainNoteContexts.length - 1 : oldIdx - 1].ntxId; @@ -550,13 +503,12 @@ export default class TabManager extends Component { } async closeActiveTabCommand() { - if (this.activeNtxId) { - await this.removeNoteContext(this.activeNtxId); - } + await this.removeNoteContext(this.activeNtxId); } - beforeUnloadEvent(): boolean { + beforeUnloadEvent() { this.tabsUpdate.updateNowIfNecessary(); + return true; // don't block closing the tab, this metadata is not that important } @@ -566,39 +518,35 @@ export default class TabManager extends Component { async closeAllTabsCommand() { for (const ntxIdToRemove of this.mainNoteContexts.map((nc) => nc.ntxId)) { - if (ntxIdToRemove) { - await this.removeNoteContext(ntxIdToRemove); - } + await this.removeNoteContext(ntxIdToRemove); } } - async closeOtherTabsCommand({ ntxId }: { ntxId: string }) { + async closeOtherTabsCommand({ ntxId }) { for (const ntxIdToRemove of this.mainNoteContexts.map((nc) => nc.ntxId)) { - if (ntxIdToRemove && ntxIdToRemove !== ntxId) { + if (ntxIdToRemove !== ntxId) { await this.removeNoteContext(ntxIdToRemove); } } } - async closeRightTabsCommand({ ntxId }: { ntxId: string }) { + async closeRightTabsCommand({ ntxId }) { const ntxIds = this.mainNoteContexts.map((nc) => nc.ntxId); const index = ntxIds.indexOf(ntxId); if (index !== -1) { const idsToRemove = ntxIds.slice(index + 1); for (const ntxIdToRemove of idsToRemove) { - if (ntxIdToRemove) { - await this.removeNoteContext(ntxIdToRemove); - } + await this.removeNoteContext(ntxIdToRemove); } } } - async closeTabCommand({ ntxId }: { ntxId: string }) { + async closeTabCommand({ ntxId }) { await this.removeNoteContext(ntxId); } - async moveTabToNewWindowCommand({ ntxId }: { ntxId: string }) { + async moveTabToNewWindowCommand({ ntxId }) { const { notePath, hoistedNoteId } = this.getNoteContextById(ntxId); const removed = await this.removeNoteContext(ntxId); @@ -608,16 +556,17 @@ export default class TabManager extends Component { } } - async copyTabToNewWindowCommand({ ntxId }: { ntxId: string }) { + async copyTabToNewWindowCommand({ ntxId }) { const { notePath, hoistedNoteId } = this.getNoteContextById(ntxId); this.triggerCommand("openInWindow", { notePath, hoistedNoteId }); } async reopenLastTabCommand() { - const closeLastEmptyTab: NoteContext | undefined = await this.mutex.runExclusively(async () => { - let closeLastEmptyTab + let closeLastEmptyTab = null; + + await this.mutex.runExclusively(async () => { if (this.recentlyClosedTabs.length === 0) { - return closeLastEmptyTab; + return; } if (this.noteContexts.length === 1 && this.noteContexts[0].isEmpty()) { @@ -626,8 +575,6 @@ export default class TabManager extends Component { } const lastClosedTab = this.recentlyClosedTabs.pop(); - if (!lastClosedTab) return closeLastEmptyTab; - const noteContexts = lastClosedTab.contexts; for (const noteContext of noteContexts) { @@ -642,26 +589,25 @@ export default class TabManager extends Component { ...this.noteContexts.slice(-noteContexts.length), ...this.noteContexts.slice(lastClosedTab.position, -noteContexts.length) ]; - this.noteContextReorderEvent({ ntxIdsInOrder: ntxsInOrder.map((nc) => nc.ntxId).filter((id) => id !== null) }); + await this.noteContextReorderEvent({ ntxIdsInOrder: ntxsInOrder.map((nc) => nc.ntxId) }); let mainNtx = noteContexts.find((nc) => nc.isMainContext()); if (mainNtx) { // reopened a tab, need to reorder new tab widget in tab row - await this.triggerEvent("contextsReopenedEvent", { + await this.triggerEvent("contextsReopened", { mainNtxId: mainNtx.ntxId, tabPosition: ntxsInOrder.filter((nc) => nc.isMainContext()).findIndex((nc) => nc.ntxId === mainNtx.ntxId) }); } else { // reopened a single split, need to reorder the pane widget in split note container - await this.triggerEvent("contextsReopenedEvent", { - mainNtxId: ntxsInOrder[lastClosedTab.position].ntxId, + await this.triggerEvent("contextsReopened", { + ntxId: ntxsInOrder[lastClosedTab.position].ntxId, // this is safe since lastClosedTab.position can never be 0 in this case - tabPosition: lastClosedTab.position - 1 + afterNtxId: ntxsInOrder[lastClosedTab.position - 1].ntxId }); } const noteContextToActivate = noteContexts.length === 1 ? noteContexts[0] : noteContexts.find((nc) => nc.isMainContext()); - if (!noteContextToActivate) return closeLastEmptyTab; await this.activateNoteContext(noteContextToActivate.ntxId); @@ -669,7 +615,6 @@ export default class TabManager extends Component { noteContext: noteContextToActivate, notePath: noteContextToActivate.notePath }); - return closeLastEmptyTab; }); if (closeLastEmptyTab) { @@ -681,9 +626,7 @@ export default class TabManager extends Component { this.tabsUpdate.scheduleUpdate(); } - async updateDocumentTitle(activeNoteContext: NoteContext | null) { - if (!activeNoteContext) return; - + async updateDocumentTitle(activeNoteContext) { const titleFragments = [ // it helps to navigate in history if note title is included in the title await activeNoteContext.getNavigationTitle(), @@ -693,7 +636,7 @@ export default class TabManager extends Component { document.title = titleFragments.join(" - "); } - async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { + async entitiesReloadedEvent({ loadResults }) { const activeContext = this.getActiveContext(); if (activeContext && loadResults.isNoteReloaded(activeContext.noteId)) { @@ -703,6 +646,7 @@ export default class TabManager extends Component { async frocaReloadedEvent() { const activeContext = this.getActiveContext(); + if (activeContext) { await this.updateDocumentTitle(activeContext); } diff --git a/src/public/app/menus/link_context_menu.ts b/src/public/app/menus/link_context_menu.ts index cef67b7da..6456c6519 100644 --- a/src/public/app/menus/link_context_menu.ts +++ b/src/public/app/menus/link_context_menu.ts @@ -22,19 +22,13 @@ function getItems(): MenuItem[] { function handleLinkContextMenuItem(command: string | undefined, notePath: string, viewScope = {}, hoistedNoteId: string | null = null) { if (!hoistedNoteId) { - hoistedNoteId = appContext.tabManager.getActiveContext()?.hoistedNoteId ?? null; + hoistedNoteId = appContext.tabManager.getActiveContext().hoistedNoteId; } if (command === "openNoteInNewTab") { appContext.tabManager.openContextWithNote(notePath, { hoistedNoteId, viewScope }); } else if (command === "openNoteInNewSplit") { - const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts(); - - if (!subContexts) { - logError("subContexts is null"); - return; - } - + const subContexts = appContext.tabManager.getActiveContext().getSubContexts(); const { ntxId } = subContexts[subContexts.length - 1]; appContext.triggerCommand("openNewNoteSplit", { ntxId, notePath, hoistedNoteId, viewScope }); diff --git a/src/public/app/services/link.ts b/src/public/app/services/link.ts index 7cd0a861d..8cda26fa5 100644 --- a/src/public/app/services/link.ts +++ b/src/public/app/services/link.ts @@ -288,15 +288,11 @@ function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent const noteContext = ntxId ? appContext.tabManager.getNoteContextById(ntxId) : appContext.tabManager.getActiveContext(); - if (noteContext) { - noteContext.setNote(notePath, { viewScope }).then(() => { - if (noteContext !== appContext.tabManager.getActiveContext()) { - appContext.tabManager.activateNoteContext(noteContext.ntxId); - } - }); - } else { - appContext.tabManager.openContextWithNote(notePath, { viewScope, activate: true }); - } + noteContext.setNote(notePath, { viewScope }).then(() => { + if (noteContext !== appContext.tabManager.getActiveContext()) { + appContext.tabManager.activateNoteContext(noteContext.ntxId); + } + }); } } else if (hrefLink) { const withinEditLink = $link?.hasClass("ck-link-actions__preview"); diff --git a/src/public/app/services/tree.ts b/src/public/app/services/tree.ts index ff4c34210..e7c94ca0e 100644 --- a/src/public/app/services/tree.ts +++ b/src/public/app/services/tree.ts @@ -138,7 +138,7 @@ function getParentProtectedStatus(node: Fancytree.FancytreeNode) { return hoistedNoteService.isHoistedNode(node) ? false : node.getParent().data.isProtected; } -function getNoteIdFromUrl(urlOrNotePath: string | null | undefined) { +function getNoteIdFromUrl(urlOrNotePath: string | undefined) { if (!urlOrNotePath) { return null; } diff --git a/src/public/app/utils/mutex.ts b/src/public/app/utils/mutex.ts index 197e2f134..76ea57b0d 100644 --- a/src/public/app/utils/mutex.ts +++ b/src/public/app/utils/mutex.ts @@ -16,7 +16,7 @@ export default class Mutex { return newPromise; } - async runExclusively(cb: () => Promise) { + async runExclusively(cb: () => Promise) { const unlock = await this.lock(); try { diff --git a/src/public/app/widgets/containers/split_note_container.ts b/src/public/app/widgets/containers/split_note_container.ts index 9b828120b..61f82b793 100644 --- a/src/public/app/widgets/containers/split_note_container.ts +++ b/src/public/app/widgets/containers/split_note_container.ts @@ -63,7 +63,7 @@ export default class SplitNoteContainer extends FlexContainer { hoistedNoteId?: string; viewScope?: any; }) { - const mainNtxId = appContext.tabManager.getActiveMainContext()?.ntxId; + const mainNtxId = appContext.tabManager.getActiveMainContext().ntxId; if (!mainNtxId) { logError("empty mainNtxId!"); @@ -76,7 +76,7 @@ export default class SplitNoteContainer extends FlexContainer { ntxId = mainNtxId; } - hoistedNoteId = hoistedNoteId || appContext.tabManager.getActiveContext()?.hoistedNoteId; + hoistedNoteId = hoistedNoteId || appContext.tabManager.getActiveContext().hoistedNoteId; const noteContext = await appContext.tabManager.openEmptyTab(null, hoistedNoteId, mainNtxId); diff --git a/src/public/app/widgets/tab_row.ts b/src/public/app/widgets/tab_row.ts index c726cc528..f0af54493 100644 --- a/src/public/app/widgets/tab_row.ts +++ b/src/public/app/widgets/tab_row.ts @@ -1,10 +1,10 @@ -import Draggabilly, { type MoveVector } from "draggabilly"; +import Draggabilly, { type DraggabillyCallback, type MoveVector } from "draggabilly"; import { t } from "../services/i18n.js"; import BasicWidget from "./basic_widget.js"; import contextMenu from "../menus/context_menu.js"; import utils from "../services/utils.js"; import keyboardActionService from "../services/keyboard_actions.js"; -import appContext, { type CommandListenerData, type EventData } from "../components/app_context.js"; +import appContext, { type CommandData, type CommandListenerData, type EventData } from "../components/app_context.js"; import froca from "../services/froca.js"; import attributeService from "../services/attributes.js"; import type NoteContext from "../components/note_context.js"; @@ -419,13 +419,13 @@ export default class TabRowWidget extends BasicWidget { closeActiveTabCommand({ $el }: CommandListenerData<"closeActiveTab">) { const ntxId = $el.closest(".note-tab").attr("data-ntx-id"); - appContext.tabManager.removeNoteContext(ntxId ?? null); + appContext.tabManager.removeNoteContext(ntxId); } setTabCloseEvent($tab: JQuery) { $tab.on("mousedown", (e) => { if (e.which === 2) { - appContext.tabManager.removeNoteContext($tab.attr("data-ntx-id") ?? null); + appContext.tabManager.removeNoteContext($tab.attr("data-ntx-id")); return true; // event has been handled } @@ -494,7 +494,7 @@ export default class TabRowWidget extends BasicWidget { return $tab.attr("data-ntx-id"); } - noteContextRemovedEvent({ ntxIds }: EventData<"noteContextRemoved">) { + noteContextRemovedEvent({ ntxIds }: EventData<"noteContextRemovedEvent">) { for (const ntxId of ntxIds) { this.removeTab(ntxId); } @@ -516,7 +516,7 @@ export default class TabRowWidget extends BasicWidget { this.draggabillyDragging.element.style.transform = ""; this.draggabillyDragging.dragEnd(); this.draggabillyDragging.isDragging = false; - this.draggabillyDragging.positionDrag = () => { }; // Prevent Draggabilly from updating tabEl.style.transform in later frames + this.draggabillyDragging.positionDrag = () => {}; // Prevent Draggabilly from updating tabEl.style.transform in later frames this.draggabillyDragging.destroy(); this.draggabillyDragging = null; } @@ -650,7 +650,7 @@ export default class TabRowWidget extends BasicWidget { } contextsReopenedEvent({ mainNtxId, tabPosition }: EventData<"contextsReopenedEvent">) { - if (!mainNtxId || !tabPosition) { + if (mainNtxId === undefined || tabPosition === undefined) { // no tab reopened return; } @@ -748,7 +748,7 @@ export default class TabRowWidget extends BasicWidget { hoistedNoteChangedEvent({ ntxId }: EventData<"hoistedNoteChanged">) { const $tab = this.getTabById(ntxId); - if ($tab && ntxId) { + if ($tab) { const noteContext = appContext.tabManager.getNoteContextById(ntxId); this.updateTab($tab, noteContext); diff --git a/src/public/app/widgets/type_widgets/canvas.ts b/src/public/app/widgets/type_widgets/canvas.ts index f5866e4e8..c8b822552 100644 --- a/src/public/app/widgets/type_widgets/canvas.ts +++ b/src/public/app/widgets/type_widgets/canvas.ts @@ -541,10 +541,6 @@ export default class ExcalidrawTypeWidget extends TypeWidget { excalidrawAPI: (api: ExcalidrawImperativeAPI) => { this.excalidrawApi = api; }, - onPaste: (data: unknown, event: unknown) => { - console.log("Verbose: excalidraw internal paste. No trilium action implemented.", data, event); - return false; - }, onLibraryChange: () => { this.libraryChanged = true; diff --git a/src/public/app/widgets/type_widgets/options/other/html_import_tags.ts b/src/public/app/widgets/type_widgets/options/other/html_import_tags.ts index 38ff45fbf..4b1e9fa3a 100644 --- a/src/public/app/widgets/type_widgets/options/other/html_import_tags.ts +++ b/src/public/app/widgets/type_widgets/options/other/html_import_tags.ts @@ -102,13 +102,20 @@ export const DEFAULT_ALLOWED_TAGS = [ ]; const TPL = ` -
+
+

${t("import.html_import_tags.title")}

${t("import.html_import_tags.description")}

- +