Skip to content

Commit

Permalink
Merge pull request #51 from taga3s/refactor/rehype-plugins
Browse files Browse the repository at this point in the history
Refactor rehype plugins
  • Loading branch information
taga3s authored Nov 24, 2024
2 parents 5b5f00d + 10d7c23 commit 515f13d
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 83 deletions.
9 changes: 5 additions & 4 deletions app/packages/rehype-mermaid/rehypeMermaid.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { Plugin } from "unified";
import type { Text, Element, Parent } from "hast";
import type { Text, Element, Parent, Nodes } from "hast";
import { visit } from "unist-util-visit";
import { renderMermaid } from "@mermaid-js/mermaid-cli";
import puppeteer from "puppeteer";
import { parser } from "./parser";
import type { Node } from "unist";

interface MermaidCodeBlock {
textNode: Text;
Expand All @@ -23,10 +24,10 @@ const rehypeMermaid: Plugin = () => {

const checkIsMermaid = (lang: string): boolean => lang === "mermaid";

return async (node) => {
return async (tree: Node) => {
const mermaidCodeBlocks: MermaidCodeBlock[] = [];

visit(node, "element", (node: Element, index: number, parent: Parent) => {
visit(tree as Nodes, "element", (node, index, parent) => {
// Check if the node is a pre tag with a single child
if (!(node.tagName === "pre" && Array.isArray(node.children) && node.children.length === 1)) {
return;
Expand Down Expand Up @@ -60,7 +61,7 @@ const rehypeMermaid: Plugin = () => {
const lang = parseLanguage(classNames);
const isMermaid = checkIsMermaid(lang);

if (isMermaid && index !== null && parent !== null) {
if (isMermaid && index && parent) {
mermaidCodeBlocks.push({ textNode, index, parent });
}
});
Expand Down
74 changes: 35 additions & 39 deletions app/packages/rehype-momiji/buildCodeBlock.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,54 @@
import { bundledLanguages, bundledThemes, type BundledTheme } from "shiki";
import { getHighlighter } from "./highlighter";
import type { BundledLanguage, HighlighterGeneric, BundledTheme } from "shiki";
import { toHtml } from "hast-util-to-html";
import type { Element } from "hast";
import { COLOR_SHIRONERI, COLOR_HAI } from "./colors";
import { visit } from "unist-util-visit";

const defaultHighlighter = await getHighlighter({ themes: bundledThemes, langs: bundledLanguages });

const buildCodeBlock = (
highlighter: HighlighterGeneric<BundledLanguage, BundledTheme>,
rawCode: string,
lang: string,
theme: BundledTheme,
filename: string,
filenameBGColor?: string,
filenameTextColor?: string,
) => {
const hast = defaultHighlighter.codeToHast(rawCode, {
lang: lang,
theme: theme,
});
const filenameColorStyle = `background-color: ${filenameBGColor ?? COLOR_HAI}; color: ${filenameTextColor ?? COLOR_SHIRONERI};`;

if (filename === "") {
return toHtml(hast);
}
const hast = highlighter.codeToHast(rawCode, {
lang: lang,
theme: theme,
transformers: [
{
pre(this, node) {
if (filename === "") return;

// Add filename to the code block if it exists
visit(hast, "element", (node: Element) => {
if (
node.tagName === "pre" &&
node.properties.class &&
typeof node.properties.class === "string" &&
node.properties.class.includes("shiki")
) {
node.properties = {
class: node.properties.class,
style: `${node.properties.style}; padding-top: 48px;`,
tabindex: node.properties.tabindex,
};
if (
node.properties.class &&
typeof node.properties.class === "string" &&
node.properties.class.includes("shiki")
) {
node.properties = {
class: node.properties.class,
style: `${node.properties.style}; padding-top: 48px;`,
tabindex: node.properties.tabindex,
};

node.children.unshift({
type: "element",
tagName: "div",
properties: {
style: `position: absolute; top: 0; left: 16px; width: fit-content; margin-bottom: 16px; padding: 4px 8px; font-size: 14px; border-radius: 0 0 4px 4px; ${filenameColorStyle}`,
node.children.unshift({
type: "element",
tagName: "div",
properties: {
style: `position: absolute; top: 0; left: 16px; width: fit-content; margin-bottom: 16px; padding: 4px 8px; font-size: 14px; border-radius: 0 0 4px 4px; ${filenameColorStyle}`,
},
children: [
{
type: "text",
value: filename,
},
],
});
}
},
children: [
{
type: "text",
value: filename,
},
],
});
}
},
],
});

return toHtml(hast);
Expand Down
19 changes: 14 additions & 5 deletions app/packages/rehype-momiji/rehypeMomiji.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { bundledLanguages, bundledThemes, type BundledLanguage, type BundledTheme } from "shiki";
import type { Node } from "unist";
import type { Plugin } from "unified";
import type { Text, Element } from "hast";
import type { Text, Element, Nodes } from "hast";
import { visit } from "unist-util-visit";
import { getHighlighter } from "./highlighter";
import { parser } from "./parser";
Expand All @@ -18,7 +18,6 @@ interface Option {
const defaultHighlighter = await getHighlighter({ themes: bundledThemes, langs: bundledLanguages });

const rehypeMomiji: Plugin<Option[]> = (options) => {
const langs = defaultHighlighter.getLoadedLanguages();
const {
theme = "github-dark-default",
fallbackLang = "c",
Expand All @@ -27,6 +26,8 @@ const rehypeMomiji: Plugin<Option[]> = (options) => {
filenameTextColor,
} = options;

const langs = defaultHighlighter.getLoadedLanguages();

const parseLanguage = (classNames: string[]): string | undefined => {
for (const className of classNames) {
if (className.startsWith("language-")) {
Expand All @@ -41,8 +42,8 @@ const rehypeMomiji: Plugin<Option[]> = (options) => {
return fallbackLang;
};

return (node: Node) => {
visit(node, "element", (node: Element) => {
return (tree: Node) => {
visit(tree as Nodes, "element", (node) => {
// Check if the node is a pre tag with a single child
if (!(node.tagName === "pre" && Array.isArray(node.children) && node.children.length === 1)) {
return;
Expand Down Expand Up @@ -89,7 +90,15 @@ const rehypeMomiji: Plugin<Option[]> = (options) => {

const filename = (codeElem.properties["data-remark-code-filename"] as string) ?? "";

const codeBlock = buildCodeBlock(rawCode, supportedLang, theme, filename, filenameBGColor, filenameTextColor);
const codeBlock = buildCodeBlock(
defaultHighlighter,
rawCode,
supportedLang,
theme,
filename,
filenameBGColor,
filenameTextColor,
);

const container = `
<div style="position: relative; display: flex; flex-direction: column; gap: 2px;">
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"remark-frontmatter": "^5.0.0",
"remark-gfm": "^4.0.0",
"remark-mdx-frontmatter": "^5.0.0",
"shiki": "^1.23.0",
"shiki": "^1.23.1",
"unified": "^11.0.5",
"unist": "^0.0.1",
"unist-util-visit": "^5.0.0",
Expand Down
70 changes: 36 additions & 34 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 515f13d

Please sign in to comment.