feat: isolate mermaid code

This commit is contained in:
Julien Calixte
2025-06-14 09:56:54 +02:00
parent 40f4ff1a00
commit 487fedf9fa

View File

@@ -1,44 +1,76 @@
import markdownItClass from '@toycode/markdown-it-class' import markdownItClass from "@toycode/markdown-it-class"
import markdownItLatex from '@vscode/markdown-it-katex' import markdownItLatex from "@vscode/markdown-it-katex"
import MarkdownIt from 'markdown-it' import MarkdownIt, { Options, Renderer, Token } from "markdown-it"
import Renderer from 'markdown-it/lib/renderer' import blockEmbedPlugin from "markdown-it-block-embed"
import blockEmbedPlugin from 'markdown-it-block-embed' import markdownItCheckbox from "markdown-it-checkbox"
import markdownItCheckbox from 'markdown-it-checkbox' import markdownItFootnote from "markdown-it-footnote"
import markdownItFootnote from 'markdown-it-footnote' import MarkdownItGitHubAlerts from "markdown-it-github-alerts"
import MarkdownItGitHubAlerts from 'markdown-it-github-alerts' import markdownItIframe from "markdown-it-iframe"
import markdownItIframe from 'markdown-it-iframe' import Shikiji from "markdown-it-shikiji"
import Shikiji from 'markdown-it-shikiji' import { Ref, toValue } from "vue"
import { Ref, toValue } from 'vue'
import { decodeBase64ToUTF8 } from '@/utils/decodeBase64ToUTF8' import { decodeBase64ToUTF8 } from "@/utils/decodeBase64ToUTF8"
import { html5Media } from '@/utils/markdown/markdown-html5-media' import { html5Media } from "@/utils/markdown/markdown-html5-media"
import { twitterPlugin } from '@/utils/markdown/markdown-it-twitter' import { twitterPlugin } from "@/utils/markdown/markdown-it-twitter"
import mermaid from "mermaid"
const markdownItMermaidExtractor = (md: MarkdownIt) => {
const defaultFence =
md.renderer.rules.fence ||
function (
tokens: Array<Token>,
index: number,
options: Options,
_: unknown,
self: Renderer,
) {
return self.renderToken(tokens, index, options)
}
md.renderer.rules.fence = function (
tokens: Array<Token>,
index: number,
options: Options,
env: unknown,
self: Renderer,
) {
const token = tokens[index]
if (token.info.trim() === "mermaid") {
const content = token.content.trim()
return `<pre class="mermaid">\n${md.utils.escapeHtml(content)}\n</pre>\n`
}
return defaultFence(tokens, index, options, env, self)
}
}
const md = new MarkdownIt({ const md = new MarkdownIt({
typographer: true, typographer: true,
quotes: ['«\xA0', '\xA0»', '\xA0', '\xA0'] quotes: ["«\xA0", "\xA0»", "\xA0", "\xA0"],
}) })
.use(markdownItClass, { .use(markdownItClass, {
h1: ['title', 'is-2'], h1: ["title", "is-2"],
h2: ['title', 'is-3'], h2: ["title", "is-3"],
h3: ['title', 'is-4'], h3: ["title", "is-4"],
h4: ['title', 'is-5'], h4: ["title", "is-5"],
h5: ['title', 'is-6'], h5: ["title", "is-6"],
h6: ['title', 'is-6'] h6: ["title", "is-6"],
}) })
.use(markdownItMermaidExtractor)
.use(html5Media) .use(html5Media)
.use(blockEmbedPlugin, { .use(blockEmbedPlugin, {
youtube: { youtube: {
width: '100%', width: "100%",
height: 300 height: 300,
} },
}) })
.use(twitterPlugin) .use(twitterPlugin)
.use(markdownItCheckbox) .use(markdownItCheckbox)
.use(markdownItFootnote) .use(markdownItFootnote)
.use(markdownItLatex) .use(markdownItLatex)
.use(markdownItIframe, { .use(markdownItIframe, {
width: '100%' width: "100%",
}) })
.use(MarkdownItGitHubAlerts) .use(MarkdownItGitHubAlerts)
@@ -46,19 +78,21 @@ const useShikiji = async () => {
md.use( md.use(
await Shikiji({ await Shikiji({
themes: { themes: {
light: 'vitesse-light', light: "vitesse-light",
dark: 'vitesse-black' dark: "vitesse-black",
} },
}) }),
) )
} }
useShikiji() useShikiji()
mermaid.initialize({ startOnLoad: false })
const rules: Renderer.RenderRuleRecord = { const rules: Renderer.RenderRuleRecord = {
table_open: () => table_open: () =>
'<div class="overflow-x-auto"><table class="table table-zebra">', '<div class="overflow-x-auto"><table class="table table-zebra">',
table_close: () => '</table></div>' table_close: () => "</table></div>",
} }
md.renderer.rules = { ...md.renderer.rules, ...rules } md.renderer.rules = { ...md.renderer.rules, ...rules }
@@ -68,15 +102,15 @@ export const useMarkdown = (defaultPrefix?: Ref<string> | string) => {
const renderFromUTF8 = (content: string, prefix?: string) => const renderFromUTF8 = (content: string, prefix?: string) =>
content content
? md.render(content, { ? md.render(content, {
docId: defaultPrefix ? toValue(defaultPrefix) : (prefix ?? '') docId: defaultPrefix ? toValue(defaultPrefix) : (prefix ?? ""),
}) })
: '' : ""
return { return {
toHTML: (content: string) => (content ? md.render(content) : ''), toHTML: (content: string) => (content ? md.render(content) : ""),
render: (content: string, prefix?: string) => render: (content: string, prefix?: string) =>
renderFromUTF8(decodeBase64ToUTF8(content), prefix), renderFromUTF8(decodeBase64ToUTF8(content), prefix),
renderFromUTF8, renderFromUTF8,
getRawContent getRawContent,
} }
} }