mirror of
https://github.com/zadam/trilium.git
synced 2026-01-14 03:12:15 +01:00
Compare commits
56 Commits
standalone
...
renovate/n
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c4fb6c0d0 | ||
|
|
ed1bf17add | ||
|
|
4800f2a172 | ||
|
|
e7ff364c01 | ||
|
|
79ca299726 | ||
|
|
9d7ba48a6a | ||
|
|
9329665919 | ||
|
|
f6821bce03 | ||
|
|
a7aedf93ab | ||
|
|
4ffcf01452 | ||
|
|
618459d353 | ||
|
|
6436c16449 | ||
|
|
1bec457004 | ||
|
|
3e541e37fe | ||
|
|
a41b78d36f | ||
|
|
79c50f3b4c | ||
|
|
0f54b01cdd | ||
|
|
41f2b03711 | ||
|
|
0be76f982c | ||
|
|
5deb277672 | ||
|
|
3d15c9e94c | ||
|
|
1363f94621 | ||
|
|
abdcd6cc0c | ||
|
|
dc8abed2f3 | ||
|
|
892c2cd838 | ||
|
|
2796b29138 | ||
|
|
05620a129f | ||
|
|
cb11955a44 | ||
|
|
c3623a15fb | ||
|
|
0273c64bbf | ||
|
|
5b37140ffa | ||
|
|
fb4d63b049 | ||
|
|
015e41e792 | ||
|
|
8e47f33329 | ||
|
|
ad4a8ec5f4 | ||
|
|
56356f9c61 | ||
|
|
abda0f9111 | ||
|
|
c2a9d21198 | ||
|
|
59ffa1fa93 | ||
|
|
d056185368 | ||
|
|
251c1f6471 | ||
|
|
9efca9827e | ||
|
|
f5e2129ad4 | ||
|
|
6c8e6f2429 | ||
|
|
9b4b1a393e | ||
|
|
028334407c | ||
|
|
b93540b40d | ||
|
|
9e7eba5eab | ||
|
|
a5e8c8f573 | ||
|
|
644cc27fa7 | ||
|
|
72d9e846b7 | ||
|
|
6595fd9c10 | ||
|
|
2dd541e1d0 | ||
|
|
8157ef5e74 | ||
|
|
0185dd0d18 | ||
|
|
142ed42d90 |
30
.github/workflows/i18n.yml
vendored
Normal file
30
.github/workflows/i18n.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Internationalization
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "weblate:*"
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
paths:
|
||||
- "apps/client/src/translations/**"
|
||||
- ".github/workflows/i18n.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
i18n-check:
|
||||
name: Check i18n translations
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Set up node & dependencies
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'pnpm'
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Check translations
|
||||
run: pnpm tsx scripts/translation/check-translation-coverage.ts
|
||||
2
.github/workflows/website.yml
vendored
2
.github/workflows/website.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --filter website --frozen-lockfile
|
||||
run: pnpm install --filter website --frozen-lockfile --ignore-scripts
|
||||
|
||||
- name: Build the website
|
||||
run: pnpm website:build
|
||||
|
||||
11
README.md
11
README.md
@@ -165,6 +165,17 @@ pnpm install
|
||||
pnpm edit-docs:edit-docs
|
||||
```
|
||||
|
||||
Alternatively, if you have Nix installed:
|
||||
```shell
|
||||
# Run directly
|
||||
nix run .#edit-docs
|
||||
|
||||
# Or install to your profile
|
||||
nix profile install .#edit-docs
|
||||
trilium-edit-docs
|
||||
```
|
||||
|
||||
|
||||
### Building the Executable
|
||||
Download the repository, install dependencies using `pnpm` and then build the desktop app for Windows:
|
||||
```shell
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"license": "AGPL-3.0-only",
|
||||
"packageManager": "pnpm@10.28.0",
|
||||
"devDependencies": {
|
||||
"@redocly/cli": "2.14.4",
|
||||
"@redocly/cli": "2.14.5",
|
||||
"archiver": "7.0.1",
|
||||
"fs-extra": "11.3.3",
|
||||
"react": "19.2.3",
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"draggabilly": "3.0.0",
|
||||
"force-graph": "1.51.0",
|
||||
"globals": "17.0.0",
|
||||
"i18next": "25.7.3",
|
||||
"i18next": "25.7.4",
|
||||
"i18next-http-backend": "3.0.2",
|
||||
"jquery": "3.7.1",
|
||||
"jquery.fancytree": "2.38.5",
|
||||
@@ -60,7 +60,7 @@
|
||||
"normalize.css": "8.0.1",
|
||||
"panzoom": "9.4.3",
|
||||
"preact": "10.28.2",
|
||||
"react-i18next": "16.5.1",
|
||||
"react-i18next": "16.5.2",
|
||||
"react-window": "2.2.5",
|
||||
"reveal.js": "5.2.1",
|
||||
"svg-pan-zoom": "3.6.2",
|
||||
@@ -78,7 +78,7 @@
|
||||
"@types/reveal.js": "5.2.2",
|
||||
"@types/tabulator-tables": "6.3.1",
|
||||
"copy-webpack-plugin": "13.0.1",
|
||||
"happy-dom": "20.0.11",
|
||||
"happy-dom": "20.1.0",
|
||||
"lightningcss": "1.30.2",
|
||||
"script-loader": "0.7.2",
|
||||
"vite-plugin-static-copy": "3.1.4"
|
||||
|
||||
@@ -100,6 +100,20 @@ describe("shortcuts", () => {
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("should match letter keys using code when key is a special character (macOS Alt behavior)", () => {
|
||||
// On macOS, pressing Option/Alt + A produces 'å' as the key, but code is still 'KeyA'
|
||||
const macOSAltAEvent = createKeyboardEvent("å", "KeyA");
|
||||
expect(keyMatches(macOSAltAEvent, "a")).toBe(true);
|
||||
|
||||
// Option + H produces '˙'
|
||||
const macOSAltHEvent = createKeyboardEvent("˙", "KeyH");
|
||||
expect(keyMatches(macOSAltHEvent, "h")).toBe(true);
|
||||
|
||||
// Option + S produces 'ß'
|
||||
const macOSAltSEvent = createKeyboardEvent("ß", "KeyS");
|
||||
expect(keyMatches(macOSAltSEvent, "s")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("matchesShortcut", () => {
|
||||
@@ -200,6 +214,33 @@ describe("shortcuts", () => {
|
||||
expect(consoleSpy).toHaveBeenCalled();
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("should match Alt+letter shortcuts on macOS where key is a special character", () => {
|
||||
// On macOS, pressing Option/Alt + A produces 'å' but code remains 'KeyA'
|
||||
const macOSAltAEvent = createKeyboardEvent({
|
||||
key: "å",
|
||||
code: "KeyA",
|
||||
altKey: true
|
||||
});
|
||||
expect(matchesShortcut(macOSAltAEvent, "alt+a")).toBe(true);
|
||||
|
||||
// Option/Alt + H produces '˙'
|
||||
const macOSAltHEvent = createKeyboardEvent({
|
||||
key: "˙",
|
||||
code: "KeyH",
|
||||
altKey: true
|
||||
});
|
||||
expect(matchesShortcut(macOSAltHEvent, "alt+h")).toBe(true);
|
||||
|
||||
// Combined with Ctrl: Ctrl+Alt+S where Alt produces 'ß'
|
||||
const macOSCtrlAltSEvent = createKeyboardEvent({
|
||||
key: "ß",
|
||||
code: "KeyS",
|
||||
ctrlKey: true,
|
||||
altKey: true
|
||||
});
|
||||
expect(matchesShortcut(macOSCtrlAltSEvent, "ctrl+alt+s")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("bindGlobalShortcut", () => {
|
||||
|
||||
@@ -213,8 +213,11 @@ export function keyMatches(e: KeyboardEvent, key: string): boolean {
|
||||
}
|
||||
|
||||
// For letter keys, use the physical key code for consistency
|
||||
// On macOS, Option/Alt key produces special characters, so we must use e.code
|
||||
if (key.length === 1 && key >= 'a' && key <= 'z') {
|
||||
return e.key.toLowerCase() === key.toLowerCase();
|
||||
// e.code is like "KeyA", "KeyB", etc.
|
||||
const expectedCode = `Key${key.toUpperCase()}`;
|
||||
return e.code === expectedCode || e.key.toLowerCase() === key.toLowerCase();
|
||||
}
|
||||
|
||||
// For regular keys, check both key and code as fallback
|
||||
|
||||
@@ -1604,7 +1604,9 @@
|
||||
"clone-indicator-tooltip": "此笔记有 {{- count}} 个父级: {{- parents}}",
|
||||
"clone-indicator-tooltip-single": "此笔记已克隆(1 个额外的父级:{{- parent}})",
|
||||
"subtree-hidden-tooltip_other": "从树中隐藏的 {{count}} 篇子笔记",
|
||||
"subtree-hidden-moved-title": "已添加到 {{title}}"
|
||||
"subtree-hidden-moved-title": "已添加到 {{title}}",
|
||||
"subtree-hidden-moved-description-collection": "此集合隐藏其树中的子笔记。",
|
||||
"subtree-hidden-moved-description-other": "子笔记隐藏于此笔记的树中。"
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "保持此窗口置顶"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"about": {
|
||||
"title": "Über Trilium Notes",
|
||||
"title": "Über Trilium Notizen",
|
||||
"homepage": "Startseite:",
|
||||
"app_version": "App-Version:",
|
||||
"db_version": "DB-Version:",
|
||||
@@ -26,7 +26,12 @@
|
||||
"widget-list-error": {
|
||||
"title": "Abruf der Liste von Widgets vom Server ist fehlgeschlagen"
|
||||
},
|
||||
"open-script-note": "Script-Notiz öffnen"
|
||||
"open-script-note": "Script-Notiz öffnen",
|
||||
"widget-render-error": {
|
||||
"title": "Eine externe React Integration konnte nicht dargestellt werden"
|
||||
},
|
||||
"widget-missing-parent": "Der externen Integration fehlt die erforderliche Eigenschaft '{{property}}'\n\nFalls dieses Skript ohne UI-Element ausgeführt werden soll, benutze stattdessen '#run=frontendStartup'.",
|
||||
"scripting-error": "Benutzerdefinierter Skriptfehler: {{title}}"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Link hinzufügen",
|
||||
@@ -210,7 +215,7 @@
|
||||
"modalTitle": "Infonachricht",
|
||||
"closeButton": "Schließen",
|
||||
"okButton": "OK",
|
||||
"copy_to_clipboard": "In die Zwischenablage kopieren"
|
||||
"copy_to_clipboard": "In Zwischenablage kopieren"
|
||||
},
|
||||
"jump_to_note": {
|
||||
"search_button": "Suche im Volltext",
|
||||
@@ -698,8 +703,8 @@
|
||||
"export_as_image_png": "PNG (Raster)",
|
||||
"export_as_image_svg": "SVG (Vektor)",
|
||||
"note_map": "Notizen Karte",
|
||||
"view_revisions": "Notizrevisionen",
|
||||
"advanced": "Erweitert"
|
||||
"view_revisions": "Änderungshistorie...",
|
||||
"advanced": "Fortgeschritten"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "Das Schaltflächen-Widget „{{componentId}}“ hat keinen definierten Klick-Handler"
|
||||
@@ -792,7 +797,8 @@
|
||||
"expand_all_levels": "Alle Ebenen erweitern",
|
||||
"expand_tooltip": "Erweitert die direkten Unterelemente dieser Sammlung (eine Ebene tiefer). Für weitere Optionen auf den Pfeil rechts klicken.",
|
||||
"expand_first_level": "Direkte Unterelemente erweitern",
|
||||
"expand_nth_level": "{{depth}} Ebenen erweitern"
|
||||
"expand_nth_level": "{{depth}} Ebenen erweitern",
|
||||
"hide_child_notes": "Unterknoten im Baum ausblenden"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "An diesem Tag wurden noch keine Notizen bearbeitet...",
|
||||
@@ -805,7 +811,7 @@
|
||||
"file_type": "Dateityp",
|
||||
"file_size": "Dateigröße",
|
||||
"download": "Herunterladen",
|
||||
"open": "Offen",
|
||||
"open": "Extern öffnen",
|
||||
"upload_new_revision": "Neue Revision hochladen",
|
||||
"upload_success": "Neue Dateirevision wurde hochgeladen.",
|
||||
"upload_failed": "Das Hochladen einer neuen Dateirevision ist fehlgeschlagen.",
|
||||
@@ -903,7 +909,7 @@
|
||||
"unknown_search_option": "Unbekannte Suchoption {{searchOptionName}}",
|
||||
"search_note_saved": "Suchnotiz wurde in {{-notePathTitle}} gespeichert",
|
||||
"actions_executed": "Aktionen wurden ausgeführt.",
|
||||
"view_options": "Anzeigeoptionen:"
|
||||
"view_options": "Optionen anzeigen:"
|
||||
},
|
||||
"similar_notes": {
|
||||
"title": "Ähnliche Notizen",
|
||||
@@ -1009,9 +1015,9 @@
|
||||
"auto-detect-language": "Automatisch erkannt",
|
||||
"keeps-crashing": "Die Bearbeitungskomponente stürzt immer wieder ab. Bitte starten Sie Trilium neu. Wenn das Problem weiterhin besteht, erstellen Sie einen Fehlerbericht.",
|
||||
"editor_crashed_title": "Der Text Editor ist abgestürzt",
|
||||
"editor_crashed_content": "Ihr Inhalt wurde erfolgreich wiederhergestellt, aber einzelne Ihrer letzten Änderungen waren möglicherweise noch nicht gespeichert.",
|
||||
"editor_crashed_details_button": "Zeige mehr Details…",
|
||||
"editor_crashed_details_intro": "Falls Sie diesen Fehler mehrmals sehen, melden Sie dies auf GitHub mit den folgenden Informationen.",
|
||||
"editor_crashed_content": "Ihr Inhalt wurde erfolgreich wiederhergestellt, aber kürzlich gemachte Änderungen wurden unter Umständen nicht gespeichert.",
|
||||
"editor_crashed_details_button": "Mehr Details anzeigen...",
|
||||
"editor_crashed_details_intro": "Falls dieser Fehler häufiger auftritt, ziehen Sie in Betracht uns diesen über GitHub zu melden, indem Sie die folgenden Informationen bereitstellen.",
|
||||
"editor_crashed_details_title": "Technische Informationen"
|
||||
},
|
||||
"empty": {
|
||||
@@ -1412,7 +1418,7 @@
|
||||
"will_be_deleted_in": "Dieser Anhang wird in {{time}} automatisch gelöscht",
|
||||
"will_be_deleted_soon": "Dieser Anhang wird bald automatisch gelöscht",
|
||||
"deletion_reason": ", da der Anhang nicht im Inhalt der Notiz verlinkt ist. Um das Löschen zu verhindern, füge den Anhangslink wieder in den Inhalt ein oder wandel den Anhang in eine Notiz um.",
|
||||
"role_and_size": "Rolle: {{role}}, Größe: {{size}}",
|
||||
"role_and_size": "Rolle: {{role}}, Größe: {{size}}, MIME: {{- mimeType}}",
|
||||
"link_copied": "Anhangslink in die Zwischenablage kopiert.",
|
||||
"unrecognized_role": "Unbekannte Anhangsrolle „{{role}}“."
|
||||
},
|
||||
@@ -1463,10 +1469,13 @@
|
||||
"import-into-note": "In Notiz importieren",
|
||||
"apply-bulk-actions": "Massenaktionen anwenden",
|
||||
"converted-to-attachments": "{{count}} Notizen wurden als Anhang konvertiert.",
|
||||
"convert-to-attachment-confirm": "Bist du sicher, dass du die ausgewählten Notizen in Anhänge ihrer übergeordneten Notizen umwandeln möchtest?",
|
||||
"convert-to-attachment-confirm": "Bist du sicher, dass du die ausgewählten Notizen in Anhänge ihrer übergeordneten Notizen umwandeln möchtest? Diese Operation wird nur auf Bildnotizes angewandt. Andere Notizen werden übersprungen.",
|
||||
"open-in-popup": "Schnellbearbeitung",
|
||||
"archive": "Archiviere",
|
||||
"unarchive": "Entarchivieren"
|
||||
"unarchive": "Entarchivieren",
|
||||
"open-in-a-new-window": "In neuem Fenster öffnen",
|
||||
"hide-subtree": "Teilbaum ausblenden",
|
||||
"show-subtree": "Teilbaum anzeigen"
|
||||
},
|
||||
"shared_info": {
|
||||
"shared_publicly": "Diese Notiz ist öffentlich geteilt auf {{- link}}.",
|
||||
@@ -1556,7 +1565,16 @@
|
||||
"create-child-note": "Unternotiz anlegen",
|
||||
"unhoist": "Fokus verlassen",
|
||||
"toggle-sidebar": "Seitenleiste ein-/ausblenden",
|
||||
"dropping-not-allowed": "Ablegen von Notizen an dieser Stelle ist nicht zulässig."
|
||||
"dropping-not-allowed": "Ablegen von Notizen an dieser Stelle ist nicht zulässig.",
|
||||
"clone-indicator-tooltip": "Diese Notiz hat {{- count}} Elterknoten: {{- parents}}",
|
||||
"clone-indicator-tooltip-single": "Diese Notiz ist geklont (1 weiterer Elternknoten: {{- parent}})",
|
||||
"shared-indicator-tooltip": "Diese Notiz ist öffentlich einsehbar",
|
||||
"shared-indicator-tooltip-with-url": "Diese Notiz ist unter {{- url}} öffentlich einsehbar",
|
||||
"subtree-hidden-tooltip_one": "{{count}} Unterknoten, der im Baum ausgeblendet ist",
|
||||
"subtree-hidden-tooltip_other": "{{count}} Unterknoten, die im Baum ausgeblendet sind",
|
||||
"subtree-hidden-moved-title": "Zu {{title}} hinzugefügt",
|
||||
"subtree-hidden-moved-description-collection": "Diese Sammlung blendet ihre Unternotizem im Baum aus.",
|
||||
"subtree-hidden-moved-description-other": "Diese Sammlung blendet ihre Unterknoten im Baum aus."
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "Dieses Fenster immer oben halten"
|
||||
@@ -1567,7 +1585,9 @@
|
||||
"printing_pdf": "PDF-Export läuft…",
|
||||
"print_report_title": "Druckreport",
|
||||
"print_report_collection_details_button": "Details anzeigen",
|
||||
"print_report_collection_details_ignored_notes": "Ignorierte Notizen"
|
||||
"print_report_collection_details_ignored_notes": "Ignorierte Notizen",
|
||||
"print_report_collection_content_one": "{{count}} Notiz in der Sammlung konnte nicht gedruckt werden, weil sie nicht unterstützt ist oder geschützt ist.",
|
||||
"print_report_collection_content_other": "{{count}} Notizen in der Sammlung konnten nicht gedruckt werden, weil sie nicht unterstützt sind oder geschützt sind."
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "Titel der Notiz hier eingeben…",
|
||||
@@ -1720,7 +1740,8 @@
|
||||
"open_note_in_new_tab": "Notiz in neuen Tab öffnen",
|
||||
"open_note_in_new_split": "Notiz in neuen geteilten Tab öffnen",
|
||||
"open_note_in_new_window": "Notiz in neuen Fenster öffnen",
|
||||
"open_note_in_popup": "Schnellbearbeitung"
|
||||
"open_note_in_popup": "Schnellbearbeitung",
|
||||
"open_note_in_other_split": "Notiz in neuer Spalte öffnen"
|
||||
},
|
||||
"electron_integration": {
|
||||
"desktop-application": "Desktop Anwendung",
|
||||
@@ -1988,8 +2009,9 @@
|
||||
"unknown_widget": "Unbekanntes Widget für '{{id}}'."
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "Nicht gesetzt",
|
||||
"configure-languages": "Konfiguriere Sprachen..."
|
||||
"not_set": "Keine Sprache ausgewählt",
|
||||
"configure-languages": "Konfiguriere Sprachen...",
|
||||
"help-on-languages": "Zu Übersetzungen beitragen..."
|
||||
},
|
||||
"content_language": {
|
||||
"title": "Inhaltssprachen",
|
||||
@@ -2007,7 +2029,8 @@
|
||||
"button_title": "Exportiere Diagramm als PNG"
|
||||
},
|
||||
"svg": {
|
||||
"export_to_png": "Das Diagramm konnte als PNG nicht exportiert werden."
|
||||
"export_to_png": "Das Diagramm konnte als PNG nicht exportiert werden.",
|
||||
"export_to_svg": "Das Diagramm konnte nicht als SVG exportiert werden."
|
||||
},
|
||||
"code_theme": {
|
||||
"title": "Aussehen",
|
||||
@@ -2055,7 +2078,7 @@
|
||||
"book_properties_config": {
|
||||
"hide-weekends": "Wochenenden ausblenden",
|
||||
"display-week-numbers": "Zeige Kalenderwoche",
|
||||
"map-style": "Kartenstil:",
|
||||
"map-style": "Kartenstil",
|
||||
"max-nesting-depth": "Maximale Verschachtelungstiefe:",
|
||||
"raster": "Raster",
|
||||
"vector_light": "Vektor (Hell)",
|
||||
@@ -2108,14 +2131,20 @@
|
||||
"background_effects_title": "Hintergrundeffekte sind jetzt zuverlässig nutzbar",
|
||||
"background_effects_message": "Auf Windows-Geräten sind die Hintergrundeffekte nun vollständig stabil. Die Hintergrundeffekte verleihen der Benutzeroberfläche einen Farbakzent, indem der Hintergrund dahinter weichgezeichnet wird. Diese Technik wird auch in anderen Anwendungen wie dem Windows-Explorer eingesetzt.",
|
||||
"background_effects_button": "Aktiviere Hintergrundeffekte",
|
||||
"dismiss": "Ablehnen"
|
||||
"dismiss": "Ablehnen",
|
||||
"new_layout_title": "Neues Layout",
|
||||
"new_layout_message": "Wir haben ein modernisiertes Layout für Trilium eingeführt. Die Multifunktionsleiste wurde entfernt und als neue Statusanzeige und ausklappbaren Sektionen (wie hervorgehobenen Attributen), welche Schlüsselfunktionen übernehmen, nahtlos in das Hauptinterface integriert.\n\nDas neue Layout ist standardmäßig aktiviert und kann temporär in Optionen → Anzeige deaktiviert werden.",
|
||||
"new_layout_button": "Mehr Informationen"
|
||||
},
|
||||
"settings": {
|
||||
"related_settings": "Ähnliche Einstellungen"
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "Farbschema für Code-Blöcke in Textnotizen",
|
||||
"related_code_notes": "Farbschema für Code-Notizen"
|
||||
"related_code_notes": "Farbschema für Code-Notizen",
|
||||
"ui": "Benutzeroberfläche",
|
||||
"ui_old_layout": "Altes Layout",
|
||||
"ui_new_layout": "Neues Layout"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
@@ -2151,6 +2180,88 @@
|
||||
"experimental_features": {
|
||||
"title": "Experimentelle Optionen",
|
||||
"disclaimer": "Diese Optionen sind experimentell und können Instabilitäten verursachen. Achtsam zu verwenden.",
|
||||
"new_layout_name": "Neues Layout"
|
||||
"new_layout_name": "Neues Layout",
|
||||
"new_layout_description": "Probiere das neue Layout für eine modernere Darstellung und verbesserte Benutzbarkeit aus. Kann sich in Zukunft stark ändern."
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "Bei der Kommunikation mit dem Server ist ein Fehler aufgetreten",
|
||||
"unknown_http_error_content": "Statuscode: {{statusCode}}\nURL: {{method}} {{url}}\nNachricht: {{message}}",
|
||||
"traefik_blocks_requests": "Der Traefik Reverse-Proxy hat ein fatales Update bekommen, welche die Kommunikation mit dem Server stört."
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "Zur vorherigen Notiz zurück kehren",
|
||||
"go-forward": "Zur nächsten Notiz"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"hoisted_badge": "Gehoben",
|
||||
"hoisted_badge_title": "Abgesenkt",
|
||||
"workspace_badge": "Arbeitsfläche",
|
||||
"scroll_to_top_title": "Zum Anfang der Notiz springen",
|
||||
"create_new_note": "Neue Unternotiz erstellen",
|
||||
"empty_hide_archived_notes": "Archivierte Notizen ausblenden"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "Nicht Änderbar",
|
||||
"read_only_explicit_description": "Diese Notiz wurde händisch als nicht änderbar markiert.\nKlicke hier um sie temporär zu bearbeiten.",
|
||||
"read_only_auto": "Automatisch nicht änderbar",
|
||||
"read_only_auto_description": "Diese Notiz wurde automatisch aus Leistungsgründen als nicht änderbar markiert. Dieses automatische Limit kann in den Einstellungen angepasst werden.\n\nKlicke hier, um sie temporär zu bearbeiten.",
|
||||
"read_only_temporarily_disabled": "Temporär bearbeitbar",
|
||||
"read_only_temporarily_disabled_description": "Diese Notiz ist aktuell bearbeitbar, ist aber normalerweise nicht änderbar. Sobald du zu einer anderen Notiz navigierst, kehrt diese Notiz in ihren Normalzustand zurück.\n\nKlicke hier, um die Notiz wieder nicht änderbar zu machen.",
|
||||
"shared_publicly": "Öffentlich geteilt",
|
||||
"shared_locally": "Lokal geteilt",
|
||||
"shared_copy_to_clipboard": "Link in die Zwischenablage kopieren",
|
||||
"shared_open_in_browser": "Link öffnen",
|
||||
"shared_unshare": "Teilen aufheben",
|
||||
"clipped_note": "Internetschnellverweis",
|
||||
"clipped_note_description": "Diese Notiz wurde von {{url}} übernommen.\n\nKlicke hier, um zum Ursprung zu gehen.",
|
||||
"execute_script": "Skript ausführen",
|
||||
"execute_script_description": "Diese Notiz ist eine Skriptnotiz. Klicke hier, um das Skript auszuführen.",
|
||||
"execute_sql": "SQL ausführen",
|
||||
"execute_sql_description": "Diese Notiz ist eine SQL-Notiz. Klicke hier, um die SQL-Abfrage auszuführen.",
|
||||
"save_status_saved": "Gespeichert",
|
||||
"save_status_saving": "Speichern...",
|
||||
"save_status_unsaved": "Nicht gespeichert",
|
||||
"save_status_error": "Speichern fehlgeschlagen",
|
||||
"save_status_saving_tooltip": "Änderungen werden gespeichert.",
|
||||
"save_status_unsaved_tooltip": "Es gibt ungespeicherte Änderungen, welche gleich automatisch gespeichert werden.",
|
||||
"save_status_error_tooltip": "Beim speichern der Notiz ist ein Fehler aufgetreten. Wenn möglich, versuche die Notiz woandershin zu kopieren und die Applikation neu zu laden."
|
||||
},
|
||||
"status_bar": {
|
||||
"language_title": "Inhaltssprache ändern",
|
||||
"note_info_title": "Notizinfo anzeigen (z.B.: Datum, Notizgröße)",
|
||||
"backlinks_one": "{{count}} Rücklink",
|
||||
"backlinks_other": "{{count}} Rücklinks",
|
||||
"backlinks_title_one": "Rücklink anzeigen",
|
||||
"backlinks_title_other": "Rücklinks anzeigen",
|
||||
"attachments_one": "{{count}} Anhang",
|
||||
"attachments_other": "{{count}} Anhänge",
|
||||
"attachments_title_one": "Anhang in einem neuen Tab öffnen",
|
||||
"attachments_title_other": "Anhänge in einem neuen Tab öffnen",
|
||||
"attributes_one": "{{count}} Eigenschaft",
|
||||
"attributes_other": "{{count}} Eigenschaften",
|
||||
"attributes_title": "Eigene und gererbte Eigenschaften",
|
||||
"note_paths_one": "{{count}} Pfad",
|
||||
"note_paths_other": "{{count}} Pfade",
|
||||
"note_paths_title": "Notizpfade",
|
||||
"code_note_switcher": "Sprachmodus ändern"
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "Notizeigenschaften"
|
||||
},
|
||||
"right_pane": {
|
||||
"empty_message": "Für diese Notiz gibt es nichts anzuzeigen",
|
||||
"empty_button": "Anzeige ausblenden",
|
||||
"toggle": "Rechte Anzeige umschalten",
|
||||
"custom_widget_go_to_source": "Zum Ursprungscode"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} Anhang",
|
||||
"attachments_other": "{{count}} Anhänge",
|
||||
"layers_one": "{{count}} Ebene",
|
||||
"layers_other": "{{count}} Ebenen",
|
||||
"pages_one": "{{count}} Seite",
|
||||
"pages_other": "{{count}} Seiten",
|
||||
"pages_alt": "Seite {{pageNumber}}",
|
||||
"pages_loading": "Laden..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,5 +69,8 @@
|
||||
"clear-color": "Clear note colour",
|
||||
"set-color": "Set note colour",
|
||||
"set-custom-color": "Set custom note colour"
|
||||
},
|
||||
"about": {
|
||||
"title": "About Trilium Notes"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,5 +60,23 @@
|
||||
},
|
||||
"include_note": {
|
||||
"label_note": "Notat"
|
||||
},
|
||||
"prompt": {
|
||||
"title": "Ledetekst",
|
||||
"ok": "OK",
|
||||
"defaultTitle": "Ledetekst"
|
||||
},
|
||||
"info": {
|
||||
"closeButton": "Lukk",
|
||||
"okButton": "OK"
|
||||
},
|
||||
"markdown_import": {
|
||||
"import_button": "Importer"
|
||||
},
|
||||
"protected_session_password": {
|
||||
"close_label": "Lukk"
|
||||
},
|
||||
"recent_changes": {
|
||||
"undelete_link": "gjenopprett"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -772,7 +772,10 @@
|
||||
"filter-default": "Icons default",
|
||||
"no_results": "Não foram encontrados icons.",
|
||||
"search_placeholder_filtered": "Procurar {{number}} icons no {{name}}",
|
||||
"icon_tooltip": "{{name}}\nPacote de icons: {{iconPack}}"
|
||||
"icon_tooltip": "{{name}}\nPacote de icons: {{iconPack}}",
|
||||
"search_placeholder_one": "Procurar {{number}} icon nos {{count}} pacotes",
|
||||
"search_placeholder_many": "Procurar {{number}} icons em {{count}} pacotes",
|
||||
"search_placeholder_other": "Procurar {{number}} icons nos {{count}} pacotes"
|
||||
},
|
||||
"basic_properties": {
|
||||
"note_type": "Tipo da nota",
|
||||
@@ -799,7 +802,8 @@
|
||||
"expand_nth_level": "Expandir {{depth}} níveis",
|
||||
"expand_all_levels": "Expandir todos os níveis",
|
||||
"include_archived_notes": "Mostrar notas arquivadas",
|
||||
"expand_tooltip": "Expande a direcção dos descendentes desta colecção (um nível). Para mais opções, carregar na seta à direita."
|
||||
"expand_tooltip": "Expande a direcção dos descendentes desta colecção (um nível). Para mais opções, carregar na seta à direita.",
|
||||
"hide_child_notes": "Esconder notas descendentes na árvore"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "Ainda não há nenhuma nota editada neste dia…",
|
||||
@@ -1017,7 +1021,9 @@
|
||||
"editor_crashed_title": "O editor de texto quebrou",
|
||||
"editor_crashed_details_button": "Ver mais detalhes...",
|
||||
"editor_crashed_details_title": "Informação técnica",
|
||||
"editor_crashed_details_intro": "Se teve este erro várias vezes, considerer reportar no GitHub disponibilizando a informação abaixo."
|
||||
"editor_crashed_details_intro": "Se teve este erro várias vezes, considerer reportar no GitHub disponibilizando a informação abaixo.",
|
||||
"editor_crashed_content": "O seu conteudo foi recuperado com sucesso, mas alguns das alterações mais recentes podem não ter sido gravadas.",
|
||||
"keeps-crashing": "Componente de edição a rebentar continuamente. Por favor tentar reiniciar Trilium. Se o problema persistir, considere abrir um bug report."
|
||||
},
|
||||
"empty": {
|
||||
"open_note_instruction": "Abra uma nota a digitar o título da nota no campo abaixo ou escolha uma nota na árvore.",
|
||||
@@ -1145,7 +1151,8 @@
|
||||
"title": "Largura do Conteúdo",
|
||||
"default_description": "Por padrão, o Trilium limita a largura máxima do conteúdo para melhorar a legibilidade em janelas maximizadas em ecrãs largos.",
|
||||
"max_width_label": "Largura máxima do conteúdo",
|
||||
"max_width_unit": "pixels"
|
||||
"max_width_unit": "pixels",
|
||||
"centerContent": "Manter conteúdo centrado"
|
||||
},
|
||||
"native_title_bar": {
|
||||
"title": "Barra de Título Nativa (requer recarregar a app)",
|
||||
@@ -1177,7 +1184,9 @@
|
||||
"title": "Desempenho",
|
||||
"enable-motion": "Ativar transições e animações",
|
||||
"enable-shadows": "Ativar sombras",
|
||||
"enable-backdrop-effects": "Ativar efeitos de fundo para menus, popups e painéis"
|
||||
"enable-backdrop-effects": "Ativar efeitos de fundo para menus, popups e painéis",
|
||||
"enable-smooth-scroll": "Activar deslocamento suave",
|
||||
"app-restart-required": "(é necessário reiniciar a aplicação para aplicar as alterações)"
|
||||
},
|
||||
"ai_llm": {
|
||||
"not_started": "Não iniciado",
|
||||
@@ -1336,7 +1345,10 @@
|
||||
"title": "Editor"
|
||||
},
|
||||
"code_mime_types": {
|
||||
"title": "Tipos MIME disponíveis no dropdown"
|
||||
"title": "Tipos MIME disponíveis no dropdown",
|
||||
"tooltip_syntax_highlighting": "Destaque de sintaxe",
|
||||
"tooltip_code_block_syntax": "Blocos de código nas notas de texto",
|
||||
"tooltip_code_note_syntax": "Notas de código"
|
||||
},
|
||||
"vim_key_bindings": {
|
||||
"use_vim_keybindings_in_code_notes": "Atribuições de teclas do Vim",
|
||||
@@ -1456,7 +1468,13 @@
|
||||
"min-days-in-first-week": "Mínimo de dias da primeira semana",
|
||||
"first-week-info": "Primeira semana que contenha a primeira Quinta-feira do ano é baseado na <a href=\"https://en.wikipedia.org/wiki/ISO_week_date#First_week\">ISO 8601</a>.",
|
||||
"first-week-warning": "Alterar as opções de primeira semana pode causar duplicidade nas Notas Semanais existentes e estas Notas não serão atualizadas de acordo.",
|
||||
"formatting-locale": "Formato de data e número"
|
||||
"formatting-locale": "Formato de data e número",
|
||||
"tuesday": "Terça-feira",
|
||||
"wednesday": "Quarta-feira",
|
||||
"thursday": "Quinta-feira",
|
||||
"friday": "Sexta-feira",
|
||||
"saturday": "Sábado",
|
||||
"formatting-locale-auto": "Baseado na linguagem da aplicação"
|
||||
},
|
||||
"backup": {
|
||||
"automatic_backup": "Backup automático",
|
||||
@@ -1549,7 +1567,8 @@
|
||||
"oauth_description_warning": "Para ativar o OAuth/OpenID, precisa definir a URL base do OAuth/OpenID, o client ID e o client secret no ficheiro config.ini e reiniciar a aplicação. Se quiser configurar via variáveis de ambiente, defina TRILIUM_OAUTH_BASE_URL, TRILIUM_OAUTH_CLIENT_ID e TRILIUM_OAUTH_CLIENT_SECRET.",
|
||||
"oauth_user_account": "Conta do Utilizador: ",
|
||||
"oauth_user_email": "E-mail do Utilizador: ",
|
||||
"oauth_user_not_logged_in": "Não está logado!"
|
||||
"oauth_user_not_logged_in": "Não está logado!",
|
||||
"oauth_missing_vars": "Configurações em falta: {{-variables}}"
|
||||
},
|
||||
"shortcuts": {
|
||||
"keyboard_shortcuts": "Atalhos de Teclado",
|
||||
@@ -1649,7 +1668,12 @@
|
||||
"apply-bulk-actions": "Aplicar ações em massa",
|
||||
"converted-to-attachments": "{{count}} notas foram convertidas em anexos.",
|
||||
"convert-to-attachment-confirm": "Tem certeza que deseja converter as notas selecionadas em anexos das suas notas-pai?",
|
||||
"open-in-popup": "Edição rápida"
|
||||
"open-in-popup": "Edição rápida",
|
||||
"open-in-a-new-window": "Abrir numa nova janela",
|
||||
"archive": "Arquivar",
|
||||
"unarchive": "Retirar do arquivo",
|
||||
"hide-subtree": "Esconder sub-árvore",
|
||||
"show-subtree": "Mostrar sub-árvore"
|
||||
},
|
||||
"shared_info": {
|
||||
"shared_publicly": "Esta nota é partilhada publicamente em {{- link}}.",
|
||||
@@ -1710,7 +1734,13 @@
|
||||
},
|
||||
"highlights_list_2": {
|
||||
"title": "Lista de Destaques",
|
||||
"options": "Opções"
|
||||
"options": "Opções",
|
||||
"no_highlights": "Sem destaques encontrados.",
|
||||
"menu_configure": "Configurar lista de destaques...",
|
||||
"modal_title": "Configurar list de destaques",
|
||||
"title_with_count_one": "{{count}} destaque",
|
||||
"title_with_count_many": "{{count}} destaques",
|
||||
"title_with_count_other": "{{count}} destaques"
|
||||
},
|
||||
"quick-search": {
|
||||
"placeholder": "Pesquisa rápida",
|
||||
@@ -1733,16 +1763,43 @@
|
||||
"refresh-saved-search-results": "Atualizar resultados de pesquisa gravados",
|
||||
"create-child-note": "Criar nota filha",
|
||||
"unhoist": "Desafixar",
|
||||
"toggle-sidebar": "Alternar barra lateral"
|
||||
"toggle-sidebar": "Alternar barra lateral",
|
||||
"dropping-not-allowed": "Largar notas nesta localização não é permitida",
|
||||
"clone-indicator-tooltip": "Esta nota tem {{- count}} ascendentes: {{- parents}}",
|
||||
"shared-indicator-tooltip": "Esta nota está partilhada publicamente",
|
||||
"shared-indicator-tooltip-with-url": "Esta nota está partilhada publicamente em: {{- url}}",
|
||||
"subtree-hidden-moved-title": "Adicionar ao {{title}}",
|
||||
"subtree-hidden-moved-description-collection": "Esta colecção esconde as notas descendentes na árvore.",
|
||||
"subtree-hidden-moved-description-other": "Notas descendentes estão escondidades na árvore para esta nota.",
|
||||
"subtree-hidden-tooltip_one": "{{count}} nota descendentes escondidas da árvore",
|
||||
"subtree-hidden-tooltip_many": "{{count}} notas descendentes escondidas da árvore",
|
||||
"subtree-hidden-tooltip_other": "{{count}} notas descendentes escondidas da árvore",
|
||||
"clone-indicator-tooltip-single": "Esta nota está clonada (1 additional parent: {{- parent}})"
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "Manter Janela no Topo"
|
||||
},
|
||||
"note_detail": {
|
||||
"could_not_find_typewidget": "Não foi possível encontrar typeWidget para o tipo '{{type}}'"
|
||||
"could_not_find_typewidget": "Não foi possível encontrar typeWidget para o tipo '{{type}}'",
|
||||
"print_report_collection_details_button": "Ver detalhes",
|
||||
"printing": "Impressão em progresso...",
|
||||
"printing_pdf": "Exportação PDF em progresso...",
|
||||
"print_report_title": "Imprimir relatório",
|
||||
"print_report_collection_details_ignored_notes": "Ignorar notas",
|
||||
"print_report_collection_content_one": "{{count}} nota na colecção não pode ser impressa porque não é suportado ou está protegida.",
|
||||
"print_report_collection_content_many": "{{count}} notas na colecção não podem ser impressas porque não é suportado ou estão protegidas.",
|
||||
"print_report_collection_content_other": "{{count}} notas na colecção não podem ser impressas porque não é suportado ou estão protegidas."
|
||||
},
|
||||
"note_title": {
|
||||
"placeholder": "digite o título da nota aqui..."
|
||||
"placeholder": "digite o título da nota aqui...",
|
||||
"promoted_attributes": "Atributos destacados",
|
||||
"created_on": "Criado em <Value />",
|
||||
"last_modified": "Modificado em <Value />",
|
||||
"note_type_switcher_label": "Alterar de {{type}} para:",
|
||||
"note_type_switcher_others": "Outro tipo de nota",
|
||||
"note_type_switcher_templates": "Template",
|
||||
"note_type_switcher_collection": "Colecção",
|
||||
"edited_notes": "Notas editadas neste dia"
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "Nenhuma nota encontrada para os parâmetros de pesquisa digitados.",
|
||||
@@ -1771,7 +1828,8 @@
|
||||
},
|
||||
"toc": {
|
||||
"table_of_contents": "Tabela de Conteúdos",
|
||||
"options": "Opções"
|
||||
"options": "Opções",
|
||||
"no_headings": "Sem cabeçalhos."
|
||||
},
|
||||
"watched_file_update_status": {
|
||||
"file_last_modified": "O ficheiro <code class=\"file-path\"></code> foi modificado pela última vez em <span class=\"file-last-modified\"></span>.",
|
||||
@@ -1814,7 +1872,9 @@
|
||||
"ws": {
|
||||
"sync-check-failed": "A verificação de sincronização falhou!",
|
||||
"consistency-checks-failed": "A verificação de consistência falhou! Veja os logs para pormenores.",
|
||||
"encountered-error": "Encontrado o erro \"{{message}}\", verifique o console."
|
||||
"encountered-error": "Encontrado o erro \"{{message}}\", verifique o console.",
|
||||
"lost-websocket-connection-title": "Perdida conexão com o servidor",
|
||||
"lost-websocket-connection-message": "Verifique a configuração da proxy inversa (e.g. nginx ou Apache) para assegurar conexões WebSocket estão permitidas e não bloqueadas."
|
||||
},
|
||||
"hoisted_note": {
|
||||
"confirm_unhoisting": "A nota solicitada '{{requestedNote}}' está fora da árvore da nota fixada '{{hoistedNote}}' e precisa desafixar para aceder a nota. Quer prosseguir e desafixar?"
|
||||
@@ -1870,7 +1930,8 @@
|
||||
"copy-link": "Copiar ligação",
|
||||
"paste": "Colar",
|
||||
"paste-as-plain-text": "Colar como texto sem formatação",
|
||||
"search_online": "Pesquisar por \"{{term}}\" com {{searchEngine}}"
|
||||
"search_online": "Pesquisar por \"{{term}}\" com {{searchEngine}}",
|
||||
"search_in_trilium": "A procurar \"{{term}}\" no Trilium"
|
||||
},
|
||||
"image_context_menu": {
|
||||
"copy_reference_to_clipboard": "Copiar referência para a área de transferência",
|
||||
@@ -1880,7 +1941,8 @@
|
||||
"open_note_in_new_tab": "Abrir nota em nova guia",
|
||||
"open_note_in_new_split": "Abrir nota em nova divisão",
|
||||
"open_note_in_new_window": "Abrir nota em nova janela",
|
||||
"open_note_in_popup": "Edição rápida"
|
||||
"open_note_in_popup": "Edição rápida",
|
||||
"open_note_in_other_split": "Abrir nota noutro separador"
|
||||
},
|
||||
"electron_integration": {
|
||||
"desktop-application": "Aplicação Desktop",
|
||||
@@ -1888,7 +1950,8 @@
|
||||
"native-title-bar-description": "Para Windows e macOS, manter a barra de título nativa desativada faz a aplicação parecer mais compacta. No Linux, manter a barra de título nativa ativada faz a aplicação se integrar melhor com o restante do sistema.",
|
||||
"background-effects": "Ativar efeitos de fundo (apenas Windows 11)",
|
||||
"restart-app-button": "Reiniciar a aplicação para ver as alterações",
|
||||
"zoom-factor": "Fator de Zoom"
|
||||
"zoom-factor": "Fator de Zoom",
|
||||
"background-effects-description": "O Mica adiciona um desfoque, fundo estiloso as janelas da aplicação, criando uma profundidade e aspecto moderno. \"Barra de titulo nativa\" deve estar inactiva."
|
||||
},
|
||||
"note_autocomplete": {
|
||||
"search-for": "Pesquisar por \"{{term}}\"",
|
||||
@@ -1948,7 +2011,8 @@
|
||||
},
|
||||
"note_language": {
|
||||
"not_set": "Não atribuído",
|
||||
"configure-languages": "Configurar idiomas..."
|
||||
"configure-languages": "Configurar idiomas...",
|
||||
"help-on-languages": "Ajuda nas linguagens de conteúdos..."
|
||||
},
|
||||
"content_language": {
|
||||
"title": "Idiomas do conteúdo",
|
||||
@@ -1966,7 +2030,8 @@
|
||||
"button_title": "Exportar diagrama como PNG"
|
||||
},
|
||||
"svg": {
|
||||
"export_to_png": "O diagrama não pôde ser exportado como PNG."
|
||||
"export_to_png": "O diagrama não pôde ser exportado como PNG.",
|
||||
"export_to_svg": "O diagrama não pode ser exportado para SVG."
|
||||
},
|
||||
"code_theme": {
|
||||
"title": "Aparência",
|
||||
@@ -1985,7 +2050,11 @@
|
||||
"editorfeatures": {
|
||||
"title": "Recursos",
|
||||
"emoji_completion_enabled": "Ativar auto-completar de Emoji",
|
||||
"note_completion_enabled": "Ativar auto-completar de notas"
|
||||
"note_completion_enabled": "Ativar auto-completar de notas",
|
||||
"emoji_completion_description": "Se activo, emojis podem ser facilmente inseridos em texto ao pressionar `:`, seguido do nome de um emoji.",
|
||||
"note_completion_description": "Se activo, links para notas podem ser criadas ao escrever `@` seguido do titulo de uma nota.",
|
||||
"slash_commands_enabled": "Activar comentários simples",
|
||||
"slash_commands_description": "Se activo, editar comandos como inserir quebras de linha ou cabeçalhos podem ser activado/inactivado ao escrever `/`."
|
||||
},
|
||||
"table_view": {
|
||||
"new-row": "Nova linha",
|
||||
@@ -2027,7 +2096,16 @@
|
||||
"delete-column": "Apagar coluna",
|
||||
"delete-column-confirmation": "Tem certeza que deseja apagar esta coluna? O atributo correspondente também será apagado de todas as notas abaixo desta coluna.",
|
||||
"new-item": "Novo elemento",
|
||||
"add-column": "Adicionar Coluna"
|
||||
"add-column": "Adicionar Coluna",
|
||||
"delete-note": "Apagar nota...",
|
||||
"remove-from-board": "Remover do quadro",
|
||||
"archive-note": "Arquivar nota",
|
||||
"new-item-placeholder": "Inserir titulo da nota...",
|
||||
"add-column-placeholder": "Inserir nome da coluna...",
|
||||
"edit-note-title": "Clicar para editar o titulo da nota",
|
||||
"unarchive-note": "Remover nota do arquivo",
|
||||
"edit-column-title": "Click para editar titulo da coluna",
|
||||
"column-already-exists": "Esta coluna já existe no quadro."
|
||||
},
|
||||
"command_palette": {
|
||||
"tree-action-name": "Árvore: {{name}}",
|
||||
@@ -2058,16 +2136,146 @@
|
||||
"background_effects_title": "Efeitos de fundo estão estáveis agora",
|
||||
"background_effects_message": "Em dispositivos Windows, efeitos de fundo estão estáveis agora. Os efeitos de fundo adicionam um toque de cor à interface do utilizador borrando o plano de fundo atrás dela. Esta técnica também é usada noutras aplicações como o Windows Explorer.",
|
||||
"background_effects_button": "Ativar os efeitos de fundo",
|
||||
"dismiss": "Dispensar"
|
||||
"dismiss": "Dispensar",
|
||||
"new_layout_title": "Novo titulo do layout",
|
||||
"new_layout_button": "Mais informação",
|
||||
"new_layout_message": "Estamos a introduzir um layout modernizado para o Trilium. A faixa foi removida e está integrada na interface principal, com uma nota barra de estado e secções expansíveis (como as propriedades próprias) a tomar papéis principais.\n\nO novo layout está activo por defeito, e pode ser temporáriamente disabilidade em Opções → Aparência."
|
||||
},
|
||||
"settings": {
|
||||
"related_settings": "Configurações relacionadas"
|
||||
},
|
||||
"settings_appearance": {
|
||||
"related_code_blocks": "Esquema de cores para blocos de código em notas de texto",
|
||||
"related_code_notes": "Esquema de cores para notas de código"
|
||||
"related_code_notes": "Esquema de cores para notas de código",
|
||||
"ui": "Interface do utilizador",
|
||||
"ui_old_layout": "Layout antigo",
|
||||
"ui_new_layout": "Nova aparência"
|
||||
},
|
||||
"units": {
|
||||
"percentage": "%"
|
||||
},
|
||||
"experimental_features": {
|
||||
"title": "Opções experimentais",
|
||||
"new_layout_name": "Novo layout",
|
||||
"new_layout_description": "Experimente o novo layout para um aspecto moderno e melhor estabilidade. Sujeito a grandes alterações nas próximas publicações.",
|
||||
"disclaimer": "Estas opções são experimentais e podem causar instabilidade. Usar com cuidado."
|
||||
},
|
||||
"read-only-info": {
|
||||
"read-only-note": "Actualmente a ver em modo de leitura.",
|
||||
"edit-note": "Editar nota",
|
||||
"auto-read-only-note": "Esta nota está a ser mostrada em modo de leitura para um carregamento mais rápido."
|
||||
},
|
||||
"presentation_view": {
|
||||
"edit-slide": "Editar este slide",
|
||||
"start-presentation": "Iniciar apresentação",
|
||||
"slide-overview": "Alternar visão geral dos slides"
|
||||
},
|
||||
"calendar_view": {
|
||||
"delete_note": "Apagar nota..."
|
||||
},
|
||||
"pagination": {
|
||||
"page_title": "Página {{startIndex}} - {{endIndex}}",
|
||||
"total_notes": "{{count}} notas"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "Sem possíbilidade de mostrar conteúdos devido a um erro."
|
||||
},
|
||||
"note-color": {
|
||||
"clear-color": "Remover cor da nota",
|
||||
"set-color": "Atribuir cor da nota",
|
||||
"set-custom-color": "Afectar cor personalizada da nota"
|
||||
},
|
||||
"popup-editor": {
|
||||
"maximize": "Alterar para editor completo"
|
||||
},
|
||||
"server": {
|
||||
"unknown_http_error_title": "Erro na comunicação com servidor",
|
||||
"unknown_http_error_content": "Código de estado: {{statusCode}}\nURL: {{method}} {{url}}\nMessagem: {{message}}",
|
||||
"traefik_blocks_requests": "Se está a usar o Traefik, este introduz uma alteração que afecta a comunicação com o servidor."
|
||||
},
|
||||
"tab_history_navigation_buttons": {
|
||||
"go-back": "Ir para a nota anterior",
|
||||
"go-forward": "Ir para nota seguinte"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"hoisted_badge": "Içado",
|
||||
"workspace_badge": "Área de trabalho",
|
||||
"scroll_to_top_title": "Saltar para o início da nota",
|
||||
"create_new_note": "Criar nova nota descendente",
|
||||
"empty_hide_archived_notes": "Esconder notas arquivadas",
|
||||
"hoisted_badge_title": "Retirar de içado"
|
||||
},
|
||||
"breadcrumb_badges": {
|
||||
"read_only_explicit": "Modo de leitura",
|
||||
"read_only_auto": "Modo de leitura automático",
|
||||
"read_only_temporarily_disabled": "Editável temporáriamente",
|
||||
"read_only_auto_description": "Esta nota foi automaticamente colocada em modo de leitura por razões de performance. Este limite automatico é ajustável nas configurações.\n\nClicar para editar temporáriamente.",
|
||||
"read_only_temporarily_disabled_description": "Esta nota está editável, mas normalmente está em modo de leitura. A nova vai regressar para mode de leitura assim que navegar para outra nota.\n\nClicar para reactivar o modo de leitura.",
|
||||
"read_only_explicit_description": "Esta nota foi manualmente colocada em modo de leitura.\nClicar para editar temporáriamente.",
|
||||
"shared_publicly": "Partilhado publicamente",
|
||||
"shared_locally": "Partilhado localmente",
|
||||
"shared_copy_to_clipboard": "Copiar link para a área de transferência",
|
||||
"shared_open_in_browser": "Abrir link no browser",
|
||||
"shared_unshare": "Remover partilha",
|
||||
"clipped_note_description": "Esta nota foi retirar do {{url}}.\n\nClicar para navegar no código fonte da página.",
|
||||
"clipped_note": "Web clipe",
|
||||
"execute_script": "Correr script",
|
||||
"execute_script_description": "Esta nota é uma nota de script. Clicar para executar o script.",
|
||||
"execute_sql": "Correr SQL",
|
||||
"execute_sql_description": "Esta nota é uma nota de SQL. Clicar para executar script SQL.",
|
||||
"save_status_saved": "Guardar",
|
||||
"save_status_saving": "A guardar...",
|
||||
"save_status_unsaved": "Não gravado",
|
||||
"save_status_error": "Gravar falhou",
|
||||
"save_status_saving_tooltip": "Alterações estão a ser guardadas",
|
||||
"save_status_unsaved_tooltip": "Existem alterações não guardadas. Serão guardadas automaticamente em breve.",
|
||||
"save_status_error_tooltip": "Ocorreu um erro ao guardar a nota. Se possível, tente copiar os conteúdos da nota para outro local e reiniciar a aplicação."
|
||||
},
|
||||
"status_bar": {
|
||||
"language_title": "Alterar lingua do conteúdo",
|
||||
"note_info_title": "Ver informação da nota (e.g., datas, tamanho da nota)",
|
||||
"backlinks_one": "{{count}} backlink",
|
||||
"backlinks_many": "{{count}} backlinks",
|
||||
"backlinks_other": "{{count}} backlinks",
|
||||
"backlinks_title_one": "Ver backlink",
|
||||
"backlinks_title_many": "Ver backlinks",
|
||||
"backlinks_title_other": "Ver backlinks",
|
||||
"attachments_one": "{{count}} anexo",
|
||||
"attachments_many": "{{count}} anexos",
|
||||
"attachments_other": "{{count}} anexos",
|
||||
"attachments_title_one": "Ver anexo num novo separador",
|
||||
"attachments_title_many": "Ver anexos num novo separador",
|
||||
"attachments_title_other": "Ver anexos num novo separador",
|
||||
"attributes_one": "{{count}} atributo",
|
||||
"attributes_many": "{{count}} atributos",
|
||||
"attributes_other": "{{count}} atributos",
|
||||
"attributes_title": "Atributos próprios e herdados",
|
||||
"note_paths_one": "{{count}} caminho",
|
||||
"note_paths_many": "{{count}} caminhos",
|
||||
"note_paths_other": "{{count}} caminhos",
|
||||
"note_paths_title": "Caminhos da nota",
|
||||
"code_note_switcher": "Alterar modo de linguagem"
|
||||
},
|
||||
"attributes_panel": {
|
||||
"title": "Atributos da nota"
|
||||
},
|
||||
"right_pane": {
|
||||
"empty_message": "Nada para mostrar nesta nota",
|
||||
"empty_button": "Esconder painél",
|
||||
"toggle": "Alterar painel direito",
|
||||
"custom_widget_go_to_source": "Ir para código fonte"
|
||||
},
|
||||
"pdf": {
|
||||
"attachments_one": "{{count}} anexo pdf",
|
||||
"attachments_many": "{{count}} anexos pdf",
|
||||
"attachments_other": "{{count}} anexos pdf",
|
||||
"layers_one": "{{count}} camada",
|
||||
"layers_many": "{{count}} camadas",
|
||||
"layers_other": "{{count}} camadas",
|
||||
"pages_one": "{{count}} página",
|
||||
"pages_many": "{{count}} páginas",
|
||||
"pages_other": "{{count}} páginas",
|
||||
"pages_alt": "Página {{pageNumber}}",
|
||||
"pages_loading": "A carregar..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"description": "Tool to compare content of Trilium databases. Useful for debugging sync problems.",
|
||||
"dependencies": {
|
||||
"colors": "1.4.0",
|
||||
"diff": "8.0.2",
|
||||
"diff": "8.0.3",
|
||||
"sqlite": "5.1.1",
|
||||
"sqlite3": "5.1.7"
|
||||
},
|
||||
|
||||
@@ -36,14 +36,14 @@
|
||||
"@triliumnext/server": "workspace:*",
|
||||
"copy-webpack-plugin": "13.0.1",
|
||||
"electron": "39.2.7",
|
||||
"@electron-forge/cli": "7.10.2",
|
||||
"@electron-forge/maker-deb": "7.10.2",
|
||||
"@electron-forge/maker-dmg": "7.10.2",
|
||||
"@electron-forge/maker-flatpak": "7.10.2",
|
||||
"@electron-forge/maker-rpm": "7.10.2",
|
||||
"@electron-forge/maker-squirrel": "7.10.2",
|
||||
"@electron-forge/maker-zip": "7.10.2",
|
||||
"@electron-forge/plugin-auto-unpack-natives": "7.10.2",
|
||||
"@electron-forge/cli": "7.11.1",
|
||||
"@electron-forge/maker-deb": "7.11.1",
|
||||
"@electron-forge/maker-dmg": "7.11.1",
|
||||
"@electron-forge/maker-flatpak": "7.11.1",
|
||||
"@electron-forge/maker-rpm": "7.11.1",
|
||||
"@electron-forge/maker-squirrel": "7.11.1",
|
||||
"@electron-forge/maker-zip": "7.11.1",
|
||||
"@electron-forge/plugin-auto-unpack-natives": "7.11.1",
|
||||
"prebuild-install": "7.1.3"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@triliumnext/edit-docs",
|
||||
"version": "0.0.1",
|
||||
"version": "0.101.3",
|
||||
"private": true,
|
||||
"description": "Desktop version of Trilium which imports the demo database (presented to new users at start-up) or the user guide and other documentation and saves the modifications for committing.",
|
||||
"dependencies": {
|
||||
@@ -16,7 +16,9 @@
|
||||
"fs-extra": "11.3.3"
|
||||
},
|
||||
"scripts": {
|
||||
"edit-docs": "cross-env TRILIUM_PORT=37741 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store DOCS_ROOT=../../../docs USER_GUIDE_ROOT=\"../../server/src/assets/doc_notes/en/User Guide\" tsx ../../scripts/electron-start.mts src/edit-docs.ts",
|
||||
"build": "tsx scripts/build.ts",
|
||||
"test-build": "vitest --config vitest.build.config.mts",
|
||||
"edit-docs": "cross-env TRILIUM_PORT=37741 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store tsx ../../scripts/electron-start.mts src/edit-docs.ts",
|
||||
"edit-demo": "cross-env TRILIUM_PORT=37744 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store DOCS_ROOT=../../../docs USER_GUIDE_ROOT=\"../../server/src/assets/doc_notes/en/User Guide\" tsx ../../scripts/electron-start.mts src/edit-demo.ts"
|
||||
}
|
||||
}
|
||||
40
apps/edit-docs/scripts/build.ts
Normal file
40
apps/edit-docs/scripts/build.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { writeFileSync } from "fs";
|
||||
import { join } from "path";
|
||||
|
||||
import BuildHelper from "../../../scripts/build-utils";
|
||||
import originalPackageJson from "../package.json" with { type: "json" };
|
||||
|
||||
const build = new BuildHelper("apps/edit-docs");
|
||||
|
||||
async function main() {
|
||||
await build.buildBackend(["src/edit-docs.ts", "src/utils.ts"]);
|
||||
|
||||
// Copy assets from server (needed for DB initialization)
|
||||
build.copy("/apps/server/src/assets", "assets/");
|
||||
build.triggerBuildAndCopyTo("packages/share-theme", "share-theme/assets/");
|
||||
build.copy("/packages/share-theme/src/templates", "share-theme/templates/");
|
||||
build.copy("/node_modules/ckeditor5/dist/ckeditor5-content.css", "ckeditor5-content.css");
|
||||
build.buildFrontend();
|
||||
|
||||
// Copy node modules dependencies
|
||||
build.copyNodeModules(["better-sqlite3", "bindings", "file-uri-to-path", "@electron/remote"]);
|
||||
|
||||
generatePackageJson();
|
||||
}
|
||||
|
||||
function generatePackageJson() {
|
||||
const { version, author, license, description, dependencies, devDependencies } = originalPackageJson;
|
||||
const packageJson = {
|
||||
name: "trilium-edit-docs",
|
||||
main: "edit-docs.cjs",
|
||||
version,
|
||||
author,
|
||||
license,
|
||||
description,
|
||||
dependencies: {"better-sqlite3": dependencies["better-sqlite3"]},
|
||||
devDependencies: {electron: devDependencies.electron},
|
||||
};
|
||||
writeFileSync(join(build.outDir, "package.json"), JSON.stringify(packageJson, null, "\t"), "utf-8");
|
||||
}
|
||||
|
||||
main();
|
||||
48
apps/edit-docs/spec/build-checks/artifacts.spec.ts
Normal file
48
apps/edit-docs/spec/build-checks/artifacts.spec.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { globSync } from "fs";
|
||||
import { join } from "path";
|
||||
import { it, describe, expect } from "vitest";
|
||||
|
||||
describe("Check artifacts are present", () => {
|
||||
const distPath = join(__dirname, "../../dist");
|
||||
|
||||
it("has the necessary node modules", async () => {
|
||||
const paths = [
|
||||
"node_modules/better-sqlite3",
|
||||
"node_modules/bindings",
|
||||
"node_modules/file-uri-to-path",
|
||||
"node_modules/@electron/remote"
|
||||
];
|
||||
|
||||
ensurePathsExist(paths);
|
||||
});
|
||||
|
||||
it("includes the client", async () => {
|
||||
const paths = [
|
||||
"public/assets",
|
||||
"public/fonts",
|
||||
"public/node_modules",
|
||||
"public/src",
|
||||
"public/stylesheets",
|
||||
"public/translations"
|
||||
];
|
||||
|
||||
ensurePathsExist(paths);
|
||||
});
|
||||
|
||||
it("includes necessary assets", async () => {
|
||||
const paths = [
|
||||
"assets",
|
||||
"share-theme",
|
||||
"ckeditor5-content.css"
|
||||
];
|
||||
|
||||
ensurePathsExist(paths);
|
||||
});
|
||||
|
||||
function ensurePathsExist(paths: string[]) {
|
||||
for (const path of paths) {
|
||||
const result = globSync(join(distPath, path, "**"));
|
||||
expect(result, path).not.toHaveLength(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,14 +1,17 @@
|
||||
import fs from "fs/promises";
|
||||
import fsExtra from "fs-extra";
|
||||
import path from "path";
|
||||
import type { NoteMetaFile } from "@triliumnext/server/src/services/meta/note_meta.js";
|
||||
import { initializeTranslations } from "@triliumnext/server/src/services/i18n.js";
|
||||
import debounce from "@triliumnext/client/src/services/debounce.js";
|
||||
import { extractZip, importData, initializeDatabase, startElectron } from "./utils.js";
|
||||
import cls from "@triliumnext/server/src/services/cls.js";
|
||||
import type { AdvancedExportOptions, ExportFormat } from "@triliumnext/server/src/services/export/zip/abstract_provider.js";
|
||||
import { initializeTranslations } from "@triliumnext/server/src/services/i18n.js";
|
||||
import { parseNoteMetaFile } from "@triliumnext/server/src/services/in_app_help.js";
|
||||
import type { NoteMetaFile } from "@triliumnext/server/src/services/meta/note_meta.js";
|
||||
import type NoteMeta from "@triliumnext/server/src/services/meta/note_meta.js";
|
||||
import fs from "fs/promises";
|
||||
import fsExtra from "fs-extra";
|
||||
import yaml from "js-yaml";
|
||||
import path from "path";
|
||||
|
||||
import packageJson from "../package.json" with { type: "json" };
|
||||
import { extractZip, importData, initializeDatabase, startElectron } from "./utils.js";
|
||||
|
||||
interface NoteMapping {
|
||||
rootNoteId: string;
|
||||
@@ -18,47 +21,113 @@ interface NoteMapping {
|
||||
exportOnly?: boolean;
|
||||
}
|
||||
|
||||
const { DOCS_ROOT, USER_GUIDE_ROOT } = process.env;
|
||||
if (!DOCS_ROOT || !USER_GUIDE_ROOT) {
|
||||
throw new Error("Missing DOCS_ROOT or USER_GUIDE_ROOT environment variable.");
|
||||
interface Config {
|
||||
baseUrl: string;
|
||||
noteMappings: NoteMapping[];
|
||||
}
|
||||
|
||||
const BASE_URL = "https://docs.triliumnotes.org";
|
||||
// Parse command-line arguments
|
||||
function parseArgs() {
|
||||
const args = process.argv.slice(2);
|
||||
let configPath: string | undefined;
|
||||
let showHelp = false;
|
||||
let showVersion = false;
|
||||
|
||||
const NOTE_MAPPINGS: NoteMapping[] = [
|
||||
{
|
||||
rootNoteId: "pOsGYCXsbNQG",
|
||||
path: path.join(__dirname, DOCS_ROOT, "User Guide"),
|
||||
format: "markdown"
|
||||
},
|
||||
{
|
||||
rootNoteId: "pOsGYCXsbNQG",
|
||||
path: path.join(__dirname, USER_GUIDE_ROOT),
|
||||
format: "html",
|
||||
ignoredFiles: ["index.html", "navigation.html", "style.css", "User Guide.html"],
|
||||
exportOnly: true
|
||||
},
|
||||
{
|
||||
rootNoteId: "jdjRLhLV3TtI",
|
||||
path: path.join(__dirname, DOCS_ROOT, "Developer Guide"),
|
||||
format: "markdown"
|
||||
},
|
||||
{
|
||||
rootNoteId: "hD3V4hiu2VW4",
|
||||
path: path.join(__dirname, DOCS_ROOT, "Release Notes"),
|
||||
format: "markdown"
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] === '--config' || args[i] === '-c') {
|
||||
configPath = args[i + 1];
|
||||
if (!configPath) {
|
||||
console.error("Error: --config/-c requires a path argument");
|
||||
process.exit(1);
|
||||
}
|
||||
i++; // Skip the next argument as it's the value
|
||||
} else if (args[i] === '--help' || args[i] === '-h') {
|
||||
showHelp = true;
|
||||
} else if (args[i] === '--version' || args[i] === '-v') {
|
||||
showVersion = true;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
return { configPath, showHelp, showVersion };
|
||||
}
|
||||
|
||||
function getVersion(): string {
|
||||
return packageJson.version;
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
const version = getVersion();
|
||||
console.log(`
|
||||
Usage: trilium-edit-docs [options]
|
||||
|
||||
Options:
|
||||
-c, --config <path> Path to the configuration file (default: edit-docs-config.yaml in the root)
|
||||
-h, --help Display this help message
|
||||
-v, --version Display version information
|
||||
|
||||
Version: ${version}
|
||||
`);
|
||||
}
|
||||
|
||||
function printVersion() {
|
||||
const version = getVersion();
|
||||
console.log(version);
|
||||
}
|
||||
|
||||
const { configPath, showHelp, showVersion } = parseArgs();
|
||||
|
||||
if (showHelp) {
|
||||
printHelp();
|
||||
process.exit(0);
|
||||
} else if (showVersion) {
|
||||
printVersion();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Configuration variables to be initialized
|
||||
let BASE_URL: string;
|
||||
let NOTE_MAPPINGS: NoteMapping[];
|
||||
|
||||
// Load configuration from edit-docs-config.yaml
|
||||
async function loadConfig() {
|
||||
let CONFIG_PATH = configPath
|
||||
? path.resolve(configPath)
|
||||
: path.join(process.cwd(), "edit-docs-config.yaml");
|
||||
|
||||
const exists = await fs.access(CONFIG_PATH).then(() => true).catch(() => false);
|
||||
if (!exists && !configPath) {
|
||||
// Fallback to project root if running from within a subproject
|
||||
CONFIG_PATH = path.join(__dirname, "../../../edit-docs-config.yaml");
|
||||
}
|
||||
|
||||
const configContent = await fs.readFile(CONFIG_PATH, "utf-8");
|
||||
const config = yaml.load(configContent) as Config;
|
||||
|
||||
BASE_URL = config.baseUrl;
|
||||
// Resolve all paths relative to the config file's directory (for flexibility with external configs)
|
||||
const CONFIG_DIR = path.dirname(CONFIG_PATH);
|
||||
NOTE_MAPPINGS = config.noteMappings.map((mapping) => ({
|
||||
...mapping,
|
||||
path: path.resolve(CONFIG_DIR, mapping.path)
|
||||
}));
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await loadConfig();
|
||||
const initializedPromise = startElectron(() => {
|
||||
// Wait for the import to be finished and the application to be loaded before we listen to changes.
|
||||
setTimeout(() => registerHandlers(), 10_000);
|
||||
setTimeout(() => {
|
||||
registerHandlers();
|
||||
}, 10_000);
|
||||
});
|
||||
|
||||
await initializeTranslations();
|
||||
await initializeDatabase(true);
|
||||
|
||||
// Wait for becca to be loaded before importing data
|
||||
const beccaLoader = await import("@triliumnext/server/src/becca/becca_loader.js");
|
||||
await beccaLoader.beccaLoaded;
|
||||
|
||||
cls.init(async () => {
|
||||
for (const mapping of NOTE_MAPPINGS) {
|
||||
if (!mapping.exportOnly) {
|
||||
@@ -142,7 +211,7 @@ async function exportData(noteId: string, format: ExportFormat, outputPath: stri
|
||||
}
|
||||
}
|
||||
|
||||
const minifyMeta = (format === "html");
|
||||
const minifyMeta = (format === "html" || format === "share");
|
||||
await cleanUpMeta(outputPath, minifyMeta);
|
||||
}
|
||||
|
||||
@@ -195,7 +264,6 @@ async function registerHandlers() {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Got entity changed", e.entityName, e.entity.title);
|
||||
debouncer();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
import cls from "@triliumnext/server/src/services/cls.js";
|
||||
import TaskContext from "@triliumnext/server/src/services/task_context.js";
|
||||
import windowService from "@triliumnext/server/src/services/window.js";
|
||||
import archiver, { type Archiver } from "archiver";
|
||||
import electron from "electron";
|
||||
import type { WriteStream } from "fs";
|
||||
import fs from "fs/promises";
|
||||
import fsExtra from "fs-extra";
|
||||
import path from "path";
|
||||
import electron from "electron";
|
||||
import windowService from "@triliumnext/server/src/services/window.js";
|
||||
import archiver, { type Archiver } from "archiver";
|
||||
import type { WriteStream } from "fs";
|
||||
import TaskContext from "@triliumnext/server/src/services/task_context.js";
|
||||
import { resolve } from "path";
|
||||
import { deferred, DeferredPromise } from "../../../packages/commons/src";
|
||||
|
||||
export function initializeDatabase(skipDemoDb: boolean) {
|
||||
return new Promise<void>(async (resolve) => {
|
||||
const sqlInit = (await import("@triliumnext/server/src/services/sql_init.js")).default;
|
||||
cls.init(async () => {
|
||||
if (!sqlInit.isDbInitialized()) {
|
||||
await sqlInit.createInitialDatabase(skipDemoDb);
|
||||
}
|
||||
resolve();
|
||||
import { deferred, type DeferredPromise } from "../../../packages/commons/src/index.js";
|
||||
|
||||
export function initializeDatabase(skipDemoDb: boolean): Promise<void> {
|
||||
return new Promise<void>((resolve) => {
|
||||
import("@triliumnext/server/src/services/sql_init.js").then((m) => {
|
||||
const sqlInit = m.default;
|
||||
cls.init(async () => {
|
||||
if (!sqlInit.isDbInitialized()) {
|
||||
sqlInit.createInitialDatabase(skipDemoDb).then(() => resolve());
|
||||
} else {
|
||||
sqlInit.dbReady.resolve();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -32,10 +36,9 @@ export function initializeDatabase(skipDemoDb: boolean) {
|
||||
*/
|
||||
export function startElectron(callback: () => void): DeferredPromise<void> {
|
||||
const initializedPromise = deferred<void>();
|
||||
electron.app.on("ready", async () => {
|
||||
await initializedPromise;
|
||||
|
||||
console.log("Electron is ready!");
|
||||
const readyHandler = async () => {
|
||||
await initializedPromise;
|
||||
|
||||
// Start the server.
|
||||
const startTriliumServer = (await import("@triliumnext/server/src/www.js")).default;
|
||||
@@ -45,7 +48,15 @@ export function startElectron(callback: () => void): DeferredPromise<void> {
|
||||
await windowService.createMainWindow(electron.app);
|
||||
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
// Handle race condition: Electron ready event may have already fired
|
||||
if (electron.app.isReady()) {
|
||||
readyHandler();
|
||||
} else {
|
||||
electron.app.on("ready", readyHandler);
|
||||
}
|
||||
|
||||
return initializedPromise;
|
||||
}
|
||||
|
||||
@@ -70,7 +81,6 @@ async function createImportZip(path: string) {
|
||||
zlib: { level: 0 }
|
||||
});
|
||||
|
||||
console.log("Archive path is ", resolve(path))
|
||||
archive.directory(path, "/");
|
||||
|
||||
const outputStream = fsExtra.createWriteStream(inputFile);
|
||||
@@ -85,14 +95,16 @@ async function createImportZip(path: string) {
|
||||
}
|
||||
|
||||
function waitForEnd(archive: Archiver, stream: WriteStream) {
|
||||
return new Promise<void>(async (res, rej) => {
|
||||
stream.on("finish", () => res());
|
||||
await archive.finalize();
|
||||
return new Promise<void>((res, rej) => {
|
||||
stream.on("finish", res);
|
||||
stream.on("error", rej);
|
||||
archive.on("error", rej);
|
||||
archive.finalize().catch(rej);
|
||||
});
|
||||
}
|
||||
|
||||
export async function extractZip(zipFilePath: string, outputPath: string, ignoredFiles?: Set<string>) {
|
||||
const promise = deferred<void>()
|
||||
const promise = deferred<void>();
|
||||
setTimeout(async () => {
|
||||
// Then extract the zip.
|
||||
const { readZipFile, readContent } = (await import("@triliumnext/server/src/services/import/zip.js"));
|
||||
|
||||
17
apps/edit-docs/vitest.build.config.mts
Normal file
17
apps/edit-docs/vitest.build.config.mts
Normal file
@@ -0,0 +1,17 @@
|
||||
/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
export default defineConfig(() => ({
|
||||
root: __dirname,
|
||||
cacheDir: '../../node_modules/.vite/apps/edit-docs',
|
||||
plugins: [],
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: "node",
|
||||
include: ['spec/build-checks/**'],
|
||||
reporters: [
|
||||
"verbose"
|
||||
]
|
||||
},
|
||||
}));
|
||||
@@ -99,7 +99,7 @@
|
||||
"html2plaintext": "2.1.4",
|
||||
"http-proxy-agent": "7.0.2",
|
||||
"https-proxy-agent": "7.0.6",
|
||||
"i18next": "25.7.3",
|
||||
"i18next": "25.7.4",
|
||||
"i18next-fs-backend": "2.6.1",
|
||||
"image-type": "6.0.0",
|
||||
"ini": "6.0.0",
|
||||
|
||||
@@ -13,5 +13,31 @@
|
||||
},
|
||||
"setup_sync-from-desktop": {
|
||||
"step6-here": "her"
|
||||
},
|
||||
"set_password": {
|
||||
"password": "Passord"
|
||||
},
|
||||
"setup": {
|
||||
"next": "Neste",
|
||||
"title": "Konfigurasjon"
|
||||
},
|
||||
"login": {
|
||||
"title": "Logg inn",
|
||||
"password": "Passord",
|
||||
"button": "Logg inn"
|
||||
},
|
||||
"setup_sync-from-server": {
|
||||
"server-host-placeholder": "https://<hostnavn>:<port>",
|
||||
"proxy-server-placeholder": "https://<hostnavn>:<port>",
|
||||
"note": "Obs:",
|
||||
"password": "Passord",
|
||||
"password-placeholder": "Passord",
|
||||
"back": "Tilbake"
|
||||
},
|
||||
"setup_sync-in-progress": {
|
||||
"outstanding-items-default": "N/A"
|
||||
},
|
||||
"share_page": {
|
||||
"parent": "overordnet notat:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ describe("data_dir.ts unit tests", async () => {
|
||||
const mockFn = {
|
||||
existsSyncMock: vi.fn(),
|
||||
mkdirSyncMock: vi.fn(),
|
||||
statSyncMock: vi.fn(),
|
||||
osHomedirMock: vi.fn(),
|
||||
osPlatformMock: vi.fn(),
|
||||
pathJoinMock: vi.fn()
|
||||
@@ -21,7 +22,8 @@ describe("data_dir.ts unit tests", async () => {
|
||||
return {
|
||||
default: {
|
||||
existsSync: mockFn.existsSyncMock,
|
||||
mkdirSync: mockFn.mkdirSyncMock
|
||||
mkdirSync: mockFn.mkdirSyncMock,
|
||||
statSync: mockFn.statSyncMock
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -109,34 +111,36 @@ describe("data_dir.ts unit tests", async () => {
|
||||
*/
|
||||
|
||||
describe("case A", () => {
|
||||
it("when folder exists – it should return the path, without attempting to create the folder", async () => {
|
||||
it("when folder exists – it should return the path, handling EEXIST gracefully", async () => {
|
||||
const mockTriliumDataPath = "/home/mock/trilium-data-ENV-A1";
|
||||
process.env.TRILIUM_DATA_DIR = mockTriliumDataPath;
|
||||
|
||||
// set fs.existsSync to true, i.e. the folder does exist
|
||||
mockFn.existsSyncMock.mockImplementation(() => true);
|
||||
// mkdirSync throws EEXIST when folder already exists (EAFP pattern)
|
||||
const eexistError = new Error("EEXIST: file already exists") as NodeJS.ErrnoException;
|
||||
eexistError.code = "EEXIST";
|
||||
mockFn.mkdirSyncMock.mockImplementation(() => { throw eexistError; });
|
||||
|
||||
// statSync confirms it's a directory
|
||||
mockFn.statSyncMock.mockImplementation(() => ({ isDirectory: () => true }));
|
||||
|
||||
const result = getTriliumDataDir("trilium-data");
|
||||
|
||||
// createDirIfNotExisting should call existsync 1 time and mkdirSync 0 times -> as it does not need to create the folder
|
||||
// and return value should be TRILIUM_DATA_DIR value from process.env
|
||||
expect(mockFn.existsSyncMock).toHaveBeenCalledTimes(1);
|
||||
expect(mockFn.mkdirSyncMock).toHaveBeenCalledTimes(0);
|
||||
// createDirIfNotExisting tries mkdirSync first (EAFP), then statSync to verify it's a directory
|
||||
expect(mockFn.mkdirSyncMock).toHaveBeenCalledTimes(1);
|
||||
expect(mockFn.statSyncMock).toHaveBeenCalledTimes(1);
|
||||
expect(result).toEqual(process.env.TRILIUM_DATA_DIR);
|
||||
});
|
||||
|
||||
it("when folder does not exist – it should attempt to create the folder and return the path", async () => {
|
||||
it("when folder does not exist – it should create the folder and return the path", async () => {
|
||||
const mockTriliumDataPath = "/home/mock/trilium-data-ENV-A2";
|
||||
process.env.TRILIUM_DATA_DIR = mockTriliumDataPath;
|
||||
|
||||
// set fs.existsSync mock to return false, i.e. the folder does not exist
|
||||
mockFn.existsSyncMock.mockImplementation(() => false);
|
||||
// mkdirSync succeeds when folder doesn't exist
|
||||
mockFn.mkdirSyncMock.mockImplementation(() => undefined);
|
||||
|
||||
const result = getTriliumDataDir("trilium-data");
|
||||
|
||||
// createDirIfNotExisting should call existsync 1 time and mkdirSync 1 times -> as it has to create the folder
|
||||
// and return value should be TRILIUM_DATA_DIR value from process.env
|
||||
expect(mockFn.existsSyncMock).toHaveBeenCalledTimes(1);
|
||||
// createDirIfNotExisting calls mkdirSync which succeeds
|
||||
expect(mockFn.mkdirSyncMock).toHaveBeenCalledTimes(1);
|
||||
expect(result).toEqual(process.env.TRILIUM_DATA_DIR);
|
||||
});
|
||||
@@ -171,19 +175,19 @@ describe("data_dir.ts unit tests", async () => {
|
||||
|
||||
// use Generator to precisely control order of fs.existSync return values
|
||||
const existsSyncMockGen = (function* () {
|
||||
// 1) fs.existSync -> case B
|
||||
// 1) fs.existSync -> case B -> checking if folder exists in home dir
|
||||
yield false;
|
||||
// 2) fs.existSync -> case C -> checking if default OS PlatformAppDataDir exists
|
||||
yield true;
|
||||
// 3) fs.existSync -> case C -> checking if Trilium Data folder exists
|
||||
yield false;
|
||||
})();
|
||||
|
||||
mockFn.existsSyncMock.mockImplementation(() => existsSyncMockGen.next().value);
|
||||
// mkdirSync succeeds (folder doesn't exist)
|
||||
mockFn.mkdirSyncMock.mockImplementation(() => undefined);
|
||||
|
||||
const result = getTriliumDataDir(dataDirName);
|
||||
|
||||
expect(mockFn.existsSyncMock).toHaveBeenCalledTimes(3);
|
||||
expect(mockFn.existsSyncMock).toHaveBeenCalledTimes(2);
|
||||
expect(mockFn.mkdirSyncMock).toHaveBeenCalledTimes(1);
|
||||
expect(result).toEqual(mockPlatformDataPath);
|
||||
});
|
||||
@@ -198,21 +202,26 @@ describe("data_dir.ts unit tests", async () => {
|
||||
|
||||
// use Generator to precisely control order of fs.existSync return values
|
||||
const existsSyncMockGen = (function* () {
|
||||
// 1) fs.existSync -> case B
|
||||
// 1) fs.existSync -> case B -> checking if folder exists in home dir
|
||||
yield false;
|
||||
// 2) fs.existSync -> case C -> checking if default OS PlatformAppDataDir exists
|
||||
yield true;
|
||||
// 3) fs.existSync -> case C -> checking if Trilium Data folder exists
|
||||
yield true;
|
||||
})();
|
||||
|
||||
mockFn.existsSyncMock.mockImplementation(() => existsSyncMockGen.next().value);
|
||||
|
||||
// mkdirSync throws EEXIST (folder already exists), statSync confirms it's a directory
|
||||
const eexistError = new Error("EEXIST: file already exists") as NodeJS.ErrnoException;
|
||||
eexistError.code = "EEXIST";
|
||||
mockFn.mkdirSyncMock.mockImplementation(() => { throw eexistError; });
|
||||
mockFn.statSyncMock.mockImplementation(() => ({ isDirectory: () => true }));
|
||||
|
||||
const result = getTriliumDataDir(dataDirName);
|
||||
|
||||
expect(result).toEqual(mockPlatformDataPath);
|
||||
expect(mockFn.existsSyncMock).toHaveBeenCalledTimes(3);
|
||||
expect(mockFn.mkdirSyncMock).toHaveBeenCalledTimes(0);
|
||||
expect(mockFn.existsSyncMock).toHaveBeenCalledTimes(2);
|
||||
expect(mockFn.mkdirSyncMock).toHaveBeenCalledTimes(1);
|
||||
expect(mockFn.statSyncMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("w/ Platform 'win32' and set process.env.APPDATA behaviour", async () => {
|
||||
@@ -227,20 +236,20 @@ describe("data_dir.ts unit tests", async () => {
|
||||
|
||||
// use Generator to precisely control order of fs.existSync return values
|
||||
const existsSyncMockGen = (function* () {
|
||||
// 1) fs.existSync -> case B
|
||||
// 1) fs.existSync -> case B -> checking if folder exists in home dir
|
||||
yield false;
|
||||
// 2) fs.existSync -> case C -> checking if default OS PlatformAppDataDir exists
|
||||
yield true;
|
||||
// 3) fs.existSync -> case C -> checking if Trilium Data folder exists
|
||||
yield false;
|
||||
})();
|
||||
|
||||
mockFn.existsSyncMock.mockImplementation(() => existsSyncMockGen.next().value);
|
||||
// mkdirSync succeeds (folder doesn't exist)
|
||||
mockFn.mkdirSyncMock.mockImplementation(() => undefined);
|
||||
|
||||
const result = getTriliumDataDir(dataDirName);
|
||||
|
||||
expect(result).toEqual(mockPlatformDataPath);
|
||||
expect(mockFn.existsSyncMock).toHaveBeenCalledTimes(3);
|
||||
expect(mockFn.existsSyncMock).toHaveBeenCalledTimes(2);
|
||||
expect(mockFn.mkdirSyncMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -253,19 +262,15 @@ describe("data_dir.ts unit tests", async () => {
|
||||
|
||||
setMockPlatform("aix", homedir, mockPlatformDataPath);
|
||||
|
||||
const existsSyncMockGen = (function* () {
|
||||
// first fs.existSync -> case B -> checking if folder exists in home folder
|
||||
yield false;
|
||||
// second fs.existSync -> case D -> triggered by createDirIfNotExisting
|
||||
yield false;
|
||||
})();
|
||||
|
||||
mockFn.existsSyncMock.mockImplementation(() => existsSyncMockGen.next().value);
|
||||
// fs.existSync -> case B -> checking if folder exists in home folder
|
||||
mockFn.existsSyncMock.mockImplementation(() => false);
|
||||
// mkdirSync succeeds (folder doesn't exist)
|
||||
mockFn.mkdirSyncMock.mockImplementation(() => undefined);
|
||||
|
||||
const result = getTriliumDataDir(dataDirName);
|
||||
|
||||
expect(result).toEqual(mockPlatformDataPath);
|
||||
expect(mockFn.existsSyncMock).toHaveBeenCalledTimes(2);
|
||||
expect(mockFn.existsSyncMock).toHaveBeenCalledTimes(1);
|
||||
expect(mockFn.mkdirSyncMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -75,9 +75,56 @@ export function getPlatformAppDataDir(platform: ReturnType<typeof os.platform>,
|
||||
}
|
||||
}
|
||||
|
||||
function outputPermissionDiagnostics(targetPath: fs.PathLike) {
|
||||
const pathStr = targetPath.toString();
|
||||
const parentDir = pathJoin(pathStr, "..");
|
||||
|
||||
console.error("\n========== PERMISSION ERROR DIAGNOSTICS ==========");
|
||||
console.error(`Failed to create directory: ${pathStr}`);
|
||||
|
||||
// Output current process UID:GID (Unix only)
|
||||
if (typeof process.getuid === "function" && typeof process.getgid === "function") {
|
||||
console.error(`Process running as UID:GID = ${process.getuid()}:${process.getgid()}`);
|
||||
}
|
||||
|
||||
// Try to get parent directory stats
|
||||
try {
|
||||
const stats = fs.statSync(parentDir);
|
||||
console.error(`Parent directory: ${parentDir}`);
|
||||
console.error(` Owner UID:GID = ${stats.uid}:${stats.gid}`);
|
||||
console.error(` Permissions = ${(stats.mode & 0o777).toString(8)} (octal)`);
|
||||
} catch {
|
||||
console.error(`Parent directory ${parentDir} is not accessible`);
|
||||
}
|
||||
|
||||
console.error("\nTo fix this issue:");
|
||||
console.error(" - Ensure the data directory is owned by the user running Trilium");
|
||||
console.error(" - Or set USER_UID and USER_GID environment variables to match the directory owner");
|
||||
console.error(" - Example: docker run -e USER_UID=$(id -u) -e USER_GID=$(id -g) ...");
|
||||
console.error("====================================================\n");
|
||||
}
|
||||
|
||||
function createDirIfNotExisting(path: fs.PathLike, permissionMode: fs.Mode = FOLDER_PERMISSIONS) {
|
||||
if (!fs.existsSync(path)) {
|
||||
try {
|
||||
fs.mkdirSync(path, permissionMode);
|
||||
} catch (err: unknown) {
|
||||
if (err && typeof err === "object" && "code" in err) {
|
||||
const code = (err as { code: string }).code;
|
||||
|
||||
if (code === "EACCES") {
|
||||
outputPermissionDiagnostics(path);
|
||||
} else if (code === "EEXIST") {
|
||||
// Directory already exists - verify it's actually a directory
|
||||
try {
|
||||
if (fs.statSync(path).isDirectory()) {
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
// If we can't stat it, fall through to re-throw original error
|
||||
}
|
||||
}
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
"preview": "pnpm build && vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"i18next": "25.7.3",
|
||||
"i18next": "25.7.4",
|
||||
"i18next-http-backend": "3.0.2",
|
||||
"preact": "10.28.2",
|
||||
"preact-iso": "2.11.1",
|
||||
"preact-render-to-string": "6.6.5",
|
||||
"react-i18next": "16.5.1"
|
||||
"react-i18next": "16.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@preact/preset-vite": "2.10.2",
|
||||
@@ -23,7 +23,7 @@
|
||||
"typescript": "5.9.3",
|
||||
"user-agent-data-types": "0.4.2",
|
||||
"vite": "7.3.1",
|
||||
"vitest": "4.0.16"
|
||||
"vitest": "4.0.17"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "preact"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"note_structure_description": "Notizen lassen sich hierarchisch anordnen. Ordner sind nicht nötig, da jede Notiz Unternotizen enthalten kann. Eine einzelne Notiz kann an mehreren Stellen in der Hierarchie hinzugefügt werden.",
|
||||
"hoisting_description": "Trennen Sie Ihre persönlichen und beruflichen Notizen ganz einfach, indem Sie sie in einem Arbeitsbereich gruppieren. Dadurch wird Ihre Notizstruktur so fokussiert, dass nur ein bestimmter Satz von Notizen angezeigt wird.",
|
||||
"hoisting_title": "Arbeitsbereiche und Fokusansicht",
|
||||
"attributes_description": "Verwenden Sie Beziehungen zwischen Notizen oder fügen Sie Beschriftungen hinzu, um die Kategorisierung zu vereinfachen. Verwenden Sie hervorgehobene Attribute, um strukturierte Informationen einzugeben, die in Tabellen und Boards verwendet werden können."
|
||||
"attributes_description": "Für leichtes kategorsieren, nutze Verbindungen zwischen Notizen oder füge Label hinzu. Verwende hervorgehobene Attribute, um sie als strukturierte Informationen in Tabellen oder Anschlagbretter zu verwenden."
|
||||
},
|
||||
"productivity_benefits": {
|
||||
"revisions_title": "Notizrevisionen",
|
||||
@@ -30,7 +30,7 @@
|
||||
"protected_notes_title": "Geschützte Notizen",
|
||||
"jump_to_title": "Schnellsuche und Kommandos",
|
||||
"search_title": "Leistungsstarke Suche",
|
||||
"web_clipper_title": "Web clipper",
|
||||
"web_clipper_title": "Webschnipsel",
|
||||
"revisions_content": "Notizen werden regelmäßig im Hintergrund gespeichert und Revisionen können zur Überprüfung oder zum Rückgängigmachen versehentlicher Änderungen verwendet werden. Revisionen können auch bei Bedarf erstellt werden.",
|
||||
"sync_content": "Verwenden Sie eine selbst gehostete oder Cloud-Instanz, um Ihre Notizen ganz einfach auf mehreren Geräten zu synchronisieren und über eine WebApp von Ihrem mobilen Gerät aus darauf zuzugreifen.",
|
||||
"protected_notes_content": "Halten Sie vertrauliche Informationen sicher, indem Sie Notizen verschlüsseln und mit einem Passwort schützen.",
|
||||
@@ -41,7 +41,7 @@
|
||||
"note_types": {
|
||||
"text_title": "Text Notizen",
|
||||
"code_title": "Code Notizen",
|
||||
"canvas_title": "Canvas",
|
||||
"canvas_title": "Leinwand",
|
||||
"mermaid_title": "Mermaid Diagramm",
|
||||
"mindmap_title": "Mind Map",
|
||||
"text_description": "Die Notizen werden mit einem visuellen Editor (WYSIWYG) bearbeitet, der Tabellen, Bilder, mathematische Ausdrücke und Code-Blöcke mit Syntaxhervorhebung unterstützt. Formatieren Sie den Text schnell mit einer Markdown-ähnlichen Syntax oder mit Slash-Befehlen.",
|
||||
@@ -162,7 +162,7 @@
|
||||
},
|
||||
"social_buttons": {
|
||||
"github": "GitHub",
|
||||
"github_discussions": "GitHub Discussions",
|
||||
"github_discussions": "GitHub Diskussionen",
|
||||
"matrix": "Matrix",
|
||||
"reddit": "Reddit"
|
||||
},
|
||||
@@ -184,7 +184,7 @@
|
||||
"way_market": "Weitersagen: Teilen Sie Trilium Notes mit Freunden, in Blogs und sozialen Medien."
|
||||
},
|
||||
"404": {
|
||||
"title": "404: Not Found",
|
||||
"title": "404: Nicht gefunden",
|
||||
"description": "Die gesuchte Seite konnte nicht gefunden werden. Möglicherweise wurde sie gelöscht oder die URL ist falsch."
|
||||
},
|
||||
"download_helper_desktop_windows": {
|
||||
@@ -193,7 +193,7 @@
|
||||
"description_x64": "Kompatibel mit Intel- oder AMD-Geräten unter Windows 10 und 11.",
|
||||
"description_arm64": "Kompatibel mit ARM-Geräten (z. B. mit Qualcomm Snapdragon).",
|
||||
"quick_start": "Installation über Winget:",
|
||||
"download_exe": "Download Installer (.exe)",
|
||||
"download_exe": "Installationsdatei herunterladen (.exe)",
|
||||
"download_zip": "Portable (.zip)",
|
||||
"download_scoop": "Scoop"
|
||||
}
|
||||
|
||||
4
docs/README-de.md
vendored
4
docs/README-de.md
vendored
@@ -132,8 +132,8 @@ Unsere Dokumentation ist verfügbar in mehreren Formaten:
|
||||
einfachen Speichern von Webinhalten
|
||||
* Anpassbare Benutzeroberfläche (Seitenleisten-Schaltflächen, benutzerdefinierte
|
||||
Widgets, ...)
|
||||
* [Metriken](https://docs.triliumnotes.org/user-guide/advanced-usage/metrics)
|
||||
zusammen mit einem Grafana-Dashboard.
|
||||
* [Metrics](https://docs.triliumnotes.org/user-guide/advanced-usage/metrics),
|
||||
zusätzlich mit dem Grafana Dashboard.
|
||||
|
||||
✨ Weitere Informationen zu TriliumNext findet man in den folgenden
|
||||
Ressourcen/Communities von Drittanbietern:
|
||||
|
||||
4
docs/README-nb_NO.md
vendored
4
docs/README-nb_NO.md
vendored
@@ -91,8 +91,8 @@ Vår dokumentasjon er tilgjengelig i flere format:
|
||||
* Direct [OpenID and TOTP
|
||||
integration](https://docs.triliumnotes.org/user-guide/setup/server/mfa) for
|
||||
more secure login
|
||||
* [Synchronization](https://docs.triliumnotes.org/user-guide/setup/synchronization)
|
||||
with self-hosted sync server
|
||||
* [Synkronisering](https://docs.triliumnotes.org/user-guide/setup/synchronization)
|
||||
med selv-hostet sync server
|
||||
* there are [3rd party services for hosting synchronisation
|
||||
server](https://docs.triliumnotes.org/user-guide/setup/server/cloud-hosting)
|
||||
* [Sharing](https://docs.triliumnotes.org/user-guide/advanced-usage/sharing)
|
||||
|
||||
24
edit-docs-config.yaml
Normal file
24
edit-docs-config.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
baseUrl: "https://docs.triliumnotes.org"
|
||||
|
||||
noteMappings:
|
||||
- rootNoteId: "pOsGYCXsbNQG"
|
||||
path: "docs/User Guide"
|
||||
format: "markdown"
|
||||
|
||||
- rootNoteId: "pOsGYCXsbNQG"
|
||||
path: "apps/server/src/assets/doc_notes/en/User Guide"
|
||||
format: "html"
|
||||
ignoredFiles:
|
||||
- "index.html"
|
||||
- "navigation.html"
|
||||
- "style.css"
|
||||
- "User Guide.html"
|
||||
exportOnly: true
|
||||
|
||||
- rootNoteId: "jdjRLhLV3TtI"
|
||||
path: "docs/Developer Guide"
|
||||
format: "markdown"
|
||||
|
||||
- rootNoteId: "hD3V4hiu2VW4"
|
||||
path: "docs/Release Notes"
|
||||
format: "markdown"
|
||||
25
flake.nix
25
flake.nix
@@ -112,7 +112,7 @@
|
||||
nodejs.python
|
||||
removeReferencesTo
|
||||
]
|
||||
++ lib.optionals (app == "desktop") [
|
||||
++ lib.optionals (app == "desktop" || app == "edit-docs") [
|
||||
copyDesktopItems
|
||||
# required for NIXOS_OZONE_WL expansion
|
||||
# https://github.com/NixOS/nixpkgs/issues/172583
|
||||
@@ -252,10 +252,33 @@
|
||||
--add-flags $out/opt/trilium-server/main.cjs
|
||||
'';
|
||||
};
|
||||
|
||||
edit-docs = makeApp {
|
||||
app = "edit-docs";
|
||||
preBuildCommands = ''
|
||||
export npm_config_nodedir=${electron.headers}
|
||||
pnpm postinstall
|
||||
'';
|
||||
buildTask = "edit-docs:build";
|
||||
mainProgram = "trilium-edit-docs";
|
||||
installCommands = ''
|
||||
#remove-references-to -t ${electron.headers} apps/edit-docs/dist/node_modules/better-sqlite3/build/config.gypi
|
||||
#remove-references-to -t ${nodejs.python} apps/edit-docs/dist/node_modules/better-sqlite3/build/config.gypi
|
||||
|
||||
mkdir -p $out/{bin,opt/trilium-edit-docs}
|
||||
cp --archive apps/edit-docs/dist/* $out/opt/trilium-edit-docs
|
||||
makeShellWrapper ${lib.getExe electron} $out/bin/trilium-edit-docs \
|
||||
--set-default ELECTRON_IS_DEV 0 \
|
||||
--set TRILIUM_RESOURCE_DIR $out/opt/trilium-edit-docs \
|
||||
--add-flags $out/opt/trilium-edit-docs/edit-docs.cjs
|
||||
'';
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
packages.desktop = desktop;
|
||||
packages.server = server;
|
||||
packages.edit-docs = edit-docs;
|
||||
|
||||
packages.default = desktop;
|
||||
|
||||
|
||||
25
package.json
25
package.json
@@ -17,6 +17,8 @@
|
||||
"desktop:start": "pnpm run --filter desktop dev",
|
||||
"desktop:build": "pnpm run --filter desktop build",
|
||||
"desktop:start-prod": "pnpm run --filter desktop start-prod",
|
||||
"edit-docs:edit-docs": "pnpm run --filter edit-docs edit-docs",
|
||||
"edit-docs:build": "pnpm run --filter edit-docs build",
|
||||
"website:start": "pnpm run --filter website dev",
|
||||
"website:build": "pnpm run --filter website build",
|
||||
"electron:build": "pnpm desktop:build",
|
||||
@@ -28,7 +30,6 @@
|
||||
"chore:update-version": "tsx ./scripts/update-version.ts",
|
||||
"docs:build": "pnpm run --filter build-docs start",
|
||||
"docs:preview": "pnpm http-server site -p 9000",
|
||||
"edit-docs:edit-docs": "pnpm run --filter edit-docs edit-docs",
|
||||
"edit-docs:edit-demo": "pnpm run --filter edit-docs edit-demo",
|
||||
"test:all": "pnpm test:parallel && pnpm test:sequential",
|
||||
"test:parallel": "pnpm --filter=!server --filter=!ckeditor5-mermaid --filter=!ckeditor5-math --parallel test",
|
||||
@@ -48,10 +49,11 @@
|
||||
"@playwright/test": "1.57.0",
|
||||
"@triliumnext/server": "workspace:*",
|
||||
"@types/express": "5.0.6",
|
||||
"@types/node": "24.10.7",
|
||||
"@vitest/browser-webdriverio": "4.0.16",
|
||||
"@vitest/coverage-v8": "4.0.16",
|
||||
"@vitest/ui": "4.0.16",
|
||||
"@types/js-yaml": "4.0.9",
|
||||
"@types/node": "24.10.8",
|
||||
"@vitest/browser-webdriverio": "4.0.17",
|
||||
"@vitest/coverage-v8": "4.0.17",
|
||||
"@vitest/ui": "4.0.17",
|
||||
"chalk": "5.6.2",
|
||||
"cross-env": "10.1.0",
|
||||
"dpdm": "3.14.0",
|
||||
@@ -59,22 +61,23 @@
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-preact": "2.0.0",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"eslint-plugin-playwright": "2.4.1",
|
||||
"eslint-plugin-playwright": "2.5.0",
|
||||
"eslint-plugin-simple-import-sort": "12.1.1",
|
||||
"happy-dom": "~20.0.0",
|
||||
"happy-dom": "20.1.0",
|
||||
"http-server": "14.1.1",
|
||||
"jiti": "2.6.1",
|
||||
"js-yaml": "4.1.1",
|
||||
"jsonc-eslint-parser": "2.4.2",
|
||||
"react-refresh": "0.18.0",
|
||||
"rollup-plugin-webpack-stats": "2.1.9",
|
||||
"tslib": "2.8.1",
|
||||
"tsx": "4.21.0",
|
||||
"typescript": "~5.9.0",
|
||||
"typescript-eslint": "8.52.0",
|
||||
"typescript": "5.9.3",
|
||||
"typescript-eslint": "8.53.0",
|
||||
"upath": "2.0.1",
|
||||
"vite": "7.3.1",
|
||||
"vite-plugin-dts": "~4.5.0",
|
||||
"vitest": "4.0.16"
|
||||
"vite-plugin-dts": "4.5.4",
|
||||
"vitest": "4.0.17"
|
||||
},
|
||||
"license": "AGPL-3.0-only",
|
||||
"author": {
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
"@ckeditor/ckeditor5-dev-build-tools": "54.2.3",
|
||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "~8.52.0",
|
||||
"@typescript-eslint/parser": "8.52.0",
|
||||
"@vitest/browser": "4.0.16",
|
||||
"@vitest/coverage-istanbul": "4.0.16",
|
||||
"@typescript-eslint/eslint-plugin": "8.53.0",
|
||||
"@typescript-eslint/parser": "8.53.0",
|
||||
"@vitest/browser": "4.0.17",
|
||||
"@vitest/coverage-istanbul": "4.0.17",
|
||||
"ckeditor5": "47.3.0",
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-ckeditor5": ">=9.1.0",
|
||||
@@ -37,8 +37,8 @@
|
||||
"stylelint-config-ckeditor5": ">=9.1.0",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.9.3",
|
||||
"vite-plugin-svgo": "~2.0.0",
|
||||
"vitest": "4.0.16",
|
||||
"vite-plugin-svgo": "2.0.0",
|
||||
"vitest": "4.0.17",
|
||||
"webdriverio": "9.23.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
"@ckeditor/ckeditor5-dev-build-tools": "54.2.3",
|
||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "~8.52.0",
|
||||
"@typescript-eslint/parser": "8.52.0",
|
||||
"@vitest/browser": "4.0.16",
|
||||
"@vitest/coverage-istanbul": "4.0.16",
|
||||
"@typescript-eslint/eslint-plugin": "8.53.0",
|
||||
"@typescript-eslint/parser": "8.53.0",
|
||||
"@vitest/browser": "4.0.17",
|
||||
"@vitest/coverage-istanbul": "4.0.17",
|
||||
"ckeditor5": "47.3.0",
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-ckeditor5": ">=9.1.0",
|
||||
@@ -38,8 +38,8 @@
|
||||
"stylelint-config-ckeditor5": ">=9.1.0",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.9.3",
|
||||
"vite-plugin-svgo": "~2.0.0",
|
||||
"vitest": "4.0.16",
|
||||
"vite-plugin-svgo": "2.0.0",
|
||||
"vitest": "4.0.17",
|
||||
"webdriverio": "9.23.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
"@ckeditor/ckeditor5-dev-build-tools": "54.2.3",
|
||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "~8.52.0",
|
||||
"@typescript-eslint/parser": "8.52.0",
|
||||
"@vitest/browser": "4.0.16",
|
||||
"@vitest/coverage-istanbul": "4.0.16",
|
||||
"@typescript-eslint/eslint-plugin": "8.53.0",
|
||||
"@typescript-eslint/parser": "8.53.0",
|
||||
"@vitest/browser": "4.0.17",
|
||||
"@vitest/coverage-istanbul": "4.0.17",
|
||||
"ckeditor5": "47.3.0",
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-ckeditor5": ">=9.1.0",
|
||||
@@ -40,8 +40,8 @@
|
||||
"stylelint-config-ckeditor5": ">=9.1.0",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.9.3",
|
||||
"vite-plugin-svgo": "~2.0.0",
|
||||
"vitest": "4.0.16",
|
||||
"vite-plugin-svgo": "2.0.0",
|
||||
"vitest": "4.0.17",
|
||||
"webdriverio": "9.23.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
"@ckeditor/ckeditor5-dev-build-tools": "54.2.3",
|
||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "~8.52.0",
|
||||
"@typescript-eslint/parser": "8.52.0",
|
||||
"@vitest/browser": "4.0.16",
|
||||
"@vitest/coverage-istanbul": "4.0.16",
|
||||
"@typescript-eslint/eslint-plugin": "8.53.0",
|
||||
"@typescript-eslint/parser": "8.53.0",
|
||||
"@vitest/browser": "4.0.17",
|
||||
"@vitest/coverage-istanbul": "4.0.17",
|
||||
"ckeditor5": "47.3.0",
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-ckeditor5": ">=9.1.0",
|
||||
@@ -40,8 +40,8 @@
|
||||
"stylelint-config-ckeditor5": ">=9.1.0",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.9.3",
|
||||
"vite-plugin-svgo": "~2.0.0",
|
||||
"vitest": "4.0.16",
|
||||
"vite-plugin-svgo": "2.0.0",
|
||||
"vitest": "4.0.17",
|
||||
"webdriverio": "9.23.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
"@ckeditor/ckeditor5-dev-build-tools": "54.2.3",
|
||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "~8.52.0",
|
||||
"@typescript-eslint/parser": "8.52.0",
|
||||
"@vitest/browser": "4.0.16",
|
||||
"@vitest/coverage-istanbul": "4.0.16",
|
||||
"@typescript-eslint/eslint-plugin": "8.53.0",
|
||||
"@typescript-eslint/parser": "8.53.0",
|
||||
"@vitest/browser": "4.0.17",
|
||||
"@vitest/coverage-istanbul": "4.0.17",
|
||||
"ckeditor5": "47.3.0",
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-ckeditor5": ">=9.1.0",
|
||||
@@ -40,8 +40,8 @@
|
||||
"stylelint-config-ckeditor5": ">=9.1.0",
|
||||
"ts-node": "10.9.2",
|
||||
"typescript": "5.9.3",
|
||||
"vite-plugin-svgo": "~2.0.0",
|
||||
"vitest": "4.0.16",
|
||||
"vite-plugin-svgo": "2.0.0",
|
||||
"vitest": "4.0.17",
|
||||
"webdriverio": "9.23.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"ckeditor5-premium-features": "47.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@smithy/middleware-retry": "4.4.19",
|
||||
"@smithy/middleware-retry": "4.4.20",
|
||||
"@types/jquery": "3.5.33"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
"devDependencies": {
|
||||
"@digitak/esrun": "3.2.26",
|
||||
"@triliumnext/ckeditor5": "workspace:*",
|
||||
"@typescript-eslint/eslint-plugin": "8.52.0",
|
||||
"@typescript-eslint/parser": "8.52.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.53.0",
|
||||
"@typescript-eslint/parser": "8.53.0",
|
||||
"dotenv": "17.2.3",
|
||||
"esbuild": "0.27.2",
|
||||
"eslint": "9.39.2",
|
||||
|
||||
1363
pnpm-lock.yaml
generated
1363
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,8 @@ import { getElectronPath, isNixOS } from "./utils.mjs";
|
||||
|
||||
const LD_LIBRARY_PATH = isNixOS() && execSync("nix eval --raw nixpkgs#gcc.cc.lib").toString("utf-8") + "/lib";
|
||||
|
||||
execSync(`${getElectronPath()} ${process.argv[2]} --no-sandbox`, {
|
||||
const args = process.argv.slice(2);
|
||||
execSync(`${getElectronPath()} ${args.join(" ")} --no-sandbox`, {
|
||||
stdio: "inherit",
|
||||
env: {
|
||||
...process.env,
|
||||
|
||||
@@ -26,7 +26,7 @@ function getVersion(packageJsonPath: string) {
|
||||
function main() {
|
||||
const version = getVersion(join(__dirname, "..", "package.json"));
|
||||
|
||||
for (const appName of ["server", "client", "desktop"]) {
|
||||
for (const appName of ["server", "client", "desktop", "edit-docs"]) {
|
||||
patchPackageJson(join(__dirname, "..", "apps", appName, "package.json"), version);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user