ARCHITECTURE / MUTABLE REGISTRY

Registry

Tree-shake grammars down to what you actually use, import bundled defaults dynamically on demand, or register custom grammars at runtime.

The default fractalpop entry ships a mutable language registry seeded with just TypeScript + plaintext, so unused grammars tree-shake away. You grow it at runtime — the panels on this page run the real calls live.

Registered right now (32): typescript plaintext javascript css scss sass html svelte markdown diff c cpp csharp dockerfile go graphql hcl java json kotlin lua php powershell python ruby rust shell sql swift toml yaml zig

One registry is shared per app: every entry point re-exports the same core, so a registration made through fractalpop/full is visible to fractalpop importers too. This site renders through @fractalpop/sveltefractalpop/full, so if you arrived here from another page, all 32 languages are already registered.

01 /

Entry points

Four ways in, depending on how much you want shipped and registered:

import { highlight } from 'fractalpop'        // tiny — TypeScript + plaintext
import { highlight } from 'fractalpop/full'   // all 32 languages registered
import { parse, generate } from 'fractalpop/core' // engine only, no registry
import { highlight } from 'fractalpop/gpu'    // async WebGPU path

Grow the default entry

Python is registered in this session — def is highlighted as a keyword:

def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

lang('py')python

import { importDefaults } from 'fractalpop'

// pull bundled configs in at runtime, tree-shaking the rest
await importDefaults(['python', 'rust', 'sass'])

Register your own language

registerLanguage() takes metadata plus a parse config — a keyword set and comment rules are enough for a small language. The panel starts unregistered (TypeScript fallback) and lights up when you register:

; 2026 budget
account assets:checking
commodity $
alias food
payee Grocery Store
import { registerLanguage } from 'fractalpop'

registerLanguage(
  { id: 'ledger', extension: 'ledger', aliases: ['journal'] },
  {
    keywords: new Set(['account', 'payee', 'commodity', 'alias']),
    onCommentStart: (curr) => (curr === ';' ? 1 : 0),
    onCommentEnd: (_prev, curr) => (curr === '\n' ? 1 : 0),
  },
)

highlight(source, { lang: 'journal' }) // aliases resolve

Replace the whole set

setDefaults() wipes both registries and seeds exactly what you pass — the same call the default entry uses to seed TypeScript + plaintext at load. (Not a button here: on this site it would strip the 32 languages the other pages use until reload.)

import { setDefaults } from 'fractalpop'

// replace the default set outright — metadata only…
setDefaults([
  { id: 'rust', extension: 'rs', aliases: [] },
  { id: 'python', extension: 'py', aliases: ['python3'] },
])

// …or id → config pairs
setDefaults({ rust: rustConfig, python: pythonConfig })

WebGPU

fractalpop/gpu is an async entry that tokenizes through the optional gpu-lexer peer (npm i gpu-lexer) and renders the same token markup as the CPU path:

import { highlight } from 'fractalpop/gpu'

  // async — tokenizes via the optional gpu-lexer peer
const html = await highlight(code, { lang: 'typescript' })