今回はMarkdownをHTMLに変換して表示する方法を紹介します。
完成しているコードは下記になります。
環境
- node: 18.20.0
- Angular CLI:17.0.0
- Marked:14.1.3
- Highlight.js:11.10.0
- marked-highlight:2.2.0
プロジェクトの作成
$ ng new markdown
パッケージのインストール
$ npm install marked
MarkdownからHTMLの変換には Marked を使用します。
あとは必要に応じて Angular Material などをインストールしてください。
コンポーネントの作成
$ ng generate component component/page/marked
import { Component } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { InputComponent } from '../../share/input/input.component';
import { OutputComponent } from '../../share/output/output.component';
import { marked } from 'marked';
@Component({
selector: 'app-marked',
standalone: true,
imports: [InputComponent, OutputComponent],
templateUrl: './marked.component.html',
styleUrl: './marked.component.css'
})
export class MarkedComponent {
public safeHTML!: SafeHtml;
constructor(
private sanitizer: DomSanitizer
) { }
public async onParse(message: any) {
const content = await marked.parse(message);
this.safeHTML = this.sanitizer.bypassSecurityTrustHtml(content);
}
}
入力用のコンポーネントや出力用のコンポーネントのインポートなどをしていますが、 Markdown の出力で重要なのは下記だけです。
7行目
Marked をインポートします。
24行目
marked.parse() を使用して Markdown を HTML に変換します。
25行目
ここはMarkdonwの変換には関係ないですが、 <mat-card-content [innerHTML]="safeHtml">
で出力しているので、 XSS 対策で SafeHTML に変換しています。
確認
$ ng serve
ブラウザで「http://localhost:4200/」にアクセスすると確認できます。下記のように Markdown 形式で入力するとHTMLに変換されて表示されます。
# Ruby
``` ruby
puts 'Hello world'
```
# Python
``` python
print('Hello world')
```
# empty
```
print('Hello world')
```

シンタックスハイライト
このままだとコード部分が味気ないのでシンタックスハイライト(コードを色分け表示)していきます。シンタックスハイライトには Highlight.js と marked-highlight を使用します。
Highlight.js がコードにシンタックスハイライトをしてくれるライブラリで、marked-highlight が Highlight.js を Marked で簡単に使えるようにするライブラリとなります。
パッケージのインストール
$ npm install highlight.js marked-highlight
スタイルシートのインポート
@import 'highlight.js/styles/atom-one-dark.min.css';
html,
body {
height: 100%;
}
body {
margin: 0;
font-family: Roboto, "Helvetica Neue", sans-serif;
}
style.css に Highlight.js の css をインポートします。css が読み込めればどこで読み込んでも大丈夫です。スタイルは色々な種類があるので自分の好みのものを設定しましょう。
コンポーネントの作成
$ ng generate component component/page/highlight
import { Component } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { InputComponent } from '../../share/input/input.component';
import { OutputComponent } from '../../share/output/output.component';
import { Marked } from 'marked';
import { markedHighlight } from 'marked-highlight';
import hljs from 'highlight.js';
@Component({
selector: 'app-highlight',
standalone: true,
imports: [InputComponent, OutputComponent],
templateUrl: './highlight.component.html',
styleUrl: './highlight.component.css'
})
export class HighlightComponent {
public safeHTML!: SafeHtml;
private marked: Marked;
constructor(
private sanitizer: DomSanitizer
) {
this.marked = new Marked(
markedHighlight({
emptyLangClass: 'hljs',
langPrefix: 'hljs language-',
highlight(code, lang, info) {
const language = hljs.getLanguage(lang) ? lang : 'plaintext';
return hljs.highlight(code, { language }).value;
}
})
);
}
public async onParse(message: any) {
const content = await this.marked.parse(message);
this.safeHTML = this.sanitizer.bypassSecurityTrustHtml(content);
}
}
Marked を使用したコンポーネントを使いまわしてもいいんですが、今回は比較用に別コンポーネントを作成します。
TypeScriptではコンストラクターで Marked と Highlight.js を使えるように定義しています。
確認
$ ng serve
ブラウザで「http://localhost:4200/」にアクセスすると確認できます。下記のように Markdown 形式で入力するとHTMLに変換され、コードが色分けされて表示されます。
# Ruby
``` ruby
puts 'Hello world'
```
# Python
``` python
print('Hello world')
```
# empty
```
print('Hello world')
```

コメント