/** * Based on https://github.com/dwengovzw/Learning-Object-Repository/blob/main/app/processors/markdown/learing_object_markdown_renderer.js [sic!] */ import PdfProcessor from '../pdf/pdf-processor.js'; import AudioProcessor from '../audio/audio-processor.js'; import ExternProcessor from '../extern/extern-processor.js'; import InlineImageProcessor from '../image/inline-image-processor.js'; import * as marked from 'marked'; import { getUrlStringForLearningObjectHTML, isValidHttpUrl } from '../../../../util/links.js'; import { ProcessingError } from '../processing-error.js'; import Image = marked.Tokens.Image; import Heading = marked.Tokens.Heading; import Link = marked.Tokens.Link; import RendererObject = marked.RendererObject; import { LearningObjectIdentifierDTO } from '@dwengo-1/common/interfaces/learning-content'; import { Language } from '@dwengo-1/common/util/language'; const prefixes = { learningObject: '@learning-object', pdf: '@pdf', audio: '@audio', extern: '@extern', video: '@youtube', notebook: '@notebook', blockly: '@blockly', }; function extractLearningObjectIdFromHref(href: string): LearningObjectIdentifierDTO { const [hruid, language, version] = href.split(/\/(.+)/, 2)[1].split('/'); return { hruid, language: language as Language, version: parseInt(version), }; } /** * An extension for the renderer of the Marked Markdown renderer which adds support for * - a custom heading, * - links to other learning objects, * - embeddings of other learning objects. */ const dwengoMarkedRenderer: RendererObject = { heading(heading: Heading): string { const text = heading.text; const level = heading.depth; const escapedText = text.toLowerCase().replace(/[^\w]+/g, '-'); return ( `\n` + ` \n` + ` \n` + ` \n` + ` ${text}\n` + `\n` ); }, // When the syntax for a link is used => [text](href "title") // Render a custom link when the prefix for a learning object is used. link(link: Link): string { const href = link.href; const title = link.title || ''; const text = marked.parseInline(link.text); // There could for example be an image in the link. if (href.startsWith(prefixes.learningObject)) { // Link to learning-object const learningObjectId = extractLearningObjectIdFromHref(href); return `${text}`; } // Any other link if (!isValidHttpUrl(href)) { throw new ProcessingError('Link is not a valid HTTP URL!'); } // return `${text}`; }, // When the syntax for an image is used => ![text](href "title") // Render a learning object, pdf, audio or video if a prefix is used. image(img: Image): string { const href = img.href; if (href.startsWith(prefixes.learningObject)) { // Embedded learning-object const learningObjectId = extractLearningObjectIdFromHref(href); return ` `; // Placeholder for the learning object since we cannot fetch its HTML here (this has to be a sync function!) } else if (href.startsWith(prefixes.pdf)) { // Embedded pdf const proc = new PdfProcessor(); return proc.render(href.split(/\/(.+)/, 2)[1]); } else if (href.startsWith(prefixes.audio)) { // Embedded audio const proc = new AudioProcessor(); return proc.render(href.split(/\/(.+)/, 2)[1]); } else if (href.startsWith(prefixes.extern) || href.startsWith(prefixes.video) || href.startsWith(prefixes.notebook)) { // Embedded youtube video or notebook (or other extern content) const proc = new ExternProcessor(); return proc.render(href.split(/\/(.+)/, 2)[1]); } // Embedded image const proc = new InlineImageProcessor(); return proc.render(href); }, }; export default dwengoMarkedRenderer;