refactor: replace comark with custom Bun.markdown

This commit is contained in:
mitchell 2026-04-19 16:39:59 -04:00
parent dd0f85a9c8
commit c0ab652135
4 changed files with 125 additions and 244 deletions

View file

@ -1,141 +1,92 @@
import { render } from "@comark/ansi";
import highlight from "@comark/ansi/plugins/highlight";
import bash from "@shikijs/langs/bash";
import c from "@shikijs/langs/c";
import cmake from "@shikijs/langs/cmake";
import cpp from "@shikijs/langs/cpp";
import csharp from "@shikijs/langs/csharp";
import css from "@shikijs/langs/css";
import dart from "@shikijs/langs/dart";
import docker from "@shikijs/langs/docker";
import dockerfile from "@shikijs/langs/dockerfile";
import dotenv from "@shikijs/langs/dotenv";
import elixir from "@shikijs/langs/elixir";
import fish from "@shikijs/langs/fish";
import golang from "@shikijs/langs/go";
import graphql from "@shikijs/langs/graphql";
import groovy from "@shikijs/langs/groovy";
import haskell from "@shikijs/langs/haskell";
import hcl from "@shikijs/langs/hcl";
import html from "@shikijs/langs/html";
import java from "@shikijs/langs/java";
import javascript from "@shikijs/langs/javascript";
import jinja from "@shikijs/langs/jinja";
import json from "@shikijs/langs/json";
import jsonc from "@shikijs/langs/jsonc";
import jsx from "@shikijs/langs/jsx";
import kotlin from "@shikijs/langs/kotlin";
import less from "@shikijs/langs/less";
import lua from "@shikijs/langs/lua";
import markdown from "@shikijs/langs/markdown";
import mdc from "@shikijs/langs/mdc";
import nginx from "@shikijs/langs/nginx";
import objc from "@shikijs/langs/objc";
import ocaml from "@shikijs/langs/ocaml";
import perl from "@shikijs/langs/perl";
import php from "@shikijs/langs/php";
import powershell from "@shikijs/langs/powershell";
import proto from "@shikijs/langs/proto";
import python from "@shikijs/langs/python";
import r from "@shikijs/langs/r";
import ruby from "@shikijs/langs/ruby";
import rust from "@shikijs/langs/rust";
import scala from "@shikijs/langs/scala";
import scss from "@shikijs/langs/scss";
import shell from "@shikijs/langs/shell";
import sql from "@shikijs/langs/sql";
import svelte from "@shikijs/langs/svelte";
import swift from "@shikijs/langs/swift";
import terraform from "@shikijs/langs/terraform";
import toml from "@shikijs/langs/toml";
import tsx from "@shikijs/langs/tsx";
import typescript from "@shikijs/langs/typescript";
import vim from "@shikijs/langs/vim";
import vue from "@shikijs/langs/vue";
import xml from "@shikijs/langs/xml";
import yaml from "@shikijs/langs/yaml";
import zig from "@shikijs/langs/zig";
import zsh from "@shikijs/langs/zsh";
import kanagawaLotus from "@shikijs/themes/kanagawa-lotus";
import kanagawaWave from "@shikijs/themes/kanagawa-wave";
// Ignore error emitted to stderr by comark highlight plugin, when missing a language.
const originalError = console.error;
console.error = (...data: unknown[]) => {
if (data.includes("Shiki highlighting error:")) return;
else originalError(data);
};
import chalk from "chalk";
import { highlight } from "cli-highlight";
import CliTable3 from "cli-table3";
export async function renderMarkdown(
text: PromiseLike<string> | string,
columns: number,
) {
return render(await text, {
width: columns,
plugins: [
highlight({
themes: { dark: kanagawaWave, light: kanagawaLotus },
registerDefaultThemes: false,
registerDefaultLanguages: false,
languages: [
bash,
c,
cmake,
cpp,
csharp,
css,
dart,
docker,
dockerfile,
dotenv,
elixir,
fish,
graphql,
golang,
groovy,
haskell,
hcl,
html,
java,
javascript,
jinja,
json,
jsonc,
jsx,
kotlin,
less,
lua,
markdown,
mdc,
nginx,
objc,
ocaml,
perl,
php,
powershell,
proto,
python,
r,
ruby,
rust,
scala,
scss,
shell,
sql,
svelte,
swift,
terraform,
toml,
tsx,
typescript,
vim,
vue,
xml,
yaml,
zig,
zsh,
],
}),
],
): Promise<string> {
const md = await text;
let currentTable = new CliTable3();
return Bun.markdown.render(md, {
heading: (children, { level }) => {
const colors = [
chalk.cyanBright.underline,
chalk.blueBright,
chalk.greenBright,
chalk.cyan,
chalk.blue,
chalk.green,
];
const color = colors[level - 1] ?? chalk.white;
return color.bold(`${"#".repeat(level)} ${children}\n\n`);
},
paragraph: (children) => `${children}\n\n`,
blockquote: (children) => {
const lines = children.split("\n");
return lines
.map((line) => `${chalk.dim("> ")}${line}`)
.join("\n")
.replace(/\n$/, "\n\n");
},
code: (children, meta) => {
let toRender = children;
if (meta?.language) {
try {
toRender = highlight(children, {
language: meta.language,
ignoreIllegals: true,
theme: { string: chalk.greenBright },
});
} catch {}
}
return `\`\`\`${chalk.green(meta?.language)}\n${toRender}\n\`\`\`\n`;
},
list: (children, { depth }) =>
`${depth > 0 ? "\n" : ""}${children}${depth === 0 ? "\n" : ""}`,
listItem: (children, { index, depth, ordered, start, checked }) => {
const indent = " ".repeat(depth);
let marker = "";
if (checked !== undefined) {
marker = checked ? "[x]" : "[ ]";
} else if (ordered) {
const n = (start ?? 1) + index;
marker = `${n}.`;
} else {
marker = "-";
}
return `${indent}${marker} ${children}\n`;
},
hr: () => `\n${chalk.dim("─".repeat(columns))}\n`,
table: (_children) => {
const toRender = currentTable.toString();
currentTable = new CliTable3();
return `${toRender}\n\n`;
},
thead: () => {
return "";
},
tr: (children) => {
if (children) currentTable.push(children.split("|").slice(1));
return "";
},
td: (children) => `|${children}`,
th: (children) => {
currentTable.options.head.push(children);
return "";
},
strong: (children) => chalk.bold(children),
emphasis: (children) => chalk.italic(children),
strikethrough: (children) => chalk.grey.strikethrough(children),
codespan: (children) => chalk.bgWhite.black(children),
link: (children, { href }) =>
chalk.blueBright(`${children}: ${chalk.underline(href)}`),
image: () => "",
text: (children) => children,
html: () => "",
});
}