Skip to main content

Starlighter

Python Version PyPI Version License Zero Dependencies

Server-side Python syntax highlighter with zero dependencies. Built for StarHTML with Datastar-aware tokenization, and compatible with FastHTML.

Features

  • Fast: ~1.5ms P99 for 200-line files, ~3ms for 500-line files
  • XSS-safe: All output is entity-encoded
  • Zero dependencies: Pure Python standard library
  • 17 built-in themes: GitHub, VS Code, Monokai, Catppuccin, Dracula, Nord, Solarized, One Dark, Xcode (dark + light variants)
  • StarHTML-aware: Distinct token classes for HTML elements, Datastar attributes, signals, and CSS class/style strings
  • FastHTML compatible: Works with both StarHTML and FastHTML projects

Installation

# Using uv (recommended)
uv add starlighter

# Using pip
pip install starlighter

Usage

Basic highlighting

from starlighter import highlight

code = '''def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10))'''

html = highlight(code)

StarHTML-aware highlighting

The lexer recognizes StarHTML elements, Datastar attributes, and signal references, giving each a distinct token class:

from starlighter import highlight

code = '''Button(
    "Increment",
    data_on_click=count.add(1),
    cls="px-4 py-2 bg-blue-500"
)'''

html = highlight(code)
# Button  -> token-starhtml-element
# data_on_click -> token-datastar-attr
# cls string    -> token-css-class

You can also register custom elements, attributes, and signal names:

html = highlight(
    code,
    elements={"MyWidget", "AppShell"},
    attrs={"custom_bind"},
    signals={"count", "message"},
)

With StarHTML

from starhtml import *
from starlighter import CodeBlock, StarlighterStyles

app, rt = star_app(
    hdrs=(
        StarlighterStyles("github-dark", "monokai", "dracula"),
    )
)

@rt("/")
def home():
    sample = '''def greet(name: str) -> str:
    return f"Hello, {name}!"'''

    return Div(
        H1("Code Preview"),
        CodeBlock(sample, theme="github-dark"),
        cls="container"
    )

serve()

With FastHTML

from fasthtml.common import *
from starlighter import CodeBlock, StarlighterStyles

app, rt = fast_app(
    pico=False,
    hdrs=(StarlighterStyles("vscode"),)
)

@rt("/")
def get():
    return Div(
        CodeBlock('print("hello")', theme="vscode"),
        cls="container"
    )

serve()

Themes

17 themes are available:

Dark Light
github-dark (default) github-light
vscode-dark / vscode vscode-light
monokai catppuccin-latte
catppuccin-mocha nord-light
dracula solarized-light
one-dark xcode-light
nord-dark
solarized-dark
xcode-dark
from starlighter import get_theme_css

# Get raw CSS for a theme
css = get_theme_css("monokai")

# Use StarlighterStyles to load multiple themes at once
StarlighterStyles("github-dark", "monokai", "dracula")

# Auto-switch between themes based on prefers-color-scheme
StarlighterStyles("github-dark", "github-light", auto_switch=True)

CSS Token Classes

Class Tokens
.token-keyword def, class, if, for, return, ...
.token-string "text", 'text', f"..."
.token-comment # ..., docstrings
.token-number 42, 3.14, 0xFF
.token-operator +, -, ==, !=
.token-identifier Variable and function names
.token-builtin print, len, str, range, ...
.token-decorator @app.route, @property
.token-punctuation (), [], {}, ,, :
.token-starhtml-element Div, Button, Input, ...
.token-datastar-attr data_on_click, data_bind, ...
.token-signal Signal variable references
.token-css-class Strings passed to cls=, data_class=
.token-css-style Strings passed to style=, data_style=

API

from starlighter import highlight, CodeBlock, StarlighterStyles, get_theme_css

highlight(
    code: str,
    language: str | None = "python",
    elements: set[str] | None = None,
    attrs: set[str] | None = None,
    signals: set[str] | None = None,
) -> str

CodeBlock(code: str, theme: str = "github-dark", **kwargs) -> Component

StarlighterStyles(*themes: str, auto_switch: bool = False, **kwargs) -> Style

get_theme_css(theme: str = "github-dark") -> str

Security

All input is HTML-entity-encoded before output. Script injection via code input is not possible:

code = 'return "</pre><script>alert(1)</script><pre>"'
html = highlight(code)
# Scripts are escaped: &lt;script&gt;alert(1)&lt;/script&gt;

Development

git clone https://github.com/banditburai/starlighter.git
cd starlighter
uv sync --all-extras
uv run pytest tests/ -v --cov=starlighter
uv run ruff check && uv run ruff format --check

Links

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

starlighter-0.2.0.tar.gz (10.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

starlighter-0.2.0-py3-none-any.whl (11.9 kB view details)

Uploaded Python 3

File details

Details for the file starlighter-0.2.0.tar.gz.

File metadata

  • Download URL: starlighter-0.2.0.tar.gz
  • Upload date:
  • Size: 10.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for starlighter-0.2.0.tar.gz
Algorithm Hash digest
SHA256 e74134ce1e38ef27b181c09e138021e327024d8fbe8d1054048962323540e04f
MD5 0a1efb51b99ae4266895ada4620ce152
BLAKE2b-256 ecb66b93e2a82094f5b483dfa6140dc5feb61d0e4630a41f0d85295d7bfcb653

See more details on using hashes here.

Provenance

The following attestation bundles were made for starlighter-0.2.0.tar.gz:

Publisher: release.yml on banditburai/starlighter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file starlighter-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: starlighter-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 11.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for starlighter-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 faab3babc81eb6b33bac4e86ded536e5381b87554497cafebe142b4b98264ce3
MD5 5e0f5772f86d2633c420ce1a3837a31b
BLAKE2b-256 697cecc8a9bce5737c4668f6e4963a114e610bb5b413a452133e7ce0032ff437

See more details on using hashes here.

Provenance

The following attestation bundles were made for starlighter-0.2.0-py3-none-any.whl:

Publisher: release.yml on banditburai/starlighter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page