+
+## ⚠️ ¿Por qué usar TriliumNext?
+
+[El proyecto Trilium original está en modo de mantenimiento](https://github.com/zadam/trilium/issues/4620)
+
+### ¿Cómo migrar desde Trilium?
+
+No hay pasos de migración especiales para migrar de una instancia de zadam/Trilium a una instancia de TriliumNext/Notes. Simplemente actualice su instancia de Trilium a la última versión e [instale TriliumNext/Notes como de costumbre](#-Instalación)
+
+## 💬 Discuta con nosotros
+
+Siéntase libre de unirse a nuestras conversaciones oficiales. ¡Nos encantaría escuchar de las características, sugerencias o problemas que pueda tener!
+
+- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (Para discusiones síncronas)
+ - La sala `General` es replicada a [XMPP](xmpp:discuss@trilium.thisgreat.party?join)
+- [Discusiones de GitHub](https://github.com/TriliumNext/Notes/discussions) (Para discusiones asíncronas)
+- [Wiki](https://triliumnext.github.io/Docs/) (Para preguntas frecuentes y guías de usuario)
+
+## 🎁 Características
+
+- Las notas pueden ser acomodadas en un árbol de profundidad arbitraria. Una sola nota puede ser colocada en múltiples lugares del árbol (vea [clonar](https://triliumnext.github.io/Docs/Wiki/cloning-notes)
+- Edición de notas WYSIWYG enriquecida que incluye, por ejemplo, tablas, imágenes y [matemáticas](https://triliumnext.github.io/Docs/Wiki/text-notes) con [autoformato](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat) markdown
+- Soporte para editar [notas con código fuente](https://triliumnext.github.io/Docs/Wiki/code-notes), incluyendo resaltado de sintaxis
+- Rápida y sencilla [navegación entre notas](https://triliumnext.github.io/Docs/Wiki/note-navigation), búsqueda de texto completo y [elevación de notas](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
+- [Versionado de notas](https://triliumnext.github.io/Docs/Wiki/note-revisions) sutil
+- Los [atributos](https://triliumnext.github.io/Docs/Wiki/attributes) de las notas pueden utilizarse para organización, realizar consultas y [scripts](https://triliumnext.github.io/Docs/Wiki/scripts) avanzados
+- [Sincronización](https://triliumnext.github.io/Docs/Wiki/synchronization) con servidor de sincronización propio
+ - existe un [servicio de terceros para alojar el servidor de sincronización](https://trilium.cc/paid-hosting)
+- [Compartir](https://triliumnext.github.io/Docs/Wiki/sharing) (publicar) notas al Internet público
+- Fuerte [encriptación de notas](https://triliumnext.github.io/Docs/Wiki/protected-notes) con granularidad para cada nota
+- Esbozo de diagramas con Excalidraw incorporado (tipo de nota «canvas»)
+- [Mapas de relaciones](
+### Mobile
+
+To use TriliumNext on a mobile device:
+
+* Use a mobile web browser to access the mobile interface of a server installation (see below)
+* Use of a mobile app is not yet supported ([see here](https://github.com/TriliumNext/Notes/issues/72)) to track mobile improvements.
+
+### Server
+
+To install TriliumNext on your own server (including via Docker from [Dockerhub](https://hub.docker.com/r/triliumnext/notes)) follow [the server installation docs](https://triliumnext.github.io/Docs/Wiki/server-installation).
## 📝 Documentation
[See wiki for complete list of documentation pages.](https://triliumnext.github.io/Docs)
-You can also read [Patterns of personal knowledge base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge) to get some inspiration on how you might use Trilium.
+You can also read [Patterns of personal knowledge base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge) to get some inspiration on how you might use TriliumNext.
## 💻 Contribute
-Clone locally and run
-```
+### Code
+
+```shell
+git clone https://github.com/TriliumNext/Notes.git
+cd Notes
npm install
npm run start-server
```
+### Documentation
+
+Head on over to our [Docs repo](https://github.com/TriliumNext/Docs)
+
## 👏 Shoutouts
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - best WYSIWYG editor on the market, very interactive and listening team
-* [FancyTree](https://github.com/mar10/fancytree) - very feature rich tree library without real competition. Trilium Notes would not be the same without it.
+* [FancyTree](https://github.com/mar10/fancytree) - very feature rich tree library without real competition. TriliumNext Notes would not be the same without it.
* [CodeMirror](https://github.com/codemirror/CodeMirror) - code editor with support for huge amount of languages
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library without competition. Used in [relation maps](https://triliumnext.github.io/Docs/Wiki/Relation-map) and [link maps](https://triliumnext.github.io/Docs/Wiki/Link-map)
diff --git a/README.ru.md b/README.ru.md
index 7964c0b48..d78738915 100644
--- a/README.ru.md
+++ b/README.ru.md
@@ -1,6 +1,6 @@
# TriliumNext Notes
-[English](https://github.com/TriliumNext/Notes/blob/master/README.md) | [Chinese](https://github.com/TriliumNext/Notes/blob/master/README-ZH_CN.md) | [Russian](https://github.com/TriliumNext/Notes/blob/master/README.ru.md) | [Japanese](https://github.com/TriliumNext/Notes/blob/master/README.ja.md) | [Italian](https://github.com/TriliumNext/Notes/blob/master/README.it.md)
+[English](./README.md) | [Chinese](./README-ZH_CN.md) | [Russian](./README.ru.md) | [Japanese](./README.ja.md) | [Italian](./README.it.md) | [Spanish](./README.es.md)
Trilium Notes – это приложение для заметок с иерархической структурой, ориентированное на создание больших персональных баз знаний. Для быстрого ознакомления посмотрите [скриншот-тур](https://triliumnext.github.io/Docs/Wiki/screenshot-tour):
@@ -41,7 +41,8 @@ Trilium предоставляется в виде десктопного при
## 💻 Участвуйте в разработке
Или склонируйте на своё устройство и запустите
-```
+
+```shell
npm install
npm run start-server
```
diff --git a/bin/better-sqlite3/linux-desktop-better_sqlite3.node b/bin/better-sqlite3/linux-desktop-better_sqlite3.node
deleted file mode 100755
index dc587cec5..000000000
Binary files a/bin/better-sqlite3/linux-desktop-better_sqlite3.node and /dev/null differ
diff --git a/bin/better-sqlite3/linux-server-better_sqlite3.node b/bin/better-sqlite3/linux-server-better_sqlite3.node
deleted file mode 100755
index 00c00a96f..000000000
Binary files a/bin/better-sqlite3/linux-server-better_sqlite3.node and /dev/null differ
diff --git a/bin/better-sqlite3/mac-arm64-better_sqlite3.node b/bin/better-sqlite3/mac-arm64-better_sqlite3.node
deleted file mode 100755
index 3eadd64bc..000000000
Binary files a/bin/better-sqlite3/mac-arm64-better_sqlite3.node and /dev/null differ
diff --git a/bin/better-sqlite3/mac-x64-better_sqlite3.node b/bin/better-sqlite3/mac-x64-better_sqlite3.node
deleted file mode 100755
index 0bb7c6a56..000000000
Binary files a/bin/better-sqlite3/mac-x64-better_sqlite3.node and /dev/null differ
diff --git a/bin/better-sqlite3/update.sh b/bin/better-sqlite3/update.sh
deleted file mode 100755
index 74dbeb01b..000000000
--- a/bin/better-sqlite3/update.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env bash
-ELECTRON_VERSION="electron-v125"
-NODE_VERSION="node-v115"
-
-if ! command -v jq &> /dev/null; then
- echo "Missing command: jq"
- exit 1
-fi
-
-script_dir=$(realpath $(dirname $0))
-cd "$script_dir"
-BETTER_SQLITE3_VERSION=$(jq -r '.dependencies.["better-sqlite3"]' ../../package.json | grep -oP "\d+\.\d+\.\d+")
-
-if [ -z $BETTER_SQLITE3_VERSION ]; then
- echo "Unable to determine better-sqlite3 version."
- exit 2
-fi
-
-echo "Version: $BETTER_SQLITE3_VERSION"
-
-function download() {
- version="$1"
- platform="$2"
- dest_name="$3"
- url=https://github.com/WiseLibs/better-sqlite3/releases/download/v${BETTER_SQLITE3_VERSION}/better-sqlite3-v${BETTER_SQLITE3_VERSION}-${version}-${platform}.tar.gz
- temp_file="temp.tar.gz"
- curl -L "$url" -o "$temp_file"
- tar -xzvf "$temp_file"
- mv build/Release/better_sqlite3.node "$dest_name-better_sqlite3.node"
- rm -rf build
- rm -f "$temp_file"
-}
-
-download $NODE_VERSION "linux-x64" "linux-server"
-download $ELECTRON_VERSION "linux-x64" "linux-desktop"
-download $ELECTRON_VERSION "win32-x64" "win"
-download $ELECTRON_VERSION "darwin-x64" "mac-x64"
-download $ELECTRON_VERSION "darwin-arm64" "mac-arm64"
\ No newline at end of file
diff --git a/bin/better-sqlite3/win-better_sqlite3.node b/bin/better-sqlite3/win-better_sqlite3.node
deleted file mode 100644
index 5020e45eb..000000000
Binary files a/bin/better-sqlite3/win-better_sqlite3.node and /dev/null differ
diff --git a/bin/build-debian.sh b/bin/build-debian.sh
deleted file mode 100755
index ecf88f359..000000000
--- a/bin/build-debian.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env bash
-
-set -e # Fail on any command error
-
-if ! command -v dpkg-deb &> /dev/null; then
- echo "Missing command: dpkg-deb"
- exit 1
-fi
-
-if dpkg-deb 2>&1 | grep BusyBox &> /dev/null; then
- echo "The dpkg-deb binary provided by BusyBox is not compatible. The Debian tool needs to be used instead."
- exit 1
-fi
-
-echo "Packaging debian x64 distribution..."
-
-VERSION=`jq -r ".version" package.json`
-
-./node_modules/.bin/electron-installer-debian --config bin/deb-options.json --options.version=${VERSION} --arch amd64
diff --git a/bin/build-docker.sh b/bin/build-docker.sh
index 9d614eb2b..a765930db 100755
--- a/bin/build-docker.sh
+++ b/bin/build-docker.sh
@@ -10,8 +10,8 @@ cat package.json | grep -v electron > server-package.json
echo "Compiling typescript..."
npx tsc
-sudo docker build -t zadam/trilium:$VERSION --network host -t zadam/trilium:$SERIES .
+sudo docker build -t triliumnext/notes:$VERSION --network host -t triliumnext/notes:$SERIES .
if [[ $VERSION != *"beta"* ]]; then
- sudo docker tag zadam/trilium:$VERSION zadam/trilium:latest
+ sudo docker tag triliumnext/notes:$VERSION triliumnext/notes:latest
fi
diff --git a/bin/build-linux-x64.sh b/bin/build-linux-x64.sh
deleted file mode 100755
index 8003c9d73..000000000
--- a/bin/build-linux-x64.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env bash
-
-set -e # Fail on any command error
-
-if ! command -v jq &> /dev/null; then
- echo "Missing command: jq"
- exit 1
-fi
-
-if ! command -v fakeroot &> /dev/null; then
- echo "Missing command: fakeroot"
- exit 1
-fi
-
-if ! command -v dpkg-deb &> /dev/null; then
- echo "Missing command: dpkg-deb"
- exit 1
-fi
-
-if dpkg-deb 2>&1 | grep BusyBox &> /dev/null; then
- echo "The dpkg-deb binary provided by BusyBox is not compatible. The Debian tool needs to be used instead."
- exit 1
-fi
-
-SRC_DIR=./dist/trilium-linux-x64-src
-
-[ "$1" != "DONTCOPY" ] && ./bin/copy-trilium.sh "$SRC_DIR"
-
-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
-
-echo "Packaging linux x64 electron build"
-./node_modules/.bin/electron-packager "$SRC_DIR" --asar --out=dist --executable-name=trilium --platform=linux --arch=x64 --overwrite
-
-BUILD_DIR=./dist/trilium-linux-x64
-rm -rf "$BUILD_DIR"
-
-mv "./dist/TriliumNext Notes-linux-x64" "$BUILD_DIR"
-
-cp images/app-icons/png/128x128.png "$BUILD_DIR"/icon.png
-cp bin/tpl/anonymize-database.sql "$BUILD_DIR"/
-
-cp -r dump-db "$BUILD_DIR"/
-rm -rf "$BUILD_DIR"/dump-db/node_modules
-
-for f in 'trilium-portable' 'trilium-safe-mode' 'trilium-no-cert-check'; do
- cp bin/tpl/"$f".sh "$BUILD_DIR"/
- chmod 755 "$BUILD_DIR"/"$f".sh
-done
-
-echo "Packaging linux x64 electron distribution..."
-VERSION=`jq -r ".version" package.json`
-
-pushd dist
- tar cJf "trilium-linux-x64-${VERSION}.tar.xz" trilium-linux-x64
-popd
-
-bin/build-debian.sh
diff --git a/bin/build-mac-arm64.sh b/bin/build-mac-arm64.sh
deleted file mode 100755
index c1b4ff144..000000000
--- a/bin/build-mac-arm64.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env bash
-
-set -e # Fail on any command error
-
-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
-
-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/TriliumNext 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
-
-zip -r9 --symlinks trilium-mac-arm64-${VERSION}.zip trilium-mac-arm64
diff --git a/bin/build-mac-x64.sh b/bin/build-mac-x64.sh
deleted file mode 100755
index 890cf6d3d..000000000
--- a/bin/build-mac-x64.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env bash
-
-set -e # Fail on any command error
-
-SRC_DIR=./dist/trilium-mac-x64-src
-
-if [ "$1" != "DONTCOPY" ]
-then
- ./bin/copy-trilium.sh $SRC_DIR
-fi
-
-echo "Copying required mac x64 binaries"
-
-cp -r bin/better-sqlite3/mac-x64-better_sqlite3.node $SRC_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node
-
-echo "Packaging mac x64 electron build"
-
-./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=darwin --arch=x64 --overwrite --icon=images/app-icons/mac/icon.icns
-
-BUILD_DIR=./dist/trilium-mac-x64
-rm -rf $BUILD_DIR
-
-# Mac build has by default useless directory level
-mv "./dist/TriliumNext Notes-darwin-x64" $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 x64 electron distribution..."
-
-VERSION=`jq -r ".version" package.json`
-
-cd dist
-
-zip -r9 --symlinks trilium-mac-x64-${VERSION}.zip trilium-mac-x64
diff --git a/bin/build-server.sh b/bin/build-server.sh
index 33a93bf5a..64e798422 100755
--- a/bin/build-server.sh
+++ b/bin/build-server.sh
@@ -22,15 +22,14 @@ rm -r $PKG_DIR/node/lib/node_modules/npm
rm -r $PKG_DIR/node/include/node
rm -r $PKG_DIR/node_modules/electron*
-rm -r $PKG_DIR/electron.js
+rm -r $PKG_DIR/electron*.js
-cp -r bin/better-sqlite3/linux-server-better_sqlite3.node $PKG_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node
-
-printf "#!/bin/sh\n./node/bin/node src/www" > $PKG_DIR/trilium.sh
+printf "#!/bin/sh\n./node/bin/node src/main" > $PKG_DIR/trilium.sh
chmod 755 $PKG_DIR/trilium.sh
cp bin/tpl/anonymize-database.sql $PKG_DIR/
+cp -r translations $PKG_DIR/
cp -r dump-db $PKG_DIR/
rm -rf $PKG_DIR/dump-db/node_modules
diff --git a/bin/build-win-x64.sh b/bin/build-win-x64.sh
deleted file mode 100755
index 1d5780d2a..000000000
--- a/bin/build-win-x64.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env bash
-
-set -e # Fail on any command error
-
-if ! command -v wine &> /dev/null; then
- echo "Missing command: wine"
- exit 1
-fi
-
-SRC_DIR=./dist/trilium-windows-x64-src
-
-if [ "$1" != "DONTCOPY" ]
-then
- ./bin/copy-trilium.sh $SRC_DIR
-fi
-
-echo "Copying required windows binaries"
-
-cp -r bin/better-sqlite3/win-better_sqlite3.node $SRC_DIR/node_modules/better-sqlite3/build/Release/better_sqlite3.node
-
-echo "Packaging windows x64 electron build"
-
-./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=win32 --arch=x64 --overwrite --icon=images/app-icons/win/icon.ico
-
-BUILD_DIR=./dist/trilium-windows-x64
-rm -rf $BUILD_DIR
-
-mv "./dist/TriliumNext Notes-win32-x64" $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 bin/tpl/trilium-{portable,no-cert-check,safe-mode}.bat $BUILD_DIR/
-
-if [ "$1" != "DONTPACK" ]
-then
- echo "Zipping windows x64 electron distribution..."
- VERSION=`jq -r ".version" package.json`
-
- cd dist
- zip -r9 trilium-windows-x64-${VERSION}.zip trilium-windows-x64
-fi
\ No newline at end of file
diff --git a/bin/copy-dist.ts b/bin/copy-dist.ts
index 820c6c864..1927221fc 100644
--- a/bin/copy-dist.ts
+++ b/bin/copy-dist.ts
@@ -35,7 +35,7 @@ const copy = async () => {
await fs.copy(file, path.join(DEST_DIR, file));
}
- const dirsToCopy = ["images", "libraries", "db"];
+ const dirsToCopy = ["images", "libraries", "translations", "db"];
for (const dir of dirsToCopy) {
log(`Copying ${dir}`);
await fs.copy(dir, path.join(DEST_DIR, dir));
@@ -75,7 +75,21 @@ const copy = async () => {
"node_modules/split.js/dist/",
"node_modules/panzoom/dist/",
"node_modules/i18next/",
- "node_modules/i18next-http-backend/"
+ "node_modules/i18next-http-backend/",
+ "node_modules/eslint/bin/",
+ "node_modules/jsplumb/dist/",
+ "node_modules/vanilla-js-wheel-zoom/dist/",
+ "node_modules/mark.js/dist/",
+ "node_modules/knockout/build/output/",
+ "node_modules/normalize.css/",
+ "node_modules/jquery.fancytree/dist/",
+ "node_modules/bootstrap/dist/",
+ "node_modules/autocomplete.js/dist/",
+ "node_modules/codemirror/lib/",
+ "node_modules/codemirror/addon/",
+ "node_modules/codemirror/mode/",
+ "node_modules/codemirror/keymap/",
+ "node_modules/mind-elixir/dist/"
];
for (const folder of nodeModulesFolder) {
diff --git a/bin/copy-trilium.sh b/bin/copy-trilium.sh
index 9f63aaaa8..ca2acf674 100755
--- a/bin/copy-trilium.sh
+++ b/bin/copy-trilium.sh
@@ -37,11 +37,11 @@ for f in 'package.json' 'package-lock.json' 'README.md' 'LICENSE' 'config-sample
done
# Patch package.json main
-sed -i 's/.\/dist\/electron.js/electron.js/g' "$DIR/package.json"
+sed -i 's/.\/dist\/electron-main.js/electron-main.js/g' "$DIR/package.json"
script_dir=$(realpath $(dirname $0))
cp -R "$script_dir/../build/src" "$DIR"
-cp "$script_dir/../build/electron.js" "$DIR"
+cp "$script_dir/../build/electron-main.js" "$DIR"
# run in subshell (so we return to original dir)
(cd $DIR && npm install --omit=dev)
@@ -52,7 +52,6 @@ if [[ -d "$DIR"/node_modules ]]; then
'@excalidraw/excalidraw/dist/excalidraw-assets-dev' '@excalidraw/excalidraw/dist/excalidraw.development.js' '@excalidraw/excalidraw/dist/excalidraw-with-preact.development.js' \
'mermaid/dist/mermaid.js' \
'boxicons/svg' 'boxicons/node_modules/react'/* \
- 'better-sqlite3/Release' 'better-sqlite3/deps/sqlite3.tar.gz' 'better-sqlite3/deps/sqlite3' \
'@jimp/plugin-print/fonts' 'jimp/browser' 'jimp/fonts'; do
[[ -e "$DIR"/node_modules/"$d" ]] && rm -r "$DIR"/node_modules/"$d"
done
diff --git a/bin/create-anonymization-script.js b/bin/create-anonymization-script.ts
similarity index 53%
rename from bin/create-anonymization-script.js
rename to bin/create-anonymization-script.ts
index 4c71d6071..5cf991b22 100755
--- a/bin/create-anonymization-script.js
+++ b/bin/create-anonymization-script.ts
@@ -1,7 +1,7 @@
#!/usr/bin/env node
-const anonymizationService = require('../src/services/anonymization');
-const fs = require('fs');
-const path = require('path');
+import anonymizationService from '../src/services/anonymization.js';
+import fs from 'fs';
+import path from 'path';
fs.writeFileSync(path.resolve(__dirname, 'tpl', 'anonymize-database.sql'), anonymizationService.getFullAnonymizationScript());
diff --git a/bin/create-icons.sh b/bin/create-icons.sh
new file mode 100755
index 000000000..fa370dde4
--- /dev/null
+++ b/bin/create-icons.sh
@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+
+if ! command -v magick &> /dev/null; then
+ echo "This tool requires ImageMagick to be installed in order to create the icons."
+ exit 1
+fi
+
+if ! command -v inkscape &> /dev/null; then
+ echo "This tool requires Inkscape to be render sharper SVGs than ImageMagick."
+ exit 1
+fi
+
+if ! command -v icnsutil &> /dev/null; then
+ echo "This tool requires icnsutil to be installed in order to generate macOS icons."
+ exit 1
+fi
+
+script_dir=$(realpath $(dirname $0))
+cd "${script_dir}/../images/app-icons"
+inkscape -w 180 -h 180 "../icon-color.svg" -o "./ios/apple-touch-icon.png"
+
+# Build PNGs
+inkscape -w 128 -h 128 "../icon-color.svg" -o "./png/128x128.png"
+inkscape -w 256 -h 256 "../icon-color.svg" -o "./png/256x256.png"
+inkscape -w 256 -h 256 "../icon-purple.svg" -o "./png/256x256-dev.png"
+
+# Build Mac .icns
+declare -a sizes=("16" "32" "512" "1024")
+for size in "${sizes[@]}"; do
+ inkscape -w $size -h $size "../icon-color.svg" -o "./png/${size}x${size}.png"
+done
+
+mkdir -p fakeapp.app
+npx iconsur set fakeapp.app -l -i "png/1024x1024.png" -o "mac/1024x1024.png" -s 0.8
+declare -a sizes=("16x16" "32x32" "128x128" "512x512")
+for size in "${sizes[@]}"; do
+ magick "mac/1024x1024.png" -resize "${size}" "mac/${size}.png"
+done
+icnsutil compose -f "mac/icon.icns" ./mac/*.png
+
+# Build Windows icon
+magick -background none "../icon-color.svg" -define icon:auto-resize=16,32,48,64,128,256 "./icon.ico"
+
+# Build Squirrel splash image
+magick "./png/256x256.png" -background "#ffffff" -gravity center -extent 640x480 "./win/setup-banner.gif"
\ No newline at end of file
diff --git a/bin/deb-options.json b/bin/deb-options.json
deleted file mode 100644
index 86531cc48..000000000
--- a/bin/deb-options.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "src": "dist/trilium-linux-x64",
- "dest": "dist/",
- "compression": "xz",
- "name": "trilium",
- "productName": "Trilium Notes",
- "genericName": "Note taker",
- "description": "Trilium Notes is a hierarchical note taking application with focus on building large personal knowledge bases.",
- "sections": "misc",
- "maintainer": "zadam.apps@gmail.com",
- "homepage": "https://github.com/zadam/trilium",
- "bin": "trilium",
- "icon": "dist/trilium-linux-x64/icon.png",
- "categories": [ "Office" ]
-}
diff --git a/bin/electron-forge/desktop.ejs b/bin/electron-forge/desktop.ejs
new file mode 100644
index 000000000..f803f37b2
--- /dev/null
+++ b/bin/electron-forge/desktop.ejs
@@ -0,0 +1,12 @@
+[Desktop Entry]
+<% if (productName) { %>Name=<%= productName %>
+<% } %><% if (description) { %>Comment=<%= description %>
+<% } %><% if (genericName) { %>GenericName=<%= genericName %>
+<% } %><% if (name) { %>Exec=<%= name %> %U
+Icon=<%= name %>
+<% } %>Type=Application
+StartupNotify=true
+<% if (productName) { %>StartupWMClass=<%= productName %>
+<% } if (categories && categories.length) { %>Categories=<%= categories.join(';') %>;
+<% } %><% if (mimeType && mimeType.length) { %>MimeType=<%= mimeType.join(';') %>;
+<% } %>
\ No newline at end of file
diff --git a/bin/release.sh b/bin/release.sh
index 0d4ef905d..fea1e030f 100755
--- a/bin/release.sh
+++ b/bin/release.sh
@@ -47,35 +47,3 @@ echo "Tagging commit with $TAG"
git tag $TAG
git push origin $TAG
-
-bin/build.sh
-
-LINUX_X64_BUILD=trilium-linux-x64-$VERSION.tar.xz
-DEBIAN_X64_BUILD=trilium_${VERSION}_amd64.deb
-WINDOWS_X64_BUILD=trilium-windows-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
-
-echo "Creating release in GitHub"
-
-EXTRA=
-
-if [[ $TAG == *"beta"* ]]; then
- EXTRA=--prerelease
-fi
-
-if [ ! -z "$GITHUB_CLI_AUTH_TOKEN" ]; then
- echo "$GITHUB_CLI_AUTH_TOKEN" | gh auth login --with-token
-fi
-
-gh release create "$TAG" \
- --title "$TAG release" \
- --notes "" \
- $EXTRA \
- "dist/$DEBIAN_X64_BUILD" \
- "dist/$LINUX_X64_BUILD" \
- "dist/$WINDOWS_X64_BUILD" \
- "dist/$MAC_X64_BUILD" \
- "dist/$MAC_ARM64_BUILD" \
- "dist/$SERVER_BUILD"
diff --git a/bin/translation.sh b/bin/translation.sh
new file mode 100755
index 000000000..7e1d9412d
--- /dev/null
+++ b/bin/translation.sh
@@ -0,0 +1,98 @@
+#!/usr/bin/env bash
+
+# --------------------------------------------------------------------------------------------------
+#
+# Create PO files to make easier the labor of translation.
+#
+# Info:
+# https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html
+# https://docs.translatehouse.org/projects/translate-toolkit/en/latest/commands/json2po.html
+#
+# Dependencies:
+# jq
+# translate-toolkit
+# python-wcwidth
+#
+# Created by @hasecilu
+#
+# --------------------------------------------------------------------------------------------------
+
+stats() {
+ # Print the number of existing strings on the JSON files for each locale
+ s=$(jq 'path(..) | select(length == 2) | .[1]' "${paths[0]}/en/server.json" | wc -l)
+ c=$(jq 'path(..) | select(length == 2) | .[1]' "${paths[1]}/en/translation.json" | wc -l)
+ echo "|locale |server strings |client strings |"
+ echo "|-------|---------------|---------------|"
+ echo "| en | ${s} | ${c} |"
+ for locale in "${locales[@]}"; do
+ s=$(jq 'path(..) | select(length == 2) | .[1]' "${paths[0]}/${locale}/server.json" | wc -l)
+ c=$(jq 'path(..) | select(length == 2) | .[1]' "${paths[1]}/${locale}/translation.json" | wc -l)
+ echo "| ${locale} | ${s} | ${c} |"
+ done
+}
+
+help() {
+ echo -e "\nDescription:"
+ echo -e "\tCreate PO files to make easier the labor of translation"
+ echo -e "\nUsage:"
+ echo -e "\t./translation.sh [--stats] [--update "+b(a)+"
"}return{empty:a.empty&&k.templatify(a.empty),header:a.header&&k.templatify(a.header),footer:a.footer&&k.templatify(a.footer),suggestion:a.suggestion||c}}function g(a){return/^[_a-zA-Z0-9-]+$/.test(a)}var h="aaDataset",i="aaValue",j="aaDatum",k=c(4),l=c(2),m=c(18),n=c(19),o=c(8);d.extractDatasetName=function(a){return l.element(a).data(h)},d.extractValue=function(a){return l.element(a).data(i)},d.extractDatum=function(a){var b=l.element(a).data(j);return"string"==typeof b&&(b=JSON.parse(b)),b},k.mixin(d.prototype,o,{_render:function(a,b){function c(){var b=[].slice.call(arguments,0);return b=[{query:a,isEmpty:!0}].concat(b),n.templates.empty.apply(this,b)}function d(){function a(a){var b,c=m.suggestion.replace("%PREFIX%",f.cssClasses.prefix).replace("%SUGGESTION%",f.cssClasses.suggestion);return b=l.element(c).attr({role:"option",id:["option",Math.floor(1e8*Math.random())].join("-")}).append(n.templates.suggestion.apply(this,[a].concat(e))),b.data(h,n.name),b.data(i,n.displayFn(a)||void 0),b.data(j,JSON.stringify(a)),b.children().each(function(){l.element(this).css(f.css.suggestionChild)}),b}var c,d,e=[].slice.call(arguments,0),f=this,g=m.suggestions.replace("%PREFIX%",this.cssClasses.prefix).replace("%SUGGESTIONS%",this.cssClasses.suggestions);return c=l.element(g).css(this.css.suggestions),d=k.map(b,a),c.append.apply(c,d),c}function e(){var b=[].slice.call(arguments,0);return b=[{query:a,isEmpty:!g}].concat(b),n.templates.header.apply(this,b)}function f(){var b=[].slice.call(arguments,0);return b=[{query:a,isEmpty:!g}].concat(b),n.templates.footer.apply(this,b)}if(this.$el){var g,n=this,o=[].slice.call(arguments,2);if(this.$el.empty(),g=b&&b.length,this._isEmpty=!g,!g&&this.templates.empty)this.$el.html(c.apply(this,o)).prepend(n.templates.header?e.apply(this,o):null).append(n.templates.footer?f.apply(this,o):null);else if(g)this.$el.html(d.apply(this,o)).prepend(n.templates.header?e.apply(this,o):null).append(n.templates.footer?f.apply(this,o):null);else if(b&&!Array.isArray(b))throw new TypeError("suggestions must be an array");this.$menu&&this.$menu.addClass(this.cssClasses.prefix+(g?"with":"without")+"-"+this.name).removeClass(this.cssClasses.prefix+(g?"without":"with")+"-"+this.name),this.trigger("rendered",a)}},getRoot:function(){return this.$el},update:function(a){function b(b){if(!this.canceled&&a===this.query){ - var c=[].slice.call(arguments,1);this.cacheSuggestions(a,b,c),this._render.apply(this,[a,b].concat(c))}}if(this.query=a,this.canceled=!1,this.shouldFetchFromCache(a))b.apply(this,[this.cachedSuggestions].concat(this.cachedRenderExtraArgs));else{var c=this,d=function(){c.canceled||c.source(a,b.bind(c))};if(this.debounce){var e=function(){c.debounceTimeout=null,d()};clearTimeout(this.debounceTimeout),this.debounceTimeout=setTimeout(e,this.debounce)}else d()}},cacheSuggestions:function(a,b,c){this.cachedQuery=a,this.cachedSuggestions=b,this.cachedRenderExtraArgs=c},shouldFetchFromCache:function(a){return this.cache&&this.cachedQuery===a&&this.cachedSuggestions&&this.cachedSuggestions.length},clearCachedSuggestions:function(){delete this.cachedQuery,delete this.cachedSuggestions,delete this.cachedRenderExtraArgs},cancel:function(){this.canceled=!0},clear:function(){this.$el&&(this.cancel(),this.$el.empty(),this.trigger("rendered",""))},isEmpty:function(){return this._isEmpty},destroy:function(){this.clearCachedSuggestions(),this.$el=null}}),a.exports=d},function(a,b){"use strict";a.exports={wrapper:'',dropdown:'',dataset:'',suggestions:'',suggestion:''}},function(a,b,c){"use strict";var d=c(4),e={wrapper:{position:"relative",display:"inline-block"},hint:{position:"absolute",top:"0",left:"0",borderColor:"transparent",boxShadow:"none",opacity:"1"},input:{position:"relative",verticalAlign:"top",backgroundColor:"transparent"},inputWithNoHint:{position:"relative",verticalAlign:"top"},dropdown:{position:"absolute",top:"100%",left:"0",zIndex:"100",display:"none"},suggestions:{display:"block"},suggestion:{whiteSpace:"nowrap",cursor:"pointer"},suggestionChild:{whiteSpace:"normal"},ltr:{left:"0",right:"auto"},rtl:{left:"auto",right:"0"},defaultClasses:{root:"algolia-autocomplete",prefix:"aa",noPrefix:!1,dropdownMenu:"dropdown-menu",input:"input",hint:"hint",suggestions:"suggestions",suggestion:"suggestion",cursor:"cursor",dataset:"dataset",empty:"empty"},appendTo:{wrapper:{position:"absolute",zIndex:"100",display:"none"},input:{},inputWithNoHint:{},dropdown:{display:"block"}}};d.isMsie()&&d.mixin(e.input,{backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"}),d.isMsie()&&d.isMsie()<=7&&d.mixin(e.input,{marginTop:"-1px"}),a.exports=e},function(a,b,c){"use strict";a.exports={hits:c(21),popularIn:c(24)}},function(a,b,c){"use strict";var d=c(4),e=c(22),f=c(23),g=function(){function a(a,d){return window.Promise.resolve().then(function(){return b.length&&(e=a.search(b),b=[]),e}).then(function(a){if(a)return c=a.results,c[d]})}var b=[],c=[],e=window.Promise.resolve();return function(c,e){return function(f,g){a(c.as,b.push({indexName:c.indexName,query:f,params:e})-1).then(function(a){a&&g(a.hits,a)}).catch(function(a){d.error(a.message)})}}}();a.exports=function(a,b){var c=f(a.as._ua);if(c&&c[0]>=3&&c[1]>20){var d="autocomplete.js "+e;a.as._ua.indexOf(d)===-1&&(a.as._ua+="; "+d)}return g(a,b)}},function(a,b){a.exports="0.38.1"},function(a,b){"use strict";a.exports=function(a){var b=a.match(/Algolia for JavaScript \((\d+\.)(\d+\.)(\d+)\)/)||a.match(/Algolia for vanilla JavaScript (\d+\.)(\d+\.)(\d+)/);if(b)return[b[1],b[2],b[3]]}},function(a,b,c){"use strict";var d=c(4),e=c(22),f=c(23);a.exports=function(a,b,c,g){function h(h,i){a.search(h,b,function(a,h){if(a)return void d.error(a.message);if(h.hits.length>0){var l=h.hits[0],m=d.mixin({hitsPerPage:0},c);delete m.source,delete m.index;var n=f(k.as._ua);return n&&n[0]>=3&&n[1]>20&&(b.additionalUA="autocomplete.js "+e),void k.search(j(l),m,function(a,b){if(a)return void d.error(a.message);var c=[];if(g.includeAll){var e=g.allTitle||"All departments";c.push(d.mixin({facet:{value:e,count:b.nbHits}},d.cloneDeep(l)))}d.each(b.facets,function(a,b){d.each(a,function(a,e){c.push(d.mixin({facet:{facet:b,value:e,count:a}},d.cloneDeep(l)))})});for(var f=1;f`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Remove the bottom border in Firefox 39-.\n// 5. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-original-title] { // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 4\n text-decoration-skip-ink: none; // 5\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n\nsmall {\n @include font-size(80%); // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n @include font-size(75%);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n\n @include hover() {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n color: inherit;\n text-decoration: none;\n\n @include hover() {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n // Disable auto-hiding scrollbar in IE & legacy Edge to avoid overlap,\n // making it impossible to interact with the content\n -ms-overflow-style: scrollbar;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\n// 1. Removes font-weight bold by inheriting\n// 2. Matches default `