ngx-markdown
Version:
Angular library that uses marked to parse markdown to html combined with Prism.js for synthax highlights
158 lines (157 loc) • 14.1 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
import { isPlatformBrowser } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { Inject, Injectable, Optional, PLATFORM_ID, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { parse, Renderer } from 'marked';
import { map } from 'rxjs/operators';
import { MarkedOptions } from './marked-options';
/** @type {?} */
export const errorSrcWithoutHttpClient = '[ngx-markdown] When using the [src] attribute you *have to* pass the `HttpClient` as a parameter of the `forRoot` method. See README for more information';
export class MarkdownService {
/**
* @param {?} platform
* @param {?} http
* @param {?} domSanitizer
* @param {?} options
*/
constructor(platform, http, domSanitizer, options) {
this.platform = platform;
this.http = http;
this.domSanitizer = domSanitizer;
this.options = options;
if (!this.renderer) {
this.renderer = new Renderer();
}
}
/**
* @return {?}
*/
get renderer() { return this.options.renderer; }
/**
* @param {?} value
* @return {?}
*/
set renderer(value) {
this.options.renderer = value;
}
/**
* @param {?} markdown
* @param {?=} decodeHtml
* @param {?=} markedOptions
* @return {?}
*/
compile(markdown, decodeHtml = false, markedOptions = this.options) {
/** @type {?} */
const precompiled = this.precompile(markdown);
/** @type {?} */
const compiled = parse(decodeHtml ? this.decodeHtml(precompiled) : precompiled, markedOptions);
return markedOptions.sanitize && !markedOptions.sanitizer
? this.domSanitizer.sanitize(SecurityContext.HTML, compiled)
: compiled;
}
/**
* @param {?} src
* @return {?}
*/
getSource(src) {
if (!this.http) {
throw new Error(errorSrcWithoutHttpClient);
}
return this.http
.get(src, { responseType: 'text' })
.pipe(map(markdown => this.handleExtension(src, markdown)));
}
/**
* @return {?}
*/
highlight() {
if (isPlatformBrowser(this.platform) && typeof Prism !== 'undefined') {
Prism.highlightAll(false);
}
}
/**
* @param {?} html
* @return {?}
*/
decodeHtml(html) {
if (isPlatformBrowser(this.platform)) {
/** @type {?} */
const textarea = document.createElement('textarea');
textarea.innerHTML = html;
return textarea.value;
}
return html;
}
/**
* @param {?} src
* @param {?} markdown
* @return {?}
*/
handleExtension(src, markdown) {
/** @type {?} */
const extension = src
? src.split('.').splice(-1).join()
: null;
return extension !== 'md'
? '```' + extension + '\n' + markdown + '\n```'
: markdown;
}
/**
* @param {?} markdown
* @return {?}
*/
precompile(markdown) {
if (!markdown) {
return '';
}
/** @type {?} */
let indentStart;
return markdown
.split('\n')
.map(line => {
/** @type {?} */
let lineIdentStart = indentStart;
// find position of 1st non-whitespace character
// to determine the current line indentation start
if (line.length > 0) {
lineIdentStart = isNaN(lineIdentStart)
? line.search(/\S|$/)
: Math.min(line.search(/\S|$/), lineIdentStart);
}
// keep 1st non-whitespace line indentation
// as base reference for other lines
if (isNaN(indentStart)) {
indentStart = lineIdentStart;
}
// remove whitespaces before current line indentation
return !!lineIdentStart
? line.substring(lineIdentStart)
: line;
}).join('\n');
}
}
MarkdownService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
MarkdownService.ctorParameters = () => [
{ type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] },
{ type: HttpClient, decorators: [{ type: Optional }] },
{ type: DomSanitizer },
{ type: MarkedOptions }
];
if (false) {
/** @type {?} */
MarkdownService.prototype.platform;
/** @type {?} */
MarkdownService.prototype.http;
/** @type {?} */
MarkdownService.prototype.domSanitizer;
/** @type {?} */
MarkdownService.prototype.options;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFya2Rvd24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25neC1tYXJrZG93bi8iLCJzb3VyY2VzIjpbInNyYy9tYXJrZG93bi5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0YsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBRXpDLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVyQyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7O0FBT2pELGFBQWEseUJBQXlCLEdBQUcsMkpBQTJKLENBQUM7QUFHck0sTUFBTSxPQUFPLGVBQWU7Ozs7Ozs7SUFNMUIsWUFDK0IsUUFBZ0IsRUFDekIsSUFBZ0IsRUFDNUIsY0FDRDtRQUhzQixhQUFRLEdBQVIsUUFBUSxDQUFRO1FBQ3pCLFNBQUksR0FBSixJQUFJLENBQVk7UUFDNUIsaUJBQVksR0FBWixZQUFZO1FBQ2IsWUFBTyxHQUFQLE9BQU87UUFFZCxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUNsQixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksUUFBUSxFQUFFLENBQUM7U0FDaEM7S0FDRjs7OztJQWRELElBQUksUUFBUSxLQUFlLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRTs7Ozs7SUFDMUQsSUFBSSxRQUFRLENBQUMsS0FBc0I7UUFDakMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxR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QzthQUNuRDs7O1lBR0QsSUFBSSxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUU7Z0JBQ3RCLFdBQVcsR0FBRyxjQUFjLENBQUM7YUFDOUI7O1lBRUQsT0FBTyxDQUFDLENBQUMsY0FBYztnQkFDckIsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDO2dCQUNoQyxDQUFDLENBQUMsSUFBSSxDQUFDO1NBQ1YsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzs7OztZQXZGbkIsVUFBVTs7OztZQVFnQyxNQUFNLHVCQUE1QyxNQUFNLFNBQUMsV0FBVztZQXhCZCxVQUFVLHVCQXlCZCxRQUFRO1lBdkJKLFlBQVk7WUFLWixhQUFhIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBIdHRwQ2xpZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xyXG5pbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUsIE9wdGlvbmFsLCBQTEFURk9STV9JRCwgU2VjdXJpdHlDb250ZXh0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IERvbVNhbml0aXplciB9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXInO1xyXG5pbXBvcnQgeyBwYXJzZSwgUmVuZGVyZXIgfSBmcm9tICdtYXJrZWQnO1xyXG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuXHJcbmltcG9ydCB7IE1hcmtlZE9wdGlvbnMgfSBmcm9tICcuL21hcmtlZC1vcHRpb25zJztcclxuXHJcbmRlY2xhcmUgdmFyIFByaXNtOiB7XHJcbiAgaGlnaGxpZ2h0QWxsOiAoYXN5bmM6IGJvb2xlYW4pID0+IHZvaWQ7XHJcbn07XHJcblxyXG4vLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoXHJcbmV4cG9ydCBjb25zdCBlcnJvclNyY1dpdGhvdXRIdHRwQ2xpZW50ID0gJ1tuZ3gtbWFya2Rvd25dIFdoZW4gdXNpbmcgdGhlIFtzcmNdIGF0dHJpYnV0ZSB5b3UgKmhhdmUgdG8qIHBhc3MgdGhlIGBIdHRwQ2xpZW50YCBhcyBhIHBhcmFtZXRlciBvZiB0aGUgYGZvclJvb3RgIG1ldGhvZC4gU2VlIFJFQURNRSBmb3IgbW9yZSBpbmZvcm1hdGlvbic7XHJcblxyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBNYXJrZG93blNlcnZpY2Uge1xyXG4gIGdldCByZW5kZXJlcigpOiBSZW5kZXJlciB7IHJldHVybiB0aGlzLm9wdGlvbnMucmVuZGVyZXI7IH1cclxuICBzZXQgcmVuZGVyZXIodmFsdWU6IG1hcmtlZC5SZW5kZXJlcikge1xyXG4gICAgdGhpcy5vcHRpb25zLnJlbmRlcmVyID0gdmFsdWU7XHJcbiAgfVxyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIEBJbmplY3QoUExBVEZPUk1fSUQpIHByaXZhdGUgcGxhdGZvcm06IE9iamVjdCxcclxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgaHR0cDogSHR0cENsaWVudCxcclxuICAgIHByaXZhdGUgZG9tU2FuaXRpemVyOiBEb21TYW5pdGl6ZXIsXHJcbiAgICBwdWJsaWMgb3B0aW9uczogTWFya2VkT3B0aW9ucyxcclxuICApIHtcclxuICAgIGlmICghdGhpcy5yZW5kZXJlcikge1xyXG4gICAgICB0aGlzLnJlbmRlcmVyID0gbmV3IFJlbmRlcmVyKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjb21waWxlKG1hcmtkb3duOiBzdHJpbmcsIGRlY29kZUh0bWwgPSBmYWxzZSwgbWFya2VkT3B0aW9ucyA9IHRoaXMub3B0aW9ucyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBwcmVjb21waWxlZCA9IHRoaXMucHJlY29tcGlsZShtYXJrZG93bik7XHJcbiAgICBjb25zdCBjb21waWxlZCA9IHBhcnNlKFxyXG4gICAgICBkZWNvZGVIdG1sID8gdGhpcy5kZWNvZGVIdG1sKHByZWNvbXBpbGVkKSA6IHByZWNvbXBpbGVkLFxyXG4gICAgICBtYXJrZWRPcHRpb25zKTtcclxuICAgIHJldHVybiBtYXJrZWRPcHRpb25zLnNhbml0aXplICYmICFtYXJrZWRPcHRpb25zLnNhbml0aXplclxyXG4gICAgICA/IHRoaXMuZG9tU2FuaXRpemVyLnNhbml0aXplKFNlY3VyaXR5Q29udGV4dC5IVE1MLCBjb21waWxlZClcclxuICAgICAgOiBjb21waWxlZDtcclxuICB9XHJcblxyXG4gIGdldFNvdXJjZShzcmM6IHN0cmluZyk6IE9ic2VydmFibGU8c3RyaW5nPiB7XHJcbiAgICBpZiAoIXRoaXMuaHR0cCkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3JTcmNXaXRob3V0SHR0cENsaWVudCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcy5odHRwXHJcbiAgICAgIC5nZXQoc3JjLCB7IHJlc3BvbnNlVHlwZTogJ3RleHQnIH0pXHJcbiAgICAgIC5waXBlKG1hcChtYXJrZG93biA9PiB0aGlzLmhhbmRsZUV4dGVuc2lvbihzcmMsIG1hcmtkb3duKSkpO1xyXG4gIH1cclxuXHJcbiAgaGlnaGxpZ2h0KCkge1xyXG4gICAgaWYgKGlzUGxhdGZvcm1Ccm93c2VyKHRoaXMucGxhdGZvcm0pICYmIHR5cGVvZiBQcmlzbSAhPT0gJ3VuZGVmaW5lZCcpIHtcclxuICAgICAgUHJpc20uaGlnaGxpZ2h0QWxsKGZhbHNlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZGVjb2RlSHRtbChodG1sOiBzdHJpbmcpIHtcclxuICAgIGlmIChpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtKSkge1xyXG4gICAgICBjb25zdCB0ZXh0YXJlYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3RleHRhcmVhJyk7XHJcbiAgICAgIHRleHRhcmVhLmlubmVySFRNTCA9IGh0bWw7XHJcbiAgICAgIHJldHVybiB0ZXh0YXJlYS52YWx1ZTtcclxuICAgIH1cclxuICAgIHJldHVybiBodG1sO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBoYW5kbGVFeHRlbnNpb24oc3JjOiBzdHJpbmcsIG1hcmtkb3duOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgZXh0ZW5zaW9uID0gc3JjXHJcbiAgICAgID8gc3JjLnNwbGl0KCcuJykuc3BsaWNlKC0xKS5qb2luKClcclxuICAgICAgOiBudWxsO1xyXG4gICAgcmV0dXJuIGV4dGVuc2lvbiAhPT0gJ21kJ1xyXG4gICAgICA/ICdgYGAnICsgZXh0ZW5zaW9uICsgJ1xcbicgKyBtYXJrZG93biArICdcXG5gYGAnXHJcbiAgICAgIDogbWFya2Rvd247XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHByZWNvbXBpbGUobWFya2Rvd246IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBpZiAoIW1hcmtkb3duKSB7XHJcbiAgICAgIHJldHVybiAnJztcclxuICAgIH1cclxuICAgIGxldCBpbmRlbnRTdGFydDogbnVtYmVyO1xyXG4gICAgcmV0dXJuIG1hcmtkb3duXHJcbiAgICAgIC5zcGxpdCgnXFxuJylcclxuICAgICAgLm1hcChsaW5lID0+IHtcclxuICAgICAgICAvLyBzZXQgY3VycmVudCBsaW5lIGlkZW50IHN0YXJ0IHRvIGJhc2UgcmVmZXJlbmNlIGluZGVudGF0aW9uXHJcbiAgICAgICAgbGV0IGxpbmVJZGVudFN0YXJ0ID0gaW5kZW50U3RhcnQ7XHJcbiAgICAgICAgLy8gZmluZCBwb3NpdGlvbiBvZiAxc3Qgbm9uLXdoaXRlc3BhY2UgY2hhcmFjdGVyXHJcbiAgICAgICAgLy8gdG8gZGV0ZXJtaW5lIHRoZSBjdXJyZW50IGxpbmUgaW5kZW50YXRpb24gc3RhcnRcclxuICAgICAgICBpZiAobGluZS5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICBsaW5lSWRlbnRTdGFydCA9IGlzTmFOKGxpbmVJZGVudFN0YXJ0KVxyXG4gICAgICAgICAgICA/IGxpbmUuc2VhcmNoKC9cXFN8JC8pXHJcbiAgICAgICAgICAgIDogTWF0aC5taW4obGluZS5zZWFyY2goL1xcU3wkLyksIGxpbmVJZGVudFN0YXJ0KTtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8ga2VlcCAxc3Qgbm9uLXdoaXRlc3BhY2UgbGluZSBpbmRlbnRhdGlvblxyXG4gICAgICAgIC8vIGFzIGJhc2UgcmVmZXJlbmNlIGZvciBvdGhlciBsaW5lc1xyXG4gICAgICAgIGlmIChpc05hTihpbmRlbnRTdGFydCkpIHtcclxuICAgICAgICAgIGluZGVudFN0YXJ0ID0gbGluZUlkZW50U3RhcnQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIHJlbW92ZSB3aGl0ZXNwYWNlcyBiZWZvcmUgY3VycmVudCBsaW5lIGluZGVudGF0aW9uXHJcbiAgICAgICAgcmV0dXJuICEhbGluZUlkZW50U3RhcnRcclxuICAgICAgICAgID8gbGluZS5zdWJzdHJpbmcobGluZUlkZW50U3RhcnQpXHJcbiAgICAgICAgICA6IGxpbmU7XHJcbiAgICAgIH0pLmpvaW4oJ1xcbicpO1xyXG4gIH1cclxufVxyXG4iXX0=