前回までの3記事の総まとめです。
完成しているコードは下記にあります。
Angular-sample/markdown at main · tsuneken5/Angular-sample
Contribute to tsuneken5/Angular-sample development by creating an account on GitHub.
環境
- node: 18.20.0
- Angular CLI:17.0.0
- Marked:14.1.3
- Highlight.js:11.10.0
- marked-katex-extension:5.1.2
- Mermaid:11.3.0
パッケージのインストール
$ npm install marked highlight.js marked-katex-extension mermaid
今回は Mermaid との兼ね合いで自分で Highlight.js を使用するための設定を自分で設定する必要があるため、 marked-highlight は使いません。
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"esModuleInterop": true,
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "ES2022",
"module": "ES2022",
"useDefineForClassFields": false,
"skipLibCheck": true,
"lib": [
"ES2022",
"dom"
]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}
"skipLibCheck": true
を設定します。
コンポーネントの生成
$ ng generate component component/page/markdown
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, Renderer, Tokens } from 'marked';
import hljs from 'highlight.js';
import markedKatex from "marked-katex-extension";
import mermaid from 'mermaid';
@Component({
selector: 'app-markdown',
standalone: true,
imports: [InputComponent, OutputComponent],
templateUrl: './markdown.component.html',
styleUrl: './markdown.component.css'
})
export class MarkdownComponent {
public safeHTML!: SafeHtml;
private readonly KATEX_OPTIONS = {
throwOnError: false
};
constructor(
private sanitizer: DomSanitizer
) {
mermaid.initialize({ startOnLoad: false });
this.setupMarked();
}
private setupMarked() {
const renderer: Renderer = new marked.Renderer();
renderer.code = function ({ text, lang, escaped }: Tokens.Code): string {
if (lang === 'mermaid') {
return `<div class="mermaid">${text}</div>`;
}
const language = lang || 'plaintext';
if (language == 'plaintext') {
return `<pre><code class="hljs">${marked.parseInline(text)}</code></pre>`;
} else {
return `<pre><code class="hljs language-${language}">${hljs.highlight(text, { language }).value}</code></pre>`;
}
};
marked.use({ renderer });
marked.use(markedKatex(this.KATEX_OPTIONS))
}
public async onParse(message: any) {
const content = await marked.parse(message);
this.safeHTML = this.sanitizer.bypassSecurityTrustHtml(content);
setTimeout(async () => {
await mermaid.run({
querySelector: '.mermaid',
});
}, 0);
}
}
33~50行目
Mermaid と Highlight.js を同時に使うための Render を設定しています。コードブロックで mermaid が指定されていたら図式できるように <div class="mermaid></div>
要素を返し、それ以外が指定された場合は Highlight.js の機能を使ってシンタックスハイライトで色分けされるように <pre><code class="hljs"></code></pre>
要素を返すようにします。
確認
上記で設定したように、Mermaid もコードブロックで入力します。
# Python
``` python
print('Hello world')
```
# KaTeX
This is inline katex: $c = \pm\sqrt{a^2 + b^2}$
# Mermaid
``` mermaid
graph LR
A["$$x^2$$"] -->|"$$\sqrt{x+3}$$"| B("$$\frac{1}{2}$$")
```

コメント