96252: Even more lazy dsMarkdown

This commit is contained in:
Yury Bondarenko
2022-10-22 00:24:48 +02:00
parent ca864379c8
commit 674a4829ce

View File

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