diff --git a/.github/actions/build-server/action.yml b/.github/actions/build-server/action.yml index faa3c0752..b92b3875f 100644 --- a/.github/actions/build-server/action.yml +++ b/.github/actions/build-server/action.yml @@ -12,7 +12,7 @@ runs: - name: Set up node & dependencies uses: actions/setup-node@v6 with: - node-version: 22 + node-version: 24 cache: "pnpm" - name: Install dependencies shell: bash diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 62e04d48d..40423c776 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -1,6 +1,4 @@ -# GitHub Actions workflow for deploying MkDocs documentation to Cloudflare Pages -# This workflow builds and deploys your MkDocs site when changes are pushed to main -name: Deploy MkDocs Documentation +name: Deploy Documentation on: # Trigger on push to main branch @@ -11,11 +9,8 @@ on: # Only run when docs files change paths: - 'docs/**' - - 'README.md' # README is synced to docs/index.md - - 'mkdocs.yml' - - 'requirements-docs.txt' - - '.github/workflows/deploy-docs.yml' - - 'scripts/fix-mkdocs-structure.ts' + - 'apps/edit-docs/**' + - 'packages/share-theme/**' # Allow manual triggering from Actions tab workflow_dispatch: @@ -27,15 +22,12 @@ on: - master paths: - 'docs/**' - - 'README.md' # README is synced to docs/index.md - - 'mkdocs.yml' - - 'requirements-docs.txt' - - '.github/workflows/deploy-docs.yml' - - 'scripts/fix-mkdocs-structure.ts' + - 'apps/edit-docs/**' + - 'packages/share-theme/**' jobs: build-and-deploy: - name: Build and Deploy MkDocs + name: Build and Deploy Documentation runs-on: ubuntu-latest timeout-minutes: 10 @@ -49,72 +41,25 @@ jobs: steps: - name: Checkout Repository uses: actions/checkout@v5 - with: - fetch-depth: 0 # Fetch all history for git info and mkdocs-git-revision-date plugin - - name: Setup Python - uses: actions/setup-python@v6 - with: - python-version: '3.14' - cache: 'pip' - cache-dependency-path: 'requirements-docs.txt' - - - name: Install MkDocs and Dependencies - run: | - pip install --upgrade pip - pip install -r requirements-docs.txt - env: - PIP_DISABLE_PIP_VERSION_CHECK: 1 - - # Setup pnpm before fixing docs structure - name: Setup pnpm uses: pnpm/action-setup@v4 - # Setup Node.js with pnpm - name: Setup Node.js uses: actions/setup-node@v6 with: - node-version: '22' + node-version: '24' cache: 'pnpm' - # Install Node.js dependencies for the TypeScript script - name: Install Dependencies - run: | - pnpm install --frozen-lockfile + run: pnpm install --frozen-lockfile - - name: Fix Documentation Structure - run: | - # Fix duplicate navigation entries by moving overview pages to index.md - pnpm run chore:fix-mkdocs-structure - - - name: Build MkDocs Site - run: | - # Build with strict mode but allow expected warnings - mkdocs build --verbose || { - EXIT_CODE=$? - # Check if the only issue is expected warnings - if mkdocs build 2>&1 | grep -E "WARNING.*(README|not found)" && \ - [ $(mkdocs build 2>&1 | grep -c "ERROR") -eq 0 ]; then - echo "✅ Build succeeded with expected warnings" - mkdocs build --verbose - else - echo "❌ Build failed with unexpected errors" - exit $EXIT_CODE - fi - } - - - name: Fix HTML Links - run: | - # Remove .md extensions from links in generated HTML - pnpm tsx ./scripts/fix-html-links.ts site + - name: Trigger build of documentation + run: pnpm docs:build - name: Validate Built Site run: | - # Basic validation that important files exist test -f site/index.html || (echo "ERROR: site/index.html not found" && exit 1) - test -f site/sitemap.xml || (echo "ERROR: site/sitemap.xml not found" && exit 1) - test -d site/assets || (echo "ERROR: site/assets directory not found" && exit 1) - echo "✅ Site validation passed" - name: Deploy uses: ./.github/actions/deploy-to-cloudflare-pages diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index ec4aeda0e..f9174fb42 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -30,7 +30,7 @@ jobs: - name: Set up node & dependencies uses: actions/setup-node@v6 with: - node-version: 22 + node-version: 24 cache: "pnpm" - run: pnpm install --frozen-lockfile diff --git a/.github/workflows/main-docker.yml b/.github/workflows/main-docker.yml index 827320146..fab20d242 100644 --- a/.github/workflows/main-docker.yml +++ b/.github/workflows/main-docker.yml @@ -46,7 +46,7 @@ jobs: - name: Set up node & dependencies uses: actions/setup-node@v6 with: - node-version: 22 + node-version: 24 cache: "pnpm" - name: Install npm dependencies @@ -116,10 +116,10 @@ jobs: - dockerfile: Dockerfile platform: linux/arm64 image: ubuntu-24.04-arm - - dockerfile: Dockerfile + - dockerfile: Dockerfile.legacy platform: linux/arm/v7 image: ubuntu-24.04-arm - - dockerfile: Dockerfile + - dockerfile: Dockerfile.legacy platform: linux/arm/v8 image: ubuntu-24.04-arm runs-on: ${{ matrix.image }} @@ -146,7 +146,7 @@ jobs: - name: Set up node & dependencies uses: actions/setup-node@v6 with: - node-version: 22 + node-version: 24 cache: 'pnpm' - name: Install dependencies diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index ac15f9914..ddce68d42 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -52,7 +52,7 @@ jobs: - name: Set up node & dependencies uses: actions/setup-node@v6 with: - node-version: 22 + node-version: 24 cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index e2a2757f5..a33d24283 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -24,7 +24,7 @@ jobs: - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v6 with: - node-version: 22 + node-version: 24 cache: 'pnpm' - name: Install dependencies diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1bd2d89ba..3d48cb80d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -50,7 +50,7 @@ jobs: - name: Set up node & dependencies uses: actions/setup-node@v6 with: - node-version: 22 + node-version: 24 cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index fe94c987a..7a87cc192 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -30,7 +30,7 @@ jobs: - name: Set up node & dependencies uses: actions/setup-node@v6 with: - node-version: 22 + node-version: 24 cache: "pnpm" - name: Install dependencies diff --git a/_regroup/package.json b/_regroup/package.json index 1937327e0..0b2a759a9 100644 --- a/_regroup/package.json +++ b/_regroup/package.json @@ -37,8 +37,8 @@ "devDependencies": { "@playwright/test": "1.56.1", "@stylistic/eslint-plugin": "5.5.0", - "@types/express": "5.0.4", - "@types/node": "22.18.12", + "@types/express": "5.0.5", + "@types/node": "24.9.1", "@types/yargs": "17.0.34", "@vitest/coverage-v8": "3.2.4", "eslint": "9.38.0", diff --git a/apps/client/package.json b/apps/client/package.json index 61738b8bb..6bc7f10f2 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -54,12 +54,12 @@ "leaflet-gpx": "2.2.0", "mark.js": "8.11.1", "marked": "16.4.1", - "mermaid": "11.12.0", + "mermaid": "11.12.1", "mind-elixir": "5.3.4", "normalize.css": "8.0.1", "panzoom": "9.4.3", "preact": "10.27.2", - "react-i18next": "16.2.0", + "react-i18next": "16.2.1", "reveal.js": "5.2.1", "svg-pan-zoom": "3.6.2", "tabulator-tables": "6.3.1", diff --git a/apps/client/src/components/app_context.ts b/apps/client/src/components/app_context.ts index ce33d1447..7bc544e7e 100644 --- a/apps/client/src/components/app_context.ts +++ b/apps/client/src/components/app_context.ts @@ -218,12 +218,12 @@ export type CommandMappings = { /** Works only in the electron context menu. */ replaceMisspelling: CommandData; - importMarkdownInline: CommandData; showPasswordNotSet: CommandData; showProtectedSessionPasswordDialog: CommandData; showUploadAttachmentsDialog: CommandData & { noteId: string }; showIncludeNoteDialog: CommandData & { textTypeWidget: EditableTextTypeWidget }; showAddLinkDialog: CommandData & { textTypeWidget: EditableTextTypeWidget, text: string }; + showPasteMarkdownDialog: CommandData & { textTypeWidget: EditableTextTypeWidget }; closeProtectedSessionPasswordDialog: CommandData; copyImageReferenceToClipboard: CommandData; copyImageToClipboard: CommandData; @@ -270,6 +270,7 @@ export type CommandMappings = { closeThisNoteSplit: CommandData; moveThisNoteSplit: CommandData & { isMovingLeft: boolean }; jumpToNote: CommandData; + openTodayNote: CommandData; commandPalette: CommandData; // Keyboard shortcuts diff --git a/apps/client/src/components/entrypoints.ts b/apps/client/src/components/entrypoints.ts index 7989960a6..8a902666f 100644 --- a/apps/client/src/components/entrypoints.ts +++ b/apps/client/src/components/entrypoints.ts @@ -159,6 +159,16 @@ export default class Entrypoints extends Component { this.openInWindowCommand({ notePath: "", hoistedNoteId: "root" }); } + async openTodayNoteCommand() { + const todayNote = await dateNoteService.getTodayNote(); + if (!todayNote) { + console.warn("Missing today note."); + return; + } + + await appContext.tabManager.openInSameTab(todayNote.noteId); + } + async runActiveNoteCommand() { const noteContext = appContext.tabManager.getActiveContext(); if (!noteContext) { diff --git a/apps/client/src/entities/fnote.ts b/apps/client/src/entities/fnote.ts index bcb6c408e..6d0a15506 100644 --- a/apps/client/src/entities/fnote.ts +++ b/apps/client/src/entities/fnote.ts @@ -417,7 +417,7 @@ export default class FNote { return notePaths; } - getSortedNotePathRecords(hoistedNoteId = "root"): NotePathRecord[] { + getSortedNotePathRecords(hoistedNoteId = "root", activeNotePath: string | null = null): NotePathRecord[] { const isHoistedRoot = hoistedNoteId === "root"; const notePaths: NotePathRecord[] = this.getAllNotePaths().map((path) => ({ @@ -428,7 +428,23 @@ export default class FNote { isHidden: path.includes("_hidden") })); + // Calculate the length of the prefix match between two arrays + const prefixMatchLength = (path: string[], target: string[]) => { + const diffIndex = path.findIndex((seg, i) => seg !== target[i]); + return diffIndex === -1 ? Math.min(path.length, target.length) : diffIndex; + }; + notePaths.sort((a, b) => { + if (activeNotePath) { + const activeSegments = activeNotePath.split('/'); + const aOverlap = prefixMatchLength(a.notePath, activeSegments); + const bOverlap = prefixMatchLength(b.notePath, activeSegments); + // Paths with more matching prefix segments are prioritized + // when the match count is equal, other criteria are used for sorting + if (bOverlap !== aOverlap) { + return bOverlap - aOverlap; + } + } if (a.isInHoistedSubTree !== b.isInHoistedSubTree) { return a.isInHoistedSubTree ? -1 : 1; } else if (a.isArchived !== b.isArchived) { @@ -449,10 +465,11 @@ export default class FNote { * Returns the note path considered to be the "best" * * @param {string} [hoistedNoteId='root'] + * @param {string|null} [activeNotePath=null] * @return {string[]} array of noteIds constituting the particular note path */ - getBestNotePath(hoistedNoteId = "root") { - return this.getSortedNotePathRecords(hoistedNoteId)[0]?.notePath; + getBestNotePath(hoistedNoteId = "root", activeNotePath: string | null = null) { + return this.getSortedNotePathRecords(hoistedNoteId, activeNotePath)[0]?.notePath; } /** diff --git a/apps/client/src/services/glob.ts b/apps/client/src/services/glob.ts index 48d0d29a7..44ce64309 100644 --- a/apps/client/src/services/glob.ts +++ b/apps/client/src/services/glob.ts @@ -20,9 +20,6 @@ function setupGlobs() { window.glob.froca = froca; window.glob.treeCache = froca; // compatibility for CKEditor builds for a while - // for CKEditor integration (button on block toolbar) - window.glob.importMarkdownInline = async () => appContext.triggerCommand("importMarkdownInline"); - window.onerror = function (msg, url, lineNo, columnNo, error) { const string = String(msg).toLowerCase(); diff --git a/apps/client/src/services/tree.ts b/apps/client/src/services/tree.ts index fc54c3c75..ec5bc0191 100644 --- a/apps/client/src/services/tree.ts +++ b/apps/client/src/services/tree.ts @@ -26,21 +26,12 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root } const path = notePath.split("/").reverse(); - - if (!path.includes("root")) { - path.push("root"); - } - const effectivePathSegments: string[] = []; let childNoteId: string | null = null; let i = 0; - while (true) { - if (i >= path.length) { - break; - } - - const parentNoteId = path[i++]; + for (let i = 0; i < path.length; i++) { + const parentNoteId = path[i]; if (childNoteId !== null) { const child = await froca.getNote(childNoteId, !logErrors); @@ -65,7 +56,7 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root return null; } - if (!parents.some((p) => p.noteId === parentNoteId)) { + if (!parents.some(p => p.noteId === parentNoteId) || (i === path.length - 1 && parentNoteId !== 'root')) { if (logErrors) { const parent = froca.getNoteFromCache(parentNoteId); @@ -77,7 +68,8 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root ); } - const bestNotePath = child.getBestNotePath(hoistedNoteId); + const activeNotePath = appContext.tabManager.getActiveContextNotePath(); + const bestNotePath = child.getBestNotePath(hoistedNoteId, activeNotePath); if (bestNotePath) { const pathToRoot = bestNotePath.reverse().slice(1); @@ -108,7 +100,9 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root if (!note) { throw new Error(`Unable to find note: ${notePath}.`); } - const bestNotePath = note.getBestNotePath(hoistedNoteId); + + const activeNotePath = appContext.tabManager.getActiveContextNotePath(); + const bestNotePath = note.getBestNotePath(hoistedNoteId, activeNotePath); if (!bestNotePath) { throw new Error(`Did not find any path segments for '${note.toString()}', hoisted note '${hoistedNoteId}'`); diff --git a/apps/client/src/services/utils.ts b/apps/client/src/services/utils.ts index 0f17bdc79..f5e037be5 100644 --- a/apps/client/src/services/utils.ts +++ b/apps/client/src/services/utils.ts @@ -11,7 +11,11 @@ export function reloadFrontendApp(reason?: string) { logInfo(`Frontend app reload: ${reason}`); } - window.location.reload(); + if (isElectron()) { + dynamicRequire("@electron/remote").BrowserWindow.getFocusedWindow()?.reload(); + } else { + window.location.reload(); + } } export function restartDesktopApp() { diff --git a/apps/client/src/share.ts b/apps/client/src/share.ts deleted file mode 100644 index b438f0c0c..000000000 --- a/apps/client/src/share.ts +++ /dev/null @@ -1,84 +0,0 @@ -import "normalize.css"; -import "boxicons/css/boxicons.min.css"; -import "@triliumnext/ckeditor5/src/theme/ck-content.css"; -import "@triliumnext/share-theme/styles/index.css"; -import "@triliumnext/share-theme/scripts/index.js"; - -async function ensureJQuery() { - const $ = (await import("jquery")).default; - (window as any).$ = $; -} - -async function applyMath() { - const anyMathBlock = document.querySelector("#content .math-tex"); - if (!anyMathBlock) { - return; - } - - const renderMathInElement = (await import("./services/math.js")).renderMathInElement; - renderMathInElement(document.getElementById("content")); -} - -async function formatCodeBlocks() { - const anyCodeBlock = document.querySelector("#content pre"); - if (!anyCodeBlock) { - return; - } - await ensureJQuery(); - const { formatCodeBlocks } = await import("./services/syntax_highlight.js"); - await formatCodeBlocks($("#content")); -} - -async function setupTextNote() { - formatCodeBlocks(); - applyMath(); - - const setupMermaid = (await import("./share/mermaid.js")).default; - setupMermaid(); -} - -/** - * Fetch note with given ID from backend - * - * @param noteId of the given note to be fetched. If false, fetches current note. - */ -async function fetchNote(noteId: string | null = null) { - if (!noteId) { - noteId = document.body.getAttribute("data-note-id"); - } - - const resp = await fetch(`api/notes/${noteId}`); - - return await resp.json(); -} - -document.addEventListener( - "DOMContentLoaded", - () => { - const noteType = determineNoteType(); - - if (noteType === "text") { - setupTextNote(); - } - - const toggleMenuButton = document.getElementById("toggleMenuButton"); - const layout = document.getElementById("layout"); - - if (toggleMenuButton && layout) { - toggleMenuButton.addEventListener("click", () => layout.classList.toggle("showMenu")); - } - }, - false -); - -function determineNoteType() { - const bodyClass = document.body.className; - const match = bodyClass.match(/type-([^\s]+)/); - return match ? match[1] : null; -} - -// workaround to prevent webpack from removing "fetchNote" as dead code: -// add fetchNote as property to the window object -Object.defineProperty(window, "fetchNote", { - value: fetchNote -}); diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index 7f67e4827..1f4152792 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -2034,9 +2034,9 @@ body.zen #right-pane, body.zen #mobile-sidebar-wrapper, body.zen .tab-row-container, body.zen .tab-row-widget, -body.zen .ribbon-container:not(:has(.classic-toolbar-widget.visible)), -body.zen .ribbon-container:has(.classic-toolbar-widget.visible) .ribbon-top-row, -body.zen .ribbon-container .ribbon-body:not(:has(.classic-toolbar-widget.visible)), +body.zen .ribbon-container:not(:has(.classic-toolbar-widget)), +body.zen .ribbon-container:has(.classic-toolbar-widget) .ribbon-top-row, +body.zen .ribbon-container .ribbon-body:not(:has(.classic-toolbar-widget)), body.zen .note-icon-widget, body.zen .title-row .icon-action, body.zen .floating-buttons-children > *:not(.bx-edit-alt), diff --git a/apps/client/src/translations/cn/translation.json b/apps/client/src/translations/cn/translation.json index c7053e709..e9738c25a 100644 --- a/apps/client/src/translations/cn/translation.json +++ b/apps/client/src/translations/cn/translation.json @@ -51,7 +51,7 @@ "bulk_actions_executed": "批量操作已成功执行。", "none_yet": "暂无操作 ... 通过点击上方的可用操作添加一个操作。", "labels": "标签", - "relations": "关联关系", + "relations": "关系", "notes": "笔记", "other": "其它" }, @@ -104,7 +104,8 @@ "export_status": "导出状态", "export_in_progress": "导出进行中:{{progressCount}}", "export_finished_successfully": "导出成功完成。", - "format_pdf": "PDF - 用于打印或共享目的。" + "format_pdf": "PDF - 用于打印或共享目的。", + "share-format": "HTML 网页发布——采用与共享笔记相同的主题,但可发布为静态网站。" }, "help": { "noteNavigation": "笔记导航", @@ -184,7 +185,8 @@ }, "import-status": "导入状态", "in-progress": "导入进行中:{{progress}}", - "successful": "导入成功完成。" + "successful": "导入成功完成。", + "importZipRecommendation": "导入 ZIP 文件时,笔记层级将反映压缩文件内的子目录结构。" }, "include_note": { "dialog_title": "包含笔记", @@ -259,7 +261,6 @@ "delete_all_revisions": "删除此笔记的所有修订版本", "delete_all_button": "删除所有修订版本", "help_title": "关于笔记修订版本的帮助", - "revision_last_edited": "此修订版本上次编辑于 {{date}}", "confirm_delete_all": "您是否要删除此笔记的所有修订版本?", "no_revisions": "此笔记暂无修订版本...", "restore_button": "恢复", @@ -1558,7 +1559,9 @@ "window-on-top": "保持此窗口置顶" }, "note_detail": { - "could_not_find_typewidget": "找不到类型为 '{{type}}' 的 typeWidget" + "could_not_find_typewidget": "找不到类型为 '{{type}}' 的 typeWidget", + "printing": "正在打印…", + "printing_pdf": "正在导出为PDF…" }, "note_title": { "placeholder": "请输入笔记标题..." diff --git a/apps/client/src/translations/de/translation.json b/apps/client/src/translations/de/translation.json index b3f4c9a46..6d4790da8 100644 --- a/apps/client/src/translations/de/translation.json +++ b/apps/client/src/translations/de/translation.json @@ -4,7 +4,7 @@ "homepage": "Startseite:", "app_version": "App-Version:", "db_version": "DB-Version:", - "sync_version": "Synch-version:", + "sync_version": "Sync-Version:", "build_date": "Build-Datum:", "build_revision": "Build-Revision:", "data_directory": "Datenverzeichnis:" @@ -104,7 +104,8 @@ "export_status": "Exportstatus", "export_in_progress": "Export läuft: {{progressCount}}", "export_finished_successfully": "Der Export wurde erfolgreich abgeschlossen.", - "format_pdf": "PDF - für Ausdrucke oder Teilen." + "format_pdf": "PDF - für Ausdrucke oder Teilen.", + "share-format": "HTML für die Web-Veröffentlichung – verwendet dasselbe Theme wie bei freigegebenen Notizen, kann jedoch als statische Website veröffentlicht werden." }, "help": { "noteNavigation": "Notiz Navigation", @@ -260,7 +261,6 @@ "delete_all_revisions": "Lösche alle Revisionen dieser Notiz", "delete_all_button": "Alle Revisionen löschen", "help_title": "Hilfe zu Notizrevisionen", - "revision_last_edited": "Diese Revision wurde zuletzt am {{date}} bearbeitet", "confirm_delete_all": "Möchtest du alle Revisionen dieser Notiz löschen?", "no_revisions": "Für diese Notiz gibt es noch keine Revisionen...", "confirm_restore": "Möchtest du diese Revision wiederherstellen? Dadurch werden der aktuelle Titel und Inhalt der Notiz mit dieser Revision überschrieben.", @@ -991,7 +991,7 @@ "enter_password_instruction": "Um die geschützte Notiz anzuzeigen, musst du dein Passwort eingeben:", "start_session_button": "Starte eine geschützte Sitzung Eingabetaste", "started": "Geschützte Sitzung gestartet.", - "wrong_password": "Passwort flasch.", + "wrong_password": "Passwort falsch.", "protecting-finished-successfully": "Geschützt erfolgreich beendet.", "unprotecting-finished-successfully": "Ungeschützt erfolgreich beendet.", "protecting-in-progress": "Schützen läuft: {{count}}", diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 1949d3357..78056e19a 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -104,7 +104,8 @@ "export_status": "Export status", "export_in_progress": "Export in progress: {{progressCount}}", "export_finished_successfully": "Export finished successfully.", - "format_pdf": "PDF - for printing or sharing purposes." + "format_pdf": "PDF - for printing or sharing purposes.", + "share-format": "HTML for web publishing - uses the same theme that is used shared notes, but can be published as a static website." }, "help": { "title": "Cheatsheet", @@ -260,7 +261,6 @@ "delete_all_revisions": "Delete all revisions of this note", "delete_all_button": "Delete all revisions", "help_title": "Help on Note Revisions", - "revision_last_edited": "This revision was last edited on {{date}}", "confirm_delete_all": "Do you want to delete all revisions of this note?", "no_revisions": "No revisions for this note yet...", "restore_button": "Restore", diff --git a/apps/client/src/translations/es/translation.json b/apps/client/src/translations/es/translation.json index e07ce8036..fe2f00dc0 100644 --- a/apps/client/src/translations/es/translation.json +++ b/apps/client/src/translations/es/translation.json @@ -104,7 +104,8 @@ "export_status": "Estado de exportación", "export_in_progress": "Exportación en curso: {{progressCount}}", "export_finished_successfully": "La exportación finalizó exitosamente.", - "format_pdf": "PDF - para propósitos de impresión o compartición." + "format_pdf": "PDF - para propósitos de impresión o compartición.", + "share-format": "HTML para publicación web: utiliza el mismo tema que se utiliza en las notas compartidas, pero se puede publicar como un sitio web estático." }, "help": { "noteNavigation": "Navegación de notas", @@ -184,7 +185,8 @@ }, "import-status": "Estado de importación", "in-progress": "Importación en progreso: {{progress}}", - "successful": "Importación finalizada exitosamente." + "successful": "Importación finalizada exitosamente.", + "importZipRecommendation": "Al importar un archivo ZIP, la jerarquía de notas reflejará la estructura de subdirectorios dentro del archivo comprimido." }, "include_note": { "dialog_title": "Incluir nota", @@ -259,7 +261,6 @@ "delete_all_revisions": "Eliminar todas las revisiones de esta nota", "delete_all_button": "Eliminar todas las revisiones", "help_title": "Ayuda sobre revisiones de notas", - "revision_last_edited": "Esta revisión se editó por última vez en {{date}}", "confirm_delete_all": "¿Quiere eliminar todas las revisiones de esta nota?", "no_revisions": "Aún no hay revisiones para esta nota...", "restore_button": "Restaurar", @@ -1715,7 +1716,9 @@ "window-on-top": "Mantener esta ventana en la parte superior" }, "note_detail": { - "could_not_find_typewidget": "No se pudo encontrar typeWidget para el tipo '{{type}}'" + "could_not_find_typewidget": "No se pudo encontrar typeWidget para el tipo '{{type}}'", + "printing": "Impresión en curso...", + "printing_pdf": "Exportando a PDF en curso.." }, "note_title": { "placeholder": "escriba el título de la nota aquí..." diff --git a/apps/client/src/translations/fr/translation.json b/apps/client/src/translations/fr/translation.json index 926307d18..84593207b 100644 --- a/apps/client/src/translations/fr/translation.json +++ b/apps/client/src/translations/fr/translation.json @@ -260,7 +260,6 @@ "delete_all_revisions": "Supprimer toutes les versions de cette note", "delete_all_button": "Supprimer toutes les versions", "help_title": "Aide sur les versions de notes", - "revision_last_edited": "Cette version a été modifiée pour la dernière fois le {{date}}", "confirm_delete_all": "Voulez-vous supprimer toutes les versions de cette note ?", "no_revisions": "Aucune version pour cette note pour l'instant...", "confirm_restore": "Voulez-vous restaurer cette version ? Le titre et le contenu actuels de la note seront écrasés par cette version.", diff --git a/apps/client/src/translations/hi/translation.json b/apps/client/src/translations/hi/translation.json new file mode 100644 index 000000000..2d1c3b9f1 --- /dev/null +++ b/apps/client/src/translations/hi/translation.json @@ -0,0 +1,5 @@ +{ + "about": { + "title": "ट्रिलियम नोट्स के बारें में" + } +} diff --git a/apps/client/src/translations/it/translation.json b/apps/client/src/translations/it/translation.json index a49a9a5dc..d8bf6bad6 100644 --- a/apps/client/src/translations/it/translation.json +++ b/apps/client/src/translations/it/translation.json @@ -867,7 +867,6 @@ "delete_all_revisions": "Elimina tutte le revisioni di questa nota", "delete_all_button": "Elimina tutte le revisioni", "help_title": "Aiuto sulle revisioni delle note", - "revision_last_edited": "Questa revisione è stata modificata l'ultima volta il {{date}}", "confirm_delete_all": "Vuoi eliminare tutte le revisioni di questa nota?", "no_revisions": "Ancora nessuna revisione per questa nota...", "restore_button": "Ripristina", diff --git a/apps/client/src/translations/ja/translation.json b/apps/client/src/translations/ja/translation.json index 1f81a4a4f..05c8b48f9 100644 --- a/apps/client/src/translations/ja/translation.json +++ b/apps/client/src/translations/ja/translation.json @@ -254,7 +254,8 @@ "export_status": "エクスポート状況", "export_in_progress": "エクスポート処理中: {{progressCount}}", "export_finished_successfully": "エクスポートが正常に完了しました。", - "format_pdf": "PDF - 印刷または共有目的に。" + "format_pdf": "PDF - 印刷または共有目的に。", + "share-format": "Web 公開用の HTML - 共有ノートで使用されるのと同じテーマを使用しますが、静的 Web サイトとして公開できます。" }, "help": { "title": "チートシート", @@ -610,7 +611,6 @@ "delete_all_revisions": "このノートの変更履歴をすべて削除", "delete_all_button": "変更履歴をすべて削除", "help_title": "変更履歴のヘルプ", - "revision_last_edited": "この変更は{{date}}に行われました", "confirm_delete_all": "このノートのすべての変更履歴を削除しますか?", "no_revisions": "このノートに変更履歴はまだありません...", "restore_button": "復元", diff --git a/apps/client/src/translations/mr/translation.json b/apps/client/src/translations/mr/translation.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/apps/client/src/translations/mr/translation.json @@ -0,0 +1 @@ +{} diff --git a/apps/client/src/translations/pl/translation.json b/apps/client/src/translations/pl/translation.json index 1d90a30e8..426296d14 100644 --- a/apps/client/src/translations/pl/translation.json +++ b/apps/client/src/translations/pl/translation.json @@ -912,7 +912,6 @@ "delete_all_revisions": "Usuń wszystkie wersje tej notatki", "delete_all_button": "Usuń wszystkie wersje", "help_title": "Pomoc dotycząca wersji notatki", - "revision_last_edited": "Ta wersja była ostatnio edytowana {{date}}", "confirm_delete_all": "Czy chcesz usunąć wszystkie wersje tej notatki?", "no_revisions": "Brak wersji dla tej notatki...", "restore_button": "Przywróć", diff --git a/apps/client/src/translations/pt/translation.json b/apps/client/src/translations/pt/translation.json index b4b1366bb..f386f61e8 100644 --- a/apps/client/src/translations/pt/translation.json +++ b/apps/client/src/translations/pt/translation.json @@ -259,7 +259,6 @@ "delete_all_revisions": "Apagar todas as versões desta nota", "delete_all_button": "Apagar todas as versões", "help_title": "Ajuda sobre as versões da nota", - "revision_last_edited": "Esta versão foi editada pela última vez em {{date}}", "confirm_delete_all": "Quer apagar todas as versões desta nota?", "no_revisions": "Ainda não há versões para esta nota...", "restore_button": "Recuperar", diff --git a/apps/client/src/translations/pt_br/translation.json b/apps/client/src/translations/pt_br/translation.json index 7c51d7c2a..08d891356 100644 --- a/apps/client/src/translations/pt_br/translation.json +++ b/apps/client/src/translations/pt_br/translation.json @@ -415,7 +415,6 @@ "delete_all_revisions": "Excluir todas as versões desta nota", "delete_all_button": "Excluir todas as versões", "help_title": "Ajuda sobre as versões da nota", - "revision_last_edited": "Esta versão foi editada pela última vez em {{date}}", "confirm_delete_all": "Você quer excluir todas as versões desta nota?", "no_revisions": "Ainda não há versões para esta nota...", "restore_button": "Recuperar", diff --git a/apps/client/src/translations/ro/translation.json b/apps/client/src/translations/ro/translation.json index f35d2ce89..c683aba59 100644 --- a/apps/client/src/translations/ro/translation.json +++ b/apps/client/src/translations/ro/translation.json @@ -1090,7 +1090,6 @@ "preview_not_available": "Nu este disponibilă o previzualizare pentru acest tip de notiță.", "restore_button": "Restaurează", "revision_deleted": "Revizia notiței a fost ștearsă.", - "revision_last_edited": "Revizia a fost ultima oară modificată pe {{date}}", "revision_restored": "Revizia notiței a fost restaurată.", "revisions_deleted": "Notița reviziei a fost ștearsă.", "maximum_revisions": "Numărul maxim de revizii pentru notița curentă: {{number}}.", diff --git a/apps/client/src/translations/ru/translation.json b/apps/client/src/translations/ru/translation.json index eeee4b28f..c1e62e327 100644 --- a/apps/client/src/translations/ru/translation.json +++ b/apps/client/src/translations/ru/translation.json @@ -366,7 +366,6 @@ "delete_all_button": "Удалить все версии", "help_title": "Помощь по версиям заметок", "confirm_delete_all": "Вы хотите удалить все версии этой заметки?", - "revision_last_edited": "Эта версия последний раз редактировалась {{date}}", "confirm_restore": "Хотите восстановить эту версию? Текущее название и содержание заметки будут перезаписаны этой версией.", "confirm_delete": "Вы хотите удалить эту версию?", "revisions_deleted": "Версии заметки были удалены.", diff --git a/apps/client/src/translations/sr/translation.json b/apps/client/src/translations/sr/translation.json index dd0ff6ff9..df88fdcda 100644 --- a/apps/client/src/translations/sr/translation.json +++ b/apps/client/src/translations/sr/translation.json @@ -256,7 +256,6 @@ "delete_all_revisions": "Obriši sve revizije ove beleške", "delete_all_button": "Obriši sve revizije", "help_title": "Pomoć za Revizije beleški", - "revision_last_edited": "Ova revizija je poslednji put izmenjena {{date}}", "confirm_delete_all": "Da li želite da obrišete sve revizije ove beleške?", "no_revisions": "Još uvek nema revizija za ovu belešku...", "restore_button": "Vrati", diff --git a/apps/client/src/translations/tw/translation.json b/apps/client/src/translations/tw/translation.json index ea0e021e5..e31228844 100644 --- a/apps/client/src/translations/tw/translation.json +++ b/apps/client/src/translations/tw/translation.json @@ -104,7 +104,8 @@ "export_in_progress": "正在匯出:{{progressCount}}", "export_finished_successfully": "成功匯出。", "format_html": "HTML - 推薦,因為它保留了所有格式", - "format_pdf": "PDF - 用於列印或與他人分享。" + "format_pdf": "PDF - 用於列印或與他人分享。", + "share-format": "HTML 網頁發佈——使用與共享筆記相同的佈景主題,但可發佈為靜態網站。" }, "help": { "noteNavigation": "筆記導航", @@ -260,7 +261,6 @@ "delete_all_revisions": "刪除此筆記的所有歷史版本", "delete_all_button": "刪除所有歷史版本", "help_title": "關於筆記歷史版本的說明", - "revision_last_edited": "此歷史版本上次於 {{date}} 編輯", "confirm_delete_all": "您是否要刪除此筆記的所有歷史版本?", "no_revisions": "此筆記暫無歷史版本…", "confirm_restore": "您是否要還原此歷史版本?這將使用此歷史版本覆寫筆記的目前標題和內容。", diff --git a/apps/client/src/translations/uk/translation.json b/apps/client/src/translations/uk/translation.json index b35c6c826..9c2a1eca1 100644 --- a/apps/client/src/translations/uk/translation.json +++ b/apps/client/src/translations/uk/translation.json @@ -309,7 +309,6 @@ "delete_all_revisions": "Видалити всі версії цієї нотатки", "delete_all_button": "Видалити всі версії", "help_title": "Довідка щодо Версій нотаток", - "revision_last_edited": "Цю версію востаннє редагували {{date}}", "confirm_delete_all": "Ви хочете видалити всі версії цієї нотатки?", "no_revisions": "Поки що немає версій цієї нотатки...", "restore_button": "Відновити", diff --git a/apps/client/src/types.d.ts b/apps/client/src/types.d.ts index c5a93bd0a..d283983b4 100644 --- a/apps/client/src/types.d.ts +++ b/apps/client/src/types.d.ts @@ -26,7 +26,6 @@ interface CustomGlobals { appContext: AppContext; froca: Froca; treeCache: Froca; - importMarkdownInline: () => Promise; SEARCH_HELP_TEXT: string; activeDialog: JQuery | null; componentId: string; diff --git a/apps/client/src/widgets/dialogs/export.tsx b/apps/client/src/widgets/dialogs/export.tsx index dded32624..b694d9abe 100644 --- a/apps/client/src/widgets/dialogs/export.tsx +++ b/apps/client/src/widgets/dialogs/export.tsx @@ -79,6 +79,7 @@ export default function ExportDialog() { values={[ { value: "html", label: t("export.format_html_zip") }, { value: "markdown", label: t("export.format_markdown") }, + { value: "share", label: t("export.share-format") }, { value: "opml", label: t("export.format_opml") } ]} /> diff --git a/apps/client/src/widgets/dialogs/markdown_import.tsx b/apps/client/src/widgets/dialogs/markdown_import.tsx index d14d6fb11..43b20d378 100644 --- a/apps/client/src/widgets/dialogs/markdown_import.tsx +++ b/apps/client/src/widgets/dialogs/markdown_import.tsx @@ -7,6 +7,7 @@ import utils from "../../services/utils"; import Modal from "../react/Modal"; import Button from "../react/Button"; import { useTriliumEvent } from "../react/hooks"; +import EditableTextTypeWidget from "../type_widgets/editable_text"; interface RenderMarkdownResponse { htmlContent: string; @@ -14,39 +15,34 @@ interface RenderMarkdownResponse { export default function MarkdownImportDialog() { const markdownImportTextArea = useRef(null); + const [textTypeWidget, setTextTypeWidget] = useState(); const [ text, setText ] = useState(""); const [ shown, setShown ] = useState(false); - const triggerImport = useCallback(() => { - if (appContext.tabManager.getActiveContextNoteType() !== "text") { - return; - } - + useTriliumEvent("showPasteMarkdownDialog", ({ textTypeWidget }) => { + setTextTypeWidget(textTypeWidget); if (utils.isElectron()) { const { clipboard } = utils.dynamicRequire("electron"); const text = clipboard.readText(); - convertMarkdownToHtml(text); + convertMarkdownToHtml(text, textTypeWidget); } else { setShown(true); } - }, []); - - useTriliumEvent("importMarkdownInline", triggerImport); - useTriliumEvent("pasteMarkdownIntoText", triggerImport); - - async function sendForm() { - await convertMarkdownToHtml(text); - setText(""); - setShown(false); - } + }); return ( } + footer={