chore(client/ts): port services/content_renderer

This commit is contained in:
Elian Doran 2024-12-21 14:56:51 +02:00
parent 27ed750d48
commit ef4d2378f1
No known key found for this signature in database
3 changed files with 54 additions and 31 deletions

View File

@ -21,10 +21,11 @@ class FAttachment {
attachmentId!: string; attachmentId!: string;
private ownerId!: string; private ownerId!: string;
role!: string; role!: string;
private mime!: string; mime!: string;
private title!: string; title!: string;
isProtected!: boolean; // TODO: Is this used?
private dateModified!: string; private dateModified!: string;
private utcDateModified!: string; utcDateModified!: string;
private utcDateScheduledForErasureSince!: string; private utcDateScheduledForErasureSince!: string;
/** /**
* optionally added to the entity * optionally added to the entity

View File

@ -16,12 +16,13 @@ import { loadElkIfNeeded } from "./mermaid.js";
let idCounter = 1; let idCounter = 1;
/** interface Options {
* @param {FNote|FAttachment} entity tooltip?: boolean;
* @param {object} options trim?: boolean;
* @return {Promise<{type: string, $renderedContent: jQuery}>} imageHasZoom?: boolean;
*/ }
async function getRenderedContent(entity, options = {}) {
async function getRenderedContent(this: {} | { ctx: string }, entity: FNote, options: Options = {}) {
options = Object.assign({ options = Object.assign({
tooltip: false tooltip: false
}, options); }, options);
@ -49,7 +50,7 @@ async function getRenderedContent(entity, options = {}) {
else if (type === 'render') { else if (type === 'render') {
const $content = $('<div>'); const $content = $('<div>');
await renderService.render(entity, $content, this.ctx); await renderService.render(entity, $content);
$renderedContent.append($content); $renderedContent.append($content);
} }
@ -86,12 +87,11 @@ async function getRenderedContent(entity, options = {}) {
}; };
} }
/** @param {FNote} note */ async function renderText(note: FNote, $renderedContent: JQuery<HTMLElement>) {
async function renderText(note, $renderedContent) {
// entity must be FNote // entity must be FNote
const blob = await note.getBlob(); const blob = await note.getBlob();
if (!utils.isHtmlEmpty(blob.content)) { if (blob && !utils.isHtmlEmpty(blob.content)) {
$renderedContent.append($('<div class="ck-content">').html(blob.content)); $renderedContent.append($('<div class="ck-content">').html(blob.content));
if ($renderedContent.find('span.math-tex').length > 0) { if ($renderedContent.find('span.math-tex').length > 0) {
@ -100,9 +100,9 @@ async function renderText(note, $renderedContent) {
renderMathInElement($renderedContent[0], {trust: true}); renderMathInElement($renderedContent[0], {trust: true});
} }
const getNoteIdFromLink = el => treeService.getNoteIdFromUrl($(el).attr('href')); const getNoteIdFromLink = (el: HTMLElement) => treeService.getNoteIdFromUrl($(el).attr('href') || "");
const referenceLinks = $renderedContent.find("a.reference-link"); const referenceLinks = $renderedContent.find("a.reference-link");
const noteIdsToPrefetch = referenceLinks.map(el => getNoteIdFromLink(el)); const noteIdsToPrefetch = referenceLinks.map((i, el) => getNoteIdFromLink(el));
await froca.getNotes(noteIdsToPrefetch); await froca.getNotes(noteIdsToPrefetch);
for (const el of referenceLinks) { for (const el of referenceLinks) {
@ -117,19 +117,17 @@ async function renderText(note, $renderedContent) {
/** /**
* Renders a code note, by displaying its content and applying syntax highlighting based on the selected MIME type. * Renders a code note, by displaying its content and applying syntax highlighting based on the selected MIME type.
*
* @param {FNote} note
*/ */
async function renderCode(note, $renderedContent) { async function renderCode(note: FNote, $renderedContent: JQuery<HTMLElement>) {
const blob = await note.getBlob(); const blob = await note.getBlob();
const $codeBlock = $("<code>"); const $codeBlock = $("<code>");
$codeBlock.text(blob.content); $codeBlock.text(blob?.content || "");
$renderedContent.append($("<pre>").append($codeBlock)); $renderedContent.append($("<pre>").append($codeBlock));
await applySingleBlockSyntaxHighlight($codeBlock, mime_types.normalizeMimeTypeForCKEditor(note.mime)); await applySingleBlockSyntaxHighlight($codeBlock, mime_types.normalizeMimeTypeForCKEditor(note.mime));
} }
function renderImage(entity, $renderedContent, options = {}) { function renderImage(entity: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>, options: Options = {}) {
const encodedTitle = encodeURIComponent(entity.title); const encodedTitle = encodeURIComponent(entity.title);
let url; let url;
@ -146,7 +144,7 @@ function renderImage(entity, $renderedContent, options = {}) {
.css('justify-content', 'center'); .css('justify-content', 'center');
const $img = $("<img>") const $img = $("<img>")
.attr("src", url) .attr("src", url || "")
.attr("id", "attachment-image-" + idCounter++) .attr("id", "attachment-image-" + idCounter++)
.css("max-width", "100%"); .css("max-width", "100%");
@ -165,7 +163,7 @@ function renderImage(entity, $renderedContent, options = {}) {
imageContextMenuService.setupContextMenu($img); imageContextMenuService.setupContextMenu($img);
} }
function renderFile(entity, type, $renderedContent) { function renderFile(entity: FNote | FAttachment, type: string, $renderedContent: JQuery<HTMLElement>) {
let entityType, entityId; let entityType, entityId;
if (entity instanceof FNote) { if (entity instanceof FNote) {
@ -201,7 +199,7 @@ function renderFile(entity, type, $renderedContent) {
$content.append($videoPreview); $content.append($videoPreview);
} }
if (entityType === 'notes') { if (entityType === 'notes' && "noteId" in entity) {
// TODO: we should make this available also for attachments, but there's a problem with "Open externally" support // TODO: we should make this available also for attachments, but there's a problem with "Open externally" support
// in attachment list // in attachment list
const $downloadButton = $('<button class="file-download btn btn-primary" type="button">Download</button>'); const $downloadButton = $('<button class="file-download btn btn-primary" type="button">Download</button>');
@ -222,11 +220,11 @@ function renderFile(entity, type, $renderedContent) {
$renderedContent.append($content); $renderedContent.append($content);
} }
async function renderMermaid(note, $renderedContent) { async function renderMermaid(note: FNote, $renderedContent: JQuery<HTMLElement>) {
await libraryLoader.requireLibrary(libraryLoader.MERMAID); await libraryLoader.requireLibrary(libraryLoader.MERMAID);
const blob = await note.getBlob(); const blob = await note.getBlob();
const content = blob.content || ""; const content = blob?.content || "";
$renderedContent $renderedContent
.css("display", "flex") .css("display", "flex")
@ -254,7 +252,7 @@ async function renderMermaid(note, $renderedContent) {
* @param {FNote} note * @param {FNote} note
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async function renderChildrenList($renderedContent, note) { async function renderChildrenList($renderedContent: JQuery<HTMLElement>, note: FNote) {
$renderedContent.css("padding", "10px"); $renderedContent.css("padding", "10px");
$renderedContent.addClass("text-with-ellipsis"); $renderedContent.addClass("text-with-ellipsis");
@ -277,15 +275,21 @@ async function renderChildrenList($renderedContent, note) {
} }
} }
function getRenderingType(entity) { function getRenderingType(entity: FNote | FAttachment) {
let type = entity.type || entity.role; let type: string = "";
const mime = entity.mime; if ("type" in entity) {
type = entity.type;
} else if ("role" in entity) {
type = entity.role;
}
const mime = ("mime" in entity && entity.mime);
if (type === 'file' && mime === 'application/pdf') { if (type === 'file' && mime === 'application/pdf') {
type = 'pdf'; type = 'pdf';
} else if (type === 'file' && mime.startsWith('audio/')) { } else if (type === 'file' && mime && mime.startsWith('audio/')) {
type = 'audio'; type = 'audio';
} else if (type === 'file' && mime.startsWith('video/')) { } else if (type === 'file' && mime && mime.startsWith('video/')) {
type = 'video'; type = 'video';
} }

View File

@ -109,4 +109,22 @@ declare global {
var renderMathInElement: (element: HTMLElement, options: { var renderMathInElement: (element: HTMLElement, options: {
trust: boolean; trust: boolean;
}) => void; }) => void;
var WZoom = {
create(selector: string, opts: {
maxScale: number;
speed: number;
zoomOnClick: boolean
})
};
interface MermaidApi {
initialize(opts: {
startOnLoad: boolean,
theme: string,
securityLevel: "antiscript"
}): void;
render(selector: string, data: string);
}
var mermaid: {
mermaidAPI: MermaidApi;
};
} }