From ac18eb0739ffd303ce411bcd84dd3e2e8188fa30 Mon Sep 17 00:00:00 2001 From: taga3s Date: Sun, 3 Nov 2024 23:04:51 +0900 Subject: [PATCH] wip --- app/packages/rehype-mermaid/parser.ts | 6 ++ app/packages/rehype-mermaid/rehypeMermaid.ts | 89 ++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 app/packages/rehype-mermaid/parser.ts create mode 100644 app/packages/rehype-mermaid/rehypeMermaid.ts diff --git a/app/packages/rehype-mermaid/parser.ts b/app/packages/rehype-mermaid/parser.ts new file mode 100644 index 0000000..9d82f1d --- /dev/null +++ b/app/packages/rehype-mermaid/parser.ts @@ -0,0 +1,6 @@ +import { unified } from "unified"; +import rehypeParse from "rehype-parse"; + +const parser = unified().use(rehypeParse, { fragment: true }); + +export { parser }; diff --git a/app/packages/rehype-mermaid/rehypeMermaid.ts b/app/packages/rehype-mermaid/rehypeMermaid.ts new file mode 100644 index 0000000..4cc54a5 --- /dev/null +++ b/app/packages/rehype-mermaid/rehypeMermaid.ts @@ -0,0 +1,89 @@ +import { bundledLanguages, bundledThemes, type BundledLanguage, type BundledTheme } from "shiki"; +import type { Plugin } from "unified"; +import type { Text, Element } from "hast"; +import { visit } from "unist-util-visit"; +// import { getHighlighter } from "./highlighter"; +import { parser } from "./parser"; +import { isArray, isObject, isString } from "./utils/checkTypeOfOperandValue"; +// import { buildCodeBlockHTML } from "./buildCodeBlockHTML"; +import mermaid from "mermaid"; +mermaid.initialize({ startOnLoad: false }); + +const drawDiagram = async (graphDefinition: string) => {}; + +type Options = { + theme?: BundledTheme; + fallbackLang?: BundledLanguage; + filenameBGColor?: string; + filenameTextColor?: string; +}; + +// const defaultHighlighter = await getHighlighter({ themes: bundledThemes, langs: bundledLanguages }); + +const checkIsMermaid = (lang: string): boolean => lang === "mermaid"; + +const rehypeMermaid: Plugin = (options: Options = {}) => { + const parseLanguage = (classNames: string[]): string => { + for (const className of classNames) { + if (className.startsWith("language-")) { + return className.replace("language-", ""); + } + } + return ""; + }; + + return (node) => { + visit(node, "element", (node: Element) => { + // Check if the node is a pre tag with a single child + if (!(node.tagName === "pre" && isArray(node.children) && node.children.length === 1)) { + return; + } + + // Check if the child is a code tag + const codeElem = node.children[0] as Element; + if (!(isObject(codeElem) && codeElem.tagName === "code")) { + return; + } + + // Check if the code tag has a className property + const classNames = codeElem.properties?.className; + if (!(isArray(classNames) && classNames.length > 0 && classNames.every(isString))) { + return; + } + + // Check if the code tag has a text child + const textNode = codeElem.children[0] as Text; + if (!isString(textNode.value)) { + return; + } + + const rawCode = textNode.value.trim(); + + // Parse the language from the class names and check if it is supported + const lang = parseLanguage(classNames); + const isMermaid = checkIsMermaid(lang); + if (!isMermaid) { + return; + } + + // const highlightCode = buildCodeBlockHTML( + // rawCode, + // supportedLang, + // theme, + // filename, + // filenameBGColor, + // filenameTextColor, + // ); + + const container = ` +
isMermaid: ${isMermaid}
+ `; + + const parsedRoot = parser.parse(container); + node.tagName = "div"; + node.children = parsedRoot.children as Element[]; + }); + }; +}; + +export default rehypeMermaid;