refactor: migrate shiki to core API with dynamic language/theme loading

- Update code block regex to support symbols/numbers in language identifiers
- Adjust codespan background color to a softer shade
This commit is contained in:
mitchell 2026-06-03 15:52:49 -04:00
parent 6372dfc41f
commit 3e96007f1f
3 changed files with 24 additions and 14 deletions

View file

@ -15,6 +15,7 @@ const { values: args, positionals } = parseArgs({
n: { type: "boolean" }, n: { type: "boolean" },
config: { type: "boolean" }, config: { type: "boolean" },
c: { type: "boolean" }, c: { type: "boolean" },
v: { type: "boolean" },
plain: { type: "boolean" }, plain: { type: "boolean" },
plainOut: { type: "boolean" }, plainOut: { type: "boolean" },
plainErr: { type: "boolean" }, plainErr: { type: "boolean" },
@ -30,6 +31,11 @@ async function main() {
const modelFlag = args.model ?? args.m; const modelFlag = args.model ?? args.m;
const configFlag = args.config ?? args.c; const configFlag = args.config ?? args.c;
if (args.v) {
console.log("0.0.0");
return;
}
const config = await loadConfig(configFlag); const config = await loadConfig(configFlag);
if (configFlag || !config) { if (configFlag || !config) {

View file

@ -24,7 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. */ SOFTWARE. */
import c from "chalk"; import c from "chalk";
import type { BundledLanguage, BundledTheme, HighlighterGeneric } from "shiki"; import type { BundledLanguage, BundledTheme, HighlighterCore } from "shiki";
// From @shikijs/vscode-textmate // From @shikijs/vscode-textmate
enum FontStyle { enum FontStyle {
@ -37,7 +37,7 @@ enum FontStyle {
} }
export function codeToANSI( export function codeToANSI(
highlighter: HighlighterGeneric<BundledLanguage, BundledTheme>, highlighter: HighlighterCore,
code: string, code: string,
lang: BundledLanguage, lang: BundledLanguage,
theme: BundledTheme, theme: BundledTheme,

View file

@ -1,18 +1,15 @@
import { Cell, Table } from "@cliffy/table"; import { Cell, Table } from "@cliffy/table";
import chalk from "chalk"; import chalk from "chalk";
import { marked, Renderer, type Tokens } from "marked"; import { marked, Renderer, type Tokens } from "marked";
import { import type { BundledLanguage, HighlighterCore } from "shiki";
type BundledLanguage, import { createHighlighterCore } from "shiki/core";
type BundledTheme, import { createOnigurumaEngine } from "shiki/engine/oniguruma";
createHighlighter,
type HighlighterGeneric,
} from "shiki";
import stringWidth from "string-width"; import stringWidth from "string-width";
import terminalLink from "terminal-link"; import terminalLink from "terminal-link";
import wrapAnsi from "wrap-ansi"; import wrapAnsi from "wrap-ansi";
import { codeToANSI } from "./codeToANSI"; import { codeToANSI } from "./codeToANSI";
let highlighter: HighlighterGeneric<BundledLanguage, BundledTheme> | undefined; let highlighter: HighlighterCore | undefined;
let highligherLangs = ""; let highligherLangs = "";
class SWCell extends Cell { class SWCell extends Cell {
@ -147,7 +144,7 @@ class LmcRenderer extends Renderer {
} }
override codespan({ text }: Tokens.Codespan) { override codespan({ text }: Tokens.Codespan) {
return chalk.bgYellow.black.bold(text); return chalk.bgRgb(165, 165, 190).black.bold(text);
} }
override link({ href, tokens }: Tokens.Link) { override link({ href, tokens }: Tokens.Link) {
@ -194,15 +191,22 @@ export async function renderMarkdown(
const md = await text; const md = await text;
const langs = md const langs = md
.match(/```[a-z]+\n/g) .match(/```\S+\n/g)
?.map((lang) => lang.replace("```", "").trimEnd()); ?.map((lang) => lang.replace("```", "").trimEnd());
if (langs && langs?.join() !== highligherLangs) { if (langs && langs?.join() !== highligherLangs) {
const { bundledThemes, bundledLanguages, bundledLanguagesAlias } =
await import("shiki/bundle/full");
try { try {
highligherLangs = langs.join(); highligherLangs = langs.join();
highlighter = await createHighlighter({ highlighter = await createHighlighterCore({
langs, langs: langs.map(
themes: ["kanagawa-wave", "kanagawa-lotus"], (lang) =>
bundledLanguages[lang as BundledLanguage] ||
bundledLanguagesAlias[lang],
),
themes: [bundledThemes["kanagawa-wave"]],
engine: createOnigurumaEngine(import("shiki/wasm")),
}); });
} catch {} } catch {}
} }