mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
[DURACOM-240] refactor markdownPipe to markdownDirective
missing tests and splitting the service into a browser one and a server one
This commit is contained in:

committed by
Giuseppe Digilio

parent
825308e223
commit
68c9ef1051
@@ -1,60 +0,0 @@
|
|||||||
import {
|
|
||||||
Directive,
|
|
||||||
ElementRef,
|
|
||||||
Input,
|
|
||||||
OnChanges,
|
|
||||||
OnDestroy,
|
|
||||||
OnInit,
|
|
||||||
SimpleChanges,
|
|
||||||
} from '@angular/core';
|
|
||||||
import { Subject } from 'rxjs';
|
|
||||||
import {
|
|
||||||
take,
|
|
||||||
takeUntil,
|
|
||||||
} from 'rxjs/operators';
|
|
||||||
|
|
||||||
import { MathService } from './math.service';
|
|
||||||
|
|
||||||
@Directive({
|
|
||||||
selector: '[dsMath]',
|
|
||||||
standalone: true,
|
|
||||||
})
|
|
||||||
export class MathDirective implements OnInit, OnChanges, OnDestroy {
|
|
||||||
@Input() dsMath: string;
|
|
||||||
private alive$ = new Subject<boolean>();
|
|
||||||
private readonly el: HTMLElement;
|
|
||||||
|
|
||||||
constructor(private mathService: MathService, private elementRef: ElementRef) {
|
|
||||||
this.el = elementRef.nativeElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
|
||||||
if (changes?.dsMath?.currentValue) {
|
|
||||||
this.render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private render() {
|
|
||||||
this.mathService.ready().pipe(
|
|
||||||
take(1),
|
|
||||||
takeUntil(this.alive$),
|
|
||||||
).subscribe(() => {
|
|
||||||
// if this.dsMath begins with "The observation of the"
|
|
||||||
if (this.dsMath.startsWith('The observation of the')) {
|
|
||||||
console.warn('rendering math after ready');
|
|
||||||
console.warn('this.dsMath', this.dsMath);
|
|
||||||
console.warn('this.el', this.el);
|
|
||||||
}
|
|
||||||
this.mathService.render(this.el, this.dsMath);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.alive$.next(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -7,16 +7,9 @@ import {
|
|||||||
|
|
||||||
interface MathJaxConfig {
|
interface MathJaxConfig {
|
||||||
source: string;
|
source: string;
|
||||||
integrity: string;
|
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
MathJax: any;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
@@ -38,12 +31,10 @@ export class MathService {
|
|||||||
|
|
||||||
private mathJax: MathJaxConfig = {
|
private mathJax: MathJaxConfig = {
|
||||||
source: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js',
|
source: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js',
|
||||||
integrity: 'sha256-CnzfCXjFj1REmPHgWvm/OQv8gFaxwbLKUi41yCU7N2s=',
|
|
||||||
id: 'MathJaxScript',
|
id: 'MathJaxScript',
|
||||||
};
|
};
|
||||||
private mathJaxFallback: MathJaxConfig = {
|
private mathJaxFallback: MathJaxConfig = {
|
||||||
source: 'assets/mathjax/mml-chtml.js',
|
source: 'assets/mathjax/mml-chtml.js',
|
||||||
integrity: 'sha256-CnzfCXjFj1REmPHgWvm/OQv8gFaxwbLKUi41yCU7N2s=',
|
|
||||||
id: 'MathJaxBackupScript',
|
id: 'MathJaxBackupScript',
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -62,6 +53,7 @@ export class MathService {
|
|||||||
|
|
||||||
private async registerMathJaxAsync(config: MathJaxConfig): Promise<any> {
|
private async registerMathJaxAsync(config: MathJaxConfig): Promise<any> {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
|
||||||
const optionsScript: HTMLScriptElement = document.createElement('script');
|
const optionsScript: HTMLScriptElement = document.createElement('script');
|
||||||
optionsScript.type = 'text/javascript';
|
optionsScript.type = 'text/javascript';
|
||||||
optionsScript.text = `MathJax = ${JSON.stringify(this.mathJaxOptions)};`;
|
optionsScript.text = `MathJax = ${JSON.stringify(this.mathJaxOptions)};`;
|
||||||
@@ -83,11 +75,7 @@ export class MathService {
|
|||||||
return this.signal;
|
return this.signal;
|
||||||
}
|
}
|
||||||
|
|
||||||
render(element: HTMLElement, value: string) {
|
render(element: HTMLElement) {
|
||||||
// Take initial typesetting which MathJax performs into account
|
(window as any).MathJax.typesetPromise([element]);
|
||||||
// window.MathJax.startup.promise.then(() => {
|
|
||||||
element.innerHTML = value;
|
|
||||||
window.MathJax.typesetPromise([element]);
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<!-- Render value as markdown -->
|
<!-- Render value as markdown -->
|
||||||
<ng-template #markdown let-value="value">
|
<ng-template #markdown let-value="value">
|
||||||
<span class="dont-break-out" [innerHTML]="value | dsMarkdown | async">
|
<span class="dont-break-out" [dsMarkdown]="value">
|
||||||
</span>
|
</span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@ import { MetadataValue } from '../../../core/shared/metadata.models';
|
|||||||
import { VALUE_LIST_BROWSE_DEFINITION } from '../../../core/shared/value-list-browse-definition.resource-type';
|
import { VALUE_LIST_BROWSE_DEFINITION } from '../../../core/shared/value-list-browse-definition.resource-type';
|
||||||
import { hasValue } from '../../../shared/empty.util';
|
import { hasValue } from '../../../shared/empty.util';
|
||||||
import { MetadataFieldWrapperComponent } from '../../../shared/metadata-field-wrapper/metadata-field-wrapper.component';
|
import { MetadataFieldWrapperComponent } from '../../../shared/metadata-field-wrapper/metadata-field-wrapper.component';
|
||||||
import { MarkdownPipe as MarkdownPipe_1 } from '../../../shared/utils/markdown.pipe';
|
import { MarkdownDirective } from '../../../shared/utils/markdown.directive';
|
||||||
import { ImageField } from '../../simple/field-components/specific-field/image-field';
|
import { ImageField } from '../../simple/field-components/specific-field/image-field';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,7 +36,7 @@ import { ImageField } from '../../simple/field-components/specific-field/image-f
|
|||||||
styleUrls: ['./metadata-values.component.scss'],
|
styleUrls: ['./metadata-values.component.scss'],
|
||||||
templateUrl: './metadata-values.component.html',
|
templateUrl: './metadata-values.component.html',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [MetadataFieldWrapperComponent, NgFor, NgTemplateOutlet, NgIf, RouterLink, AsyncPipe, MarkdownPipe_1, TranslateModule],
|
imports: [MetadataFieldWrapperComponent, NgFor, NgTemplateOutlet, NgIf, RouterLink, AsyncPipe, TranslateModule, MarkdownDirective],
|
||||||
})
|
})
|
||||||
export class MetadataValuesComponent implements OnChanges {
|
export class MetadataValuesComponent implements OnChanges {
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ export class MetadataValuesComponent implements OnChanges {
|
|||||||
@Input() label: string;
|
@Input() label: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the {@link MarkdownPipe} should be used to render these metadata values.
|
* Whether the {@link MarkdownDirective} should be used to render these metadata values.
|
||||||
* This will only have effect if {@link MarkdownConfig#enabled} is true.
|
* This will only have effect if {@link MarkdownConfig#enabled} is true.
|
||||||
* Mathjax will only be rendered if {@link MarkdownConfig#mathjax} is true.
|
* Mathjax will only be rendered if {@link MarkdownConfig#mathjax} is true.
|
||||||
*/
|
*/
|
||||||
|
@@ -47,7 +47,7 @@ export class ItemPageAbstractFieldComponent extends ItemPageFieldComponent {
|
|||||||
label = 'item.page.abstract';
|
label = 'item.page.abstract';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use the {@link MarkdownPipe} to render dc.description.abstract values
|
* Use the {@link MarkdownDirective} to render dc.description.abstract values
|
||||||
*/
|
*/
|
||||||
enableMarkdown = true;
|
enableMarkdown = true;
|
||||||
}
|
}
|
||||||
|
@@ -43,7 +43,7 @@ export class GenericItemPageFieldComponent extends ItemPageFieldComponent {
|
|||||||
@Input() label: string;
|
@Input() label: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the {@link MarkdownPipe} should be used to render this metadata.
|
* Whether the {@link MarkdownDirective} should be used to render this metadata.
|
||||||
*/
|
*/
|
||||||
@Input() enableMarkdown = false;
|
@Input() enableMarkdown = false;
|
||||||
|
|
||||||
|
@@ -39,7 +39,7 @@ export class ItemPageFieldComponent {
|
|||||||
@Input() item: Item;
|
@Input() item: Item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the {@link MarkdownPipe} should be used to render this metadata.
|
* Whether the {@link MarkdownDirective} should be used to render this metadata.
|
||||||
*/
|
*/
|
||||||
enableMarkdown = false;
|
enableMarkdown = false;
|
||||||
|
|
||||||
|
8
src/app/shared/utils/markdown.directive.spec.ts
Normal file
8
src/app/shared/utils/markdown.directive.spec.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { MarkdownDirective } from './markdown.directive';
|
||||||
|
|
||||||
|
describe('MarkdownDirective', () => {
|
||||||
|
it('should create an instance', () => {
|
||||||
|
const directive = new MarkdownDirective();
|
||||||
|
expect(directive).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
85
src/app/shared/utils/markdown.directive.ts
Normal file
85
src/app/shared/utils/markdown.directive.ts
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import {
|
||||||
|
Directive,
|
||||||
|
ElementRef,
|
||||||
|
Inject,
|
||||||
|
InjectionToken,
|
||||||
|
Input,
|
||||||
|
OnDestroy,
|
||||||
|
OnInit,
|
||||||
|
SecurityContext,
|
||||||
|
} from '@angular/core';
|
||||||
|
import {
|
||||||
|
DomSanitizer,
|
||||||
|
SafeHtml,
|
||||||
|
} from '@angular/platform-browser';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import {
|
||||||
|
take,
|
||||||
|
takeUntil,
|
||||||
|
} from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { environment } from '../../../environments/environment';
|
||||||
|
import { MathService } from '../../core/shared/math.service';
|
||||||
|
import { isEmpty } from '../empty.util';
|
||||||
|
|
||||||
|
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 },
|
||||||
|
);
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[dsMarkdown]',
|
||||||
|
standalone: true,
|
||||||
|
})
|
||||||
|
export class MarkdownDirective implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
@Input() dsMarkdown: string;
|
||||||
|
private alive$ = new Subject<boolean>();
|
||||||
|
|
||||||
|
el: HTMLElement;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected sanitizer: DomSanitizer,
|
||||||
|
@Inject(MARKDOWN_IT) private markdownIt: LazyMarkdownIt,
|
||||||
|
private mathService: MathService,
|
||||||
|
private elementRef: ElementRef) {
|
||||||
|
this.el = elementRef.nativeElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.render(this.dsMarkdown);
|
||||||
|
}
|
||||||
|
|
||||||
|
async render(value: string, forcePreview = false): Promise<SafeHtml> {
|
||||||
|
if (isEmpty(value) || (!environment.markdown.enabled && !forcePreview)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
const MarkdownIt = await this.markdownIt;
|
||||||
|
const md = new MarkdownIt({
|
||||||
|
html: true,
|
||||||
|
linkify: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const html = this.sanitizer.sanitize(SecurityContext.HTML, md.render(value));
|
||||||
|
this.el.innerHTML = html;
|
||||||
|
|
||||||
|
if (environment.markdown.mathjax) {
|
||||||
|
this.renderMathjax();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderMathjax() {
|
||||||
|
this.mathService.ready().pipe(
|
||||||
|
take(1),
|
||||||
|
takeUntil(this.alive$),
|
||||||
|
).subscribe(() => {
|
||||||
|
this.mathService.render(this.el);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.alive$.next(false);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,79 +0,0 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { APP_CONFIG } from '../../../config/app-config.interface';
|
|
||||||
import { environment } from '../../../environments/environment';
|
|
||||||
import { MarkdownPipe } from './markdown.pipe';
|
|
||||||
|
|
||||||
describe('Markdown Pipe', () => {
|
|
||||||
|
|
||||||
let markdownPipe: MarkdownPipe;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
providers: [
|
|
||||||
MarkdownPipe,
|
|
||||||
{
|
|
||||||
provide: APP_CONFIG,
|
|
||||||
useValue: Object.assign(environment, {
|
|
||||||
markdown: {
|
|
||||||
enabled: true,
|
|
||||||
mathjax: true,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}).compileComponents();
|
|
||||||
|
|
||||||
markdownPipe = TestBed.inject(MarkdownPipe);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render markdown', async () => {
|
|
||||||
await testTransform(
|
|
||||||
'# Header',
|
|
||||||
'<h1>Header</h1>',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render mathjax', async () => {
|
|
||||||
await testTransform(
|
|
||||||
'$\\sqrt{2}^2$',
|
|
||||||
'<svg.*?>.*</svg>',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render regular links', async () => {
|
|
||||||
await testTransform(
|
|
||||||
'<a href="https://www.dspace.com">DSpace</a>',
|
|
||||||
'<a href="https://www.dspace.com">DSpace</a>',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not render javascript links', async () => {
|
|
||||||
await testTransform(
|
|
||||||
'<a href="javascript:window.alert(\'bingo!\');">exploit</a>',
|
|
||||||
'<a>exploit</a>',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render undefined value', async () => {
|
|
||||||
await testTransform(
|
|
||||||
undefined,
|
|
||||||
undefined,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render null value', async () => {
|
|
||||||
await testTransform(
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
async function testTransform(input: string, output: string) {
|
|
||||||
expect(
|
|
||||||
await markdownPipe.transform(input),
|
|
||||||
).toMatch(
|
|
||||||
new RegExp('.*' + output + '.*'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
@@ -1,127 +0,0 @@
|
|||||||
import {
|
|
||||||
Inject,
|
|
||||||
InjectionToken,
|
|
||||||
Pipe,
|
|
||||||
PipeTransform,
|
|
||||||
SecurityContext,
|
|
||||||
} from '@angular/core';
|
|
||||||
import {
|
|
||||||
DomSanitizer,
|
|
||||||
SafeHtml,
|
|
||||||
} from '@angular/platform-browser';
|
|
||||||
import { MathService } from 'src/app/core/shared/math.service';
|
|
||||||
|
|
||||||
import { environment } from '../../../environments/environment';
|
|
||||||
import { isEmpty } from '../empty.util';
|
|
||||||
|
|
||||||
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;
|
|
||||||
// type Mathjax = ReturnType<typeof mathjaxLoader>;
|
|
||||||
// const MATHJAX = new InjectionToken<Mathjax>(
|
|
||||||
// 'Lazily loaded mathjax',
|
|
||||||
// { 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.
|
|
||||||
* - markdown will only be rendered if {@link MarkdownConfig#enabled} is true
|
|
||||||
* - mathjax will only be rendered if both {@link MarkdownConfig#enabled} and {@link MarkdownConfig#mathjax} are true
|
|
||||||
*
|
|
||||||
* This pipe should be used on the 'innerHTML' attribute of a component, in combination with an async pipe.
|
|
||||||
* Example usage:
|
|
||||||
* <span class="example" [innerHTML]="'# title' | dsMarkdown | async"></span>
|
|
||||||
* Result:
|
|
||||||
* <span class="example">
|
|
||||||
* <h1>title</h1>
|
|
||||||
* </span>
|
|
||||||
*/
|
|
||||||
@Pipe({
|
|
||||||
name: 'dsMarkdown',
|
|
||||||
standalone: true,
|
|
||||||
})
|
|
||||||
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,
|
|
||||||
private mathService: MathService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
async transform(value: string, forcePreview = false): Promise<SafeHtml> {
|
|
||||||
if (isEmpty(value) || (!environment.markdown.enabled && !forcePreview)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
const MarkdownIt = await this.markdownIt;
|
|
||||||
const md = new MarkdownIt({
|
|
||||||
html: true,
|
|
||||||
linkify: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
let html: string;
|
|
||||||
if (environment.markdown.mathjax) {
|
|
||||||
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,
|
|
||||||
'mjx-container', 'svg', 'g', 'path', 'rect', 'text',
|
|
||||||
// Also let the mjx-assistive-mml tag (and it's children) through (for screen readers)
|
|
||||||
'mjx-assistive-mml', 'math', 'mrow', 'mi',
|
|
||||||
],
|
|
||||||
allowedAttributes: {
|
|
||||||
...sanitizeHtml.defaults.allowedAttributes,
|
|
||||||
'mjx-container': [
|
|
||||||
'class', 'style', 'jax',
|
|
||||||
],
|
|
||||||
svg: [
|
|
||||||
'xmlns', 'viewBox', 'style', 'width', 'height', 'role', 'focusable', 'alt', 'aria-label',
|
|
||||||
],
|
|
||||||
g: [
|
|
||||||
'data-mml-node', 'style', 'stroke', 'fill', 'stroke-width', 'transform',
|
|
||||||
],
|
|
||||||
path: [
|
|
||||||
'd', 'style', 'transform',
|
|
||||||
],
|
|
||||||
rect: [
|
|
||||||
'width', 'height', 'x', 'y', 'transform', 'style',
|
|
||||||
],
|
|
||||||
text: [
|
|
||||||
'transform', 'font-size',
|
|
||||||
],
|
|
||||||
'mjx-assistive-mml': [
|
|
||||||
'unselectable', 'display', 'style',
|
|
||||||
],
|
|
||||||
math: [
|
|
||||||
'xmlns',
|
|
||||||
],
|
|
||||||
mrow: [
|
|
||||||
'data-mjx-texclass',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
parser: {
|
|
||||||
lowerCaseAttributeNames: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
html = this.sanitizer.sanitize(SecurityContext.HTML, md.render(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.sanitizer.bypassSecurityTrustHtml(html);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,20 +1,20 @@
|
|||||||
import { Config } from './config.interface';
|
import { Config } from './config.interface';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config related to the {@link MarkdownPipe}.
|
* Config related to the {@link MarkdownDirective}.
|
||||||
*/
|
*/
|
||||||
export interface MarkdownConfig extends Config {
|
export interface MarkdownConfig extends Config {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable Markdown (https://commonmark.org/) syntax for values passed to the {@link MarkdownPipe}.
|
* Enable Markdown (https://commonmark.org/) syntax for values passed to the {@link MarkdownDirective}.
|
||||||
* - If this is true, values passed to the MarkdownPipe will be transformed to html according to the markdown syntax
|
* - If this is true, values passed to the MarkdownDirective will be transformed to html according to the markdown syntax
|
||||||
* rules.
|
* rules.
|
||||||
* - If this is false, using the MarkdownPipe will have no effect.
|
* - If this is false, using the MarkdownDirective will have no effect.
|
||||||
*/
|
*/
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable MathJax (https://www.mathjax.org/) syntax for values passed to the {@link MarkdownPipe}.
|
* Enable MathJax (https://www.mathjax.org/) syntax for values passed to the {@link MarkdownDirective}.
|
||||||
* Requires {@link enabled} to also be true before MathJax will display.
|
* Requires {@link enabled} to also be true before MathJax will display.
|
||||||
*/
|
*/
|
||||||
mathjax: boolean;
|
mathjax: boolean;
|
||||||
|
Reference in New Issue
Block a user