mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 21:19:01 +01:00 
			
		
		
		
	Merge branch 'develop' of https://github.com/TriliumNext/Notes into develop
This commit is contained in:
		
						commit
						2659bd33e8
					
				@ -83,7 +83,7 @@ export type CommandMappings = {
 | 
			
		||||
    };
 | 
			
		||||
    showExportDialog: CommandData & {
 | 
			
		||||
        notePath: string;
 | 
			
		||||
        defaultType: "single";
 | 
			
		||||
        defaultType: "single" | "subtree";
 | 
			
		||||
    };
 | 
			
		||||
    showDeleteNotesDialog: CommandData & {
 | 
			
		||||
        branchIdsToDelete: string[];
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
import treeService from "../../services/tree.js";
 | 
			
		||||
import utils from "../../services/utils.js";
 | 
			
		||||
import ws from "../../services/ws.js";
 | 
			
		||||
import toastService from "../../services/toast.js";
 | 
			
		||||
import toastService, { type ToastOptions } from "../../services/toast.js";
 | 
			
		||||
import froca from "../../services/froca.js";
 | 
			
		||||
import openService from "../../services/open.js";
 | 
			
		||||
import BasicWidget from "../basic_widget.js";
 | 
			
		||||
import { t } from "../../services/i18n.js";
 | 
			
		||||
import type { EventData } from "../../components/app_context.js";
 | 
			
		||||
 | 
			
		||||
const TPL = `
 | 
			
		||||
<div class="export-dialog modal fade mx-auto" tabindex="-1" role="dialog">
 | 
			
		||||
@ -105,6 +106,13 @@ const TPL = `
 | 
			
		||||
                                ${t("export.format_markdown")}
 | 
			
		||||
                            </label>
 | 
			
		||||
                        </div>
 | 
			
		||||
 | 
			
		||||
                        <div class="form-check">
 | 
			
		||||
                            <label class="form-check-label tn-radio">
 | 
			
		||||
                                <input class="form-check-input" type="radio" name="export-single-format" value="pdf">
 | 
			
		||||
                                ${t("export.format_pdf")}
 | 
			
		||||
                            </label>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="modal-footer">
 | 
			
		||||
@ -116,6 +124,19 @@ const TPL = `
 | 
			
		||||
</div>`;
 | 
			
		||||
 | 
			
		||||
export default class ExportDialog extends BasicWidget {
 | 
			
		||||
 | 
			
		||||
    private taskId: string;
 | 
			
		||||
    private branchId: string | null;
 | 
			
		||||
    private modal?: bootstrap.Modal;
 | 
			
		||||
    private $form!: JQuery<HTMLElement>;
 | 
			
		||||
    private $noteTitle!: JQuery<HTMLElement>;
 | 
			
		||||
    private $subtreeFormats!: JQuery<HTMLElement>;
 | 
			
		||||
    private $singleFormats!: JQuery<HTMLElement>;
 | 
			
		||||
    private $subtreeType!: JQuery<HTMLElement>;
 | 
			
		||||
    private $singleType!: JQuery<HTMLElement>;
 | 
			
		||||
    private $exportButton!: JQuery<HTMLElement>;
 | 
			
		||||
    private $opmlVersions!: JQuery<HTMLElement>;
 | 
			
		||||
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
@ -125,6 +146,8 @@ export default class ExportDialog extends BasicWidget {
 | 
			
		||||
 | 
			
		||||
    doRender() {
 | 
			
		||||
        this.$widget = $(TPL);
 | 
			
		||||
        // Remove once bootstrap is fixed.
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
 | 
			
		||||
        this.$form = this.$widget.find(".export-form");
 | 
			
		||||
        this.$noteTitle = this.$widget.find(".export-note-title");
 | 
			
		||||
@ -136,7 +159,7 @@ export default class ExportDialog extends BasicWidget {
 | 
			
		||||
        this.$opmlVersions = this.$widget.find(".opml-versions");
 | 
			
		||||
 | 
			
		||||
        this.$form.on("submit", () => {
 | 
			
		||||
            this.modal.hide();
 | 
			
		||||
            this.modal?.hide();
 | 
			
		||||
 | 
			
		||||
            const exportType = this.$widget.find("input[name='export-type']:checked").val();
 | 
			
		||||
 | 
			
		||||
@ -149,13 +172,15 @@ export default class ExportDialog extends BasicWidget {
 | 
			
		||||
 | 
			
		||||
            const exportVersion = exportFormat === "opml" ? this.$widget.find("input[name='opml-version']:checked").val() : "1.0";
 | 
			
		||||
 | 
			
		||||
            this.exportBranch(this.branchId, exportType, exportFormat, exportVersion);
 | 
			
		||||
            if (this.branchId) {
 | 
			
		||||
                this.exportBranch(this.branchId, String(exportType), String(exportFormat), String(exportVersion));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.$widget.find("input[name=export-type]").on("change", (e) => {
 | 
			
		||||
            if (e.currentTarget.value === "subtree") {
 | 
			
		||||
            if ((e.currentTarget as HTMLInputElement).value === "subtree") {
 | 
			
		||||
                if (this.$widget.find("input[name=export-subtree-format]:checked").length === 0) {
 | 
			
		||||
                    this.$widget.find("input[name=export-subtree-format]:first").prop("checked", true);
 | 
			
		||||
                }
 | 
			
		||||
@ -173,7 +198,7 @@ export default class ExportDialog extends BasicWidget {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.$widget.find("input[name=export-subtree-format]").on("change", (e) => {
 | 
			
		||||
            if (e.currentTarget.value === "opml") {
 | 
			
		||||
            if ((e.currentTarget as HTMLInputElement).value === "opml") {
 | 
			
		||||
                this.$opmlVersions.slideDown();
 | 
			
		||||
            } else {
 | 
			
		||||
                this.$opmlVersions.slideUp();
 | 
			
		||||
@ -181,7 +206,7 @@ export default class ExportDialog extends BasicWidget {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async showExportDialogEvent({ notePath, defaultType }) {
 | 
			
		||||
    async showExportDialogEvent({ notePath, defaultType }: EventData<"showExportDialog">) {
 | 
			
		||||
        this.taskId = "";
 | 
			
		||||
        this.$exportButton.removeAttr("disabled");
 | 
			
		||||
 | 
			
		||||
@ -201,11 +226,15 @@ export default class ExportDialog extends BasicWidget {
 | 
			
		||||
 | 
			
		||||
        const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(notePath);
 | 
			
		||||
 | 
			
		||||
        if (parentNoteId) {
 | 
			
		||||
            this.branchId = await froca.getBranchId(parentNoteId, noteId);
 | 
			
		||||
        }
 | 
			
		||||
        if (noteId) {
 | 
			
		||||
            this.$noteTitle.text(await treeService.getNoteTitle(noteId));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    exportBranch(branchId, type, format, version) {
 | 
			
		||||
    exportBranch(branchId: string, type: string, format: string, version: string) {
 | 
			
		||||
        this.taskId = utils.randomString(10);
 | 
			
		||||
 | 
			
		||||
        const url = openService.getUrlForDownload(`api/branches/${branchId}/export/${type}/${format}/${version}/${this.taskId}`);
 | 
			
		||||
@ -215,12 +244,14 @@ export default class ExportDialog extends BasicWidget {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ws.subscribeToMessages(async (message) => {
 | 
			
		||||
    const makeToast = (id, message) => ({
 | 
			
		||||
    function makeToast(id: string, message: string): ToastOptions {
 | 
			
		||||
        return {
 | 
			
		||||
            id: id,
 | 
			
		||||
            title: t("export.export_status"),
 | 
			
		||||
            message: message,
 | 
			
		||||
            icon: "arrow-square-up-right"
 | 
			
		||||
    });
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (message.taskType !== "export") {
 | 
			
		||||
        return;
 | 
			
		||||
@ -261,6 +261,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
 | 
			
		||||
        const { ipcRenderer } = utils.dynamicRequire("electron");
 | 
			
		||||
        ipcRenderer.send("export-as-pdf", {
 | 
			
		||||
            title: this.note.title,
 | 
			
		||||
            pageSize: this.note.getAttributeValue("label", "pageSize") ?? "Letter",
 | 
			
		||||
            landscape: this.note.hasAttribute("label", "printLandscape")
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -109,7 +109,8 @@
 | 
			
		||||
    "choose_export_type": "Choose export type first please",
 | 
			
		||||
    "export_status": "Export status",
 | 
			
		||||
    "export_in_progress": "Export in progress: {{progressCount}}",
 | 
			
		||||
    "export_finished_successfully": "Export finished successfully."
 | 
			
		||||
    "export_finished_successfully": "Export finished successfully.",
 | 
			
		||||
    "format_pdf": "PDF - for printing or sharing purposes."
 | 
			
		||||
  },
 | 
			
		||||
  "help": {
 | 
			
		||||
    "fullDocumentation": "Help (full documentation is available <a class=\"external\" href=\"https://triliumnext.github.io/Docs/\">online</a>)",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										0
									
								
								src/services/export/pdf.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/services/export/pdf.ts
									
									
									
									
									
										Normal file
									
								
							@ -51,6 +51,7 @@ ipcMain.on("create-extra-window", (event, arg) => {
 | 
			
		||||
interface ExportAsPdfOpts {
 | 
			
		||||
    title: string;
 | 
			
		||||
    landscape: boolean;
 | 
			
		||||
    pageSize: "A0" | "A1" | "A2" | "A3" | "A4" | "A5" | "A6" | "Legal" | "Letter" | "Tabloid" | "Ledger";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ipcMain.on("export-as-pdf", async (e, opts: ExportAsPdfOpts) => {
 | 
			
		||||
@ -76,6 +77,7 @@ ipcMain.on("export-as-pdf", async (e, opts: ExportAsPdfOpts) => {
 | 
			
		||||
    try {
 | 
			
		||||
        buffer = await browserWindow.webContents.printToPDF({
 | 
			
		||||
            landscape: opts.landscape,
 | 
			
		||||
            pageSize: opts.pageSize,
 | 
			
		||||
            generateDocumentOutline: true,
 | 
			
		||||
            generateTaggedPDF: true,
 | 
			
		||||
            displayHeaderFooter: true,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user