Merge remote-tracking branch 'origin/develop' into feature/client_typescript_port1
; Conflicts: ; package-lock.json
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg enable-background="new 0 0 256 256" version="1.1" viewBox="0 0 256 256" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>TrilliumNext Notes</title>
|
||||
<title>TriliumNext Notes</title>
|
||||
<path fill="black" d="m232.6 27.598c-17.706 0.092041-40.298 3.7127-58.258 10.104-1.7959 0.63909-3.5465 1.3043-5.2402 1.998-3.1 1.2-6.0988 2.6016-8.7988 4.1016-2.2 1.2-4.3016 2.4988-6.1016 3.7988-21.6 15.5-27.9 44.2-28.6 65.4l14.9-10.5 14.301-10 51.199-35.9-49.1 39.301-14.1 11.299-14.801 11.801c20.4 6.5 52.4 9.7992 74.9-6.3008 3.1886-2.319 6.4708-5.1162 9.7559-8.459 0.14708-0.08175 0.29689-0.1571 0.44336-0.24023 2.3386-2.3386 4.7705-4.8714 7.0215-7.5898 0.02928-0.033868 0.05864-0.065681 0.08789-0.099609 0.0964-0.038723 0.1948-0.072111 0.29102-0.11133 14.544-16.737 27.833-39.152 32.252-55.658 0.67979-2.5395 1.1487-4.9387 1.3809-7.1562 0.11607-1.1088 0.17422-2.173 0.16797-3.1855-1.0438-0.3625-2.1849-0.68557-3.4121-0.9707-1.2272-0.28513-2.542-0.53096-3.9336-0.74024s-2.8595-0.38069-4.3965-0.51562c-3.0739-0.26987-6.4198-0.39341-9.9609-0.375zm-202.79 20.252c-11.737-0.05-22.113 1.4004-28.312 4.6504 0.9 5.6625 4.3309 13.419 9.3125 21.77v0.001953c3.3209 5.5664 7.332 11.395 11.74 17.043v0.001953c6.6127 8.4716 14.122 16.534 21.547 22.684 2.3 1.9 4.5008 3.5996 6.8008 5.0996 0.048555 0.0124 0.097907 0.019 0.14648 0.03125 1.7845 1.2837 3.569 2.2777 5.3535 3.1699 20.8 10.4 45.5 3.7984 62.1-4.1016l-14.301-7.2988-13.6-6.9004-48.127-24.607 49.928 21.707 14.5 6.3008 15.199 6.5996c-3.4-18.3-14.099-44-35.799-54.9-3.3-1.6-6.9004-3.1004-10.9-4.4004-2.9-0.9-5.8996-1.7-9.0996-2.5-11.65-2.75-24.751-4.2996-36.488-4.3496zm97.488 73.85 3.6992 13.9 3.5996 13.201 12.801 47.6-15.9-47-4.5-13.4-4.8008-14.199c-10.3 13.4-21.3 36.199-15.5 57.199 0.8747 3.11 2.1333 6.3182 3.6719 9.709 0.01066 0.06374 0.01836 0.12769 0.0293 0.19141 1.1 2.5 2.3988 5.0992 3.7988 7.6992 10.4 18.8 27.701 38.501 39.701 42.801 0.00763-0.00936 0.01581-0.01991 0.02344-0.0293 0.02502 0.00909 0.05119 0.02035 0.07617 0.0293 8.8-10.8 16.8-42.601 15.9-65.701-0.1-2.7-0.30117-5.2992-0.70117-7.6992-0.3-1.9-0.69922-3.8-1.1992-5.5-5.6-20.2-25.199-32.601-40.699-38.801z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg enable-background="new 0 0 256 256" version="1.1" viewBox="0 0 256 256" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>TrilliumNext Notes</title>
|
||||
<title>TriliumNext Notes</title>
|
||||
<style type="text/css">
|
||||
.st0{fill:#95C980;}
|
||||
.st1{fill:#72B755;}
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg enable-background="new 0 0 256 256" version="1.1" viewBox="0 0 256 256" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>TrilliumNext Notes</title>
|
||||
<title>TriliumNext Notes</title>
|
||||
<g>
|
||||
<path d="m202.9 112.7c-22.5 16.1-54.5 12.8-74.9 6.3l14.8-11.8 14.1-11.3 49.1-39.3-51.2 35.9-14.3 10-14.9 10.5c0.7-21.2 7-49.9 28.6-65.4 1.8-1.3 3.9-2.6 6.1-3.8 2.7-1.5 5.7-2.9 8.8-4.1 27.1-11.1 68.5-15.3 85.2-9.5 0.1 16.2-15.9 45.4-33.9 65.9-2.4 2.8-4.9 5.4-7.4 7.8-3.4 3.5-6.8 6.4-10.1 8.8z" fill="#ab60e3"/>
|
||||
<path d="m213.1 104c-22.2 12.6-51.4 9.3-70.3 3.2l14.1-11.3 49.1-39.3-51.2 35.9-14.3 10c0.5-18.1 4.9-42.1 19.7-58.6 2.7-1.5 5.7-2.9 8.8-4.1 27.1-11.1 68.5-15.3 85.2-9.5 0.1 16.2-15.9 45.4-33.9 65.9-2.3 2.8-4.8 5.4-7.2 7.8z" fill="#8038b8"/>
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg enable-background="new 0 0 256 256" version="1.1" viewBox="0 0 256 256" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>TrilliumNext Notes</title>
|
||||
<title>TriliumNext Notes</title>
|
||||
<path fill="white" d="m232.6 27.598c-17.706 0.092041-40.298 3.7127-58.258 10.104-1.7959 0.63909-3.5465 1.3043-5.2402 1.998-3.1 1.2-6.0988 2.6016-8.7988 4.1016-2.2 1.2-4.3016 2.4988-6.1016 3.7988-21.6 15.5-27.9 44.2-28.6 65.4l14.9-10.5 14.301-10 51.199-35.9-49.1 39.301-14.1 11.299-14.801 11.801c20.4 6.5 52.4 9.7992 74.9-6.3008 3.1886-2.319 6.4708-5.1162 9.7559-8.459 0.14708-0.08175 0.29689-0.1571 0.44336-0.24023 2.3386-2.3386 4.7705-4.8714 7.0215-7.5898 0.02928-0.033868 0.05864-0.065681 0.08789-0.099609 0.0964-0.038723 0.1948-0.072111 0.29102-0.11133 14.544-16.737 27.833-39.152 32.252-55.658 0.67979-2.5395 1.1487-4.9387 1.3809-7.1562 0.11607-1.1088 0.17422-2.173 0.16797-3.1855-1.0438-0.3625-2.1849-0.68557-3.4121-0.9707-1.2272-0.28513-2.542-0.53096-3.9336-0.74024s-2.8595-0.38069-4.3965-0.51562c-3.0739-0.26987-6.4198-0.39341-9.9609-0.375zm-202.79 20.252c-11.737-0.05-22.113 1.4004-28.312 4.6504 0.9 5.6625 4.3309 13.419 9.3125 21.77v0.001953c3.3209 5.5664 7.332 11.395 11.74 17.043v0.001953c6.6127 8.4716 14.122 16.534 21.547 22.684 2.3 1.9 4.5008 3.5996 6.8008 5.0996 0.048555 0.0124 0.097907 0.019 0.14648 0.03125 1.7845 1.2837 3.569 2.2777 5.3535 3.1699 20.8 10.4 45.5 3.7984 62.1-4.1016l-14.301-7.2988-13.6-6.9004-48.127-24.607 49.928 21.707 14.5 6.3008 15.199 6.5996c-3.4-18.3-14.099-44-35.799-54.9-3.3-1.6-6.9004-3.1004-10.9-4.4004-2.9-0.9-5.8996-1.7-9.0996-2.5-11.65-2.75-24.751-4.2996-36.488-4.3496zm97.488 73.85 3.6992 13.9 3.5996 13.201 12.801 47.6-15.9-47-4.5-13.4-4.8008-14.199c-10.3 13.4-21.3 36.199-15.5 57.199 0.8747 3.11 2.1333 6.3182 3.6719 9.709 0.01066 0.06374 0.01836 0.12769 0.0293 0.19141 1.1 2.5 2.3988 5.0992 3.7988 7.6992 10.4 18.8 27.701 38.501 39.701 42.801 0.00763-0.00936 0.01581-0.01991 0.02344-0.0293 0.02502 0.00909 0.05119 0.02035 0.07617 0.0293 8.8-10.8 16.8-42.601 15.9-65.701-0.1-2.7-0.30117-5.2992-0.70117-7.6992-0.3-1.9-0.69922-3.8-1.1992-5.5-5.6-20.2-25.199-32.601-40.699-38.801z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
43
package-lock.json
generated
@ -25,7 +25,7 @@
|
||||
"bootstrap": "5.3.3",
|
||||
"boxicons": "2.1.4",
|
||||
"cheerio": "1.0.0",
|
||||
"chokidar": "4.0.1",
|
||||
"chokidar": "4.0.2",
|
||||
"cls-hooked": "4.2.2",
|
||||
"codemirror": "5.65.18",
|
||||
"compression": "1.7.5",
|
||||
@ -42,7 +42,7 @@
|
||||
"escape-html": "1.0.3",
|
||||
"eslint": "9.17.0",
|
||||
"express": "4.21.2",
|
||||
"express-rate-limit": "7.4.1",
|
||||
"express-rate-limit": "7.5.0",
|
||||
"express-session": "1.18.1",
|
||||
"force-graph": "1.47.1",
|
||||
"fs-extra": "11.2.0",
|
||||
@ -51,7 +51,7 @@
|
||||
"html2plaintext": "2.1.4",
|
||||
"http-proxy-agent": "7.0.2",
|
||||
"https-proxy-agent": "7.0.6",
|
||||
"i18next": "24.1.0",
|
||||
"i18next": "24.1.2",
|
||||
"i18next-fs-backend": "2.6.0",
|
||||
"i18next-http-backend": "3.0.1",
|
||||
"image-type": "5.2.0",
|
||||
@ -65,10 +65,10 @@
|
||||
"jquery.fancytree": "2.38.3",
|
||||
"jsdom": "25.0.1",
|
||||
"jsplumb": "2.15.6",
|
||||
"katex": "0.16.15",
|
||||
"katex": "0.16.17",
|
||||
"knockout": "3.5.1",
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "15.0.3",
|
||||
"marked": "15.0.4",
|
||||
"mermaid": "11.4.1",
|
||||
"mime-types": "2.1.35",
|
||||
"mind-elixir": "4.3.3",
|
||||
@ -5694,9 +5694,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz",
|
||||
"integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==",
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.2.tgz",
|
||||
"integrity": "sha512-/b57FK+bblSU+dfewfFe0rT1YjVDfOmeLQwCAuC+vwvgLkXboATqqmy+Ipux6JrF6L5joe5CBnFOw+gLWH6yKg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"readdirp": "^4.0.1"
|
||||
@ -8390,9 +8390,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/express-rate-limit": {
|
||||
"version": "7.4.1",
|
||||
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.4.1.tgz",
|
||||
"integrity": "sha512-KS3efpnpIDVIXopMc65EMbWbUht7qvTCdtCR2dD/IZmi9MIkopYESwyRqLgv8Pfu589+KqDqOdzJWW7AHoACeg==",
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz",
|
||||
"integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
@ -8400,7 +8401,7 @@
|
||||
"url": "https://github.com/sponsors/express-rate-limit"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"express": "4 || 5 || ^5.0.0-beta.1"
|
||||
"express": "^4.11 || 5 || ^5.0.0-beta.1"
|
||||
}
|
||||
},
|
||||
"node_modules/express-session": {
|
||||
@ -9912,9 +9913,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/i18next": {
|
||||
"version": "24.1.0",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-24.1.0.tgz",
|
||||
"integrity": "sha512-suKlX82AlptkMUO5YRfaAeH4FQyyKvR66jNaubTMiyPPMx7INU6PXAiy3PGULc0q6K+t9nxmDf/TRj9KjAivmw==",
|
||||
"version": "24.1.2",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-24.1.2.tgz",
|
||||
"integrity": "sha512-th/075GW0Ub1gYDMHLiZXMGSfGv1aP1VqjT3fma/12hNHCNlH8oJMftvlDzycT/R+KoULWk+xLU8H1JRwV85qw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@ -11723,9 +11724,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/katex": {
|
||||
"version": "0.16.15",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.15.tgz",
|
||||
"integrity": "sha512-yE9YJIEAk2aZ+FL/G8r+UGw0CTUzEA8ZFy6E+8tc3spHUKq3qBnzCkI1CQwGoI9atJhVyFPEypQsTY7mJ1Pi9w==",
|
||||
"version": "0.16.17",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.17.tgz",
|
||||
"integrity": "sha512-OyzSrXBllz+Jdc9Auiw0kt21gbZ4hkz8Q5srVAb2U9INcYIfGKbxe+bvNvEz1bQ/NrDeRRho5eLCyk/L03maAw==",
|
||||
"funding": [
|
||||
"https://opencollective.com/katex",
|
||||
"https://github.com/sponsors/katex"
|
||||
@ -12281,9 +12282,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "15.0.3",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.3.tgz",
|
||||
"integrity": "sha512-Ai0cepvl2NHnTcO9jYDtcOEtVBNVYR31XnEA3BndO7f5As1wzpcOceSUM8FDkNLJNIODcLpDTWay/qQhqbuMvg==",
|
||||
"version": "15.0.4",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.4.tgz",
|
||||
"integrity": "sha512-TCHvDqmb3ZJ4PWG7VEGVgtefA5/euFmsIhxtD0XsBxI39gUSKL81mIRFdt0AiNQozUahd4ke98ZdirExd/vSEw==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
|
10
package.json
@ -68,7 +68,7 @@
|
||||
"bootstrap": "5.3.3",
|
||||
"boxicons": "2.1.4",
|
||||
"cheerio": "1.0.0",
|
||||
"chokidar": "4.0.1",
|
||||
"chokidar": "4.0.2",
|
||||
"cls-hooked": "4.2.2",
|
||||
"codemirror": "5.65.18",
|
||||
"compression": "1.7.5",
|
||||
@ -85,7 +85,7 @@
|
||||
"escape-html": "1.0.3",
|
||||
"eslint": "9.17.0",
|
||||
"express": "4.21.2",
|
||||
"express-rate-limit": "7.4.1",
|
||||
"express-rate-limit": "7.5.0",
|
||||
"express-session": "1.18.1",
|
||||
"force-graph": "1.47.1",
|
||||
"fs-extra": "11.2.0",
|
||||
@ -94,7 +94,7 @@
|
||||
"html2plaintext": "2.1.4",
|
||||
"http-proxy-agent": "7.0.2",
|
||||
"https-proxy-agent": "7.0.6",
|
||||
"i18next": "24.1.0",
|
||||
"i18next": "24.1.2",
|
||||
"i18next-fs-backend": "2.6.0",
|
||||
"i18next-http-backend": "3.0.1",
|
||||
"image-type": "5.2.0",
|
||||
@ -108,10 +108,10 @@
|
||||
"jquery.fancytree": "2.38.3",
|
||||
"jsdom": "25.0.1",
|
||||
"jsplumb": "2.15.6",
|
||||
"katex": "0.16.15",
|
||||
"katex": "0.16.17",
|
||||
"knockout": "3.5.1",
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "15.0.3",
|
||||
"marked": "15.0.4",
|
||||
"mermaid": "11.4.1",
|
||||
"mime-types": "2.1.35",
|
||||
"mind-elixir": "4.3.3",
|
||||
|
52
spec/services/export/md.spec.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import markdownExportService from "../../../src/services/export/md.js";
|
||||
import { trimIndentation } from "../../support/utils.js";
|
||||
|
||||
describe("Markdown export", () => {
|
||||
it("trims language tag for code blocks", () => {
|
||||
const html = trimIndentation`\
|
||||
<p>A diff:</p>
|
||||
<pre><code class="language-text-x-diff">Hello
|
||||
-world
|
||||
+worldy
|
||||
</code></pre>`;
|
||||
const expected = trimIndentation`\
|
||||
A diff:
|
||||
|
||||
\`\`\`diff
|
||||
Hello
|
||||
-world
|
||||
+worldy
|
||||
|
||||
\`\`\``;
|
||||
|
||||
expect(markdownExportService.toMarkdown(html)).toBe(expected);
|
||||
});
|
||||
|
||||
it("removes auto tag for code blocks", () => {
|
||||
const html = trimIndentation`\
|
||||
<pre><code class="language-text-x-trilium-auto">Hello
|
||||
-world
|
||||
+worldy
|
||||
</code></pre>`;
|
||||
const expected = trimIndentation`\
|
||||
\`\`\`
|
||||
Hello
|
||||
-world
|
||||
+worldy
|
||||
|
||||
\`\`\``;
|
||||
|
||||
expect(markdownExportService.toMarkdown(html)).toBe(expected);
|
||||
});
|
||||
|
||||
it("supports code block with no language tag", () => {
|
||||
const html = trimIndentation`\
|
||||
<pre><code>Hello</code></pre>`;
|
||||
const expected = trimIndentation`\
|
||||
\`\`\`
|
||||
Hello
|
||||
\`\`\``;
|
||||
|
||||
expect(markdownExportService.toMarkdown(html)).toBe(expected);
|
||||
});
|
||||
});
|
14
spec/support/utils.spec.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { trimIndentation } from "./utils.js";
|
||||
|
||||
describe("Utils", () => {
|
||||
it("trims indentation", () => {
|
||||
expect(trimIndentation`\
|
||||
Hello
|
||||
world
|
||||
123`
|
||||
).toBe(`\
|
||||
Hello
|
||||
world
|
||||
123`);
|
||||
});
|
||||
});
|
21
spec/support/utils.ts
Normal file
@ -0,0 +1,21 @@
|
||||
export function trimIndentation(strings: TemplateStringsArray) {
|
||||
const str = strings.toString();
|
||||
|
||||
// Count the number of spaces on the first line.
|
||||
let numSpaces = 0;
|
||||
while (str.charAt(numSpaces) == ' ' && numSpaces < str.length) {
|
||||
numSpaces++;
|
||||
}
|
||||
|
||||
// Trim the indentation of the first line in all the lines.
|
||||
const lines = str.split("\n");
|
||||
const output = [];
|
||||
for (let i=0; i<lines.length; i++) {
|
||||
let numSpacesLine = 0;
|
||||
while (str.charAt(numSpacesLine) == ' ' && numSpacesLine < str.length) {
|
||||
numSpacesLine++;
|
||||
}
|
||||
output.push(lines[i].substring(numSpacesLine));
|
||||
}
|
||||
return output.join("\n");
|
||||
}
|
@ -57,7 +57,7 @@ app.use(`/icon.png`, express.static(path.join(scriptDir, 'public/icon.png')));
|
||||
app.use(sessionParser);
|
||||
app.use(favicon(`${scriptDir}/../images/app-icons/icon.ico`));
|
||||
|
||||
assets.register(app);
|
||||
await assets.register(app);
|
||||
routes.register(app);
|
||||
custom.register(app);
|
||||
error_handlers.register(app);
|
||||
|
@ -98,7 +98,7 @@ class BAttachment extends AbstractBeccaEntity<BAttachment> {
|
||||
|
||||
/** @returns true if the note has string content (not binary) */
|
||||
hasStringContent(): boolean {
|
||||
return this.type !== undefined && utils.isStringNote(this.type, this.mime);
|
||||
return utils.isStringNote(this.type, this.mime); // here was !== undefined && utils.isStringNote(this.type, this.mime); I dont know why we need !=undefined. But it filters out canvas libary items
|
||||
}
|
||||
|
||||
isContentAvailable() {
|
||||
|
@ -85,6 +85,7 @@ export default class RootCommandExecutor extends Component {
|
||||
|
||||
async showLaunchBarSubtreeCommand() {
|
||||
await this.showAndHoistSubtree('_lbRoot');
|
||||
this.showLeftPaneCommand();
|
||||
}
|
||||
|
||||
async showShareSubtreeCommand() {
|
||||
|
@ -227,7 +227,7 @@ export default class RibbonContainer extends NoteContextAwareWidget {
|
||||
.attr('data-ribbon-component-name', ribbonWidget.name)
|
||||
.append($('<span class="ribbon-tab-title-icon">')
|
||||
.addClass(ret.icon)
|
||||
.attr("data-title", ret.title)
|
||||
.attr("title", ret.title)
|
||||
.attr('data-toggle-command', ribbonWidget.toggleCommand))
|
||||
.append(" ")
|
||||
.append($('<span class="ribbon-tab-title-label">').text(ret.title));
|
||||
|
@ -12,7 +12,7 @@ const TPL = `
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">${t("about.title")}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('about.close')}"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<table class="table table-borderless text-nowrap">
|
||||
|
@ -45,8 +45,8 @@ const TPL = `
|
||||
<h4>${t('bulk_actions.affected_notes')}: <span class="affected-note-count">0</span></h4>
|
||||
|
||||
<div class="form-check">
|
||||
<input class="include-descendants form-check-input" type="checkbox" value="">
|
||||
<label class="form-check-label">${t('bulk_actions.include_descendants')}</label>
|
||||
<input id="include-descendants" class="include-descendants form-check-input" type="checkbox" value="">
|
||||
<label for="include-descendants" class="form-check-label">${t('bulk_actions.include_descendants')}</label>
|
||||
</div>
|
||||
|
||||
<h4>${t('bulk_actions.available_actions')}</h4>
|
||||
|
@ -15,7 +15,7 @@ const TPL = `
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title flex-grow-1">${t('clone_to.clone_notes_to')}</h5>
|
||||
<button type="button" class="help-button" title="${t('clone_to.help_on_links')}" data-help-page="cloning-notes.html">?</button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('clone_to.close')}"></button>
|
||||
</div>
|
||||
<form class="clone-to-form">
|
||||
<div class="modal-body">
|
||||
|
@ -9,7 +9,7 @@ const TPL = `
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">${t('confirm.confirmation')}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('confirm.close')}"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="confirm-dialog-content"></div>
|
||||
|
@ -11,17 +11,17 @@ const TPL = `
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">${t('delete_notes.delete_notes_preview')}</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('delete_notes.close')}"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-checkbox">
|
||||
<input class="delete-all-clones form-check-input" value="1" type="checkbox">
|
||||
<label class="form-check-label">${t('delete_notes.delete_all_clones_description')}</label>
|
||||
<input id="delete-all-clones" class="delete-all-clones form-check-input" value="1" type="checkbox">
|
||||
<label for="delete-all-clones" class="form-check-label">${t('delete_notes.delete_all_clones_description')}</label>
|
||||
</div>
|
||||
|
||||
<div class="form-checkbox" style="margin-bottom: 1rem">
|
||||
<input class="erase-notes form-check-input" value="1" type="checkbox">
|
||||
<label class="form-check-label">${t('delete_notes.erase_notes_warning')}</label>
|
||||
<input id="erase-notes" class="erase-notes form-check-input" value="1" type="checkbox">
|
||||
<label for="erase-notes" class="form-check-label">${t('delete_notes.erase_notes_warning')}</label>
|
||||
</div>
|
||||
|
||||
<div class="delete-notes-list-wrapper">
|
||||
|
@ -11,7 +11,7 @@ const TPL = `
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">${t('include_note.dialog_title')}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('include_note.close')}"></button>
|
||||
</div>
|
||||
<form class="include-note-form">
|
||||
<div class="modal-body">
|
||||
|
@ -12,7 +12,7 @@ const TPL = `<div class="jump-to-note-dialog modal mx-auto" tabindex="-1" role="
|
||||
<div class="input-group">
|
||||
<input class="jump-to-note-autocomplete form-control" placeholder="${t('jump_to_note.search_placeholder')}">
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('jump_to_note.close')}"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="algolia-autocomplete-container jump-to-note-results"></div>
|
||||
|
@ -12,7 +12,7 @@ const TPL = `
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">${t("markdown_import.dialog_title")}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("markdown_import.close")}"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>${t("markdown_import.modal_body_text")}</p>
|
||||
|
@ -13,7 +13,7 @@ const TPL = `
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title me-auto">${t("move_to.dialog_title")}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("move_to.close")}"></button>
|
||||
</div>
|
||||
<form class="move-to-form">
|
||||
<div class="modal-body">
|
||||
|
@ -24,7 +24,7 @@ const TPL = `
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">${t("note_type_chooser.modal_title")}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("note_type_chooser.close")}"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
${t("note_type_chooser.modal_body")}
|
||||
|
@ -8,7 +8,7 @@ const TPL = `
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">${t("password_not_set.title")}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("password_not_set.close")}"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
${t("password_not_set.body1")}
|
||||
|
@ -9,7 +9,7 @@ const TPL = `
|
||||
<form class="prompt-dialog-form">
|
||||
<div class="modal-header">
|
||||
<h5 class="prompt-title modal-title">${t("prompt.title")}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('prompt.close')}"></button>
|
||||
</div>
|
||||
<div class="modal-body"></div>
|
||||
<div class="modal-footer">
|
||||
|
@ -14,8 +14,8 @@ const TPL = `
|
||||
</div>
|
||||
<form class="protected-session-password-form">
|
||||
<div class="modal-body">
|
||||
<label class="col-form-label">${t("protected_session_password.form_label")}</label>
|
||||
<input class="form-control protected-session-password" type="password">
|
||||
<label for="protected-session-password" class="col-form-label">${t("protected_session_password.form_label")}asbd</label>
|
||||
<input id="protected-session-password" class="form-control protected-session-password" type="password">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary">${t("protected_session_password.start_button")}</button>
|
||||
|
@ -18,7 +18,7 @@ const TPL = `
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title flex-grow-1">${t('recent_changes.title')}</h5>
|
||||
<button class="erase-deleted-notes-now-button btn btn-sm" style="padding: 0 10px">${t('recent_changes.erase_notes_button')}</button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('recent_changes.close')}"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="recent-changes-content"></div>
|
||||
|
@ -46,7 +46,7 @@ const TPL = `
|
||||
title="${t("revisions.delete_all_revisions")}"
|
||||
style="padding: 0 10px 0 10px;" type="button">${t("revisions.delete_all_button")}</button>
|
||||
<button class="help-button" type="button" data-help-page="note-revisions.html" title="${t("revisions.help_title")}">?</button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("revisions.close")}"></button>
|
||||
</div>
|
||||
<div class="modal-body" style="display: flex; height: 80vh;">
|
||||
<div class="dropdown">
|
||||
|
@ -8,44 +8,44 @@ const TPL = `<div class="sort-child-notes-dialog modal mx-auto" tabindex="-1" ro
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">${t("sort_child_notes.sort_children_by")}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("sort_child_notes.close")}"></button>
|
||||
</div>
|
||||
<form class="sort-child-notes-form">
|
||||
<div class="modal-body">
|
||||
<h5>${t("sort_child_notes.sorting_criteria")}</h5>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="sort-by" value="title" checked>
|
||||
<label class="form-check-label">${t("sort_child_notes.title")}</label>
|
||||
<input id="sort-by-title" class="form-check-input" type="radio" name="sort-by" value="title" checked>
|
||||
<label for="sort-by-title" class="form-check-label">${t("sort_child_notes.title")}</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="sort-by" value="dateCreated">
|
||||
<label class="form-check-label">${t("sort_child_notes.date_created")}</label>
|
||||
<input id="sort-by-dateCreated" class="form-check-input" type="radio" name="sort-by" value="dateCreated">
|
||||
<label for="sort-by-dateCreated" class="form-check-label">${t("sort_child_notes.date_created")}</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="sort-by" value="dateModified">
|
||||
<label class="form-check-label">${t("sort_child_notes.date_modified")}</label>
|
||||
<input id="sort-by-dateModified" class="form-check-input" type="radio" name="sort-by" value="dateModified">
|
||||
<label for="sort-by-dateModified" class="form-check-label">${t("sort_child_notes.date_modified")}</label>
|
||||
</div>
|
||||
<br/>
|
||||
<h5>${t("sort_child_notes.sorting_direction")}</h5>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="sort-direction" value="asc" checked>
|
||||
<label class="form-check-label">${t("sort_child_notes.ascending")}</label>
|
||||
<input id="sort-direction-asc" class="form-check-input" type="radio" name="sort-direction" value="asc" checked>
|
||||
<label for="sort-direction-asc" class="form-check-label">${t("sort_child_notes.ascending")}</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="sort-direction" value="desc">
|
||||
<label class="form-check-label">${t("sort_child_notes.descending")}</label>
|
||||
<input id="sort-direction-desc" class="form-check-input" type="radio" name="sort-direction" value="desc">
|
||||
<label for="sort-direction-desc" class="form-check-label">${t("sort_child_notes.descending")}</label>
|
||||
</div>
|
||||
<br />
|
||||
<h5>${t("sort_child_notes.folders")}</h5>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="sort-folders-first" value="1">
|
||||
<label class="form-check-label">${t("sort_child_notes.sort_folders_at_top")}</label>
|
||||
<input id="sort-folders-first" class="form-check-input" type="checkbox" name="sort-folders-first" value="1">
|
||||
<label for="sort-folders-first" class="form-check-label">${t("sort_child_notes.sort_folders_at_top")}</label>
|
||||
</div>
|
||||
<br />
|
||||
<h5>${t("sort_child_notes.natural_sort")}</h5>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="sort-natural" value="1">
|
||||
<label class="form-check-label">${t("sort_child_notes.sort_with_respect_to_different_character_sorting")}</label>
|
||||
<input id="sort-natural" class="form-check-input" type="checkbox" name="sort-natural" value="1">
|
||||
<label for="sort-natural" class="form-check-label">${t("sort_child_notes.sort_with_respect_to_different_character_sorting")}</label>
|
||||
</div>
|
||||
<br />
|
||||
<div class="form-check">
|
||||
|
@ -11,7 +11,7 @@ const TPL = `
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">${t("upload_attachments.upload_attachments_to_note")}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('upload_attachments.close')}"></button>
|
||||
</div>
|
||||
<form class="upload-attachment-form">
|
||||
<div class="modal-body">
|
||||
|
@ -76,7 +76,7 @@ export default class QuickSearchWidget extends BasicWidget {
|
||||
});
|
||||
|
||||
shortcutService.bindElShortcut(this.$searchString, 'down', () => {
|
||||
this.$dropdownMenu.find('.dropdown-item:first').focus();
|
||||
this.$dropdownMenu.find('.dropdown-item:not(.disabled):first').focus();
|
||||
});
|
||||
|
||||
shortcutService.bindElShortcut(this.$searchString, 'esc', () => {
|
||||
|
@ -96,7 +96,6 @@ export default class SyncStatusWidget extends BasicWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Align ", this.settings.titlePlacement);
|
||||
bootstrap.Tooltip.getOrCreateInstance(this.$widget.find(`.sync-status-${className}`), {
|
||||
html: true,
|
||||
placement: this.settings.titlePlacement,
|
||||
|
@ -116,7 +116,6 @@ const TAB_ROW_TPL = `
|
||||
|
||||
.tab-row-widget .note-tab,
|
||||
.tab-row-widget .note-tab * {
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
@ -177,6 +176,7 @@ const TAB_ROW_TPL = `
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.tab-row-widget .note-tab .note-tab-close {
|
||||
|
@ -22,7 +22,6 @@ export default class TemplateSwitchWidget extends SwitchWidget {
|
||||
this.$switchOffButton.attr("title", t("template_switch.toggle-off-hint"));
|
||||
|
||||
this.$helpButton.attr("data-help-page", "template.html").show();
|
||||
this.$helpButton.on('click', e => utils.openHelp($(e.target)));
|
||||
}
|
||||
|
||||
async switchOn() {
|
||||
|
@ -2,7 +2,7 @@ import libraryLoader from '../../services/library_loader.js';
|
||||
import TypeWidget from './type_widget.js';
|
||||
import utils from '../../services/utils.js';
|
||||
import linkService from '../../services/link.js';
|
||||
|
||||
import server from '../../services/server.js';
|
||||
const TPL = `
|
||||
<div class="canvas-widget note-detail-canvas note-detail-printable note-detail">
|
||||
<style>
|
||||
@ -115,6 +115,11 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
this.reactHandlers; // used to control react state
|
||||
|
||||
this.libraryChanged = false;
|
||||
|
||||
// these 2 variables are needed to compare the library state (all library items) after loading to the state when the library changed. So we can find attachments to be deleted.
|
||||
//every libraryitem is saved on its own json file in the attachments of the note.
|
||||
this.librarycache = [];
|
||||
this.attachmentMetadata=[]
|
||||
}
|
||||
|
||||
static getType() {
|
||||
@ -236,24 +241,48 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
fileArray.push(file);
|
||||
}
|
||||
|
||||
this.excalidrawApi.updateScene(sceneData);
|
||||
this.excalidrawApi.addFiles(fileArray);
|
||||
this.excalidrawApi.history.clear();
|
||||
}
|
||||
|
||||
Promise.all(
|
||||
(await note.getAttachmentsByRole('canvasLibraryItem'))
|
||||
.map(attachment => attachment.getBlob())
|
||||
).then(blobs => {
|
||||
.map(async attachment => {
|
||||
const blob = await attachment.getBlob();
|
||||
return {
|
||||
blob, // Save the blob for libraryItems
|
||||
metadata: { // metadata to use in the cache variables for comparing old library state and new one. We delete unnecessary items later, calling the server directly
|
||||
attachmentId: attachment.attachmentId,
|
||||
title: attachment.title,
|
||||
},
|
||||
};
|
||||
})
|
||||
).then(results => {
|
||||
if (note.noteId !== this.currentNoteId) {
|
||||
// current note changed in the course of the async operation
|
||||
return;
|
||||
}
|
||||
|
||||
const libraryItems = blobs.map(blob => blob.getJsonContentSafely()).filter(item => !!item);
|
||||
this.excalidrawApi.updateLibrary({libraryItems, merge: false});
|
||||
// Extract libraryItems from the blobs
|
||||
const libraryItems = results
|
||||
.map(result => result.blob.getJsonContentSafely())
|
||||
.filter(item => !!item);
|
||||
|
||||
// Extract metadata for each attachment
|
||||
const metadata = results.map(result => result.metadata);
|
||||
|
||||
// Update the library and save to independent variables
|
||||
this.excalidrawApi.updateLibrary({ libraryItems, merge: false });
|
||||
|
||||
// save state of library to compare it to the new state later.
|
||||
this.librarycache = libraryItems;
|
||||
this.attachmentMetadata = metadata;
|
||||
});
|
||||
|
||||
// Update the scene
|
||||
this.excalidrawApi.updateScene(sceneData);
|
||||
this.excalidrawApi.addFiles(fileArray);
|
||||
this.excalidrawApi.history.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// set initial scene version
|
||||
if (this.currentSceneVersion === this.SCENE_VERSION_INITIAL) {
|
||||
this.currentSceneVersion = this.getSceneVersion();
|
||||
@ -313,19 +342,54 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
|
||||
// there's no separate method to get library items, so have to abuse this one
|
||||
const libraryItems = await this.excalidrawApi.updateLibrary({merge: true});
|
||||
|
||||
// excalidraw saves the library as a own state. the items are saved to libraryItems. then we compare the library right now with a libraryitemcache. The cache is filled when we first load the Library into the note.
|
||||
//We need the cache to delete old attachments later in the server.
|
||||
|
||||
const libraryItemsMissmatch = this.librarycache.filter(obj1 => !libraryItems.some(obj2 => obj1.id === obj2.id));
|
||||
|
||||
|
||||
// before we saved the metadata of the attachments in a cache. the title of the attachment is a combination of libraryitem ´s ID und it´s name.
|
||||
// we compare the library items in the libraryitemmissmatch variable (this one saves all libraryitems that are different to the state right now. E.g. you delete 1 item, this item is saved as mismatch)
|
||||
// then we combine its id and title and search the according attachmentID.
|
||||
|
||||
const matchingItems = this.attachmentMetadata.filter(meta => {
|
||||
// Loop through the second array and check for a match
|
||||
return libraryItemsMissmatch.some(item => {
|
||||
// Combine the `name` and `id` from the second array
|
||||
const combinedTitle = `${item.id}${item.name}`;
|
||||
return meta.title === combinedTitle;
|
||||
});
|
||||
});
|
||||
|
||||
// we save the attachment ID`s in a variable and delete every attachmentID. Now the items that the user deleted will be deleted.
|
||||
const attachmentIds = matchingItems.map(item => item.attachmentId);
|
||||
|
||||
|
||||
|
||||
//delete old attachments that are no longer used
|
||||
for (const item of attachmentIds){
|
||||
|
||||
await server.remove(`attachments/${item}`);
|
||||
|
||||
}
|
||||
|
||||
let position = 10;
|
||||
|
||||
// prepare data to save to server e.g. new library items.
|
||||
for (const libraryItem of libraryItems) {
|
||||
|
||||
attachments.push({
|
||||
role: 'canvasLibraryItem',
|
||||
title: libraryItem.id,
|
||||
title: libraryItem.id + libraryItem.name,
|
||||
mime: 'application/json',
|
||||
content: JSON.stringify(libraryItem),
|
||||
position: position
|
||||
|
||||
});
|
||||
|
||||
position += 10;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -28,8 +28,8 @@ const TPL = `
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-6">
|
||||
<label>${t("highlighting.color-scheme")}</label>
|
||||
<select class="theme-select form-select"></select>
|
||||
<label for="highlighting-color-scheme-select">${t("highlighting.color-scheme")}</label>
|
||||
<select id="highlighting-color-scheme-select" class="theme-select form-select"></select>
|
||||
</div>
|
||||
|
||||
<div class="col-6 side-checkbox">
|
||||
|
@ -8,8 +8,8 @@ const TPL = `
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-12">
|
||||
<label>${t("electron_integration.zoom-factor")}</label>
|
||||
<input type="number" class="zoom-factor-select form-control options-number-input" min="0.3" max="2.0" step="0.1"/>
|
||||
<label for="zoom-factor-select">${t("electron_integration.zoom-factor")}</label>
|
||||
<input id="zoom-factor-select" type="number" class="zoom-factor-select form-control options-number-input" min="0.3" max="2.0" step="0.1"/>
|
||||
<p>${t("zoom_factor.description")}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -36,15 +36,15 @@ const TPL = `
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-6">
|
||||
<label>${t("fonts.font_family")}</label>
|
||||
<select class="main-font-family form-select"></select>
|
||||
<label for="main-font-family">${t("fonts.font_family")}</label>
|
||||
<select id="main-font-family" class="main-font-family form-select"></select>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<label>${t("fonts.size")}</label>
|
||||
<label for="main-font-size">${t("fonts.size")}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input type="number" class="main-font-size form-control options-number-input" min="50" max="200" step="10"/>
|
||||
<input id="main-font-size" type="number" class="main-font-size form-control options-number-input" min="50" max="200" step="10"/>
|
||||
<span class="input-group-text">%</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -54,15 +54,15 @@ const TPL = `
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-4">
|
||||
<label>${t("fonts.font_family")}</label>
|
||||
<select class="tree-font-family form-select"></select>
|
||||
<label for="tree-font-family">${t("fonts.font_family")}</label>
|
||||
<select id="tree-font-family" class="tree-font-family form-select"></select>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<label>${t("fonts.size")}</label>
|
||||
<label for="tree-font-size">${t("fonts.size")}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input type="number" class="tree-font-size form-control options-number-input" min="50" max="200" step="10"/>
|
||||
<input id="tree-font-size" type="number" class="tree-font-size form-control options-number-input" min="50" max="200" step="10"/>
|
||||
<span class="input-group-text">%</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -72,15 +72,15 @@ const TPL = `
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-4">
|
||||
<label>${t("fonts.font_family")}</label>
|
||||
<select class="detail-font-family form-select"></select>
|
||||
<label for="detail-font-family">${t("fonts.font_family")}</label>
|
||||
<select id="detail-font-family" class="detail-font-family form-select"></select>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<label>${t("fonts.size")}</label>
|
||||
<label for="detail-font-size">${t("fonts.size")}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input type="number" class="detail-font-size form-control options-number-input" min="50" max="200" step="10"/>
|
||||
<input id="detail-font-size" type="number" class="detail-font-size form-control options-number-input" min="50" max="200" step="10"/>
|
||||
<span class="input-group-text">%</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -90,15 +90,15 @@ const TPL = `
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-4">
|
||||
<label>${t("fonts.font_family")}</label>
|
||||
<select class="monospace-font-family form-select"></select>
|
||||
<label for="monospace-font-family">${t("fonts.font_family")}</label>
|
||||
<select id="monospace-font-family" class="monospace-font-family form-select"></select>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<label>${t("fonts.size")}</label>
|
||||
<label for="monospace-font-size">${t("fonts.size")}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input type="number" class="monospace-font-size form-control options-number-input" min="50" max="200" step="10"/>
|
||||
<input id="monospace-font-size" type="number" class="monospace-font-size form-control options-number-input" min="50" max="200" step="10"/>
|
||||
<span class="input-group-text">%</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -9,13 +9,13 @@ const TPL = `
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-6">
|
||||
<label>${t("i18n.language")}</label>
|
||||
<select class="locale-select form-select"></select>
|
||||
<label for="locale-select">${t("i18n.language")}</label>
|
||||
<select id="locale-select" class="locale-select form-select"></select>
|
||||
</div>
|
||||
|
||||
<div class="col-6">
|
||||
<label>${t("i18n.first-day-of-the-week")}</label>
|
||||
<select class="first-day-of-week-select form-select">
|
||||
<label for="first-day-of-week-select">${t("i18n.first-day-of-the-week")}</label>
|
||||
<select id="first-day-of-week-select" class="first-day-of-week-select form-select">
|
||||
<option value="0">${t("i18n.sunday")}</option>
|
||||
<option value="1">${t("i18n.monday")}</option>
|
||||
</select>
|
||||
|
@ -12,8 +12,8 @@ const TPL = `
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-6">
|
||||
<label>${t("max_content_width.max_width_label")}</label>
|
||||
<input type="number" min="${MIN_VALUE}" step="10" class="max-content-width form-control options-number-input">
|
||||
<label for="max-content-width">${t("max_content_width.max_width_label")}</label>
|
||||
<input id="max-content-width" type="number" min="${MIN_VALUE}" step="10" class="max-content-width form-control options-number-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -31,8 +31,8 @@ const TPL = `
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-6">
|
||||
<label>${t("theme.theme_label")}</label>
|
||||
<select class="theme-select form-select"></select>
|
||||
<label for="theme-select">${t("theme.theme_label")}</label>
|
||||
<select id="theme-select" class="theme-select form-select"></select>
|
||||
</div>
|
||||
|
||||
<div class="col-6 side-checkbox">
|
||||
@ -69,6 +69,9 @@ export default class ThemeOptions extends OptionsWidget {
|
||||
async optionsLoaded(options) {
|
||||
const themes = [
|
||||
{ val: 'next', title: t("theme.triliumnext") },
|
||||
{ val: 'next-light', title: t("theme.triliumnext-light") },
|
||||
{ val: 'next-dark', title: t("theme.triliumnext-dark") },
|
||||
{ val: 'auto', title: t('theme.auto_theme') },
|
||||
{ val: 'light', title: t('theme.light_theme') },
|
||||
{ val: 'dark', title: t('theme.dark_theme') }
|
||||
].concat(await server.get('options/user-themes'));
|
||||
|
@ -8,8 +8,8 @@ const TPL = `
|
||||
<p>${t('code_auto_read_only_size.description')}</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>${t('code_auto_read_only_size.label')}</label>
|
||||
<input class="auto-readonly-size-code form-control options-number-input" type="number" min="0">
|
||||
<label for="auto-readonly-size-code">${t('code_auto_read_only_size.label')}</label>
|
||||
<input id="auto-readonly-size-code" class="auto-readonly-size-code form-control options-number-input" type="number" min="0">
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
@ -10,8 +10,8 @@ const TPL = `
|
||||
|
||||
<form class="sync-setup-form">
|
||||
<div class="form-group">
|
||||
<label>${t("search_engine.predefined_templates_label")}</label>
|
||||
<select class="predefined-search-engine-select form-control">
|
||||
<label for="predefined-search-engine-select">${t("search_engine.predefined_templates_label")}</label>
|
||||
<select id="predefined-search-engine-select" class="predefined-search-engine-select form-control">
|
||||
<option value="Bing">${t("search_engine.bing")}</option>
|
||||
<option value="Baidu">${t("search_engine.baidu")}</option>
|
||||
<option value="DuckDuckGo">${t("search_engine.duckduckgo")}</option>
|
||||
|
@ -14,18 +14,18 @@ const TPL = `
|
||||
|
||||
<form class="change-password-form">
|
||||
<div class="old-password-form-group form-group">
|
||||
<label>${t("password.old_password")}</label>
|
||||
<input class="old-password form-control" type="password">
|
||||
<label for="old-password">${t("password.old_password")}</label>
|
||||
<input id="old-password" class="old-password form-control" type="password">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>${t("password.new_password")}</label>
|
||||
<input class="new-password1 form-control" type="password">
|
||||
<label for="new-password1">${t("password.new_password")}</label>
|
||||
<input id="new-password1" class="new-password1 form-control" type="password">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>${t("password.new_password_confirmation")}</label>
|
||||
<input class="new-password2 form-control" type="password">
|
||||
<label for="new-password2">${t("password.new_password_confirmation")}</label>
|
||||
<input id="new-password2" class="new-password2 form-control" type="password">
|
||||
</div>
|
||||
|
||||
<button class="save-password-button btn btn-primary">${t("password.change_password")}</button>
|
||||
@ -38,8 +38,8 @@ const TPL = `
|
||||
<p>${t("password.protected_session_timeout_description")} <a href="https://triliumnext.github.io/Docs/Wiki/protected-notes.html" class="external">${t("password.wiki")}</a> ${t("password.for_more_info")}</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>${t("password.protected_session_timeout_label")}</label>
|
||||
<input class="protected-session-timeout-in-seconds form-control options-number-input" type="number" min="60">
|
||||
<label for="protected-session-timeout-in-seconds">${t("password.protected_session_timeout_label")}</label>
|
||||
<input id="protected-session-timeout-in-seconds" class="protected-session-timeout-in-seconds form-control options-number-input" type="number" min="60">
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
@ -24,8 +24,8 @@ const TPL_ELECTRON = `
|
||||
<br/>
|
||||
|
||||
<div class="form-group">
|
||||
<label>${t('spellcheck.language_code_label')}</label>
|
||||
<input type="text" class="spell-check-language-code form-control" placeholder="${t('spellcheck.language_code_placeholder')}">
|
||||
<label for="spell-check-language-code">${t('spellcheck.language_code_label')}</label>
|
||||
<input id="spell-check-language-code" type="text" class="spell-check-language-code form-control" placeholder="${t('spellcheck.language_code_placeholder')}">
|
||||
</div>
|
||||
|
||||
<p>${t('spellcheck.multiple_languages_info')}</p>
|
||||
|
@ -9,18 +9,18 @@ const TPL = `
|
||||
|
||||
<form class="sync-setup-form">
|
||||
<div class="form-group">
|
||||
<label>${t('sync_2.server_address')}</label>
|
||||
<input class="sync-server-host form-control" placeholder="https://<host>:<port>">
|
||||
<label for="sync-server-host" >${t('sync_2.server_address')}</label>
|
||||
<input id="sync-server-host" class="sync-server-host form-control" placeholder="https://<host>:<port>">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>${t('sync_2.timeout')}</label>
|
||||
<input class="sync-server-timeout form-control" min="1" max="10000000" type="number" style="text-align: left;">
|
||||
<label for="sync-server-timeout" >${t('sync_2.timeout')}</label>
|
||||
<input id="sync-server-timeout" class="sync-server-timeout form-control" min="1" max="10000000" type="number" style="text-align: left;">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>${t('sync_2.proxy_label')}</label>
|
||||
<input class="sync-proxy form-control" placeholder="https://<host>:<port>">
|
||||
<label for="sync-proxy form-control" >${t('sync_2.proxy_label')}</label>
|
||||
<input id="sync-proxy form-control" class="sync-proxy form-control" placeholder="https://<host>:<port>">
|
||||
|
||||
<p><strong>${t('sync_2.note')}:</strong> ${t('sync_2.note_description')}</p>
|
||||
<p>${t('sync_2.special_value_description')}</p>
|
||||
|
@ -8,8 +8,8 @@ const TPL = `
|
||||
<p>${t("text_auto_read_only_size.description")}</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>${t("text_auto_read_only_size.label")}</label>
|
||||
<input class="auto-readonly-size-text form-control options-number-input" type="number" min="0">
|
||||
<label for="auto-readonly-size-text">${t("text_auto_read_only_size.label")}</label>
|
||||
<input id="auto-readonly-size-text" class="auto-readonly-size-text form-control options-number-input" type="number" min="0">
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
|
170
src/public/stylesheets/theme-next-dark.css
Normal file
@ -0,0 +1,170 @@
|
||||
/* Import the Next theme base style */
|
||||
@import url(./theme-next/base.css);
|
||||
|
||||
/*
|
||||
* Color scheme
|
||||
*/
|
||||
:root {
|
||||
--theme-style: dark;
|
||||
--native-titlebar-background: #00000000;
|
||||
|
||||
--main-background-color: #333;
|
||||
--main-text-color: #ccc;
|
||||
--main-border-color: #454545;
|
||||
--subtle-border-color: #313131;
|
||||
--dropdown-border-color: #292929;
|
||||
--dropdown-shadow-opacity: .6;
|
||||
--dropdown-item-icon-destructive-color: #de6e5b;
|
||||
--disabled-tooltip-icon-color: #7fd2ef;
|
||||
|
||||
|
||||
--accented-background-color: #555;
|
||||
|
||||
--button-background-color: transparent;
|
||||
--button-border-color: #ccc;
|
||||
--button-text-color: currentColor;
|
||||
--button-border-radius: 5px;
|
||||
--button-disabled-background-color: transparent;
|
||||
--button-disabled-text-color: #999;
|
||||
|
||||
--primary-button-background-color: #888;
|
||||
--primary-button-text-color: white;
|
||||
--primary-button-border-color: #999;
|
||||
|
||||
--muted-text-color: #bbb;
|
||||
|
||||
--input-text-color: #ccc;
|
||||
--input-background-color: #333;
|
||||
|
||||
--hover-item-text-color: #efefef;
|
||||
--hover-item-background-color: #ffffff24;
|
||||
--hover-item-border-color: transparent;
|
||||
|
||||
--active-item-text-color: var(--left-pane-text-color);
|
||||
--active-item-background-color: #777;
|
||||
--active-item-border-color: transparent;
|
||||
|
||||
--new-tab-button-background: #fff0;
|
||||
--new-tab-button-color: #ffffff96;
|
||||
--new-tab-button-shadow: 2px 2px 4px rgba(0, 0, 0, .4);
|
||||
--new-tab-button-hover-background: #fff3;
|
||||
--new-tab-button-hover-color: white;
|
||||
|
||||
--menu-text-color: #e3e3e3;
|
||||
--menu-background-color: #222222d9;
|
||||
--menu-item-icon-color: #8c8c8c;
|
||||
--menu-item-disabled-opacity: .5;
|
||||
--menu-item-keyboard-shortcut-color: #ffffff8f;
|
||||
--menu-item-arrow-color: #ffffffa3;
|
||||
--menu-item-delimiter-color: #ffffff1c;
|
||||
|
||||
|
||||
--modal-background-color: #333;
|
||||
--modal-backdrop-color: #444;
|
||||
|
||||
--quick-search-background: #ffffff12;
|
||||
--quick-search-color: #ffffff52;
|
||||
--quick-search-hover-background: #ffffff1f;
|
||||
--quick-search-focus-border: #80808095;
|
||||
--quick-search-focus-background: #ffffff1f;
|
||||
--quick-search-focus-color: white;
|
||||
|
||||
--left-pane-collapsed-border-color: #0009;
|
||||
--left-pane-background-color: #1f1f1f;
|
||||
--left-pane-text-color: #AAAAAA;
|
||||
--left-pane-item-hover-background: #ffffff0d;
|
||||
--left-pane-item-selected-background: #ffffff25;
|
||||
--left-pane-item-selected-color: #dfdfdf;
|
||||
--left-pane-item-selected-shadow: 1px 1px 2px rgba(0, 0, 0, .6);
|
||||
--left-pane-item-action-button-background: #ffffff73;
|
||||
--left-pane-item-action-button-color: black;
|
||||
--left-pane-item-action-button-hover-background: #ffffffad;
|
||||
--left-pane-item-action-button-hover-shadow: 2px 2px 3px rgba(0, 0, 0, .15);
|
||||
--left-pane-item-selected-action-button-hover-shadow: 2px 2px 10px rgba(0, 0, 0, .25);
|
||||
|
||||
--launcher-pane-background-color: #1a1a1a;
|
||||
--launcher-pane-horizontal-background-color: #282828;
|
||||
--launcher-pane-horizontal-border-color: rgb(22, 22, 22);
|
||||
--launcher-pane-text-color: #909090;
|
||||
--launcher-pane-button-hover-color: #ffffff;
|
||||
--launcher-pane-button-hover-background: #ffffff1c;
|
||||
--launcher-pane-button-hover-shadow: 4px 4px 4px rgba(0, 0, 0, .2);
|
||||
|
||||
--protected-session-active-icon-color: #8edd8e;
|
||||
--sync-status-error-pulse-color: #f47871;
|
||||
|
||||
--root-background: var(--left-pane-background-color);
|
||||
|
||||
--gutter-color: transparent;
|
||||
--gutter-hover-color: #626262;
|
||||
|
||||
--tab-close-button-hover-background: #a45353;
|
||||
--tab-close-button-hover-color: white;
|
||||
|
||||
--active-tab-background-color: #ffffff1c;
|
||||
--active-tab-hover-background-color: var(--active-tab-background-color);
|
||||
--active-tab-text-color: #ffffffcd;
|
||||
--active-tab-shadow: 3px 3px 6px rgba(0, 0, 0, .2), -1px -1px 3px rgba(0, 0, 0, .4);
|
||||
--active-tab-dragging-shadow: var(--active-tab-shadow), 0 0 20px rgba(0, 0, 0, .4);
|
||||
|
||||
--inactive-tab-background-color: transparent;
|
||||
--inactive-tab-hover-background-color: #ffffff0f;
|
||||
--inactive-tab-text-color: #7c7c7c;
|
||||
|
||||
--right-pane-item-hover-background: #ffffff26;
|
||||
--right-pane-item-hover-color: white;
|
||||
|
||||
--scrollbar-border-color: #666;
|
||||
--scrollbar-background-color: #333;
|
||||
--link-color: lightskyblue;
|
||||
|
||||
--mermaid-theme: dark;
|
||||
|
||||
--code-block-box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.6);
|
||||
|
||||
--card-background-color: #363636;
|
||||
--card-background-hover-color: #3c3c3c;
|
||||
--card-background-press-color: #464646;
|
||||
--card-border-color: #222222;
|
||||
--card-box-shadow: 0 0 12px rgba(0, 0, 0, 0.15);
|
||||
|
||||
--calendar-color: var(--menu-text-color);
|
||||
--calendar-weekday-labels-color: var(--muted-text-color);
|
||||
--calendar-day-hover-color: var(--hover-item-text-color);
|
||||
--calendar-day-hover-background: var(--active-item-background-color);
|
||||
--calendar-day-highlight-background: #8080805a;
|
||||
|
||||
--timeline-bullet-color: gray;
|
||||
--timeline-bullet-hover-color: white;
|
||||
--timeline-connector-color: #464646;
|
||||
--timeline-connector-active-color: #545454;
|
||||
--timeline-connector-hover-blend-mode: exclusion;
|
||||
|
||||
--tooltip-background-color: rgba(67, 67, 67, 0.86);
|
||||
--tooltip-foreground-color: #ffffffeb;
|
||||
--tooltip-shadow-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dark color scheme tweaks
|
||||
*/
|
||||
|
||||
body ::-webkit-calendar-picker-indicator {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
body .CodeMirror {
|
||||
filter: invert(90%) hue-rotate(180deg);
|
||||
}
|
||||
|
||||
.excalidraw.theme--dark {
|
||||
--theme-filter: invert(80%) hue-rotate(180deg) !important;
|
||||
}
|
||||
|
||||
body .todo-list input[type="checkbox"]:not(:checked):before {
|
||||
border-color: var(--muted-text-color) !important;
|
||||
}
|
||||
|
||||
.btn-close {
|
||||
filter: invert(1);
|
||||
}
|
145
src/public/stylesheets/theme-next-light.css
Normal file
@ -0,0 +1,145 @@
|
||||
/* Import the Next theme base style */
|
||||
@import url(./theme-next/base.css);
|
||||
|
||||
/*
|
||||
* Color scheme
|
||||
*/
|
||||
:root {
|
||||
--theme-style: light;
|
||||
--native-titlebar-background: #ffffff00;
|
||||
|
||||
--main-background-color: white;
|
||||
--main-text-color: black;
|
||||
--main-border-color: #dbdbdb;
|
||||
--subtle-border-color: rgba(0, 0, 0, 0.1);
|
||||
--dropdown-border-color: #ccc;
|
||||
--dropdown-shadow-opacity: .2;
|
||||
--dropdown-item-icon-destructive-color: #ec5138;
|
||||
--disabled-tooltip-icon-color: #004382;
|
||||
|
||||
--accented-background-color: #f5f5f5;
|
||||
|
||||
--button-background-color: transparent;
|
||||
--button-border-color: #ddd;
|
||||
--button-text-color: black;
|
||||
--button-border-radius: 5px;
|
||||
--button-disabled-background-color: #ddd;
|
||||
--button-disabled-text-color: black;
|
||||
|
||||
--primary-button-background-color: #6c757d;
|
||||
--primary-button-text-color: white;
|
||||
--primary-button-border-color: #6c757d;
|
||||
|
||||
--muted-text-color: #666;
|
||||
|
||||
--input-text-color: black;
|
||||
--input-background-color: transparent;
|
||||
|
||||
--hover-item-text-color: black;
|
||||
--hover-item-background-color: #0000001a;
|
||||
--hover-item-border-color: transparent;
|
||||
|
||||
--active-item-text-color: var(--left-pane-text-color);
|
||||
--active-item-background-color: #ddd;
|
||||
--active-item-border-color: transparent;
|
||||
|
||||
--menu-text-color: #272727;
|
||||
--menu-background-color: #ffffffd9;
|
||||
--menu-item-icon-color: #727272;
|
||||
--menu-item-disabled-opacity: .5;
|
||||
--menu-item-keyboard-shortcut-color: #666666a8;
|
||||
--menu-item-arrow-color: #00000080;
|
||||
--menu-item-delimiter-color: #00000030;
|
||||
|
||||
--modal-background-color: white;
|
||||
--modal-backdrop-color: black;
|
||||
|
||||
--quick-search-background: #00000012;
|
||||
--quick-search-color: #06060682;
|
||||
--quick-search-hover-background: #00000020;
|
||||
--quick-search-focus-border: #00000029;
|
||||
--quick-search-focus-background: #ffffff80;
|
||||
--quick-search-focus-color: #000;
|
||||
|
||||
--left-pane-collapsed-border-color: #0000000d;
|
||||
--left-pane-background-color: #f2f2f2;
|
||||
--left-pane-text-color: #383838;
|
||||
--left-pane-item-hover-background: #eaeaea;
|
||||
--left-pane-item-selected-background: white;
|
||||
--left-pane-item-selected-color: black;
|
||||
--left-pane-item-selected-shadow: 1px 1px 2px rgba(0, 0, 0, .2);
|
||||
--left-pane-item-action-button-background: #d7d7d7;
|
||||
--left-pane-item-action-button-color: inherit;
|
||||
--left-pane-item-action-button-hover-background: white;
|
||||
--left-pane-item-action-button-hover-shadow: 2px 2px 3px rgba(0, 0, 0, .15);
|
||||
--left-pane-item-selected-action-button-hover-shadow: 2px 2px 10px rgba(0, 0, 0, .25);
|
||||
|
||||
--launcher-pane-background-color: #e8e8e8;
|
||||
--launcher-pane-horizontal-background-color: #fafafa;
|
||||
--launcher-pane-horizontal-border-color: rgba(0, 0, 0, 0.1);
|
||||
--launcher-pane-text-color: #000000bd;
|
||||
--launcher-pane-button-hover-color: black;
|
||||
--launcher-pane-button-hover-background: white;
|
||||
--launcher-pane-button-hover-shadow: 4px 4px 4px rgba(0, 0, 0, .075);
|
||||
|
||||
--protected-session-active-icon-color: #16b516;
|
||||
--sync-status-error-pulse-color: #ff5528;
|
||||
|
||||
--root-background: var(--left-pane-background-color);
|
||||
|
||||
--gutter-color: transparent;
|
||||
--gutter-hover-color: #bfbfbf;
|
||||
|
||||
--tab-close-button-hover-background: #c95a5a;
|
||||
--tab-close-button-hover-color: white;
|
||||
|
||||
--active-tab-background-color: white;
|
||||
--active-tab-hover-background-color: var(--active-tab-background-color);
|
||||
--active-tab-text-color: black;
|
||||
--active-tab-shadow: 3px 3px 6px rgba(0, 0, 0, .1), -1px -1px 3px rgba(0, 0, 0, .05);
|
||||
--active-tab-dragging-shadow: var(--active-tab-shadow), 0 0 20px rgba(0, 0, 0, .1);
|
||||
|
||||
--inactive-tab-background-color: transparent;
|
||||
--inactive-tab-hover-background-color: #00000016;
|
||||
--inactive-tab-text-color: #4e4e4e;
|
||||
|
||||
--new-tab-button-background: #d8d8d8;
|
||||
--new-tab-button-color: #3a3a3a;
|
||||
--new-tab-button-shadow: 2px 2px 4px rgba(0, 0, 0, .2);
|
||||
--new-tab-button-hover-background: white;
|
||||
--new-tab-button-hover-color: black;
|
||||
|
||||
--right-pane-item-hover-background: #ececec;
|
||||
--right-pane-item-hover-color: inherit;
|
||||
|
||||
--scrollbar-border-color: #ddd;
|
||||
--scrollbar-background-color: #ddd;
|
||||
--link-color: blue;
|
||||
|
||||
--mermaid-theme: default;
|
||||
|
||||
--code-block-box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.1), 0px 0px 2px rgba(0, 0, 0, 0.2);
|
||||
|
||||
--card-background-color: var(--accented-background-color);
|
||||
--card-background-hover-color: #f9f9f9;
|
||||
--card-background-press-color: #efefef;
|
||||
--card-border-color: #eaeaea;
|
||||
--card-shadow-color: rgba(0, 0, 0, 0.1);
|
||||
--card-box-shadow: 0 0 12px var(--card-shadow-color);
|
||||
|
||||
--calendar-color: var(--menu-text-color);
|
||||
--calendar-weekday-labels-color: var(--muted-text-color);
|
||||
--calendar-day-hover-color: var(--hover-item-text-color);
|
||||
--calendar-day-hover-background: var(--active-item-background-color);
|
||||
--calendar-day-highlight-background: #80808024;
|
||||
|
||||
--timeline-bullet-color: #a5a5a5;
|
||||
--timeline-bullet-hover-color: black;
|
||||
--timeline-connector-color: #f1f1f1;
|
||||
--timeline-connector-active-color: #ddd;
|
||||
--timeline-connector-hover-blend-mode: multiply;
|
||||
|
||||
--tooltip-background-color: rgba(255, 255, 255, 0.85);
|
||||
--tooltip-foreground-color: #000000ba;
|
||||
--tooltip-shadow-color: rgba(0, 0, 0, .15);
|
||||
}
|
@ -1,393 +1,7 @@
|
||||
@import url(./theme-next/shell.css);
|
||||
@import url(./theme-next/settings.css);
|
||||
@import url(./theme-next/notes/text.css);
|
||||
/* Import the light color scheme.
|
||||
* This is the base color scheme, always active and overridden by the dark
|
||||
* color scheme stylesheet when necessary. */
|
||||
@import url(./theme-next-light.css);
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans";
|
||||
src: url(../fonts/Noto_Sans/NotoSans-VariableFont_wdth\,wght.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Ubuntu Sans";
|
||||
src: url(../fonts/Ubuntu_Sans/UbuntuSans-VariableFont_wdth\,wght.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Nunito";
|
||||
src: url(../fonts/Nunito/Nunito-VariableFont_wght.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
src: url(../fonts/Inter/Inter-VariableFont_opsz\,wght.ttf);
|
||||
}
|
||||
|
||||
:root {
|
||||
/* --main-font-family: "Noto Sans", sans-serif; */
|
||||
--main-font-family: "Segoe UI", sans-serif;
|
||||
/* --main-font-family: "Ubuntu", sans-serif; */
|
||||
/* --main-font-family: "Nunito", sans-serif; */
|
||||
/* --main-font-family: "Inter", sans-serif; */
|
||||
|
||||
--main-font-size: normal;
|
||||
|
||||
--tree-font-family: var(--main-font-family);
|
||||
--tree-font-size: normal;
|
||||
|
||||
--detail-font-family: var(--main-font-family);
|
||||
--detail-font-size: normal;
|
||||
|
||||
--monospace-font-family: JetBrainsLight;
|
||||
--monospace-font-size: normal;
|
||||
|
||||
--left-pane-item-selected-shadow-size: 2px;
|
||||
|
||||
--launcher-pane-size: 58px;
|
||||
--launcher-pane-horizontal-size: 54px;
|
||||
--launcher-pane-horizontal-icon-size: 20px;
|
||||
--launcher-pane-button-margin: 6px;
|
||||
--launcher-pane-button-gap: 3px;
|
||||
|
||||
--tree-actions-toolbar-horizontal-margin: 8px;
|
||||
--tree-actions-toolbar-vertical-margin: 8px;
|
||||
--tree-actions-toolbar-padding-size: 4px;
|
||||
--tree-actions-toolbar-collapsed-width: 40px;
|
||||
--tree-actions-toolbar-expand-button-size: 25px;
|
||||
|
||||
--tab-bar-height: 50px;
|
||||
--tab-height: 36px;
|
||||
--tab-first-item-horiz-offset: 1px;
|
||||
--new-tab-button-size: 24px;
|
||||
|
||||
--center-pane-border-radius: 10px;
|
||||
|
||||
--menu-padding-size: 8px;
|
||||
--menu-item-icon-vert-offset: 0;
|
||||
|
||||
--more-accented-background-color: var(--card-background-hover-color);
|
||||
|
||||
--timeline-left-gap: 20px;
|
||||
--timeline-right-gap: 20px;
|
||||
--timeline-item-top-padding: 4px;
|
||||
--timeline-item-bottom-padding: 8px;
|
||||
--timeline-bullet-size: 10px;
|
||||
--timeline-bullet-vertical-pos: .75em;
|
||||
--timeline-connector-size: 4px;
|
||||
|
||||
/* Theme capabilities */
|
||||
--tab-note-icons: true;
|
||||
}
|
||||
|
||||
/*
|
||||
* THEME COLORS
|
||||
*/
|
||||
|
||||
/*
|
||||
* Light theme scheme
|
||||
*/
|
||||
:root {
|
||||
--theme-style: light;
|
||||
--native-titlebar-background: #ffffff00;
|
||||
|
||||
--main-background-color: white;
|
||||
--main-text-color: black;
|
||||
--main-border-color: #dbdbdb;
|
||||
--subtle-border-color: rgba(0, 0, 0, 0.1);
|
||||
--dropdown-border-color: #ccc;
|
||||
--dropdown-shadow-opacity: .2;
|
||||
--dropdown-item-icon-destructive-color: #ec5138;
|
||||
--disabled-tooltip-icon-color: #004382;
|
||||
|
||||
--accented-background-color: #f5f5f5;
|
||||
|
||||
--button-background-color: transparent;
|
||||
--button-border-color: #ddd;
|
||||
--button-text-color: black;
|
||||
--button-border-radius: 5px;
|
||||
--button-disabled-background-color: #ddd;
|
||||
--button-disabled-text-color: black;
|
||||
|
||||
--primary-button-background-color: #6c757d;
|
||||
--primary-button-text-color: white;
|
||||
--primary-button-border-color: #6c757d;
|
||||
|
||||
--muted-text-color: #666;
|
||||
|
||||
--input-text-color: black;
|
||||
--input-background-color: transparent;
|
||||
|
||||
--hover-item-text-color: black;
|
||||
--hover-item-background-color: #0000001a;
|
||||
--hover-item-border-color: transparent;
|
||||
|
||||
--active-item-text-color: var(--left-pane-text-color);
|
||||
--active-item-background-color: #ddd;
|
||||
--active-item-border-color: transparent;
|
||||
|
||||
--menu-text-color: #272727;
|
||||
--menu-background-color: #ffffffd9;
|
||||
--menu-item-icon-color: #727272;
|
||||
--menu-item-disabled-opacity: .5;
|
||||
--menu-item-keyboard-shortcut-color: #666666a8;
|
||||
--menu-item-arrow-color: #00000080;
|
||||
--menu-item-delimiter-color: #00000030;
|
||||
|
||||
--modal-background-color: white;
|
||||
--modal-backdrop-color: black;
|
||||
|
||||
--quick-search-background: #00000012;
|
||||
--quick-search-color: #06060682;
|
||||
--quick-search-hover-background: #00000020;
|
||||
--quick-search-focus-border: #00000029;
|
||||
--quick-search-focus-background: #ffffff80;
|
||||
--quick-search-focus-color: #000;
|
||||
|
||||
--left-pane-collapsed-border-color: #0000000d;
|
||||
--left-pane-background-color: #f2f2f2;
|
||||
--left-pane-text-color: #383838;
|
||||
--left-pane-item-hover-background: #eaeaea;
|
||||
--left-pane-item-selected-background: white;
|
||||
--left-pane-item-selected-color: black;
|
||||
--left-pane-item-selected-shadow: 1px 1px 2px rgba(0, 0, 0, .2);
|
||||
--left-pane-item-action-button-background: #d7d7d7;
|
||||
--left-pane-item-action-button-color: inherit;
|
||||
--left-pane-item-action-button-hover-background: white;
|
||||
--left-pane-item-action-button-hover-shadow: 2px 2px 3px rgba(0, 0, 0, .15);
|
||||
--left-pane-item-selected-action-button-hover-shadow: 2px 2px 10px rgba(0, 0, 0, .25);
|
||||
|
||||
--launcher-pane-background-color: #e8e8e8;
|
||||
--launcher-pane-horizontal-background-color: #fafafa;
|
||||
--launcher-pane-horizontal-border-color: rgba(0, 0, 0, 0.1);
|
||||
--launcher-pane-text-color: #000000bd;
|
||||
--launcher-pane-button-hover-color: black;
|
||||
--launcher-pane-button-hover-background: white;
|
||||
--launcher-pane-button-hover-shadow: 4px 4px 4px rgba(0, 0, 0, .075);
|
||||
|
||||
--protected-session-active-icon-color: #16b516;
|
||||
--sync-status-error-pulse-color: #ff5528;
|
||||
|
||||
--root-background: var(--left-pane-background-color);
|
||||
|
||||
--gutter-color: transparent;
|
||||
--gutter-hover-color: #bfbfbf;
|
||||
|
||||
--tab-close-button-hover-background: #c95a5a;
|
||||
--tab-close-button-hover-color: white;
|
||||
|
||||
--active-tab-background-color: white;
|
||||
--active-tab-hover-background-color: var(--active-tab-background-color);
|
||||
--active-tab-text-color: black;
|
||||
--active-tab-shadow: 3px 3px 6px rgba(0, 0, 0, .1), -1px -1px 3px rgba(0, 0, 0, .05);
|
||||
--active-tab-dragging-shadow: var(--active-tab-shadow), 0 0 20px rgba(0, 0, 0, .1);
|
||||
|
||||
--inactive-tab-background-color: transparent;
|
||||
--inactive-tab-hover-background-color: #00000016;
|
||||
--inactive-tab-text-color: #4e4e4e;
|
||||
|
||||
--new-tab-button-background: #d8d8d8;
|
||||
--new-tab-button-color: #3a3a3a;
|
||||
--new-tab-button-shadow: 2px 2px 4px rgba(0, 0, 0, .2);
|
||||
--new-tab-button-hover-background: white;
|
||||
--new-tab-button-hover-color: black;
|
||||
|
||||
--right-pane-item-hover-background: #ececec;
|
||||
--right-pane-item-hover-color: inherit;
|
||||
|
||||
--scrollbar-border-color: #ddd;
|
||||
--scrollbar-background-color: #ddd;
|
||||
--link-color: blue;
|
||||
|
||||
--mermaid-theme: default;
|
||||
|
||||
--code-block-box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.1), 0px 0px 2px rgba(0, 0, 0, 0.2);
|
||||
|
||||
--card-background-color: var(--accented-background-color);
|
||||
--card-background-hover-color: #f9f9f9;
|
||||
--card-background-press-color: #efefef;
|
||||
--card-border-color: #eaeaea;
|
||||
--card-shadow-color: rgba(0, 0, 0, 0.1);
|
||||
--card-box-shadow: 0 0 12px var(--card-shadow-color);
|
||||
|
||||
--calendar-color: var(--menu-text-color);
|
||||
--calendar-weekday-labels-color: var(--muted-text-color);
|
||||
--calendar-day-hover-color: var(--hover-item-text-color);
|
||||
--calendar-day-hover-background: var(--active-item-background-color);
|
||||
--calendar-day-highlight-background: #80808024;
|
||||
|
||||
--timeline-bullet-color: #a5a5a5;
|
||||
--timeline-bullet-hover-color: black;
|
||||
--timeline-connector-color: #f1f1f1;
|
||||
--timeline-connector-active-color: #ddd;
|
||||
--timeline-connector-hover-blend-mode: multiply;
|
||||
|
||||
--tooltip-background-color: rgba(255, 255, 255, 0.85);
|
||||
--tooltip-foreground-color: #000000ba;
|
||||
--tooltip-shadow-color: rgba(0, 0, 0, .15);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dark color scheme
|
||||
*/
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--theme-style: dark;
|
||||
--native-titlebar-background: #00000000;
|
||||
|
||||
--main-background-color: #333;
|
||||
--main-text-color: #ccc;
|
||||
--main-border-color: #454545;
|
||||
--subtle-border-color: #313131;
|
||||
--dropdown-border-color: #292929;
|
||||
--dropdown-shadow-opacity: .6;
|
||||
--dropdown-item-icon-destructive-color: #de6e5b;
|
||||
--disabled-tooltip-icon-color: #7fd2ef;
|
||||
|
||||
|
||||
--accented-background-color: #555;
|
||||
|
||||
--button-background-color: transparent;
|
||||
--button-border-color: #ccc;
|
||||
--button-text-color: currentColor;
|
||||
--button-border-radius: 5px;
|
||||
--button-disabled-background-color: transparent;
|
||||
--button-disabled-text-color: #999;
|
||||
|
||||
--primary-button-background-color: #888;
|
||||
--primary-button-text-color: white;
|
||||
--primary-button-border-color: #999;
|
||||
|
||||
--muted-text-color: #bbb;
|
||||
|
||||
--input-text-color: #ccc;
|
||||
--input-background-color: #333;
|
||||
|
||||
--hover-item-text-color: #efefef;
|
||||
--hover-item-background-color: #ffffff24;
|
||||
--hover-item-border-color: transparent;
|
||||
|
||||
--active-item-text-color: var(--left-pane-text-color);
|
||||
--active-item-background-color: #777;
|
||||
--active-item-border-color: transparent;
|
||||
|
||||
--new-tab-button-background: #fff0;
|
||||
--new-tab-button-color: #ffffff96;
|
||||
--new-tab-button-shadow: 2px 2px 4px rgba(0, 0, 0, .4);
|
||||
--new-tab-button-hover-background: #fff3;
|
||||
--new-tab-button-hover-color: white;
|
||||
|
||||
--menu-text-color: #e3e3e3;
|
||||
--menu-background-color: #222222d9;
|
||||
--menu-item-icon-color: #8c8c8c;
|
||||
--menu-item-disabled-opacity: .5;
|
||||
--menu-item-keyboard-shortcut-color: #ffffff8f;
|
||||
--menu-item-arrow-color: #ffffffa3;
|
||||
--menu-item-delimiter-color: #ffffff1c;
|
||||
|
||||
|
||||
--modal-background-color: #333;
|
||||
--modal-backdrop-color: #444;
|
||||
|
||||
--quick-search-background: #ffffff12;
|
||||
--quick-search-color: #ffffff52;
|
||||
--quick-search-hover-background: #ffffff1f;
|
||||
--quick-search-focus-border: #80808095;
|
||||
--quick-search-focus-background: #ffffff1f;
|
||||
--quick-search-focus-color: white;
|
||||
|
||||
--left-pane-collapsed-border-color: #0009;
|
||||
--left-pane-background-color: #1f1f1f;
|
||||
--left-pane-text-color: #AAAAAA;
|
||||
--left-pane-item-hover-background: #ffffff0d;
|
||||
--left-pane-item-selected-background: #ffffff25;
|
||||
--left-pane-item-selected-color: #dfdfdf;
|
||||
--left-pane-item-selected-shadow: 1px 1px 2px rgba(0, 0, 0, .6);
|
||||
--left-pane-item-action-button-background: #ffffff73;
|
||||
--left-pane-item-action-button-color: black;
|
||||
--left-pane-item-action-button-hover-background: #ffffffad;
|
||||
--left-pane-item-action-button-hover-shadow: 2px 2px 3px rgba(0, 0, 0, .15);
|
||||
--left-pane-item-selected-action-button-hover-shadow: 2px 2px 10px rgba(0, 0, 0, .25);
|
||||
|
||||
--launcher-pane-background-color: #1a1a1a;
|
||||
--launcher-pane-horizontal-background-color: #282828;
|
||||
--launcher-pane-horizontal-border-color: rgb(22, 22, 22);
|
||||
--launcher-pane-text-color: #909090;
|
||||
--launcher-pane-button-hover-color: #ffffff;
|
||||
--launcher-pane-button-hover-background: #ffffff1c;
|
||||
--launcher-pane-button-hover-shadow: 4px 4px 4px rgba(0, 0, 0, .2);
|
||||
|
||||
--protected-session-active-icon-color: #8edd8e;
|
||||
--sync-status-error-pulse-color: #f47871;
|
||||
|
||||
--root-background: var(--left-pane-background-color);
|
||||
|
||||
--gutter-color: transparent;
|
||||
--gutter-hover-color: #626262;
|
||||
|
||||
--tab-close-button-hover-background: #a45353;
|
||||
--tab-close-button-hover-color: white;
|
||||
|
||||
--active-tab-background-color: #ffffff1c;
|
||||
--active-tab-hover-background-color: var(--active-tab-background-color);
|
||||
--active-tab-text-color: #ffffffcd;
|
||||
--active-tab-shadow: 3px 3px 6px rgba(0, 0, 0, .2), -1px -1px 3px rgba(0, 0, 0, .4);
|
||||
--active-tab-dragging-shadow: var(--active-tab-shadow), 0 0 20px rgba(0, 0, 0, .4);
|
||||
|
||||
--inactive-tab-background-color: transparent;
|
||||
--inactive-tab-hover-background-color: #ffffff0f;
|
||||
--inactive-tab-text-color: #7c7c7c;
|
||||
|
||||
--right-pane-item-hover-background: #ffffff26;
|
||||
--right-pane-item-hover-color: white;
|
||||
|
||||
--scrollbar-border-color: #666;
|
||||
--scrollbar-background-color: #333;
|
||||
--link-color: lightskyblue;
|
||||
|
||||
--mermaid-theme: dark;
|
||||
|
||||
--code-block-box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.6);
|
||||
|
||||
--card-background-color: #363636;
|
||||
--card-background-hover-color: #3c3c3c;
|
||||
--card-background-press-color: #464646;
|
||||
--card-border-color: #222222;
|
||||
--card-box-shadow: 0 0 12px rgba(0, 0, 0, 0.15);
|
||||
|
||||
--calendar-color: var(--menu-text-color);
|
||||
--calendar-weekday-labels-color: var(--muted-text-color);
|
||||
--calendar-day-hover-color: var(--hover-item-text-color);
|
||||
--calendar-day-hover-background: var(--active-item-background-color);
|
||||
--calendar-day-highlight-background: #8080805a;
|
||||
|
||||
--timeline-bullet-color: gray;
|
||||
--timeline-bullet-hover-color: white;
|
||||
--timeline-connector-color: #464646;
|
||||
--timeline-connector-active-color: #545454;
|
||||
--timeline-connector-hover-blend-mode: exclusion;
|
||||
|
||||
--tooltip-background-color: rgba(67, 67, 67, 0.86);
|
||||
--tooltip-foreground-color: #ffffffeb;
|
||||
--tooltip-shadow-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
body ::-webkit-calendar-picker-indicator {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
body .CodeMirror {
|
||||
filter: invert(90%) hue-rotate(180deg);
|
||||
}
|
||||
|
||||
.excalidraw.theme--dark {
|
||||
--theme-filter: invert(80%) hue-rotate(180deg) !important;
|
||||
}
|
||||
|
||||
body .todo-list input[type="checkbox"]:not(:checked):before {
|
||||
border-color: var(--muted-text-color) !important;
|
||||
}
|
||||
|
||||
.btn-close {
|
||||
filter: invert(1);
|
||||
}
|
||||
}
|
||||
/* Import the dark color scheme when the system preference is set to dark mode */
|
||||
@import url(./theme-next-dark.css) (prefers-color-scheme: dark);
|
79
src/public/stylesheets/theme-next/base.css
Normal file
@ -0,0 +1,79 @@
|
||||
@import url(./shell.css);
|
||||
@import url(./settings.css);
|
||||
@import url(./notes/text.css);
|
||||
|
||||
@font-face {
|
||||
font-family: "Noto Sans";
|
||||
src: url(../fonts/Noto_Sans/NotoSans-VariableFont_wdth\,wght.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Ubuntu Sans";
|
||||
src: url(../fonts/Ubuntu_Sans/UbuntuSans-VariableFont_wdth\,wght.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Nunito";
|
||||
src: url(../fonts/Nunito/Nunito-VariableFont_wght.ttf);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
src: url(../fonts/Inter/Inter-VariableFont_opsz\,wght.ttf);
|
||||
}
|
||||
|
||||
:root {
|
||||
/* --main-font-family: "Noto Sans", sans-serif; */
|
||||
--main-font-family: "Segoe UI", sans-serif;
|
||||
/* --main-font-family: "Ubuntu", sans-serif; */
|
||||
/* --main-font-family: "Nunito", sans-serif; */
|
||||
/* --main-font-family: "Inter", sans-serif; */
|
||||
|
||||
--main-font-size: normal;
|
||||
|
||||
--tree-font-family: var(--main-font-family);
|
||||
--tree-font-size: normal;
|
||||
|
||||
--detail-font-family: var(--main-font-family);
|
||||
--detail-font-size: normal;
|
||||
|
||||
--monospace-font-family: JetBrainsLight;
|
||||
--monospace-font-size: normal;
|
||||
|
||||
--left-pane-item-selected-shadow-size: 2px;
|
||||
|
||||
--launcher-pane-size: 58px;
|
||||
--launcher-pane-horizontal-size: 54px;
|
||||
--launcher-pane-horizontal-icon-size: 20px;
|
||||
--launcher-pane-button-margin: 6px;
|
||||
--launcher-pane-button-gap: 3px;
|
||||
|
||||
--tree-actions-toolbar-horizontal-margin: 8px;
|
||||
--tree-actions-toolbar-vertical-margin: 8px;
|
||||
--tree-actions-toolbar-padding-size: 4px;
|
||||
--tree-actions-toolbar-collapsed-width: 40px;
|
||||
--tree-actions-toolbar-expand-button-size: 25px;
|
||||
|
||||
--tab-bar-height: 50px;
|
||||
--tab-height: 36px;
|
||||
--tab-first-item-horiz-offset: 1px;
|
||||
--new-tab-button-size: 24px;
|
||||
|
||||
--center-pane-border-radius: 10px;
|
||||
|
||||
--menu-padding-size: 8px;
|
||||
--menu-item-icon-vert-offset: 0;
|
||||
|
||||
--more-accented-background-color: var(--card-background-hover-color);
|
||||
|
||||
--timeline-left-gap: 20px;
|
||||
--timeline-right-gap: 20px;
|
||||
--timeline-item-top-padding: 4px;
|
||||
--timeline-item-bottom-padding: 8px;
|
||||
--timeline-bullet-size: 10px;
|
||||
--timeline-bullet-vertical-pos: .75em;
|
||||
--timeline-connector-size: 4px;
|
||||
|
||||
/* Theme capabilities */
|
||||
--tab-note-icons: true;
|
||||
}
|
@ -109,6 +109,7 @@ body.layout-horizontal > .horizontal {
|
||||
#launcher-pane.horizontal {
|
||||
height: var(--launcher-pane-size) !important;
|
||||
border-bottom: 1px solid var(--launcher-pane-horizontal-border-color);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#launcher-pane .launcher-button,
|
||||
@ -138,8 +139,10 @@ body.layout-horizontal > .horizontal {
|
||||
}
|
||||
|
||||
#launcher-pane .launcher-button:hover,
|
||||
#launcher-pane .launcher-button.right-dropdown-button.show {
|
||||
background: var(--launcher-pane-button-hover-background);
|
||||
#launcher-pane .launcher-button.right-dropdown-button.show,
|
||||
#launcher-pane.horizontal .global-menu-button:hover,
|
||||
#launcher-pane.horizontal .global-menu-button.show {
|
||||
background: var(--launcher-pane-button-hover-background) !important;
|
||||
color: var(--launcher-pane-button-hover-color);
|
||||
box-shadow: var(--launcher-pane-button-hover-shadow);
|
||||
transition: background-color 100ms ease-in,
|
||||
@ -1075,6 +1078,97 @@ body .calendar-dropdown-widget .calendar-body a:hover {
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Jump to note
|
||||
*/
|
||||
|
||||
.jump-to-note-dialog .modal-dialog {
|
||||
--modal-background-color: var(--menu-background-color);
|
||||
--bs-modal-header-border-width: 0;
|
||||
--bs-modal-footer-border-width: 0;
|
||||
--bs-modal-footer-gap: 0;
|
||||
|
||||
backdrop-filter: var(--dropdown-backdrop-filter);
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .modal-content {
|
||||
box-shadow: 0 10px 20px rgba(0, 0, 0, var(--dropdown-shadow-opacity));
|
||||
border: 1px solid var(--dropdown-border-color);
|
||||
padding: 32px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .modal-header {
|
||||
padding: unset !important;
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .modal-body {
|
||||
padding: 26px 0 !important;
|
||||
}
|
||||
|
||||
/* Search box wrapper */
|
||||
.jump-to-note-dialog .input-group {
|
||||
margin-right: 16px;
|
||||
background: var(--quick-search-background);
|
||||
border: 2px solid transparent;
|
||||
border-radius: 6px;
|
||||
color: var(--quick-search-color);
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .input-group:hover {
|
||||
background: var(--quick-search-hover-background);
|
||||
}
|
||||
|
||||
/* Focused search box */
|
||||
.jump-to-note-dialog .input-group:focus-within {
|
||||
border-color: var(--quick-search-focus-border);
|
||||
background: var(--quick-search-focus-background);
|
||||
color: var(--quick-search-focus-color)
|
||||
}
|
||||
|
||||
/* Search box input */
|
||||
.jump-to-note-dialog .input-group input {
|
||||
--bs-border-width: 0;
|
||||
|
||||
box-shadow: unset;
|
||||
background: transparent;
|
||||
color: currentColor;
|
||||
}
|
||||
|
||||
/* Search box buttons */
|
||||
.jump-to-note-dialog .input-group button {
|
||||
--bs-border-width: 0;
|
||||
--accented-background-color: transparent;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .input-group button:last-child {
|
||||
padding-right: .75em;
|
||||
}
|
||||
|
||||
.jump-to-note-dialog .input-clearer-button {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
/* List body */
|
||||
.jump-to-note-dialog .jump-to-note-results .aa-suggestions {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* List item */
|
||||
.jump-to-note-dialog .aa-suggestions div {
|
||||
border-radius: 6px;
|
||||
padding: 6px 12px;
|
||||
color: var(--menu-text-color);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* Selected list item */
|
||||
.jump-to-note-dialog .aa-suggestions div.aa-cursor {
|
||||
background: var(--hover-item-background-color);
|
||||
color: var(--hover-item-text-color);
|
||||
}
|
||||
|
||||
/*
|
||||
* Recent changes list
|
||||
*/
|
||||
|
7
src/public/stylesheets/theme.css
Normal file
@ -0,0 +1,7 @@
|
||||
/* Import the light color scheme.
|
||||
* This is the base color scheme, always active and overridden by the dark
|
||||
* color scheme stylesheet when necessary. */
|
||||
@import url(./theme-light.css);
|
||||
|
||||
/* Import the dark color scheme when the system preference is set to dark mode */
|
||||
@import url(./theme-dark.css) (prefers-color-scheme: dark);
|
@ -147,7 +147,7 @@
|
||||
"numberedList": "<kbd>1.</kbd> oder <kbd>1)</kbd> gefolgt von Leerzeichen für nummerierte Liste",
|
||||
"blockQuote": "Beginne eine Zeile mit <kbd>></kbd> gefolgt von einem Leerzeichen für Blockzitate",
|
||||
"troubleshooting": "Fehlerbehebung",
|
||||
"reloadFrontend": "Trillium-Frontend neuladen",
|
||||
"reloadFrontend": "Trilium-Frontend neuladen",
|
||||
"showDevTools": "Entwicklertools anzeigen",
|
||||
"showSQLConsole": "SQL-Konsole anzeigen",
|
||||
"other": "Andere",
|
||||
@ -660,7 +660,7 @@
|
||||
},
|
||||
"code_buttons": {
|
||||
"execute_button_title": "Skript ausführen",
|
||||
"trilium_api_docs_button_title": "Öffne die Trillium-API-Dokumentation",
|
||||
"trilium_api_docs_button_title": "Öffne die Trilium-API-Dokumentation",
|
||||
"save_to_note_button_title": "In die Notiz speichern",
|
||||
"opening_api_docs_message": "API-Dokumentation wird geöffnet...",
|
||||
"sql_console_saved_message": "SQL-Konsolennotiz wurde in {{note_path}} gespeichert"
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "About TriliumNext Notes",
|
||||
"close": "Close",
|
||||
"homepage": "Homepage:",
|
||||
"app_version": "App version:",
|
||||
"db_version": "DB version:",
|
||||
@ -59,6 +60,7 @@
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "Clone notes to...",
|
||||
"close": "Close",
|
||||
"help_on_links": "Help on links",
|
||||
"notes_to_clone": "Notes to clone",
|
||||
"target_parent_note": "Target parent note",
|
||||
@ -71,6 +73,7 @@
|
||||
},
|
||||
"confirm": {
|
||||
"confirmation": "Confirmation",
|
||||
"close": "Close",
|
||||
"cancel": "Cancel",
|
||||
"ok": "OK",
|
||||
"are_you_sure_remove_note": "Are you sure you want to remove the note \"{{title}}\" from relation map? ",
|
||||
@ -79,6 +82,7 @@
|
||||
},
|
||||
"delete_notes": {
|
||||
"delete_notes_preview": "Delete notes preview",
|
||||
"close": "Close",
|
||||
"delete_all_clones_description": "Delete also all clones (can be undone in recent changes)",
|
||||
"erase_notes_description": "Normal (soft) deletion only marks the notes as deleted and they can be undeleted (in recent changes dialog) within a period of time. Checking this option will erase the notes immediately and it won't be possible to undelete the notes.",
|
||||
"erase_notes_warning": "Erase notes permanently (can't be undone), including all clones. This will force application reload.",
|
||||
@ -189,6 +193,7 @@
|
||||
},
|
||||
"include_note": {
|
||||
"dialog_title": "Include note",
|
||||
"close": "Close",
|
||||
"label_note": "Note",
|
||||
"placeholder_search": "search for note by its name",
|
||||
"box_size_prompt": "Box size of the included note:",
|
||||
@ -204,16 +209,19 @@
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_placeholder": "search for note by its name",
|
||||
"close": "Close",
|
||||
"search_button": "Search in full text <kbd>Ctrl+Enter</kbd>"
|
||||
},
|
||||
"markdown_import": {
|
||||
"dialog_title": "Markdown import",
|
||||
"close": "Close",
|
||||
"modal_body_text": "Because of browser sandbox it's not possible to directly read clipboard from JavaScript. Please paste the Markdown to import to textarea below and click on Import button",
|
||||
"import_button": "Import Ctrl+Enter",
|
||||
"import_success": "Markdown content has been imported into the document."
|
||||
},
|
||||
"move_to": {
|
||||
"dialog_title": "Move notes to ...",
|
||||
"close": "Close",
|
||||
"notes_to_move": "Notes to move",
|
||||
"target_parent_note": "Target parent note",
|
||||
"search_placeholder": "search for note by its name",
|
||||
@ -223,16 +231,19 @@
|
||||
},
|
||||
"note_type_chooser": {
|
||||
"modal_title": "Choose note type",
|
||||
"close": "Close",
|
||||
"modal_body": "Choose note type / template of the new note:",
|
||||
"templates": "Templates:"
|
||||
},
|
||||
"password_not_set": {
|
||||
"title": "Password is not set",
|
||||
"close": "Close",
|
||||
"body1": "Protected notes are encrypted using a user password, but password has not been set yet.",
|
||||
"body2": "To be able to protect notes, click <a class=\"open-password-options-button\" href=\"javascript:\">here</a> to open the Options dialog and set your password."
|
||||
},
|
||||
"prompt": {
|
||||
"title": "Prompt",
|
||||
"close": "Close",
|
||||
"ok": "OK <kbd>enter</kbd>",
|
||||
"defaultTitle": "Prompt"
|
||||
},
|
||||
@ -246,6 +257,7 @@
|
||||
"recent_changes": {
|
||||
"title": "Recent changes",
|
||||
"erase_notes_button": "Erase deleted notes now",
|
||||
"close": "Close",
|
||||
"deleted_notes_message": "Deleted notes have been erased.",
|
||||
"no_changes_message": "No changes yet...",
|
||||
"undelete_link": "undelete",
|
||||
@ -256,6 +268,7 @@
|
||||
"delete_all_revisions": "Delete all revisions of this note",
|
||||
"delete_all_button": "Delete all revisions",
|
||||
"help_title": "Help on Note Revisions",
|
||||
"close": "Close",
|
||||
"revision_last_edited": "This revision was last edited on {{date}}",
|
||||
"confirm_delete_all": "Do you want to delete all revisions of this note? This action will erase the revision title and content, but still preserve the revision metadata.",
|
||||
"no_revisions": "No revisions for this note yet...",
|
||||
@ -277,6 +290,7 @@
|
||||
},
|
||||
"sort_child_notes": {
|
||||
"sort_children_by": "Sort children by...",
|
||||
"close": "Close",
|
||||
"sorting_criteria": "Sorting criteria",
|
||||
"title": "title",
|
||||
"date_created": "date created",
|
||||
@ -294,6 +308,7 @@
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "Upload attachments to note",
|
||||
"close": "Close",
|
||||
"choose_files": "Choose files",
|
||||
"files_will_be_uploaded": "Files will be uploaded as attachments into",
|
||||
"options": "Options",
|
||||
@ -1072,9 +1087,12 @@
|
||||
"title": "Application Theme",
|
||||
"theme_label": "Theme",
|
||||
"override_theme_fonts_label": "Override theme fonts",
|
||||
"auto_theme": "Auto",
|
||||
"light_theme": "Light",
|
||||
"dark_theme": "Dark",
|
||||
"triliumnext": "TriliumNext (beta)",
|
||||
"triliumnext": "TriliumNext Beta (Follow system color scheme)",
|
||||
"triliumnext-light": "TriliumNext Beta (Light)",
|
||||
"triliumnext-dark": "TriliumNext Beta (Dark)",
|
||||
"layout": "Layout",
|
||||
"layout-vertical-title": "Vertical",
|
||||
"layout-horizontal-title": "Horizontal",
|
||||
|
@ -153,7 +153,7 @@
|
||||
"numberedList": "<kbd>1.</kbd> o <kbd>1)</kbd> seguido de espacio para la lista numerada",
|
||||
"blockQuote": "comience una línea con <kbd>></kbd> seguido de espacio para el bloque de cita",
|
||||
"troubleshooting": "Solución de problemas",
|
||||
"reloadFrontend": "recargar la interfaz de Trillium",
|
||||
"reloadFrontend": "recargar la interfaz de Trilium",
|
||||
"showDevTools": "mostrar herramientas de desarrollador",
|
||||
"showSQLConsole": "mostrar consola SQL",
|
||||
"other": "Otro",
|
||||
|
@ -1195,8 +1195,12 @@
|
||||
"title": "Pragul de mod de citire automat"
|
||||
},
|
||||
"theme": {
|
||||
"auto_theme": "Temă auto (se adaptează la schema de culori a sistemului)",
|
||||
"dark_theme": "Temă întunecată",
|
||||
"light_theme": "Temă luminoasă",
|
||||
"triliumnext": "TriliumNext Beta (se adaptează la schema de culori a sistemului)",
|
||||
"triliumnext-light": "TriliumNext Beta (luminoasă)",
|
||||
"triliumnext-dark": "TriliumNext Beta (întunecată)",
|
||||
"override_theme_fonts_label": "Suprascrie fonturile temei",
|
||||
"theme_label": "Temă",
|
||||
"title": "Tema aplicației",
|
||||
@ -1204,8 +1208,7 @@
|
||||
"layout-horizontal-description": "bara de lansare se află sub bara de taburi, bara de taburi este pe toată lungimea.",
|
||||
"layout-horizontal-title": "Orizontal",
|
||||
"layout-vertical-title": "Vertical",
|
||||
"layout-vertical-description": "bara de lansare se află pe stânga (implicit)",
|
||||
"triliumnext": "TriliumNext (experimentală)"
|
||||
"layout-vertical-description": "bara de lansare se află pe stânga (implicit)"
|
||||
},
|
||||
"toast": {
|
||||
"critical-error": {
|
||||
|
@ -4,8 +4,6 @@ import { fileURLToPath } from "url";
|
||||
import express from "express";
|
||||
import env from "../services/env.js";
|
||||
import serveStatic from "serve-static";
|
||||
import webpack from "webpack";
|
||||
import webpackMiddleware from "webpack-dev-middleware";
|
||||
|
||||
const persistentCacheStatic = (root: string, options?: serveStatic.ServeStaticOptions<express.Response<any, Record<string, any>>>) => {
|
||||
if (!env.isDev()) {
|
||||
@ -17,9 +15,12 @@ const persistentCacheStatic = (root: string, options?: serveStatic.ServeStaticOp
|
||||
return express.static(root, options);
|
||||
};
|
||||
|
||||
function register(app: express.Application) {
|
||||
async function register(app: express.Application) {
|
||||
const srcRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
if (env.isDev()) {
|
||||
const webpack = (await import("webpack")).default;
|
||||
const webpackMiddleware = (await import("webpack-dev-middleware")).default;
|
||||
|
||||
const frontendCompiler = webpack({
|
||||
mode: "development",
|
||||
entry: {
|
||||
|
@ -61,13 +61,19 @@ function index(req: Request, res: Response) {
|
||||
}
|
||||
|
||||
function getThemeCssUrl(theme: string, themeNote: BNote | null) {
|
||||
if (theme === 'light') {
|
||||
if (theme === 'auto') {
|
||||
return `${assetPath}/stylesheets/theme.css`;
|
||||
} else if (theme === 'light') {
|
||||
// light theme is always loaded as baseline
|
||||
return false;
|
||||
} else if (theme === 'dark') {
|
||||
return `${assetPath}/stylesheets/theme-dark.css`;
|
||||
} else if (theme === "next") {
|
||||
return `${assetPath}/stylesheets/theme-next.css`;
|
||||
} else if (theme === "next-light") {
|
||||
return `${assetPath}/stylesheets/theme-next-light.css`;
|
||||
} else if (theme === "next-dark") {
|
||||
return `${assetPath}/stylesheets/theme-next-dark.css`;
|
||||
} else if (!process.env.TRILIUM_SAFE_MODE && themeNote) {
|
||||
return `api/notes/download/${themeNote.noteId}`;
|
||||
} else {
|
||||
|
@ -5,15 +5,57 @@ import turndownPluginGfm from "joplin-turndown-plugin-gfm";
|
||||
|
||||
let instance: TurndownService | null = null;
|
||||
|
||||
const fencedCodeBlockFilter: TurndownService.Rule = {
|
||||
filter: function (node, options) {
|
||||
return (
|
||||
options.codeBlockStyle === 'fenced' &&
|
||||
node.nodeName === 'PRE' &&
|
||||
node.firstChild !== null &&
|
||||
node.firstChild.nodeName === 'CODE'
|
||||
)
|
||||
},
|
||||
|
||||
replacement: function (content, node, options) {
|
||||
if (!node.firstChild || !("getAttribute" in node.firstChild) || typeof node.firstChild.getAttribute !== "function") {
|
||||
return content;
|
||||
}
|
||||
|
||||
const className = node.firstChild.getAttribute('class') || ''
|
||||
const language = rewriteLanguageTag((className.match(/language-(\S+)/) || [null, ''])[1]);
|
||||
|
||||
return (
|
||||
'\n\n' + options.fence + language + '\n' +
|
||||
node.firstChild.textContent +
|
||||
'\n' + options.fence + '\n\n'
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
function toMarkdown(content: string) {
|
||||
if (instance === null) {
|
||||
instance = new TurndownService({ codeBlockStyle: 'fenced' });
|
||||
// Filter is heavily based on: https://github.com/mixmark-io/turndown/issues/274#issuecomment-458730974
|
||||
instance.addRule('fencedCodeBlock', fencedCodeBlockFilter);
|
||||
instance.use(turndownPluginGfm.gfm);
|
||||
}
|
||||
|
||||
return instance.turndown(content);
|
||||
}
|
||||
|
||||
function rewriteLanguageTag(source: string) {
|
||||
if (!source) {
|
||||
return source;
|
||||
}
|
||||
|
||||
if (source === "text-x-trilium-auto") {
|
||||
return "";
|
||||
}
|
||||
|
||||
return source
|
||||
.split("-")
|
||||
.at(-1);
|
||||
}
|
||||
|
||||
export default {
|
||||
toMarkdown
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ import striptags from "striptags";
|
||||
import utils from "../../utils.js";
|
||||
import sql from "../../sql.js";
|
||||
|
||||
|
||||
const ALLOWED_OPERATORS = ['=', '!=', '*=*', '*=', '=*', '%='];
|
||||
|
||||
const cachedRegexes: Record<string, RegExp> = {};
|
||||
@ -133,6 +134,74 @@ class NoteContentFulltextExp extends Expression {
|
||||
|
||||
content = content.replace(/ /g, ' ');
|
||||
}
|
||||
else if (type === 'mindMap' && mime === 'application/json') {
|
||||
|
||||
let mindMapcontent = JSON.parse (content);
|
||||
|
||||
// Define interfaces for the JSON structure
|
||||
interface MindmapNode {
|
||||
id: string;
|
||||
topic: string;
|
||||
children: MindmapNode[]; // Recursive structure
|
||||
direction?: number;
|
||||
expanded?: boolean;
|
||||
}
|
||||
|
||||
interface MindmapData {
|
||||
nodedata: MindmapNode;
|
||||
arrows: any[]; // If you know the structure, replace `any` with the correct type
|
||||
summaries: any[];
|
||||
direction: number;
|
||||
theme: {
|
||||
name: string;
|
||||
type: string;
|
||||
palette: string[];
|
||||
cssvar: Record<string, string>; // Object with string keys and string values
|
||||
};
|
||||
}
|
||||
|
||||
// Recursive function to collect all topics
|
||||
function collectTopics(node: MindmapNode): string[] {
|
||||
// Collect the current node's topic
|
||||
let topics = [node.topic];
|
||||
|
||||
// If the node has children, collect topics recursively
|
||||
if (node.children && node.children.length > 0) {
|
||||
for (const child of node.children) {
|
||||
topics = topics.concat(collectTopics(child));
|
||||
}
|
||||
}
|
||||
|
||||
return topics;
|
||||
}
|
||||
|
||||
|
||||
// Start extracting from the root node
|
||||
const topicsArray = collectTopics(mindMapcontent.nodedata);
|
||||
|
||||
// Combine topics into a single string
|
||||
const topicsString = topicsArray.join(", ");
|
||||
|
||||
|
||||
content = utils.normalize(topicsString.toString());
|
||||
}
|
||||
else if (type === 'canvas' && mime === 'application/json') {
|
||||
interface Element {
|
||||
type: string;
|
||||
text?: string; // Optional since not all objects have a `text` property
|
||||
id: string;
|
||||
[key: string]: any; // Other properties that may exist
|
||||
}
|
||||
|
||||
let canvasContent = JSON.parse (content);
|
||||
const elements: Element [] = canvasContent.elements;
|
||||
const texts = elements
|
||||
.filter((element: Element) => element.type === 'text' && element.text) // Filter for 'text' type elements with a 'text' property
|
||||
.map((element: Element) => element.text!); // Use `!` to assert `text` is defined after filtering
|
||||
|
||||
content =utils.normalize(texts.toString())
|
||||
}
|
||||
|
||||
|
||||
return content.trim();
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ const STRING_MIME_TYPES = [
|
||||
"image/svg+xml"
|
||||
];
|
||||
|
||||
function isStringNote(type: string | null, mime: string) {
|
||||
function isStringNote(type: string | undefined, mime: string) {
|
||||
// render and book are string note in the sense that they are expected to contain empty string
|
||||
return (type && ["text", "code", "relationMap", "search", "render", "book", "mermaid", "canvas"].includes(type))
|
||||
|| mime.startsWith('text/')
|
||||
|
@ -62,7 +62,7 @@ class SAttachment extends AbstractShacaEntity {
|
||||
|
||||
/** @returns true if the attachment has string content (not binary) */
|
||||
hasStringContent() {
|
||||
return utils.isStringNote(null, this.mime);
|
||||
return utils.isStringNote(undefined, this.mime);
|
||||
}
|
||||
|
||||
getPojo() {
|
||||
|
@ -94,7 +94,7 @@
|
||||
},
|
||||
"login": {
|
||||
"title": "Iniciar sesión",
|
||||
"heading": "Iniciar sesión en Trillium",
|
||||
"heading": "Iniciar sesión en Trilium",
|
||||
"incorrect-password": "La contraseña es incorrecta. Por favor inténtalo de nuevo.",
|
||||
"password": "Contraseña",
|
||||
"remember-me": "Recordarme",
|
||||
@ -109,7 +109,7 @@
|
||||
},
|
||||
"javascript-required": "Trilium requiere que JavaScript esté habilitado.",
|
||||
"setup": {
|
||||
"heading": "Configuración de TrilliumNext Notes",
|
||||
"heading": "Configuración de TriliumNext Notes",
|
||||
"new-document": "Soy un usuario nuevo y quiero crear un nuevo documento de Trilium para mis notas",
|
||||
"sync-from-desktop": "Ya tengo una instancia de escritorio y quiero configurar la sincronización con ella",
|
||||
"sync-from-server": "Ya tengo una instancia de servidor y quiero configurar la sincronización con ella",
|
||||
|