Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
joplin / usr / lib / joplin / resources / app / InteropServiceHelper.js
Size: Mime:
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const InteropService_1 = require("@joplin/lib/services/interop/InteropService");
const CommandService_1 = require("@joplin/lib/services/CommandService");
const shim_1 = require("@joplin/lib/shim");
const types_1 = require("@joplin/lib/services/interop/types");
const locale_1 = require("@joplin/lib/locale");
const bridge_1 = require("./services/bridge");
const Setting_1 = require("@joplin/lib/models/Setting");
const Note_1 = require("@joplin/lib/models/Note");
const { friendlySafeFilename } = require('@joplin/lib/path-utils');
const time_1 = require("@joplin/lib/time");
const md5 = require('md5');
const url = require('url');
class InteropServiceHelper {
    static exportNoteToHtmlFile(noteId, exportOptions) {
        return __awaiter(this, void 0, void 0, function* () {
            const tempFile = `${Setting_1.default.value('tempDir')}/${md5(Date.now() + Math.random())}.html`;
            const fullExportOptions = Object.assign({ path: tempFile, format: types_1.ExportModuleOutputFormat.Html, target: types_1.FileSystemItem.File, sourceNoteIds: [noteId], customCss: '' }, exportOptions);
            const service = InteropService_1.default.instance();
            const result = yield service.export(fullExportOptions);
            // eslint-disable-next-line no-console
            console.info('Export HTML result: ', result);
            return tempFile;
        });
    }
    static exportNoteTo_(target, noteId, options = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            let win = null;
            let htmlFile = null;
            const cleanup = () => {
                if (win)
                    win.destroy();
                if (htmlFile)
                    void shim_1.default.fsDriver().remove(htmlFile);
            };
            try {
                const exportOptions = {
                    customCss: options.customCss ? options.customCss : '',
                    plugins: options.plugins,
                };
                htmlFile = yield this.exportNoteToHtmlFile(noteId, exportOptions);
                const windowOptions = {
                    show: false,
                };
                win = (0, bridge_1.default)().newBrowserWindow(windowOptions);
                // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
                return new Promise((resolve, reject) => {
                    win.webContents.on('did-finish-load', () => {
                        // did-finish-load will trigger when most assets are done loading, probably
                        // images, JavaScript and CSS. However it seems it might trigger *before*
                        // all fonts are loaded, which will break for example Katex rendering.
                        // So we need to add an additional timer to make sure fonts are loaded
                        // as it doesn't seem there's any easy way to figure that out.
                        shim_1.default.setTimeout(() => __awaiter(this, void 0, void 0, function* () {
                            if (target === 'pdf') {
                                try {
                                    // The below line "opens" all <details> tags
                                    // before printing. This assures that the
                                    // contents of the tag are visible in printed
                                    // pdfs.
                                    // https://github.com/laurent22/joplin/issues/6254.
                                    yield win.webContents.executeJavaScript('document.querySelectorAll(\'details\').forEach(el=>el.setAttribute(\'open\',\'\'))');
                                    // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
                                    const data = yield win.webContents.printToPDF(options);
                                    resolve(data);
                                }
                                catch (error) {
                                    reject(error);
                                }
                                finally {
                                    cleanup();
                                }
                            }
                            else {
                                // TODO: it is crashing at this point :( Appears to
                                // be a Chromium bug:
                                // https://github.com/electron/electron/issues/19946
                                // Maybe can be fixed by doing everything from main
                                // process? i.e. creating a function `print()` that
                                // takes the `htmlFile` variable as input.
                                //
                                // 2021-10-01: This old bug is fixed, and has been
                                // replaced by a brand new bug:
                                // https://github.com/electron/electron/issues/28192
                                // Still doesn't work but at least it doesn't crash
                                // the app.
                                //
                                // 2024-01-31: Printing with webContents.print still
                                // fails on Linux (even if run in the main process).
                                // As such, we use window.print(), which seems to work.
                                if (shim_1.default.isLinux()) {
                                    yield win.webContents.executeJavaScript(`
									// Blocks while the print dialog is open
									window.print();
								`);
                                    shim_1.default.setTimeout(() => {
                                        // To prevent a crash, the window can only be closed after a timeout.
                                        // This timeout can't be too small, or else it may still crash (e.g. 100ms
                                        // is too short).
                                        //
                                        // See https://github.com/electron/electron/issues/31635 for details
                                        cleanup();
                                        resolve(null);
                                    }, 1000);
                                }
                                else {
                                    // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
                                    win.webContents.print(options, (success, reason) => {
                                        cleanup();
                                        if (!success && reason !== 'cancelled')
                                            reject(new Error(`Could not print: ${reason}`));
                                        resolve(null);
                                    });
                                }
                            }
                        }), 2000);
                    });
                    void win.loadURL(url.format({
                        pathname: htmlFile,
                        protocol: 'file:',
                        slashes: true,
                    }));
                });
            }
            catch (error) {
                cleanup();
                throw error;
            }
        });
    }
    static exportNoteToPdf(noteId, options = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            return this.exportNoteTo_('pdf', noteId, options);
        });
    }
    static printNote(noteId, options = {}) {
        return __awaiter(this, void 0, void 0, function* () {
            return this.exportNoteTo_('printer', noteId, options);
        });
    }
    static defaultFilename(noteId, fileExtension) {
        return __awaiter(this, void 0, void 0, function* () {
            // Default filename is just the date
            const date = time_1.default.formatMsToLocal(new Date().getTime(), time_1.default.dateFormat());
            let filename = friendlySafeFilename(`${date}`, 100);
            if (noteId) {
                const note = yield Note_1.default.load(noteId);
                // In a rare case the passed note will be null, use the id for filename
                filename = friendlySafeFilename(note ? note.title : noteId, 100);
            }
            return `${filename}.${fileExtension}`;
        });
    }
    // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
    static export(_dispatch, module, options = null) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!options)
                options = {};
            let path = null;
            if (module.target === 'file') {
                const noteId = options.sourceNoteIds && options.sourceNoteIds.length ? options.sourceNoteIds[0] : null;
                path = yield (0, bridge_1.default)().showSaveDialog({
                    filters: [{ name: module.description, extensions: module.fileExtensions }],
                    defaultPath: yield this.defaultFilename(noteId, module.fileExtensions[0]),
                });
            }
            else {
                path = yield (0, bridge_1.default)().showOpenDialog({
                    properties: ['openDirectory', 'createDirectory'],
                });
            }
            if (!path || (Array.isArray(path) && !path.length))
                return;
            if (Array.isArray(path))
                path = path[0];
            void CommandService_1.default.instance().execute('showModalMessage', (0, locale_1._)('Exporting to "%s" as "%s" format. Please wait...', path, module.format));
            const exportOptions = {};
            exportOptions.path = path;
            exportOptions.format = module.format;
            // exportOptions.modulePath = module.path;
            if (options.plugins)
                exportOptions.plugins = options.plugins;
            exportOptions.customCss = options.customCss;
            exportOptions.target = module.target;
            exportOptions.includeConflicts = !!options.includeConflicts;
            if (options.sourceFolderIds)
                exportOptions.sourceFolderIds = options.sourceFolderIds;
            if (options.sourceNoteIds)
                exportOptions.sourceNoteIds = options.sourceNoteIds;
            const service = InteropService_1.default.instance();
            try {
                const result = yield service.export(exportOptions);
                // eslint-disable-next-line no-console
                console.info('Export result: ', result);
            }
            catch (error) {
                console.error(error);
                (0, bridge_1.default)().showErrorMessageBox((0, locale_1._)('Could not export notes: %s', error.message));
            }
            void CommandService_1.default.instance().execute('hideModalMessage');
        });
    }
}
exports.default = InteropServiceHelper;
//# sourceMappingURL=InteropServiceHelper.js.map