diff --git a/.eslintrc.js b/.eslintrc.js index 17b060730..92acecbee 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -98,7 +98,7 @@ module.exports = { CodeMirror: true, // \src\public\app\services\resizer.js Split: true, - // \src\public\app\services\note_content_renderer.js + // \src\public\app\services\content_renderer.js mermaid: true, // src\public\app\services\frontend_script_api.js dayjs: true, diff --git a/package-lock.json b/package-lock.json index 53959742a..6f37a2826 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "trilium", - "version": "0.59.4", + "version": "0.60.0-beta", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "trilium", - "version": "0.59.4", + "version": "0.60.0-beta", "hasInstallScript": true, "license": "AGPL-3.0-only", "dependencies": { @@ -24,8 +24,8 @@ "cookie-parser": "1.4.6", "csurf": "1.11.0", "dayjs": "1.11.7", - "dayjs-plugin-utc": "^0.1.2", - "debounce": "^1.2.1", + "dayjs-plugin-utc": "0.1.2", + "debounce": "1.2.1", "ejs": "3.1.9", "electron-debug": "3.2.0", "electron-dl": "3.5.0", @@ -39,8 +39,8 @@ "helmet": "7.0.0", "html": "1.0.0", "html2plaintext": "2.1.4", - "http-proxy-agent": "6.0.1", - "https-proxy-agent": "6.1.0", + "http-proxy-agent": "6.1.0", + "https-proxy-agent": "6.2.0", "image-type": "4.1.0", "ini": "3.0.1", "is-animated": "2.0.2", @@ -57,7 +57,7 @@ "react": "17.0.2", "react-dom": "17.0.2", "request": "2.88.2", - "rimraf": "5.0.0", + "rimraf": "5.0.1", "safe-compare": "1.1.4", "sanitize-filename": "1.6.3", "sanitize-html": "2.10.0", @@ -79,11 +79,11 @@ }, "devDependencies": { "cross-env": "7.0.3", - "electron": "25.0.0-beta.5", + "electron": "25.0.0-beta.7", "electron-builder": "23.6.0", "electron-packager": "17.1.1", "electron-rebuild": "3.2.9", - "eslint": "8.40.0", + "eslint": "8.41.0", "eslint-config-airbnb-base": "15.0.0", "eslint-config-prettier": "8.8.0", "eslint-plugin-import": "2.27.5", @@ -99,7 +99,7 @@ "nodemon": "2.0.22", "prettier": "2.8.8", "rcedit": "3.0.1", - "webpack": "5.82.1", + "webpack": "5.83.1", "webpack-cli": "5.1.1" }, "optionalDependencies": { @@ -450,9 +450,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", - "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", + "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -522,7 +522,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -539,7 +538,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "engines": { "node": ">=12" }, @@ -551,7 +549,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, "engines": { "node": ">=12" }, @@ -562,14 +559,12 @@ "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -586,7 +581,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -601,7 +595,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -1296,7 +1289,6 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, "optional": true, "engines": { "node": ">=14" @@ -1870,7 +1862,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "devOptional": true, "engines": { "node": ">=8" } @@ -3641,7 +3632,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "devOptional": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -4177,8 +4167,7 @@ "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/ecc-jsbn": { "version": "0.1.2", @@ -4209,9 +4198,9 @@ } }, "node_modules/electron": { - "version": "25.0.0-beta.5", - "resolved": "https://registry.npmjs.org/electron/-/electron-25.0.0-beta.5.tgz", - "integrity": "sha512-48EC6IuddKcvxDZLYEqlw3uSCzTwTwM85UhaNsEDScygVByWTWQjQgbl1ivdvvwIm+0wzDZjTK/0fTcL2QEPAg==", + "version": "25.0.0-beta.7", + "resolved": "https://registry.npmjs.org/electron/-/electron-25.0.0-beta.7.tgz", + "integrity": "sha512-pNlAmEH0v3ADTUeMfDiD5u2ODTQKdhABBSkUzvmq+tMJgCbbb8SlffcmekL2fHENDxwPycaH1ld+fCMG33ce6g==", "hasInstallScript": true, "dependencies": { "@electron/get": "^2.0.0", @@ -4826,8 +4815,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "devOptional": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -5042,15 +5030,15 @@ } }, "node_modules/eslint": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", - "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", + "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.40.0", + "@eslint/js": "8.41.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -5070,13 +5058,12 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -6273,7 +6260,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -6289,7 +6275,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", - "dev": true, "engines": { "node": ">=14" }, @@ -6746,10 +6731,10 @@ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, "node_modules/har-schema": { @@ -6979,11 +6964,11 @@ } }, "node_modules/http-proxy-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-6.0.1.tgz", - "integrity": "sha512-rD8wrfJHbnVll9lkIpQH3vDbKON1Ssciggwydom/r89HLBXEqdMhL6wx7QF5WePDPSr0OdoztdXoojbrXadG5Q==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-6.1.0.tgz", + "integrity": "sha512-75t5ACHLOMnz/KsDAS4BdHx4J0sneT/HW+Sz070NR+n7RZ7SmYXYn2FXq6D0XwQid8hYgRVf6HZJrYuGzaEqtw==", "dependencies": { - "agent-base": "^7.0.1", + "agent-base": "^7.0.2", "debug": "^4.3.4" }, "engines": { @@ -6991,9 +6976,9 @@ } }, "node_modules/http-proxy-agent/node_modules/agent-base": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.0.1.tgz", - "integrity": "sha512-V9to8gr2GK7eA+xskWGAFUX/TLSQKuH2TI06c/jGLL6yLp3oEjtnqM7a5tPV9fC1rabLeAgThZeBwsYX+WWHpw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.0.2.tgz", + "integrity": "sha512-k2/tQ1+8Zf50dEUJWklUP80LcE/+Ph+OJ6cf2Ff2fD/c/TtCe6ofnCoNMz9UnyxOQYlaAALZtEWETzn+1JjfHg==", "dependencies": { "debug": "^4.3.4" }, @@ -7028,11 +7013,11 @@ } }, "node_modules/https-proxy-agent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-6.1.0.tgz", - "integrity": "sha512-rvGRAlc3y+iS7AC9Os2joN91mX8wHpJ4TEklmHHxr7Gz2Juqa7fJmJ8wWxXNpTaRt56MQTwojxV5d82UW/+jwg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-6.2.0.tgz", + "integrity": "sha512-4xhCnMpxR9fupa7leh9uJK2P/qjYIeaM9uZ9c1bi1JDSwX2VH9NDk/oKSToNX4gBKa2WT31Mldne7e26ckohLQ==", "dependencies": { - "agent-base": "^7.0.1", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { @@ -7040,9 +7025,9 @@ } }, "node_modules/https-proxy-agent/node_modules/agent-base": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.0.1.tgz", - "integrity": "sha512-V9to8gr2GK7eA+xskWGAFUX/TLSQKuH2TI06c/jGLL6yLp3oEjtnqM7a5tPV9fC1rabLeAgThZeBwsYX+WWHpw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.0.2.tgz", + "integrity": "sha512-k2/tQ1+8Zf50dEUJWklUP80LcE/+Ph+OJ6cf2Ff2fD/c/TtCe6ofnCoNMz9UnyxOQYlaAALZtEWETzn+1JjfHg==", "dependencies": { "debug": "^4.3.4" }, @@ -7449,7 +7434,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "devOptional": true, "engines": { "node": ">=8" } @@ -7713,8 +7697,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "devOptional": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "node_modules/isobject": { "version": "3.0.1", @@ -7743,7 +7726,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.0.tgz", "integrity": "sha512-r5XBrqIJfwRIjRt/Xr5fv9Wh09qyhHfKnYddDlpM+ibRR20qrYActpCAgU6U+d53EOEjzkvxPMVHSlgR7leXrQ==", - "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -7903,16 +7885,6 @@ "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" }, - "node_modules/js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -9973,7 +9945,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "devOptional": true, "engines": { "node": ">=8" } @@ -10833,11 +10804,11 @@ "dev": true }, "node_modules/rimraf": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz", - "integrity": "sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz", + "integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==", "dependencies": { - "glob": "^10.0.0" + "glob": "^10.2.5" }, "bin": { "rimraf": "dist/cjs/src/bin.js" @@ -10858,14 +10829,18 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.0.0.tgz", - "integrity": "sha512-zmp9ZDC6NpDNLujV2W2n+3lH+BafIVZ4/ct+Yj3BMZTH/+bgm/eVjHzeFLwxJrrIGgjjS2eiQLlpurHsNlEAtQ==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.5.tgz", + "integrity": "sha512-Gj+dFYPZ5hc5dazjXzB0iHg2jKWJZYMjITXYPBRQ/xc2Buw7H0BINknRTwURJ6IC6MEFpYbLvtgVb3qD+DwyuA==", "dependencies": { - "fs.realpath": "^1.0.0", + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", "minimatch": "^9.0.0", - "minipass": "^5.0.0", - "path-scurry": "^1.6.4" + "minipass": "^5.0.0 || ^6.0.2", + "path-scurry": "^1.7.0" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -10889,11 +10864,11 @@ } }, "node_modules/rimraf/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", + "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==", "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/rndm": { @@ -11327,7 +11302,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "devOptional": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -11339,7 +11313,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "devOptional": true, "engines": { "node": ">=8" } @@ -11677,7 +11650,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "devOptional": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -11692,7 +11664,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -11756,7 +11727,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "devOptional": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -11769,7 +11739,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -12595,9 +12564,9 @@ } }, "node_modules/webpack": { - "version": "5.82.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", - "integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", + "version": "5.83.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.83.1.tgz", + "integrity": "sha512-TNsG9jDScbNuB+Lb/3+vYolPplCS3bbEaJf+Bj0Gw4DhP3ioAflBb1flcRt9zsWITyvOhM96wMQNRWlSX52DgA==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", @@ -12757,7 +12726,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "devOptional": true, "dependencies": { "isexe": "^2.0.0" }, @@ -12853,7 +12821,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -13357,9 +13324,9 @@ } }, "@eslint/js": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.40.0.tgz", - "integrity": "sha512-ElyB54bJIhXQYVKjDSvCkPO1iU1tSAeVQJbllWJq1XQSmmA4dgFk8CbiBGpiOPxleE48vDogxCtmMYku4HSVLA==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", + "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", "dev": true }, "@excalidraw/excalidraw": { @@ -13412,7 +13379,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, "requires": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -13425,26 +13391,22 @@ "ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" }, "ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" }, "emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, "requires": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -13455,7 +13417,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, "requires": { "ansi-regex": "^6.0.1" } @@ -13464,7 +13425,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, "requires": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -13986,7 +13946,6 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, "optional": true }, "@sindresorhus/is": { @@ -14483,8 +14442,7 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "devOptional": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", @@ -15875,7 +15833,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "devOptional": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -16269,8 +16226,7 @@ "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "ecc-jsbn": { "version": "0.1.2", @@ -16295,9 +16251,9 @@ } }, "electron": { - "version": "25.0.0-beta.5", - "resolved": "https://registry.npmjs.org/electron/-/electron-25.0.0-beta.5.tgz", - "integrity": "sha512-48EC6IuddKcvxDZLYEqlw3uSCzTwTwM85UhaNsEDScygVByWTWQjQgbl1ivdvvwIm+0wzDZjTK/0fTcL2QEPAg==", + "version": "25.0.0-beta.7", + "resolved": "https://registry.npmjs.org/electron/-/electron-25.0.0-beta.7.tgz", + "integrity": "sha512-pNlAmEH0v3ADTUeMfDiD5u2ODTQKdhABBSkUzvmq+tMJgCbbb8SlffcmekL2fHENDxwPycaH1ld+fCMG33ce6g==", "requires": { "@electron/get": "^2.0.0", "@types/node": "^18.11.18", @@ -16772,8 +16728,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "devOptional": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "encodeurl": { "version": "1.0.2", @@ -16946,15 +16901,15 @@ "dev": true }, "eslint": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.40.0.tgz", - "integrity": "sha512-bvR+TsP9EHL3TqNtj9sCNJVAFK3fBN8Q7g5waghxyRsPLIMwL73XSKnZFK0hk/O2ANC+iAoq6PWMQ+IfBAJIiQ==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", + "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.40.0", + "@eslint/js": "8.41.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -16974,13 +16929,12 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -17851,7 +17805,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, "requires": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -17860,8 +17813,7 @@ "signal-exit": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", - "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", - "dev": true + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==" } } }, @@ -18224,10 +18176,10 @@ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", "dev": true }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, "har-schema": { @@ -18391,18 +18343,18 @@ } }, "http-proxy-agent": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-6.0.1.tgz", - "integrity": "sha512-rD8wrfJHbnVll9lkIpQH3vDbKON1Ssciggwydom/r89HLBXEqdMhL6wx7QF5WePDPSr0OdoztdXoojbrXadG5Q==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-6.1.0.tgz", + "integrity": "sha512-75t5ACHLOMnz/KsDAS4BdHx4J0sneT/HW+Sz070NR+n7RZ7SmYXYn2FXq6D0XwQid8hYgRVf6HZJrYuGzaEqtw==", "requires": { - "agent-base": "^7.0.1", + "agent-base": "^7.0.2", "debug": "^4.3.4" }, "dependencies": { "agent-base": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.0.1.tgz", - "integrity": "sha512-V9to8gr2GK7eA+xskWGAFUX/TLSQKuH2TI06c/jGLL6yLp3oEjtnqM7a5tPV9fC1rabLeAgThZeBwsYX+WWHpw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.0.2.tgz", + "integrity": "sha512-k2/tQ1+8Zf50dEUJWklUP80LcE/+Ph+OJ6cf2Ff2fD/c/TtCe6ofnCoNMz9UnyxOQYlaAALZtEWETzn+1JjfHg==", "requires": { "debug": "^4.3.4" } @@ -18429,18 +18381,18 @@ } }, "https-proxy-agent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-6.1.0.tgz", - "integrity": "sha512-rvGRAlc3y+iS7AC9Os2joN91mX8wHpJ4TEklmHHxr7Gz2Juqa7fJmJ8wWxXNpTaRt56MQTwojxV5d82UW/+jwg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-6.2.0.tgz", + "integrity": "sha512-4xhCnMpxR9fupa7leh9uJK2P/qjYIeaM9uZ9c1bi1JDSwX2VH9NDk/oKSToNX4gBKa2WT31Mldne7e26ckohLQ==", "requires": { - "agent-base": "^7.0.1", + "agent-base": "^7.0.2", "debug": "4" }, "dependencies": { "agent-base": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.0.1.tgz", - "integrity": "sha512-V9to8gr2GK7eA+xskWGAFUX/TLSQKuH2TI06c/jGLL6yLp3oEjtnqM7a5tPV9fC1rabLeAgThZeBwsYX+WWHpw==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.0.2.tgz", + "integrity": "sha512-k2/tQ1+8Zf50dEUJWklUP80LcE/+Ph+OJ6cf2Ff2fD/c/TtCe6ofnCoNMz9UnyxOQYlaAALZtEWETzn+1JjfHg==", "requires": { "debug": "^4.3.4" } @@ -18726,8 +18678,7 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "devOptional": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-function": { "version": "1.0.2", @@ -18901,8 +18852,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "devOptional": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "3.0.1", @@ -18928,7 +18878,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.0.tgz", "integrity": "sha512-r5XBrqIJfwRIjRt/Xr5fv9Wh09qyhHfKnYddDlpM+ibRR20qrYActpCAgU6U+d53EOEjzkvxPMVHSlgR7leXrQ==", - "dev": true, "requires": { "@isaacs/cliui": "^8.0.2", "@pkgjs/parseargs": "^0.11.0" @@ -19050,12 +18999,6 @@ "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" }, - "js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", - "dev": true - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -20621,8 +20564,7 @@ "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "devOptional": true + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-parse": { "version": "1.0.7", @@ -21265,11 +21207,11 @@ "dev": true }, "rimraf": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz", - "integrity": "sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz", + "integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==", "requires": { - "glob": "^10.0.0" + "glob": "^10.2.5" }, "dependencies": { "brace-expansion": { @@ -21281,14 +21223,15 @@ } }, "glob": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.0.0.tgz", - "integrity": "sha512-zmp9ZDC6NpDNLujV2W2n+3lH+BafIVZ4/ct+Yj3BMZTH/+bgm/eVjHzeFLwxJrrIGgjjS2eiQLlpurHsNlEAtQ==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.5.tgz", + "integrity": "sha512-Gj+dFYPZ5hc5dazjXzB0iHg2jKWJZYMjITXYPBRQ/xc2Buw7H0BINknRTwURJ6IC6MEFpYbLvtgVb3qD+DwyuA==", "requires": { - "fs.realpath": "^1.0.0", + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", "minimatch": "^9.0.0", - "minipass": "^5.0.0", - "path-scurry": "^1.6.4" + "minipass": "^5.0.0 || ^6.0.2", + "path-scurry": "^1.7.0" } }, "minimatch": { @@ -21300,9 +21243,9 @@ } }, "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", + "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==" } } }, @@ -21650,7 +21593,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "devOptional": true, "requires": { "shebang-regex": "^3.0.0" } @@ -21658,8 +21600,7 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "devOptional": true + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "shimmer": { "version": "1.2.1", @@ -21906,7 +21847,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "devOptional": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -21917,7 +21857,6 @@ "version": "npm:string-width@4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -21966,7 +21905,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "devOptional": true, "requires": { "ansi-regex": "^5.0.1" } @@ -21975,7 +21913,6 @@ "version": "npm:strip-ansi@6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -22619,9 +22556,9 @@ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" }, "webpack": { - "version": "5.82.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.82.1.tgz", - "integrity": "sha512-C6uiGQJ+Gt4RyHXXYt+v9f+SN1v83x68URwgxNQ98cvH8kxiuywWGP4XeNZ1paOzZ63aY3cTciCEQJNFUljlLw==", + "version": "5.83.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.83.1.tgz", + "integrity": "sha512-TNsG9jDScbNuB+Lb/3+vYolPplCS3bbEaJf+Bj0Gw4DhP3ioAflBb1flcRt9zsWITyvOhM96wMQNRWlSX52DgA==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.3", @@ -22726,7 +22663,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "devOptional": true, "requires": { "isexe": "^2.0.0" } @@ -22800,7 +22736,6 @@ "version": "npm:wrap-ansi@7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", diff --git a/package.json b/package.json index 5f16fefea..d48a2033f 100644 --- a/package.json +++ b/package.json @@ -60,8 +60,8 @@ "helmet": "7.0.0", "html": "1.0.0", "html2plaintext": "2.1.4", - "http-proxy-agent": "6.0.1", - "https-proxy-agent": "6.1.0", + "http-proxy-agent": "6.1.0", + "https-proxy-agent": "6.2.0", "image-type": "4.1.0", "ini": "3.0.1", "is-animated": "2.0.2", @@ -78,7 +78,7 @@ "react": "17.0.2", "react-dom": "17.0.2", "request": "2.88.2", - "rimraf": "5.0.0", + "rimraf": "5.0.1", "safe-compare": "1.1.4", "sanitize-filename": "1.6.3", "sanitize-html": "2.10.0", @@ -97,11 +97,11 @@ }, "devDependencies": { "cross-env": "7.0.3", - "electron": "25.0.0-beta.5", + "electron": "25.0.0-beta.7", "electron-builder": "23.6.0", "electron-packager": "17.1.1", "electron-rebuild": "3.2.9", - "eslint": "8.40.0", + "eslint": "8.41.0", "eslint-config-airbnb-base": "15.0.0", "eslint-config-prettier": "8.8.0", "eslint-plugin-import": "2.27.5", diff --git a/src/becca/entities/abstract_becca_entity.js b/src/becca/entities/abstract_becca_entity.js index bf4c4597d..16e0f87c5 100644 --- a/src/becca/entities/abstract_becca_entity.js +++ b/src/becca/entities/abstract_becca_entity.js @@ -254,6 +254,13 @@ class AbstractBeccaEntity { ? "" : content.toString("utf-8"); } else { + // see https://github.com/zadam/trilium/issues/3523 + // IIRC a zero-sized buffer can be returned as null from the database + if (content === null) { + // this will force de/encryption + content = Buffer.alloc(0); + } + return content; } } diff --git a/src/becca/entities/battachment.js b/src/becca/entities/battachment.js index c106f375c..cc2e30011 100644 --- a/src/becca/entities/battachment.js +++ b/src/becca/entities/battachment.js @@ -5,6 +5,7 @@ const dateUtils = require('../../services/date_utils'); const AbstractBeccaEntity = require("./abstract_becca_entity"); const sql = require("../../services/sql"); const protectedSessionService = require("../../services/protected_session.js"); +const log = require("../../services/log.js"); const attachmentRoleToNoteTypeMapping = { 'image': 'image' @@ -57,6 +58,8 @@ class BAttachment extends AbstractBeccaEntity { this.utcDateModified = row.utcDateModified; /** @type {string} */ this.utcDateScheduledForErasureSince = row.utcDateScheduledForErasureSince; + + this.decrypt(); } /** @returns {BAttachment} */ @@ -86,6 +89,22 @@ class BAttachment extends AbstractBeccaEntity { || protectedSessionService.isProtectedSessionAvailable() } + getTitleOrProtected() { + return this.isContentAvailable() ? this.title : '[protected]'; + } + + decrypt() { + if (this.isProtected && !this.isDecrypted && protectedSessionService.isProtectedSessionAvailable()) { + try { + this.title = protectedSessionService.decryptString(this.title); + this.isDecrypted = true; + } + catch (e) { + log.error(`Could not decrypt attachment ${this.attachmentId}: ${e.message} ${e.stack}`); + } + } + } + /** @returns {string|Buffer} */ getContent() { return this._getContent(); @@ -192,7 +211,19 @@ class BAttachment extends AbstractBeccaEntity { } getPojoToSave() { - return this.getPojo(); + const pojo = this.getPojo(); + + if (pojo.isProtected) { + if (this.isDecrypted) { + pojo.title = protectedSessionService.encrypt(pojo.title); + } + else { + // updating protected note outside of protected session means we will keep original ciphertexts + delete pojo.title; + } + } + + return pojo; } } diff --git a/src/public/app/services/content_renderer.js b/src/public/app/services/content_renderer.js new file mode 100644 index 000000000..97496431c --- /dev/null +++ b/src/public/app/services/content_renderer.js @@ -0,0 +1,292 @@ +import renderService from "./render.js"; +import protectedSessionService from "./protected_session.js"; +import protectedSessionHolder from "./protected_session_holder.js"; +import libraryLoader from "./library_loader.js"; +import openService from "./open.js"; +import froca from "./froca.js"; +import utils from "./utils.js"; +import linkService from "./link.js"; +import treeService from "./tree.js"; +import FNote from "../entities/fnote.js"; +import FAttachment from "../entities/fattachment.js"; + +let idCounter = 1; + +/** + * @param {FNote|FAttachment} entity + * @param {object} options + * @return {Promise<{type: string, $renderedContent: jQuery}>} + */ +async function getRenderedContent(entity, options = {}) { + options = Object.assign({ + trim: false, + tooltip: false + }, options); + + const type = getRenderingType(entity); + // attachment supports only image and file/pdf/audio/video + + const $renderedContent = $('
'); + + if (type === 'text') { + await renderText(entity, options, $renderedContent); + } + else if (type === 'code') { + await renderCode(entity, options, $renderedContent); + } + else if (type === 'image') { + renderImage(entity, $renderedContent); + } + else if (!options.tooltip && ['file', 'pdf', 'audio', 'video'].includes(type)) { + renderFile(entity, type, $renderedContent); + } + else if (type === 'mermaid') { + await renderMermaid(entity, $renderedContent); + } + else if (type === 'render') { + const $content = $('
'); + + await renderService.render(entity, $content, this.ctx); + + $renderedContent.append($content); + } + else if (type === 'canvas') { + await renderCanvas(entity, $renderedContent); + } + else if (type === 'book') { + // nothing, a book doesn't have its own content + } + else if (!options.tooltip && type === 'protectedSession') { + const $button = $(``) + .on('click', protectedSessionService.enterProtectedSession); + + $renderedContent.append( + $("
") + .append("
This note is protected and to access it you need to enter password.
") + .append("
") + .append($button) + ); + } + else { + $renderedContent.append($("

Content of this note cannot be displayed

")); + } + + if (entity instanceof FNote) { + $renderedContent.addClass(entity.getCssClass()); + } + + return { + $renderedContent, + type + }; +} + +async function renderText(note, options, $renderedContent) { + // entity must be FNote + const blob = await note.getBlob({preview: options.trim}); + + if (!utils.isHtmlEmpty(blob.content)) { + $renderedContent.append($('
').html(trim(blob.content, options.trim))); + + if ($renderedContent.find('span.math-tex').length > 0) { + await libraryLoader.requireLibrary(libraryLoader.KATEX); + + renderMathInElement($renderedContent[0], {trust: true}); + } + + const getNoteIdFromLink = el => treeService.getNoteIdFromNotePath($(el).attr('href')); + const referenceLinks = $renderedContent.find("a.reference-link"); + const noteIdsToPrefetch = referenceLinks.map(el => getNoteIdFromLink(el)); + await froca.getNotes(noteIdsToPrefetch); + + for (const el of referenceLinks) { + const noteId = getNoteIdFromLink(el); + + await linkService.loadReferenceLinkTitle(noteId, $(el)); + } + } else { + await renderChildrenList($renderedContent, note); + } +} + +async function renderCode(note, options, $renderedContent) { + const blob = await note.getBlob({preview: options.trim}); + + $renderedContent.append($("
").text(trim(blob.content, options.trim)));
+}
+
+function renderImage(entity, $renderedContent) {
+    const sanitizedTitle = entity.title.replace(/[^a-z0-9-.]/gi, "");
+
+    $renderedContent.append(
+        $("")
+            .attr("src", `api/images/${entity.noteId}/${sanitizedTitle}`)
+            .css("max-width", "100%")
+    );
+}
+
+function renderFile(entity, type, $renderedContent) {
+    let entityType, entityId;
+
+    if (entity instanceof FNote) {
+        entityType = 'notes';
+        entityId = entity.noteId;
+    } else if (entity instanceof FAttachment) {
+        entityType = 'attachments';
+        entityId = entity.attachmentId;
+    } else {
+        throw new Error(`Can't recognize entity type of '${entity}'`);
+    }
+
+    const $downloadButton = $('');
+    const $openButton = $('');
+
+    $downloadButton.on('click', () => openService.downloadFileNote(entity.noteId));
+    $openButton.on('click', () => openService.openNoteExternally(entity.noteId, entity.mime));
+
+    // open doesn't work for protected notes since it works through a browser which isn't in protected session
+    $openButton.toggle(!entity.isProtected);
+
+    const $content = $('
'); + + if (type === 'pdf') { + const $pdfPreview = $(''); + $pdfPreview.attr("src", openService.getUrlForDownload(`api/${entityType}/${entityId}/open`)); + + $content.append($pdfPreview); + } else if (type === 'audio') { + const $audioPreview = $('') + .attr("src", openService.getUrlForStreaming(`api/${entityType}/${entityId}/open-partial`)) + .attr("type", entity.mime) + .css("width", "100%"); + + $content.append($audioPreview); + } else if (type === 'video') { + const $videoPreview = $('') + .attr("src", openService.getUrlForDownload(`api/${entityType}/${entityId}/open-partial`)) + .attr("type", entity.mime) + .css("width", "100%"); + + $content.append($videoPreview); + } + + $content.append( + $('
') + .append($downloadButton) + .append($openButton) + ); + + $renderedContent.append($content); +} + +async function renderMermaid(note, $renderedContent) { + await libraryLoader.requireLibrary(libraryLoader.MERMAID); + + const blob = await note.getBlob(); + const content = blob.content || ""; + + $renderedContent + .css("display", "flex") + .css("justify-content", "space-around"); + + const documentStyle = window.getComputedStyle(document.documentElement); + const mermaidTheme = documentStyle.getPropertyValue('--mermaid-theme'); + + mermaid.mermaidAPI.initialize({startOnLoad: false, theme: mermaidTheme.trim(), securityLevel: 'antiscript'}); + + try { + mermaid.mermaidAPI.render("in-mermaid-graph-" + idCounter++, content, + content => $renderedContent.append($(content))); + } catch (e) { + const $error = $("

The diagram could not displayed.

"); + + $renderedContent.append($error); + } +} + +async function renderCanvas(note, $renderedContent) { + // make sure surrounding container has size of what is visible. Then image is shrinked to its boundaries + $renderedContent.css({height: "100%", width: "100%"}); + + const blob = await note.getBlob(); + const content = blob.content || ""; + + try { + const placeHolderSVG = ""; + const data = JSON.parse(content) + const svg = data.svg || placeHolderSVG; + /** + * maxWidth: size down to 100% (full) width of container but do not enlarge! + * height:auto to ensure that height scales with width + */ + $renderedContent.append($(svg).css({maxWidth: "100%", maxHeight: "100%", height: "auto", width: "auto"})); + } catch (err) { + console.error("error parsing content as JSON", content, err); + $renderedContent.append($("
").text("Error parsing content. Please check console.error() for more details.")); + } +} + +/** + * @param {jQuery} $renderedContent + * @param {FNote} note + * @returns {Promise} + */ +async function renderChildrenList($renderedContent, note) { + $renderedContent.css("padding", "10px"); + $renderedContent.addClass("text-with-ellipsis"); + + let childNoteIds = note.getChildNoteIds(); + + if (childNoteIds.length > 10) { + childNoteIds = childNoteIds.slice(0, 10); + } + + // just load the first 10 child notes + const childNotes = await froca.getNotes(childNoteIds); + + for (const childNote of childNotes) { + $renderedContent.append(await linkService.createNoteLink(`${note.noteId}/${childNote.noteId}`, { + showTooltip: false, + showNoteIcon: true + })); + + $renderedContent.append("
"); + } +} + +function trim(text, doTrim) { + if (!doTrim) { + return text; + } + else { + return text.substr(0, Math.min(text.length, 2000)); + } +} + +function getRenderingType(entity) { + let type = entity.type || entity.role; + const mime = entity.mime; + + if (type === 'file' && mime === 'application/pdf') { + type = 'pdf'; + } else if (type === 'file' && mime.startsWith('audio/')) { + type = 'audio'; + } else if (type === 'file' && mime.startsWith('video/')) { + type = 'video'; + } + + if (entity.isProtected) { + if (protectedSessionHolder.isProtectedSessionAvailable()) { + protectedSessionHolder.touchProtectedSession(); + } + else { + type = 'protectedSession'; + } + } + + return type; +} + +export default { + getRenderedContent +}; diff --git a/src/public/app/services/note_content_renderer.js b/src/public/app/services/note_content_renderer.js deleted file mode 100644 index 41639b7af..000000000 --- a/src/public/app/services/note_content_renderer.js +++ /dev/null @@ -1,248 +0,0 @@ -import server from "./server.js"; -import renderService from "./render.js"; -import protectedSessionService from "./protected_session.js"; -import protectedSessionHolder from "./protected_session_holder.js"; -import libraryLoader from "./library_loader.js"; -import openService from "./open.js"; -import froca from "./froca.js"; -import utils from "./utils.js"; -import linkService from "./link.js"; -import treeService from "./tree.js"; - -let idCounter = 1; - -/** - * @param {FNote} note - * @param {object} options - * @return {Promise<{type: string, $renderedContent: jQuery}>} - */ -async function getRenderedContent(note, options = {}) { - options = Object.assign({ - trim: false, - tooltip: false - }, options); - - const type = getRenderingType(note); - - const $renderedContent = $('
'); - - if (type === 'text') { - const blob = await note.getBlob({ preview: options.trim }); - - if (!utils.isHtmlEmpty(blob.content)) { - $renderedContent.append($('
').html(trim(blob.content, options.trim))); - - if ($renderedContent.find('span.math-tex').length > 0) { - await libraryLoader.requireLibrary(libraryLoader.KATEX); - - renderMathInElement($renderedContent[0], {trust: true}); - } - - const getNoteIdFromLink = el => treeService.getNoteIdFromNotePath($(el).attr('href')); - const referenceLinks = $renderedContent.find("a.reference-link"); - const noteIdsToPrefetch = referenceLinks.map(el => getNoteIdFromLink(el)); - await froca.getNotes(noteIdsToPrefetch); - - for (const el of referenceLinks) { - const noteId = getNoteIdFromLink(el); - - await linkService.loadReferenceLinkTitle(noteId, $(el)); - } - } - else { - await renderChildrenList($renderedContent, note); - } - } - else if (type === 'code') { - const blob = await note.getBlob({ preview: options.trim }); - - $renderedContent.append($("
").text(trim(blob.content, options.trim)));
-    }
-    else if (type === 'image') {
-        const sanitizedTitle = note.title.replace(/[^a-z0-9-.]/gi, "");
-
-        $renderedContent.append(
-            $("")
-                .attr("src", `api/images/${note.noteId}/${sanitizedTitle}`)
-                .css("max-width", "100%")
-        );
-    }
-    else if (!options.tooltip && ['file', 'pdf', 'audio', 'video'].includes(type)) {
-        const $downloadButton = $('');
-        const $openButton = $('');
-
-        $downloadButton.on('click', () => openService.downloadFileNote(note.noteId));
-        $openButton.on('click', () => openService.openNoteExternally(note.noteId, note.mime));
-
-        // open doesn't work for protected notes since it works through a browser which isn't in protected session
-        $openButton.toggle(!note.isProtected);
-
-        const $content = $('
'); - - if (type === 'pdf') { - const $pdfPreview = $(''); - $pdfPreview.attr("src", openService.getUrlForDownload(`api/notes/${note.noteId}/open`)); - - $content.append($pdfPreview); - } - else if (type === 'audio') { - const $audioPreview = $('') - .attr("src", openService.getUrlForStreaming(`api/notes/${note.noteId}/open-partial`)) - .attr("type", note.mime) - .css("width", "100%"); - - $content.append($audioPreview); - } - else if (type === 'video') { - const $videoPreview = $('') - .attr("src", openService.getUrlForDownload(`api/notes/${note.noteId}/open-partial`)) - .attr("type", note.mime) - .css("width", "100%"); - - $content.append($videoPreview); - } - - $content.append( - $('
') - .append($downloadButton) - .append($openButton) - ); - - $renderedContent.append($content); - } - else if (type === 'mermaid') { - await libraryLoader.requireLibrary(libraryLoader.MERMAID); - - const blob = await note.getBlob(); - const content = blob.content || ""; - - $renderedContent - .css("display", "flex") - .css("justify-content", "space-around"); - - const documentStyle = window.getComputedStyle(document.documentElement); - const mermaidTheme = documentStyle.getPropertyValue('--mermaid-theme'); - - mermaid.mermaidAPI.initialize({ startOnLoad: false, theme: mermaidTheme.trim(), securityLevel: 'antiscript' }); - - try { - mermaid.mermaidAPI.render("in-mermaid-graph-" + idCounter++, content, - content => $renderedContent.append($(content))); - } catch (e) { - const $error = $("

The diagram could not displayed.

"); - - $renderedContent.append($error); - } - } - else if (type === 'render') { - const $content = $('
'); - - await renderService.render(note, $content, this.ctx); - - $renderedContent.append($content); - } - else if (type === 'canvas') { - // make sure surrounding container has size of what is visible. Then image is shrinked to its boundaries - $renderedContent.css({height: "100%", width:"100%"}); - - const blob = await note.getBlob(); - const content = blob.content || ""; - - try { - const placeHolderSVG = ""; - const data = JSON.parse(content) - const svg = data.svg || placeHolderSVG; - /** - * maxWidth: size down to 100% (full) width of container but do not enlarge! - * height:auto to ensure that height scales with width - */ - $renderedContent.append($(svg).css({maxWidth: "100%", maxHeight: "100%", height: "auto", width: "auto"})); - } catch(err) { - console.error("error parsing content as JSON", content, err); - $renderedContent.append($("
").text("Error parsing content. Please check console.error() for more details.")); - } - } - else if (type === 'book') { - // nothing, a book doesn't have its own content - } - else if (!options.tooltip && type === 'protectedSession') { - const $button = $(``) - .on('click', protectedSessionService.enterProtectedSession); - - $renderedContent.append( - $("
") - .append("
This note is protected and to access it you need to enter password.
") - .append("
") - .append($button) - ); - } - else { - $renderedContent.append($("

Content of this note cannot be displayed in the book format

")); - } - - $renderedContent.addClass(note.getCssClass()); - - return { - $renderedContent, - type - }; -} - -async function renderChildrenList($renderedContent, note) { - $renderedContent.css("padding", "10px"); - $renderedContent.addClass("text-with-ellipsis"); - - let childNoteIds = note.getChildNoteIds(); - - if (childNoteIds.length > 10) { - childNoteIds = childNoteIds.slice(0, 10); - } - - // just load the first 10 child notes - const childNotes = await froca.getNotes(childNoteIds); - - for (const childNote of childNotes) { - $renderedContent.append(await linkService.createNoteLink(`${note.noteId}/${childNote.noteId}`, { - showTooltip: false, - showNoteIcon: true - })); - - $renderedContent.append("
"); - } -} - -function trim(text, doTrim) { - if (!doTrim) { - return text; - } - else { - return text.substr(0, Math.min(text.length, 2000)); - } -} - -function getRenderingType(note) { - let type = note.type; - - if (type === 'file' && note.mime === 'application/pdf') { - type = 'pdf'; - } else if (type === 'file' && note.mime.startsWith('audio/')) { - type = 'audio'; - } else if (type === 'file' && note.mime.startsWith('video/')) { - type = 'video'; - } - - if (note.isProtected) { - if (protectedSessionHolder.isProtectedSessionAvailable()) { - protectedSessionHolder.touchProtectedSession(); - } - else { - type = 'protectedSession'; - } - } - - return type; -} - -export default { - getRenderedContent -}; diff --git a/src/public/app/services/note_list_renderer.js b/src/public/app/services/note_list_renderer.js index 60040698c..54881cc23 100644 --- a/src/public/app/services/note_list_renderer.js +++ b/src/public/app/services/note_list_renderer.js @@ -1,5 +1,5 @@ import linkService from "./link.js"; -import noteContentRenderer from "./note_content_renderer.js"; +import contentRenderer from "./content_renderer.js"; import froca from "./froca.js"; import attributeRenderer from "./attribute_renderer.js"; import libraryLoader from "./library_loader.js"; @@ -333,7 +333,7 @@ class NoteListRenderer { const $content = $('
'); try { - const {$renderedContent, type} = await noteContentRenderer.getRenderedContent(note, { + const {$renderedContent, type} = await contentRenderer.getRenderedContent(note, { trim: this.viewType === 'grid' // for grid only short content is needed }); diff --git a/src/public/app/services/note_tooltip.js b/src/public/app/services/note_tooltip.js index bb7e9c897..df6530ed9 100644 --- a/src/public/app/services/note_tooltip.js +++ b/src/public/app/services/note_tooltip.js @@ -3,7 +3,7 @@ import linkService from "./link.js"; import froca from "./froca.js"; import utils from "./utils.js"; import attributeRenderer from "./attribute_renderer.js"; -import noteContentRenderer from "./note_content_renderer.js"; +import contentRenderer from "./content_renderer.js"; import appContext from "../components/app_context.js"; function setupGlobalTooltip() { @@ -90,7 +90,7 @@ async function renderTooltip(note) { const {$renderedAttributes} = await attributeRenderer.renderNormalAttributes(note); - const {$renderedContent} = await noteContentRenderer.getRenderedContent(note, { + const {$renderedContent} = await contentRenderer.getRenderedContent(note, { tooltip: true, trim: true }); diff --git a/src/public/app/widgets/attachment_detail.js b/src/public/app/widgets/attachment_detail.js index f149c10ad..a134fc8fc 100644 --- a/src/public/app/widgets/attachment_detail.js +++ b/src/public/app/widgets/attachment_detail.js @@ -5,6 +5,7 @@ import server from "../services/server.js"; import options from "../services/options.js"; import imageService from "../services/image.js"; import linkService from "../services/link.js"; +import contentRenderer from "../services/content_renderer.js"; const TPL = `
@@ -140,17 +141,7 @@ export default class AttachmentDetailWidget extends BasicWidget { this.$wrapper.find('.attachment-details') .text(`Role: ${this.attachment.role}, Size: ${utils.formatSize(this.attachment.contentLength)}`); this.$wrapper.find('.attachment-actions-container').append(this.attachmentActionsWidget.render()); - this.$wrapper.find('.attachment-content').append(this.renderContent()); - } - - renderContent() { - if (this.attachment.content) { - return $("
").text(this.attachment.content);
-        } else if (this.attachment.role === 'image') {
-            return ``;
-        } else {
-            return '';
-        }
+        this.$wrapper.find('.attachment-content').append(contentRenderer.getRenderedContent(this.attachment));
     }
 
     copyAttachmentReferenceToClipboard() {
@@ -164,7 +155,7 @@ export default class AttachmentDetailWidget extends BasicWidget {
             if (attachmentChange.isDeleted) {
                 this.toggleInt(false);
             } else {
-                this.attachment = await server.get(`attachments/${this.attachment.attachmentId}?includeContent=true`);
+                this.attachment = await server.get(`attachments/${this.attachment.attachmentId}`);
 
                 this.refresh();
             }
diff --git a/src/public/app/widgets/type_widgets/abstract_text_type_widget.js b/src/public/app/widgets/type_widgets/abstract_text_type_widget.js
index 29399790a..1d8570dd6 100644
--- a/src/public/app/widgets/type_widgets/abstract_text_type_widget.js
+++ b/src/public/app/widgets/type_widgets/abstract_text_type_widget.js
@@ -2,7 +2,7 @@ import TypeWidget from "./type_widget.js";
 import appContext from "../../components/app_context.js";
 import froca from "../../services/froca.js";
 import linkService from "../../services/link.js";
-import noteContentRenderer from "../../services/note_content_renderer.js";
+import contentRenderer from "../../services/content_renderer.js";
 import utils from "../../services/utils.js";
 
 export default class AbstractTextTypeWidget extends TypeWidget {
@@ -86,7 +86,7 @@ export default class AbstractTextTypeWidget extends TypeWidget {
                     .append($link)
             );
 
-            const {$renderedContent, type} = await noteContentRenderer.getRenderedContent(note);
+            const {$renderedContent, type} = await contentRenderer.getRenderedContent(note);
 
             $wrapper.append(
                 $(`
`) diff --git a/src/public/app/widgets/type_widgets/attachment_detail.js b/src/public/app/widgets/type_widgets/attachment_detail.js index c22e8cdcf..679b5de27 100644 --- a/src/public/app/widgets/type_widgets/attachment_detail.js +++ b/src/public/app/widgets/type_widgets/attachment_detail.js @@ -50,7 +50,7 @@ export default class AttachmentDetailTypeWidget extends TypeWidget { }) ); - const attachment = await server.get(`attachments/${this.attachmentId}/?includeContent=true`); + const attachment = await server.get(`attachments/${this.attachmentId}`); if (!attachment) { this.$wrapper.html("This attachment has been deleted."); @@ -67,8 +67,6 @@ export default class AttachmentDetailTypeWidget extends TypeWidget { async entitiesReloadedEvent({loadResults}) { const attachmentChange = loadResults.getAttachments().find(att => att.attachmentId === this.attachmentId); - console.log(attachmentChange); - if (attachmentChange?.isDeleted) { this.refresh(); // all other updates are handled within AttachmentDetailWidget } diff --git a/src/public/app/widgets/type_widgets/attachment_list.js b/src/public/app/widgets/type_widgets/attachment_list.js index 5c66feffe..707b6b5fa 100644 --- a/src/public/app/widgets/type_widgets/attachment_list.js +++ b/src/public/app/widgets/type_widgets/attachment_list.js @@ -51,7 +51,7 @@ export default class AttachmentListTypeWidget extends TypeWidget { this.children = []; this.renderedAttachmentIds = new Set(); - const attachments = await server.get(`notes/${this.noteId}/attachments?includeContent=true`); + const attachments = await server.get(`notes/${this.noteId}/attachments`); if (attachments.length === 0) { this.$list.html('
This note has no attachments.
'); @@ -73,7 +73,7 @@ export default class AttachmentListTypeWidget extends TypeWidget { async entitiesReloadedEvent({loadResults}) { // updates and deletions are handled by the detail, for new attachments the whole list has to be refreshed const attachmentsAdded = loadResults.getAttachments() - .find(att => this.renderedAttachmentIds.has(att.attachmentId)); + .some(att => !this.renderedAttachmentIds.has(att.attachmentId)); if (attachmentsAdded) { this.refresh(); diff --git a/src/routes/api/attachments.js b/src/routes/api/attachments.js index 5ce7b1054..352a9c51a 100644 --- a/src/routes/api/attachments.js +++ b/src/routes/api/attachments.js @@ -1,5 +1,4 @@ const becca = require("../../becca/becca"); -const utils = require("../../services/utils"); const blobService = require("../../services/blob.js"); function getAttachmentBlob(req) { @@ -9,42 +8,15 @@ function getAttachmentBlob(req) { } function getAttachments(req) { - const includeContent = req.query.includeContent === 'true'; const note = becca.getNoteOrThrow(req.params.noteId); - return note.getAttachments() - .map(attachment => processAttachment(attachment, includeContent)); + return note.getAttachments(); } function getAttachment(req) { - const includeContent = req.query.includeContent === 'true'; const {attachmentId} = req.params; - const attachment = becca.getAttachmentOrThrow(attachmentId); - - return processAttachment(attachment, includeContent); -} - -function processAttachment(attachment, includeContent) { - const pojo = attachment.getPojo(); - - if (includeContent) { - if (utils.isStringNote(null, attachment.mime)) { - pojo.content = attachment.getContent()?.toString(); - pojo.contentLength = pojo.content.length; - - const MAX_ATTACHMENT_LENGTH = 1_000_000; - - if (pojo.content.length > MAX_ATTACHMENT_LENGTH) { - pojo.content = pojo.content.substring(0, MAX_ATTACHMENT_LENGTH); - } - } else { - const content = attachment.getContent(); - pojo.contentLength = content?.length; - } - } - - return pojo; + return becca.getAttachmentOrThrow(attachmentId); } function saveAttachment(req) { diff --git a/src/services/notes.js b/src/services/notes.js index 6fe949115..fea136870 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -311,18 +311,19 @@ function protectNote(note, protect) { const content = note.getContent(); note.isProtected = protect; - - // see https://github.com/zadam/trilium/issues/3523 - // IIRC a zero-sized buffer can be returned as null from the database - if (content !== null) { - // this will force de/encryption - note.setContent(content); - } - - note.save(); + note.setContent(content, { forceSave: true }); } noteRevisionService.protectNoteRevisions(note); + + for (const attachment of note.getAttachments()) { + if (protect !== attachment.isProtected) { + const content = attachment.getContent(); + + attachment.isProtected = protect; + attachment.setContent(content, { forceSave: true }); + } + } } catch (e) { log.error(`Could not un/protect note '${note.noteId}'`);