From f261c5841a1ddba582fb5589452081ac881e31a1 Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Mon, 31 Mar 2025 09:00:15 +0200 Subject: [PATCH 01/33] deps: remove dprint to be replaced by eslint-stylistic https://eslint.style/ --- package-lock.json | 146 +--------------------------------------------- package.json | 5 +- 2 files changed, 5 insertions(+), 146 deletions(-) diff --git a/package-lock.json b/package-lock.json index da65a3d3f..89aba5d2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "trilium", - "version": "0.92.5", + "version": "0.92.5-beta", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "trilium", - "version": "0.92.5", + "version": "0.92.5-beta", "license": "AGPL-3.0-only", "dependencies": { "@braintree/sanitize-url": "7.1.1", @@ -201,8 +201,7 @@ "webpack-dev-middleware": "7.4.2" }, "optionalDependencies": { - "appdmg": "0.6.6", - "dprint": "0.49.1" + "appdmg": "0.6.6" } }, "node_modules/@ampproject/remapping": { @@ -574,123 +573,6 @@ "node": ">=14.17.0" } }, - "node_modules/@dprint/darwin-arm64": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/@dprint/darwin-arm64/-/darwin-arm64-0.49.1.tgz", - "integrity": "sha512-ib6KcJWo/M5RJWXOQKhP664FG1hAvG7nrbkh+j8n+oXdzmbyDdXTP+zW+aM3/sIQUkGaZky1xy1j2VeScMEEHQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@dprint/darwin-x64": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/@dprint/darwin-x64/-/darwin-x64-0.49.1.tgz", - "integrity": "sha512-vIVgnYxV7YYa1d6Uyz707RbgB9rwefGPam+rzaueFNPQjdOxPOTQDuMEJDS+Z3BlI00MfeoupIfIUGsXoM4dpQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@dprint/linux-arm64-glibc": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-glibc/-/linux-arm64-glibc-0.49.1.tgz", - "integrity": "sha512-ZeIh6qMPWLBBifDtU0XadpK36b4WoaTqCOt0rWKfoTjq1RAt78EgqETWp43Dbr6et/HvTgYdoWF0ZNEu2FJFFA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@dprint/linux-arm64-musl": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-musl/-/linux-arm64-musl-0.49.1.tgz", - "integrity": "sha512-/nuRyx+TykN6MqhlSCRs/t3o1XXlikiwTc9emWdzMeLGllYvJrcht9gRJ1/q1SqwCFhzgnD9H7roxxfji1tc+Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@dprint/linux-riscv64-glibc": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/@dprint/linux-riscv64-glibc/-/linux-riscv64-glibc-0.49.1.tgz", - "integrity": "sha512-RHBqrnvGO+xW4Oh0QuToBqWtkXMcfjqa1TqbBFF03yopFzZA2oRKX83PhjTWgd/IglaOns0BgmaLJy/JBSxOfQ==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@dprint/linux-x64-glibc": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/@dprint/linux-x64-glibc/-/linux-x64-glibc-0.49.1.tgz", - "integrity": "sha512-MjFE894mIQXOKBencuakKyzAI4KcDe/p0Y9lRp9YSw/FneR4QWH9VBH90h8fRxcIlWMArjFFJJAtsBnn5qgxeg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@dprint/linux-x64-musl": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/@dprint/linux-x64-musl/-/linux-x64-musl-0.49.1.tgz", - "integrity": "sha512-CvGBWOksHgrL1uzYqtPFvZz0+E82BzgoCIEHJeuYaveEn37qWZS5jqoCm/vz6BfoivE1dVuyyOT78Begj9KxkQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@dprint/win32-arm64": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/@dprint/win32-arm64/-/win32-arm64-0.49.1.tgz", - "integrity": "sha512-gQa4s82lMcXjfdxjWBQun6IJlXdPZZaIj2/2cqXWVEOYPKxAZ/JvGzt2pPG+i73h9KHjNLIV8M9ckqEH3oHufg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@dprint/win32-x64": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/@dprint/win32-x64/-/win32-x64-0.49.1.tgz", - "integrity": "sha512-nPU6+hoVze5JJlgET7woYWElBw0IUaB/9XKTaglknQuUUfsmD75D9pkgJTxdIxl9Bg/i5O7c9wb3Nj4XNiTIfw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@electron-forge/cli": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/@electron-forge/cli/-/cli-7.8.0.tgz", @@ -9507,28 +9389,6 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/dprint": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/dprint/-/dprint-0.49.1.tgz", - "integrity": "sha512-pO9XH79SyXybj2Vhc9ITZMEI8cJkdlQQRoD8oEfPH6Jjpp/7WX5kIgECVd3DBOjjAdCSiW6R47v3gJBx/qZVkw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "bin": { - "dprint": "bin.js" - }, - "optionalDependencies": { - "@dprint/darwin-arm64": "0.49.1", - "@dprint/darwin-x64": "0.49.1", - "@dprint/linux-arm64-glibc": "0.49.1", - "@dprint/linux-arm64-musl": "0.49.1", - "@dprint/linux-riscv64-glibc": "0.49.1", - "@dprint/linux-x64-glibc": "0.49.1", - "@dprint/linux-x64-musl": "0.49.1", - "@dprint/win32-arm64": "0.49.1", - "@dprint/win32-x64": "0.49.1" - } - }, "node_modules/draggabilly": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/draggabilly/-/draggabilly-3.0.0.tgz", diff --git a/package.json b/package.json index 9035538b5..c4123f8ce 100644 --- a/package.json +++ b/package.json @@ -219,7 +219,7 @@ "bootstrap": "5.3.3", "copy-webpack-plugin": "13.0.0", "cross-env": "7.0.3", - "css-loader": "7.1.2", + "css-loader": "7.1.2", "electron": "35.1.2", "eslint": "9.23.0", "esm": "3.2.25", @@ -258,7 +258,6 @@ "webpack-dev-middleware": "7.4.2" }, "optionalDependencies": { - "appdmg": "0.6.6", - "dprint": "0.49.1" + "appdmg": "0.6.6" } } From 66cfc78d8dfb9a393fb6ed0993d05e7af4622fd1 Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Mon, 31 Mar 2025 09:01:39 +0200 Subject: [PATCH 02/33] deps: @stylistic/eslint-plugin for formatting replaces previously used dprint --- package-lock.json | 34 ++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 35 insertions(+) diff --git a/package-lock.json b/package-lock.json index 89aba5d2e..00f8617eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -117,6 +117,7 @@ "@mind-elixir/node-menu": "1.0.5", "@playwright/test": "1.51.1", "@popperjs/core": "2.11.8", + "@stylistic/eslint-plugin": "4.2.0", "@types/archiver": "6.0.3", "@types/better-sqlite3": "7.6.12", "@types/bootstrap": "5.2.10", @@ -4436,6 +4437,39 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@stylistic/eslint-plugin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.2.0.tgz", + "integrity": "sha512-8hXezgz7jexGHdo5WN6JBEIPHCSFyyU4vgbxevu4YLVS5vl+sxqAAGyXSzfNDyR6xMNSH5H1x67nsXcYMOHtZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.23.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "estraverse": "^5.3.0", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0" + } + }, + "node_modules/@stylistic/eslint-plugin/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", diff --git a/package.json b/package.json index c4123f8ce..fdb888156 100644 --- a/package.json +++ b/package.json @@ -174,6 +174,7 @@ "@mind-elixir/node-menu": "1.0.5", "@playwright/test": "1.51.1", "@popperjs/core": "2.11.8", + "@stylistic/eslint-plugin": "4.2.0", "@types/archiver": "6.0.3", "@types/better-sqlite3": "7.6.12", "@types/bootstrap": "5.2.10", From 8354fec70ea6f138d5bafedc67e85dcee2d41777 Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Tue, 1 Apr 2025 08:50:43 +0200 Subject: [PATCH 03/33] chore: add initial @stylistic rules based on what we had with dprint -> which in turn was based on what we had with prettier --- eslint.config.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/eslint.config.js b/eslint.config.js index 55ad4d9a2..9c5490480 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,5 +1,20 @@ import eslint from "@eslint/js"; import tseslint from "typescript-eslint"; +import stylistic from "@stylistic/eslint-plugin"; + + +// Go to https://eslint.style/rules/default/${rule_without_prefix} to check the rule details +const stylisticRules = { + "@stylistic/indent": [ "error", 4 ], + "@stylistic/quotes": [ "error", "double" ], + "@stylistic/semi": [ "error", "always" ], + "@stylistic/quote-props": [ "error", "consistent-as-needed" ], + "@stylistic/max-len": [ "error", { code: 200 } ], + "@stylistic/comma-dangle": [ "error", "never" ], + "@stylistic/linebreak-style": [ "error", "unix" ], + "@stylistic/array-bracket-spacing": [ "error", "always" ], + "@stylistic/object-curly-spacing": [ "error", "always" ] +}; export default tseslint.config( eslint.configs.recommended, @@ -17,6 +32,9 @@ export default tseslint.config( } }, { + plugins: { + "@stylistic": stylistic + }, rules: { // add rule overrides here "no-undef": "off", @@ -27,7 +45,8 @@ export default tseslint.config( "argsIgnorePattern": "^_", "varsIgnorePattern": "^_", } - ] + ], + ...stylisticRules } }, { From ad18883952c9ef1fbc07095ca67e901417bf42c7 Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Tue, 1 Apr 2025 08:56:36 +0200 Subject: [PATCH 04/33] chore: add padded-blocks @stylistic rule --- eslint.config.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/eslint.config.js b/eslint.config.js index 9c5490480..3e908d953 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -13,7 +13,8 @@ const stylisticRules = { "@stylistic/comma-dangle": [ "error", "never" ], "@stylistic/linebreak-style": [ "error", "unix" ], "@stylistic/array-bracket-spacing": [ "error", "always" ], - "@stylistic/object-curly-spacing": [ "error", "always" ] + "@stylistic/object-curly-spacing": [ "error", "always" ], + "@stylistic/padded-blocks": [ "error", { classes: "always" } ] }; export default tseslint.config( From 237fcdab2080b57bc9a4203e2c890fd0bee72db9 Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Tue, 1 Apr 2025 08:57:24 +0200 Subject: [PATCH 05/33] chore: run eslint on eslint.config.js :-) --- eslint.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 3e908d953..d54886b60 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -43,8 +43,8 @@ export default tseslint.config( "@typescript-eslint/no-unused-vars": [ "error", { - "argsIgnorePattern": "^_", - "varsIgnorePattern": "^_", + argsIgnorePattern: "^_", + varsIgnorePattern: "^_" } ], ...stylisticRules From cd992806a6a59f6abd52245da8edeabd610661e1 Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Tue, 1 Apr 2025 09:00:37 +0200 Subject: [PATCH 06/33] chore(tsconfig): add "*.js" to include, to fix eslint "ProjectService" error added it only to the "dev" tsconfig. The tsconfig.build.json, which is used for build output does not require it. eslint was previosuly reporting on itself: "TriliumNextNotes/eslint.config.js was not found by the project service. Consider either including it in the tsconfig.json or including it in allowDefaultProject" --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index c1f3ef48b..10da18c4b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,7 @@ "esModuleInterop": true, "verbatimModuleSyntax": true }, - "include": ["./src/**/*.js", "./src/**/*.ts", "./*.ts", "./spec/**/*.ts"], + "include": ["./src/**/*.js", "./src/**/*.ts", "./*.ts", "./*.js", "./spec/**/*.ts"], "exclude": ["./node_modules/**/*", "./spec-es6/**/*.ts"], "files": ["src/types.d.ts", "src/public/app/types.d.ts"] } From e93d7e6bd10505d315d6411c800d64451e59b71d Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Tue, 1 Apr 2025 09:01:11 +0200 Subject: [PATCH 07/33] chore: remove .dprint.json config file -> now unused --- .dprint.json | 44 -------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 .dprint.json diff --git a/.dprint.json b/.dprint.json deleted file mode 100644 index 21e6f8585..000000000 --- a/.dprint.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "typescript": { - "indentWidth": 4, - "quoteStyle": "preferDouble", - "semiColons": "prefer", - "quoteProps": "asNeeded", - "newLineKind": "lf", - "lineWidth": 200, - "trailingCommas": "never", - "arrayPattern.spaceAround": true, - "arrayExpression.spaceAround": true - }, - "json": { - }, - "markdown": { - }, - "dockerfile": { - }, - "malva": { - }, - "markup": { - }, - "yaml": { - }, - "excludes": [ - "**/node_modules", - "**/*-lock.json", - "*.html", - "*.md", - "*.yml", - "libraries/*", - "docs/*", - "src/public/app/doc_notes" - ], - "plugins": [ - "https://plugins.dprint.dev/typescript-0.94.0.wasm", - "https://plugins.dprint.dev/json-0.20.0.wasm", - "https://plugins.dprint.dev/markdown-0.18.0.wasm", - "https://plugins.dprint.dev/dockerfile-0.3.2.wasm", - "https://plugins.dprint.dev/g-plane/malva-v0.11.1.wasm", - "https://plugins.dprint.dev/g-plane/markup_fmt-v0.19.0.wasm", - "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm" - ] -} From 8dfdb48e8d7abd76ef0a72ebdc914d9a15bcf908 Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Tue, 1 Apr 2025 09:17:24 +0200 Subject: [PATCH 08/33] chore(eslint): configure @stylistic/quotes rule --- eslint.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eslint.config.js b/eslint.config.js index d54886b60..5abb68103 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -6,7 +6,7 @@ import stylistic from "@stylistic/eslint-plugin"; // Go to https://eslint.style/rules/default/${rule_without_prefix} to check the rule details const stylisticRules = { "@stylistic/indent": [ "error", 4 ], - "@stylistic/quotes": [ "error", "double" ], + "@stylistic/quotes": [ "error", "double", { avoidEscape: true, allowTemplateLiterals: "always" } ], "@stylistic/semi": [ "error", "always" ], "@stylistic/quote-props": [ "error", "consistent-as-needed" ], "@stylistic/max-len": [ "error", { code: 200 } ], From a0fe60eff1bfb9a9952683c5c26a4588191f0232 Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Wed, 2 Apr 2025 08:35:24 +0200 Subject: [PATCH 09/33] chore(eslint): move formatting rules to own config file for now this will allow us to run linting and formatting separately for now, where we have a ton of linting errors still --- eslint.config.js | 19 +------------------ eslint.format.config.js | 42 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 18 deletions(-) create mode 100644 eslint.format.config.js diff --git a/eslint.config.js b/eslint.config.js index 5abb68103..35cbd959d 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,21 +1,5 @@ import eslint from "@eslint/js"; import tseslint from "typescript-eslint"; -import stylistic from "@stylistic/eslint-plugin"; - - -// Go to https://eslint.style/rules/default/${rule_without_prefix} to check the rule details -const stylisticRules = { - "@stylistic/indent": [ "error", 4 ], - "@stylistic/quotes": [ "error", "double", { avoidEscape: true, allowTemplateLiterals: "always" } ], - "@stylistic/semi": [ "error", "always" ], - "@stylistic/quote-props": [ "error", "consistent-as-needed" ], - "@stylistic/max-len": [ "error", { code: 200 } ], - "@stylistic/comma-dangle": [ "error", "never" ], - "@stylistic/linebreak-style": [ "error", "unix" ], - "@stylistic/array-bracket-spacing": [ "error", "always" ], - "@stylistic/object-curly-spacing": [ "error", "always" ], - "@stylistic/padded-blocks": [ "error", { classes: "always" } ] -}; export default tseslint.config( eslint.configs.recommended, @@ -46,8 +30,7 @@ export default tseslint.config( argsIgnorePattern: "^_", varsIgnorePattern: "^_" } - ], - ...stylisticRules + ] } }, { diff --git a/eslint.format.config.js b/eslint.format.config.js new file mode 100644 index 000000000..ec6b8f3ff --- /dev/null +++ b/eslint.format.config.js @@ -0,0 +1,42 @@ +import stylistic from "@stylistic/eslint-plugin"; + +// eslint config just for formatting rules +// potentially to be merged with the linting rules into one single config, +// once we have fixed the majority of lint errors + +// Go to https://eslint.style/rules/default/${rule_without_prefix} to check the rule details +export const stylisticRules = { + "@stylistic/indent": [ "error", 4 ], + "@stylistic/quotes": [ "error", "double", { avoidEscape: true, allowTemplateLiterals: "always" } ], + "@stylistic/semi": [ "error", "always" ], + "@stylistic/quote-props": [ "error", "consistent-as-needed" ], + "@stylistic/max-len": [ "error", { code: 200 } ], + "@stylistic/comma-dangle": [ "error", "never" ], + "@stylistic/linebreak-style": [ "error", "unix" ], + "@stylistic/array-bracket-spacing": [ "error", "always" ], + "@stylistic/object-curly-spacing": [ "error", "always" ], + "@stylistic/padded-blocks": [ "error", { classes: "always" } ] +}; + +export default [ + { + plugins: { + "@stylistic": stylistic + }, + rules: { + ...stylisticRules + } + }, + { + ignores: [ + "build/*", + "dist/*", + "docs/*", + "libraries/*", + // TriliumNextTODO: check if we want to format packages here as well - for now skipping it + "packages/*", + "src/public/app-dist/*", + "src/public/app/doc_notes/*" + ] + } +]; From d432a56211e1b8c73ee7afe58997943d4a3e06be Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Wed, 2 Apr 2025 08:37:57 +0200 Subject: [PATCH 10/33] chore(scripts): update dev:format scripts to eslint --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fdb888156..d4a2c2e08 100644 --- a/package.json +++ b/package.json @@ -59,8 +59,8 @@ "test:integration-mem-db": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts", "test:integration-mem-db-dev": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts", "dev:watch-dist": "tsx ./bin/watch-dist.ts", - "dev:format-check": "dprint check", - "dev:format-fix": "dprint fmt", + "dev:format-check": "eslint -c eslint.format.config.js .", + "dev:format-fix": "eslint -c eslint.format.config.js . --fix", "dev:linter-check": "eslint .", "dev:linter-fix": "eslint . --fix", "chore:update-build-info": "tsx bin/update-build-info.ts", From 42edb0c0bdfe9372137c5a73dfce2e3e9d248f6d Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Wed, 2 Apr 2025 08:42:14 +0200 Subject: [PATCH 11/33] chore(eslint): ignore "demo" folder for now --- eslint.config.js | 1 + eslint.format.config.js | 1 + 2 files changed, 2 insertions(+) diff --git a/eslint.config.js b/eslint.config.js index 35cbd959d..648af36bd 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -38,6 +38,7 @@ export default tseslint.config( "build/*", "dist/*", "docs/*", + "demo/*", "libraries/*", "src/public/app-dist/*", "src/public/app/doc_notes/*" diff --git a/eslint.format.config.js b/eslint.format.config.js index ec6b8f3ff..dce319416 100644 --- a/eslint.format.config.js +++ b/eslint.format.config.js @@ -32,6 +32,7 @@ export default [ "build/*", "dist/*", "docs/*", + "demo/*", "libraries/*", // TriliumNextTODO: check if we want to format packages here as well - for now skipping it "packages/*", From e98516df8a886b05359050f62510404ec49acacf Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Wed, 2 Apr 2025 08:54:10 +0200 Subject: [PATCH 12/33] chore(eslint): remove leftover plugin --- eslint.config.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 648af36bd..88656cf8a 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -17,9 +17,6 @@ export default tseslint.config( } }, { - plugins: { - "@stylistic": stylistic - }, rules: { // add rule overrides here "no-undef": "off", From 7812c0574c1fd5224fd04a5a63e39deded6b8a2e Mon Sep 17 00:00:00 2001 From: Panagiotis Papadopoulos Date: Wed, 2 Apr 2025 08:58:52 +0200 Subject: [PATCH 13/33] chore(eslint): correctly pickup ts files as well --- eslint.format.config.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/eslint.format.config.js b/eslint.format.config.js index dce319416..d5bfce331 100644 --- a/eslint.format.config.js +++ b/eslint.format.config.js @@ -1,4 +1,5 @@ import stylistic from "@stylistic/eslint-plugin"; +import tsParser from "@typescript-eslint/parser"; // eslint config just for formatting rules // potentially to be merged with the linting rules into one single config, @@ -20,6 +21,10 @@ export const stylisticRules = { export default [ { + files: [ "**/*.{js,ts,mjs,cjs}" ], + languageOptions: { + parser: tsParser + }, plugins: { "@stylistic": stylistic }, From db66d86bc2df387fb3148b4f863b67694df29245 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 2 Apr 2025 16:39:16 +0300 Subject: [PATCH 14/33] fix(in-app-help): help not rendering in other languages (fixes #1600) --- e2e/help.spec.ts | 37 +++++++++++++++++++++++++ e2e/support/app.ts | 6 ++++ src/public/app/services/doc_renderer.ts | 6 ++-- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/e2e/help.spec.ts b/e2e/help.spec.ts index 4402ffa30..6416afb6f 100644 --- a/e2e/help.spec.ts +++ b/e2e/help.spec.ts @@ -25,3 +25,40 @@ test("Complete help in search", async ({ page, context }) => { const popup = await popupPromise; expect(popup.url()).toBe("https://triliumnext.github.io/Docs/Wiki/search.html"); }); + +test("In-app-help works in English", async ({ page, context }) => { + const app = new App(page, context); + await app.goto(); + + await app.currentNoteSplit.press("F1"); + const title = "User Guide"; + await expect(app.noteTreeHoistedNote).toContainText(title); + await expect(app.currentNoteSplitTitle).toHaveValue(title); + + app.noteTree.getByText("Troubleshooting").click(); + await expect(app.currentNoteSplitTitle).toHaveValue("Troubleshooting"); + await app.currentNoteSplitContent.locator("p").first().waitFor({ state: "visible" }); + expect(await app.currentNoteSplitContent.locator("p").count()).toBeGreaterThan(10); +}); + +test("In-app-help works in other languages", async ({ page, context }) => { + const app = new App(page, context); + try { + await app.goto(); + await app.setOption("locale", "cn"); + await app.goto(); + + await app.currentNoteSplit.press("F1"); + const title = "用户指南"; + await expect(app.noteTreeHoistedNote).toContainText(title); + await expect(app.currentNoteSplitTitle).toHaveValue(title); + + app.noteTree.getByText("Troubleshooting").click(); + await expect(app.currentNoteSplitTitle).toHaveValue("Troubleshooting"); + await app.currentNoteSplitContent.locator("p").first().waitFor({ state: "visible" }); + expect(await app.currentNoteSplitContent.locator("p").count()).toBeGreaterThan(10); + } finally { + // Ensure English is set after each locale change to avoid any leaks to other tests. + await app.setOption("locale", "en"); + } +}); diff --git a/e2e/support/app.ts b/e2e/support/app.ts index b526638d9..d6b3d231a 100644 --- a/e2e/support/app.ts +++ b/e2e/support/app.ts @@ -14,8 +14,11 @@ export default class App { readonly tabBar: Locator; readonly noteTree: Locator; + readonly noteTreeHoistedNote: Locator; readonly launcherBar: Locator; readonly currentNoteSplit: Locator; + readonly currentNoteSplitTitle: Locator; + readonly currentNoteSplitContent: Locator; readonly sidebar: Locator; constructor(page: Page, context: BrowserContext) { @@ -24,8 +27,11 @@ export default class App { this.tabBar = page.locator(".tab-row-widget-container"); this.noteTree = page.locator(".tree-wrapper"); + this.noteTreeHoistedNote = this.noteTree.locator(".fancytree-node", { has: page.locator(".unhoist-button") }); this.launcherBar = page.locator("#launcher-container"); this.currentNoteSplit = page.locator(".note-split:not(.hidden-ext)"); + this.currentNoteSplitTitle = this.currentNoteSplit.locator(".note-title"); + this.currentNoteSplitContent = this.currentNoteSplit.locator(".note-detail-printable.visible"); this.sidebar = page.locator("#right-pane"); } diff --git a/src/public/app/services/doc_renderer.ts b/src/public/app/services/doc_renderer.ts index ac1560d4c..290adbb72 100644 --- a/src/public/app/services/doc_renderer.ts +++ b/src/public/app/services/doc_renderer.ts @@ -14,8 +14,10 @@ export default function renderDoc(note: FNote) { // fallback to english doc if no translation available if (status === "error") { const fallbackUrl = getUrl(docName, "en"); - $content.load(fallbackUrl, () => processContent(fallbackUrl, $content)); - resolve($content); + $content.load(fallbackUrl, () => { + processContent(fallbackUrl, $content) + resolve($content); + }); return; } From 69b2824f9ce337b255521408b429cdfa662a94f1 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 2 Apr 2025 20:08:18 +0300 Subject: [PATCH 15/33] fix(client): note context not correctly define (closes #1193) --- e2e/layout/tab_bar.spec.ts | 25 +++++++++++++++++++ e2e/support/app.ts | 9 +++++-- .../app/widgets/note_context_aware_widget.ts | 1 - 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/e2e/layout/tab_bar.spec.ts b/e2e/layout/tab_bar.spec.ts index e6df6f328..ccaff3876 100644 --- a/e2e/layout/tab_bar.spec.ts +++ b/e2e/layout/tab_bar.spec.ts @@ -57,3 +57,28 @@ test("Can drag tab to new window", async ({ page, context }) => { const popupApp = new App(popup, context); await expect(popupApp.getActiveTab()).toHaveText(NOTE_TITLE); }); + +test("Tabs are restored in right order", async ({ page, context }) => { + const app = new App(page, context); + await app.goto(); + + // Open three tabs. + await app.closeAllTabs(); + await app.goToNoteInNewTab("Code notes"); + await app.addNewTab(); + await app.goToNoteInNewTab("Text notes"); + await app.addNewTab(); + await app.goToNoteInNewTab("Mermaid"); + + // Select the mid one. + await app.getTab(1).click(); + + // Refresh the page and check the order. + await app.goto( { preserveTabs: true }); + await expect(app.getTab(0)).toContainText("Code notes"); + await expect(app.getTab(1)).toContainText("Text notes"); + await expect(app.getTab(2)).toContainText("Mermaid"); + + // Check the note tree has the right active node. + await expect(app.noteTreeActiveNote).toContainText("Text notes"); +}); diff --git a/e2e/support/app.ts b/e2e/support/app.ts index d6b3d231a..8ae430f1b 100644 --- a/e2e/support/app.ts +++ b/e2e/support/app.ts @@ -4,6 +4,7 @@ import type { BrowserContext } from "@playwright/test"; interface GotoOpts { url?: string; isMobile?: boolean; + preserveTabs?: boolean; } const BASE_URL = "http://127.0.0.1:8082"; @@ -14,6 +15,7 @@ export default class App { readonly tabBar: Locator; readonly noteTree: Locator; + readonly noteTreeActiveNote: Locator; readonly noteTreeHoistedNote: Locator; readonly launcherBar: Locator; readonly currentNoteSplit: Locator; @@ -27,6 +29,7 @@ export default class App { this.tabBar = page.locator(".tab-row-widget-container"); this.noteTree = page.locator(".tree-wrapper"); + this.noteTreeActiveNote = this.noteTree.locator(".fancytree-node.fancytree-active"); this.noteTreeHoistedNote = this.noteTree.locator(".fancytree-node", { has: page.locator(".unhoist-button") }); this.launcherBar = page.locator("#launcher-container"); this.currentNoteSplit = page.locator(".note-split:not(.hidden-ext)"); @@ -35,7 +38,7 @@ export default class App { this.sidebar = page.locator("#right-pane"); } - async goto({ url, isMobile }: GotoOpts = {}) { + async goto({ url, isMobile, preserveTabs }: GotoOpts = {}) { await this.context.addCookies([ { url: BASE_URL, @@ -53,7 +56,9 @@ export default class App { // Wait for the page to load. if (url === "/") { await expect(this.page.locator(".tree")).toContainText("Trilium Integration Test"); - await this.closeAllTabs(); + if (!preserveTabs) { + await this.closeAllTabs(); + } } } diff --git a/src/public/app/widgets/note_context_aware_widget.ts b/src/public/app/widgets/note_context_aware_widget.ts index cadd77c49..df04b35b2 100644 --- a/src/public/app/widgets/note_context_aware_widget.ts +++ b/src/public/app/widgets/note_context_aware_widget.ts @@ -82,7 +82,6 @@ class NoteContextAwareWidget extends BasicWidget { async refreshWithNote(note: FNote | null | undefined) {} async noteSwitchedEvent({ noteContext, notePath }: EventData<"noteSwitched">) { - this.noteContext = noteContext; // if notePath does not match, then the noteContext has been switched to another note in the meantime if (noteContext.notePath === notePath) { await this.noteSwitched(); From 86433e4c5140fb10ec9a0c72053bc5bb17f26da2 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 2 Apr 2025 20:22:10 +0300 Subject: [PATCH 16/33] feat(launch_bar): improve look on small windows --- src/public/app/widgets/buttons/global_menu.ts | 1 + src/public/stylesheets/style.css | 1 + 2 files changed, 2 insertions(+) diff --git a/src/public/app/widgets/buttons/global_menu.ts b/src/public/app/widgets/buttons/global_menu.ts index 657813773..d21e43b0d 100644 --- a/src/public/app/widgets/buttons/global_menu.ts +++ b/src/public/app/widgets/buttons/global_menu.ts @@ -11,6 +11,7 @@ const TPL = /*html*/` .global-menu { width: 53px; height: 53px; + flex-shrink: 0; } .global-menu .dropdown-menu { diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css index d3f914173..e04801943 100644 --- a/src/public/stylesheets/style.css +++ b/src/public/stylesheets/style.css @@ -1288,6 +1288,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { border: none; color: var(--launcher-pane-text-color); background-color: var(--launcher-pane-background-color); + flex-shrink: 0; } #launcher-pane.vertical .launcher-button { From d8a18529359114ccb55dddba28398ae51697f81e Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 2 Apr 2025 20:36:24 +0300 Subject: [PATCH 17/33] feat(launch_bar): make scrollable when icons don't fit --- .../app/widgets/containers/launcher_container.ts | 14 +++++++++++++- src/public/stylesheets/style.css | 5 +++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/public/app/widgets/containers/launcher_container.ts b/src/public/app/widgets/containers/launcher_container.ts index 7fa833182..87d25250e 100644 --- a/src/public/app/widgets/containers/launcher_container.ts +++ b/src/public/app/widgets/containers/launcher_container.ts @@ -11,7 +11,19 @@ export default class LauncherContainer extends FlexContainer { super(isHorizontalLayout ? "row" : "column"); this.id("launcher-container"); - this.css(isHorizontalLayout ? "width" : "height", "100%"); + + if (isHorizontalLayout) { + this.css("width", "100%"); + this.css("height", "100%"); + this.css("overflow-x", "auto"); + this.css("overflow-y", "hidden"); + } else { + this.css("height", "100%"); + this.css("overflow-x", "hidden"); + this.css("overflow-y", "auto"); + } + + this.css("scrollbar-gutter", "stable both-edges"); this.filling(); this.isHorizontalLayout = isHorizontalLayout; diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css index e04801943..c20edef76 100644 --- a/src/public/stylesheets/style.css +++ b/src/public/stylesheets/style.css @@ -1177,6 +1177,10 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { left: calc(-100% + 10px); } +.right-dropdown-widget { + flex-shrink: 0; +} + #launcher-pane.horizontal .right-dropdown-widget { width: 53px; } @@ -1303,6 +1307,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { #launcher-pane.horizontal .quick-search { width: 350px; + min-width: 150px; } #launcher-pane .icon-action:hover { From 3e5bd01fc17e2abfb1157b99016e39b7bc8c822a Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 2 Apr 2025 20:44:39 +0300 Subject: [PATCH 18/33] feat(electron): set window minimum size (closes #994) --- src/services/window.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/services/window.ts b/src/services/window.ts index a575d27d6..70c178612 100644 --- a/src/services/window.ts +++ b/src/services/window.ts @@ -156,6 +156,8 @@ async function createMainWindow(app: App) { y: mainWindowState.y, width: mainWindowState.width, height: mainWindowState.height, + minWidth: 500, + minHeight: 400, title: "TriliumNext Notes", webPreferences: { nodeIntegration: true, @@ -185,7 +187,7 @@ async function createMainWindow(app: App) { if (lastFocusedWindow.isMinimized()) { lastFocusedWindow.restore(); } - lastFocusedWindow.show(); + lastFocusedWindow.show(); lastFocusedWindow.focus(); } }); From f420b5cbd4208c59b44d071df1745edb914b521f Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 2 Apr 2025 20:47:53 +0300 Subject: [PATCH 19/33] feat(electron): constrain setup window size --- src/services/window.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/services/window.ts b/src/services/window.ts index 70c178612..f5c7857a1 100644 --- a/src/services/window.ts +++ b/src/services/window.ts @@ -257,9 +257,12 @@ function getIcon() { async function createSetupWindow() { const { BrowserWindow } = await import("electron"); // should not be statically imported + const width = 750; + const height = 650; setupWindow = new BrowserWindow({ - width: 800, - height: 800, + width, + height, + resizable: false, title: "TriliumNext Notes Setup", icon: getIcon(), webPreferences: { From c4750942845deb02526cb2f5fd6155c18f275cb1 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 2 Apr 2025 20:51:53 +0300 Subject: [PATCH 20/33] feat(a11y): suggest new password in set password --- src/views/set_password.ejs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/set_password.ejs b/src/views/set_password.ejs index 5b8d29707..c58cc798f 100644 --- a/src/views/set_password.ejs +++ b/src/views/set_password.ejs @@ -29,13 +29,13 @@
- +
- +
From af835dfe26f3ff9a443eb85fb7761707039a8fe7 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 2 Apr 2025 20:59:01 +0300 Subject: [PATCH 21/33] style(set_password): add some margins --- src/public/app/set_password.ts | 1 + src/public/stylesheets/auth.css | 3 +++ src/views/set_password.ejs | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 src/public/stylesheets/auth.css diff --git a/src/public/app/set_password.ts b/src/public/app/set_password.ts index ebf6b68a4..95e6cc2da 100644 --- a/src/public/app/set_password.ts +++ b/src/public/app/set_password.ts @@ -1,4 +1,5 @@ import "../stylesheets/bootstrap.scss"; +import "../stylesheets/auth.css"; // @TriliumNextTODO: is this even needed anymore? // @ts-ignore - module = undefined diff --git a/src/public/stylesheets/auth.css b/src/public/stylesheets/auth.css new file mode 100644 index 000000000..623516439 --- /dev/null +++ b/src/public/stylesheets/auth.css @@ -0,0 +1,3 @@ +.set-password .form-group { + margin-bottom: 1rem; +} \ No newline at end of file diff --git a/src/views/set_password.ejs b/src/views/set_password.ejs index c58cc798f..4f2992320 100644 --- a/src/views/set_password.ejs +++ b/src/views/set_password.ejs @@ -13,7 +13,7 @@ -
+

<%= t("set_password.heading") %>

From 8ec97602c883abea735b58adb30dc62d365681aa Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 2 Apr 2025 21:02:24 +0300 Subject: [PATCH 22/33] feat(a11y): set autocomplete for login --- src/views/login.ejs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/login.ejs b/src/views/login.ejs index 56c2bf762..d013b1b15 100644 --- a/src/views/login.ejs +++ b/src/views/login.ejs @@ -34,14 +34,14 @@
- +
<% if( totpEnabled ) { %>
- +
<% } %> From 0c5cd66eaeb35b4a64662a7002d1f794f4ba474c Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Wed, 2 Apr 2025 21:04:22 +0300 Subject: [PATCH 23/33] feat(a11y): set autocomplete for protected session --- src/public/app/widgets/dialogs/protected_session_password.ts | 2 +- src/public/app/widgets/type_widgets/protected_session.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/public/app/widgets/dialogs/protected_session_password.ts b/src/public/app/widgets/dialogs/protected_session_password.ts index b044a9b7f..d839aac3b 100644 --- a/src/public/app/widgets/dialogs/protected_session_password.ts +++ b/src/public/app/widgets/dialogs/protected_session_password.ts @@ -16,7 +16,7 @@ const TPL = /*html*/`