Overview
CodeInk uses Shiki for syntax highlighting, providing accurate, beautiful highlighting that matches VS Code’s tokenization. Shiki uses TextMate grammars to ensure precise syntax recognition.
Supported Languages
Core Languages
CodeInk includes optimized support for 60+ languages loaded on-demand:
Web
HTML
CSS / SCSS / Sass / Less
JavaScript / TypeScript
JSX / TSX
Vue / Svelte
Backend
Python
Go
Rust
Java
Ruby
PHP
DevOps
Bash / Shell
Dockerfile
Terraform / HCL
YAML / TOML
Nginx
Complete Language List
const LANGUAGE_LOADERS = {
html , js , ts , tsx , jsx , css , json , bash , markdown , python ,
yaml , go , hcl , dockerfile , sql , rust , java , xml , c , cpp ,
csharp , dart , graphql , kotlin , less , lua , nginx , php ,
powershell , r , ruby , sass , scss , svelte , swift , terraform ,
latex , mermaid , toml , vue
}
Theme Support
Dual Theme System
Shiki is configured with both light and dark themes that automatically match the application theme:
One Dark Pro - A refined dark theme with excellent contrast:import darkTheme from "@shikijs/themes/one-dark-pro"
const THEME = {
dark: "one-dark-pro" ,
light: "github-light" ,
}
Provides rich, saturated colors optimized for long coding sessions. GitHub Light - Clean, professional light theme:import lightTheme from "@shikijs/themes/github-light"
Familiar color scheme matching GitHub’s code blocks.
Dynamic Theme Switching
The active theme is determined from the document’s data attribute:
function getDocumentTheme () : "light" | "dark" {
if ( typeof document === "undefined" ) return "dark"
const theme = document . documentElement . getAttribute ( "data-theme" )
return theme === "light" ? "light" : "dark"
}
// Applied during highlighting
return h . codeToHtml ( code , {
lang: resolvedLang ,
theme: THEME [ getDocumentTheme ()],
transformers: [ ... ]
})
Language Detection
Language Aliases
Common language aliases are automatically resolved:
const LANGUAGE_ALIASES = {
plaintext: "text" ,
javascript: "js" ,
typescript: "ts" ,
docker: "dockerfile" ,
md: "markdown" ,
yml: "yaml" ,
sh: "bash" ,
shell: "bash" ,
ps1: "powershell" ,
tf: "terraform" ,
tfvars: "terraform" ,
tex: "latex" ,
mmd: "mermaid" ,
}
Normalization Process
function normalizeLanguage ( lang ?: string ) : string {
const normalized = ( lang ?? "" ). toLowerCase ()
if ( ! normalized ) return "text"
return LANGUAGE_ALIASES [ normalized ] ?? normalized
}
Lazy Language Loading
Languages are loaded on-demand to minimize initial bundle size:
const loadedLanguages = new Set < string >()
async function ensureLanguageLoaded ( h : HighlighterCore , lang : string ) {
if ( loadedLanguages . has ( lang )) return
const language = await LANGUAGE_LOADERS [ lang ]()
h . loadLanguage ( language . default )
loadedLanguages . add ( lang )
}
Only languages actually used in the document are loaded, reducing memory usage and load time.
JavaScript Regex Engine
Shiki uses a lightweight JavaScript regex engine instead of Oniguruma for better performance:
import { createJavaScriptRegexEngine } from "shiki/engine/javascript"
let jsEngine : RegexEngine | null = null
const getJsEngine = () : RegexEngine => {
jsEngine ??= createJavaScriptRegexEngine ()
return jsEngine
}
const highlighter = createHighlighterCore ({
themes: [ darkTheme , lightTheme ],
langs: [],
engine: getJsEngine (),
})
Singleton Highlighter
A single highlighter instance is reused across all highlighting operations:
let highlighter : Promise < HighlighterCore > | null = null
const highlight = async () : Promise < HighlighterCore > => {
highlighter ??= createHighlighterCore ({
themes: [ darkTheme , lightTheme ],
langs: [],
engine: getJsEngine (),
})
return highlighter
}
Code Block Rendering
Enhanced Code Blocks
Code blocks include language indicators and copy buttons:
const renderer = {
code ({ text , lang } : Tokens . Code ) {
const highlighted = highlightMap . get ( text ) ?? text
const label = normalizedLang || "text"
const iconPath = `/icons/lang/ ${ iconLabel } .svg`
const displayLabel = label . charAt ( 0 ). toUpperCase () + label . slice ( 1 )
return `
<div class="code-block group" data-language=" ${ label } ">
<div class="code-block-header">
<div class="code-block-lang-info">
<img src=" ${ iconPath } " alt="" />
<span class="code-block-lang"> ${ displayLabel } </span>
</div>
<button class="copy-code-btn" type="button">
<!-- Copy icon -->
</button>
</div>
${ highlighted }
</div>
`
},
}
Line Numbers
Line numbers are added using a custom Shiki transformer:
const showLineNumbers = () : ShikiTransformer => ({
name: "AddLineNumbers" ,
pre ( node ) {
appendClass ( node , "shiki-line-numbers" )
},
})
Word Wrapping
Optional word wrapping for long lines:
const wordWrapContent = () : ShikiTransformer => ({
name: "WordWrap" ,
pre ( node ) {
appendClass ( node , "shiki-word-wrap" )
},
})
Integration with Marked
Async Token Walking
Highlighting is performed asynchronously during markdown parsing:
marked . use ({
async: true ,
async walkTokens ( token : Token ) {
if ( token . type === "code" ) {
const codeToken = token as Tokens . Code
const normalizedLang = ( codeToken . lang || "" ). toLowerCase ()
// Skip Mermaid diagrams
if ( normalizedLang !== "mermaid" && normalizedLang !== "mmd" ) {
const html = await highlightCode ( codeToken . text , codeToken . lang )
highlightMap . set ( codeToken . text , html )
}
}
},
})
Highlight Cache
Highlighted code is cached during the walk phase and reused during rendering:
let highlightMap = new Map < string , string >()
export async function renderMarkdown ( content : string ) : Promise < string > {
highlightMap = new Map ()
const result = await marked . parse ( content )
highlightMap = new Map () // Clear after use
return result
}
Language Icons
Each language gets a custom icon in code blocks:
const iconLabel =
label === "tf" || label === "tfvars"
? "terraform"
: label === "mmd"
? "mermaid"
: label === "tex"
? "latex"
: label
const iconPath = iconLabel === "text"
? `/icons/lang/default.svg`
: `/icons/lang/ ${ iconLabel } .svg`
Source Code Reference
Implementation details can be found in:
/src/lib/shiki/highlight.ts - Core highlighting logic and language loaders
/src/lib/shiki/transformers.ts - Custom Shiki transformers
/src/lib/markdown.ts - Integration with marked.js