Merge pull request #1168 from TriliumNext/chore_bootstrap-ts-ignore

build: bundle bootstrap with webpack
This commit is contained in:
Elian Doran 2025-02-22 14:57:47 +02:00 committed by GitHub
commit f6224d9ec4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 991 additions and 132 deletions

View File

@ -95,7 +95,6 @@ const copy = async () => {
"node_modules/mark.js/dist/", "node_modules/mark.js/dist/",
"node_modules/normalize.css/", "node_modules/normalize.css/",
"node_modules/jquery.fancytree/dist/", "node_modules/jquery.fancytree/dist/",
"node_modules/bootstrap/dist/",
"node_modules/autocomplete.js/dist/", "node_modules/autocomplete.js/dist/",
"node_modules/codemirror/lib/", "node_modules/codemirror/lib/",
"node_modules/codemirror/addon/", "node_modules/codemirror/addon/",

801
package-lock.json generated
View File

@ -29,7 +29,6 @@
"autocomplete.js": "0.38.1", "autocomplete.js": "0.38.1",
"axios": "1.7.9", "axios": "1.7.9",
"better-sqlite3": "11.8.1", "better-sqlite3": "11.8.1",
"bootstrap": "5.3.3",
"boxicons": "2.1.4", "boxicons": "2.1.4",
"chardet": "2.0.0", "chardet": "2.0.0",
"cheerio": "1.0.0", "cheerio": "1.0.0",
@ -124,6 +123,7 @@
"@electron-forge/plugin-auto-unpack-natives": "7.7.0", "@electron-forge/plugin-auto-unpack-natives": "7.7.0",
"@electron/rebuild": "3.7.1", "@electron/rebuild": "3.7.1",
"@playwright/test": "1.50.1", "@playwright/test": "1.50.1",
"@popperjs/core": "2.11.8",
"@types/archiver": "6.0.3", "@types/archiver": "6.0.3",
"@types/better-sqlite3": "7.6.12", "@types/better-sqlite3": "7.6.12",
"@types/bootstrap": "5.2.10", "@types/bootstrap": "5.2.10",
@ -160,15 +160,22 @@
"@types/xml2js": "0.4.14", "@types/xml2js": "0.4.14",
"@types/yargs": "17.0.33", "@types/yargs": "17.0.33",
"@vitest/coverage-v8": "3.0.6", "@vitest/coverage-v8": "3.0.6",
"autoprefixer": "10.4.20",
"bootstrap": "5.3.3",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"css-loader": "7.1.2",
"electron": "34.2.0", "electron": "34.2.0",
"esm": "3.2.25", "esm": "3.2.25",
"jsdoc": "4.0.4", "jsdoc": "4.0.4",
"lorem-ipsum": "2.0.8", "lorem-ipsum": "2.0.8",
"mini-css-extract-plugin": "2.9.2",
"nodemon": "3.1.9", "nodemon": "3.1.9",
"postcss-loader": "8.1.1",
"prettier": "3.5.1", "prettier": "3.5.1",
"rcedit": "4.0.1", "rcedit": "4.0.1",
"rimraf": "6.0.1", "rimraf": "6.0.1",
"sass": "1.85.0",
"sass-loader": "16.0.5",
"swagger-jsdoc": "6.2.8", "swagger-jsdoc": "6.2.8",
"tslib": "2.8.1", "tslib": "2.8.1",
"tsx": "4.19.3", "tsx": "4.19.3",
@ -297,6 +304,21 @@
"node": "20 || >=22" "node": "20 || >=22"
} }
}, },
"node_modules/@babel/code-frame": {
"version": "7.26.2",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
"integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-validator-identifier": "^7.25.9",
"js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": { "node_modules/@babel/helper-string-parser": {
"version": "7.25.9", "version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
@ -3235,6 +3257,330 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/@parcel/watcher": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
"integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"dependencies": {
"detect-libc": "^1.0.3",
"is-glob": "^4.0.3",
"micromatch": "^4.0.5",
"node-addon-api": "^7.0.0"
},
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
},
"optionalDependencies": {
"@parcel/watcher-android-arm64": "2.5.1",
"@parcel/watcher-darwin-arm64": "2.5.1",
"@parcel/watcher-darwin-x64": "2.5.1",
"@parcel/watcher-freebsd-x64": "2.5.1",
"@parcel/watcher-linux-arm-glibc": "2.5.1",
"@parcel/watcher-linux-arm-musl": "2.5.1",
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
"@parcel/watcher-linux-arm64-musl": "2.5.1",
"@parcel/watcher-linux-x64-glibc": "2.5.1",
"@parcel/watcher-linux-x64-musl": "2.5.1",
"@parcel/watcher-win32-arm64": "2.5.1",
"@parcel/watcher-win32-ia32": "2.5.1",
"@parcel/watcher-win32-x64": "2.5.1"
}
},
"node_modules/@parcel/watcher-android-arm64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
"integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-darwin-arm64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
"integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-darwin-x64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
"integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-freebsd-x64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
"integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm-glibc": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
"integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm-musl": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
"integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm64-glibc": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
"integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm64-musl": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
"integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-x64-glibc": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
"integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-x64-musl": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
"integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-win32-arm64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
"integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-win32-ia32": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
"integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-win32-x64": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
"integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher/node_modules/detect-libc": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
"integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
"dev": true,
"license": "Apache-2.0",
"optional": true,
"bin": {
"detect-libc": "bin/detect-libc.js"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/@pkgjs/parseargs": { "node_modules/@pkgjs/parseargs": {
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@ -3265,6 +3611,7 @@
"version": "2.11.8", "version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"dev": true,
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
@ -5385,6 +5732,44 @@
"immediate": "^3.2.3" "immediate": "^3.2.3"
} }
}, },
"node_modules/autoprefixer": {
"version": "10.4.20",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
"integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/autoprefixer"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"browserslist": "^4.23.3",
"caniuse-lite": "^1.0.30001646",
"fraction.js": "^4.3.7",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.1",
"postcss-value-parser": "^4.2.0"
},
"bin": {
"autoprefixer": "bin/autoprefixer"
},
"engines": {
"node": "^10 || ^12 || >=14"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/await-to-js": { "node_modules/await-to-js": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz", "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz",
@ -5648,6 +6033,7 @@
"version": "5.3.3", "version": "5.3.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz",
"integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@ -6100,6 +6486,16 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001689", "version": "1.0.30001689",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001689.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001689.tgz",
@ -6785,6 +7181,52 @@
"layout-base": "^1.0.0" "layout-base": "^1.0.0"
} }
}, },
"node_modules/cosmiconfig": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
"integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
"dev": true,
"license": "MIT",
"dependencies": {
"env-paths": "^2.2.1",
"import-fresh": "^3.3.0",
"js-yaml": "^4.1.0",
"parse-json": "^5.2.0"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/d-fischer"
},
"peerDependencies": {
"typescript": ">=4.9.5"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/cosmiconfig/node_modules/parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.0.0",
"error-ex": "^1.3.1",
"json-parse-even-better-errors": "^2.3.0",
"lines-and-columns": "^1.1.6"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/crc-32": { "node_modules/crc-32": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
@ -6965,6 +7407,42 @@
"node": ">=0.6" "node": ">=0.6"
} }
}, },
"node_modules/css-loader": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz",
"integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==",
"dev": true,
"license": "MIT",
"dependencies": {
"icss-utils": "^5.1.0",
"postcss": "^8.4.33",
"postcss-modules-extract-imports": "^3.1.0",
"postcss-modules-local-by-default": "^4.0.5",
"postcss-modules-scope": "^3.2.0",
"postcss-modules-values": "^4.0.0",
"postcss-value-parser": "^4.2.0",
"semver": "^7.5.4"
},
"engines": {
"node": ">= 18.12.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"@rspack/core": "0.x || 1.x",
"webpack": "^5.27.0"
},
"peerDependenciesMeta": {
"@rspack/core": {
"optional": true
},
"webpack": {
"optional": true
}
}
},
"node_modules/css-select": { "node_modules/css-select": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
@ -6993,6 +7471,19 @@
"url": "https://github.com/sponsors/fb55" "url": "https://github.com/sponsors/fb55"
} }
}, },
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true,
"license": "MIT",
"bin": {
"cssesc": "bin/cssesc"
},
"engines": {
"node": ">=4"
}
},
"node_modules/cssstyle": { "node_modules/cssstyle": {
"version": "4.2.1", "version": "4.2.1",
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.2.1.tgz", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.2.1.tgz",
@ -9907,6 +10398,20 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/fraction.js": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
"integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
"dev": true,
"license": "MIT",
"engines": {
"node": "*"
},
"funding": {
"type": "patreon",
"url": "https://github.com/sponsors/rawify"
}
},
"node_modules/fresh": { "node_modules/fresh": {
"version": "0.5.2", "version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@ -10774,6 +11279,19 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/icss-utils": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
"dev": true,
"license": "ISC",
"engines": {
"node": "^10 || ^12 || >= 14"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/ieee754": { "node_modules/ieee754": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@ -10851,6 +11369,30 @@
"integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/immutable": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz",
"integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==",
"dev": true,
"license": "MIT"
},
"node_modules/import-fresh": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/import-local": { "node_modules/import-local": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
@ -11438,6 +11980,16 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/jiti": {
"version": "1.21.7",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"dev": true,
"license": "MIT",
"bin": {
"jiti": "bin/jiti.js"
}
},
"node_modules/jpeg-js": { "node_modules/jpeg-js": {
"version": "0.4.4", "version": "0.4.4",
"resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz",
@ -11854,6 +12406,13 @@
"resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz",
"integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA=="
}, },
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true,
"license": "MIT"
},
"node_modules/linkify-it": { "node_modules/linkify-it": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
@ -12503,6 +13062,27 @@
"integrity": "sha512-Ja8zcKAwjYG180ZGB8WKygmbqs4RFEQZ0JTE1T49/6nCHWXVcA0WNW8Syl0sMbMyYZvQ5kOZWzLylgCvplqhRw==", "integrity": "sha512-Ja8zcKAwjYG180ZGB8WKygmbqs4RFEQZ0JTE1T49/6nCHWXVcA0WNW8Syl0sMbMyYZvQ5kOZWzLylgCvplqhRw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/mini-css-extract-plugin": {
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz",
"integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==",
"dev": true,
"license": "MIT",
"dependencies": {
"schema-utils": "^4.0.0",
"tapable": "^2.2.1"
},
"engines": {
"node": ">= 12.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"webpack": "^5.0.0"
}
},
"node_modules/minimalistic-assert": { "node_modules/minimalistic-assert": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
@ -12766,6 +13346,14 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/node-addon-api": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
"dev": true,
"license": "MIT",
"optional": true
},
"node_modules/node-api-version": { "node_modules/node-api-version": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.0.tgz", "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.0.tgz",
@ -12975,6 +13563,16 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/normalize-range": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
"integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/normalize-strings": { "node_modules/normalize-strings": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/normalize-strings/-/normalize-strings-1.1.1.tgz", "resolved": "https://registry.npmjs.org/normalize-strings/-/normalize-strings-1.1.1.tgz",
@ -13331,6 +13929,19 @@
"wheel": "^1.0.0" "wheel": "^1.0.0"
} }
}, },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
"license": "MIT",
"dependencies": {
"callsites": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/parse-author": { "node_modules/parse-author": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz", "resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz",
@ -13848,6 +14459,122 @@
"node": "^10 || ^12 || >=14" "node": "^10 || ^12 || >=14"
} }
}, },
"node_modules/postcss-loader": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz",
"integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"cosmiconfig": "^9.0.0",
"jiti": "^1.20.0",
"semver": "^7.5.4"
},
"engines": {
"node": ">= 18.12.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"@rspack/core": "0.x || 1.x",
"postcss": "^7.0.0 || ^8.0.1",
"webpack": "^5.0.0"
},
"peerDependenciesMeta": {
"@rspack/core": {
"optional": true
},
"webpack": {
"optional": true
}
}
},
"node_modules/postcss-modules-extract-imports": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz",
"integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==",
"dev": true,
"license": "ISC",
"engines": {
"node": "^10 || ^12 || >= 14"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/postcss-modules-local-by-default": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz",
"integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==",
"dev": true,
"license": "MIT",
"dependencies": {
"icss-utils": "^5.0.0",
"postcss-selector-parser": "^7.0.0",
"postcss-value-parser": "^4.1.0"
},
"engines": {
"node": "^10 || ^12 || >= 14"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/postcss-modules-scope": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz",
"integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==",
"dev": true,
"license": "ISC",
"dependencies": {
"postcss-selector-parser": "^7.0.0"
},
"engines": {
"node": "^10 || ^12 || >= 14"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/postcss-modules-values": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
"integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
"dev": true,
"license": "ISC",
"dependencies": {
"icss-utils": "^5.0.0"
},
"engines": {
"node": "^10 || ^12 || >= 14"
},
"peerDependencies": {
"postcss": "^8.1.0"
}
},
"node_modules/postcss-selector-parser": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz",
"integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
"dev": true,
"license": "MIT",
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
},
"engines": {
"node": ">=4"
}
},
"node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true,
"license": "MIT"
},
"node_modules/postject": { "node_modules/postject": {
"version": "1.0.0-alpha.6", "version": "1.0.0-alpha.6",
"resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz", "resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz",
@ -14706,6 +15433,16 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/resolve-pathname": { "node_modules/resolve-pathname": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
@ -15070,6 +15807,68 @@
"postcss": "^8.3.11" "postcss": "^8.3.11"
} }
}, },
"node_modules/sass": {
"version": "1.85.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.85.0.tgz",
"integrity": "sha512-3ToiC1xZ1Y8aU7+CkgCI/tqyuPXEmYGJXO7H4uqp0xkLXUqp88rQQ4j1HmP37xSJLbCJPaIiv+cT1y+grssrww==",
"dev": true,
"license": "MIT",
"dependencies": {
"chokidar": "^4.0.0",
"immutable": "^5.0.2",
"source-map-js": ">=0.6.2 <2.0.0"
},
"bin": {
"sass": "sass.js"
},
"engines": {
"node": ">=14.0.0"
},
"optionalDependencies": {
"@parcel/watcher": "^2.4.1"
}
},
"node_modules/sass-loader": {
"version": "16.0.5",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.5.tgz",
"integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==",
"dev": true,
"license": "MIT",
"dependencies": {
"neo-async": "^2.6.2"
},
"engines": {
"node": ">= 18.12.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"@rspack/core": "0.x || 1.x",
"node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
"sass": "^1.3.0",
"sass-embedded": "*",
"webpack": "^5.0.0"
},
"peerDependenciesMeta": {
"@rspack/core": {
"optional": true
},
"node-sass": {
"optional": true
},
"sass": {
"optional": true
},
"sass-embedded": {
"optional": true
},
"webpack": {
"optional": true
}
}
},
"node_modules/sax": { "node_modules/sax": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",

View File

@ -79,7 +79,6 @@
"autocomplete.js": "0.38.1", "autocomplete.js": "0.38.1",
"axios": "1.7.9", "axios": "1.7.9",
"better-sqlite3": "11.8.1", "better-sqlite3": "11.8.1",
"bootstrap": "5.3.3",
"boxicons": "2.1.4", "boxicons": "2.1.4",
"chardet": "2.0.0", "chardet": "2.0.0",
"cheerio": "1.0.0", "cheerio": "1.0.0",
@ -171,6 +170,7 @@
"@electron-forge/plugin-auto-unpack-natives": "7.7.0", "@electron-forge/plugin-auto-unpack-natives": "7.7.0",
"@electron/rebuild": "3.7.1", "@electron/rebuild": "3.7.1",
"@playwright/test": "1.50.1", "@playwright/test": "1.50.1",
"@popperjs/core": "2.11.8",
"@types/archiver": "6.0.3", "@types/archiver": "6.0.3",
"@types/better-sqlite3": "7.6.12", "@types/better-sqlite3": "7.6.12",
"@types/bootstrap": "5.2.10", "@types/bootstrap": "5.2.10",
@ -207,15 +207,22 @@
"@types/xml2js": "0.4.14", "@types/xml2js": "0.4.14",
"@types/yargs": "17.0.33", "@types/yargs": "17.0.33",
"@vitest/coverage-v8": "3.0.6", "@vitest/coverage-v8": "3.0.6",
"autoprefixer": "10.4.20",
"bootstrap": "5.3.3",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"css-loader": "7.1.2",
"electron": "34.2.0", "electron": "34.2.0",
"esm": "3.2.25", "esm": "3.2.25",
"jsdoc": "4.0.4", "jsdoc": "4.0.4",
"lorem-ipsum": "2.0.8", "lorem-ipsum": "2.0.8",
"mini-css-extract-plugin": "2.9.2",
"nodemon": "3.1.9", "nodemon": "3.1.9",
"postcss-loader": "8.1.1",
"prettier": "3.5.1", "prettier": "3.5.1",
"rcedit": "4.0.1", "rcedit": "4.0.1",
"rimraf": "6.0.1", "rimraf": "6.0.1",
"sass": "1.85.0",
"sass-loader": "16.0.5",
"swagger-jsdoc": "6.2.8", "swagger-jsdoc": "6.2.8",
"tslib": "2.8.1", "tslib": "2.8.1",
"tsx": "4.19.3", "tsx": "4.19.3",

View File

@ -10,6 +10,7 @@ import { t } from "./services/i18n.js";
import options from "./services/options.js"; import options from "./services/options.js";
import type ElectronRemote from "@electron/remote"; import type ElectronRemote from "@electron/remote";
import type Electron from "electron"; import type Electron from "electron";
import "../stylesheets/bootstrap.scss";
await appContext.earlyInit(); await appContext.earlyInit();

32
src/public/app/login.ts Normal file
View File

@ -0,0 +1,32 @@
import "../stylesheets/bootstrap.scss";
// @ts-ignore - module = undefined
// Required for correct loading of scripts in Electron
if (typeof module === 'object') {window.module = module; module = undefined;}
const device = getDeviceType()
console.log("Setting device cookie to:", device);
setCookie("trilium-device", device);
function setCookie(name: string, value?: string) {
const date = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1000);
const expires = "; expires=" + date.toUTCString();
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function getDeviceType() {
if (window.location.search === '?desktop') return "desktop";
if (window.location.search === '?mobile') return "mobile";
return isMobile() ? "mobile" : "desktop";
}
// https://stackoverflow.com/a/73731646/944162
function isMobile() {
const mQ = matchMedia?.('(pointer:coarse)');
if (mQ?.media === '(pointer:coarse)') return !!mQ.matches;
if ('orientation' in window) return true;
const userAgentsRegEx = /\b(Android|iPhone|iPad|iPod|Windows Phone|BlackBerry|webOS|IEMobile)\b/i
return userAgentsRegEx.test(navigator.userAgent)
}

View File

@ -1,6 +1,7 @@
import appContext from "./components/app_context.js"; import appContext from "./components/app_context.js";
import noteAutocompleteService from "./services/note_autocomplete.js"; import noteAutocompleteService from "./services/note_autocomplete.js";
import glob from "./services/glob.js"; import glob from "./services/glob.js";
import "../stylesheets/bootstrap.scss";
glob.setupGlobs(); glob.setupGlobs();

View File

@ -1,4 +1,5 @@
import dayjs from "dayjs"; import dayjs from "dayjs";
import { Modal } from "bootstrap";
function reloadFrontendApp(reason?: string) { function reloadFrontendApp(reason?: string) {
if (reason) { if (reason) {
@ -244,9 +245,7 @@ function getMimeTypeClass(mime: string) {
function closeActiveDialog() { function closeActiveDialog() {
if (glob.activeDialog) { if (glob.activeDialog) {
// TODO: Fix once we use proper ES imports. Modal.getOrCreateInstance(glob.activeDialog[0]).hide();
//@ts-ignore
bootstrap.Modal.getOrCreateInstance(glob.activeDialog[0]).hide();
glob.activeDialog = null; glob.activeDialog = null;
} }
} }
@ -288,9 +287,7 @@ async function openDialog($dialog: JQuery<HTMLElement>, closeActDialog = true) {
} }
saveFocusedElement(); saveFocusedElement();
// TODO: Fix once we use proper ES imports. Modal.getOrCreateInstance($dialog[0]).show();
//@ts-ignore
bootstrap.Modal.getOrCreateInstance($dialog[0]).show();
$dialog.on("hidden.bs.modal", () => { $dialog.on("hidden.bs.modal", () => {
const $autocompleteEl = $(".aa-input"); const $autocompleteEl = $(".aa-input");

View File

@ -0,0 +1,6 @@
import "../stylesheets/bootstrap.scss";
// @TriliumNextTODO: is this even needed anymore?
// @ts-ignore - module = undefined
// Required for correct loading of scripts in Electron
if (typeof module === 'object') {window.module = module; module = undefined;}

View File

@ -1,5 +1,6 @@
import utils from "./services/utils.js"; import utils from "./services/utils.js";
import ko from "knockout"; import ko from "knockout";
import "../stylesheets/bootstrap.scss";
// TriliumNextTODO: properly make use of below types // TriliumNextTODO: properly make use of below types
// type SetupModelSetupType = "new-document" | "sync-from-desktop" | "sync-from-server" | ""; // type SetupModelSetupType = "new-document" | "sync-from-desktop" | "sync-from-server" | "";

View File

@ -1,3 +1,5 @@
import "../stylesheets/bootstrap.scss";
/** /**
* Fetch note with given ID from backend * Fetch note with given ID from backend
* *

View File

@ -1,3 +1,4 @@
import { Tooltip } from "bootstrap";
import NoteContextAwareWidget from "../note_context_aware_widget.js"; import NoteContextAwareWidget from "../note_context_aware_widget.js";
const TPL = `<button class="button-widget bx" const TPL = `<button class="button-widget bx"
@ -17,7 +18,7 @@ export interface AbstractButtonWidgetSettings {
export default class AbstractButtonWidget<SettingsT extends AbstractButtonWidgetSettings> extends NoteContextAwareWidget { export default class AbstractButtonWidget<SettingsT extends AbstractButtonWidgetSettings> extends NoteContextAwareWidget {
protected settings!: SettingsT; protected settings!: SettingsT;
protected tooltip!: bootstrap.Tooltip; protected tooltip!: Tooltip;
isEnabled(): boolean | null | undefined { isEnabled(): boolean | null | undefined {
return true; return true;
@ -25,11 +26,10 @@ export default class AbstractButtonWidget<SettingsT extends AbstractButtonWidget
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
// Fix once bootstrap is available as non-UMD this.tooltip = new Tooltip(this.$widget[0], {
//@ts-ignore
this.tooltip = new bootstrap.Tooltip(this.$widget, {
html: true, html: true,
title: () => this.getTitle(), // in case getTitle() returns null -> use empty string as fallback
title: () => this.getTitle() || "",
trigger: "hover", trigger: "hover",
placement: this.settings.titlePlacement, placement: this.settings.titlePlacement,
fallbackPlacements: [this.settings.titlePlacement] fallbackPlacements: [this.settings.titlePlacement]

View File

@ -7,6 +7,7 @@ import ws from "../../services/ws.js";
import appContext from "../../components/app_context.js"; import appContext from "../../components/app_context.js";
import openService from "../../services/open.js"; import openService from "../../services/open.js";
import utils from "../../services/utils.js"; import utils from "../../services/utils.js";
import { Dropdown } from "bootstrap";
const TPL = ` const TPL = `
<div class="dropdown attachment-actions"> <div class="dropdown attachment-actions">
@ -91,7 +92,7 @@ export default class AttachmentActionsWidget extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")); this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"));
this.$widget.on("click", ".dropdown-item", () => this.dropdown.toggle()); this.$widget.on("click", ".dropdown-item", () => this.dropdown.toggle());
this.$uploadNewRevisionInput = this.$widget.find(".attachment-upload-new-revision-input"); this.$uploadNewRevisionInput = this.$widget.find(".attachment-upload-new-revision-input");

View File

@ -7,6 +7,7 @@ import appContext from "../../components/app_context.js";
import RightDropdownButtonWidget from "./right_dropdown_button.js"; import RightDropdownButtonWidget from "./right_dropdown_button.js";
import toastService from "../../services/toast.js"; import toastService from "../../services/toast.js";
import options from "../../services/options.js"; import options from "../../services/options.js";
import { Dropdown } from "bootstrap";
const MONTHS = [ const MONTHS = [
t("calendar.january"), t("calendar.january"),
@ -84,7 +85,7 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
// Don't trigger dropdownShown() at widget level when the month selection dropdown is shown, since it would cause a redundant refresh. // Don't trigger dropdownShown() at widget level when the month selection dropdown is shown, since it would cause a redundant refresh.
e.stopPropagation(); e.stopPropagation();
}); });
this.monthDropdown = bootstrap.Dropdown.getOrCreateInstance(this.$monthSelect); this.monthDropdown = Dropdown.getOrCreateInstance(this.$monthSelect);
this.$dropdownContent.find('[data-calendar-input="month-list"] button').on("click", (e) => { this.$dropdownContent.find('[data-calendar-input="month-list"] button').on("click", (e) => {
this.date.setMonth(e.target.dataset.value); this.date.setMonth(e.target.dataset.value);
this.createMonth(); this.createMonth();

View File

@ -3,6 +3,7 @@ import BasicWidget from "../basic_widget.js";
import utils from "../../services/utils.js"; import utils from "../../services/utils.js";
import UpdateAvailableWidget from "./update_available.js"; import UpdateAvailableWidget from "./update_available.js";
import options from "../../services/options.js"; import options from "../../services/options.js";
import { Tooltip, Dropdown } from "bootstrap";
const TPL = ` const TPL = `
<div class="dropdown global-menu"> <div class="dropdown global-menu">
@ -251,8 +252,8 @@ const TPL = `
export default class GlobalMenuWidget extends BasicWidget { export default class GlobalMenuWidget extends BasicWidget {
private updateAvailableWidget: UpdateAvailableWidget; private updateAvailableWidget: UpdateAvailableWidget;
private isHorizontalLayout: boolean; private isHorizontalLayout: boolean;
private tooltip!: bootstrap.Tooltip; private tooltip!: Tooltip;
private dropdown!: bootstrap.Dropdown; private dropdown!: Dropdown;
private $updateToLatestVersionButton!: JQuery<HTMLElement>; private $updateToLatestVersionButton!: JQuery<HTMLElement>;
private $zoomState!: JQuery<HTMLElement>; private $zoomState!: JQuery<HTMLElement>;
@ -292,17 +293,16 @@ export default class GlobalMenuWidget extends BasicWidget {
</g> </g>
</svg>`) </svg>`)
); );
//TODO: Fix once bootstrap is imported via modules.
//@ts-ignore this.tooltip = new Tooltip(this.$widget.find("[data-bs-toggle='tooltip']")[0], { trigger: "hover" });
this.tooltip = new bootstrap.Tooltip(this.$widget.find("[data-bs-toggle='tooltip']"), { trigger: "hover" });
} else { } else {
$globalMenuButton.toggleClass("bx bx-menu"); $globalMenuButton.toggleClass("bx bx-menu");
} }
//TODO: Fix once bootstrap is imported via modules. this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")[0], {
//@ts-ignore popperConfig: {
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"), { placement: "bottom"
alignment: "bottom" }
}); });
this.$widget.find(".show-about-dialog-button").on("click", () => this.triggerCommand("openAboutDialog")); this.$widget.find(".show-about-dialog-button").on("click", () => this.triggerCommand("openAboutDialog"));

View File

@ -1,4 +1,5 @@
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { Tooltip, Dropdown } from "bootstrap";
const TPL = ` const TPL = `
<div class="dropdown right-dropdown-widget dropend"> <div class="dropdown right-dropdown-widget dropend">
@ -28,10 +29,10 @@ export default class RightDropdownButtonWidget extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$dropdownMenu = this.$widget.find(".dropdown-menu"); this.$dropdownMenu = this.$widget.find(".dropdown-menu");
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")); this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"));
this.$tooltip = this.$widget.find(".tooltip-trigger").attr("title", this.title); this.$tooltip = this.$widget.find(".tooltip-trigger").attr("title", this.title);
this.tooltip = new bootstrap.Tooltip(this.$tooltip, { this.tooltip = new Tooltip(this.$tooltip, {
placement: this.settings.titlePlacement, placement: this.settings.titlePlacement,
fallbackPlacements: [this.settings.titlePlacement] fallbackPlacements: [this.settings.titlePlacement]
}); });

View File

@ -6,6 +6,7 @@ import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import appContext from "../../components/app_context.js"; import appContext from "../../components/app_context.js";
import { t } from "../../services/i18n.js"; import { t } from "../../services/i18n.js";
import { Modal } from "bootstrap";
let branchId; let branchId;
@ -39,7 +40,7 @@ const TPL = `<div class="branch-prefix-dialog modal fade mx-auto" tabindex="-1"
export default class BranchPrefixDialog extends BasicWidget { export default class BranchPrefixDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget); this.modal = Modal.getOrCreateInstance(this.$widget);
this.$form = this.$widget.find(".branch-prefix-form"); this.$form = this.$widget.find(".branch-prefix-form");
this.$treePrefixInput = this.$widget.find(".branch-prefix-input"); this.$treePrefixInput = this.$widget.find(".branch-prefix-input");
this.$noteTitle = this.$widget.find(".branch-prefix-note-title"); this.$noteTitle = this.$widget.find(".branch-prefix-note-title");

View File

@ -1,5 +1,6 @@
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js"; import { t } from "../../services/i18n.js";
import { Modal } from "bootstrap";
const DELETE_NOTE_BUTTON_CLASS = "confirm-dialog-delete-note"; const DELETE_NOTE_BUTTON_CLASS = "confirm-dialog-delete-note";
@ -49,7 +50,7 @@ export interface ConfirmWithTitleOptions {
export default class ConfirmDialog extends BasicWidget { export default class ConfirmDialog extends BasicWidget {
private resolve: ConfirmDialogCallback | null; private resolve: ConfirmDialogCallback | null;
private modal!: bootstrap.Modal; private modal!: Modal;
private $originallyFocused!: JQuery<HTMLElement> | null; private $originallyFocused!: JQuery<HTMLElement> | null;
private $confirmContent!: JQuery<HTMLElement>; private $confirmContent!: JQuery<HTMLElement>;
private $okButton!: JQuery<HTMLElement>; private $okButton!: JQuery<HTMLElement>;
@ -65,9 +66,7 @@ export default class ConfirmDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
// TODO: Fix once we use proper ES imports. this.modal = Modal.getOrCreateInstance(this.$widget[0]);
//@ts-ignore
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$confirmContent = this.$widget.find(".confirm-dialog-content"); this.$confirmContent = this.$widget.find(".confirm-dialog-content");
this.$okButton = this.$widget.find(".confirm-dialog-ok-button"); this.$okButton = this.$widget.find(".confirm-dialog-ok-button");
this.$cancelButton = this.$widget.find(".confirm-dialog-cancel-button"); this.$cancelButton = this.$widget.find(".confirm-dialog-cancel-button");

View File

@ -7,6 +7,7 @@ import openService from "../../services/open.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js"; import { t } from "../../services/i18n.js";
import type { EventData } from "../../components/app_context.js"; import type { EventData } from "../../components/app_context.js";
import { Modal } from "bootstrap";
const TPL = ` const TPL = `
<div class="export-dialog modal fade mx-auto" tabindex="-1" role="dialog"> <div class="export-dialog modal fade mx-auto" tabindex="-1" role="dialog">
@ -127,7 +128,7 @@ export default class ExportDialog extends BasicWidget {
private taskId: string; private taskId: string;
private branchId: string | null; private branchId: string | null;
private modal?: bootstrap.Modal; private modal?: Modal;
private $form!: JQuery<HTMLElement>; private $form!: JQuery<HTMLElement>;
private $noteTitle!: JQuery<HTMLElement>; private $noteTitle!: JQuery<HTMLElement>;
private $subtreeFormats!: JQuery<HTMLElement>; private $subtreeFormats!: JQuery<HTMLElement>;
@ -146,9 +147,7 @@ export default class ExportDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
// Remove once bootstrap is fixed. this.modal = Modal.getOrCreateInstance(this.$widget[0]);
// @ts-ignore
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$form = this.$widget.find(".export-form"); this.$form = this.$widget.find(".export-form");
this.$noteTitle = this.$widget.find(".export-note-title"); this.$noteTitle = this.$widget.find(".export-note-title");
this.$subtreeFormats = this.$widget.find(".export-subtree-formats"); this.$subtreeFormats = this.$widget.find(".export-subtree-formats");

View File

@ -4,6 +4,7 @@ import importService from "../../services/import.js";
import options from "../../services/options.js"; import options from "../../services/options.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js"; import { t } from "../../services/i18n.js";
import { Modal, Tooltip } from "bootstrap";
const TPL = ` const TPL = `
<div class="import-dialog modal fade mx-auto" tabindex="-1" role="dialog"> <div class="import-dialog modal fade mx-auto" tabindex="-1" role="dialog">
@ -86,7 +87,7 @@ export default class ImportDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
bootstrap.Modal.getOrCreateInstance(this.$widget); Modal.getOrCreateInstance(this.$widget);
this.$form = this.$widget.find(".import-form"); this.$form = this.$widget.find(".import-form");
this.$noteTitle = this.$widget.find(".import-note-title"); this.$noteTitle = this.$widget.find(".import-note-title");
@ -117,7 +118,7 @@ export default class ImportDialog extends BasicWidget {
}); });
let _ = [...this.$widget.find('[data-bs-toggle="tooltip"]')].forEach((element) => { let _ = [...this.$widget.find('[data-bs-toggle="tooltip"]')].forEach((element) => {
bootstrap.Tooltip.getOrCreateInstance(element, { Tooltip.getOrCreateInstance(element, {
html: true html: true
}); });
}); });

View File

@ -4,6 +4,7 @@ import noteAutocompleteService from "../../services/note_autocomplete.js";
import utils from "../../services/utils.js"; import utils from "../../services/utils.js";
import froca from "../../services/froca.js"; import froca from "../../services/froca.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
const TPL = ` const TPL = `
<div class="include-note-dialog modal mx-auto" tabindex="-1" role="dialog"> <div class="include-note-dialog modal mx-auto" tabindex="-1" role="dialog">
@ -54,7 +55,7 @@ const TPL = `
export default class IncludeNoteDialog extends BasicWidget { export default class IncludeNoteDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget); this.modal = Modal.getOrCreateInstance(this.$widget);
this.$form = this.$widget.find(".include-note-form"); this.$form = this.$widget.find(".include-note-form");
this.$autoComplete = this.$widget.find(".include-note-autocomplete"); this.$autoComplete = this.$widget.find(".include-note-autocomplete");
this.$form.on("submit", () => { this.$form.on("submit", () => {

View File

@ -1,6 +1,7 @@
import { t } from "../../services/i18n.js"; import { t } from "../../services/i18n.js";
import utils from "../../services/utils.js"; import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
const TPL = ` const TPL = `
<div class="info-dialog modal mx-auto" tabindex="-1" role="dialog" style="z-index: 2000;"> <div class="info-dialog modal mx-auto" tabindex="-1" role="dialog" style="z-index: 2000;">
@ -30,7 +31,7 @@ export default class InfoDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget); this.modal = Modal.getOrCreateInstance(this.$widget);
this.$infoContent = this.$widget.find(".info-dialog-content"); this.$infoContent = this.$widget.find(".info-dialog-content");
this.$okButton = this.$widget.find(".info-dialog-ok-button"); this.$okButton = this.$widget.find(".info-dialog-ok-button");

View File

@ -4,6 +4,7 @@ import utils from "../../services/utils.js";
import appContext from "../../components/app_context.js"; import appContext from "../../components/app_context.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import shortcutService from "../../services/shortcuts.js"; import shortcutService from "../../services/shortcuts.js";
import { Modal } from "bootstrap";
const TPL = `<div class="jump-to-note-dialog modal mx-auto" tabindex="-1" role="dialog"> const TPL = `<div class="jump-to-note-dialog modal mx-auto" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" role="document"> <div class="modal-dialog modal-lg" role="document">
@ -35,7 +36,7 @@ export default class JumpToNoteDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget); this.modal = Modal.getOrCreateInstance(this.$widget);
this.$autoComplete = this.$widget.find(".jump-to-note-autocomplete"); this.$autoComplete = this.$widget.find(".jump-to-note-autocomplete");
this.$results = this.$widget.find(".jump-to-note-results"); this.$results = this.$widget.find(".jump-to-note-results");

View File

@ -5,6 +5,7 @@ import appContext from "../../components/app_context.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import shortcutService from "../../services/shortcuts.js"; import shortcutService from "../../services/shortcuts.js";
import server from "../../services/server.js"; import server from "../../services/server.js";
import { Modal } from "bootstrap";
const TPL = ` const TPL = `
<div class="markdown-import-dialog modal fade mx-auto" tabindex="-1" role="dialog"> <div class="markdown-import-dialog modal fade mx-auto" tabindex="-1" role="dialog">
@ -35,7 +36,7 @@ export default class MarkdownImportDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget); this.modal = Modal.getOrCreateInstance(this.$widget);
this.$importTextarea = this.$widget.find(".markdown-import-textarea"); this.$importTextarea = this.$widget.find(".markdown-import-textarea");
this.$importButton = this.$widget.find(".markdown-import-button"); this.$importButton = this.$widget.find(".markdown-import-button");

View File

@ -3,6 +3,7 @@ import type { MenuCommandItem } from "../../menus/context_menu.js";
import { t } from "../../services/i18n.js"; import { t } from "../../services/i18n.js";
import noteTypesService from "../../services/note_types.js"; import noteTypesService from "../../services/note_types.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { Dropdown, Modal } from "bootstrap";
const TPL = ` const TPL = `
<div class="note-type-chooser-dialog modal mx-auto" tabindex="-1" role="dialog"> <div class="note-type-chooser-dialog modal mx-auto" tabindex="-1" role="dialog">
@ -53,8 +54,8 @@ type Callback = (data: ChooseNoteTypeResponse) => void;
export default class NoteTypeChooserDialog extends BasicWidget { export default class NoteTypeChooserDialog extends BasicWidget {
private resolve: Callback | null; private resolve: Callback | null;
private dropdown!: bootstrap.Dropdown; private dropdown!: Dropdown;
private modal!: JQuery<HTMLElement>; private modal!: Modal;
private $noteTypeDropdown!: JQuery<HTMLElement>; private $noteTypeDropdown!: JQuery<HTMLElement>;
private $originalFocused: JQuery<HTMLElement> | null; private $originalFocused: JQuery<HTMLElement> | null;
private $originalDialog: JQuery<HTMLElement> | null; private $originalDialog: JQuery<HTMLElement> | null;
@ -69,14 +70,10 @@ export default class NoteTypeChooserDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
// TODO: Remove once we import bootstrap the right way this.modal = Modal.getOrCreateInstance(this.$widget[0]);
//@ts-ignore
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown"); this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown");
// TODO: Remove once we import bootstrap the right way this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find(".note-type-dropdown-trigger")[0]);
//@ts-ignore
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find(".note-type-dropdown-trigger"));
this.$widget.on("hidden.bs.modal", () => { this.$widget.on("hidden.bs.modal", () => {
if (this.resolve) { if (this.resolve) {
@ -142,7 +139,7 @@ export default class NoteTypeChooserDialog extends BasicWidget {
this.dropdown.show(); this.dropdown.show();
this.$originalDialog = glob.activeDialog; this.$originalDialog = glob.activeDialog;
glob.activeDialog = this.modal; glob.activeDialog = this.$widget;
this.modal.show(); this.modal.show();
this.$noteTypeDropdown.find(".dropdown-item:first").focus(); this.$noteTypeDropdown.find(".dropdown-item:first").focus();

View File

@ -1,6 +1,7 @@
import { t } from "../../services/i18n.js"; import { t } from "../../services/i18n.js";
import utils from "../../services/utils.js"; import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
const TPL = ` const TPL = `
<div class="password-not-set-dialog modal fade mx-auto" tabindex="-1" role="dialog"> <div class="password-not-set-dialog modal fade mx-auto" tabindex="-1" role="dialog">
@ -22,13 +23,12 @@ const TPL = `
export default class PasswordNoteSetDialog extends BasicWidget { export default class PasswordNoteSetDialog extends BasicWidget {
private modal!: bootstrap.Modal; private modal!: Modal;
private $openPasswordOptionsButton!: JQuery<HTMLElement>; private $openPasswordOptionsButton!: JQuery<HTMLElement>;
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
//@ts-ignore fix once bootstrap is imported via JQuery. this.modal = Modal.getOrCreateInstance(this.$widget[0]);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$openPasswordOptionsButton = this.$widget.find(".open-password-options-button"); this.$openPasswordOptionsButton = this.$widget.find(".open-password-options-button");
this.$openPasswordOptionsButton.on("click", () => { this.$openPasswordOptionsButton.on("click", () => {
this.modal.hide(); this.modal.hide();

View File

@ -1,6 +1,7 @@
import { t } from "../../services/i18n.js"; import { t } from "../../services/i18n.js";
import utils from "../../services/utils.js"; import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
const TPL = ` const TPL = `
<div class="prompt-dialog modal mx-auto" tabindex="-1" role="dialog" style="z-index: 2000;"> <div class="prompt-dialog modal mx-auto" tabindex="-1" role="dialog" style="z-index: 2000;">
@ -41,7 +42,7 @@ export default class PromptDialog extends BasicWidget {
private resolve?: ((value: string | null) => void) | undefined | null; private resolve?: ((value: string | null) => void) | undefined | null;
private shownCb?: PromptShownDialogCallback | null; private shownCb?: PromptShownDialogCallback | null;
private modal!: bootstrap.Modal; private modal!: Modal;
private $dialogBody!: JQuery<HTMLElement>; private $dialogBody!: JQuery<HTMLElement>;
private $question!: JQuery<HTMLElement> | null; private $question!: JQuery<HTMLElement> | null;
private $answer!: JQuery<HTMLElement> | null; private $answer!: JQuery<HTMLElement> | null;
@ -56,9 +57,7 @@ export default class PromptDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
// TODO: Fix once we use proper ES imports. this.modal = Modal.getOrCreateInstance(this.$widget[0]);
//@ts-ignore
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$dialogBody = this.$widget.find(".modal-body"); this.$dialogBody = this.$widget.find(".modal-body");
this.$form = this.$widget.find(".prompt-dialog-form"); this.$form = this.$widget.find(".prompt-dialog-form");
this.$question = null; this.$question = null;

View File

@ -2,6 +2,7 @@ import { t } from "../../services/i18n.js";
import protectedSessionService from "../../services/protected_session.js"; import protectedSessionService from "../../services/protected_session.js";
import utils from "../../services/utils.js"; import utils from "../../services/utils.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { Modal } from "bootstrap";
const TPL = ` const TPL = `
<div class="protected-session-password-dialog modal mx-auto" data-backdrop="false" tabindex="-1" role="dialog"> <div class="protected-session-password-dialog modal mx-auto" data-backdrop="false" tabindex="-1" role="dialog">
@ -28,7 +29,7 @@ const TPL = `
export default class ProtectedSessionPasswordDialog extends BasicWidget { export default class ProtectedSessionPasswordDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget); this.modal = Modal.getOrCreateInstance(this.$widget);
this.$passwordForm = this.$widget.find(".protected-session-password-form"); this.$passwordForm = this.$widget.find(".protected-session-password-form");
this.$passwordInput = this.$widget.find(".protected-session-password"); this.$passwordInput = this.$widget.find(".protected-session-password");

View File

@ -10,6 +10,7 @@ import server from "../../services/server.js";
import toastService from "../../services/toast.js"; import toastService from "../../services/toast.js";
import utils from "../../services/utils.js"; import utils from "../../services/utils.js";
import ws from "../../services/ws.js"; import ws from "../../services/ws.js";
import { Modal } from "bootstrap";
const TPL = ` const TPL = `
<div class="recent-changes-dialog modal fade mx-auto" tabindex="-1" role="dialog"> <div class="recent-changes-dialog modal fade mx-auto" tabindex="-1" role="dialog">
@ -30,7 +31,7 @@ const TPL = `
export default class RecentChangesDialog extends BasicWidget { export default class RecentChangesDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget); this.modal = Modal.getOrCreateInstance(this.$widget);
this.$content = this.$widget.find(".recent-changes-content"); this.$content = this.$widget.find(".recent-changes-content");
this.$eraseDeletedNotesNow = this.$widget.find(".erase-deleted-notes-now-button"); this.$eraseDeletedNotesNow = this.$widget.find(".erase-deleted-notes-now-button");

View File

@ -11,6 +11,7 @@ import dialogService from "../../services/dialog.js";
import options from "../../services/options.js"; import options from "../../services/options.js";
import type FNote from "../../entities/fnote.js"; import type FNote from "../../entities/fnote.js";
import type { NoteType } from "../../entities/fnote.js"; import type { NoteType } from "../../entities/fnote.js";
import { Dropdown, Modal } from "bootstrap";
const TPL = ` const TPL = `
<div class="revisions-dialog modal fade mx-auto" tabindex="-1" role="dialog"> <div class="revisions-dialog modal fade mx-auto" tabindex="-1" role="dialog">
@ -100,10 +101,8 @@ export default class RevisionsDialog extends BasicWidget {
private note: FNote | null; private note: FNote | null;
private revisionId: string | null; private revisionId: string | null;
//@ts-ignore private modal!: Modal;
private modal: bootstrap.Modal; private listDropdown!: Dropdown;
//@ts-ignore
private listDropdown: bootstrap.Dropdown;
private $list!: JQuery<HTMLElement>; private $list!: JQuery<HTMLElement>;
private $listDropdown!: JQuery<HTMLElement>; private $listDropdown!: JQuery<HTMLElement>;
@ -125,13 +124,13 @@ export default class RevisionsDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
//@ts-ignore
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget); this.modal = Modal.getOrCreateInstance(this.$widget[0]);
this.$list = this.$widget.find(".revision-list"); this.$list = this.$widget.find(".revision-list");
this.$listDropdown = this.$widget.find(".revision-list-dropdown"); this.$listDropdown = this.$widget.find(".revision-list-dropdown");
//@ts-ignore
this.listDropdown = bootstrap.Dropdown.getOrCreateInstance(this.$listDropdown, { autoClose: false }); this.listDropdown = Dropdown.getOrCreateInstance(this.$listDropdown[0], { autoClose: false });
this.$content = this.$widget.find(".revision-content"); this.$content = this.$widget.find(".revision-content");
this.$title = this.$widget.find(".revision-title"); this.$title = this.$widget.find(".revision-title");
this.$titleButtons = this.$widget.find(".revision-title-buttons"); this.$titleButtons = this.$widget.find(".revision-title-buttons");

View File

@ -4,6 +4,7 @@ import treeService from "../../services/tree.js";
import importService from "../../services/import.js"; import importService from "../../services/import.js";
import options from "../../services/options.js"; import options from "../../services/options.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { Modal, Tooltip } from "bootstrap";
const TPL = ` const TPL = `
<div class="upload-attachments-dialog modal fade mx-auto" tabindex="-1" role="dialog"> <div class="upload-attachments-dialog modal fade mx-auto" tabindex="-1" role="dialog">
@ -49,7 +50,7 @@ export default class UploadAttachmentsDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget); this.modal = Modal.getOrCreateInstance(this.$widget);
this.$form = this.$widget.find(".upload-attachment-form"); this.$form = this.$widget.find(".upload-attachment-form");
this.$noteTitle = this.$widget.find(".upload-attachment-note-title"); this.$noteTitle = this.$widget.find(".upload-attachment-note-title");
@ -72,7 +73,7 @@ export default class UploadAttachmentsDialog extends BasicWidget {
} }
}); });
bootstrap.Tooltip.getOrCreateInstance(this.$widget.find('[data-bs-toggle="tooltip"]'), { Tooltip.getOrCreateInstance(this.$widget.find('[data-bs-toggle="tooltip"]'), {
html: true html: true
}); });
} }

View File

@ -3,6 +3,7 @@ import NoteContextAwareWidget from "./note_context_aware_widget.js";
import { t } from "../services/i18n.js"; import { t } from "../services/i18n.js";
import type FNote from "../entities/fnote.js"; import type FNote from "../entities/fnote.js";
import type { EventData } from "../components/app_context.js"; import type { EventData } from "../components/app_context.js";
import { Dropdown } from "bootstrap";
type Editability = "auto" | "readOnly" | "autoReadOnlyDisabled"; type Editability = "auto" | "readOnly" | "autoReadOnlyDisabled";
@ -59,15 +60,13 @@ const TPL = `
export default class EditabilitySelectWidget extends NoteContextAwareWidget { export default class EditabilitySelectWidget extends NoteContextAwareWidget {
private dropdown!: bootstrap.Dropdown; private dropdown!: Dropdown;
private $editabilityActiveDesc!: JQuery<HTMLElement>; private $editabilityActiveDesc!: JQuery<HTMLElement>;
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
// TODO: Remove once bootstrap is added to webpack. this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")[0]);
//@ts-ignore
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"));
this.$editabilityActiveDesc = this.$widget.find(".editability-active-desc"); this.$editabilityActiveDesc = this.$widget.find(".editability-active-desc");

View File

@ -6,6 +6,7 @@ import { t } from "../services/i18n.js";
import type FNote from "../entities/fnote.js"; import type FNote from "../entities/fnote.js";
import type { NoteType } from "../entities/fnote.js"; import type { NoteType } from "../entities/fnote.js";
import type { EventData } from "../components/app_context.js"; import type { EventData } from "../components/app_context.js";
import { Dropdown } from "bootstrap";
interface NoteTypeMapping { interface NoteTypeMapping {
type: NoteType; type: NoteType;
@ -80,7 +81,7 @@ const TPL = `
export default class NoteTypeWidget extends NoteContextAwareWidget { export default class NoteTypeWidget extends NoteContextAwareWidget {
private dropdown!: bootstrap.Dropdown; private dropdown!: Dropdown;
private $noteTypeDropdown!: JQuery<HTMLElement>; private $noteTypeDropdown!: JQuery<HTMLElement>;
private $noteTypeButton!: JQuery<HTMLElement>; private $noteTypeButton!: JQuery<HTMLElement>;
private $noteTypeDesc!: JQuery<HTMLElement>; private $noteTypeDesc!: JQuery<HTMLElement>;
@ -88,8 +89,7 @@ export default class NoteTypeWidget extends NoteContextAwareWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
//@ts-ignore this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")[0]);
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"));
this.$widget.on("show.bs.dropdown", () => this.renderDropdown()); this.$widget.on("show.bs.dropdown", () => this.renderDropdown());

View File

@ -6,6 +6,7 @@ import utils from "../services/utils.js";
import appContext from "../components/app_context.js"; import appContext from "../components/app_context.js";
import shortcutService from "../services/shortcuts.js"; import shortcutService from "../services/shortcuts.js";
import { t } from "../services/i18n.js"; import { t } from "../services/i18n.js";
import { Dropdown, Tooltip } from "bootstrap";
const TPL = ` const TPL = `
<div class="quick-search input-group input-group-sm"> <div class="quick-search input-group input-group-sm">
@ -44,7 +45,7 @@ const MAX_DISPLAYED_NOTES = 15;
export default class QuickSearchWidget extends BasicWidget { export default class QuickSearchWidget extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")); this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"));
this.$searchString = this.$widget.find(".search-string"); this.$searchString = this.$widget.find(".search-string");
this.$dropdownMenu = this.$widget.find(".dropdown-menu"); this.$dropdownMenu = this.$widget.find(".dropdown-menu");
@ -100,7 +101,7 @@ export default class QuickSearchWidget extends BasicWidget {
const { searchResultNoteIds, error } = await server.get(`quick-search/${encodeURIComponent(searchString)}`); const { searchResultNoteIds, error } = await server.get(`quick-search/${encodeURIComponent(searchString)}`);
if (error) { if (error) {
let tooltip = new bootstrap.Tooltip(this.$searchString, { let tooltip = new Tooltip(this.$searchString, {
trigger: "manual", trigger: "manual",
title: `Search error: ${error}`, title: `Search error: ${error}`,
placement: "right" placement: "right"

View File

@ -16,6 +16,7 @@ import Limit from "../search_options/limit.js";
import Debug from "../search_options/debug.js"; import Debug from "../search_options/debug.js";
import appContext from "../../components/app_context.js"; import appContext from "../../components/app_context.js";
import bulkActionService from "../../services/bulk_action.js"; import bulkActionService from "../../services/bulk_action.js";
import { Dropdown } from "bootstrap";
const TPL = ` const TPL = `
<div class="search-definition-widget"> <div class="search-definition-widget">
@ -203,7 +204,7 @@ export default class SearchDefinitionWidget extends NoteContextAwareWidget {
}); });
this.$widget.on("click", "[data-action-add]", async (event) => { this.$widget.on("click", "[data-action-add]", async (event) => {
bootstrap.Dropdown.getOrCreateInstance(this.$widget.find(".action-add-toggle")); Dropdown.getOrCreateInstance(this.$widget.find(".action-add-toggle"));
const actionName = $(event.target).attr("data-action-add"); const actionName = $(event.target).attr("data-action-add");

View File

@ -4,6 +4,7 @@ import server from "../../services/server.js";
import shortcutService from "../../services/shortcuts.js"; import shortcutService from "../../services/shortcuts.js";
import appContext from "../../components/app_context.js"; import appContext from "../../components/app_context.js";
import { t } from "../../services/i18n.js"; import { t } from "../../services/i18n.js";
import { Tooltip } from "bootstrap";
const TPL = ` const TPL = `
<tr> <tr>
@ -78,7 +79,7 @@ export default class SearchString extends AbstractSearchOption {
} }
showSearchErrorEvent({ error }) { showSearchErrorEvent({ error }) {
let tooltip = new bootstrap.Tooltip(this.$searchString, { let tooltip = new Tooltip(this.$searchString, {
trigger: "manual", trigger: "manual",
title: `${t("search_string.error", { error })}`, title: `${t("search_string.error", { error })}`,
placement: "bottom" placement: "bottom"

View File

@ -4,6 +4,7 @@ import ws from "../services/ws.js";
import options from "../services/options.js"; import options from "../services/options.js";
import syncService from "../services/sync.js"; import syncService from "../services/sync.js";
import { escapeQuotes } from "../services/utils.js"; import { escapeQuotes } from "../services/utils.js";
import { Tooltip } from "bootstrap";
const TPL = ` const TPL = `
<div class="sync-status-widget launcher-button"> <div class="sync-status-widget launcher-button">
@ -96,7 +97,7 @@ export default class SyncStatusWidget extends BasicWidget {
return; return;
} }
bootstrap.Tooltip.getOrCreateInstance(this.$widget.find(`.sync-status-${className}`), { Tooltip.getOrCreateInstance(this.$widget.find(`.sync-status-${className}`), {
html: true, html: true,
placement: this.settings.titlePlacement, placement: this.settings.titlePlacement,
fallbackPlacements: [this.settings.titlePlacement] fallbackPlacements: [this.settings.titlePlacement]

2
src/public/stylesheets/bootstrap.scss vendored Normal file
View File

@ -0,0 +1,2 @@
// Import all of Bootstrap's CSS
@import "bootstrap/scss/bootstrap";

View File

@ -28,6 +28,7 @@ async function register(app: express.Application) {
type: "filesystem", type: "filesystem",
cacheDirectory: path.join(srcRoot, "..", ".cache", isElectron ? "electron" : "server") cacheDirectory: path.join(srcRoot, "..", ".cache", isElectron ? "electron" : "server")
}, },
plugins: productionConfig.plugins,
entry: productionConfig.entry, entry: productionConfig.entry,
module: productionConfig.module, module: productionConfig.module,
resolve: productionConfig.resolve, resolve: productionConfig.resolve,
@ -95,8 +96,6 @@ async function register(app: express.Application) {
app.use(`/${assetPath}/node_modules/jquery.fancytree/dist/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/jquery.fancytree/dist/"))); app.use(`/${assetPath}/node_modules/jquery.fancytree/dist/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/jquery.fancytree/dist/")));
app.use(`/${assetPath}/node_modules/bootstrap/dist/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/bootstrap/dist/")));
// CodeMirror // CodeMirror
app.use(`/${assetPath}/node_modules/codemirror/lib/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/codemirror/lib/"))); app.use(`/${assetPath}/node_modules/codemirror/lib/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/codemirror/lib/")));
app.use(`/${assetPath}/node_modules/codemirror/addon/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/codemirror/addon/"))); app.use(`/${assetPath}/node_modules/codemirror/addon/`, persistentCacheStatic(path.join(srcRoot, "..", "node_modules/codemirror/addon/")));

View File

@ -7,6 +7,8 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover" />
<link rel="manifest" crossorigin="use-credentials" href="manifest.webmanifest"> <link rel="manifest" crossorigin="use-credentials" href="manifest.webmanifest">
<% // TriliumNextTODO: move the css file to ${assetPath}/stylesheets/ %>
<link rel="stylesheet" href="<%= appPath %>/desktop.css">
<title>TriliumNext Notes</title> <title>TriliumNext Notes</title>
</head> </head>
<body class="desktop heading-style-<%= headingStyle %> layout-<%= layoutOrientation %> platform-<%= platform %> <%= isElectron ? 'electron' : '' %> <%= hasNativeTitleBar ? 'native-titlebar' : '' %> <%= hasBackgroundEffects ? 'background-effects' : '' %>"> <body class="desktop heading-style-<%= headingStyle %> layout-<%= layoutOrientation %> platform-<%= platform %> <%= isElectron ? 'electron' : '' %> <%= hasNativeTitleBar ? 'native-titlebar' : '' %> <%= hasBackgroundEffects ? 'background-effects' : '' %>">
@ -34,8 +36,6 @@
<script src="<%= assetPath %>/node_modules/jquery/dist/jquery.min.js"></script> <script src="<%= assetPath %>/node_modules/jquery/dist/jquery.min.js"></script>
<link href="<%= assetPath %>/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="<%= assetPath %>/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<!-- Include Fancytree library and skip --> <!-- Include Fancytree library and skip -->
<link href="<%= assetPath %>/stylesheets/tree.css" rel="stylesheet"> <link href="<%= assetPath %>/stylesheets/tree.css" rel="stylesheet">

View File

@ -6,10 +6,11 @@
<title><%= t("login.title") %></title> <title><%= t("login.title") %></title>
<link rel="apple-touch-icon" sizes="180x180" href="<%= assetPath %>/images/app-icons/ios/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="<%= assetPath %>/images/app-icons/ios/apple-touch-icon.png">
<link rel="shortcut icon" href="favicon.ico"> <link rel="shortcut icon" href="favicon.ico">
<link rel="stylesheet" href="<%= assetPath %>/node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="<%= assetPath %>/stylesheets/theme-light.css"> <link rel="stylesheet" href="<%= assetPath %>/stylesheets/theme-light.css">
<link rel="stylesheet" href="<%= assetPath %>/stylesheets/theme-next.css"> <link rel="stylesheet" href="<%= assetPath %>/stylesheets/theme-next.css">
<link rel="stylesheet" href="<%= assetPath %>/stylesheets/style.css"> <link rel="stylesheet" href="<%= assetPath %>/stylesheets/style.css">
<% // TriliumNextTODO: move the css file to ${assetPath}/stylesheets/ %>
<link rel="stylesheet" href="<%= appPath %>/login.css">
</head> </head>
<body> <body>
<div class="container"> <div class="container">
@ -44,37 +45,8 @@
</form> </form>
</div> </div>
</div> </div>
<script src="<%= appPath %>/login.js" crossorigin type="module"></script>
<script>
// Required for correct loading of scripts in Electron
if (typeof module === 'object') {window.module = module; module = undefined;}
const device = getDeviceType()
console.log("Setting device cookie to:", device);
setCookie("trilium-device", device);
function setCookie(name, value) {
const date = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1000);
const expires = "; expires=" + date.toUTCString();
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function getDeviceType() {
if (window.location.search === '?desktop') return "desktop";
if (window.location.search === '?mobile') return "mobile";
return isMobile() ? "mobile" : "desktop";
}
// https://stackoverflow.com/a/73731646/944162
function isMobile() {
const mQ = matchMedia?.('(pointer:coarse)');
if (mQ?.media === '(pointer:coarse)') return !!mQ.matches;
if ('orientation' in window) return true;
const userAgentsRegEx = /\b(Android|iPhone|iPad|iPod|Windows Phone|BlackBerry|webOS|IEMobile)\b/i
return userAgentsRegEx.test(navigator.userAgent)
}
</script>
</body> </body>
</html> </html>

View File

@ -10,6 +10,9 @@
<title>TriliumNext Notes</title> <title>TriliumNext Notes</title>
<link rel="manifest" crossorigin="use-credentials" href="manifest.webmanifest"> <link rel="manifest" crossorigin="use-credentials" href="manifest.webmanifest">
<% // TriliumNextTODO: move the css file to ${assetPath}/stylesheets/ %>
<link rel="stylesheet" href="<%= appPath %>/mobile.css">
<style> <style>
.lds-roller { .lds-roller {
display: inline-block; display: inline-block;
@ -117,9 +120,6 @@
<link href="<%= assetPath %>/stylesheets/tree.css" rel="stylesheet"> <link href="<%= assetPath %>/stylesheets/tree.css" rel="stylesheet">
<script src="<%= assetPath %>/node_modules/jquery.fancytree/dist/jquery.fancytree-all-deps.min.js"></script> <script src="<%= assetPath %>/node_modules/jquery.fancytree/dist/jquery.fancytree-all-deps.min.js"></script>
<link href="<%= assetPath %>/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="<%= assetPath %>/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="<%= appPath %>/mobile.js" crossorigin type="module"></script> <script src="<%= appPath %>/mobile.js" crossorigin type="module"></script>
<link href="api/fonts" rel="stylesheet"> <link href="api/fonts" rel="stylesheet">

View File

@ -6,7 +6,8 @@
<title><%= t("set_password.title") %></title> <title><%= t("set_password.title") %></title>
<link rel="apple-touch-icon" sizes="180x180" href="<%= assetPath %>/images/app-icons/ios/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="<%= assetPath %>/images/app-icons/ios/apple-touch-icon.png">
<link rel="shortcut icon" href="favicon.ico"> <link rel="shortcut icon" href="favicon.ico">
<link rel="stylesheet" href="<%= assetPath %>/node_modules/bootstrap/dist/css/bootstrap.min.css"> <% // TriliumNextTODO: move the css file to ${assetPath}/stylesheets/ %>
<link rel="stylesheet" href="<%= appPath %>/set_password.css">
<link rel="stylesheet" href="<%= assetPath %>/stylesheets/theme-light.css"> <link rel="stylesheet" href="<%= assetPath %>/stylesheets/theme-light.css">
<link rel="stylesheet" href="<%= assetPath %>/stylesheets/theme-next.css"> <link rel="stylesheet" href="<%= assetPath %>/stylesheets/theme-next.css">
<link rel="stylesheet" href="<%= assetPath %>/stylesheets/style.css"> <link rel="stylesheet" href="<%= assetPath %>/stylesheets/style.css">
@ -45,9 +46,7 @@
</div> </div>
</div> </div>
<script> <script src="<%= appPath %>/set_password.js" crossorigin type="module"></script>
// Required for correct loading of scripts in Electron
if (typeof module === 'object') {window.module = module; module = undefined;}
</script>
</body> </body>
</html> </html>

View File

@ -6,6 +6,9 @@
<meta id="syncInProgress" content="<%= syncInProgress ? 1 : 0 %>" /> <meta id="syncInProgress" content="<%= syncInProgress ? 1 : 0 %>" />
<title><%= t("setup.title") %></title> <title><%= t("setup.title") %></title>
<% // TriliumNextTODO: move the css file to ${assetPath}/stylesheets/ %>
<link rel="stylesheet" href="<%= appPath %>/setup.css">
<style> <style>
.lds-ring { .lds-ring {
display: inline-block; display: inline-block;
@ -168,9 +171,6 @@
<script src="<%= assetPath %>/node_modules/jquery/dist/jquery.min.js"></script> <script src="<%= assetPath %>/node_modules/jquery/dist/jquery.min.js"></script>
<script src="<%= assetPath %>/node_modules/jquery-hotkeys/jquery-hotkeys.js"></script> <script src="<%= assetPath %>/node_modules/jquery-hotkeys/jquery-hotkeys.js"></script>
<link href="<%= assetPath %>/node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="<%= assetPath %>/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="<%= appPath %>/setup.js" crossorigin type="module"></script> <script src="<%= appPath %>/setup.js" crossorigin type="module"></script>
<link href="<%= assetPath %>/stylesheets/theme-light.css" rel="stylesheet" /> <link href="<%= assetPath %>/stylesheets/theme-light.css" rel="stylesheet" />
<link href="<%= assetPath %>/stylesheets/theme-next.css" rel="stylesheet" /> <link href="<%= assetPath %>/stylesheets/theme-next.css" rel="stylesheet" />

View File

@ -1,6 +1,8 @@
import { fileURLToPath } from "url"; import { fileURLToPath } from "url";
import path from "path"; import path from "path";
import autoprefixer from "autoprefixer";
import assetPath from "./src/services/asset_path.js"; import assetPath from "./src/services/asset_path.js";
import miniCssExtractPlugin from "mini-css-extract-plugin";
import type { Configuration } from "webpack"; import type { Configuration } from "webpack";
const rootDir = path.dirname(fileURLToPath(import.meta.url)); const rootDir = path.dirname(fileURLToPath(import.meta.url));
@ -8,15 +10,24 @@ const config: Configuration = {
mode: "production", mode: "production",
entry: { entry: {
setup: "./src/public/app/setup.js", setup: "./src/public/app/setup.js",
login: "./src/public/app/login.js",
mobile: "./src/public/app/mobile.js", mobile: "./src/public/app/mobile.js",
desktop: "./src/public/app/desktop.js", desktop: "./src/public/app/desktop.js",
share: "./src/public/app/share.js" share: "./src/public/app/share.js",
// TriliumNextTODO: integrate set_password into setup entry point/view
set_password: "./src/public/app/set_password.js"
}, },
output: { output: {
publicPath: `${assetPath}/app-dist/`, publicPath: `${assetPath}/app-dist/`,
path: path.resolve(rootDir, "src/public/app-dist"), path: path.resolve(rootDir, "src/public/app-dist"),
filename: "[name].js" filename: "[name].js"
}, },
plugins: [
new miniCssExtractPlugin({
// TriliumNextTODO: enable this, once webpack build outputs into the "build" folder, instead of "src/public/app-dist" folder => @pano9000
//filename: "../stylesheets/[name].css"
})
],
module: { module: {
rules: [ rules: [
{ {
@ -30,6 +41,29 @@ const config: Configuration = {
} }
], ],
exclude: /node_modules/ exclude: /node_modules/
},
{
// bootstrap CSS related configuration
test: /\.(scss)$/,
use: [
{
loader: miniCssExtractPlugin.loader
},
{
loader: "css-loader"
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [autoprefixer]
}
}
},
{
loader: "sass-loader"
}
]
} }
] ]
}, },