Kalian akan memakai API inti Shiki seperti createHighlighter, createHighlighterCore, codeToHtml, codeToTokens, dan getSingletonHighlighter, lalu mengintegrasikan Shiki langsung di luar rehype seperti markdown-it dan skrip render manual.

Sejauh ini kalian memakai Shiki lewat rehype-pretty-code. Padahal Shiki adalah library mandiri yang bisa dipanggil langsung dari kode apa pun: build script, markdown-it, atau server API. Memahami API intinya membuka kemungkinan di luar ekosistem rehype.
Episode 18 membahas Shiki core dan highlighter API: createHighlighter, createHighlighterCore, codeToHtml, codeToTokens, dan getSingletonHighlighter, plus contoh pemakaian di luar rehype seperti markdown-it dan render manual dari Node.js.
Cara paling sederhana membuat highlighter adalah createHighlighter. Fungsi ini memuat langs dan themes yang kalian tentukan, lalu mengembalikan instance yang siap dipakai:
import { createHighlighter } from "shiki";
const highlighter = await createHighlighter({
langs: ["typescript", "css", "json"],
themes: ["github-dark-default"],
});Daftar langs dan themes yang dipilih akan dimuat ke memory. Semakin sedikit isinya, semakin cepat inisialisasi. Instance ini bisa dipakai berkali-kali untuk kode yang berbeda.
Untuk pemakaian sekali jalan, Shiki menyediakan fungsi pendek yang membuat highlighter internal secara otomatis:
import { codeToHtml } from "shiki";
const html = await codeToHtml('console.log("halo")', {
lang: "typescript",
theme: "github-dark-default",
});Fungsi codeToHtml praktis untuk skrip kecil. Untuk pemakaian berulang dalam proses yang sama, buat instance sendiri supaya grammar tidak dimuat ulang setiap panggilan.
Ketika ukuran bundle kritis, gunakan createHighlighterCore dari shiki/core. Entry point ini tidak memuat bahasa, theme, maupun WASM secara otomatis:
import { createHighlighterCore } from "shiki/core";
import { createOnigurumaEngine } from "@shikijs/engine-oniguruma";
const highlighter = await createHighlighterCore({
langs: [import("@shikijs/langs/typescript")],
themes: [import("@shikijs/themes/github-dark-default")],
engine: createOnigurumaEngine(import("shiki/wasm")),
});Setiap bahasa dimuat lewat import dinamis sehingga bundler memecahnya menjadi chunk terpisah. Engine disuntikkan secara eksplisit, memberi kendali penuh atas cara tokenisasi berjalan.
Highlight tidak selalu berarti membuat HTML. codeToTokens mengembalikan token sebagai data mentah, berguna untuk analisis atau render kustom:
const result = await highlighter.codeToTokens(
"const x = 1;",
{ lang: "typescript", theme: "github-dark-default" },
);
for (const line of result.tokens) {
for (const token of line) {
console.log(token.content, token.color);
}
}Setiap token membawa content (teks asli) dan color (warna hasil theme). Dengan data ini, kalian bisa merender kode ke format lain, seperti canvas atau SVG.
Membuat highlighter di beberapa tempat bisa memuat grammar yang sama berulang kali. getSingletonHighlighter menjamin hanya satu instance yang dibuat dan dipakai bersama:
import { getSingletonHighlighter } from "shiki";
const highlighter = await getSingletonHighlighter({
langs: ["typescript"],
themes: ["github-dark-default"],
});
const html = highlighter.codeToHtml("const a = 1;", {
lang: "typescript",
theme: "github-dark-default",
});Pemanggilan kedua dengan konfigurasi serupa tidak membuat instance baru; grammar yang sudah ada langsung dipakai ulang. Ini mencegah kebocoran memory di proses yang panjang seperti server.
markdown-it memiliki opsi highlight untuk menggantikan renderer kode default. Masukkan codeToHtml di sana:
import MarkdownIt from "markdown-it";
import { codeToHtml } from "shiki";
const md = new MarkdownIt({
highlight(code, lang) {
return codeToHtml(code, {
lang: lang || "plaintext",
theme: "github-dark-default",
});
},
});Ketika markdown-it menemukan fenced code block, opsi highlight dipanggil dan hasil HTML Shiki dipakai sebagai output. Pola yang sama berlaku untuk library Markdown lain yang menyediakan hook highlight.
Tanpa library Markdown sama sekali, kalian bisa membaca kode lalu menulis hasil highlight ke file:
node render.mjsimport { readFile, writeFile } from "node:fs/promises";
import { codeToHtml } from "shiki";
const code = await readFile("./snippet.ts", "utf8");
const html = await codeToHtml(code, {
lang: "typescript",
theme: "github-dark-default",
});
await writeFile("./snippet.html", html);Skrip semacam ini bisa dijalankan di build pipeline untuk menghasilkan halaman statis tanpa framework. Karena semuanya berjalan di Node.js, file WASM Oniguruma tetap mudah dimuat lewat shiki/wasm.
Inti yang harus dibawa pulang:
createHighlighter memuat langs dan themes lalu siap dipakai berulang.codeToHtml adalah fungsi pendek untuk pemakaian sekali jalan.createHighlighterCore memberi kendali penuh atas bundle dan engine.codeToTokens mengembalikan token mentah untuk render kustom.getSingletonHighlighter membagi satu instance di banyak tempat.Di episode 19 kalian akan belajar performance dan troubleshooting: mendiagnosis masalah output HTML, membaca log build, dan menangani masalah umum seperti grammar yang tidak termuat, error WASM, bahasa yang tidak dikenali, meta yang tidak ter-parse, serta konflik dengan CSS theme.