import server from "./server.js"; import renderService from "./render.js"; import protectedSessionService from "./protected_session.js"; import protectedSessionHolder from "./protected_session_holder.js"; import libraryLoader from "./library_loader.js"; import openService from "./open.js"; import froca from "./froca.js"; import utils from "./utils.js"; import linkService from "./link.js"; import treeService from "./tree.js"; let idCounter = 1; async function getRenderedContent(note, options = {}) { options = Object.assign({ trim: false, tooltip: false }, options); const type = getRenderingType(note); const $renderedContent = $('
'); if (type === 'text') { const noteComplement = await froca.getNoteComplement(note.noteId); if (!utils.isHtmlEmpty(noteComplement.content)) { $renderedContent.append($('
').html(trim(noteComplement.content, options.trim))); if ($renderedContent.find('span.math-tex').length > 0) { await libraryLoader.requireLibrary(libraryLoader.KATEX); renderMathInElement($renderedContent[0], {trust: true}); } const getNoteIdFromLink = el => treeService.getNoteIdFromNotePath($(el).attr('href')); const referenceLinks = $renderedContent.find("a.reference-link"); const noteIdsToPrefetch = referenceLinks.map(el => getNoteIdFromLink(el)); await froca.getNotes(noteIdsToPrefetch); for (const el of referenceLinks) { const noteId = getNoteIdFromLink(el); await linkService.loadReferenceLinkTitle(noteId, $(el)); } } else { await renderChildrenList($renderedContent, note); } } else if (type === 'code') { const fullNote = await server.get(`notes/${note.noteId}`); $renderedContent.append($("
").text(trim(fullNote.content, options.trim)));
    }
    else if (type === 'image') {
        const sanitizedTitle = note.title.replace(/[^a-z0-9-.]/gi, "");

        $renderedContent.append(
            $("")
                .attr("src", `api/images/${note.noteId}/${sanitizedTitle}`)
                .css("max-width", "100%")
        );
    }
    else if (!options.tooltip && ['file', 'pdf', 'audio', 'video'].includes(type)) {
        const $downloadButton = $('');
        const $openButton = $('');

        $downloadButton.on('click', () => openService.downloadFileNote(note.noteId));
        $openButton.on('click', () => openService.openNoteExternally(note.noteId, note.mime));

        // open doesn't work for protected notes since it works through browser which isn't in protected session
        $openButton.toggle(!note.isProtected);

        const $content = $('
'); if (type === 'pdf') { const $pdfPreview = $(''); $pdfPreview.attr("src", openService.getUrlForDownload(`api/notes/${note.noteId}/open`)); $content.append($pdfPreview); } else if (type === 'audio') { const $audioPreview = $('') .attr("src", openService.getUrlForStreaming(`api/notes/${note.noteId}/open-partial`)) .attr("type", note.mime) .css("width", "100%"); $content.append($audioPreview); } else if (type === 'video') { const $videoPreview = $('') .attr("src", openService.getUrlForDownload(`api/notes/${note.noteId}/open-partial`)) .attr("type", note.mime) .css("width", "100%"); $content.append($videoPreview); } $content.append( $('
') .append($downloadButton) .append($openButton) ); $renderedContent.append($content); } else if (type === 'mermaid') { await libraryLoader.requireLibrary(libraryLoader.MERMAID); const noteComplement = await froca.getNoteComplement(note.noteId); const content = noteComplement.content || ""; $renderedContent .css("display", "flex") .css("justify-content", "space-around"); const documentStyle = window.getComputedStyle(document.documentElement); const mermaidTheme = documentStyle.getPropertyValue('--mermaid-theme'); mermaid.mermaidAPI.initialize({ startOnLoad: false, theme: mermaidTheme.trim(), securityLevel: 'antiscript' }); try { mermaid.mermaidAPI.render("in-mermaid-graph-" + idCounter++, content, content => $renderedContent.append($(content))); } catch (e) { const $error = $("

The diagram could not displayed.

"); $renderedContent.append($error); } } else if (type === 'render') { const $content = $('
'); await renderService.render(note, $content, this.ctx); $renderedContent.append($content); } else if (type === 'canvas') { // make sure surrounding container has size of what is visible. Then image is shrunk to its boundaries $renderedContent.css({height: "100%", width:"100%"}); const noteComplement = await froca.getNoteComplement(note.noteId); const content = noteComplement.content || ""; try { const placeHolderSVG = ""; const data = JSON.parse(content) const svg = data.svg || placeHolderSVG; /** * maxWidth: size down to 100% (full) width of container but do not enlarge! * height:auto to ensure that height scales with width */ $renderedContent.append($(svg).css({maxWidth: "100%", maxHeight: "100%", height: "auto", width: "auto"})); } catch(err) { console.error("error parsing content as JSON", content, err); $renderedContent.append($("
").text("Error parsing content. Please check console.error() for more details.")); } } else if (!options.tooltip && type === 'protectedSession') { const $button = $(``) .on('click', protectedSessionService.enterProtectedSession); $renderedContent.append( $("
") .append("
This note is protected and to access it you need to enter password.
") .append("
") .append($button) ); } else { $renderedContent.append( $("
") .css("text-align", "center") .css("font-size", "500%") .append($("").addClass(note.getIcon())) ); } $renderedContent.addClass(note.getCssClass()); return { $renderedContent, type }; } async function renderChildrenList($renderedContent, note) { $renderedContent.css("padding", "10px"); $renderedContent.addClass("text-with-ellipsis"); let childNoteIds = note.getChildNoteIds(); if (childNoteIds.length > 10) { childNoteIds = childNoteIds.slice(0, 10); } // just load the first 10 child notes const childNotes = await froca.getNotes(childNoteIds); for (const childNote of childNotes) { $renderedContent.append(await linkService.createNoteLink(`${note.noteId}/${childNote.noteId}`, { showTooltip: false, showNoteIcon: true })); $renderedContent.append("
"); } } function trim(text, doTrim) { if (!doTrim) { return text; } else { return text.substr(0, Math.min(text.length, 2000)); } } function getRenderingType(note) { let type = note.type; if (type === 'file' && note.mime === 'application/pdf') { type = 'pdf'; } else if (type === 'file' && note.mime.startsWith('audio/')) { type = 'audio'; } else if (type === 'file' && note.mime.startsWith('video/')) { type = 'video'; } if (note.isProtected) { if (protectedSessionHolder.isProtectedSessionAvailable()) { protectedSessionHolder.touchProtectedSession(); } else { type = 'protectedSession'; } } return type; } export default { getRenderedContent };