mirror of
https://github.com/zadam/trilium.git
synced 2025-10-30 18:05:55 +01:00
Merge remote-tracking branch 'origin/develop' into client_vite
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
"url": "https://github.com/TriliumNext/Notes"
|
||||
},
|
||||
"dependencies": {
|
||||
"@eslint/js": "9.26.0",
|
||||
"@eslint/js": "9.27.0",
|
||||
"@excalidraw/excalidraw": "0.18.0",
|
||||
"@fullcalendar/core": "6.1.17",
|
||||
"@fullcalendar/daygrid": "6.1.17",
|
||||
|
||||
@@ -1637,7 +1637,9 @@ div.find-replace-widget div.find-widget-found-wrapper > span {
|
||||
|
||||
#right-pane .toc li,
|
||||
#right-pane .highlights-list li {
|
||||
padding: 2px 8px;
|
||||
padding-top: 2px;
|
||||
padding-right: 8px;
|
||||
padding-bottom: 2px;
|
||||
border-radius: 4px;
|
||||
text-align: unset;
|
||||
transition:
|
||||
|
||||
@@ -35,12 +35,8 @@ const TPL = /*html*/`<div class="toc-widget">
|
||||
.toc ol {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding-left: 20px;
|
||||
transition: max-height 0.3s ease;
|
||||
}
|
||||
|
||||
.toc > ol {
|
||||
padding-left: 0px;
|
||||
transition: max-height 0.3s ease;
|
||||
}
|
||||
|
||||
.toc li.collapsed + ol {
|
||||
@@ -51,8 +47,8 @@ const TPL = /*html*/`<div class="toc-widget">
|
||||
content: "";
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
left: 17px;
|
||||
border-left: 1px solid var(--main-border-color);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.toc li {
|
||||
@@ -67,11 +63,35 @@ const TPL = /*html*/`<div class="toc-widget">
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
.toc > ol {
|
||||
--toc-depth-level: 1;
|
||||
}
|
||||
.toc > ol > ol {
|
||||
--toc-depth-level: 2;
|
||||
}
|
||||
.toc > ol > ol > ol {
|
||||
--toc-depth-level: 3;
|
||||
}
|
||||
.toc > ol > ol > ol > ol {
|
||||
--toc-depth-level: 4;
|
||||
}
|
||||
.toc > ol > ol > ol > ol > ol {
|
||||
--toc-depth-level: 5;
|
||||
}
|
||||
|
||||
.toc > ol ol::before {
|
||||
left: calc((var(--toc-depth-level) - 2) * 20px + 14px);
|
||||
}
|
||||
|
||||
.toc li {
|
||||
padding-left: calc((var(--toc-depth-level) - 1) * 20px + 4px);
|
||||
}
|
||||
|
||||
.toc li .collapse-button {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 21px;
|
||||
height: 21px;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -83,12 +103,12 @@ const TPL = /*html*/`<div class="toc-widget">
|
||||
}
|
||||
|
||||
.toc li .item-content {
|
||||
margin-left: 28px;
|
||||
margin-left: 25px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.toc li .collapse-button + .item-content {
|
||||
margin-left: 8px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.toc li:hover {
|
||||
@@ -316,10 +336,9 @@ export default class TocWidget extends RightPanelWidget {
|
||||
//
|
||||
|
||||
const headingText = await this.replaceMathTextWithKatax(m[2]);
|
||||
const $itemContent = $('<div class="item-content">').html(headingText).on("click", () => {
|
||||
this.jumpToHeading(headingIndex);
|
||||
});
|
||||
const $li = $("<li>").append($itemContent);
|
||||
const $itemContent = $('<div class="item-content">').html(headingText);
|
||||
const $li = $("<li>").append($itemContent)
|
||||
.on("click", () => this.jumpToHeading(headingIndex));
|
||||
$ols[$ols.length - 1].append($li);
|
||||
headingCount = headingIndex;
|
||||
$previousLi = $li;
|
||||
@@ -400,7 +419,8 @@ export default class TocWidget extends RightPanelWidget {
|
||||
$previousLi.removeClass("collapsed");
|
||||
}
|
||||
|
||||
$collapseButton.on("click", () => {
|
||||
$collapseButton.on("click", (event) => {
|
||||
event.stopPropagation();
|
||||
if ($previousLi.hasClass("animating")) return;
|
||||
const willCollapse = !$previousLi.hasClass("collapsed");
|
||||
$previousLi.addClass("animating");
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
"multer": "1.4.5-lts.2",
|
||||
"normalize-strings": "1.1.1",
|
||||
"ollama": "0.5.15",
|
||||
"openai": "4.98.0",
|
||||
"openai": "4.100.0",
|
||||
"rand-token": "1.0.1",
|
||||
"safe-compare": "1.1.4",
|
||||
"sanitize-filename": "1.6.3",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { beforeAll } from "vitest";
|
||||
import i18next from "i18next";
|
||||
import { join } from "path";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
beforeAll(async () => {
|
||||
// Initialize the translations manually to avoid any side effects.
|
||||
@@ -15,4 +16,8 @@ beforeAll(async () => {
|
||||
loadPath: join(__dirname, "../src/assets/translations/{{lng}}/{{ns}}.json")
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize dayjs
|
||||
await import("dayjs/locale/en.js");
|
||||
dayjs.locale("en");
|
||||
});
|
||||
|
||||
@@ -4,7 +4,6 @@ import favicon from "serve-favicon";
|
||||
import cookieParser from "cookie-parser";
|
||||
import helmet from "helmet";
|
||||
import compression from "compression";
|
||||
import sessionParser from "./routes/session_parser.js";
|
||||
import config from "./services/config.js";
|
||||
import utils, { getResourceDir } from "./services/utils.js";
|
||||
import assets from "./routes/assets.js";
|
||||
@@ -111,6 +110,8 @@ export default async function buildApp() {
|
||||
app.use(`/manifest.webmanifest`, express.static(path.join(publicAssetsDir, "manifest.webmanifest")));
|
||||
app.use(`/robots.txt`, express.static(path.join(publicAssetsDir, "robots.txt")));
|
||||
app.use(`/icon.png`, express.static(path.join(publicAssetsDir, "icon.png")));
|
||||
|
||||
const sessionParser = (await import("./routes/session_parser.js")).default;
|
||||
app.use(sessionParser);
|
||||
app.use(favicon(path.join(assetsDir, "icon.ico")));
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
<p><strong>Note: This feature has not been merged yet, so it is not available.</strong>
|
||||
</p>
|
||||
<p>Multi-factor authentication (MFA) is a security process that requires
|
||||
users to provide two or more verification factors to gain access to a system,
|
||||
application, or account. This adds an extra layer of protection beyond
|
||||
@@ -7,80 +5,60 @@
|
||||
<p>By requiring more than one verification method, MFA helps reduce the risk
|
||||
of unauthorized access, even if someone has obtained your password. It’s
|
||||
highly recommended for securing sensitive information stored in your notes.</p>
|
||||
<p>Warning! OpenID and TOTP cannot be both used at the same time!</p>
|
||||
<h2>Log in with your Google Account with OpenID!</h2>
|
||||
<p>OpenID is a standardized way to let you log into websites using an account
|
||||
from another service, like Google, to verify your identity.</p>
|
||||
<h2>Why Time-based One Time Passwords?</h2>
|
||||
<p>TOTP (Time-Based One-Time Password) is a security feature that generates
|
||||
a unique, temporary code on your device, like a smartphone, which changes
|
||||
every 30 seconds. You use this code, along with your password, to log into
|
||||
your account, making it much harder for anyone else to access them.</p>
|
||||
<h2>Setup</h2>
|
||||
<h3>TOTP</h3>
|
||||
<ol>
|
||||
<li>
|
||||
<p>Start Trilium Notes normally.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Go to "Menu" -> "Options" -> "MFA"</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Click the "Generate TOTP Secret" button</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Copy the generated secret to your authentication app/extension</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Set an environment variable "TOTP_SECRET" as the generated secret. Environment
|
||||
variables can be set with a .env file in the root directory, by defining
|
||||
them in the command line, or with a docker container.</p><pre><code class="language-text-x-trilium-auto"># .env in the project root directory
|
||||
TOTP_ENABLED="true"
|
||||
TOTP_SECRET="secret"</code></pre><pre><code class="language-text-x-trilium-auto"># Terminal/CLI
|
||||
export TOTP_ENABLED="true"
|
||||
export TOTP_SECRET="secret"</code></pre><pre><code class="language-text-x-trilium-auto"># Docker
|
||||
docker run -p 8080:8080 -v ~/trilium-data:/home/node/trilium-data -e TOTP_ENABLED="true" -e TOTP_SECRET="secret" triliumnext/notes:[VERSION]</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<p>Restart Trilium</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Go to "Options" -> "MFA"</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Click the "Generate Recovery Codes" button</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Save the recovery codes. Recovery codes can be used once in place of the
|
||||
<aside
|
||||
class="admonition warning">
|
||||
<p>OpenID and TOTP cannot be both used at the same time!</p>
|
||||
</aside>
|
||||
<h2>Log in with your Google Account with OpenID!</h2>
|
||||
<p>OpenID is a standardized way to let you log into websites using an account
|
||||
from another service, like Google, to verify your identity.</p>
|
||||
<h2>Why Time-based One Time Passwords?</h2>
|
||||
<p>TOTP (Time-Based One-Time Password) is a security feature that generates
|
||||
a unique, temporary code on your device, like a smartphone, which changes
|
||||
every 30 seconds. You use this code, along with your password, to log into
|
||||
your account, making it much harder for anyone else to access them.</p>
|
||||
<h2>Setup</h2>
|
||||
<p>MFA can only be set up on a server instance.</p>
|
||||
<aside class="admonition note">
|
||||
<p>When Multi-Factor Authentication (MFA) is enabled on a server instance,
|
||||
a new desktop instance may fail to sync with it. As a temporary workaround,
|
||||
you can disable MFA to complete the initial sync, then re-enable MFA afterward.
|
||||
This issue will be addressed in a future release.</p>
|
||||
</aside>
|
||||
<h3>TOTP</h3>
|
||||
<ol>
|
||||
<li>Go to "Menu" -> "Options" -> "MFA"</li>
|
||||
<li>Click the “Enable Multi-Factor Authentication” checkbox if not checked</li>
|
||||
<li>Choose “Time-Based One-Time Password (TOTP)” under MFA Method</li>
|
||||
<li>Click the "Generate TOTP Secret" button</li>
|
||||
<li>Copy the generated secret to your authentication app/extension</li>
|
||||
<li>Click the "Generate Recovery Codes" button</li>
|
||||
<li>Save the recovery codes. Recovery codes can be used once in place of the
|
||||
TOTP if you loose access to your authenticator. After a rerecovery code
|
||||
is used, it will show the unix timestamp when it was used in the MFA options
|
||||
tab.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Load the secret into an authentication app like google authenticator</p>
|
||||
</li>
|
||||
</ol>
|
||||
<h3>OpenID</h3>
|
||||
<p><em>Currently only compatible with Google. Other services like Authentik and Auth0 are planned on being added.</em>
|
||||
</p>
|
||||
<p>In order to setup OpenID, you will need to setup a authentication provider.
|
||||
This requires a bit of extra setup. Follow <a href="https://developers.google.com/identity/openid-connect/openid-connect">these instructions</a> to
|
||||
setup an OpenID service through google.</p>
|
||||
<p>Set an environment variable "SSO_ENABLED" to true and add the client ID
|
||||
and secret you obtained from google. Environment variables can be set with
|
||||
a .env file in the root directory, by defining them in the command line,
|
||||
or with a docker container.</p>
|
||||
<h4>.env File</h4><pre><code class="language-text-x-trilium-auto"># .env in the project root directory
|
||||
SSO_ENABLED="true"
|
||||
BASE_URL="http://localhost:8080"
|
||||
CLIENT_ID=
|
||||
SECRET=</code></pre>
|
||||
<h4>Environment variable (linux)</h4><pre><code class="language-text-x-trilium-auto">export SSO_ENABLED="true"
|
||||
export BASE_URL="http://localhost:8080"
|
||||
export CLIENT_ID=
|
||||
export SECRET=</code></pre>
|
||||
<h4>Docker</h4><pre><code class="language-text-x-trilium-auto">docker run -d -p 8080:8080 -v ~/trilium-data:/home/node/trilium-data -e SSO_ENABLED="true" -e BASE_URL="http://localhost:8080" -e CLIENT_ID= -e SECRET= triliumnext/notes:[VERSION]</code></pre>
|
||||
<p>After you restart Trilium Notes, you will be redirected to Google's account
|
||||
selection page. Login to an account and Trilium Next will bind to that
|
||||
account, allowing you to login with it.</p>
|
||||
<p>You can now login using your google account.</p>
|
||||
tab.</li>
|
||||
<li>Re-login will be required after TOTP setup is finished (After you refreshing
|
||||
the page).</li>
|
||||
</ol>
|
||||
<h3>OpenID</h3>
|
||||
<aside class="admonition note">
|
||||
<p>Currently only compatible with Google. Other services like Authentik and
|
||||
Auth0 are planned on being added.</p>
|
||||
</aside>
|
||||
<p>In order to setup OpenID, you will need to setup a authentication provider.
|
||||
This requires a bit of extra setup. Follow <a href="https://developers.google.com/identity/openid-connect/openid-connect">these instructions</a> to
|
||||
setup an OpenID service through google.</p>
|
||||
<ol>
|
||||
<li>Set the <code>oauthBaseUrl</code>, <code>oauthClientId</code> and <code>oauthClientSecret</code> in
|
||||
the <code>config.ini</code> file (check <a class="reference-link" href="#root/_help_Gzjqa934BdH4">Configuration (config.ini or environment variables)</a> for
|
||||
more information).
|
||||
<ol>
|
||||
<li>You can also setup through environment variables (<code>TRILIUM_OAUTH_BASE_URL</code>, <code>TRILIUM_OAUTH_CLIENT_ID</code> and <code>TRILIUM_OAUTH_CLIENT_SECRET</code>).</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>Restart the server</li>
|
||||
<li>Go to "Menu" -> "Options" -> "MFA"</li>
|
||||
<li>Click the “Enable Multi-Factor Authentication” checkbox if not checked</li>
|
||||
<li>Choose “OAuth/OpenID” under MFA Method</li>
|
||||
<li>Refresh the page and login through OpenID provider</li>
|
||||
</ol>
|
||||
@@ -40,7 +40,7 @@
|
||||
<h2>Color schemes</h2>
|
||||
<p>Since Trilium 0.94.0 the colors of code notes can be customized by going
|
||||
<a
|
||||
class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_4TIF1oA4VQRO">Options</a> → Code Notes and looking for the <em>Appearance</em> section.</p>
|
||||
class="reference-link" href="#root/_help_4TIF1oA4VQRO">Options</a> → Code Notes and looking for the <em>Appearance</em> section.</p>
|
||||
<aside
|
||||
class="admonition note">
|
||||
<p><strong>Why are there only a few themes whereas the code block themes for text notes have a lot?</strong>
|
||||
|
||||
@@ -36,11 +36,11 @@ export async function initializeTranslations() {
|
||||
} catch (err) {
|
||||
console.warn(`Could not load locale ${dayjsLocale}`, err);
|
||||
}
|
||||
dayjs.locale(dayjsLocale);
|
||||
}
|
||||
|
||||
export function ordinal(date: Dayjs) {
|
||||
return dayjs(date)
|
||||
.locale(dayjsLocale)
|
||||
.format("Do");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import sessionParser from "./routes/session_parser.js";
|
||||
import fs from "fs";
|
||||
import http from "http";
|
||||
import https from "https";
|
||||
@@ -79,6 +77,7 @@ async function startTrilium() {
|
||||
|
||||
const httpServer = startHttpServer(app);
|
||||
|
||||
const sessionParser = (await import("./routes/session_parser.js")).default;
|
||||
ws.init(httpServer, sessionParser as any); // TODO: Not sure why session parser is incompatible.
|
||||
|
||||
if (utils.isElectron) {
|
||||
|
||||
Reference in New Issue
Block a user