# Mobile renders code with Shiki, tokenizing via a native engine with a JavaScript fallback
*pingdotgg/t3code@main · informative · 8 markers*

> **Engine.** The mobile app highlights code with `shiki`; `getHighlighter` builds a `createHighlighterCore` instance backed by `react-native-shiki-engine`'s native regex engine, falling back to `createJavaScriptRegexEngine` when the native engine is unavailable.
>
> **Two pipelines.** The React-side path (`shikiReviewHighlighter.ts`) tokenizes a review file's addition/deletion lines with GitHub themes and ~70 lazy-loaded languages; the native diff-surface path (`nativeReviewDiffHighlighter.ts`) tokenizes only viewport-visible rows with bespoke `t3-pierre` themes and streams tokens into the `T3ReviewDiffSurface` native view.
>
> **Non-blocking.** Both pipelines chunk tokenization and yield with `waitForNextFrame` so highlighting never blocks the UI thread.

**Author:** Fernando Ramirez · **Updated:** 2026-06-05T22:59:49.246Z

## Markers
1. **getHighlighter builds the Shiki core, native engine preferred** — `apps/mobile/src/features/review/shikiReviewHighlighter.ts:270–312`
   `getHighlighter` dynamically imports `react-native-shiki-engine` and, when `isNativeEngineAvailable()` returns true, calls `createHighlighterCore` with `createNativeEngine()`. Any failure is caught and the function drops to `createJavaScriptRegexEngine`. The engine actually used is exposed through `activeHighlighterEnginePromise`.
2. **resolveReviewHighlighterEngine picks native vs javascript** — `apps/mobile/src/features/review/reviewHighlighterEngine.ts:18–31`
   Preference defaults to `native` (overridable with `EXPO_PUBLIC_REVIEW_HIGHLIGHTER_ENGINE`; tests force `javascript`). When the preference is `native` but the native engine is not available, the resolver returns `javascript`, which is why the bootstrap always lands on a working engine.
3. **loadSingleLanguage lazy-imports a language grammar** — `apps/mobile/src/features/review/shikiReviewHighlighter.ts:404–424`
   Only seven grammars ship in the initial bundle; the rest of the ~70 entries in `languageImports` are `import()`-ed on demand and registered via `highlighter.loadLanguage`. `resolveLanguageAlias` maps extensions like `ts`/`py`/`rs` to grammar names, and unknown filetypes resolve to `text` (plain tokens, no grammar).
4. **highlightLines tokenizes in frame-yielding chunks** — `apps/mobile/src/features/review/shikiReviewHighlighter.ts:644–686`
   `highlightLines` batches short lines and calls `codeToTokensBase`, pushing oversized lines (>1000 chars) through as plain tokens. Every `REVIEW_HIGHLIGHT_CHUNK_SIZE` lines it awaits `waitForNextFrame` so a large file never blocks the UI. `highlightReviewFile` calls this for addition and deletion lines separately and caches the result by theme + `file.cacheKey`.
5. **ReviewHighlighterManager prepares the highlighter on mount** — `apps/mobile/src/features/review/reviewHighlighterState.ts:102–124`
   `useReviewHighlighterState` (consumed by `ReviewHighlighterProvider`) triggers `manager.initialize`, which runs `prepareReviewHighlighter`, warms the initial languages via `prepareReviewHighlighterLanguages`, reads back the resolved engine, and publishes `{ engine, status }` to `reviewHighlighterStateAtom`. The in-flight promise is reused so concurrent mounts initialize once.
6. **Native diff path: separate Shiki core with t3-pierre themes** — `apps/mobile/src/features/diffs/nativeReviewDiffHighlighter.ts:228–244`
   The native diff surface uses its own highlighter handles, memoized in `nativeHighlighterPromise` / `javascriptHighlighterPromise`. `getNativeReviewDiffHighlighter` tries the native engine and, on failure, the `.catch` falls back to the JavaScript engine. These cores load the bespoke `t3-pierre-light` / `t3-pierre-dark` themes rather than the GitHub themes used by the review-file path.
7. **Native path highlights only viewport-visible rows** — `apps/mobile/src/features/review/useNativeReviewDiffHighlighting.ts:64–118`
   `useNativeReviewDiffHighlighting` calls `highlightNativeReviewDiffVisibleRows` for the current visible range (plus overscan), tracks `highlightedRowIdsRef` so rows are tokenized once, and emits results as a `tokensPatchJson` patch. `updateVisibleRange` re-requests only after the viewport moves at least 20 rows, throttling work during scroll.
8. **T3ReviewDiffSurface native view consumes the token patches** — `apps/mobile/src/features/diffs/nativeReviewDiffSurface.ts:137–155`
   `resolveNativeReviewDiffView` resolves the `T3ReviewDiffSurface` native component via `requireNativeView`, returning null when the view config is absent. The view receives serialized `rowsJson`, `tokensPatchJson`, `tokensResetKey`, and theme/style JSON (assembled by `useNativeReviewDiffBridge`) and reports its visible range back through `onDebug`.

---
Interactive view: https://app.principal-ade.com/trail/ce0463fe-e26d-4a03-ade6-7eb4cc261d20
JSON: https://app.principal-ade.com/api/trails/by-id/ce0463fe-e26d-4a03-ade6-7eb4cc261d20
Authored at `b76f161d` (main).
To open a trail or tour locally in the interactive viewer, see https://app.principal-ade.com for the Principal CLI quickstart.
