概述

Trilium 项目的基本概述可在Github项目主页上找到 - https://github.com/zadam/trilium

译者的个人小站:https://smj.im

文档

wiki包含有关某些主题的更多和更深入的信息。有关所有可用页面的列表,请参见侧边栏。

快速开始


选择设置

仅限本地桌面/笔记本电脑 - 允许桌面上的单个实例并将笔记本地保存在该桌面上。

  1. 桌面端安装

仅限 Web 访问 的服务器 - 在服务器上安装应用程序并允许从任何设备(包括移动设备)上的任何 Web 浏览器进行访问。

  1. 服务器安装
  2. 移动前端(可选)
  3. Deploy

服务器和台式机/笔记本电脑的组合 - 在服务器上安装应用程序,用于 Web 访问和数据同步,以及桌面实例。这允许将所有数据存储在服务器上,并可以从 Web 浏览器或桌面应用程序访问。桌面应用程序将在本地同步和存储数据,以便在离线时使用。

  1. 服务器安装
  2. 移动前端(可选)
  3. 桌面端安装
  4. 同步

基本概念

  1. 了解Note概念
  2. 欣赏Trilium特色演示

题外话

最近更新日期:2023-07-27

如果发现错误,请邮件联系我改正

欢迎PR

我的个人小站:https://smj.im

这是Trilium的中文Wiki.

非常喜欢这个软件, 所以就自己动手翻译了一下作者写的文档:)

最后, 再次感谢@zadam开发这个项目!!!

有时,评估软件的最快方法就是通过屏幕截图,下面是一些功能演示:

See 主题.

This shows 代码笔记 editor.

See 提升属性.

See 关系映射图.

See 笔记映射图.

See 日志笔记.

See 体重追踪器.

See 任务管理器.

See 笔记修订.

See 手机.

See 平板.

文档是SQLite数据库,其中包含所有笔记,树结构,元数据和大多数配置。

位置

文档存储在数据目录中。

演示文件

首次运行Trilium时,它将为您生成一个演示文档作为起点。这对于演示Trilium的某些功能也非常有用,例如:

恢复演示文件

在某些情况下,您可能希望在删除演示文件后查看它。或者您可能想查看是否添加了某些内容(有时我们会在演示文档中添加一个新功能演示)。在这种情况下,您只需下载最新文档的 .zip 存档并将其导入树中的某个位置(右键单击要导入演示文档的笔记,然后选择“导入”)。

译者注:其实你可以在删除之前把demo先导出到本地,等你需要的时候再导入进来,当然,这样可能没有新特性的演示文件。

手动修改文档

Trilium提供了很大的灵活性,但您也可能搬起石头砸自己的脚(例如,使应用程序视图空白的启动脚本)。

在这种情况下,您可以在数据库层上手动修复记录-您可以使用例如https://sqlitebrowser.org/打开document.db文件,查找有问题的记录并手动修复它们。完成后,不要忘记提交/编写(commit / write)更改。

笔记是Trilium中的中心实体。笔记的主要属性是标题和内容。

重要的是,笔记本身不会携带有关其在Note树中的位置的信息。

笔记的树形结构类似于文件系统-但与Trilium中的笔记相比,它既可以用作文件又可以用作目录-意味着笔记可以既具有自己的内容又具有子代的内容。“叶子笔记”是没有任何子节点的笔记。

笔记类型

  • 文本笔记-这是默认的笔记类型,可让您放置富文本,图像等。
  • 代码笔记-某种形式的代码,通常是编程语言(例如JavaScript)或数据结构(例如XML)
  • 图片笔记-代表单张图片
  • 文件笔记-代表上传的文件(例如docx MS Word文档)。
  • render HTML笔记-用作附加脚本的输出屏幕
  • 已保存的搜索记录-包含保存的搜索查询,并动态显示搜索结果作为其子记录
  • 关系映射图笔记-可视化笔记及其关系
  • 书笔记-显示其子笔记,对于阅读许多简短笔记很有用
  • mermaid new-使用mermaid.js创建图表和流程图
  • 画布笔记 new-允许使用excalidraw在无限画布上手绘笔记和基本图表

请记住,没有“文件夹”笔记类型。任何笔记都可以是文件夹笔记或“叶子”笔记。

根笔记(Root note)

有一个称为“根笔记”的特殊笔记,它是笔记树的根节点。所有其他笔记均位于root结构中的下方。

删除/取消删除笔记

以下说明仅自Trilium 0.40版本起有效

当您在Trilium中删除笔记时,实际上仅将其标记为删除(软删除)-不会删除实际内容,标题,属性等,而只是将其隐藏。

(默认情况下)在7天内,可以取消删除这些已软删除的笔记-打开“最近更改”对话框,您将看到所有已修改笔记的列表,包括已删除的笔记。可以取消删除的笔记具有这样做的链接。这是类似Windows的“回收站”的功能。

单击取消删除将恢复笔记,笔记的内容和属性-笔记应与删除前一样。此操作还将取消删除在同一操作中已删除的笔记的子节点笔记。

为了能够取消删除笔记,必须取消删除已删除笔记的父节点笔记(否则就​​没有地方可以将其取消删除)。当您连续删除更多笔记时,这可能会成为问题-解决方案是按照删除的相反顺序取消删除。

7天(是可配置的)之后,笔记将被“擦除”-它们的标题,内容,修订和属性将被删除,并且将无法再恢复它们(除非您恢复备份(https://github.com/zadam/trilium/wiki/Backup))。

相关内容

Trilium 使用了很棒的CKEditor 5作为它的编辑组件。

格式化

默认情况下,Trilium文本笔记界面不显示任何工具栏或格式选项,这些需要通过以下方式启动:

  1. 选择文本将显示内联工具栏:

  1. 单击块工具栏:

只读与编辑模式

文本注释通常在编辑模式下打开,但是在只读模式下打开有两种情况:

  • 它们很长,因此需要时间来加载,所以默认情况下我们将它们打开为只读,这要快得多
  • 或笔记有readOnly 属性

在这两种情况下,都可以再次切换到可编辑模式。

Markdown和自动格式化

CKEditor 支持类似 markdown 的编辑体验。它识别语法并自动将其转换为富文本。看看它的实际效果:

CKEditor 文档 中提供了此功能的完整文档。

如果您刚刚编写的内容不适合自动格式化,您可以按CTRL-Z会将文本取消自动格式化为原始格式。

请注意,不支持使用 # 格式化Heading1样式,因为编辑器假定它用于标题,所以标题请以##(即Heading2格式)开头。在这里有详细解释。

数学支持

Trilium 使用 KaTex 提供数学符号的支持:

剪切所选内容到子节点笔记

Trilium 中的一种常见情况是当您编辑文档时,它变得有点大,因此您开始将其拆分为子笔记 - 过程基本上是这样的:

  • 选择所需的文本并将其剪切到剪贴板
  • 创建新的子节点笔记并为其命名
  • 将剪贴板中的内容粘贴到子节点笔记中

Trilium 提供了一种自动化的方法:

你可以注意到标题“Formatting”是自动检测到的,并且新的子笔记被命名为“Formatting”。

当然你也可以为此操作分配键盘快捷键。

包含笔记

文本笔记可以“include”另一个笔记释作为只读小部件。这对于例如包含动态生成的图表(来自脚本和“渲染 HTML”注释)或其他更高级的用例很有用。

此功能在工具栏图标中可用。

外部链接

外部链接是针对某些外部网络资源的一般网络链接——例如https://en.wikipedia.org/wiki/South_China_Sea是指向一个维基百科页面的外部链接。

外部链接是通过 CKEditor 原生链接完成的。要创建外部链接,请选择文本并按下CTRL-K或等待“气泡”出现,然后单击那里的链接图标。

您可以通过双击(将打开新选项卡/窗口)或右键单击外部链接并选择“在新选项卡中打开”来跟踪外部链接。

内部链接

创建内部笔记的链接略有不同。要在当前光标位置创建笔记链接,请按CTRL-L

在对话框中,您可以看到用于从不同类型的链接中进行选择的单选按钮:

  • 链接标题反映了笔记的当前标题 - 这有时也称为“参考链接”。此类链接的标题无法更改,而是始终反映链接注释的标题。这样链接标题永远不会过时
  • 链接标题可以任意更改 - 这是传统的超链接 - 您链接到特定的笔记,并且可以选择链接标题

您可以双击笔记链接。

或者,如果您只想快速预览内容,您可以将鼠标悬停在链接上并看到只读预览。

In-place链接

Trilium 还提供“内联”链接 - 键入@,您会看到一个自动完成功能,只需从所需的笔记标题中键入几个字符,按 Enter 键,您就有一个链接。

笔记映射图

Trilium 为特定笔记提供了传入和传出链接的可视化。有关详细信息,请参阅笔记映射图

Trilium 支持存储和显示图像。支持的格式为 JPEG、PNG 和 GIF。

图像实际上是放置在笔记树中的[笔记类型)(./树的概念.md)。它的参考可以复制到文本注释中,因此它显示在文本本身中。

上传图片

要将图像添加到笔记中,只需将其从文件资源管理器拖到 Trilium 内的笔记编辑器中,图像就会被上传。

或者,您可以单击块工具栏,然后单击“插入图像”:

您还可以从网络复制和粘贴图像 - 图像将(异步)下载和嵌入。

压缩

由于 Trilium 并不是真正的图像数据的主要存储,它会在将上传的图像存储到数据库之前尝试压缩和调整大小(使用非常激进的设置)。然后您可能会注意到一些质量下降。基本质量设置在Options -> Other中可用。

如果您想以原始分辨率保存图像,建议将它们保存为笔记的附件(右上角“Note actions -> Upload file”)。

动机

Trilium 的核心功能是能够将您的笔记组织成分层的树状结构。

然后您将拥有一个精致而深入层次结构的笔记 - 每个子树将代表您的知识库的更精致和专业的视图。

这是一种非常强大的方法,但它也带有一个隐藏的假设,即每个“子主题”都由一个父级“拥有”。我将用一个例子来说明这一点——假设我的基本结构是这样的:

  • Technology
    • Programming
      • Kotlin
      • JavaScript
    • Operating systems
      • Linux
      • Windows

现在,我开始学习Bash,并想创建与该主题相关的笔记。但现在我面临着在哪里分类的问题。这里的问题是 Bash 既是一种编程语言,又是一种与 Linux 密切相关的工具(shell)。似乎它属于这两者,我不能(也不想)选择一个而不是另一个。

解决方案

上面显示的问题的解决方案是允许笔记有多个父级。

我称这些为“clones”(克隆),但这有点误导性 - 没有原始和克隆的笔记 - 两个父类别中的笔记是相同的。

译者注:我感觉有点像软链接/快捷方式?只是提供一个入口,本质都是同一个程序。

关于“clones”的另一个误导性的事情是它表明已经制作了笔记的副本。这不是真的,笔记本身只保留在一个原始文件中,它只是在树层次结构中的多个位置被引用。因此,在一个类别中更改它会在所有其他类别中更改它,因为它们都是相同的笔记。

这是克隆的最终结构:

  • Technology
    • Programming
      • Kotlin
      • JavaScript
      • Bash
        • some sub-notes ...
    • Operating systems
      • Linux
        • Bash
          • some sub-notes ...
      • Windows

所以现在“Bash”子树出现在层次结构中的多个位置。两个 Bash 子树是相同的,并且包含相同的子类别和记录。

演示

在演示中,您可以看到如何使用上下文菜单创建克隆。也可以使用“Add Link”对话框或使用 CTRL+C 和 CTRL+V快捷方式来执行此操作。

如演示中所示,您可以在功能区工具栏的“Note Paths”选项卡中查看所有可用克隆笔记的列表。

树视图中克隆笔记的标题在右侧有一个星号,可以轻松看到该笔记也放置在其他位置。

前缀

由于笔记可以分类到多个位置,因此建议选择适合所有位置的通用名称,而不是更具体的名称以避免混淆。在某些情况下这是不可能的,因此 Trilium 提供了“分支前缀”,它显示在树中的音符名称之前,因此提供了一种特定的上下文。前缀是特定于位置的,因此它仅显示在树窗格中。

删除笔记/克隆笔记

对于克隆,删除的工作原理可能不会立即显而易见。

如果您尝试删除笔记,它的工作方式如下:

  1. 如果笔记有多个克隆,只删除这个克隆并保留实际的笔记(及其其他克隆)原样。
  2. 如果此笔记没有任何其他克隆,请删除该笔记
    • 在所有笔记的子笔记上从 1. 开始运行整个过程。

动机

Trilium 的核心功能是能够将您的笔记组织成分层的树状结构。

然后您将拥有一个精致而深入层次结构的笔记 - 每个子树将代表您的知识库的更精致和专业的视图。

这是一种非常强大的方法,但它也带有一个隐藏的假设,即每个“子主题”都由一个父级“拥有”。我将用一个例子来说明这一点——假设我的基本结构是这样的:

  • Technology
    • Programming
      • Kotlin
      • JavaScript
    • Operating systems
      • Linux
      • Windows

现在,我开始学习Bash,并想创建与该主题相关的笔记。但现在我面临着在哪里分类的问题。这里的问题是 Bash 既是一种编程语言,又是一种与 Linux 密切相关的工具(shell)。似乎它属于这两者,我不能(也不想)选择一个而不是另一个。

解决方案

上面显示的问题的解决方案是允许笔记有多个父级。

我称这些为“clones”(克隆),但这有点误导性 - 没有原始和克隆的笔记 - 两个父类别中的笔记是相同的。

译者注:我感觉有点像软链接/快捷方式?只是提供一个入口,本质都是同一个程序。

关于“clones”的另一个误导性的事情是它表明已经制作了笔记的副本。这不是真的,笔记本身只保留在一个原始文件中,它只是在树层次结构中的多个位置被引用。因此,在一个类别中更改它会在所有其他类别中更改它,因为它们都是相同的笔记。

这是克隆的最终结构:

  • Technology
    • Programming
      • Kotlin
      • JavaScript
      • Bash
        • some sub-notes ...
    • Operating systems
      • Linux
        • Bash
          • some sub-notes ...
      • Windows

所以现在“Bash”子树出现在层次结构中的多个位置。两个 Bash 子树是相同的,并且包含相同的子类别和记录。

演示

在演示中,您可以看到如何使用上下文菜单创建克隆。也可以使用“Add Link”对话框或使用 CTRL+C 和 CTRL+V快捷方式来执行此操作。

如演示中所示,您可以在功能区工具栏的“Note Paths”选项卡中查看所有可用克隆笔记的列表。

树视图中克隆笔记的标题在右侧有一个星号,可以轻松看到该笔记也放置在其他位置。

前缀

由于笔记可以分类到多个位置,因此建议选择适合所有位置的通用名称,而不是更具体的名称以避免混淆。在某些情况下这是不可能的,因此 Trilium 提供了“分支前缀”,它显示在树中的音符名称之前,因此提供了一种特定的上下文。前缀是特定于位置的,因此它仅显示在树窗格中。

删除笔记/克隆笔记

对于克隆,删除的工作原理可能不会立即显而易见。

如果您尝试删除笔记,它的工作方式如下:

  1. 如果笔记有多个克隆,只删除这个克隆并保留实际的笔记(及其其他克隆)原样。
  2. 如果此笔记没有任何其他克隆,请删除该笔记
    • 在所有笔记的子笔记上从 1. 开始运行整个过程。

Trilium 通过定期存储笔记的快照(“修订版本”)来支持笔记的无缝版本控制。

记录快照的时间间隔可在Options -> Other dialog对话框中配置。这提供了更多修订和要存储的更多数据之间的权衡。

要关闭特定笔记(或子树)的笔记版本控制,请将disableVersioning 属性添加到笔记。

可以通过功能区工具栏右侧的按钮访问笔记修订。

归档笔记是带有archived[标签)(./属性.md)的笔记,可以直接添加或[继承)(./属性继承.md)。

这样的笔记默认情况下不会显示在自动完成和全文搜索中。

这对于不再有用但仍然有价值的笔记仍然很有用,可以保留下来而不会带来太多阻碍。

画布笔记

(Since trilium v0.52)

画布笔记使用 excalidraw 库允许用鼠标、笔或触摸在无限的画布上手写笔记。它还支持基本的图表、文本和图形输入。

canvas note sample

导航

本页介绍了与Trilium中的笔记的树结构有关的一些基本概念。

笔记

笔记是Trilium中的中心实体。有关详细信息,请参见笔记

分支

分支描述了笔记树中的笔记放置-本质上,它是parentNoteId和noteId的元组,它表示将给定的笔记作为子元素放置在此父笔记中。

每个笔记可以具有多个这样的分支,换句话说,任何笔记可以在树中具有多个位置。由于缺乏更好的词汇,我们将其称为“克隆”。

前缀

前缀是笔记的分支(放置)特定标题前缀。假设您将笔记放置在树中的两个不同位置,但是您想在其中一个位置中稍微更改标题。为此,您可以使用前缀。

要编辑前缀,请右键单击树窗格中的注释,然后选择“Edit branch prefix”。

前缀不是笔记本身的一部分,因此在笔记受到保护时不会加密。当您希望保持树中标题的一部分可见时,这可能很有用,即使在受到保护以便于定位的情况下也是如此。

子树

子树是一组由特定笔记(子树根)及其所有子代、子代的子代(=其所有后代)组成的笔记。一些操作在子树上进行(例如Export)。

本页描述了如何操作笔记树——特别是移动笔记。

拖放

正如您在演示中看到的那样,您可以简单地通过拖放注释来操作树:

键盘操作

Trilium 通过以下快捷键提供基于键盘的快速操作:

  • CTRL-UPCTRL-DOWN- 按顺序向上或向下移动音符
  • CTRL-LEFT- 通过将笔记的父级更改为笔记的父级的父级,在层次结构中向上移动笔记。
  • CTRL-RIGHT- 通过将父级设置为当前上面的注释,在层次结构中向下移动注释(这有点难以解释 - 最好看演示或自己尝试)
  • LEFTRIGHT展开和折叠子树

上下文菜单

您还可以使用上下文菜单中熟悉的剪切和粘贴或相关的键盘快捷键 CTRL-X(剪切)和CTRL-V(粘贴)来移动笔记。

Trilium的目标之一是在之间笔记提供快速舒适的导航。

后退和前进

您可以使用alt-left和alt-right在浏览页面的历史记录中前后移动。

这与浏览器的后退/前进功能相同,实际上是为此使用内置的浏览器支持。

当然,这是基本功能和预期功能,但是值得一提的是Trilium在这里可以很好地发挥作用。

跳转到笔记

这对于快速查找和查看任意笔记非常有用,请单击顶部的Jump to按钮或按CTRL-J。然后输入笔记名称的一部分,自动完成功能将帮助您选择所需的笔记。

最近的笔记

跳转到笔记还可以显示最近查看/编辑的笔记列表并快速跳转到该列表。

要访问此功能,请单击顶部的Jump to按钮。默认情况下(当自动完成不输入任何内容时),此对话框将显示最近备忘的列表。

或者,您可以单击右侧的"time"图标。

==============================

One of the Trilium's goals is to provide fast and comfortable navigation between notes.

Backwards and forward

You can use alt-left and alt-right to move back and forward in history of viewed pages.

This works identically to browser backwards / forwards, it's actually using built-in browser support for this.

Of course this is basic and expected functionality, but it's worth mentioning that Trilium plays nicely here.

Jump to note

This is useful to quickly find and view arbitrary note - click on Jump to button on the top or press CTRL-J. Then type part of the note name and autocomplete will help you pick the desired note.

Recent notes

Jump to note also has the ability to show the list of recently viewed / edited notes and quickly jump to it.

To access this functionality, click on Jump to button on the top. By default (when nothing is entered into autocomplete), this dialog will show the list of recent notes.

Alternatively you can click on the "time" icon on the right.

本页介绍自0.44版及更高版本开始的搜索。对于0.43及更老版本,请参见旧版搜索

  • 本地搜索-在当前显示的笔记中搜索。按CTRL-F打开搜索对话框。在服务器版本中,这是由浏览器处理的;在桌面版本(electron)中,有一个单独的对话框。
  • 笔记搜索-您可以通过在标题,笔记的内容或笔记的attributes中搜索文本来查找笔记。您还可以保存搜索
    • 您可以通过单击左侧的放大镜图标或按CTRL-S键盘[快捷键)(./键盘快捷键.md)来激活笔记搜索。

简单的笔记搜索示例

rings tolkien - 全文搜索,这将尝试查找在任何地方带有单词"rings"和"tolkien"的音符

"The Lord of the Rings" Tolkien - 与上述相同,但"The Lord of the Rings"必须完全匹配

towers #book - 全文搜索与属性搜索的结合-查找在任何地方包含"towers"的笔记,并且它们还需要带有"book"标签

towers #book or #author - 在任何位置搜索包含"towers"字的笔记,并且匹配的笔记必须带有"book"或"author"标签

towers #!book-在任何地方搜索包含"towers"的笔记,并且没有"book"标签

#book #publicationYear = 1954 - 将找到带有"book"标签和带有该特定值的"publicationYear"标签的笔记

#genre *=* fan-匹配带有"genre"标签的笔记,其值包含"fan"子字符串。除了*=*是"包含"之外,还有=*是"以...开头",*=是"以...结尾",!=是"不等于"

#book #publicationYear >= 1950 #publicationYear < 1960 - 您也可以使用数字运算符-这将查找1950年代出版的所有书籍笔记

#dateNote >= TODAY-30-特殊的"智能搜索"将查找标签为" dateNote"且具有对应于最近30天的日期的笔记。智能值的完整列表:现在+-秒,今天+-天,每周+-周,月份+-月,年份+-年

~author.title *=* Tolkien - 查找具有"author"关系并且指向标题中包含单词"Tolkien"的笔记

高级用例

~author.relations.son.title = 'Christopher Tolkien' - 这将搜索具有"author"关系的笔记,该笔记与"Christopher Tolkien"笔记具有"son"关系。这种情况可以通过以下笔记结构来建模:

  • Books
    • Lord of the Rings
      • label: "book"
      • relation: "author" points to "J. R. R. Tolkien" note
  • People
    • J. R. R. Tolkien
      • relation "son" points to "Christopher Tolkien" note
    • Christoper Tolkien

~author.title *= Tolkien OR (#publicationDate >= 1954 AND #publicationDate <= 1960) - 您也可以使用布尔表达式和括号将表达式分组

note.parents.title = 'Books' 将查找所有具有(至少一个)名称为" Books"的父笔记。

note.parents.parents.title = 'Books' 这又可以传递使用,因此可以找到其父节点的父节点名称为" Books"的笔记。

note.ancestors.title = 'Books'这是父母的一种扩展-会在其笔记路径中的任何地方找到祖先的笔记(例如,父母,祖父母,祖父母或外祖父母…),其标题为"Books"。这是一种将搜索范围缩小到特定子树的好方法。

note.children.title = 'sub-note' 因此,这将在另一个方向上起作用,并将找到具有(至少一个)子级的被称为"sub-note"的笔记。

搜索笔记属性

注意具有某些可用于搜索的属性:

  • noteId
  • dateModified - local dates are in the format "2019-05-19 16:39:47.003+0200"
  • dateCreated
  • utcDateModified - UTC dates are in the format "2019-05-19 14:39:47.003Z"
  • utcDateCreated
  • isProtected (true, false)
  • type (text, code, search, relation-map, book)
  • title (when you want to search specifically the title)
  • text - search through note title and content
  • labelCount
  • relationCount
  • attributeCount - labelCount + relationCount
  • parentCount
  • childrenCount
  • isArchived (true, false)

这些可通过note.访问,例如:

note.type = code AND note.mime = 'application/json'

排序和限制

#author=Tolkien orderBy #publicationDate desc, note.title limit 10

上面的示例将按以下顺序执行以下操作:

  1. 查找作者标签为"Tolkien"的笔记
  2. 按PublicationDate的降序排列结果(最新的在最前面)
  3. 如果发布日期相等,请使用note.title的升序作为第二顺序(asc默认设置,因此可以省略)
  4. 只取前10个结果

Negation

有些查询只能用Negation表示:

#book AND not(note.ancestor.title = 'Tolkien')

这将找到所有不在“Tolkien”子树中的仿书笔记。

内部原理 Under the hood

标签和关系快捷方式

用于按标签搜索的"完整"语法如下:

note.labels.publicationYear = 1954 或者 note.relations.author.title *=* Tolkien

但是考虑到按标签和关系进行搜索非常普遍,因此也存在一种快捷语法:

#publicationYear = 1954#author.title *=* Tolkien

分隔全文部分和属性部分

从上面的示例中您可能已经注意到,搜索语法允许将全文搜索与基于属性的搜索无缝组合。怎么做?

tolkien #book作为一个例子。它包含了:

  1. 全文token - tolkien
  2. 属性表达式 - #book

棘手的部分是找出全文在哪里结束以及属性表达式在哪里开始。这是通过检测某些停止字符/单词来完成的-在遇到#~、或note.前缀之一之前,所有令牌都被视为全文。之后,所有字符/token都被理解为属性表达。

如果你想使用#~note.作为全文的一部分,你需要排除他们,详见下文。

在某些极端情况下,这还不够,例如:

tolkien (#publicationYear >= 1950 AND #publicationYear < 1960) OR #book`

这里以(的表达式开头不是(有意)停止字符,因此上面的查询实际上不会按预期运行。相反,在这些特殊情况下,我们需要添加一个单独的额外停止符#~,所以固定查询应如下所示:

tolkien # (#publicationYear >= 1950 AND #publicationYear < 1960) OR #book`

额外的终止符除了将全文部分与属性表达部分分开之外没有其他作用。

转义特殊字符

符号或值有时具有特殊含义,这可能不是您想要的。可以通过以下方式解决此问题:将包含特殊字符的字符串括在引号中,或者使用反斜杠转义各个字符:

"note.txt" - "note." 通常是停止前缀(stop-prefix),但是在这里它将用于全文搜索

\#hash - #通常是停止字符(stop-character),但此处以反斜杠转义,因此再次用于全文

#myLabel = 'Say "Hello World"' - 支持三种类型的引号:单引号,双引号和反引号。

类型强制转换

重要的是要认识到标签值在技术上始终是字符串,即使它包含逻辑上不同的值也是如此。然后,您可以执行以下操作:

note.dateCreated =* '2019-05'

这将找到在2019年5月创建的笔记,只需在日期上执行字符串"以...开头"即可。

尽管此方法不适用于数字,所以每当检测到数字运算符时,标签值就会从其常规字符串形式强制转换为数字值以进行比较。然后,这允许例如#publicationYear >= 1960正确工作。

从URL自动触发搜索

像下面的示例一样,打开Trilium将打开搜索窗格并自动触发搜索" abc":

http://localhost:8080/#search=abc

本文档介绍了0.43及更老版本中使用的搜索语法。有关最新语法,请参见搜索

Trilium支持在笔记中搜索。有几种搜索笔记的方法:

  • 本地搜索 - 在当前显示的笔记中搜索。按CTRL - F打开搜索对话框。在服务器版本中,这由浏览器处理;在桌面版(Electron版)中,有一个单独的对话框。
  • 全文搜索 - 搜索文本和代码笔记内容。由于此操作是通过数据库搜索实现的,因此仅适用于不受保护的笔记(无论您是否处于受保护的会话中都没关系)
  • 属性搜索 - 例如,您可以搜索具有特定标签的笔记 - 请参阅下面的属性查询语法
  • 您可以将搜索字符串(由全文搜索或属性搜索组成)保存到被称作的"saved search"笔记中。如果展开此笔记,您将看到搜索结果作为子笔记。
  • 保存的搜索还可以通过关系引用脚本 - 展开后,脚本将提供结果列表

您可以通过单击左侧的放大镜图标或按CTRL - S键盘[快捷键)(./键盘快捷键.md)来激活搜索。

全文

每当搜索字符串不是以@(用于属性搜索)或=(用于脚本保存的搜索)开头时,就会触发全文搜索。

全文搜索未归档的未删除,未受保护的文本笔记和代码笔记的标题和内容。

输入字符串由空格分隔符标记,并且每个单独的token(单词)必须出现在标题或内容中。如果您不希望这种自动标记,可以在搜索中用双引号引起来,例如"hello world"将搜索完全匹配。

属性查询语法

标准属性

在这里,您可以按标准属性进行查询:

  • @abc - 返回带有标签abc的笔记
  • @!abc - 返回没有标签abc的笔记
  • @year=2019 - 匹配具有标签year的值为2019的笔记
  • @year!=2019 - 匹配带有标签year,但值不是2019或根本没有标签year的笔记。
    • 如果您想表达条件: 笔记必须带有year标签,但值不是2019,则可以使用@year @year!=2019
  • @year<=2000 - 返回标签year值为2000或更小的笔记。><>=<=d都是支持的。
    • 在这种情况下,参数可以解析为数字,因此可以进行按数字比较。但是也可以以相同的方式按字典顺序比较字符串。如下所示,这对于比较日期很有用。
  • @rock @pop - 匹配同时带有rockpop标签的笔记
    • @rock and @pop 是另一种替代语法
  • @rock or @pop - 只能有一个标签
    • 在搜索字符串中使用两个运算符的情况, and优先级高于or
  • @frontMan=*John - 匹配frontMan标签以"John"开头的笔记。还有!=*b表示"不以…"开头,*=表示"以…结尾"和!*="不以…结尾",*=*表示"包含"和!*=*表示"不包含"

虚拟属性

也可以通过所谓的"虚拟属性"进行查询:

  • dateCreated - 笔记创建日期的本地日期,格式为YYYY-MM-DD HH:mm:ss.sss + OOPP,其中OOPP是相对于UTC的小时和分钟偏移量(例如,中欧时间为"+0100")
  • dateModified - 在YYYY-MM-DD HH:mm:ss.sss + OOPP中对最后一个音符进行修改的本地日期
  • utcDateCreated - 笔记创建日期的UTC日期,格式为YYYY-MM-DD HH:mm:ss.sssZ
  • utcDateModified - 最后一个笔记的修改日期的UTC日期,格式为YYYY-MM-DD HH:mm:ss.sssZ
  • noteId
  • isProtected - 如果笔记受保护,则为1,否则为0
  • title - 如果要单独搜索标题,则很有用
  • content
  • type - ,textcode,,或者imagefilesearchrelation - map
  • mime - 例如text/html表示文字笔记
  • text - 标题和内容的全文属性
    • 例如@text*=*Hello。这样您就可以同时搜索文本和属性。
  • isArchived - 仅过滤归档笔记@!archived然后仅过滤未归档的笔记。请注意,此过滤器在OR关系中不起作用,它始终为AND。
  • in - 例如,@in=VuvLpfAPx2L9将仅过滤那些具有noteId为VuvLpfAPx2L9的笔记作为祖先之一的笔记 - 即笔记在VuvLpfAPx2L9的子树中。使用否定运算符 - @in!=VuvLpfAPx2L9将过滤没有笔记VuvLpfAPx2L9作为其祖先的笔记。始于Trilium 0.37版本

顺序和限制

可以通过一个或多个属性对结果进行排序,例如,@orderBy=year, - genre将按year标签的升序对笔记进行排序,然后按genre标签的降序(由于-符号)对笔记进行排序。

您也可以使用例如:@limit=1仅返回第一个结果来限制结果的数量。如果没有limit,则返回所有笔记。

日期比较

属性值是无类型的字符串,这意味着尽管您可以将诸如数字或日期之类的任何值保存到其中,但是Trilium并不真正知道它是什么类型的值,因此也无法对其进行正确处理。

幸运的是,如果我们坚持以YYYY-MM-DD格式存储日期,我们仍然可以做很多事情,因为这些日期可以作为字符串正确地比较 - 例如@dateCreated>=2015 - 01 - 01,即使Trilium仅进行字符串比较,也将返回自2015年以来创建的笔记。

如果要查找2015年创建的笔记该怎么办?您可以像这样使用"以…开头"运算符(=*):@dateCreated=*2019 - 这将匹配带有以"2019"开头的标签的笔记,该年份创建的所有笔记都将满足。

智能过滤器

Trilium支持一些特殊值,这些特殊值可能会帮助您进行一些搜索查询:

  • NOW 表示此刻且达到秒精度,例如 2019 - 04 - 01 10:12:54
    • NOW - 3600 表示1小时前
  • TODAY 表示今天且精度为天,例如 2019 - 04 - 01
    • TODAY - 1意味着昨天,TODAY+1意味着明天
  • MONTH 表示本月,例如 2019 - 04
    • MONTH - 1 指上个月 - 即 2019 - 03
  • YEAR 表示当前年份,例如 2019
    • YEAR - 1 表示去年 - 2018年

使用此方法,您可以创建查询,例如:

  • @dateModified>=NOW - 3600 - 告诉我过去一小时内更改过的笔记
  • @dateCreated=*TODAY - 1 - 告诉我昨天整个期间创建的笔记

保存的搜索

Trilium提供了一种将常用搜索另存为笔记树中的笔记的方法。搜索结果将作为此"saved search"笔记的子笔记出现。您可以看到它是如何工作的:

使用脚本关系保存搜索

如果保存的搜索字符串以开头=,则将以下字符串用作关系名称,并执行目标脚本以获取音符结果列表。

因此,假设搜索字符串为=handler,然后Trilium尝试找到具有名称为"handler"关系的保存笔记。关系应该指向稍后执行的脚本 - 脚本应该返回的那些应作为搜索结果的笔记列表。对于正常的属性/全文搜索不能满足所有需求的用例,可以选择这个方法。

从URL自动触发搜索

像下面的示例一样,打开Trilium将打开搜索窗格并自动触发搜索"abc":

http://localhost:8080/#search=abc

要轻松访问选定的笔记,您可以为它们添加书签。见演示:

这在技术上所做的是为笔记添加了一个#bookmarked标签。

书签文件夹

左侧面板中的空间有限,您可能想要为许多项目添加书签。一种可能的解决方案是为文件夹添加书签,以便显示其子项:

为此,您需要为笔记添加#bookmarkFolder标签。

笔记挂起(Note Hoisting)是一项标准的大纲功能,通过隐藏所有父级和同级笔记,您可以专注于(或"放大")特定笔记及其子树。演示如下:

除了仅显示此子树之外,这还将全文搜索和"跳转到笔记"缩小为仅存在于挂起子树中的笔记。

Trilium从0.26版开始支持此功能。

另请参阅扩展此功能的工作区

工作区是建立在笔记挂起之上的概念。它基于用户有几个不同的兴趣领域的想法。一个例子可能是“个人”和“工作”,这两个领域非常不同,不会相互作用。当我专注于工作时,我并不真正关心个人笔记。

到目前为止,工作区包含以下功能:

  • 笔记挂起- 您可以“放大”到工作区子树以仅关注相关笔记
  • 轻松进入工作区:

  • 选项卡中工作区的识别特征:

如何使用工作区

假设您已经确定了工作区及其子树。在此子树的根节点上定义以下标签:

  • #workspace- 只需将此笔记标记为工作区,进入工作区的按钮由此控制
  • #workspaceIconClass- 要在树和选项卡中显示的控件框图标,例如bx bx-home。见https://boxicons.com/
  • #workspaceTabBackgroundColor- 选项卡的颜色,使用任何 CSS 颜色格式,例如“lightblue”或“#ddd”

排序

一次性排序

您可以通过右键单击笔记树中的父笔记,Advanced -> Sort notes by ...

自动/永久排序

本文档适用于 0.49 及更高版本。在以前的版本中,#sorted按字母顺序排序

可以通过将#sorted标签附加到父笔记来保持子笔记的排序。

排序的工作原理是比较笔记属性或子笔记上的特定标签。

有 3 个排序级别,其中第一个具有最高优先级,第二个(分别为第三个)仅当基于较高优先级比较的2个笔记相等时才会应用。

  1. 按标签#top隐式排序 - 具有此标签的子笔记将显示在文件夹的顶部。a)如果您有更多子笔记
  2. 按子笔记的属性或父笔记的#sorted标签上定义的特定标签进行排序 a) 父笔记#sorted标签无值 - 默认情况下将按字母顺序进行排序 b) 父笔记具有#sorted=title#sorted=dateModified - 排序将基于定义的笔记的属性完成 c) 父笔记具有带其他值的#sorted标签 - 此值是子笔记将用于排序的标签的名称。例如,您在父笔记上设置#sorted=myOrder,然后子笔记将具有标签#myOrder=001#myOrder=002等。
  3. "last resort"的排序是按字母顺序排列的

所有比较都是按字符串进行的 - 例如 "1" < "2" or "2020-10-10" < "2021-01-15" 还有 "2" > "10".

这应该是键盘快捷键的完整列表。请注意,其中一些可能仅在某些情况下有效(例如,在树窗格或笔记编辑器中)。

从Trilium 0.38开始,可以在Options - > Keyboard中配置键盘快捷方式。

笔记导航

  • UPDOWN - 在笔记列表中向上/向下,CTRL-SHIFT-UPCTRL-SHIFT-DOWN也可以在编辑器中使用
  • LEFTRIGHT - 折叠/展开节点
  • ALT+LEFTALT+RIGHT - 向前/后追溯
  • CTRL+J - 显示"Jump to"对话框
  • CTRL+. - 滚动到当前笔记(当滚动到远离你的笔记或你的焦点位于编辑器中时很有用)
  • BACKSPACE - 跳至父节点笔记
  • ALT+C - 折叠整个笔记树
  • ALT+- (带有减号的alt)- 折叠子树(如果某些子树在树窗格上占用太多空间,则可以将其折叠)
  • 您可以定义一个值为Ctrl+I的标签 #keyboardShortcut。按下此键盘组合将带您进入定义它的笔记。请注意,必须重新加载/重新启动 Trilium (Ctrl+R) 才能使更改生效。

笔记导航中查看其中一些功能的演示。

标签页

  • CTRL+click - 点击笔记链接(或单击鼠标中键)可在新标签页中打开笔记

仅在桌面版(electron版)中:

  • CTRL+T - 打开空白标签页
  • CTRL+W - 关闭活动标签页
  • CTRL+Tab - 激活下一个标签页
  • CTRL+Shift+Tab - 激活上一个标签页

创建笔记

  • CTRL+O - 在当前笔记之后创建新笔记
  • CTRL+P - 在当前笔记中创建新的子笔记
  • F2 - 编辑当前克隆笔记的前缀

移动/克隆笔记

  • CTRL+UPCTRL+DOWN - 在笔记列表中上/下移动笔记
  • CTRL+LEFT - 在笔记树中上移笔记
  • CTRL+RIGHT - 在笔记树中下移笔记
  • SHIFT+UPSHIFT+DOWN - 上/下多项选择音符
  • CTRL+A - 选择当前级别的所有笔记
  • SHIFT+click - 您选择的多选音符
  • CTRL+C - 将当前笔记(或当前选择)复制到剪贴板(用于[克隆)(./克隆笔记.md))
  • CTRL+X - 将当前(或当前选择)笔记剪切到剪贴板中(用于移动笔记)
  • CTRL+V - 将笔记作为子笔记粘贴到当前笔记中(是移动还是克隆,具体取决于它是被复制还是剪切到剪贴板中)
  • DEL - 删除笔记/子树

编辑笔记

  • ENTER在树窗格中,从树窗格切换到笔记标题。从笔记标题点击ENTER可以将焦点切换到文本编辑器。CTRL+.从编辑器切换回树窗格。
  • CTRL+K - 创建/编辑外部链接
  • CTRL+L - 创建内部链接
  • ALT+T - 在插入位置插入当前日期和时间
  • CTRL+. - 从编辑器跳到树状窗格并滚动到当前笔记

运行时快捷方式

这些都内置在Electron中,类似于本机浏览器的键盘快捷键。

  • F5CTRL-R - 重新加载Trilium前端
  • CTRL+SHIFT+I - 显示开发人员工具
  • CTRL+F - 显示搜索对话框

其他

  • ALT+O - 显示SQL控制台(仅当您知道自己在做什么时使用)
  • ALT+M - 无干扰模式-仅显示笔记编辑器,其他所有内容均隐藏
  • F11 - 切换全屏
  • CTRL+S - 在树状窗格中切换搜索
  • ALT+A - 显示笔记属性对话框

默认情况下,Trilium带有很少的颜色主题,白色是默认主题。要切换为深色主题,您只需转到Options(右上方)->Appearance选项卡并更改主题。

看起来是这样的:

自定义CSS主题

Trilium提供了自定义用户主题的概念。您可以通过创建CSS代码笔记并使用appTheme 标签对其进行标注来制作自己的主题。

您可以在下面看到一个示例:

@font-face {
  font-family: 'Raleway';
  font-style: normal;
  font-weight: 400;
  src: url('/custom/fonts/raleway.woff2') format('woff2');
}

body.theme-my-theme {
    --main-font-family: 'Raleway' !important;
    --main-font-size: normal;
    --tree-font-family: inherit;
    --tree-font-size: normal;
    --detail-font-family: inherit;
    --detail-font-size: normal;
    --detail-text-font-family: 'Garamond' !important;

    --main-background-color: #404552;
    --main-text-color: #AFB8C6;
    --main-border-color: #AFB8C6;
    --accented-background-color: #383C4A;
    --more-accented-background-color: #2F343F;
    --header-background-color: #383C4A;
    --button-background-color: #2F343F;
    --button-disabled-background-color: #404552;
    --button-border-color: #333;
    --button-text-color: #AFB8C6;
    --button-border-radius: 2px;
    --primary-button-background-color: #6c757d;
    --primary-button-text-color: white;
    --primary-button-border-color: #6c757d;
    --muted-text-color: #86919F;
    --input-text-color: #AFB8C6;
    --input-background-color: #404552;
    --hover-item-text-color: white;
    --hover-item-background-color: #4877B1;
    --active-item-text-color: white;
    --active-item-background-color: #4877B1;
    --menu-text-color: #AFB8C6;
    --menu-background-color: #383C4A;
    --tooltip-background-color: #383C4A;
    --link-color: lightskyblue;
    --modal-background-color: #404552;
    --modal-backdrop-color: black;
    --scrollbar-border-color: rgba(175, 184, 198, 0.5);
}

body.theme-my-theme .note-detail-text {
    font-size: 120%;
}

body.theme-steel-blue .CodeMirror {
    filter: invert(100%) hue-rotate(180deg);
}

我们定义一个自定义字体(由自定义请求处理程序提供),然后只需定义一堆CSS变量。这些变量之后在Trilium的CSS样式表中使用。您还可以使用标准CSS选择器进行进一步的自定义(使用开放式开发工具CTRL-SHIFT-I来帮助实现此目的),但请记住,HTML结构在将来的版本中可能会发生变化,这可能会破坏你的CSS选择器。因此,最好尽可能限制自己使用CSS变量。

所有CSS选择器都应加上前缀body.theme-my-theme以便仅在选择主题时才应用样式表。此类名称是根据笔记的名称自动创建的,例如,"My theme"将转换为theme-my-themetheme-是常用前缀)。如果您想手动指定类名,则将其设置为appTheme的值(theme-前缀也将添加到最终类的前面)。

要激活您的自定义主题,请转到Options -> Appearance。在选择框中,您应该看到所有标签为appTheme的笔记(主题)。

如果对主题进行了更改,则应按来重新加载前端,通过按CTRL-R以使更改生效。

CSS主题可以导出到.tar存档中,并共享给其他用户。不建议从不受信任的来源中导入CSS主题,因为存档文件中还可能包含可执行脚本,这可能是有害的。

您可以在演示文档|文档#演示文档中找到示例用户主题Steel Blue

自定义CSS

Trilium还允许您创建不与主题关联的自定义CSS。这在脚本编写的环境中很有用,例如,您可能希望更改树中笔记的颜色(如任务管理器中所使用的)。

为此,只需创建一个CSS类型的代码笔记,然后将自定义CSS代码放入笔记中并创建"appCss"标签即可。当Trilium前端启动时,所有带有"appCss"标签的笔记将添加到Trilium HTML页面的style元素中。

进行更改后,可以按CTRL-R重新加载Trilium前端来使更改生效。

样式化笔记树

如果要在树中为某些特定的笔记赋予特殊的样式,可以给它们指定cssClass 标签,然后将其放入代表树中给定笔记的节点中。

还有一种iconClass用法,您可以为树中的笔记定义自定义图标-您可以使用boxicons提供的图标(例如bx bx-home),也可以定义自己的CSS类。其中一些东西实际上是不同的。因此,您拥有bx bxs-piano而不是bx bx-piano。在boxicons网站上,打开文件后,您可以查看字体选项卡来查找文件的命名方式。

当用于模板时,iconClasscssClass特别强大。

您还可以为给定的笔记类型(和mime类型)创建特定的样式。例如,包含PNG图像的文件笔记将在树中具有以下类:type-image mime-image-png

用户提供的主题

以下是Trilium用户开发的主题:

  • https://github.com/Abourass/TriliumThemes
  • https://github.com/ZMonk91/Material-Dark-Trilium
  • https://github.com/jaroet/trilium-theme-lightslategray
  • https://github.com/raphwriter/trilium-theme-melon
  • https://github.com/Engr-AllanG/trilium-themes
  • https://github.com/idelem/trilium-theme-velvet
  • https://github.com/SADAVA/trilium-notes-theme-dark-plus
  • https://github.com/WKSu/trilium-solarized-theme
  • https://github.com/en3r0/Trilium-Nord-Theme
  • https://github.com/Sebiann/miku-hatsune-trilium-theme
  • https://github.com/AllanZyne/trilium-bear-theme

本页介绍在您自己的服务器上安装Trilium。如果您想设置同步,或者要将其用作Trilium的Web版本(可以从任何地方访问它),则可能需要这样做。

有三种方法可供选择,每种选择都有各自的优势:

服务器安装同时具有Web端和移动前端

配置

对于服务器安装,您可能要配置例如port或TLS配置。这是在Trilium配置文件中完成的,默认情况下它在数据目录中的config.ini文件中。

配置位置

config.ini文档和其他一些重要的Trilium数据文件默认保存在数据目录中。

如果不需要,可以通过TRILIUM_DATA_DIR环境变量将其更改为其他位置,例如:

    export TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data

禁用身份验证

除其他外,您还可以使用以下方法禁用身份验证(如果仅在本地主机上运行或身份验证由其他组件处理)。

    [General]
    noAuthentication=true

请注意,只有从0.44版开始,才可以禁用身份验证。

反向代理设置

nginx

    location /trilium/ {
        proxy_pass http://127.0.0.1:8080/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

还建议向server {}中添加以下内容取消有效负载的大小限制:

    # set to 0 for unlimited. Default is 1M.
    client_max_body_size 0;

Apache

请参阅Apache代理设置

本质上,这是Trilium sources + node模块 + node.js runtime,打包到一个7z文件中。

步骤

  • 使用SSH连接到您的服务器
  • 使用wget(或curl其他方式)在您的服务器上下载最新的 trilium-linux-x64-server-[VERSION].xz(注意-server后缀)
  • 解压压缩包,例如使用 tar -xf -d trilium-linux-x64-server-[VERSION].tar.xz
  • cd trilium-linux-x64-server
  • ./trilium.sh
  • 您可以打开浏览器并打开http://[your-server-hostname]:8080,然后应该看到Trilium初始化页面

上述步骤的问题在于,一旦关闭SSH连接,Trilium进程就会终止。为了避免这种情况,请先终止它(例如使用CTRL-C),然后再次运行,如下所示:

nohup ./trilium &

译者注:可以使用nohup ./trilium.sh > log 2&>1 &来重定向输出流和错误流方便定位问题。

使用 systemd 配置系统在启动时自动运行Trilium**

  • 下载后,解压并移动 Trilium:
    tar -xvf trilium-linux-x64-server-[VERSION].tar.xz
    sudo mv trilium-linux-x64-server /opt/trilium
  • 创建服务:
    sudo nano /etc/systemd/system/trilium.service
  • 将其粘贴到文件中(根据需要替换用户和组):
    [Unit]
    Description=Trilium Daemon
    After=syslog.target network.target
    
    [Service]
    User=xxx
    Group=xxx
    Type=simple
    ExecStart=/opt/trilium/trilium.sh
    WorkingDirectory=/opt/trilium/
    
    TimeoutStopSec=20
    # KillMode=process leads to error, according to https://www.freedesktop.org/software/systemd/man/systemd.kill.html
    Restart=always
    
    [Install]
    WantedBy=multi-user.target
  • 保存文件 (CTRL-S) 并退出 (CTRL-X)
  • 启用并开启服务:
    sudo systemctl enable --now -q trilium
  • 现在打开浏览器访问 http://[your-server-hostname]:8080,您应该会看到 Trilium 初始化页面。

常见问题

过时的glibc库

Error: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by /var/www/virtual/.../node_modules/@mlink/scrypt/build/Release/scrypt.node)
    at Object.Module._extensions..node (module.js:681:18)
    at Module.load (module.js:565:32)
    

如果出现这样的错误,则需要升级glibc(通常通过升级到最新的发行版)或使用其他服务器安装方法。

TLS

不要忘记配置TLS,这是安全使用所必需的!

Trilium可以作为docker映像运行。推荐作为在服务器上部署Trilium的方法。

AMD64ARMv6ARMv7ARMv8/64的官方 docker 镜像发布在 docker hub上:https ://hub.docker.com/r/zadam/trilium/

感谢霍华德(Howard)为ARMv7ARMv8提供的非官方docker镜像:https://hub.docker.com/r/hlince/trilium (build scripts)

条件

首先,您需要在计算机上安装 docker。以下是两个可以提供帮助的指南:

拉取镜像

    docker pull zadam/trilium:[VERSION]

将[VERSION]替换为实际的最新版本,或使用“series”标签-例如0.48-latest

不推荐使用“latest”标签,因为它可能会将您的Trilium实例升级到新的次要版本(minor version),这可能会破坏您的同步设置或引起其他问题。

在主机系统上准备数据目录

Trilium 需要一个可以存储其数据的目录,然后需要将其挂载到 docker 容器中。容器作为用户“节点”运行,因此我们需要使该目录可供该用户使用:

    mkdir ~/trilium-data
    chmod 777 ~/trilium-data

由于这允许系统上的任何用户读取/写入此目录,因此建议仅在单用户系统上执行此操作。该目录将在下面使用(挂载)。

运行镜像

这些命令将卷挂载到主机系统,以便在容器停止后保留 trilium 的数据(最重要的是文档)并且不会被清除。

仅限本地

这将运行容器,使其仅在本地主机上可用。使用它来测试安装:通过运行此命令的同一台机器上的 Web 浏览器,或者如果您正在使用带有 nginx/apache 的代理。

    sudo docker run -t -i -p 127.0.0.1:8080:8080 -v ~/trilium-data:/home/node/trilium-data zadam/trilium:[VERSION]
  1. 使用docker ps测试并查看 docker 映像是否正在运行:
  2. 通过打开浏览器并转到127.0.0.1:8080访问 trilium 

仅限本地网络

此命令将运行容器,使其仅在您的本地网络上可用。如果您不想向 Internet 的其余部分开放端口,则此方法更为可取。但是,您仍然可以通过使用 WireGuard 之类的 VPN 首先进入您自己的网络从外部访问它。此方法确实假定您的本地网络限制外部访问。

首先,您必须在 Docker 中创建一个新网络来访问您的本地网络。这是一个示例,请注意“parent”和网络编号,因为它可能与您自己的不同。如需更多详细信息,请单击此处

    docker network create -d macvlan -o parent=eth0 --subnet 192.168.2.0/24 --gateway 192.168.2.254 --ip-range 192.168.2.252/27 mynet

其次,您必须调整 docker run 命令,以便将这个网络考虑在内,但继续使用 localhost 来限制端口对外界的可访问性。

    docker run --net=mynet -d -p 127.0.0.1:8080:8080 -v ~/trilium-data:/home/node/trilium-data zadam/trilium:0.48-latest

最后,使用 docker inspect 查找要连接的本地 IP 地址。您可以从连接到本地网络的所有设备访问它,例如:[local:ip]:8080。

    docker ps
    docker inspect [container_name] 

随处可用

这会将容器作为后台进程运行,并且可以从任何 IP 地址访问

    docker run -d -p 0.0.0.0:8080:8080 -v ~/trilium-data:/home/node/trilium-data zadam/trilium:[VERSION]

要停止此后台 docker 进程,请使用docker ps获取“CONTAINER ID”,然后使用docker stop <CONTAINER ID>

不同的数据目录位置

如果您想以非默认方式运行您的实例,请如下所示使用volume转换:-v ~/YourOwnDirectory:/home/node/trilium-data zadam/trilium:[VERSION]. 重要的是要了解 Docker 如何使用volume工作,第一个路径是您自己的,第二个路径是虚拟绑定的。详细信息: https://docs.docker.com/storage/volumes/

本页介绍如何在服务器上手动安装Trilium。

需求

Trilium是一个node.js应用程序。支持(测试)的 node.js 版本是最新的 14.XX 和 16.XX Trilium旧版本可能也适用。

您可以使用以下命令检查节点版本(需要安装node.js):

    node --version

如果您的Linux发行版仅包含过时的node.js版本,那么您可以查看node.js网站上的安装手册,该手册涵盖了最受欢迎的发行版。

依赖项

需要有一些依赖关系才能编译。您可以在下面看到Debian及其衍生版本(如Ubuntu)的命令:

    sudo apt install libpng16-16 libpng-dev pkg-config autoconf libtool build-essential nasm libx11-dev libxkbfile-dev

安装过程

下载

您可以从最新版本下载源代码zip / tar,也可以从stable分支克隆git仓库,方法如下:

    git clone -b stable https://github.com/zadam/trilium.git

安装

    cd trilium
    
    # download all node dependencies
    npm install
    
    # make sure the better-sqlite3 binary is there
    npm rebuild

运行

    cd trilium
    
    # using nohup to make sure trilium keeps running after user logs out
    nohup node src/www &

默认情况下,应用程序在端口8080上启动,因此您可以打开浏览器并导航到http://localhost:8080以访问Trilium(将“ localhost”替换为主机名)。

TLS

不要忘记[配置TLS)(./TLS配置.md),这是安全使用所必需的!

由于 Trilium 可以在 Docker 中运行,它也可以部署在 Kubernetes 中。Trilium 可以手动或按通过helm chart 应用于 Kubernetes。

推荐的方式是helm。

安装helm

非官方的helm chart:ohdearaugustin: https://github.com/ohdearaugustin/charts

添加 helm 存储库

    helm repo add <repo_name> https://ohdearaugustin.github.io/charts/
    "<repo_name>" has been added to your repositories

如何安装图表

只需运行helm install <repo_name>/trilium-notes

有关使用 Helm 的更多信息,请参阅 Helm 文档。

我假设您已经创建了trilium.yourdomain.com的DNS的A记录,用于Trilium服务器。

  1. 下载Docker镜像并创建容器
     docker pull zadam/trilium:[VERSION]
     
     docker create --name trilium -t -p 127.0.0.1:8080:8080 -v ~/trilium-data:/root/trilium-data zadam/trilium:[VERSION]
  1. 配置Apache代理和WebSocket代理

i. 启用apache代理模块

     a2enmod ssl
     a2enmod proxy
     a2enmod proxy_http
     a2enmod proxy_wstunnel

ii. 创建一个新的let's encrypt加密证书

     sudo certbot certonly -d trilium.mydomain.com

选择standalone (2)并记下创建的证书的位置(通常为/etc/letsencrypt/live/...)

iii. 为apache创建一个新的虚拟主机文件(您可能要使用它apachectl -S来确定服务器的根目录,我的是/etc/apahce2)

     sudo nano /etc/apache2/sites-available/trilium.yourdomain.com.conf

将以下文本粘贴(并自定义)到配置文件中

     <VirtualHost *:80>
         ServerName http://trilium.yourdomain.com
     	RewriteEngine on
             RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
     </VirtualHost>
     <VirtualHost *:443>
         ServerName https://trilium.yourdomain.com
         RewriteEngine On
     	RewriteCond %{HTTP:Connection} Upgrade [NC]
     	RewriteCond %{HTTP:Upgrade} websocket [NC]
     	RewriteRule /(.*) ws://localhost:8080/$1 [P,L]
         AllowEncodedSlashes NoDecode
         ProxyPass / http://localhost:8080/ nocanon
         ProxyPassReverse / http://localhost:8080/
         SSLCertificateFile /etc/letsencrypt/live/trilium.yourdomain.com/fullchain.pem
         SSLCertificateKeyFile /etc/letsencrypt/live/trilium.yourdomain.com/privkey.pem
         Include /etc/letsencrypt/options-ssl-apache.conf
     </VirtualHost>

iv. 通过sudo a2ensite trilium.yourdomain.com.conf启用虚拟主机 

v. 用sudo systemctl reload apache2重新加载apache2 

  1. 创建并启用systemd服务以在系统启动时启动Docker容器

i. 创建一个新的空文件/lib/systemd/system/trilium.service,其内容为

     [Unit]
     Description=Trilium Server
     Requires=docker.service
     After=docker.service
     	
     [Service]
     Restart=always
     ExecStart=/usr/bin/docker start -a trilium
     ExecStop=/usr/bin/docker stop -t 2 trilium
     	
     [Install]
     WantedBy=local.target

ii. 安装,启用并启动服务

     sudo systemctl daemon-reload
     sudo systemctl enable trilium.service
     sudo systemctl start trilium.service

配置 Nginx 代理和 HTTPS。演示使用的操作系统是 Ubuntu 18.04。

  1. 下载 Nginx 并删除 Apache2
    sudo apt-get install nginx
    sudo apt-get remove apache2
  1. 创建配置文件
    cd /etc/nginx/conf.d
    vim default.conf
  1. 使用如下所示的上下文填写文件,部分设置显示被更改。然后,您可以使用 HTTPS 强制和代理来享受您的网络。
    # This part is for proxy and HTTPS configure
    server {
        listen 443;
        server_name trilium.example.net; #change trilium.example.net to your domain without HTTPS or HTTP.
        ssl_certificate /etc/ssl/note/example.crt; #change /etc/ssl/note/example.crt to your path of crt file.
        ssl_certificate_key /etc/ssl/note/example.net.key; #change /etc/ssl/note/example.net.key to your path of key file.
        ssl on;
        ssl_session_cache builtin:1000 shared:SSL:10m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
        ssl_prefer_server_ciphers on;
        access_log /var/log/nginx/access.log; #check the path of access.log, if it doesn't fit your file, change it
        
        location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_pass http://IP:port; #change it to your IP and port
            proxy_read_timeout 90;
            proxy_redirect http://IP:port https://trilium.example.net; #change them based on your IP, port and domain
        }
    }
    # This part is for HTTPS forced
    server {
                listen 80;
                server_name trilium.example.net; # change to your domain
                return 301 https://$server_name$request_uri;
    }

TLS配置是服务器安装所必需的,它与桌面端的使用无关。

首先要做的是获取TLS证书。您有两种选择:

  • 推荐 - 获取由根证书颁发机构(root certificate authority)签名的TLS证书。对于个人用途,最好的选择是Let's encrypt。它是免费的、自动化且容易的。
  • 生成自己的自签名证书。将证书导入到您连接到服务器安装的所有计算机中时会遇到额外的麻烦,因此不建议这样做。

修改config.ini

现在您已经有了证书,我们需要修改数据目录中的config.ini,以便Trilium使用它:

[Network]
port=8080
# true for TLS/SSL/HTTPS (secure), false for HTTP (unsecure).
https=true
# path to certificate (run "bash bin/generate-cert.sh" to generate self-signed certificate). Relevant only if https=true
certPath=/[username]/.acme.sh/[hostname]/fullchain.cer
keyPath=/[username]/.acme.sh/[hostname]/example.com.key

上面仅是当我使用Let's encrypt程序生成证书时如何在环境中设置的示例。您的路径可能完全不同。(请注意,如果您使用的是Docker安装,则这些路径应位于docker容器对应的分区或其他路径中。)

设置完之后,您可以重新启动Trilium,然后就可以使用"https"访问主机名。

如果您想在桌面上使用 Trilium,请从最新版本下载适用于您平台的二进制版本,解压缩包并运行trilium可执行文件。

启动脚本

还有其他一些启动 Trilium 的选项:

  • trilium-no-cert-check - Trilium 不会验证证书,例如当您使用自签名证书与同步服务器同步时很有用
  • trilium-portable - Trilium 将尝试在 trilium 的目录中创建数据目录
  • trilium-safe-mode - 以“安全模式”启动,禁用任何可能导致应用程序崩溃的启动脚本

同步

如果您使用的是桌面实例并希望与您的服务器实例同步:同步

Trilium是离线优先笔记应用程序-使用桌面应用程序时,所有数据都存储在本地,但是您还可以选择设置与服务器实例的同步。当添加另一个桌面客户端时,您可以进入星形拓扑:

这意味着有一个中央服务器(我们将其称为_同步服务器_)和多个_客户端_(有时称为_桌面_)实例,它们均指向该同步服务器并与其同步。

设置好同步后,同步将自动持续进行-您无需手动触发。它就应该“正常工作”。

如何设置同步

设置从桌面实例到同步服务器的同步

当您已经拥有Trilium的桌面实例并且想要[在Web主机上设置同步服务器)(./服务器安装.md))时,可以使用这种方法。

因此,假设您的服务器实例已经部署,但是尚未初始化(没有数据)。然后打开您的桌面实例,单击Options -> Sync tab -> Sync configuration,并将"Server instance address"设置为指向您的同步服务器。单击Save。

现在单击"Test sync"按钮,它将告诉您与同步服务器的握手是否成功。如果是,则与同步服务器启动同步-客户端开始将所有数据推向服务器实例。这可能需要一些时间才能完成,但是您可以关闭"Options"对话框并继续使用Trilium。

您还可以定期检查服务器实例,以查看同步是否完成。完成后,您应该会看到登录屏幕。

从同步服务器执行安装程序同步执行桌面实例

当您已经有同步服务器并且想要设置桌面实例以与其进行同步时,将使用此方法。

在这里,我们假设您下载了平台的最新版本,并将其解压缩并运行。

由于桌面实例完全是空的,它将首先询问您是要创建初始文档还是要设置与同步服务器的同步-您需要选择第二个选项。

您将需要配置Trilium服务器地址,并且重要的是还要正确的用户名/密码(同步设置需要身份验证)。

点击"Finish setup"按钮,如果一切顺利,您将看到以下界面:

同步完成后,您将自动重定向到Trilium应用程序。

代理设置

支持两种不同的设置:

  • 您可以在"Options / Sync"中显式设置要使用的代理服务器。当前仅支持未经身份验证的代理服务器。
  • 如果未明确配置代理服务器,则Trilium将使用系统代理设置

证书问题

使用 TLS 时,Trilium 客户端将尝试验证服务器证书。在某些情况下(自签名证书、某些公司代理服务器),验证将不成功,同步将失败。在这些情况下,您可以运行 Trilium 客户端并将环境变量NODE_TLS_REJECT_UNAUTHORIZED设置为0

export NODE_TLS_REJECT_UNAUTHORIZED=0

TLS 证书不会被验证,只是按原样接受。

较新的 Trilium 版本中的脚本为trilium-no-cert-check.sh

冲突解决

有时您会遇到这样的情况:在同步笔记更改之前,您需要在多个实例中编辑同一笔记。

Trilium通过仅接收较新的更改并丢弃较旧的更改来处理这种情况。较早的更改在笔记修订仍然应该可见,因此可以恢复在解决冲突中丢失的所有数据。

哈希检查

每次完成同步后,Trilium都会计算客户端和同步服务器上所有同步数据的哈希值。如果存在差异,则说明出现问题,Trilium将运行自动恢复机制。

Trilium([服务器版)(./服务器安装.md))具有一个移动Web前端,该前端针对基于触摸的设备(智能手机和平板电脑)进行了优化。它会在登录过程中基于浏览器检测自动激活。

与完整的桌面前端相比,移动前端的功能受到限制。有关更多详细信息,请参见下文。

请注意,这不是Android / iOS应用,这只是[服务器版)(./服务器安装.md)上提供的移动友好的网页。

屏幕截图

手机

平板

局限性

移动前端仅提供完整桌面前端的某些功能:

  • 可以浏览整个笔记树,阅读和编​​辑所有类型的笔记,但是您只能创建文本笔记
  • 可以阅读和编辑受保护的笔记,但不支持创建隐私笔记
  • 不支持编辑选项
  • 不支持克隆笔记
  • 不支持上传文件附件

强制使用移动/桌面前端

Trilium自动决定是使用移动前端还是桌面前端。如果不合适,则可以在登录页面上使用?mobile?desktop查询参数(即,可能需要注销)。

脚本

您可以像普通前端一样使用脚本更改行为。对于要执行的脚本,它们需要有标签#run=mobileStartup

Trilium Web Clipper是一个Web浏览器扩展,它允许用户剪辑文本,屏幕截图,整个页面和简短笔记,并将其直接保存到Trilium笔记中。

项目托管在这里。支持Firefox和Chrome浏览器,chrome版本也可以在其他基于chrome内核的浏览器上运行。

功能

  • 选择文本并使用上下文菜单对其进行剪辑(右键单击)
  • 单击图像或链接并通过上下文菜单将其保存
  • 从弹出菜单或上下文菜单中保存整个页面
  • 从弹出菜单或上下文菜单中保存屏幕截图(使用裁剪工具)
  • 从弹出窗口创建简短的文本笔记

Trilium会将这些剪裁另存为新的子笔记,并将其保存在"clipper inbox"笔记下。Clipper Inbox为:

  • 如果有一个带有clipperInbox[标签)(./属性.md)的笔记,则该笔记将用作剪切笔记的父项
  • 否则,日志笔记将用作父节点

如果同一页面(在同一天)有多个剪切笔记,那么它们将被添加到同一笔记中。

获取方式

扩展来自:

配置

该扩展程序需要连接到正在运行的Trilium实例。默认情况下,它扫描本地计算机上的端口范围以找到桌面Trilium实例。

对于桌面应用程序当前未运行的情况,也可以配置[服务器)(./服务器安装.md)地址。

此页面的主题是将Trilium从一个版本升级到另一个版本。

如何升级

Trilium没有内置的自动升级 - 所有升级都必须手动完成。如何执行此操作取决于安装方法:

  • 用于Docker安装服务器 - 拉取较新版本的映像并重新启动
  • 对于所有其他版本,您需要从发布页面下载您选择的发布工件的新版本,并替换应用程序的现有版本 - 即重命名/删除旧目录并提取新版本的归档文件

文档兼容性和迁移

在Trilium启动过程中,将检查文档是否符合应用程序支持的版本。如果文档为旧版本,Trilium将自动将其迁移到新版本。这将意味着旧版本的Trilium将不再可读该文档。如果您想返回到文档和Trilium的旧版本,则可以还原在每次迁移之前创建的备份backup-before-migration.db

同步兼容性

同步协议已版本化,并且同步集群的所有成员都需要使用相同的协议版本进行通话。因此,从一个版本升级到另一个版本时,可能有必要升级集群中的所有实例。

协议版本的更改通常在发行页面上显示。

Trilium支持简单的备份方案,该方案可在以下情况下保存文档副本:

  • 一天一次
  • 每周一次
  • 每月一次
  • 在将数据库迁移到较新版本之前

因此,总共您最多可以从不同的时间点获得4个备份,这可以保护您免受各种问题的影响。这些备份默认情况下存储在数据目录中的backup目录中。

这只是一个非常基本的备份解决方案,建议您添加一些更好的备份解决方案-例如,将文档备份到云/其他计算机等。

请注意,同步还通过将数据分发到其他计算机的性质而提供了一些备份功能。

恢复备份

假设您要还原每周备份,请按以下步骤操作:

  • 查找Trilium使用的数据目录-简单的方法是从左上角的“Menu”中打开“About Trilium Notes”,然后查看“data directory”
    • 从现在开始我将~/trilium-data称为数据目录
  • 查找~/trilium-data/backup/backup-weekly.db文件-这是文档备份
  • 此时停止/终止Trilium
  • 删除~/trilium-data/document.db~/trilium-data/document.db-wal~/trilium-data/document.db-shm(后面两个文件是自动生成的)
  • 复制并将~/trilium-data/backup/backup-weekly.db重命名为~/trilium-data/document.db-这将删除文档的当前状态,因此您可能需要将其备份到其他位置
  • 确保文件是可写的,例如chmod 600 document.db
  • 再次启动Trilium

如果已配置同步,则需要在同步集群的所有成员之间进行同步,否则将检测到文档的旧版本(还原的备份)并将其同步到新版本。

禁用备份

虽然不建议这样做,但可以config.ini数据目录中禁用备份:

    [General]
    
    ... some other configs
    
    # set to true to disable backups (e.g. because of limited space on server)
    noBackup=true

请参阅示例配置

数据目录包含:

  • document.db - 文档
  • config.ini - 实例设置文件,例如运行Trilium应用程序的端口
  • backup - 包含自动的文件备份
  • log - 包含应用程序日志文件

位置

查找Trilium使用哪个数据目录的简单方法是查看"About Trilium Notes"对话框(位于左上角的"Menu"中):

确定位置的方法如下:

数据目录通常是命名的trilium-data,它存储在:

  • /home/[user]/.local/share  对于Linux
  • C:\Users\[user]\AppData\Roaming 适用于Windows Vista及更高版本
  • /Users/[user]/Library/Application Support 对于Mac OS
  • 如果上面的某些路径不存在,则用户的home是一个后备路径
  • 用户的home也是[docker)(./Docker安装服务器.md)的默认设置

如果要备份Trilium数据,只需备份该文件-它包含您需要的所有内容。

更改数据目录的位置

如果要使用默认目录以外的其他位置用于数据目录,则可以通过TRILIUM_DATA_DIR环境变量将其更改为其他位置:

Linux

export TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data

Mac OS X

您需要在~/Library/LaunchAgents下面创建一个.plist文件,以便在每次登录时正确加载该文件。

要手动加载,您需要使用 launchctl setenv TRILIUM_DATA_DIR <yourpath>

这是一个预定义的模板,您只需要在其中添加路径即可:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">
    <dict>
        <key>Label</key>
        <string>set.trilium.env</string>
        <key>RunAtLoad</key>
        <true/>
        <key>ProgramArguments</key>
        <array>
            <string>launchctl</string>
            <string>setenv</string>
            <string>TRILIUM_DATA_DIR</string>
            <string>/Users/YourUserName/Library/Application Support/trilium-data</string>
        </array>
    </dict>
</plist>

创建脚本以与特定数据目录一起运行

全局设置环境变量的替代方法是仅使用此环境变量运行Trilium Notes。这允许使用不同的安装方式比如两个文档实例或"便携式"安装。

要在基于Unix的系统中做到这一点,只需如下所示运行trilium:

TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data trilium

为了方便起见,您可以将上述命令另存为shell脚本。

笔记属性是给定笔记所拥有(分配)的键值记录。

属性有两种类型:

  • 标签-简单的键值文本记录
  • 关系-指定到另一个笔记的命名关系(链接)

有时我们在谈论标签和关系-请记住,它们都是属性的类型。

标签

标签可用于多种用途:

  • 作为具有可选值的标签 - 例如,在对书籍进行编目时,您可以添加诸如 #year=1999、#genre="sci-fi"、#author="Neal Stephenson" 之类的标签
  • 属性可用于配置一些高级功能/设置 - 见下文
  • 插件/脚本可以使用这些来标记带有一些特殊值/元数据的笔记(例如,基于可以创建图表的日志笔记体重追踪器将具有“重量”属性)。

标签可用于搜索

标准标签

以下标签用于高级配置:

  • disableVersioning-禁用自动版本化。对于大型但不重要的笔记很有用-例如用于脚本编写的大型JS库
  • calendarRoot-标记用作日志笔记的根的笔记。只能有一个有这样标记的笔记。
  • archived-具有此标签的注释在基于自动完成的搜索中将不可见(跳转,添加链接)。也适用于其所有子节点。
  • excludeFromExport -笔记(及其子树)不会包含在任何笔记导出中
  • run-定义脚本应在哪些事件上运行。可能的值为:
    • frontendStartup -Trilium前端启动(或刷新)时。
    • backendStartup -Trilium后端启动时
    • hourly -每小时运行一次
    • daily -每天运行一次
  • disableInclusion -具有此标签的脚本不会包含在父脚本执行中。
  • sorted -使子笔记按标题按字母顺序排序。请参阅排序
  • hidePromotedAttributes
  • readOnly-编辑器处于只读模式。仅适用于文本笔记。在这里查看一些用例。
  • autoReadOnlyDisabled- 文本/代码笔记太大时可以自动设置为只读模式。您可以通过将此标签添加到笔记来禁用此行为
  • cssClass- 然后将此标签的值作为 CSS 类添加到表示树中给定笔记的节点。这对于高级主题很有用。可以在template笔记中使用。
  • iconClass- 此标签的值作为 CSS 类添加到树上的图标中,有助于在视觉上区分树中的笔记。一个例子:bx bx-home- 图标取自boxicons。可用于模板笔记。
  • customRequestHandlercustomResourceProvider- 请参阅自定义请求处理程序
  • widget- 见自定义小部件
  • workspace, workspaceIconClass, workspaceTabBackgroundColor- 见工作区
  • searchHome- 新的搜索笔记将作为该笔记的子项创建(否则它们将在日志笔记中创建)
  • hoistedSearchHome- 当提升到该笔记的某个祖先时,将创建新的搜索笔记作为该笔记的子项
  • inbox- 新笔记的默认inbox位置
  • hoistedInbox- 当挂起到此笔记的某个祖先节点时,新笔记的默认inbox位置
  • sqlConsoleHome- SQL 控制台笔记的默认位置
  • bookmarkedbookmarkFolder- 见书签
  • shareXXX共享中描述的标签
  • keyboardShortcut可以定义为例如“Ctrl+I”。按下此键盘组合将带您进入定义它的笔记。请注意,必须重新加载/重新启动 Trilium (Ctrl+R) 才能使更改生效。

关系

关系是两个笔记之间的一种链接。

例如,在保留书籍数据库时,可以使用此关系,可以通过在书本上定义指向作者笔记的"author"关系,来使用关系来保持书(本笔记)与该书的作者(笔记)之间的正式链接。

关系还用于一些高级脚本编写,例如将脚本附加到某些笔记上发生的事件。

标准关系

事件

  • runOnNoteCreation -在后端创建笔记时执行
  • runOnNoteTitleChange -在笔记标题更改时执行(还包括笔记创建)
  • runOnNoteChange -更改笔记时执行(还包括笔记创建)
  • runOnChildNoteCreation -在_此_笔记下创建新笔记时执行
  • runOnAttributeCreation-在_此_笔记下创建新属性时执行
  • runOnAttributeChange-在_此_笔记下更改属性时执行

其他关系:

  • template-即使没有父子关系,附加笔记的属性也会被继承。有关详情,请参见模板
  • renderNote -类型为"render HTML note"的笔记将使用代码笔记(HTML或脚本)进行渲染,并且需要使用此关系指向应渲染的笔记
  • widget -此关系的目标将被执行,并在侧边栏中显示为小部件
  • shareXXX 共享中描述的标签

多重性

属性允许多重性-可以有多个具有相同名称的属性。然后,我们将此类属性称为"多值属性"。

属性定义/提升的属性

特殊类型的标签用于创建“标签/属性”定义。有关详细信息,请参阅 提升属性

属性继承

请参阅属性继承

每个属性都有一个名为isInheritable的标签。如果为真,则此属性(键值)也将应用于其所有子笔记,子笔记的子笔记等。

archived标签在Jump to / Add link 对话框中隐藏其笔记的示例,这可能很有用。通常,您想归档某些特定的子树,可以通过使archived标签可继承来实现。

复制继承

使用child:属性名称前缀可以实现不同种类的继承。如果我们在具有child:exampleAttribute属性的笔记中创建子笔记,则子笔记将创建exampleAttribute属性。这甚至可以链接在一起,例如#child:child:exampleAttribute,在这种情况下,#child:exampleAttribute将在子节点中创建,exampleAttribute将在子节点的孩子中创建。

应该使用哪种类型的属性继承(或如果有的话)取决于特定的用例。

模板继承

[属性模板)(./模板.md)也可以看作是一种继承形式。

提升属性是被认为很重要的属性,因此被"promoted"到主笔记的UI中。请参见下面的示例:

您可以看到笔记具有几种字段的形式。这些都只是常规属性,唯一的区别是它们出现在笔记本身上。

属性非常有用,因为它们允许查询和脚本自动化等。但是,它们也很不方便地隐藏在笔记属性对话框中。这样,您就可以选择几个重要的条目,并将其推到用户的最前面。

现在,我们如何使属性出现在UI上?

属性定义

属性始终是名称-值对,其中名称和值都是字符串。

属性定义指定应如何解释此值-它只是字符串还是日期?我们应该允许多个值或者笔记?重要的是,我们是否应该提升该属性?

在上图中,您可以看到两个标签-具有一些值的tag和todoDate。但是在它们下面,您会再次注意到tag和todoDate属性,但是现在是"Label definition"类型。这些"definition"属性定义"value"属性的行为。

因此,值有一个属性,而定义有一个属性。但是请注意,"definition"属性如何是[可继承的)(./属性继承.md),这意味着它也适用于所有子代笔记。因此,以某种方式,此定义用于整个子树,而"value"属性仅应用于此笔记。

逆关系

有些关系总是成对出现-我最喜欢的例子是家庭。如果您有代表丈夫的笔记和代表妻子的笔记,则这两个之间可能存在关系isPartnerOf。这是双向关系,也就是说,如果某个关系是从丈夫到妻子指向的,那么应该总是存在另一个从妻子到丈夫指向的关系。

另一个例子是与父母-孩子的关系。同样,它们总是成对出现,但是在这种情况下,它不是完全相同的关系-从父级到子级的关系可能会调用isParentOf,而另一个从子级到父级的关系会调用isChildOf

关系定义允许您指定这样的"逆关系"-对于刚刚定义的关系,您可以指定哪个是逆关系。需要注意的是在第二个例子中,我们应该有两个关联定义-一个用于定义isParentOf,它定义isChildOf为逆关系,而第二个关系定义isChildOf,它定义isParentOf为逆关系。

这在内部的作用是,每当保存定义了逆关系的关系时,我们都要检查该逆关系是否存在于关系目标笔记上。同样,当我们删除关系时,我们也会删除目标笔记上的逆关系。

模板是一个笔记,可作为其他笔记(我们称其为实例笔记)的"模板"。

将模板关系分配给笔记会带来以下三个效果:

  • 模板笔记的所有属性都将[继承)(./属性继承.md)到实例笔记
  • 笔记内容从模板笔记复制到实例笔记(如果在分配模板属性时实例笔记内容为空)
  • 模板的所有子笔记均是实例笔记的深拷贝

实例

一个典型的示例是"Book"模板笔记,它将:

  • 定义一些提升属性-例如出版年份,作者等
  • 您还可以在笔记文本中创建书评的大纲-例如主题,结论等。
  • 您还可以为突出显示,摘要等创建子笔记。

实例说明

然后我们有实例笔记 - 此笔记与“Book”模板笔记相关,这将导致模板笔记文本用于初始化实例笔记文本,并且模板笔记中的所有属性都继承到实例笔记。

您可以通过 UI 创建实例笔记(即使用模板的笔记),如下所示:

要使模板显示在菜单中,模板笔记需要具有标签(不要将其与从实例笔记指向模板笔记的关系混淆)。#template``~template

您还可以在创建笔记后添加/更改模板笔记,只需创建指向所需模板笔记的关系即可。~template

其他备注

从视觉角度来看,模板可以定义iconClasscssClass属性,以便所有(例如,书籍)都以特定的图标和CSS样式显示。

您可以在演示文档中的关系映射图任务管理器日志笔记中查看概念。

创建新笔记时,其名称默认为“new note”。在某些情况下,可能需要具有不同的甚至动态的默认笔记标题。

对于此用例,Trilium(从 v0.52 开始)支持#titleTemplate标签。您可以为给定笔记创建此类标签,为其分配一个值,在创建子笔记时,此值将用作默认标题。与其他标签一样,您可以使其可继承以递归方式应用,甚至可以将其放在根笔记上,以便在所有位置全局应用它。

作为一个示例用例,假设您收集了您在给定年份中阅读过的书籍,如下所示:

  • 2022 Books
    • Neal Stephenson: Anathem, 2008
    • Franz Kafka: Die Verwandlung, 1915

现在,对于父笔记“2022 Books”,您可以分配标签 。#titleTemplate="[Author name]: [Book title], [Publication year]"

“2022 Books”的所有子级都将以初始标题“[Author name]: [Book title], [Publication year]”创建。这里没有人工智能,这个想法只是提示你自己手动将信息填充到笔记标题中。

动态值

#titleTemplate的值在笔记创建时作为 JavaScript 字符串进行评估,这意味着它可以在 JS 字符串插值和动态数据的帮助下进行丰富。

例如,假设您收集服务器中断事件并编写一些笔记。它看起来像这样:

  • Incidents
    • 2022-05-09: System crash
    • 2022-05-15: Backup delay

您可以通过为父笔记“Incidents”分配标签来自动分配日期分配。每当创建新的子笔记时,都会使用注入的 now 对象评估标题模板。#titleTemplate="${now.format('YYYY-MM-DD')}: "

注入的第二个变量是 parentNote,例如 。#titleTemplate="${parentNote.getLabelValue('authorName')}'s literary works"

另请参阅提供类似功能的模板,包括默认笔记的内容。

关系映射图是一种将笔记及其关系可视化的笔记。看一个例子:

开发过程演示

这是一个基本示例,您可以使用关系图创建简单的关系映射图:

这是创建它的方法:

我们首先从头创建名为"开发过程"的新笔记,然后将其类型更改为"Relation map",从头开始。之后,我们一个接一个地创建新笔记,然后单击将其放置。我们还可以拖动笔记之间的关系并命名它们。就这样!

map上的项-"Specification","Development","Testing" 和"Demo"实际上是在"开发过程"笔记下创建的笔记-您可以单击它们并写一些内容。笔记之间的连接称为关系

家庭关系演示

这是使用一些高级概念的更复杂的演示。结果图在这里:

这是您的方法:

这里有几个步骤:

  • 我们从空关系映射图和代表Prince Philip和Queen Elizabeth II的两个现有笔记开始。这两个笔记已经定义了" isPartnerOf"关系
    • 实际上有两种"逆"关系(一种是从菲利普到伊丽莎白,另一种是从伊丽莎白到菲利普)
  • 我们将两个笔记都拖动到关系映射图,然后放置到合适的位置。注意如何显示现有的"isPartnerOf"关系。
  • 现在我们创建新笔记-我们将其命名为"Prince Charles",然后通过单击所需位置将其放置在关系图上。默认情况下,笔记是在关系图笔记下创建的(在左侧的笔记树中可见)。
  • 我们针对Philip和Elizabeth创建了两个新的关系"isChildOf"
    • 现在出现了一些意外情况-我们还可以看到该关系以显示另一个"hasChild"关系。这是因为存在一个关系定义,该关系定义将"isChildOf"作为"hasChildOf"的"[逆)(./提升属性.md#逆关系)"关系(反之亦然),因此将自动创建它。
  • 我们为Princess Diana创建了另一个笔记,并从Charles创建了"isPartnerOf"关系。再次注意关系如何同时具有双向箭头-这是因为"isPartnerOf"定义再次将其逆关系指定为"isPartnerOf",因此将自动创建相反的关系。
  • 最后一步,我们可以平移和缩放地图以使其更适合窗口尺寸。

上面提到的关系定义来自"Person template"笔记,该笔记分配给"My Family Tree"关系笔记的任何子项。您可以在演示文档中进行整个操作。

See also

笔记映射图是笔记之间联系的可视化。

这提供了对笔记结构(“网络”)的检查。

有两种类型的笔记映射图:

链接图

显示笔记之间的[关系)(./属性.md):

树图

显示笔记之间的层次图:

See also

关系映射图是一个类似的概念,但有一些区别:

  • 笔记映射图是自动生成的,而关系映射图必须手动创建
  • 关系映射图是一种笔记,而笔记映射图只是虚拟可视化

书笔记是一种笔记类型,以线性方式显示其所有的子节点笔记的内容,所以你可以像阅读一本书一样阅读笔记子树。这对于阅读许多较小的笔记可能很有用。看一个例子可能会更好地解释这个概念:

请注意,在左窗格的树中,"node.js"笔记如何具有一些子项笔记,然后将这些子项显示在右窗格中。

您还可以在 Book 属性中切换到“网格视图”:

要放大和缩小,可以使用按钮,也可以将标签bookZoomLevel的值设置为1到6之间-这表示列数(1表示每个笔记占据右窗格的整个宽度)

请注意,自Trilium 0.36起提供了书籍笔记功能

从 v0.49 开始,Trilium 提供了一个功能,可以将选定的笔记共享为可公开访问的只读文档。

此功能的基本先决条件是安装服务器 - 这是托管笔记的地方。

共享笔记

点击“shared”开关,会出现可以点击的 URL。

这是打开的链接:

该 URL 指的是 localhost (127.0.0.1),因为没有配置同步服务器。

共享笔记子树

共享便笺实际上共享整个便笺子树,上面显示的便笺只是没有任何子节点。

如果我共享整个“格式化”子树,则页面如下所示:

您可以在右侧看到基本导航。有了这个,您可以创建小型网站。

高级选项

为共享笔记设置样式

默认共享页面非常简陋。如果您想更好地设计它,您可以:

  • 添加~shareCss与将在共享页面中链接的 CSS 代码注释的关系
    • 如果您希望将其应用于整个子树,请不要忘记使标签可继承
    • 链接的 CSS 代码注释也需要在共享子树中。如果要从左侧树导航中隐藏它,#shareHiddenFromTree请在 CSS 代码注释中添加标签。
  • 如果您进行大量样式更改,则建议#shareOmitDefaultCss在共享子树上使用,这样您就不需要覆盖默认样式表(这也将避免将来在默认 CSS 更改时出现问题)。

脚本

~shareJs可以使用关系向共享笔记注入 JavaScript 笔记。

如果您想访问例如属性或遍历链接的 JavaScript 注释中的树,您可以使用通过全局fetchNote(noteId = current)函数可用的 API ,例如:

const  currentNote  =  await  fetchNote ( ) ; const  parentNote  =  await  fetchNote ( currentNote.parentNoteIds [ 0 ] ) ; _ _ for  ( const  attr  of  parentNote . attributes )  {    控制台. 日志(属性。类型, 属性。名称, 属性。值); }

创建人类可读的 URL 别名

共享笔记可以使用类似的 URL 访问http://domain/share/knvU8aJy4dJ7,其中最后一部分是笔记的 ID。

您可以添加#shareAlias到单个注释以使 URL 更好,例如#shareAlias=highlighting将使 URL 看起来像http://domain/share/highlighting

请注意,您有责任保持别名的唯一性。

查看所有共享笔记

所有共享笔记都归类在自动管理的“共享笔记”笔记下。除了查看共享的内容外,您还可以通过将笔记克隆/移动到此笔记来有效地共享/取消共享笔记。

网站图标

~shareFavicon您可以通过创建指向包含 favicon(例如ico格式)的文件注释的关系来定义用于共享页面的自定义 favicon 。

作为根共享笔记

您可以将#shareRoot属性添加到文件夹或笔记中,当您访问http://domain/share时,它将被链接。这可以更容易地将 Trilium 用作一个成熟的网站,因为您可以创建一个笔记来充当“主页”。

限制

共享笔记功能与标准功能相比非常有限。

缺少的不详尽清单是:

  • 关系图支持
  • 书笔记只显示子笔记列表
  • 代码笔记没有突出显示
  • 笔记树是静态的

将来可能会删除/减少其中一些限制。

Trilium支持创建"代码"笔记,即包含某种形式化代码的笔记-包括编程语言(C ++,JavaScript),结构化数据(JSON,XML)或其他类型的代码(CSS等)。

这对以下几件事可能很有用:

  • 计算机程序员可以将代码段存储为笔记,并高亮显示语法
  • 可以在Trilium内部执行JavaScript代码笔记,以实现某些附加功能
    • 我们称这样的JavaScript代码笔记"脚本" -参见脚本
  • JSON,XML等可用作结构化数据的存储(通常与脚本结合使用)

额外的语言

Trilium支持多种语言的语法高亮显示,但默认情况下仅显示其中一部分(以减少项的数量)。您可以在Options -> Code notes中添加其他语言(自Trilium 0.35起可用)。

代码块

替代代码笔记的是"代码块"-文本笔记的功能,可以向文本编辑器添加简短的代码片段。缺点是代码块不支持语法高亮显示。

Trilium支持创建代码笔记,即允许您存储一些编程代码并将其高亮显示的笔记。特殊情况是JavaScript代码笔记,这些笔记也可以在Trilium内部执行,可以与脚本API结合使用以提供额外的功能。

脚本编写

为了进一步讲解,我必须解释Trilium的基本体系结构 - 本质上,它是一个经典的Web应用程序 - 它具有以下两个主要组件:

  • 在浏览器中运行的前端(使用HTML,CSS,JavaScript)- 主要用于与用户进行交互,显示笔记等。
  • 后端在node.js runtime中运行JavaScript代码 - 负责例如存储笔记,对其进行加密等。

因此,我们有前端和后端,每个前端和后端都有各自的职责,但是它们的共同特征是它们都运行JavaScript代码。事实是,我们能够创建JavaScript代码笔记,并且已经投入使用。

按钮用例

让我们看一下演示脚本(默认Trilium文档附带)-任务管理器(Task manager)。该脚本要做的一件事就是在Trilium界面上添加一个按钮,使用户可以轻松添加新Task(TODO项)。

首先查看顶部的红色圆圈 - 这是我们想要实现的 - UI中的新按钮,它将创建代表 任务/待办事项 的新笔记。

下方的第一个红点表示我们为此脚本创建的笔记类型-它是"JavaScript fronted"。这是前端,因为向UI添加按钮显然是前端的责任。

在笔记内容中,您可以看到调用API方法之一的代码,该代码专门用于添加新按钮。代码需要设置一些按钮属性:

  • 按钮标题
  • 应显示在按钮上的图标
  • 可选的快捷方式,您可以在该快捷方式下触发按钮
  • 最重要的是"操作"-单击按钮时必须执行某些操作

动作处理程序

将笔记保存到数据库是后端的责任,因此我们立即将控制权交给后端,并要求其创建笔记。完成此操作后,我们将显示新创建的笔记,以便用户可以设置任务标题以及某些属性。

脚本执行

因此,我们有一个脚本会将按钮添加到工具栏。但是我们如何执行它呢?一种可能性是单击"play"图标(用红色圆圈标记的那个)。问题在于,UI更改受Trilium runtime限制,因此当我们重新启动Trilium时,按钮将不存在。

每当Trilium启动时,我们都需要执行它,但是我们可能不想每次启动时都手动单击播放按钮。

解决方案在底部用红色圆圈标记-此笔记的[标签)(./属性.md)为#run=frontendStartup - 这是Trilium可以理解的"系统"标签之一。如你所想,一旦Trilium前端启动,这将导致所有带有这种标签的脚本笔记都被执行。

#run=frontendStartup不适用于[移动端)(./移动前端.md)- 如果您想在那里运行脚本,请提供脚本#run=mobileStartup标签)

更多用例

您可以在高级用例查看带有说明的更多脚本

事件

请参阅事件

脚本API

请参阅脚本API

为了使脚本执行任何有用的操作,Trilium发布了"脚本API"。实际上,有两个这样的API:

向后兼容

请注意,脚本API现在处于高度试验阶段,将来可能会发生变化。

Trilium为脚本提供了一种打开公共REST端点的机制。这为与其他服务的各种集成开辟了一条途径-一个简单的示例是通过发出slash命令从Slack创建新笔记(例如/trilium buy milk)。

从Trilium外部创建笔记

让我们看一个例子。目标是提供一个REST端点,我们可以向其发送标题和内容,Trilium将创建一个笔记。

我们将首先创建一个JavaScript后端代码笔记,其中包含:

const {req, res} = api;
const {secret, title, content} = req.body;

if (req.method == 'POST' && secret === 'secret-password') {
    // notes must be saved somewhere in the tree hierarchy specified by a parent note. 
    // This is defined by a relation from this code note to the "target" parent note
    // alternetively you can just use constant noteId for simplicity (get that from "Note Info" dialog of the desired parent note)
    const targetParentNoteId = await api.currentNote.getRelationValue('targetNote');
    
    const {note} = await api.createTextNote(targetParentNoteId, title, content);

    res.status(201).json(note);
}
else {
    res.send(400);
}

该脚本笔记还具有以下两个属性:

  • 标签customRequestHandler带有值create-note
  • 关系targetNote指向应保存新笔记的笔记

说明

让我们通过使用HTTP客户端发送请求进行测试:

POST http://my.trilium.org/custom/create-note
Content-Type: application/json

{
  "secret": "secret-password",
  "title": "hello",
  "content": "world"
}

注意请求路径中的/custom部分-Trilium将带有此前缀的任何请求视为"custom",并尝试通过查看所有具有customRequestHandler [标签)(./属性.md)的笔记来查找匹配的处理程序。然后,此标签的值包含一个正则表达式,该正则表达式将与请求路径匹配(在本例中为平凡的正则表达式"create-note")。

然后Trilium将找到上面创建的代码笔记并执行它。api.reqapi.res被设置为请求响应的对象,从中我们可以得到请求和响应的细节。

在代码笔记中,我们检查了请求方法,然后使用普通身份验证-请记住,默认情况下,这些端点完全未经身份验证,因此您需要自己进行维护。

通过这些检查后,我们将使用脚本API创建所需的笔记。

自定义资源提供者

另一个常见的用例是,你只想公开一个文件笔记-在这种情况下,你可以创建标签customResourceProvider(值还是路径正则表达式)。

注意:公开的文件需要带有#customResourceProvider =" fonts/myFont.woff"

例如,您的文件位于custom/fonts中,你可以通过custom/fonts/myFont.woff进行调用。

进阶概念

api.reqapi.res是Express.js对象-你随时可以查看其文档以了解详细信息。

参数

REST请求路径通常在URL中包含参数,例如:

http://my.trilium.org/custom/notes/123

最后一部分是动态的,因此URL的匹配也必须是动态的-因此,匹配是使用正则表达式完成的。customRequestHandler将与以下值匹配:

notes/([0-9]+)

另外,这还使用括号定义了一个匹配组,从而使提取值变得更加容易。匹配的组位于api.pathParams

const noteId = api.pathParams[0];

通常,您还需要查询参数(例如http://my.trilium.org/custom/notes?noteId=123),您可以使用标准expressreq.query.noteId获得这些参数。

脚本笔记可以由事件触发。请注意,这些是后端事件,因此关系需要指向"JS backend"代码笔记。

全局事件

全局事件通过标签附加到脚本笔记。只需使用其中的一些值创建例如"run"标签,事件发生后便会执行脚本笔记。

  • run
    • frontendStartup - 启动时在前端执行
    • mobileStartup - 启动时在移动前端执行
    • backendStartup - 启动时在后端执行
    • hourly - 在后端每小时执行一次
    • daily - 在后端每天执行一次

实体事件

其他事件绑定到某个实体,这些事件被定义为关系 - 意味着仅当笔记通过关系将脚本附加到事件(或事件可以继承脚本)时,脚本才会被触发。

  • runOnNoteCreation - 在后端创建笔记时执行
  • runOnNoteTitleChange - 在笔记标题更改时执行(还包括笔记创建)
  • runOnNoteChange - 更改笔记时执行(还包括笔记创建)
  • runOnChildNoteCreation - 在笔记创建子笔记时执行
  • runOnAttributeCreation - 在笔记创建新属性时执行
  • runOnAttributeChange -在笔记更改属性时执行

可以在三个可以显示自定义内容的位置创建自定义窗口小部件。

位置是:

  • 左窗格
  • 中央窗格
  • 右窗格

示例-字数小部件

创建类型为JS frontend的代码笔记,并为其添加widget标签。

/*
 * This defines a custom widget which displays number of words and characters in a current text note.
 * To be activated for a given note, add label 'wordCount' to the note, you can also make it inheritable and thus activate it for the whole subtree.
 * 
 * See it in action in "Books" and its subtree.
 */
const TPL = `<div style="padding: 10px; border-top: 1px solid var(--main-border-color); contain: none;">
    <strong>Word count: </strong>
    <span class="word-count"></span>

    &nbsp;

    <strong>Character count: </strong>
    <span class="character-count"></span>
</div`;

class WordCountWidget extends api.NoteContextAwareWidget {
    get position() { return 100; } // higher value means position towards the bottom/right

    get parentWidget() { return 'center-pane'; }

    isEnabled() {
        return super.isEnabled()
            && this.note.type === 'text'
            && this.note.hasLabel('wordCount');
    }

    doRender() {
        this.$widget = $(TPL);
        this.$wordCount = this.$widget.find('.word-count');
        this.$characterCount = this.$widget.find('.character-count');
        return this.$widget;
    }

    async refreshWithNote(note) {
        const {content} = await note.getNoteComplement();

        const text = $(content).text(); // get plain text only

        const counts = this.getCounts(text);

        this.$wordCount.text(counts.words);
        this.$characterCount.text(counts.characters);
    }

    getCounts(text) {
        const chunks = text
            .split(/[\s-+:,/\\]+/)
            .filter(chunk => chunk !== '');

        let words;

        if (chunks.length === 1 && chunks[0] === '') {
            words = 0;
        }
        else {
            words = chunks.length;
        }

        const characters = chunks.join('').length;

        return {words, characters};
    }

    async entitiesReloadedEvent({loadResults}) {
        if (loadResults.isNoteContentReloaded(this.noteId)) {
            this.refresh();
        }
    }
}

module.exports = new WordCountWidget();

进行更改后,必须重新启动Trilium,以便可以重新构建布局。

示例截图

在底部,您可以看到生成的小部件:

Trilium以脚本提升属性的形式提供了一些高级功能。为了解释和可视化这些功能,我们准备了一些演示用例,演示文档中也提供了这些:

请记住,重要的是上述展览品和演示功能不是Trilium内置的-这些只是Trilium可扩展性的示例。

记笔记的一种常见方式是许多笔记将集中在某个日期附近-例如,您有某些任务需要在某个日期完成,您需要在特定日期开会,您有自己的想法等等。他们都围绕各自发生的日期。因此,创建某些"每日工作区"是有意义的,该工作区将集中与特定日期相关的所有笔记。

为此,Trilium提供了"日志笔记"的概念。Trilium每天半自动生成一个笔记。在此笔记下,您可以保存所有这些相关笔记。

选择一个现有的日期笔记,菜单栏包含一个日历小部件。选择任何一天为该天创建一个笔记。

image

这种模式也因为[克隆)(./克隆笔记.md)功能而运作良好 - 笔记可以出现在笔记树中的多个位置,因此除了出现在日笔记下,它还可以分类到其他笔记中。

演示

您可以看到在"Journal"笔记下日志笔记的结构 - 有一个2017年的笔记,在其下有"12 - December",然后包含"18 - Monday"。这是我们的"日志笔记",其中包含一些内容,还包含一些子笔记(其中一些来自任务管理器)。

您还可以注意到该日志如何拥有提升属性"weight",您可以在其中跟踪每日体重。然后,此数据将在体重追踪器中使用。

模板

Trilium提供了模板功能,可以与日志笔记一起使用。

您可以在Journal的根目录上定义以下关系之一(由#calendarRoot标签标识):

  • yearTemplate
  • monthTemplate
  • dateTemplate

所有这些都是关系。当Trilium为年,月或日期创建新笔记时,它将查看根目录并将相应的~template关系附加到新创建的角色。使用此功能,您可以创建您的日志笔记模板,例如日常活动的复选框等。

日期模式

#datePattern可以通过在根日历笔记(由#calendarRoot标签标识)上定义标签来自定义生成的日期笔记的标题。以下是可能的值:

  • {dayInMonthPadded} - {weekDay}日笔记被命名为例如“24 - Monday”
  • {dayInMonthPadded}: {weekDay3}日笔记被命名为例如“24:Mon”
  • {dayInMonthPadded}: {weekDay2}日笔记被命名为例如“24:Mo”
  • {isoDate} - {weekDay}日间笔记被命名为例如“2020-12-24 - Monday”

实现

Trilium 以后端脚本 API的形式对日志笔记提供了一些特殊支持- 参见例如 getDateNote() 函数。

使用标签创建日(和年、月)笔记 - 例如#dateNote="2018-08-16",其他脚本可以使用它来向日志笔记等添加新笔记。

Journal 还具有关系child:child:child:template=Day template(请参阅属性继承),它有效地将模板添加到日志笔记(Journal 的 Grand-grand-grand 子节点)。

Weight Tracker是演示文档中提供的脚本API用例。

日志笔记显示(除其他外)我们如何在日志模板中设置"weight"提升属性。然后汇总数据并显示一个很好的重量时间变化图表。

演示

如何从顶部栏中删除体重跟踪器按钮

在Weight Tracker的链接图中,有一个笔记“Button”。打开它并删除或注释掉它的内容。重启应用程序后,体重追踪器按钮将消失。

实现

注意上面的屏幕快照中的"Weight Tracker"类型为"Render HTML note"。这样的笔记本身没有任何有用的内容,它的唯一目的是提供一些脚本可以渲染某些输出的地方。该脚本是根据关系 定义的renderNote - 恰巧它是Weight Tracker的子Implementation

然后,此实现代码笔记包含一些HTML和JavaScript,这些HTML和JavaScript会加载所有具有"weight"属性的笔记并将它们显示在图表中。为了实际渲染图表,我们使用第三方库chart.js作为附件导入(它不内置于Trilium中)。

JS代码

想要了解脚本,这里是"JS code" 笔记内容:

async function getChartData() {
    const days = await api.runOnServer(async () => {
        const notes = await api.getNotesWithLabel('weight');
        const days = [];

        for (const note of notes) {
            const date = await note.getLabelValue('dateNote');
            const weight = parseFloat(await note.getLabelValue('weight'));

            if (date && weight) {
                days.push({ date, weight });
            }
        }

        days.sort((a, b) => a.date > b.date ? 1 : -1);

        return days;
    });

    const datasets = [
        {
            label: "Weight (kg)",
            backgroundColor: 'red',
            borderColor: 'red',
            data: days.map(day => day.weight),
            fill: false,
            spanGaps: true,
            datalabels: {
                display: false
            }
        }
    ];

    return {
        datasets: datasets,
        labels: days.map(day => day.date)
    };
}

const ctx = $("#canvas")[0].getContext("2d");

new chartjs.Chart(ctx, {
    type: 'line',
    data: await getChartData()
});

任务管理器是演示文档中一个提升属性脚本的演示用例。

演示

任务管理器管理未完成的(TODO)任务和已完成的任务(非空的doneDate属性)。尚未完成的任务将按位置和任意标签进一步分类-每当您更改任务说明中的标签属性时,该任务就会自动移至适当的位置。

任务管理器还与日志笔记集成 - 笔记被克隆到todoDate笔记和doneDate笔记的日志中([前缀)(./树的概念.md#前缀)为"TODO"或"DONE")。

实现

在TODO笔记中创建了新任务,该笔记具有指向任务模板的"child:template"关系(请参阅属性继承)。

属性

任务模板定义了几个提升属性 - todoDate,doneData,标签,位置。重要的是,它还定义了~runOnAttributeChange关系-在属性更改时运行的事件处理程序。例如,当我们填写doneDate属性时,该脚本会执行-意味着任务已完成,应移至“完成”笔记,并从TODO,位置和标签中删除。

“新建任务"按钮

还有一个"button"笔记,其中包含简单的脚本,该脚本在TODO笔记中添加了一个用于创建新笔记(任务)的按钮。

api.addButtonToToolbar({
    title: 'New task',
    icon: 'check',
    shortcut: 'alt+n',
    action: async () => {
        // creating notes is backend (server) responsibility so we need to pass
        // the control there
        const taskNoteId = await api.runOnServer(async () => {
            const todoRootNote = await api.getNoteWithLabel('taskTodoRoot');
            const {note} = await api.createNote(todoRootNote.noteId, 'new task', '');

            return note.noteId;
        });

        // we got an ID of newly created note and we want to immediatelly display it
        await api.activateNewNote(taskNoteId);
    }
});

CSS

在上面的演示截图中,您可能会注意到TODO任务为红色,DONE任务为绿色。

这可以通过以下CSS代码笔记来完成,它定义了额外的CSS类:

span.fancytree-node.todo .fancytree-title {
    color: red !important;
}

span.fancytree-node.done .fancytree-title {
    color: green !important;
}

代码笔记具有appCss标签,Trilium在启动时会识别该标签,并将其作为CSS加载到应用程序中。

此功能的第二部分基于上述事件处理程序,该事件处理程序根据任务状态将#cssClass标签分配给"done"或"todo"的任务。

ETAPI 是 Trilium 的公共/外部 REST API。它从 Trilium v0.50 开始可用。

该文档采用 OpenAPI 格式,可在此处获得。

验证

所有操作都必须使用令牌进行身份验证。您可以从 Options -> ETAPI 或以编程方式使用/auth/loginREST 调用获取此令牌(请参阅规范)。

Trilium Notes支持导入Markdown(CommonMark风格)。

导入

剪贴板导入

如果您只想从剪贴板导入makrdown的一部分,则可以从编辑器块菜单中进行:

文件导入

您还可以从以下文件导入Markdown文件:

  • 单个markdown文件(扩展名为.md)
  • 整个markdown文件树(打包到.zip归档文件中)
    • Markdown文件需要打包到ZIP存档中,因为浏览器无法读取目录,只能读取单个文件。
    • 您可以使用例如7-zip将markdown文件的目录打包到ZIP文件中

导出

子树导出

您可以将整个子树导出到ZIP存档,该存档将具有按照子树结构建模的目录结构:

单个笔记导出

如果您只想导出不带子树的单个笔记,则可以从“Note actions”菜单中进行:

Trilium可以导入由Evernote用于备份/导出的ENEX文件。一个ENEX文件代表一个笔记本的内容(笔记和资源)。

从Evernote导出ENEX

要导出ENEX文件,您需要拥有Evernote的桌面版本(即非Web/移动版)。右键单击笔记本,然后选择"导出",然后按照向导进行操作。

在Trilium中导入ENEX

一旦有了ENEX文件,就可以将其导入Trilium。右键单击某个笔记(要将文件导入到该笔记),单击"导入",然后选择ENEX文件。

导入ENEX文件后,检查导入的笔记和资源,以确保导入进行顺利并且没有丢失任何数据。

局限性

所有资源(图像除外)均作为笔记的附件创建。

ENEX文件中的HTML并非完全有效,因此某些格式可能会损坏或丢失。您可以向Trilium issue tracker报告主要问题。

此页面包含一些用于组织知识库中信息的模式的描述。这旨在给人们一些启发,说明他们通常如何以及在Trilium Notes中特别是如何创建和构建其知识库。它还为某些设计决策提供了背景和依据。

元模式

只需清楚一点,元模式就是"模式的模式",即以其他模式出现的模式。

信息分层组织

基本元模式是将笔记(信息单元)按层次结构进行排序-我有一些代表粗粒度的组织"顶级"笔记,然后将这些拆分成定义更细粒度组织的子笔记,依此类推。我认为这种层次结构(树)组织对于组织大量信息非常有效。在这方面,许多笔记软件(例如Evernote)有着令人沮丧的限制,这限制了软件对大量笔记的可伸缩性。

可扩展性

重要的是,在构想以下(元)模式时,一定要了解我们正在讨论的数据量。

根据我估算个人知识库大小的经验法则,您每天可以合理地制作大约10个笔记,即一年3650个。我计划长期使用我的知识库(无论是否使用Trilium Notes),可能需要数十年,以便您轻松达到10万甚至更多。现在,我的个人知识库大约有10000个笔记。

100,000是大多数笔记软件无法很好地扩展的一个数字(在性能和用户界面方面)。但我不认为这真的是在考虑一辈子的知识。

惰性层级

我创建层次结构的方法很懒惰-我不是先创建结构,然后再用笔记填充它,而是为某个特定主题创建单个笔记,然后开始使用该笔记。内容开始增长后,我将看到如何拆分某些部分,然后将它们移到单独的子笔记中。举例来说,我对指环王的书评:

  • 书评
    • 指环王

该笔记包含基本的书籍信息(作者,出版商等),带有注解的书籍重点,然后是整体评论。现在事实证明,书中的要点太多了,总体审查时间也很长,因此我想将结构更改为以下内容:

  • 书评
    • 指环王       (仍包含基本信息)
      • 强调
      • 评论

如果我使用存储在文件系统中的标准文本文件,我很快就会遇到一个烦人的问题,为了将"亮点"和"评论"分为子笔记,我还必须将指环王从文本文件转换为目录并进行分割将笔记的所有部分都分成子笔记。相反,Trilium将所有笔记都视为相等-叶子笔记和内部笔记都可以同时具有文本内容,这使我可以仅对需要它的内容进行子结构化。

将笔记排序到层次结构中的多个位置

在将笔记组织到层次结构中时,您很快就会陷入困境–您的笔记似乎平等地属于层次结构中的两个位置。例如,您要记录一下bash,它属于"OS / Linux"还是"编程/脚本语言"?这实际上是由基本树层次结构的限制所压制的错误二分法-答案当然是它_属于两者_。这就是为什么Trilium不使用标准树结构(要求每个笔记具有一个父对象)而是使用允许每个笔记具有多个父对象的扩展版结构的原因,从而有效地允许它出现在层次结构的多个位置。由于缺乏更好的术语,我称之为"克隆"。这个词的主要问题是,它暗示每个克隆都必须有一个源头,但是这里所有的克隆都是完全相等的-实际上没有源头。

在技​​术术语中,将其描述为硬链接可能会更好,但有一个重要的区别,那就是可以硬链接(克隆)目录(内部笔记)。

隐私笔记

我会让Trilium Notes一直打开。有时候我去洗手间时忘记锁定计算机。有时候我会让朋友或家人在没有监督的情况下用一儿会计算机。他们可能单击(运行)Trilium,而无意间看到了一个我真的不想让任何人看到的笔记(个人日记,凭据)。为此,Trilium具有"隐私笔记"的概念-隐私笔记会被加密,并且最重要的是,用户需要每5分钟输入一次密码,以确保此类笔记只能在短时间内处于可读状态 。使用普通(不受保护的)笔记不需要密码,因此在不需要时不会受到额外安全性的困扰。

归档笔记

笔记可能会随着时间的流逝而失去意义-假设我换了工作-所有针对前雇主的笔记都会立即失去其大部分来源。但是,这并不意味着我要删除这些笔记-通常来说,我只是希望它们以某种方式取消优先级-在Trilium中,我可以通过为公司根目录笔记分配一个继承 标签 archived来做到这一点。该标签的主要作用是从搜索结果中过滤掉了该子树中的所有笔记(通过笔记自动完成功能快速搜索是我的主要导航方法)。除此之外,我通常还将这些过时的笔记移到层次结构中不太重要的位置。

我也将归档功能用于与创建时不太相关的笔记 - 一个示例可能会自动导入reddit评论。

有时,相关和不相关的笔记之间没有明确的类别划分,在这种情况下,我只创建带有archived标签的"O_LD_ "笔记并将所有不相关的笔记移到那里。因此,我的凭据(credentials)笔记可能看起来像这样:

Credentials

  • Personal
    • OLD       (包含一堆带有我不再使用的服务凭证的笔记)
    • Gmail
    • Github
    • ...

模式

日志

每天都有包含或引用与给定日期相关的所有内容的笔记,结构如下:

  • 2018
  • 11 - November
    • 26 - Monday
    • 27 - Tuesday
      • subnote 1

日志可同时用作工作区和笔记收件箱(Inbox) - 当我没有时间考虑适当的放置位置时,它是创建笔记的默认位置。一天结束时,我通常会查看我的日志,并将其克隆到层次结构中的适当位置。

Trilium部分内置了这种模式 - Trilium可以理解并可以半自动(通过API调用)创建Year / Month / Day结构。还有全局键盘快捷键CTRL-ALT-P,它将在日志中创建新笔记。

我将在此日志下保留哪些笔记?

  • 给定日期的待办事项列表(可以自动执行-请参阅任务管理器
  • 个人日记
  • 我在这一天中创建的笔记的克隆(代表我一直在从事的工作)。
  • 我经常克隆某些我正在做的项目指定日期的笔记(或子树)
  • 我有一些脚本可以跟踪某些日常指标(例如体重)。它们被保存到一个日常的"数据笔记"中(实际上是JSON代码笔记)。
    • 我还有其他脚本可以帮助我可视化这些数据(请参见体重追踪器示例)
    • 我有一个脚本,可以自动将所有评论从reddit导入日志。
      • 人们有时想知道为什么。答案是,我通常会在评论中投入一些精力和思想,这就是为什么我觉得值得保留,特别是如果可以自动完成。

对于大多数笔记,该日志的放置是_次要_的,它们的主要位置在其他地方(例如,对于我一直在进行的书评,它是书/评论,而不是日志)。因此,要使此模式有效,将笔记克隆到多个位置的功能非常重要。

项目

项目是肯定一目了然的(self explanatory),特别是对我而言这意味着持续时间很长(多年)- 例如Trilium Notes或大学学习等项目。考虑到它们的寿命,项目可能很大而且很深,但是它们的结构是非常特定于领域的,我看不到任何常见的模式。显而易见,它们通常与知识库的其他部分广泛关联 - 例如,大学凭据是从"凭据/大学"顶层笔记中克隆的,而与Trilium相关的博客文章位于"博客 / [博客名称] / Trilium"中。

史诗(Epics)与项目相同,但范围不同 - 它们通常长达数月之久,因此通常被放入年鉴中(例如2018 / Epics)。史诗通常具有工作性质(也被复制到工作记录中)和个人性质(例如,目前我有搬到另一个城市的大史诗)。

我没有短期项目(通常为期数天),但是继续讲Scrum的类似,我可以称它们为故事。它们通常直接放置在日志中,并手动从一天移动到另一天(或放置在一个月笔记中,例如2018 / 11 - November)。

凭据

我将所有凭据保存在知识库中,它们分为以下几类:与工作相关的,与项目相关的,每个国家/地区的个人等。这些笔记当然受到保护,并且经常被克隆到其他地方(例如,将项目凭据克隆到项目本身中) )。与诸如KeePass之类的传统工具相比,这是一个非常重要的优势-所有相关信息都集中在一个地方而不会影响安全性。

人物个人资料

对于某些人来说,这似乎令人毛骨悚然,但我对大多数人都保留了一份简介。它包含非常标准的内容,例如出生日期,联系方式,地址,还包括当前和以前的工作,他们的爱好和世界观,有时甚至是重要的(IM / mail / meatspace)会话。几乎所有我认为值得注意的东西。与人见面之前,它有助于刷新一些基本信息,尤其是如果你们有一段时间没有联系时。例如,第十次询问他们在哪里工作变得很尴尬,因为您一直忘记。

自然,我有很多(扩充的)家庭成员,朋友,熟人等,因此我需要某种方式对它们进行排序。我的主要方法是按社交圈(工作,高中,体育俱乐部等)对他们进行分类,有时还按他们的居住城市分类。家族_圈子_仍然太大,因此进一步的组织是由_氏族_组成的(例如在"Smiths"中)。有些人是几个这样的圈子里的成员,因此他们只是被克隆到多个地方。

特别是对于家庭而言,创建关系图以可视化关系非常有用:

图书

当然,我保留标准的"To read"列表。我还会保留一个已读的书的记录 - 通常,一本书有一个子树,其根目录具有一些基本信息,例如作者,页数,出版日期,开始日期,完成日期(以升级标签的形式)。我还写了一份(私人的)评论,并保留了Kindle的重点列表,可以选择添加一些笔记,这些笔记通常存储在子笔记中(除非它们很短)。

为了使书籍清单易于管理,我每年(阅读他们)对它们进行排序,这也使我对给定年份的"阅读能力"有一些基本的了解。我计划创建一个脚本,该脚本将显示一些时间线图表以可视化书籍属性dateStarted - dateFinished以更好地查看我的阅读冲刺和趋势。

一些特定的作者也有自己的笔记,其中包含克隆的书评,采访链接和其他相关资源。

我对电影和电视节目上有类似的系统,但没有那么复杂。

个人日记

这是一个反思事件,经历,新发现等的地方。这可以帮助您更深刻地了解自己的内在自我,理清思路并做出更好的决定。

我将个人日记笔记直接分类为_日志_(如上所述),但也可以克隆为"行程笔记"(如果日志是关于给定行程的)或个人简介(如果此人在日记中扮演角色)。我的所有日​​记受到保护因为他们通常都很敏感。

文件资料

我将所有个人文件(身份证,护照,教育证书...)扫描到知识库中。它们在每台PC上都是同步的,从而提供了不错的备份,并使其可在任何地方使用。

与将它们保存在Dropbox或Google Drive中相比,其优势在于它们没有存储在某些第三方服务器上,并且可以被加密(受保护)。

库存

库存中包含我重要物品的文件和其他相关输物商品 - 例如,对于汽车,您可以保留登记卡,维修记录,相关费用等。我还保留一些对我个人重要的物品的库存 - 主要是计算机,电话,相机和类似电子产品。这有时可能是实用的,但也提供了感性的价值。

主题知识库

我在这里存储硬"知识" - 总结了不同领域的主题和发现。主题范围从传统科学 - 物理,历史,经济到哲学,心理模型,应用程序(关于我使用的特定应用程序的笔记)等。当然,这是非常主观的 - 鉴于我的所作所为,与我的编程子树相比,我的物理子树相当稀疏。

工作知识库

我通常会为我目前工作的公司保留一个顶层笔记树(过去的工作已转移到其他地方)。我跟踪公司的基本组织(部门,业务部门),谁是谁(关系图)对可视化再次有用),我从事的项目等。

我需要使用各种公司服务凭证。公司通常有很多复杂的流程和工具。我记录会议记录,并链接到公司Wiki(通常很难找到相关信息)。总的来说,我需要了解很多公司特定的信息,或者需要以我能理解的良好结构来使用它们。通常,它只是将现有信息的复制粘贴和重组成对我来说更容易理解的内容。

从我的经验来看,保持这一点使我变得更有生产力,而且更重要的是极大地减少了挫折感和压力。

结论

我可能会继续讲更多的模式(例如学习笔记,旅行),但我想你明白了。无论您的生活中有什么重要的事情,记录和跟踪它都可能是有意义的。

Mac OS支持

最初,Trilium Notes的桌面版本可用于Windows和Linux,但Mac OS版本的需求却很大。

所以我做了一个,但是我低估了Mac平台的差异和特性,Mac平台似乎需要在多个地方进行特殊处理。由于缺乏知识以及坦诚地学习和编写Mac特定功能的意愿,导致Trilium目前无法很好地集成到OS中

从现在开始,Mac OS版本被视为"不受支持"。我将努力保持它的基本功能,但我不会致力于Mac特有的特性或集成。注意,这更多是对现有状态的认可,而不是方向的突然改变。

当然,也欢迎PR。

翻译/本地化支持

Trilium 目前仅提供英文版本。近期/中期没有计划翻译成其他语言,因为它会带来大量的维护开销。一旦 Trilium 稳定为更成熟的产品,可能会重新考虑这一决定。

对于中国用户来说,这里有一个非官方的分支。使用风险自负。

多用户支持

常见的许多请求是允许多个用户进行协作,共享笔记等。到目前为止,我拒绝这样做是因为以下原因:

  • 这是一个巨大的功能,或者更确切地说是潘多拉魔盒的协作功能,如用户管理、权限、冲突解决、多人实时编辑笔记等。这将是一项巨大的工作。Trilium Notes 是一个主要由一个人在空闲时间制作的项目,未来不太可能改变。
  • 鉴于它的大小,它可能会将注意力从我的主要焦点(个人笔记)上移开
  • 只有一个人可以访问应用程序的假设简化了许多事情,或者完全使它们成为可能。在多用户应用程序中,我们的脚本支持将是一个 XSS 安全漏洞,而单用户假设它是一个无限可定制的工具。

如何在一个Trilium实例中打开多个数据库文档

这是不支持的 - 一个 Trilium 进程只能打开数据库文档的一个实例。但是,您可以运行两个Trilium进程(一次安装),每个进程都连接到一个单独的文档。为此,您需要在环境变量中设置数据目录的位置,并在TRILIUM_DATA_DIR环境变量上设置单独的端口TRILIUM_PORT。如何做到这一点取决于平台,在基于Unix的系统中,您可以通过运行以下命令来实现:

TRILIUM_DATA_DIR=/home/me/path/to/data/dir TRILIUM_PORT=12345 trilium 

您可以将此命令保存到.sh脚本文件中或创建别名。对于具有不同数据目录和端口的第二个实例,像这样执行操作。

我可以使用 Dropbox / Google Drive / OneDrive 在多台计算机之间同步数据吗?

不可以。

这些通用同步应用程序不适合同步打开并由另一个应用程序处理的数据库文件。这样做的结果是它们将损坏数据库文件,导致数据丢失,并且 Trilium 日志中出现以下消息:

SqliteError: database disk image is malformed

唯一受支持的通过网络同步 Trilium 数据的方法是使用同步

为什么使用数据库而不是平面文件?

Trilium将笔记存储在SQLite数据库文档中。人们经常问为什么Trilium宁愿不使用平面文件来存储笔记-这是一个很合理的问题,因为平面文件易于互操作,可以与SCM/git等一起使用。

简而言之,就是文件系统的功能不足以实现我们希望通过Trilium实现的功能。使用文件系统意味着更少的功能,可能会有更多的问题。

更详细的回答:

  • 克隆笔记是在文件系统术语中你可能称为"硬目录链接"的内容,但是在任何文件系统中均未实现此概念
  • 文件系统区分目录和文件,而Trilium中故意没有这种区别
  • 文件没有特定的存储顺序,用户无法更改
  • Trilium允许存储笔记属性,这些属性可以用扩展的用户属性来表示,但是它们的支持在不同的文件系统/操作系统之间存在很大差异
  • Trilium在不同笔记之间建立了链接/关系,可以快速检索/导航(例如笔记映射图)。文件系统中没有这种支持,这意味着这些文件必须存储在某种形式的side car files(小型数据库)中。
  • 文件系统通常不是事务性的。尽管这对于记笔记应用程序不是完全必需的,但是进行事务处理可以更轻松地将笔记及其元数据保持在可预测且一致的状态。

Trilium当前是Beta版的软件,因此可以肯定会有一些bug。

通用快速修复

你猜对了- 重启大法。

如果出现UI问题,通常意味着Trilium前端进入不一致状态运行。修复它的最简单方法是重新加载应用程序-只需按一下即可CTRL-R将前端重新加载。

如果仍然不能解决问题,或者您怀疑这实际上是后端问题,则可以重新启动整个应用程序-如果是桌面版(Electron)构建,则只需关闭窗口并再次将其重新打开即可。

忘记用户名/密码

如果您忘记了密码,这意味着:

  • 您受保护的笔记将永远丢失-没有密码就无法解密
  • 普通(未保护的)笔记是可恢复的。请阅读下面的内容以了解操作方法。

为了能够更改用户名/密码,从而恢复未受保护的笔记,您需要访问数据目录中的文档文件。然后,您需要使用SQLite客户端(命令行或DB Browser)打开文件并执行以下查询:document.db

UPDATE options SET value = 'your_username' WHERE name = 'username'; -- feel free to change 'your_username' to your desired username
UPDATE options SET value = '77/twC5O00cuQgNC63VK32qOKKYwj21ev3jZDXoytVU=' WHERE name = 'passwordVerificationSalt';
UPDATE options SET value = '710BMasZCAgibzIc07X4P9Q4TeBd4ONnqJOho+pWcBM=' WHERE name = 'passwordDerivedKeySalt';
UPDATE options SET value = 'Eb8af1/T57b89lCRuS97tPEl4CwxsAWAU7YNJ77oY+s=' WHERE name = 'passwordVerificationHash';
UPDATE options SET value = 'QpC8XoiYYeqHPtHKRtbNxfTHsk+pEBqVBODYp0FkPBa22tlBBKBMigdLu5GNX8Uu' WHERE name = 'encryptedDataKey';

执行更改后,不要忘记提交/写入更改!

这会将密码设置为"password"。您可以使用它再次登录到该应用程序。

如果您已经有受保护的笔记(不是不可恢复的),建议您删除它们或导出不受保护的笔记,删除document.db并重新开始。

如果您决定继续使用现有的文档文件,请不要忘记更改密码(Options -> Change password)。

损坏的笔记使 Trilium 崩溃

有时,特定问题可能会导致 Trilium 出现问题(例如,使用错误的脚本渲染笔记)并导致 Trilium 崩溃。但是由于 Trilium 通常会尝试加载以前打开的笔记,它会尝试再次加载笔记,再次导致崩溃。

为了打破这个恶性循环,您可以指定TRILIUM_START_NOTE_ID环境变量,它将打开的选项卡重置为仅具有指定笔记 ID (只需使用root)的选项卡。在linux中你可以这样使用它:

TRILIUM_START_NOTE_ID=root ./trilium

同步和一致性检查

Trilium会定期检查数据库的逻辑一致性(例如,每个笔记都应有一个父项)。如果检测到一些不一致,则在UI上通知用户有关不一致的信息。

在这种情况下,建议提交错误报告并附加匿名数据库(请参见下文)。

损坏的脚本阻止应用程序启动

如果您尝试编写脚本,则可能会创建一个使整个 Trilium 崩溃的脚本。如果您将其设置为启动脚本或活动的自定义小部件,那就更糟了。

在这种情况下,您可以在不会执行任何自定义脚本的“安全模式”下启动 Trilium:

TRILIUM_SAFE_MODE=true ./trilium

恢复备份

Trilium 会定期自动备份,所以当事情变得非常糟糕时,我们可能需要最后一个选项 -恢复备份。

报告错误

发送错误报告非常有帮助。以下是一些可以查看的提示:

Trilium使用GitHub Issues - 因此请在此处发送报告:https://github.com/zadam/trilium/issues

需要明确的是,并非每个错误报告都需要遵循以下条件,但可能会根据每个问题要求其执行。

浏览器控制台

如果Trilium UI正在运行,请通过按打开开发人员控制台CTRL-SHIFT-I,可能存在一些相关的错误或警告。

所有JavaScript错误也应记录到后端日志中,但是有可能遗漏了某些内容。

后端日志

Trilium将重要事件和错误记录到logs目录(在数据目录内部)中。这些日志对于调试问题非常有用,因此请在错误报告中附加最新的日志。您不必担心,它们不包含有关笔记的任何敏感信息。

匿名数据库

在某些情况下,必须查看数据库结构才能调试问题。当然,我们不能要求您将您的[数据库文档)(./文档.md)和笔记发送给我们。

为此,Trilium支持数据库匿名化-您可以在Options -> Advanced选项卡中应用它。

image

这将创建文档的副本,并删除所有敏感数据(当前笔记标题,内容,修订,历史记录和某些选项以及非系统属性),同时保留所有结构和元数据(例如,上次更改日期)。完成此操作后,将对数据库进行真空处理,以确保文档文件中没有过时的敏感数据。结果文件存储在anonymized目录中(放在数据目录中)。您可以安全地将其附在您的错误报告中或发送到zadam.apps@gmail.com

命令行匿名

如果数据库损坏导致Trilium无法启动,则您将无法从UI触发匿名化。对于这种情况,也可以从命令行使用匿名化:

node src/anonymize.js

这需要在带有Trilium源文件的目录中执行,以便桌面版在resources/app目录中进行构建。