diff --git a/src/app/shared/utils/markdown.pipe.ts b/src/app/shared/utils/markdown.pipe.ts index f7e1032cac..e675a863f8 100644 --- a/src/app/shared/utils/markdown.pipe.ts +++ b/src/app/shared/utils/markdown.pipe.ts @@ -1,9 +1,14 @@ -import { Inject, InjectionToken, Pipe, PipeTransform } from '@angular/core'; -import MarkdownIt from 'markdown-it'; -import * as sanitizeHtml from 'sanitize-html'; +import { Inject, InjectionToken, Pipe, PipeTransform, SecurityContext } from '@angular/core'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { environment } from '../../../environments/environment'; +const markdownItLoader = async () => (await import('markdown-it')).default; +type LazyMarkdownIt = ReturnType; +const MARKDOWN_IT = new InjectionToken( + 'Lazily loaded MarkdownIt', + { providedIn: 'root', factory: markdownItLoader } +); + const mathjaxLoader = async () => (await import('markdown-it-mathjax3')).default; type Mathjax = ReturnType; const MATHJAX = new InjectionToken( @@ -11,6 +16,13 @@ const MATHJAX = new InjectionToken( { providedIn: 'root', factory: mathjaxLoader } ); +const sanitizeHtmlLoader = async () => (await import('sanitize-html') as any).default; +type SanitizeHtml = ReturnType; +const SANITIZE_HTML = new InjectionToken( + 'Lazily loaded sanitize-html', + { providedIn: 'root', factory: sanitizeHtmlLoader } +); + /** * Pipe for rendering markdown and mathjax. * - markdown will only be rendered if {@link MarkdownConfig#enabled} is true @@ -31,7 +43,9 @@ export class MarkdownPipe implements PipeTransform { constructor( protected sanitizer: DomSanitizer, + @Inject(MARKDOWN_IT) private markdownIt: LazyMarkdownIt, @Inject(MATHJAX) private mathjax: Mathjax, + @Inject(SANITIZE_HTML) private sanitizeHtml: SanitizeHtml, ) { } @@ -39,15 +53,17 @@ export class MarkdownPipe implements PipeTransform { if (!environment.markdown.enabled) { return value; } + const MarkdownIt = await this.markdownIt; const md = new MarkdownIt({ html: true, linkify: true, }); + + let html: string; if (environment.markdown.mathjax) { md.use(await this.mathjax); - } - return this.sanitizer.bypassSecurityTrustHtml( - sanitizeHtml(md.render(value), { + const sanitizeHtml = await this.sanitizeHtml + html = sanitizeHtml(md.render(value), { // sanitize-html doesn't let through SVG by default, so we extend its allowlists to cover MathJax SVG allowedTags: [ ...sanitizeHtml.defaults.allowedTags, @@ -77,7 +93,11 @@ export class MarkdownPipe implements PipeTransform { parser: { lowerCaseAttributeNames: false, }, - }) - ); + }); + } else { + html = this.sanitizer.sanitize(SecurityContext.HTML, md.render(value)); + } + + return this.sanitizer.bypassSecurityTrustHtml(html) } }