ngx-showdown is an Angular (>=2) integration for Showdown, A Markdown to HTML converter.
$ npm install ngx-showdown --saveand install peer dependencies (@angular/common/http for SourceDirective)
$ npm install showdown @angular/common @angular/platform-browser --saveand install type package of Showdown for TypeScript
$ npm install @types/showdown --save-devFor more information and explanations, see the full documentation.
ShowdownModule in your app.Add ShowdownModule to imports of App.
import { NgModule } from '@angular/core';
import { ShowdownModule } from 'ngx-showdown';
@NgModule({
imports: [ ShowdownModule ]
})
export class AppModule {}Or with config (it will init ShowdownConfig provider)
import { NgModule } from '@angular/core';
import { ShowdownModule } from 'ngx-showdown';
@NgModule({
imports: [ ShowdownModule.forRoot({emoji: true, noHeaderId: true, flavor: 'github'}) ]
})
export class AppModule {}Add showdown to allowedCommonJsDependencies in the build config of the angular.json file (From angular >= 10).
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"allowedCommonJsDependencies": [
"showdown"
]
...
}
...
},
ShowdownComponent in the template[value] propertyBind markdown value to value property of showdown component.
<input type="text" [(ngModel)]="text"/>
<showdown [value]="text"></showdown>Bind value and options.
import { Component } from '@angular/core';
import * as Showdown from 'showdown';
@Component({
selector: 'some',
template: '<showdown [value]="text" [options]="options"></showdown>'
})
export class SomeComponent {
text: string = `
# h1
## h2
`;
options: Showdown.ShowdownOptions = {...};
// ...
}As directive on anther element
<div showdown="# Static" noHeaderId></div>A markdown value in the component content.
<showdown>
# H1
## H2
</showdown>With options
<showdown [options]="{smartIndentationFix: true}">
* a
* b
* c
</showdown>As directive on anther element
<span showdown emoji>:showdown:**howdown**</span>SourceDirective)Load markdown content of url source.
<showdown src="README.md"></showdown>Bind input url to src directive.
<input type="text" placeholder="Url" [(ngModel)]="url"/>
<showdown #sd [src]="url" (error)="sd.render('**Not found..**')">**No Url..**</showdown>Note: Loading markdown content requires HttpClient of @angular/common/http
When both Content and [value], It will render [value].
<showdown value="# Value"># Content</showdown>When both Content and [src], It will render Content and when src loads then results will be src content.
<showdown src="README.md"># Content</showdown>When both [value] and [src], It will render [value] and when src loads then results will be src content.
<showdown value="# Value" src="README.md"></showdown>Bind options object (it init root ShowdownConfig and then set the bind options)
import { Component } from '@angular/core';
import * as Showdown from 'showdown';
@Component({
selector: `some`,
template: `<showdown [value]="text" [options]="options"></showdown>`
})
export class SomeComponent {
text: string = '# Some';
options: Showdown.ShowdownOptions = {noHeaderId: true};
// ...
}Or
<showdown [options]="{noHeaderId: true}"># abc</showdown>Bind single option (it have input properties for all showdown options).
<showdown noHeaderId [headerLevelStart]="2" [tables]="options.tables"># abc</showdown>Sanitize the convert html output by DomSanitizer.
<showdown sanitize>
# Some
<a href="javascript:alert('Hello!')">Click</a>
__Foo__
</showdown>Also sanitize content of src url.
<showdown [value]="# Loading.." src="README.md" sanitize="true"></showdown>ShowdownPipe in the templateTransform markdown value of text property to html.
{{ text | showdown }}Transform value with options (it init root ShowdownConfig and then set the pipe options)
import { Component } from '@angular/core';
import * as Showdown from 'showdown';
@Component({
selector: 'some',
template: '{{ text | showdown:options }}'
})
export class SomeComponent {
text: string = `
# h1
## h2
`;
options: Showdown.ShowdownOptions = {smartIndentationFix: true};
// ...
}ShowdownConverter serviceimport { Injectable } from '@angular/core';
import { ShowdownConverter } from 'ngx-showdown';
@Injectable()
export class SomeService {
constructor(showdownConverter: ShowdownConverter){
console.log(showdownConverter.makeHtml('# Showdown'));
}
}ShowdownConfig)Set root config that will be injected to ShowdownComponent, ShowdownPipe, ShowdownConverter when they are created.
import { NgModel } from '@angular/core';
import { ShowdownModule, ShowdownConverter } from 'ngx-showdown';
import * as Showdown from 'showdown';
let colorExtension: Showdown.FilterExtension = {
type: 'output',
filter(text: string, converter: ShowdownConverter){
return text.replace('$color', converter.getOption('color') || 'green')
}
};
@NgModel({
imports:[
ShowdownModule.forRoot({
flavor: 'original',
emoji: true,
color: 'red',
extensions: [ colorExtension ]
})
]
})
export class AppModule {}Override the root config provider value.
import { Component } from '@angular/core';
import { ShowdownConfig } from 'ngx-showdown';
@Component({
selector: 'some',
template: '<showdown># Header</showdown>',
providers: [ {provide: ShowdownConfig, useValue: {underline: true, emoji: false}} ]
})
export class SomeComponent {}Set the config manually by the converter methods.
import { Component } from '@angular/core';
import { ShowdownComponent } from 'ngx-showdown';
import highlightExtension from 'showdown-highlight';
import 'highlight.js/styles/default.css';
@Component({
selector: 'some',
template: '<showdown># Header</showdown>'
})
export class SomeComponent {
constructor(showdownComponent: ShowdownComponent) {
showdownComponent.addExtension(highlightExtension);
showdownComponent.setFlavor('ghost');
showdownComponent.setOptions({emoji: true});
}
}Set root flavor (Showdown flavors).
import { NgModel } from '@angular/core';
import { ShowdownModule } from 'ngx-showdown';
@NgModel({
imports:[
ShowdownModule.forRoot({flavor: 'github'})
]
})
export class AppModule {}Note: If flavor is not set then the default value is 'vanilla' flavor.
Set root ConverterOptions (Showdown options).
import { NgModel } from '@angular/core';
import { ShowdownModule } from 'ngx-showdown';
@NgModel({
imports:[
ShowdownModule.forRoot({underline: true, emoji: false})
]
})
export class AppModule {}Set root Extensions (Showdown extensions).
With extension can be made changes to the Markdown input ('lang') and the Html output also listen to parse event, you can make extension or search in npm for existing extension.
import { NgModel } from '@angular/core';
import { ShowdownModule } from 'ngx-showdown';
import * as Showdown from 'showdown';
import highlightExtension from 'showdown-highlight';
import 'highlight.js/styles/default.css';
let someExtension: Showdown.ShowdownExtension = {
type: 'lang',
regex: new RegExp('markdown', 'g'),
replace: 'showdown'
};
@NgModel({
imports: [
ShowdownModule.forRoot({extensions: [ someExtension, highlightExtension ]})
]
})
export class AppModule {}Using unescaped {} (<showdown>{}</showdown>) in template causes an template parse error (@angular/angular/#11859),
The solution is to use escape chars (html char code etc.),
Anther solution is to override the default interpolation.
Angular aot compiler remove whitespaces by default, use ngPreserveWhitespaces to preserve whitespaces.
<showdown ngPreserveWhitespaces>
* a
* 1
* 2
* b
</showdown>With ngPreserveWhitespaces
* a
* 1
* 2
* bWithout ngPreserveWhitespaces
* a * 1 * 2
* bShowdown converter smartIndentationFix option can fix string indentation problems of es6 template and html.
text = `
# A
## B
`;<showdown [value]="text" smartIndentationFix></showdown>With smartIndentationFix
# A
## BWithout smartIndentationFix
# A
## BPull requests are welcome!
This project built with Angular Cli.
Install dependencies
$ yarn installRun test
$ yarn testBuild for release
$ yarn buildThis project use Showdown library to convert Markdown to Html.
Copyright © Yisrael Eliav, Licensed under the MIT license.