Compare commits

...

74 Commits

Author SHA1 Message Date
zadam
82a437f2a8 remove unnecessary debounce which caused missed changes 2024-05-30 06:55:45 +02:00
zadam
a64a0e52ec Merge branch 'refs/heads/stable'
# Conflicts:
#	package-lock.json
2024-05-30 06:46:36 +02:00
zadam
88c4171031 lock file 2024-05-30 06:46:22 +02:00
zadam
b6c7e2e48f error handling 2024-05-30 06:25:03 +02:00
zadam
305d28b5b3 remove warning about the relation map - trilium is sunsetting anyway, there's no point now in deprecating this feature, fixes #4779 2024-05-30 06:24:50 +02:00
zadam
a88bf68eb6 verify that the uploaded modified file is temporary
(cherry picked from commit a2711cfb7b5b454182393aa160e45ccbf52c949d)
2024-05-30 06:10:30 +02:00
zadam
8ebebecd93
Merge pull request #4772 from gigamonster256/macos-arm64
Support compiling native MacOS arm64 (Apple Silicon) builds
2024-05-30 06:06:08 +02:00
Caleb Norton
f0d30dbe49 Add macos arm64 to release script 2024-05-18 03:48:33 -05:00
Caleb Norton
d142d3261d support compiling native arm64 macos builds 2024-05-18 03:34:24 -05:00
zadam
25b49e1ca2 release 0.63.6 2024-05-18 06:17:21 +02:00
zadam
c7f19e04fa Merge remote-tracking branch 'origin/master' 2024-05-18 05:50:53 +02:00
zadam
a2711cfb7b verify that the uploaded modified file is temporary 2024-05-18 05:50:46 +02:00
zadam
f984b361ee
Merge pull request #4717 from MatMasIt/italian-translation
Italian translation of README
2024-05-05 05:13:26 +02:00
Mattia Mascarello
ac1e1ebe43 Forgot to translate a heading 2024-03-28 20:51:28 +01:00
Mattia Mascarello
499bfaea9b Added italian to other READMEs language section 2024-03-28 20:42:53 +01:00
Mattia Mascarello
fa4772b91e proofreading 2024-03-28 20:38:20 +01:00
Mattia Mascarello
fa7b190c6b Translated readme in italian 2024-03-28 19:23:01 +01:00
zadam
84feec2e7e Merge branch 'stable'
# Conflicts:
#	package-lock.json
2024-03-28 07:26:17 +01:00
zadam
3035473751 release 0.63.5 2024-03-28 07:11:39 +01:00
zadam
399458b52f package lock 2024-03-28 07:08:31 +01:00
zadam
becac5fbad fix rendering of math on non-root paths, closes #4713 2024-03-28 07:08:15 +01:00
zadam
1e26b31090 release 0.63.4 2024-03-28 07:00:01 +01:00
zadam
0ebd03869d use "n space" instead of zero length space to make it obvious there is a character there 2024-03-28 06:57:44 +01:00
zadam
a4a713f102 allow cancelling mention UI with escape, fixes #4692, #4684 2024-03-28 06:43:26 +01:00
zadam
83d5d6bbd8 fix copy link in browser, closes #4682 2024-03-27 20:42:36 +01:00
zadam
90f4c6b0d1 allow converting file attachments to file notes 2024-03-27 06:59:57 +01:00
zadam
bfb8aa6481 remove eslint 2024-03-06 07:17:51 +01:00
zadam
2bb4cccd82 fix excalidraw 0.17 integration 2024-03-06 07:13:30 +01:00
zadam
6fad5f2b51 Merge branch 'master' into excali-17-2 2024-03-06 06:53:19 +01:00
zadam
36357bdf86 update mermaid 2024-03-06 06:52:41 +01:00
zadam
80eaf10656 remove husky 2024-03-06 06:51:25 +01:00
zadam
f46ce0417d more prettier removals 2024-03-06 06:48:25 +01:00
zadam
6f1e6402f0 package upgrades + removal of prettier 2024-03-06 06:47:30 +01:00
zadam
bdfa13a8a0
Merge pull request #4676 from st3iny/fix/invisible-unchecked-todo
fix: invisible unchecked to-do items
2024-03-06 06:32:23 +01:00
Richard Steinmetz
d5622dfbf7 fix: invisible unchecked to-do items 2024-03-05 22:29:10 +01:00
zadam
0948853539 release 0.63.3 2024-03-03 06:58:18 +01:00
zadam
0ad337c8e8 add API method to erase a revision #4662 2024-03-03 06:34:43 +01:00
zadam
9565b0b43d
Merge pull request #4671 from AlexeiKharchev/master
Reduce warnings count caused by bin/copy-trilium.sh
2024-03-03 06:26:18 +01:00
zadam
a115b14136 fix highlighting search results with regexp characters in fulltext string, closes #4665 2024-03-02 07:35:52 +01:00
Alexei Kharchev
bb8bfc61ed Improved scriptes bin/copy-trilium.sh, bin/build-linux-x64.sh 2024-03-02 14:18:39 +08:00
zadam
2d19f073d9 fix searching fulltext with tags, closes #4661 2024-03-02 07:13:02 +01:00
Alexei Kharchev
ff5d5d20d9 Reduce warnings count caused by bin/copy-trilium.sh 2024-03-02 11:49:17 +08:00
zadam
1f95e88cfd release 0.63.2-beta 2024-02-17 22:47:50 +01:00
zadam
15677f7178
Update README.md 2024-02-16 12:16:58 +01:00
zadam
3a0bb91b77 fix 2024-02-16 11:25:23 +01:00
zadam
157f894c9b
Merge pull request #4642 from henrikx/patch-1
Fix ribbon tooltips getting stuck on the screen by setting a small delay before saving attributes in attributeeditor
2024-02-16 11:02:13 +01:00
zadam
e6dec701c0 Merge remote-tracking branch 'origin/master' 2024-02-16 10:42:30 +01:00
zadam
450b52f6da JSDoc improvements 2024-02-16 10:42:25 +01:00
zadam
4ef31eaf3d
Merge pull request #4635 from WantToLearnJapanese/WantToLearnJapanese-patch-unhoist-bookmark
Fix showing unhoist confirm dialogue for bookmarked notes.
2024-02-16 06:48:04 +01:00
zadam
2d865576cf Merge remote-tracking branch 'origin/master' 2024-02-16 06:46:38 +01:00
zadam
41e623b009 fix JSDoc, closes #4633 2024-02-16 06:46:32 +01:00
zadam
239786e7d1
Merge pull request #4632 from bavis-m/master
Add the -o option to the groupmod command used in start-docker.sh
2024-02-16 06:40:38 +01:00
zadam
89e1e47900 Merge remote-tracking branch 'origin/master' 2024-02-14 07:21:36 +01:00
zadam
67cb926233 PWA manifest fixes for extra auth, fixes #4611 2024-02-14 07:21:31 +01:00
henrikx
2f813dfc5d
Update attribute_editor.js 2024-02-09 10:58:41 +01:00
WantToLearnJapanese
a939599223
Fix showing unhoist confirm dialogue for bookmarked notes. 2024-02-02 16:36:54 +09:00
Mark
fb10e0ad33 Add the -o option to the groupmod command used in start-docker.sh when USER_GID is set, otherwise we won't be added to existing groups (e.g. you want node to run in the users (100) group) 2024-02-01 11:56:37 -08:00
zadam
46bd5bc1ef
Update README.md 2024-01-29 22:36:52 +01:00
zadam
5abfb5c08a revert unintended license changes 2024-01-28 23:09:57 +01:00
zadam
9357caeb5a activate parent note when deleting a note, #4601 2024-01-28 23:08:44 +01:00
zadam
6b58e59819 added keyboard shortcut for toggling the right pane, closes #4552 2024-01-28 08:58:40 +01:00
zadam
c6df25ece8 fix pin button shadow, closes #4595 2024-01-28 08:36:16 +01:00
zadam
ebd6276b5e CKEditor 41.0.0 2024-01-27 23:02:11 +01:00
zadam
92e8b155e4 Merge branch 'stable'
# Conflicts:
#	package.json
#	src/services/build.js
#	src/services/migration.js
2024-01-27 22:52:47 +01:00
zadam
e76093e75c release 0.62.6 2024-01-21 23:49:23 +01:00
zadam
4f8073daa7 Revert "don't tag beta images with latest #4590"
This reverts commit 47fb96faa81e67b59f7c15c2e3bad088dab47215.
2024-01-21 23:48:56 +01:00
zadam
47fb96faa8 don't tag beta images with latest #4590 2024-01-21 23:42:57 +01:00
zadam
6e33553146 fix migration 2024-01-21 23:11:27 +01:00
zadam
807941e6a5 disable scanning for links while migration is running #4535 2024-01-21 20:50:38 +01:00
zadam
1e30c0702e add indexes sooner in the migration process to speed it up #4535 2024-01-21 11:13:45 +01:00
zadam
69b686ba3b basic emoji #4119 2024-01-21 10:44:23 +01:00
zadam
ace5660809 add special characters to CKEditor build #4119 2024-01-21 10:33:16 +01:00
zadam
8bc99fd799 downgrades to try to fix flatpak build 2024-01-12 00:17:04 +01:00
zadam
8199073342 excali 17 2023-12-27 22:48:46 +01:00
61 changed files with 2427 additions and 6353 deletions

View File

@ -1,7 +0,0 @@
node_modules
dist
bin
docs
libraries
coverage
play

View File

@ -1,212 +0,0 @@
module.exports = {
env: {
browser: true,
commonjs: true,
es2021: true,
node: true,
},
// plugins: ['prettier'], // to be activated
extends: ['eslint:recommended', 'airbnb-base', 'plugin:jsonc/recommended-with-jsonc', 'prettier'],
overrides: [
{
files: ['*.json', '*.json5', '*.jsonc'],
parser: 'jsonc-eslint-parser',
},
{
files: ['package.json'],
parser: 'jsonc-eslint-parser',
rules: {
'jsonc/sort-keys': [
'off',
{
pathPattern: '^$',
order: [
'name',
'version',
'private',
'packageManager',
'description',
'type',
'keywords',
'homepage',
'bugs',
'license',
'author',
'contributors',
'funding',
'files',
'main',
'module',
'exports',
'unpkg',
'jsdelivr',
'browser',
'bin',
'man',
'directories',
'repository',
'publishConfig',
'scripts',
'peerDependencies',
'peerDependenciesMeta',
'optionalDependencies',
'dependencies',
'devDependencies',
'engines',
'config',
'overrides',
'pnpm',
'husky',
'lint-staged',
'eslintConfig',
],
},
{
pathPattern: '^(?:dev|peer|optional|bundled)?[Dd]ependencies$',
order: { type: 'asc' },
},
],
},
},
],
globals: {
$: true,
jQuery: true,
glob: true,
log: true,
EditorWatchdog: true,
React: true,
appState: true,
ExcalidrawLib: true,
elements: true,
files: true,
ReactDOM: true,
// src\public\app\widgets\type_widgets\relation_map.js
jsPlumb: true,
panzoom: true,
logError: true,
// src\public\app\widgets\type_widgets\image.js
WZoom: true,
// \src\public\app\widgets\type_widgets\read_only_text.js
renderMathInElement: true,
// \src\public\app\widgets\type_widgets\editable_text.js
BalloonEditor: true,
FancytreeNode: true,
CKEditorInspector: true,
// \src\public\app\widgets\type_widgets\editable_code.js
CodeMirror: true,
// \src\public\app\services\resizer.js
Split: true,
// \src\public\app\services\content_renderer.js
mermaid: true,
// src\public\app\services\frontend_script_api.js
dayjs: true,
// \src\public\app\widgets\note_map.js
ForceGraph: true,
// \src\public\app\setup.js
ko: true,
syncInProgress: true,
// src\public\app\services\utils.js
logInfo: true,
__non_webpack_require__: true,
describe: true,
it: true,
expect: true
},
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
rules: {
// eslint:recommended
'no-unused-vars': 'off',
'linebreak-style': 'off',
'no-useless-escape': 'off',
'no-empty': 'off',
'no-constant-condition': 'off',
'getter-return': 'off',
'no-cond-assign': 'off',
'no-async-promise-executor': 'off',
'no-extra-semi': 'off',
'no-inner-declarations': 'off',
// prettier
'prettier/prettier': ['off', { endOfLine: 'auto' }],
// airbnb-base
'no-console': 'off',
'no-plusplus': 'off',
'no-param-reassign': 'off',
'global-require': 'off',
'no-use-before-define': 'off',
'no-await-in-loop': 'off',
radix: 'off',
'import/order': 'off',
'import/no-extraneous-dependencies': 'off',
'prefer-destructuring': 'off',
'no-shadow': 'off',
'no-new': 'off',
'no-restricted-syntax': 'off',
strict: 'off',
'class-methods-use-this': 'off',
'no-else-return': 'off',
'import/no-dynamic-require': 'off',
'no-underscore-dangle': 'off',
'prefer-template': 'off',
'consistent-return': 'off',
'no-continue': 'off',
'object-shorthand': 'off',
'one-var': 'off',
'prefer-const': 'off',
'spaced-comment': 'off',
'no-loop-func': 'off',
'arrow-body-style': 'off',
'guard-for-in': 'off',
'no-return-assign': 'off',
'dot-notation': 'off',
'func-names': 'off',
'import/no-useless-path-segments': 'off',
'default-param-last': 'off',
'prefer-arrow-callback': 'off',
'no-unneeded-ternary': 'off',
'no-return-await': 'off',
'import/extensions': 'off',
'no-var': 'off',
'import/newline-after-import': 'off',
'no-restricted-globals': 'off',
'operator-assignment': 'off',
'no-eval': 'off',
'max-classes-per-file': 'off',
'vars-on-top': 'off',
'no-bitwise': 'off',
'no-lonely-if': 'off',
'no-multi-assign': 'off',
'no-promise-executor-return': 'off',
'no-empty-function': 'off',
'import/no-unresolved': 'off',
camelcase: 'off',
eqeqeq: 'off',
'lines-between-class-members': 'off',
'import/no-cycle': 'off',
'new-cap': 'off',
'prefer-object-spread': 'off',
'no-new-func': 'off',
'no-unused-expressions': 'off',
'lines-around-directive': 'off',
'prefer-exponentiation-operator': 'off',
'no-restricted-properties': 'off',
'prefer-rest-params': 'off',
'no-unreachable-loop': 'off',
'no-alert': 'off',
'no-useless-return': 'off',
'no-nested-ternary': 'off',
'prefer-regex-literals': 'off',
'import/no-named-as-default-member': 'off',
yoda: 'off',
'no-script-url': 'off',
'no-prototype-builtins':'off'
},
};

1
.husky/.gitignore vendored
View File

@ -1 +0,0 @@
_

View File

@ -1,4 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
#npx lint-staged

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EslintConfiguration">
<option name="fix-on-save" value="true" />
</component>
</project>

View File

@ -1,13 +0,0 @@
//https://prettier.io/docs/en/options.html
module.exports = {
semi: true,
trailingComma: 'none',
singleQuote: true,
printWidth: 100,
tabWidth: 4,
useTabs: false,
quoteProps: "as-needed",
bracketSpacing: true,
arrowParens: "avoid"
// htmlWhitespaceSensitivity: 'ignore',
};

View File

@ -1,6 +0,0 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
]
}

33
.vscode/settings.json vendored
View File

@ -1,33 +1,4 @@
{ {
"[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[json]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"editor.formatOnSave": true, "editor.formatOnSave": true,
"eslint.format.enable": true, "files.eol": "\n"
"eslint.probe": [ }
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"html",
"vue",
"markdown",
"json",
"jsonc"
],
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"html",
"vue",
"markdown",
"json",
"jsonc"
],
"files.eol": "\n",
}

View File

@ -643,7 +643,7 @@ the "copyright" line and a pointer to where the full notice is found.
GNU Affero General Public License for more details. GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.js.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail. Also add information on how to contact you by electronic and paper mail.
@ -658,4 +658,4 @@ specific requirements.
You should also get your employer (if you work as a programmer) or school, You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see For more information on this, and how to apply and follow the GNU AGPL, see
<http://www.js.gnu.org/licenses/>. <http://www.gnu.org/licenses/>.

View File

@ -1,6 +1,6 @@
# Trilium Notes # Trilium Notes
[English](https://github.com/zadam/trilium/blob/master/README.md) | [Chinese](https://github.com/zadam/trilium/blob/master/README-ZH_CN.md) | [Russian](https://github.com/zadam/trilium/blob/master/README.ru.md) | [Japanese](https://github.com/zadam/trilium/blob/master/README.ja.md) [English](https://github.com/zadam/trilium/blob/master/README.md) | [Chinese](https://github.com/zadam/trilium/blob/master/README-ZH_CN.md) | [Russian](https://github.com/zadam/trilium/blob/master/README.ru.md) | [Japanese](https://github.com/zadam/trilium/blob/master/README.ja.md) | [Italian](https://github.com/zadam/trilium/blob/master/README.it.md)
[![Join the chat at https://gitter.im/trilium-notes/Lobby](https://badges.gitter.im/trilium-notes/Lobby.svg)](https://gitter.im/trilium-notes/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://gitter.im/trilium-notes/Lobby](https://badges.gitter.im/trilium-notes/Lobby.svg)](https://gitter.im/trilium-notes/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Trilium Notes 是一个层次化的笔记应用程序,专注于建立大型个人知识库。请参阅[屏幕截图](https://github.com/zadam/trilium/wiki/Screenshot-tour)以快速了解: Trilium Notes 是一个层次化的笔记应用程序,专注于建立大型个人知识库。请参阅[屏幕截图](https://github.com/zadam/trilium/wiki/Screenshot-tour)以快速了解:

93
README.it.md Normal file
View File

@ -0,0 +1,93 @@
# Trilium Notes
## Trilium è in manutenzione - vedi i dettagli in https://github.com/zadam/trilium/issues/4620
Le discussioni preliminari sull'organizzazione si stanno svolgendo in [Trilium Next discussions](https://github.com/orgs/TriliumNext/discussions).
[![Join the chat at https://gitter.im/trilium-notes/Lobby](https://badges.gitter.im/trilium-notes/Lobby.svg)](https://gitter.im/trilium-notes/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [English](https://github.com/zadam/trilium/blob/master/README.md) | [Chinese](https://github.com/zadam/trilium/blob/master/README-ZH_CN.md) | [Russian](https://github.com/zadam/trilium/blob/master/README.ru.md) | [Japanese](https://github.com/zadam/trilium/blob/master/README.ja.md) | [Italian](https://github.com/zadam/trilium/blob/master/README.it.md)
Trilium Notes è un'applicazione per appunti ad organizzazione gerarchica, studiata per la costruzione di archivi di conoscenza personali di grandi dimensioni.
Vedi [fotografie](https://github.com/zadam/trilium/wiki/Screenshot-tour) per una panoramica veloce:
<a href="https://github.com/zadam/trilium/wiki/Screenshot-tour"><img src="https://raw.githubusercontent.com/wiki/zadam/trilium/images/screenshot.png" alt="Trilium Screenshot" width="1000"></a>
L'Ucraina si sta difendendo dall'aggressione russa, considera [donare all'esercito ucraino o a organizzazioni umanitarie](https://standforukraine.com/).
<p float="left">
<img src="https://upload.wikimedia.org/wikipedia/commons/4/49/Flag_of_Ukraine.svg" alt="drawing" width="400"/>
<img src="https://signmyrocket.com//uploads/2b2a523cd0c0e76cdbba95a89a9636b2_1676971281.jpg" alt="Trilium Notes supports Ukraine!" width="570"/>
</p>
## 🎁 Funzionalità
* Gli appunti possono essere organizzati in un albero di profondità arbitraria. Un singolo appunto può essere collocato in più posti nell'albero (vedi [clonazione](https://github.com/zadam/trilium/wiki/Cloning-notes))
* Ricco editor visuale (WYSIWYG), con supporto -tra l'altro- per tabelle, immagini ed [espressioni matematiche](https://github.com/zadam/trilium/wiki/Text-notes#math-support) e con [formattazione automatica](https://github.com/zadam/trilium/wiki/Text-notes#autoformat) per markdown
* Supporto per la modifica di [appunti con codice sorgente](https://github.com/zadam/trilium/wiki/Code-notes), con evidenziazione della sintassi
* [Navigazione veloce](https://github.com/zadam/trilium/wiki/Note-navigation) tra gli appunti, ricerca testuale completa e [fissaggio degli appunti](https://github.com/zadam/trilium/wiki/Note-hoisting)
* Supporto integrato ed automatico per le [revisioni degli appunti](https://github.com/zadam/trilium/wiki/Note-revisions)
* Gli [attributi](https://github.com/zadam/trilium/wiki/Attributes) degli appunti possono essere utilizzati per l'organizzazione, per l'interrogazione e per lo scripting avanzato (prorgrammazione).
* [Sincronizzazione](https://github.com/zadam/trilium/wiki/Synchronization) con un server di sincronizzazione auto-ospitato
* c'è un [servizio di terze parti per ospitare server di sincronizzazione](https://trilium.cc/paid-hosting)
* [Condivisione](https://github.com/zadam/trilium/wiki/Sharing) (pubblicazione) di appunti sull'internet pubblico
* Robusta [crittografia](https://github.com/zadam/trilium/wiki/Protected-notes) configurabile singolarmente per ogni appunto
* Disegno di diagrammi con Excalidraw (tipo di appunto "canvas")
* [Mappe relazionali](https://github.com/zadam/trilium/wiki/Relation-map) e [mappe di collegamenti](https://github.com/zadam/trilium/wiki/Link-map) per visualizzare gli appunti e le loro relazioni
* [Scripting](https://github.com/zadam/trilium/wiki/Scripts) - vedi [Esempi avanzati](https://github.com/zadam/trilium/wiki/Advanced-showcases)
* [API REST](https://github.com/zadam/trilium/wiki/ETAPI) per l'automazione
* Si adatta bene sia in termini di usabilità che di prestazioni fino ad oltre 100 000 appunti
* Interfaccia utente ottimizzata per il [mobile](https://github.com/zadam/trilium/wiki/Mobile-frontend) (smartphone e tablet)
* [Tema Notturno](https://github.com/zadam/trilium/wiki/Themes)
* Supporto per importazione ed esportazione da e per [Evernote](https://github.com/zadam/trilium/wiki/Evernote-import) e [Markdown import](https://github.com/zadam/trilium/wiki/Markdown)
* [Web Clipper](https://github.com/zadam/trilium/wiki/Web-clipper) per il salvataggio facile di contenuti web
Dai un'occhiata a [awesome-trilium](https://github.com/Nriver/awesome-trilium) per temi, script, plugin e altro di terze parti.
## 🏗 Rilasci
Trilium è fornito come applicazione desktop (Linux e Windows) o come applicazione web ospitata sul tuo server (Linux). La versione desktop per Mac OS è disponibile, ma [non è supportata](https://github.com/zadam/trilium/wiki/FAQ#mac-os-support).
* Se vuoi usare Trilium sul tuo desktop, scarica il rilascio binario per la tua piattaforma dall'[ultimo rilascio](https://github.com/zadam/trilium/releases/latest), decomprimi l'archivio e avvia l'eseguibile ```trilium```.
* Se vuoi installare Trilium su un server, segui [questa pagina](https://github.com/zadam/trilium/wiki/Server-installation).
* Per ora solo Chrome e Firefox sono i browser supportati (testati).
Trilium è anche disponibile su Flatpak:
[<img width="240" src="https://flathub.org/assets/badges/flathub-badge-en.png">](https://flathub.org/apps/details/com.github.zadam.trilium)
## 📝 Documentazione
[Vedi la wiki per una lista completa delle pagine di documentazione.](https://github.com/zadam/trilium/wiki/)
Puoi anche leggere ["Patterns of personal knowledge base"](https://github.com/zadam/trilium/wiki/Patterns-of-personal-knowledge-base) per avere un'ispirazione su come potresti utilizzare Trilium.
## 💻 Contribuire
Usa un ambiente di sviluppo basato su browser
[![Apri in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/zadam/trilium)
O clona localmente ed esegui
```
npm install
npm run start-server
```
## 📢 Riconoscimenti
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - miglior editor visuale (WYSIWYG) sul mercato, squadra di sviluppo attenta e reattiva
* [FancyTree](https://github.com/mar10/fancytree) - libreria per alberi molto ricca di funzionalità, senza pari. Trilium Notes non sarebbe lo stesso senza di essa.
* [CodeMirror](https://github.com/codemirror/CodeMirror) - editor di codice con supporto per un'enorme quantità di linguaggi.
* [jsPlumb](https://github.com/jsplumb/jsplumb) - libreria per la connettività visuale senza pari. Utilizzata per [mappe relazionali](https://github.com/zadam/trilium/wiki/Relation-map) e [mappe di collegamenti](https://github.com/zadam/trilium/wiki/Link-map).
## 🤝 Supporto
È possibile supportare Trilium attraverso Github Sponsors, [PayPal](https://paypal.me/za4am) o Bitcoin (bitcoin:bc1qv3svjn40v89mnkre5vyvs2xw6y8phaltl385d2).
## 🔑 Licenza
Questo programma è software libero: è possibile redistribuirlo e/o modificarlo nei termini della GNU Affero General Public License come pubblicata dalla Free Software Foundation, sia la versione 3 della Licenza, o (a propria scelta) qualsiasi versione successiva.

View File

@ -1,6 +1,6 @@
# Trilium Notes # Trilium Notes
[English](https://github.com/zadam/trilium/blob/master/README.md) | [Chinese](https://github.com/zadam/trilium/blob/master/README-ZH_CN.md) | [Russian](https://github.com/zadam/trilium/blob/master/README.ru.md) | [Japanese](https://github.com/zadam/trilium/blob/master/README.ja.md) [English](https://github.com/zadam/trilium/blob/master/README.md) | [Chinese](https://github.com/zadam/trilium/blob/master/README-ZH_CN.md) | [Russian](https://github.com/zadam/trilium/blob/master/README.ru.md) | [Japanese](https://github.com/zadam/trilium/blob/master/README.ja.md) | [Italian](https://github.com/zadam/trilium/blob/master/README.it.md)
Trilium Notes は、大規模な個人知識ベースの構築に焦点を当てた、階層型ノートアプリケーションです。概要は[スクリーンショット](https://github.com/zadam/trilium/wiki/Screenshot-tour)をご覧ください: Trilium Notes は、大規模な個人知識ベースの構築に焦点を当てた、階層型ノートアプリケーションです。概要は[スクリーンショット](https://github.com/zadam/trilium/wiki/Screenshot-tour)をご覧ください:

View File

@ -1,8 +1,15 @@
# Trilium Notes # Trilium Notes
[![Join the chat at https://gitter.im/trilium-notes/Lobby](https://badges.gitter.im/trilium-notes/Lobby.svg)](https://gitter.im/trilium-notes/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [English](https://github.com/zadam/trilium/blob/master/README.md) | [Chinese](https://github.com/zadam/trilium/blob/master/README-ZH_CN.md) | [Russian](https://github.com/zadam/trilium/blob/master/README.ru.md) | [Japanese](https://github.com/zadam/trilium/blob/master/README.ja.md) ## Trilium is in maintenance mode - see details in https://github.com/zadam/trilium/issues/4620
Trilium Notes is a hierarchical note taking application with focus on building large personal knowledge bases. See [screenshots](https://github.com/zadam/trilium/wiki/Screenshot-tour) for quick overview: Preliminary disccusions on the successor organization are taking place in [Trilium Next discussions](https://github.com/orgs/TriliumNext/discussions).
[![Join the chat at https://gitter.im/trilium-notes/Lobby](https://badges.gitter.im/trilium-notes/Lobby.svg)](https://gitter.im/trilium-notes/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [English](https://github.com/zadam/trilium/blob/master/README.md) | [Chinese](https://github.com/zadam/trilium/blob/master/README-ZH_CN.md) | [Russian](https://github.com/zadam/trilium/blob/master/README.ru.md) | [Japanese](https://github.com/zadam/trilium/blob/master/README.ja.md) | [Italian](https://github.com/zadam/trilium/blob/master/README.it.md)
Trilium Notes is a hierarchical note taking application with focus on building large personal knowledge bases.
See [screenshots](https://github.com/zadam/trilium/wiki/Screenshot-tour) for quick overview:
<a href="https://github.com/zadam/trilium/wiki/Screenshot-tour"><img src="https://raw.githubusercontent.com/wiki/zadam/trilium/images/screenshot.png" alt="Trilium Screenshot" width="1000"></a> <a href="https://github.com/zadam/trilium/wiki/Screenshot-tour"><img src="https://raw.githubusercontent.com/wiki/zadam/trilium/images/screenshot.png" alt="Trilium Screenshot" width="1000"></a>

View File

@ -1,6 +1,6 @@
# Trilium Notes # Trilium Notes
[English](https://github.com/zadam/trilium/blob/master/README.md) | [Chinese](https://github.com/zadam/trilium/blob/master/README-ZH_CN.md) | [Russian](https://github.com/zadam/trilium/blob/master/README.ru.md) | [Japanese](https://github.com/zadam/trilium/blob/master/README.ja.md) [English](https://github.com/zadam/trilium/blob/master/README.md) | [Chinese](https://github.com/zadam/trilium/blob/master/README-ZH_CN.md) | [Russian](https://github.com/zadam/trilium/blob/master/README.ru.md) | [Japanese](https://github.com/zadam/trilium/blob/master/README.ja.md) | [Italian](https://github.com/zadam/trilium/blob/master/README.it.md)
[![Join the chat at https://gitter.im/trilium-notes/Lobby](https://badges.gitter.im/trilium-notes/Lobby.svg)](https://gitter.im/trilium-notes/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://gitter.im/trilium-notes/Lobby](https://badges.gitter.im/trilium-notes/Lobby.svg)](https://gitter.im/trilium-notes/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Trilium Notes это приложение для заметок с иерархической структурой, ориентированное на создание больших персональных баз знаний. Для быстрого ознакомления посмотрите [скриншот-тур](https://github.com/zadam/trilium/wiki/Screenshot-tour): Trilium Notes это приложение для заметок с иерархической структурой, ориентированное на создание больших персональных баз знаний. Для быстрого ознакомления посмотрите [скриншот-тур](https://github.com/zadam/trilium/wiki/Screenshot-tour):

Binary file not shown.

View File

@ -2,49 +2,37 @@
SRC_DIR=./dist/trilium-linux-x64-src SRC_DIR=./dist/trilium-linux-x64-src
if [ "$1" != "DONTCOPY" ] [ "$1" != "DONTCOPY" ] && ./bin/copy-trilium.sh "$SRC_DIR"
then
./bin/copy-trilium.sh $SRC_DIR
fi
rm -r $SRC_DIR/src/public/app-dist/*.mobile.* rm -r "$SRC_DIR"/src/public/app-dist/*.mobile.*
echo "Copying required linux-x64 binaries" echo "Copying required linux-x64 binaries"
cp -r bin/better-sqlite3/linux-desktop-better_sqlite3.node "$SRC_DIR"/node_modules/better-sqlite3/build/Release/better_sqlite3.node
cp -r bin/better-sqlite3/linux-desktop-better_sqlite3.node $SRC_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node
echo "Packaging linux x64 electron build" echo "Packaging linux x64 electron build"
./node_modules/.bin/electron-packager "$SRC_DIR" --asar --out=dist --executable-name=trilium --platform=linux --arch=x64 --overwrite
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=linux --arch=x64 --overwrite
BUILD_DIR=./dist/trilium-linux-x64 BUILD_DIR=./dist/trilium-linux-x64
rm -rf $BUILD_DIR rm -rf "$BUILD_DIR"
mv "./dist/Trilium Notes-linux-x64" $BUILD_DIR mv "./dist/Trilium Notes-linux-x64" "$BUILD_DIR"
cp images/app-icons/png/128x128.png $BUILD_DIR/icon.png cp images/app-icons/png/128x128.png "$BUILD_DIR"/icon.png
cp bin/tpl/anonymize-database.sql "$BUILD_DIR"/
cp bin/tpl/anonymize-database.sql $BUILD_DIR/ cp -r dump-db "$BUILD_DIR"/
rm -rf "$BUILD_DIR"/dump-db/node_modules
cp -r dump-db $BUILD_DIR/ for f in 'trilium-portable' 'trilium-safe-mode' 'trilium-no-cert-check'; do
rm -rf $BUILD_DIR/dump-db/node_modules cp bin/tpl/"$f".sh "$BUILD_DIR"/
chmod 755 "$BUILD_DIR"/"$f".sh
cp bin/tpl/trilium-portable.sh $BUILD_DIR/ done
chmod 755 $BUILD_DIR/trilium-portable.sh
cp bin/tpl/trilium-safe-mode.sh $BUILD_DIR/
chmod 755 $BUILD_DIR/trilium-safe-mode.sh
cp bin/tpl/trilium-no-cert-check.sh $BUILD_DIR/
chmod 755 $BUILD_DIR/trilium-no-cert-check.sh
echo "Packaging linux x64 electron distribution..." echo "Packaging linux x64 electron distribution..."
VERSION=`jq -r ".version" package.json` VERSION=`jq -r ".version" package.json`
cd dist pushd dist
tar cJf "trilium-linux-x64-${VERSION}.tar.xz" trilium-linux-x64
tar cJf trilium-linux-x64-${VERSION}.tar.xz trilium-linux-x64 popd
cd ..
bin/build-debian.sh bin/build-debian.sh

38
bin/build-mac-arm64.sh Executable file
View File

@ -0,0 +1,38 @@
#!/usr/bin/env bash
SRC_DIR=./dist/trilium-mac-arm64-src
if [ "$1" != "DONTCOPY" ]
then
./bin/copy-trilium.sh $SRC_DIR
fi
echo "Copying required mac arm64 binaries"
cp -r bin/better-sqlite3/mac-arm64-better_sqlite3.node $SRC_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node
rm -r $SRC_DIR/src/public/app-dist/*.mobile.*
echo "Packaging mac arm64 electron build"
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=darwin --arch=arm64 --overwrite --icon=images/app-icons/mac/icon.icns
BUILD_DIR=./dist/trilium-mac-arm64
rm -rf $BUILD_DIR
# Mac build has by default useless directory level
mv "./dist/Trilium Notes-darwin-arm64" $BUILD_DIR
cp bin/tpl/anonymize-database.sql $BUILD_DIR/
cp -r dump-db $BUILD_DIR/
rm -rf $BUILD_DIR/dump-db/node_modules
echo "Zipping mac arm64 electron distribution..."
VERSION=`jq -r ".version" package.json`
cd dist
rm trilium-mac-arm64-${VERSION}.zip
zip -r9 --symlinks trilium-mac-arm64-${VERSION}.zip trilium-mac-arm64

View File

@ -7,9 +7,9 @@ then
./bin/copy-trilium.sh $SRC_DIR ./bin/copy-trilium.sh $SRC_DIR
fi fi
echo "Copying required mac binaries" echo "Copying required mac x64 binaries"
cp -r bin/better-sqlite3/mac-better_sqlite3.node $SRC_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node cp -r bin/better-sqlite3/mac-x64-better_sqlite3.node $SRC_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node
rm -r $SRC_DIR/src/public/app-dist/*.mobile.* rm -r $SRC_DIR/src/public/app-dist/*.mobile.*

View File

@ -13,11 +13,14 @@ cp -r $SRC_DIR ./dist/trilium-linux-x64-src
cp -r $SRC_DIR ./dist/trilium-linux-x64-server cp -r $SRC_DIR ./dist/trilium-linux-x64-server
cp -r $SRC_DIR ./dist/trilium-windows-x64-src cp -r $SRC_DIR ./dist/trilium-windows-x64-src
cp -r $SRC_DIR ./dist/trilium-mac-x64-src cp -r $SRC_DIR ./dist/trilium-mac-x64-src
cp -r $SRC_DIR ./dist/trilium-mac-arm64-src
bin/build-win-x64.sh DONTCOPY bin/build-win-x64.sh DONTCOPY
bin/build-mac-x64.sh DONTCOPY bin/build-mac-x64.sh DONTCOPY
bin/build-mac-arm64.sh DONTCOPY
bin/build-linux-x64.sh DONTCOPY bin/build-linux-x64.sh DONTCOPY
bin/build-server.sh DONTCOPY bin/build-server.sh DONTCOPY

View File

@ -4,47 +4,49 @@ if [[ $# -eq 0 ]] ; then
echo "Missing argument of target directory" echo "Missing argument of target directory"
exit 1 exit 1
fi fi
if ! [[ $(which npm) ]]; then
echo "Missing npm"
exit 1
fi
n exec 18.18.2 npm run webpack n exec 18.18.2 npm run webpack || npm run webpack
DIR=$1 DIR="$1"
rm -rf $DIR rm -rf "$DIR"
mkdir $DIR mkdir -pv "$DIR"
echo "Copying Trilium to build directory $DIR" echo "Copying Trilium to build directory $DIR"
cp -r images $DIR/ for d in 'images' 'libraries' 'src' 'db'; do
cp -r libraries $DIR/ cp -r "$d" "$DIR"/
cp -r src $DIR/ done
cp -r db $DIR/ for f in 'package.json' 'package-lock.json' 'README.md' 'LICENSE' 'config-sample.ini' 'electron.js'; do
cp -r package.json $DIR/ cp "$f" "$DIR"/
cp -r package-lock.json $DIR/ done
cp -r README.md $DIR/ cp webpack-* "$DIR"/ # here warning because there is no 'webpack-*', but webpack.config.js only
cp -r LICENSE $DIR/
cp -r config-sample.ini $DIR/
cp -r electron.js $DIR/
cp webpack-* $DIR/
# run in subshell (so we return to original dir) # run in subshell (so we return to original dir)
(cd $DIR && n exec 18.18.2 npm install --only=prod) (cd $DIR && n exec 18.18.2 npm install --only=prod)
if [[ -d "$DIR"/node_modules ]]; then
# cleanup of useless files in dependencies # cleanup of useless files in dependencies
rm -r $DIR/node_modules/image-q/demo for d in 'image-q/demo' 'better-sqlite3/Release' 'better-sqlite3/deps/sqlite3.tar.gz' '@jimp/plugin-print/fonts' 'jimp/browser' 'jimp/fonts'; do
rm -r $DIR/node_modules/better-sqlite3/Release [[ -e "$DIR"/node_modules/"$d" ]] && rm -rv "$DIR"/node_modules/"$d"
rm -r $DIR/node_modules/better-sqlite3/deps/sqlite3.tar.gz done
rm -r $DIR/node_modules/@jimp/plugin-print/fonts
rm -r $DIR/node_modules/jimp/browser
rm -r $DIR/node_modules/jimp/fonts
# delete all tests (there are often large images as test file for jimp etc.) # delete all tests (there are often large images as test file for jimp etc.)
find $DIR/node_modules -name test -exec rm -rf {} \; for d in 'test' 'docs' 'demo'; do
find $DIR/node_modules -name docs -exec rm -rf {} \; find "$DIR"/node_modules -name "$d" -exec rm -rf {} \;
find $DIR/node_modules -name demo -exec rm -rf {} \; done
fi
find $DIR/libraries -name "*.map" -type f -delete find $DIR/libraries -name "*.map" -type f -delete
cp $DIR/src/public/app/share.js $DIR/src/public/app-dist/ d="$DIR"/src/public
cp -r $DIR/src/public/app/doc_notes $DIR/src/public/app-dist/ [[ -d "$d"/app-dist ]] || mkdir -pv "$d"/app-dist
cp "$d"/app/share.js "$d"/app-dist/
cp -r "$d"/app/doc_notes "$d"/app-dist/
rm -rf $DIR/src/public/app rm -rf "$d"/app
unset f d DIR

View File

@ -48,6 +48,7 @@ LINUX_X64_BUILD=trilium-linux-x64-$VERSION.tar.xz
DEBIAN_X64_BUILD=trilium_${VERSION}_amd64.deb DEBIAN_X64_BUILD=trilium_${VERSION}_amd64.deb
WINDOWS_X64_BUILD=trilium-windows-x64-$VERSION.zip WINDOWS_X64_BUILD=trilium-windows-x64-$VERSION.zip
MAC_X64_BUILD=trilium-mac-x64-$VERSION.zip MAC_X64_BUILD=trilium-mac-x64-$VERSION.zip
MAC_ARM64_BUILD=trilium-mac-arm64-$VERSION.zip
SERVER_BUILD=trilium-linux-x64-server-$VERSION.tar.xz SERVER_BUILD=trilium-linux-x64-server-$VERSION.tar.xz
echo "Creating release in GitHub" echo "Creating release in GitHub"
@ -68,4 +69,5 @@ gh release create "$TAG" \
"dist/$LINUX_X64_BUILD" \ "dist/$LINUX_X64_BUILD" \
"dist/$WINDOWS_X64_BUILD" \ "dist/$WINDOWS_X64_BUILD" \
"dist/$MAC_X64_BUILD" \ "dist/$MAC_X64_BUILD" \
"dist/$MAC_ARM64_BUILD" \
"dist/$SERVER_BUILD" "dist/$SERVER_BUILD"

View File

@ -8,3 +8,6 @@ CREATE TABLE IF NOT EXISTS "blobs" (
ALTER TABLE notes ADD blobId TEXT DEFAULT NULL; ALTER TABLE notes ADD blobId TEXT DEFAULT NULL;
ALTER TABLE note_revisions ADD blobId TEXT DEFAULT NULL; ALTER TABLE note_revisions ADD blobId TEXT DEFAULT NULL;
CREATE INDEX IF NOT EXISTS IDX_notes_blobId on notes (blobId);
CREATE INDEX IF NOT EXISTS IDX_note_revisions_blobId on note_revisions (blobId);

View File

@ -21,5 +21,6 @@ CREATE INDEX `IDX_revisions_utcDateCreated` ON `revisions` (`utcDateCreated`);
CREATE INDEX `IDX_revisions_utcDateLastEdited` ON `revisions` (`utcDateLastEdited`); CREATE INDEX `IDX_revisions_utcDateLastEdited` ON `revisions` (`utcDateLastEdited`);
CREATE INDEX `IDX_revisions_dateCreated` ON `revisions` (`dateCreated`); CREATE INDEX `IDX_revisions_dateCreated` ON `revisions` (`dateCreated`);
CREATE INDEX `IDX_revisions_dateLastEdited` ON `revisions` (`dateLastEdited`); CREATE INDEX `IDX_revisions_dateLastEdited` ON `revisions` (`dateLastEdited`);
CREATE INDEX IF NOT EXISTS IDX_revisions_blobId on revisions (blobId);
UPDATE entity_changes SET entityName = 'revisions' WHERE entityName = 'note_revisions'; UPDATE entity_changes SET entityName = 'revisions' WHERE entityName = 'note_revisions';

View File

@ -19,3 +19,5 @@ CREATE INDEX IDX_attachments_ownerId_role
CREATE INDEX IDX_attachments_utcDateScheduledForErasureSince CREATE INDEX IDX_attachments_utcDateScheduledForErasureSince
on attachments (utcDateScheduledForErasureSince); on attachments (utcDateScheduledForErasureSince);
CREATE INDEX IF NOT EXISTS IDX_attachments_blobId on attachments (blobId);

View File

@ -5,8 +5,8 @@
} }
/* /*
* CKEditor 5 (v40.1.0) content styles. * CKEditor 5 (v41.0.0) content styles.
* Generated on Mon, 20 Nov 2023 08:41:49 GMT. * Generated on Fri, 26 Jan 2024 10:23:49 GMT.
* For more information, check out https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/content-styles.html * For more information, check out https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/content-styles.html
*/ */
@ -42,18 +42,6 @@
overflow-wrap: break-word; overflow-wrap: break-word;
position: relative; position: relative;
} }
/* @ckeditor/ckeditor5-table/theme/tablecaption.css */
.ck-content .table > figcaption {
display: table-caption;
caption-side: top;
word-break: break-word;
text-align: center;
color: var(--ck-color-selector-caption-text);
background-color: var(--ck-color-selector-caption-background);
padding: .6em;
font-size: .75em;
outline-offset: -1px;
}
/* @ckeditor/ckeditor5-table/theme/table.css */ /* @ckeditor/ckeditor5-table/theme/table.css */
.ck-content .table { .ck-content .table {
margin: 0.9em auto; margin: 0.9em auto;
@ -87,12 +75,17 @@
.ck-content[dir="ltr"] .table th { .ck-content[dir="ltr"] .table th {
text-align: left; text-align: left;
} }
/* @ckeditor/ckeditor5-media-embed/theme/mediaembed.css */ /* @ckeditor/ckeditor5-table/theme/tablecaption.css */
.ck-content .media { .ck-content .table > figcaption {
clear: both; display: table-caption;
margin: 0.9em 0; caption-side: top;
display: block; word-break: break-word;
min-width: 15em; text-align: center;
color: var(--ck-color-selector-caption-text);
background-color: var(--ck-color-selector-caption-background);
padding: .6em;
font-size: .75em;
outline-offset: -1px;
} }
/* @ckeditor/ckeditor5-page-break/theme/pagebreak.css */ /* @ckeditor/ckeditor5-page-break/theme/pagebreak.css */
.ck-content .page-break { .ck-content .page-break {
@ -130,6 +123,13 @@
-ms-user-select: none; -ms-user-select: none;
user-select: none; user-select: none;
} }
/* @ckeditor/ckeditor5-media-embed/theme/mediaembed.css */
.ck-content .media {
clear: both;
margin: 0.9em 0;
display: block;
min-width: 15em;
}
/* @ckeditor/ckeditor5-list/theme/todolist.css */ /* @ckeditor/ckeditor5-list/theme/todolist.css */
.ck-content .todo-list { .ck-content .todo-list {
list-style: none; list-style: none;
@ -280,6 +280,42 @@
.ck-editor__editable.ck-content .todo-list .todo-list__label.todo-list__label_without-description input[type=checkbox] { .ck-editor__editable.ck-content .todo-list .todo-list__label.todo-list__label_without-description input[type=checkbox] {
position: absolute; position: absolute;
} }
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ol {
list-style-type: decimal;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ol ol {
list-style-type: lower-latin;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ol ol ol {
list-style-type: lower-roman;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ol ol ol ol {
list-style-type: upper-latin;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ol ol ol ol ol {
list-style-type: upper-roman;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ul {
list-style-type: disc;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ul ul {
list-style-type: circle;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ul ul ul {
list-style-type: square;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ul ul ul ul {
list-style-type: square;
}
/* @ckeditor/ckeditor5-image/theme/image.css */ /* @ckeditor/ckeditor5-image/theme/image.css */
.ck-content .image { .ck-content .image {
display: table; display: table;
@ -318,17 +354,6 @@
flex-shrink: 1; flex-shrink: 1;
max-width: 100%; max-width: 100%;
} }
/* @ckeditor/ckeditor5-image/theme/imagecaption.css */
.ck-content .image > figcaption {
display: table-caption;
caption-side: bottom;
word-break: break-word;
color: var(--ck-color-image-caption-text);
background-color: var(--ck-color-image-caption-background);
padding: .6em;
font-size: .75em;
outline-offset: -1px;
}
/* @ckeditor/ckeditor5-image/theme/imageresize.css */ /* @ckeditor/ckeditor5-image/theme/imageresize.css */
.ck-content img.image_resized { .ck-content img.image_resized {
height: auto; height: auto;
@ -347,67 +372,16 @@
.ck-content .image.image_resized > figcaption { .ck-content .image.image_resized > figcaption {
display: block; display: block;
} }
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */ /* @ckeditor/ckeditor5-image/theme/imagecaption.css */
.ck-content .marker-yellow { .ck-content .image > figcaption {
background-color: var(--ck-highlight-marker-yellow); display: table-caption;
} caption-side: bottom;
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */ word-break: break-word;
.ck-content .marker-green { color: var(--ck-color-image-caption-text);
background-color: var(--ck-highlight-marker-green); background-color: var(--ck-color-image-caption-background);
} padding: .6em;
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */ font-size: .75em;
.ck-content .marker-pink { outline-offset: -1px;
background-color: var(--ck-highlight-marker-pink);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-blue {
background-color: var(--ck-highlight-marker-blue);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .pen-red {
color: var(--ck-highlight-pen-red);
background-color: transparent;
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .pen-green {
color: var(--ck-highlight-pen-green);
background-color: transparent;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ol {
list-style-type: decimal;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ol ol {
list-style-type: lower-latin;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ol ol ol {
list-style-type: lower-roman;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ol ol ol ol {
list-style-type: upper-latin;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ol ol ol ol ol {
list-style-type: upper-roman;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ul {
list-style-type: disc;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ul ul {
list-style-type: circle;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ul ul ul {
list-style-type: square;
}
/* @ckeditor/ckeditor5-list/theme/list.css */
.ck-content ul ul ul ul {
list-style-type: square;
} }
/* @ckeditor/ckeditor5-image/theme/imagestyle.css */ /* @ckeditor/ckeditor5-image/theme/imagestyle.css */
.ck-content .image-style-block-align-left, .ck-content .image-style-block-align-left,
@ -470,6 +444,32 @@
.ck-content .image-inline.image-style-align-right { .ck-content .image-inline.image-style-align-right {
margin-left: var(--ck-inline-image-style-spacing); margin-left: var(--ck-inline-image-style-spacing);
} }
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-yellow {
background-color: var(--ck-highlight-marker-yellow);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-green {
background-color: var(--ck-highlight-marker-green);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-pink {
background-color: var(--ck-highlight-marker-pink);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .marker-blue {
background-color: var(--ck-highlight-marker-blue);
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .pen-red {
color: var(--ck-highlight-pen-red);
background-color: transparent;
}
/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
.ck-content .pen-green {
color: var(--ck-highlight-pen-green);
background-color: transparent;
}
/* @ckeditor/ckeditor5-block-quote/theme/blockquote.css */ /* @ckeditor/ckeditor5-block-quote/theme/blockquote.css */
.ck-content blockquote { .ck-content blockquote {
overflow: hidden; overflow: hidden;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

7638
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
"name": "trilium", "name": "trilium",
"productName": "Trilium Notes", "productName": "Trilium Notes",
"description": "Trilium Notes", "description": "Trilium Notes",
"version": "0.63.1-beta", "version": "0.63.6",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"main": "electron.js", "main": "electron.js",
"bin": { "bin": {
@ -31,20 +31,18 @@
"test-jasmine": "TRILIUM_DATA_DIR=~/trilium/data-test jasmine", "test-jasmine": "TRILIUM_DATA_DIR=~/trilium/data-test jasmine",
"test-es6": "node -r esm spec-es6/attribute_parser.spec.js ", "test-es6": "node -r esm spec-es6/attribute_parser.spec.js ",
"test": "npm run test-jasmine && npm run test-es6", "test": "npm run test-jasmine && npm run test-es6",
"postinstall": "rimraf ./node_modules/canvas", "postinstall": "rimraf ./node_modules/canvas"
"lint": "eslint . --cache",
"prepare": "husky install || echo 'Husky install failed, expected on flatpak build'"
}, },
"dependencies": { "dependencies": {
"@braintree/sanitize-url": "6.0.4", "@braintree/sanitize-url": "6.0.4",
"@electron/remote": "2.1.0", "@electron/remote": "2.1.2",
"@excalidraw/excalidraw": "0.16.1", "@excalidraw/excalidraw": "0.17.3",
"archiver": "6.0.1", "archiver": "7.0.0",
"async-mutex": "0.4.0", "async-mutex": "0.4.1",
"axios": "1.6.5", "axios": "1.6.7",
"better-sqlite3": "8.4.0", "better-sqlite3": "8.4.0",
"boxicons": "2.1.4", "boxicons": "2.1.4",
"chokidar": "3.5.3", "chokidar": "3.6.0",
"cls-hooked": "4.2.2", "cls-hooked": "4.2.2",
"compression": "1.7.4", "compression": "1.7.4",
"cookie-parser": "1.4.6", "cookie-parser": "1.4.6",
@ -54,35 +52,35 @@
"debounce": "1.2.1", "debounce": "1.2.1",
"ejs": "3.1.9", "ejs": "3.1.9",
"electron-debug": "3.2.0", "electron-debug": "3.2.0",
"electron-dl": "3.5.1", "electron-dl": "3.5.2",
"electron-window-state": "5.0.3", "electron-window-state": "5.0.3",
"escape-html": "1.0.3", "escape-html": "1.0.3",
"express": "4.18.2", "express": "4.18.3",
"express-partial-content": "1.0.2", "express-partial-content": "1.0.2",
"express-rate-limit": "7.1.5", "express-rate-limit": "7.2.0",
"express-session": "1.17.3", "express-session": "1.18.0",
"force-graph": "1.43.4", "force-graph": "1.43.5",
"fs-extra": "11.2.0", "fs-extra": "11.2.0",
"helmet": "7.1.0", "helmet": "7.1.0",
"html": "1.0.0", "html": "1.0.0",
"html2plaintext": "2.1.4", "html2plaintext": "2.1.4",
"http-proxy-agent": "7.0.0", "http-proxy-agent": "7.0.2",
"https-proxy-agent": "7.0.2", "https-proxy-agent": "7.0.4",
"image-type": "4.1.0", "image-type": "4.1.0",
"ini": "3.0.1", "ini": "3.0.1",
"is-animated": "2.0.2", "is-animated": "2.0.2",
"is-svg": "4.3.2", "is-svg": "4.3.2",
"jimp": "0.22.10", "jimp": "0.22.12",
"joplin-turndown-plugin-gfm": "1.0.12", "joplin-turndown-plugin-gfm": "1.0.12",
"jquery": "3.7.1", "jquery": "3.7.1",
"jquery-hotkeys": "0.2.2", "jquery-hotkeys": "0.2.2",
"jsdom": "23.2.0", "jsdom": "24.0.0",
"katex": "0.16.9", "katex": "0.16.9",
"marked": "9.1.6", "marked": "12.0.0",
"mermaid": "10.6.1", "mermaid": "10.9.0",
"mime-types": "2.1.35", "mime-types": "2.1.35",
"multer": "1.4.5-lts.1", "multer": "1.4.5-lts.1",
"node-abi": "3.52.0", "node-abi": "3.56.0",
"normalize-strings": "1.1.1", "normalize-strings": "1.1.1",
"open": "8.4.1", "open": "8.4.1",
"panzoom": "9.4.3", "panzoom": "9.4.3",
@ -94,51 +92,38 @@
"rimraf": "5.0.5", "rimraf": "5.0.5",
"safe-compare": "1.1.4", "safe-compare": "1.1.4",
"sanitize-filename": "1.6.3", "sanitize-filename": "1.6.3",
"sanitize-html": "2.11.0", "sanitize-html": "2.12.1",
"sax": "1.3.0", "sax": "1.3.0",
"semver": "7.5.4", "semver": "7.6.0",
"serve-favicon": "2.5.0", "serve-favicon": "2.5.0",
"session-file-store": "1.5.0", "session-file-store": "1.5.0",
"split.js": "1.6.5", "split.js": "1.6.5",
"stream-throttle": "0.1.3", "stream-throttle": "0.1.3",
"striptags": "3.2.0", "striptags": "3.2.0",
"tmp": "0.2.1", "tmp": "0.2.3",
"tree-kill": "1.2.2", "tree-kill": "1.2.2",
"turndown": "7.1.2", "turndown": "7.1.2",
"unescape": "1.0.1", "unescape": "1.0.1",
"ws": "8.16.0", "ws": "8.16.0",
"xml2js": "0.6.2", "xml2js": "0.6.2",
"yauzl": "2.10.0" "yauzl": "3.1.2"
}, },
"devDependencies": { "devDependencies": {
"cross-env": "7.0.3", "cross-env": "7.0.3",
"electron": "25.9.8", "electron": "25.9.8",
"electron-builder": "24.9.1", "electron-builder": "24.13.3",
"electron-packager": "17.1.2", "electron-packager": "17.1.2",
"electron-rebuild": "3.2.9", "electron-rebuild": "3.2.9",
"eslint": "8.56.0",
"eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-jsonc": "2.11.2",
"eslint-plugin-prettier": "5.0.1",
"esm": "3.2.25", "esm": "3.2.25",
"husky": "8.0.3",
"jasmine": "5.1.0", "jasmine": "5.1.0",
"jsdoc": "4.0.2", "jsdoc": "4.0.2",
"jsonc-eslint-parser": "2.4.0",
"lint-staged": "15.2.0",
"lorem-ipsum": "2.0.8", "lorem-ipsum": "2.0.8",
"nodemon": "3.0.2", "nodemon": "3.1.0",
"prettier": "3.1.1",
"rcedit": "4.0.1", "rcedit": "4.0.1",
"webpack": "5.89.0", "webpack": "5.90.3",
"webpack-cli": "5.1.4" "webpack-cli": "5.1.4"
}, },
"optionalDependencies": { "optionalDependencies": {
"electron-installer-debian": "3.2.0" "electron-installer-debian": "3.2.0"
},
"lint-staged": {
"*.js": "eslint --cache --fix"
} }
} }

View File

@ -8,7 +8,8 @@ const protectedSessionService = require('../../services/protected_session.js');
const log = require('../../services/log.js'); const log = require('../../services/log.js');
const attachmentRoleToNoteTypeMapping = { const attachmentRoleToNoteTypeMapping = {
'image': 'image' 'image': 'image',
'file': 'file'
}; };
/** /**

View File

@ -161,6 +161,13 @@ class BRevision extends AbstractBeccaEntity {
return this.getAttachments().filter(attachment => attachment.title === title)[0]; return this.getAttachments().filter(attachment => attachment.title === title)[0];
} }
/**
* Revisions are not soft-deletable, they are immediately hard-deleted (erased).
*/
eraseRevision() {
require("../../services/erase.js").eraseRevisions([this.revisionId]);
}
beforeSaving() { beforeSaving() {
super.beforeSaving(); super.beforeSaving();

View File

@ -50,10 +50,10 @@ export default class TreeContextMenu {
{ title: 'Open in a new tab <kbd>Ctrl+Click</kbd>', command: "openInTab", uiIcon: "bx bx-empty", enabled: noSelectedNotes }, { title: 'Open in a new tab <kbd>Ctrl+Click</kbd>', command: "openInTab", uiIcon: "bx bx-empty", enabled: noSelectedNotes },
{ title: 'Open in a new split', command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes }, { title: 'Open in a new split', command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes },
{ title: 'Insert note after <kbd data-command="createNoteAfter"></kbd>', command: "insertNoteAfter", uiIcon: "bx bx-plus", { title: 'Insert note after <kbd data-command="createNoteAfter"></kbd>', command: "insertNoteAfter", uiIcon: "bx bx-plus",
items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter", {removeDeprecatedTypes: true}) : null, items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter") : null,
enabled: insertNoteAfterEnabled && noSelectedNotes }, enabled: insertNoteAfterEnabled && noSelectedNotes },
{ title: 'Insert child note <kbd data-command="createNoteInto"></kbd>', command: "insertChildNote", uiIcon: "bx bx-plus", { title: 'Insert child note <kbd data-command="createNoteInto"></kbd>', command: "insertChildNote", uiIcon: "bx bx-plus",
items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote", {removeDeprecatedTypes: true}) : null, items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null,
enabled: notSearch && noSelectedNotes }, enabled: notSearch && noSelectedNotes },
{ title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "bx bx-trash", { title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "bx bx-trash",
enabled: isNotRoot && !isHoisted && parentNotSearch }, enabled: isNotRoot && !isHoisted && parentNotSearch },

View File

@ -107,6 +107,13 @@ async function deleteNotes(branchIdsToDelete, forceDeleteAllClones = false) {
return false; return false;
} }
try {
await activateParentNotePath();
}
catch (e) {
console.error(e);
}
const taskId = utils.randomString(10); const taskId = utils.randomString(10);
let counter = 0; let counter = 0;
@ -134,6 +141,16 @@ async function deleteNotes(branchIdsToDelete, forceDeleteAllClones = false) {
return true; return true;
} }
async function activateParentNotePath() {
// this is not perfect, maybe we should find the next/previous sibling, but that's more complex
const activeContext = appContext.tabManager.getActiveContext();
const parentNotePathArr = activeContext.notePathArray.slice(0, -1);
if (parentNotePathArr.length > 0) {
activeContext.setNote(parentNotePathArr.join("/"));
}
}
async function moveNodeUpInHierarchy(node) { async function moveNodeUpInHierarchy(node) {
if (hoistedNoteService.isHoistedNode(node) if (hoistedNoteService.isHoistedNode(node)
|| hoistedNoteService.isTopLevelNode(node) || hoistedNoteService.isTopLevelNode(node)

View File

@ -48,11 +48,11 @@ async function checkNoteAccess(notePath, noteContext) {
const hoistedNoteId = noteContext.hoistedNoteId; const hoistedNoteId = noteContext.hoistedNoteId;
if (!resolvedNotePath.includes(hoistedNoteId) && !resolvedNotePath.includes('_hidden')) { if (!resolvedNotePath.includes(hoistedNoteId) && (!resolvedNotePath.includes('_hidden') || resolvedNotePath.includes('_lbBookmarks'))) {
const requestedNote = await froca.getNote(treeService.getNoteIdFromUrl(resolvedNotePath)); const requestedNote = await froca.getNote(treeService.getNoteIdFromUrl(resolvedNotePath));
const hoistedNote = await froca.getNote(hoistedNoteId); const hoistedNote = await froca.getNote(hoistedNoteId);
if (!hoistedNote.hasAncestor('_hidden') if ((!hoistedNote.hasAncestor('_hidden') || resolvedNotePath.includes('_lbBookmarks'))
&& !await dialogService.confirm(`Requested note '${requestedNote.title}' is outside of hoisted note '${hoistedNote.title}' subtree and you must unhoist to access the note. Do you want to proceed with unhoisting?`)) { && !await dialogService.confirm(`Requested note '${requestedNote.title}' is outside of hoisted note '${hoistedNote.title}' subtree and you must unhoist to access the note. Do you want to proceed with unhoisting?`)) {
return false; return false;
} }

View File

@ -4,6 +4,7 @@ import froca from "./froca.js";
import attributeRenderer from "./attribute_renderer.js"; import attributeRenderer from "./attribute_renderer.js";
import libraryLoader from "./library_loader.js"; import libraryLoader from "./library_loader.js";
import treeService from "./tree.js"; import treeService from "./tree.js";
import utils from "./utils.js";
const TPL = ` const TPL = `
<div class="note-list"> <div class="note-list">
@ -215,7 +216,11 @@ class NoteListRenderer {
if (highlightedTokens.length > 0) { if (highlightedTokens.length > 0) {
await libraryLoader.requireLibrary(libraryLoader.MARKJS); await libraryLoader.requireLibrary(libraryLoader.MARKJS);
this.highlightRegex = new RegExp(highlightedTokens.join("|"), 'gi'); const regex = highlightedTokens
.map(token => utils.escapeRegExp(token))
.join("|");
this.highlightRegex = new RegExp(regex, 'gi');
} else { } else {
this.highlightRegex = null; this.highlightRegex = null;
} }

View File

@ -1,21 +1,19 @@
import server from "./server.js"; import server from "./server.js";
import froca from "./froca.js"; import froca from "./froca.js";
async function getNoteTypeItems(command, opts = {}) { async function getNoteTypeItems(command) {
const removeDeprecatedTypes = !!opts.removeDeprecatedTypes;
const items = [ const items = [
{ title: "Text", command: command, type: "text", uiIcon: "bx bx-note" }, { title: "Text", command: command, type: "text", uiIcon: "bx bx-note" },
{ title: "Code", command: command, type: "code", uiIcon: "bx bx-code" }, { title: "Code", command: command, type: "code", uiIcon: "bx bx-code" },
{ title: "Saved Search", command: command, type: "search", uiIcon: "bx bx-file-find" }, { title: "Saved Search", command: command, type: "search", uiIcon: "bx bx-file-find" },
{ title: "Relation Map", command: command, type: "relationMap", uiIcon: "bx bx-map-alt", deprecated: true }, { title: "Relation Map", command: command, type: "relationMap", uiIcon: "bx bx-map-alt" },
{ title: "Note Map", command: command, type: "noteMap", uiIcon: "bx bx-map-alt" }, { title: "Note Map", command: command, type: "noteMap", uiIcon: "bx bx-map-alt" },
{ title: "Render Note", command: command, type: "render", uiIcon: "bx bx-extension" }, { title: "Render Note", command: command, type: "render", uiIcon: "bx bx-extension" },
{ title: "Book", command: command, type: "book", uiIcon: "bx bx-book" }, { title: "Book", command: command, type: "book", uiIcon: "bx bx-book" },
{ title: "Mermaid Diagram", command: command, type: "mermaid", uiIcon: "bx bx-selection" }, { title: "Mermaid Diagram", command: command, type: "mermaid", uiIcon: "bx bx-selection" },
{ title: "Canvas", command: command, type: "canvas", uiIcon: "bx bx-pen" }, { title: "Canvas", command: command, type: "canvas", uiIcon: "bx bx-pen" },
{ title: "Web View", command: command, type: "webView", uiIcon: "bx bx-globe-alt" }, { title: "Web View", command: command, type: "webView", uiIcon: "bx bx-globe-alt" },
].filter(item => !removeDeprecatedTypes || !item.deprecated); ];
const templateNoteIds = await server.get("search-templates"); const templateNoteIds = await server.get("search-templates");
const templateNotes = await froca.getNotes(templateNoteIds); const templateNotes = await froca.getNotes(templateNoteIds);

View File

@ -487,12 +487,14 @@ function areObjectsEqual () {
} }
function copyHtmlToClipboard(content) { function copyHtmlToClipboard(content) {
const clipboardItem = new ClipboardItem({ function listener(e) {
'text/html': new Blob([content], {type: 'text/html'}), e.clipboardData.setData("text/html", content);
'text/plain': new Blob([content], {type: 'text/plain'}) e.clipboardData.setData("text/plain", content);
}); e.preventDefault();
}
navigator.clipboard.write([clipboardItem]); document.addEventListener("copy", listener);
document.execCommand("copy");
document.removeEventListener("copy", listener);
} }
/** /**

View File

@ -200,7 +200,7 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget {
this.attributeDetailWidget.hide(); this.attributeDetailWidget.hide();
}); });
this.$editor.on('blur', () => this.save()); this.$editor.on('blur', () => setTimeout(() => this.save(), 100)); // Timeout to fix https://github.com/zadam/trilium/issues/4160
this.$addNewAttributeButton = this.$widget.find('.add-new-attribute-button'); this.$addNewAttributeButton = this.$widget.find('.add-new-attribute-button');
this.$addNewAttributeButton.on('click', e => this.addNewAttribute(e)); this.$addNewAttributeButton.on('click', e => this.addNewAttribute(e));

View File

@ -8,10 +8,13 @@ export default class RightPaneContainer extends FlexContainer {
this.id('right-pane'); this.id('right-pane');
this.css('height', '100%'); this.css('height', '100%');
this.collapsible(); this.collapsible();
this.rightPaneHidden = false;
} }
isEnabled() { isEnabled() {
return super.isEnabled() return super.isEnabled()
&& !this.rightPaneHidden
&& this.children.length > 0 && this.children.length > 0
&& !!this.children.find(ch => ch.isEnabled() && ch.canBeShown()); && !!this.children.find(ch => ch.isEnabled() && ch.canBeShown());
} }
@ -44,4 +47,10 @@ export default class RightPaneContainer extends FlexContainer {
splitService.setupRightPaneResizer(); splitService.setupRightPaneResizer();
} }
} }
toggleRightPaneEvent() {
this.rightPaneHidden = !this.rightPaneHidden;
this.reEvaluateRightPaneVisibilityCommand();
}
} }

View File

@ -1091,7 +1091,9 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
return; return;
} }
const nodeCtx = this.#getActiveNodeCtx(); const activeNode = this.getActiveNode();
const activeNodeFocused = activeNode?.hasFocus();
const activeNotePath = activeNode ? treeService.getNotePath(activeNode) : null;
const refreshCtx = { const refreshCtx = {
noteIdsToUpdate: new Set(), noteIdsToUpdate: new Set(),
@ -1108,7 +1110,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
await this.#executeTreeUpdates(refreshCtx, loadResults); await this.#executeTreeUpdates(refreshCtx, loadResults);
await this.#setActiveNode(nodeCtx, movedActiveNode, parentsOfAddedNodes); await this.#setActiveNode(activeNotePath, activeNodeFocused, movedActiveNode, parentsOfAddedNodes);
if (refreshCtx.noteIdsToReload.size > 0 || refreshCtx.noteIdsToUpdate.size > 0) { if (refreshCtx.noteIdsToReload.size > 0 || refreshCtx.noteIdsToUpdate.size > 0) {
// workaround for https://github.com/mar10/fancytree/issues/1054 // workaround for https://github.com/mar10/fancytree/issues/1054
@ -1257,73 +1259,42 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
} }
} }
#getActiveNodeCtx() { async #setActiveNode(activeNotePath, activeNodeFocused, movedActiveNode, parentsOfAddedNodes) {
const nodeCtx = {
activeNotePath: null,
activeNodeFocused: null,
nextNotePath: null
};
const activeNode = this.getActiveNode();
nodeCtx.activeNodeFocused = activeNode?.hasFocus();
nodeCtx.activeNotePath = activeNode ? treeService.getNotePath(activeNode) : null;
const nextNode = activeNode ? (activeNode.getNextSibling() || activeNode.getPrevSibling() || activeNode.getParent()) : null;
nodeCtx.nextNotePath = nextNode ? treeService.getNotePath(nextNode) : null;
return nodeCtx;
}
async #setActiveNode(nodeCtx, movedActiveNode, parentsOfAddedNodes) {
if (movedActiveNode) { if (movedActiveNode) {
for (const parentNode of parentsOfAddedNodes) { for (const parentNode of parentsOfAddedNodes) {
const foundNode = (parentNode.getChildren() || []).find(child => child.data.noteId === movedActiveNode.data.noteId); const foundNode = (parentNode.getChildren() || []).find(child => child.data.noteId === movedActiveNode.data.noteId);
if (foundNode) { if (foundNode) {
nodeCtx.activeNotePath = treeService.getNotePath(foundNode); activeNotePath = treeService.getNotePath(foundNode);
break; break;
} }
} }
} }
if (!nodeCtx.activeNotePath) { if (!activeNotePath) {
return; return;
} }
let node = await this.expandToNote(nodeCtx.activeNotePath, false); let node = await this.expandToNote(activeNotePath, false);
if (node && node.data.noteId !== treeService.getNoteIdFromUrl(nodeCtx.activeNotePath)) {
if (node && node.data.noteId !== treeService.getNoteIdFromUrl(activeNotePath)) {
// if the active note has been moved elsewhere then it won't be found by the path, // if the active note has been moved elsewhere then it won't be found by the path,
// so we switch to the alternative of trying to find it by noteId // so we switch to the alternative of trying to find it by noteId
const notesById = this.getNodesByNoteId(treeService.getNoteIdFromUrl(nodeCtx.activeNotePath)); const notesById = this.getNodesByNoteId(treeService.getNoteIdFromUrl(activeNotePath));
// if there are multiple clones, then we'd rather not activate anyone // if there are multiple clones, then we'd rather not activate anyone
node = notesById.length === 1 ? notesById[0] : null; node = notesById.length === 1 ? notesById[0] : null;
} }
if (node) { if (!node) {
if (nodeCtx.activeNodeFocused) { return;
// needed by Firefox: https://github.com/zadam/trilium/issues/1865
this.tree.$container.focus();
}
await node.setActive(true, {noEvents: true, noFocus: !nodeCtx.activeNodeFocused});
} else {
// this is used when the original note has been deleted, and we want to move the focus to the note above/below
node = await this.expandToNote(nodeCtx.nextNotePath, false);
if (node) {
// FIXME: this is conceptually wrong
// here note tree is responsible for updating global state of the application
// this should be done by NoteContext / TabManager and note tree should only listen to
// changes in active note and just set the "active" state
// We don't await since that can bring up infinite cycles when e.g. custom widget does some backend requests which wait for max sync ID processed
appContext.tabManager.getActiveContext().setNote(nodeCtx.nextNotePath).then(() => {
const newActiveNode = this.getActiveNode();
// return focus if the previously active node was also focused
if (newActiveNode && nodeCtx.activeNodeFocused) {
newActiveNode.setFocus(true);
}
});
}
} }
if (activeNodeFocused) {
// needed by Firefox: https://github.com/zadam/trilium/issues/1865
this.tree.$container.focus();
}
await node.setActive(true, {noEvents: true, noFocus: !activeNodeFocused});
} }
sortChildren(node) { sortChildren(node) {

View File

@ -30,9 +30,14 @@ const TPL = `
height: 40px; height: 40px;
width: 40px; width: 40px;
} }
.title-bar-buttons .top-btn.active{ .title-bar-buttons .top-btn.active{
background-color:var(--accented-background-color); background-color:var(--accented-background-color);
} }
.title-bar-buttons .btn.focus, .title-bar-buttons .btn:focus {
box-shadow: none;
}
</style> </style>
<!-- divs act as a hitbox for the buttons, making them clickable on corners --> <!-- divs act as a hitbox for the buttons, making them clickable on corners -->

View File

@ -1,10 +1,7 @@
import libraryLoader from "../../services/library_loader.js"; import libraryLoader from '../../services/library_loader.js';
import TypeWidget from "./type_widget.js"; import TypeWidget from './type_widget.js';
import utils from '../../services/utils.js'; import utils from '../../services/utils.js';
import linkService from '../../services/link.js'; import linkService from '../../services/link.js';
import debounce from "../../services/debounce.js";
const {sleep} = utils;
const TPL = ` const TPL = `
<div class="canvas-widget note-detail-canvas note-detail-printable note-detail"> <div class="canvas-widget note-detail-canvas note-detail-printable note-detail">
@ -105,8 +102,6 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
this.SCENE_VERSION_INITIAL = -1; // -1 indicates that it is fresh. excalidraw scene version is always >0 this.SCENE_VERSION_INITIAL = -1; // -1 indicates that it is fresh. excalidraw scene version is always >0
this.SCENE_VERSION_ERROR = -2; // -2 indicates error this.SCENE_VERSION_ERROR = -2; // -2 indicates error
// config
this.DEBOUNCE_TIME_ONCHANGEHANDLER = 750; // ms
// ensure that assets are loaded from trilium // ensure that assets are loaded from trilium
window.EXCALIDRAW_ASSET_PATH = `${window.location.origin}/node_modules/@excalidraw/excalidraw/dist/`; window.EXCALIDRAW_ASSET_PATH = `${window.location.origin}/node_modules/@excalidraw/excalidraw/dist/`;
@ -115,16 +110,10 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
this.currentSceneVersion = this.SCENE_VERSION_INITIAL; this.currentSceneVersion = this.SCENE_VERSION_INITIAL;
// will be overwritten // will be overwritten
this.excalidrawRef;
this.$render; this.$render;
this.$widget; this.$widget;
this.reactHandlers; // used to control react state this.reactHandlers; // used to control react state
// binds
this.createExcalidrawReactApp = this.createExcalidrawReactApp.bind(this);
this.onChangeHandler = this.onChangeHandler.bind(this);
this.isNewSceneVersion = this.isNewSceneVersion.bind(this);
this.libraryChanged = false; this.libraryChanged = false;
} }
@ -155,7 +144,8 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
const renderElement = this.$render.get(0); const renderElement = this.$render.get(0);
ReactDOM.unmountComponentAtNode(renderElement); ReactDOM.unmountComponentAtNode(renderElement);
ReactDOM.render(React.createElement(this.createExcalidrawReactApp), renderElement); const root = ReactDOM.createRoot(renderElement);
root.render(React.createElement(() => this.createExcalidrawReactApp()));
}); });
return this.$widget; return this.$widget;
@ -179,9 +169,9 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
const blob = await note.getBlob(); const blob = await note.getBlob();
// before we load content into excalidraw, make sure excalidraw has loaded // before we load content into excalidraw, make sure excalidraw has loaded
while (!this.excalidrawRef?.current) { while (!this.excalidrawApi) {
console.log("excalidrawRef not yet loaded, sleep 200ms..."); console.log("excalidrawApi not yet loaded, sleep 200ms...");
await sleep(200); await utils.sleep(200);
} }
/** /**
@ -199,7 +189,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
collaborators: [] collaborators: []
}; };
this.excalidrawRef.current.updateScene(sceneData); this.excalidrawApi.updateScene(sceneData);
} }
else if (blob.content) { else if (blob.content) {
// load saved content into excalidraw canvas // load saved content into excalidraw canvas
@ -246,9 +236,9 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
fileArray.push(file); fileArray.push(file);
} }
this.excalidrawRef.current.updateScene(sceneData); this.excalidrawApi.updateScene(sceneData);
this.excalidrawRef.current.addFiles(fileArray); this.excalidrawApi.addFiles(fileArray);
this.excalidrawRef.current.history.clear(); this.excalidrawApi.history.clear();
} }
Promise.all( Promise.all(
@ -261,7 +251,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
} }
const libraryItems = blobs.map(blob => blob.getJsonContentSafely()).filter(item => !!item); const libraryItems = blobs.map(blob => blob.getJsonContentSafely()).filter(item => !!item);
this.excalidrawRef.current.updateLibrary({libraryItems, merge: false}); this.excalidrawApi.updateLibrary({libraryItems, merge: false});
}); });
// set initial scene version // set initial scene version
@ -275,17 +265,17 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
* this is automatically called after this.saveData(); * this is automatically called after this.saveData();
*/ */
async getData() { async getData() {
const elements = this.excalidrawRef.current.getSceneElements(); const elements = this.excalidrawApi.getSceneElements();
const appState = this.excalidrawRef.current.getAppState(); const appState = this.excalidrawApi.getAppState();
/** /**
* A file is not deleted, even though removed from canvas. Therefore, we only keep * A file is not deleted, even though removed from canvas. Therefore, we only keep
* files that are referenced by an element. Maybe this will change with a new excalidraw version? * files that are referenced by an element. Maybe this will change with a new excalidraw version?
*/ */
const files = this.excalidrawRef.current.getFiles(); const files = this.excalidrawApi.getFiles();
// parallel svg export to combat bitrot and enable rendering image for note inclusion, preview, and share // parallel svg export to combat bitrot and enable rendering image for note inclusion, preview, and share
const svg = await window.ExcalidrawLib.exportToSvg({ const svg = await ExcalidrawLib.exportToSvg({
elements, elements,
appState, appState,
exportPadding: 5, // 5 px padding exportPadding: 5, // 5 px padding
@ -321,7 +311,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
// this.libraryChanged is unset in dataSaved() // this.libraryChanged is unset in dataSaved()
// there's no separate method to get library items, so have to abuse this one // there's no separate method to get library items, so have to abuse this one
const libraryItems = await this.excalidrawRef.current.updateLibrary({merge: true}); const libraryItems = await this.excalidrawApi.updateLibrary({merge: true});
let position = 10; let position = 10;
@ -379,9 +369,6 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
createExcalidrawReactApp() { createExcalidrawReactApp() {
const React = window.React; const React = window.React;
const { Excalidraw } = window.ExcalidrawLib; const { Excalidraw } = window.ExcalidrawLib;
const excalidrawRef = React.useRef(null);
this.excalidrawRef = excalidrawRef;
const excalidrawWrapperRef = React.useRef(null); const excalidrawWrapperRef = React.useRef(null);
this.excalidrawWrapperRef = excalidrawWrapperRef; this.excalidrawWrapperRef = excalidrawWrapperRef;
const [dimensions, setDimensions] = React.useState({ const [dimensions, setDimensions] = React.useState({
@ -439,7 +426,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
React.createElement(Excalidraw, { React.createElement(Excalidraw, {
// this makes sure that 1) manual theme switch button is hidden 2) theme stays as it should after opening menu // this makes sure that 1) manual theme switch button is hidden 2) theme stays as it should after opening menu
theme: this.themeStyle, theme: this.themeStyle,
ref: excalidrawRef, excalidrawAPI: api => { this.excalidrawApi = api; },
width: dimensions.width, width: dimensions.width,
height: dimensions.height, height: dimensions.height,
onPaste: (data, event) => { onPaste: (data, event) => {
@ -450,7 +437,7 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
this.saveData(); this.saveData();
}, },
onChange: debounce(this.onChangeHandler, this.DEBOUNCE_TIME_ONCHANGEHANDLER), onChange: () => this.onChangeHandler(),
viewModeEnabled: false, viewModeEnabled: false,
zenModeEnabled: false, zenModeEnabled: false,
gridModeEnabled: false, gridModeEnabled: false,
@ -483,8 +470,8 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
} }
getSceneVersion() { getSceneVersion() {
if (this.excalidrawRef) { if (this.excalidrawApi) {
const elements = this.excalidrawRef.current.getSceneElements(); const elements = this.excalidrawApi.getSceneElements();
return window.ExcalidrawLib.getSceneVersion(elements); return window.ExcalidrawLib.getSceneVersion(elements);
} else { } else {
return this.SCENE_VERSION_ERROR; return this.SCENE_VERSION_ERROR;

View File

@ -18,6 +18,8 @@ const TPL = `
<h5>Highlights List visibility</h5> <h5>Highlights List visibility</h5>
<p>You can hide the highlights widget per-note by adding a <code>#hideHighlightWidget</code> label.</p> <p>You can hide the highlights widget per-note by adding a <code>#hideHighlightWidget</code> label.</p>
<p>You can configure a keyboard shortcut for quickly toggling the right pane (including Highlights) in the Options -> Shortcuts (name "toggleRightPane").</p>
</div>`; </div>`;
export default class HighlightsListOptions extends OptionsWidget { export default class HighlightsListOptions extends OptionsWidget {

View File

@ -11,6 +11,8 @@ const TPL = `
</div> </div>
<p>You can also use this option to effectively disable TOC by setting a very high number.</p> <p>You can also use this option to effectively disable TOC by setting a very high number.</p>
<p>You can configure a keyboard shortcut for quickly toggling the right pane (including TOC) in the Options -> Shortcuts (name "toggleRightPane").</p>
</div>`; </div>`;
export default class TableOfContentsOptions extends OptionsWidget { export default class TableOfContentsOptions extends OptionsWidget {

View File

@ -184,8 +184,6 @@ export default class RelationMapTypeWidget extends TypeWidget {
} }
async loadMapData() { async loadMapData() {
toastService.showMessage("Relation Map has been deprecated since Trilium 0.63 and will be removed in a future version. Migrate your content to some other note type (e.g. canvas) as soon as possible.", 5000);
this.mapData = { this.mapData = {
notes: [], notes: [],
// it is important to have this exact value here so that initial transform is the same as this // it is important to have this exact value here so that initial transform is the same as this

View File

@ -9,14 +9,9 @@
"start_url": "/", "start_url": "/",
"icons": [ "icons": [
{ {
"src": "/assets/vX/images/app-icons/ios/apple-touch-icon.png", "src": "favicon.ico",
"sizes": "180x180", "sizes": "180x180 512x512",
"type": "image/png" "type": "image/x-icon"
},
{
"src": "/assets/vX/images/app-icons/png/512x512.png",
"sizes": "512x512",
"type": "image/png"
} }
] ]
} }

View File

@ -3,6 +3,7 @@ body {
--ck-color-base-text: var(--main-text-color); --ck-color-base-text: var(--main-text-color);
--ck-color-base-foreground: var(--accented-background-color); --ck-color-base-foreground: var(--accented-background-color);
--ck-color-base-background: var(--main-background-color);
--ck-color-focus-border: var(--main-border-color); --ck-color-focus-border: var(--main-border-color);
--ck-color-text: var(--main-text-color); --ck-color-text: var(--main-text-color);
--ck-color-shadow-drop: var(--main-background-color); --ck-color-shadow-drop: var(--main-background-color);

View File

@ -88,3 +88,7 @@ body .CodeMirror {
.excalidraw.theme--dark { .excalidraw.theme--dark {
--theme-filter: invert(80%) hue-rotate(180deg) !important; --theme-filter: invert(80%) hue-rotate(180deg) !important;
} }
body .todo-list input[type="checkbox"]:not(:checked):before {
border-color: var(--muted-text-color) !important;
}

View File

@ -154,12 +154,16 @@ function saveAttachmentToTmpDir(req) {
return saveToTmpDir(fileName, content, 'attachments', attachment.attachmentId); return saveToTmpDir(fileName, content, 'attachments', attachment.attachmentId);
} }
const createdTemporaryFiles = new Set();
function saveToTmpDir(fileName, content, entityType, entityId) { function saveToTmpDir(fileName, content, entityType, entityId) {
const tmpObj = tmp.fileSync({ postfix: fileName }); const tmpObj = tmp.fileSync({ postfix: fileName });
fs.writeSync(tmpObj.fd, content); fs.writeSync(tmpObj.fd, content);
fs.closeSync(tmpObj.fd); fs.closeSync(tmpObj.fd);
createdTemporaryFiles.add(tmpObj.name);
log.info(`Saved temporary file ${tmpObj.name}`); log.info(`Saved temporary file ${tmpObj.name}`);
if (utils.isElectron()) { if (utils.isElectron()) {
@ -183,6 +187,10 @@ function uploadModifiedFileToNote(req) {
const noteId = req.params.noteId; const noteId = req.params.noteId;
const {filePath} = req.body; const {filePath} = req.body;
if (!createdTemporaryFiles.has(filePath)) {
throw new ValidationError(`File '${filePath}' is not a temporary file.`);
}
const note = becca.getNoteOrThrow(noteId); const note = becca.getNoteOrThrow(noteId);
log.info(`Updating note '${noteId}' with content from '${filePath}'`); log.info(`Updating note '${noteId}' with content from '${filePath}'`);

View File

@ -43,12 +43,16 @@ const optionsService = require('./options.js');
*/ */
function BackendScriptApi(currentNote, apiParams) { function BackendScriptApi(currentNote, apiParams) {
/** /**
* Note where the script started executing * Note where the script started executing (entrypoint).
* As an analogy, in C this would be the file which contains the main() function of the current process.
* @type {BNote} * @type {BNote}
*/ */
this.startNote = apiParams.startNote; this.startNote = apiParams.startNote;
/** /**
* Note where the script is currently executing. Don't mix this up with the concept of active note * Note where the script is currently executing. This comes into play when your script is spread in multiple code
* notes, the script starts in "startNote", but then through function calls may jump into another note (currentNote).
* A similar concept in C would be __FILE__
* Don't mix this up with the concept of active note.
* @type {BNote} * @type {BNote}
*/ */
this.currentNote = currentNote; this.currentNote = currentNote;
@ -288,7 +292,7 @@ function BackendScriptApi(currentNote, apiParams) {
* @param {string} params.parentNoteId * @param {string} params.parentNoteId
* @param {string} params.title * @param {string} params.title
* @param {string|Buffer} params.content * @param {string|Buffer} params.content
* @param {NoteType} params.type - text, code, file, image, search, book, relationMap, canvas * @param {NoteType} params.type - text, code, file, image, search, book, relationMap, canvas, webView
* @param {string} [params.mime] - value is derived from default mimes for type * @param {string} [params.mime] - value is derived from default mimes for type
* @param {boolean} [params.isProtected=false] * @param {boolean} [params.isProtected=false]
* @param {boolean} [params.isExpanded=false] * @param {boolean} [params.isExpanded=false]

View File

@ -1 +1 @@
module.exports = { buildDate:"2024-01-12T00:02:50+01:00", buildRevision: "17e063f01d3b6c7a601630feaa96191d26095650" }; module.exports = { buildDate:"2024-05-18T06:17:21+02:00", buildRevision: "c7f19e04fafc031910f6f9a45d2015387618e902" };

View File

@ -48,6 +48,14 @@ function isEntityEventsDisabled() {
return !!namespace.get('disableEntityEvents'); return !!namespace.get('disableEntityEvents');
} }
function setMigrationRunning(running) {
namespace.set('migrationRunning', !!running);
}
function isMigrationRunning() {
return !!namespace.get('migrationRunning');
}
function disableSlowQueryLogging(disable) { function disableSlowQueryLogging(disable) {
namespace.set('disableSlowQueryLogging', disable); namespace.set('disableSlowQueryLogging', disable);
} }
@ -102,5 +110,7 @@ module.exports = {
putEntityChange, putEntityChange,
ignoreEntityChangeIds, ignoreEntityChangeIds,
disableSlowQueryLogging, disableSlowQueryLogging,
isSlowQueryLoggingDisabled isSlowQueryLoggingDisabled,
setMigrationRunning,
isMigrationRunning
}; };

View File

@ -494,9 +494,16 @@ const DEFAULT_KEYBOARD_ACTIONS = [
separator: "Other" separator: "Other"
}, },
{
actionName: "toggleRightPane",
defaultShortcuts: [],
description: "Toggle the display of the right pane, which includes Table of Contents and Highlights",
scope: "window"
},
{ {
actionName: "printActiveNote", actionName: "printActiveNote",
defaultShortcuts: [], defaultShortcuts: [],
description: "Print active note",
scope: "window" scope: "window"
}, },
{ {

View File

@ -5,12 +5,13 @@ const log = require('./log.js');
const utils = require('./utils.js'); const utils = require('./utils.js');
const resourceDir = require('./resource_dir.js'); const resourceDir = require('./resource_dir.js');
const appInfo = require('./app_info.js'); const appInfo = require('./app_info.js');
const cls = require('./cls.js');
async function migrate() { async function migrate() {
const currentDbVersion = getDbVersion(); const currentDbVersion = getDbVersion();
if (currentDbVersion < 214) { if (currentDbVersion < 214) {
log.error("Direct migration from your current version is not supported. Please upgrade to the latest v0.60.X first and only then to this version."); log.error("Direct migration from your current version is not supported. Please upgrade to the latest v0.60.4 first and only then to this version.");
utils.crash(); utils.crash();
return; return;
@ -18,7 +19,7 @@ async function migrate() {
// backup before attempting migration // backup before attempting migration
await backupService.backupNow( await backupService.backupNow(
// creating a special backup for versions 0.60.X, the changes in 0.61 are major. // creating a special backup for version 0.60.4, the changes in 0.61 are major.
currentDbVersion === 214 currentDbVersion === 214
? `before-migration-v060` ? `before-migration-v060`
: 'before-migration' : 'before-migration'
@ -51,6 +52,9 @@ async function migrate() {
// all migrations are executed in one transaction - upgrade either succeeds, or the user can stay at the old version // all migrations are executed in one transaction - upgrade either succeeds, or the user can stay at the old version
// otherwise if half of the migrations succeed, user can't use any version - DB is too "new" for the old app, // otherwise if half of the migrations succeed, user can't use any version - DB is too "new" for the old app,
// and too old for the new app version. // and too old for the new app version.
cls.setMigrationRunning(true);
sql.transactional(() => { sql.transactional(() => {
for (const mig of migrations) { for (const mig of migrations) {
try { try {

View File

@ -458,13 +458,18 @@ function findIncludeNoteLinks(content, foundLinks) {
} }
function findRelationMapLinks(content, foundLinks) { function findRelationMapLinks(content, foundLinks) {
const obj = JSON.parse(content); try {
const obj = JSON.parse(content);
for (const note of obj.notes) { for (const note of obj.notes) {
foundLinks.push({ foundLinks.push({
name: 'relationMapLink', name: 'relationMapLink',
value: note.noteId value: note.noteId
}); });
}
}
catch (e) {
log.error("Could not scan for relation map links: " + e.message);
} }
} }
@ -895,6 +900,11 @@ function scanForLinks(note, content) {
* Things which have to be executed after updating content, but asynchronously (separate transaction) * Things which have to be executed after updating content, but asynchronously (separate transaction)
*/ */
async function asyncPostProcessContent(note, content) { async function asyncPostProcessContent(note, content) {
if (cls.isMigrationRunning()) {
// this is rarely needed for migrations, but can cause trouble by e.g. triggering downloads
return;
}
if (note.hasStringContent() && !utils.isString(content)) { if (note.hasStringContent() && !utils.isString(content)) {
content = content.toString(); content = content.toString();
} }

View File

@ -111,11 +111,7 @@ class NoteContentFulltextExp extends Expression {
if (type === 'text' && mime === 'text/html') { if (type === 'text' && mime === 'text/html') {
if (!this.raw && content.length < 20000) { // striptags is slow for very large notes if (!this.raw && content.length < 20000) { // striptags is slow for very large notes
// allow link to preserve URLs: https://github.com/zadam/trilium/issues/2412 content = this.stripTags(content);
content = striptags(content, ['a'], ' ');
// at least the closing tag can be easily stripped
content = content.replace(/<\/a>/ig, "");
} }
content = content.replace(/&nbsp;/g, ' '); content = content.replace(/&nbsp;/g, ' ');
@ -123,6 +119,23 @@ class NoteContentFulltextExp extends Expression {
return content.trim(); return content.trim();
} }
stripTags(content) {
// we want to allow link to preserve URLs: https://github.com/zadam/trilium/issues/2412
// we want to insert space in place of block tags (because they imply text separation)
// but we don't want to insert text for typical formatting inline tags which can occur within one word
const linkTag = 'a';
const inlineFormattingTags = ['b', 'strong', 'em', 'i', 'span', 'big', 'small', 'font', 'sub', 'sup'];
// replace tags which imply text separation with a space
content = striptags(content, [linkTag, ...inlineFormattingTags], ' ');
// replace the inline formatting tags (but not links) without a space
content = striptags(content, [linkTag], '');
// at least the closing link tag can be easily stripped
return content.replace(/<\/a>/ig, "");
}
} }
module.exports = NoteContentFulltextExp; module.exports = NoteContentFulltextExp;

View File

@ -105,10 +105,10 @@ function renderText(result, note) {
if (result.content.includes(`<span class="math-tex">`)) { if (result.content.includes(`<span class="math-tex">`)) {
result.header += ` result.header += `
<script src="../../${assetPath}/node_modules/katex/dist/katex.min.js"></script> <script src="../${assetPath}/node_modules/katex/dist/katex.min.js"></script>
<link rel="stylesheet" href="../../${assetPath}/node_modules/katex/dist/katex.min.css"> <link rel="stylesheet" href="../${assetPath}/node_modules/katex/dist/katex.min.css">
<script src="../../${assetPath}/node_modules/katex/dist/contrib/auto-render.min.js"></script> <script src="../${assetPath}/node_modules/katex/dist/contrib/auto-render.min.js"></script>
<script src="../../${assetPath}/node_modules/katex/dist/contrib/mhchem.min.js"></script> <script src="../${assetPath}/node_modules/katex/dist/contrib/mhchem.min.js"></script>
<script> <script>
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
renderMathInElement(document.getElementById('content')); renderMathInElement(document.getElementById('content'));

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<link rel="shortcut icon" href="favicon.ico"> <link rel="shortcut icon" href="favicon.ico">
<link rel="manifest" href="manifest.webmanifest"> <link rel="manifest" crossorigin="use-credentials" href="manifest.webmanifest">
<title>Trilium Notes</title> <title>Trilium Notes</title>
</head> </head>
<body class="desktop heading-style-<%= headingStyle %>"> <body class="desktop heading-style-<%= headingStyle %>">

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#fff"> <meta name="theme-color" content="#fff">
<title>Trilium Notes</title> <title>Trilium Notes</title>
<link rel="manifest" href="manifest.webmanifest"> <link rel="manifest" crossorigin="use-credentials" href="manifest.webmanifest">
<style> <style>
.lds-roller { .lds-roller {

View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
[[ ! -z "${USER_UID}" ]] && usermod -u ${USER_UID} node || echo "No USER_UID specified, leaving 1000" [[ ! -z "${USER_UID}" ]] && usermod -u ${USER_UID} node || echo "No USER_UID specified, leaving 1000"
[[ ! -z "${USER_GID}" ]] && groupmod -g ${USER_GID} node || echo "No USER_GID specified, leaving 1000" [[ ! -z "${USER_GID}" ]] && groupmod -og ${USER_GID} node || echo "No USER_GID specified, leaving 1000"
chown -R node:node /home/node chown -R node:node /home/node
exec su-exec node node ./src/www exec su-exec node node ./src/www