|
1 | 1 | import { Injectable } from '@angular/core'; |
2 | | -import { Marked } from 'marked'; |
3 | | -import markedShiki from 'marked-shiki'; |
4 | | -import { bundledThemes, createHighlighter } from 'shiki/bundle/web'; |
| 2 | +import { setupMarkdownRenderer, type MarkdownRenderer } from 'igniteui-webcomponents/extras'; |
5 | 3 |
|
6 | 4 |
|
7 | | -const DEFAULT_LANGUAGES = ['javascript', 'typescript', 'html', 'css']; |
8 | | -const DEFAULT_THEMES = { |
9 | | - light: 'github-light', |
10 | | - dark: 'github-dark' |
11 | | -}; |
12 | | - |
13 | 5 | @Injectable({ providedIn: 'root' }) |
14 | 6 | export class IgxChatMarkdownService { |
15 | 7 |
|
16 | | - private _instance: Marked; |
17 | | - private _isInitialized: Promise<void>; |
18 | | - |
19 | | - private _initializeMarked(): void { |
20 | | - this._instance = new Marked({ |
21 | | - breaks: true, |
22 | | - gfm: true, |
23 | | - extensions: [ |
24 | | - { |
25 | | - name: 'link', |
26 | | - renderer({ href, title, text }) { |
27 | | - return `<a href="${href}" target="_blank" rel="noopener noreferrer" ${title ? `title="${title}"` : ''}>${text}</a>`; |
28 | | - } |
29 | | - } |
30 | | - ] |
31 | | - }); |
32 | | - } |
33 | | - |
34 | | - private async _initializeShiki(): Promise<void> { |
35 | | - const highlighter = await createHighlighter({ |
36 | | - langs: DEFAULT_LANGUAGES, |
37 | | - themes: Object.keys(bundledThemes) |
38 | | - }); |
39 | | - |
40 | | - this._instance.use( |
41 | | - markedShiki({ |
42 | | - highlight(code, lang, _) { |
43 | | - try { |
44 | | - return highlighter.codeToHtml(code, { |
45 | | - lang, |
46 | | - themes: DEFAULT_THEMES, |
47 | | - }); |
48 | | - |
49 | | - } catch { |
50 | | - return `<pre><code>${code}</code></pre>`; |
51 | | - } |
52 | | - } |
53 | | - }) |
54 | | - ); |
55 | | - } |
56 | | - |
| 8 | + private _renderer: MarkdownRenderer | null = null; |
57 | 9 |
|
58 | | - constructor() { |
59 | | - this._initializeMarked(); |
60 | | - this._isInitialized = this._initializeShiki(); |
| 10 | + private async _getRenderer(): Promise<MarkdownRenderer> { |
| 11 | + if (!this._renderer) { |
| 12 | + this._renderer = await setupMarkdownRenderer(); |
| 13 | + } |
| 14 | + return this._renderer; |
61 | 15 | } |
62 | 16 |
|
63 | 17 | public async parse(text: string): Promise<string> { |
64 | | - await this._isInitialized; |
65 | | - return await this._instance.parse(text); |
| 18 | + const renderer = await this._getRenderer(); |
| 19 | + return await renderer.parse(text); |
66 | 20 | } |
67 | 21 | } |
0 commit comments