Client-side syntax highlighter for mixed source files (HTML, PHP, JavaScript, Lua).
Produces styled HTML by wrapping recognised constructs in
<span> elements with CSS classes.
No dependencies — pure vanilla JS.
The library exposes three functions that form a two-phase pipeline:
tag_parsing(html) identifies and wraps HTML/PHP tags.source_coloring(html) colorizes language constructs.text_coloring(viewer, html) runs both phases and injects the result into the DOM.The key design constraint is that Phase 2 must not corrupt the markup emitted by Phase 1. Both phases solve this with a tokenize → transform → restore pattern: protected regions are replaced with opaque placeholder tokens before any regex passes run, and restored verbatim afterwards.
| Class | Applied to |
|---|---|
tag | The < and > angle brackets of an HTML tag |
tag-inside | Everything between the angle brackets of an HTML tag |
tag-name | The tag name itself (e.g. div, span), set in post-processing |
source-coloring | Base class on all source-level highlights |
source-string | String literals |
source-comment | Comments (C-style, Lua) |
source-keyword | Language keywords (JS + Lua) |
source-underline | Function names in definitions |
tag_parsing(html: string): stringConverts raw source text into display-safe HTML, detecting and wrapping HTML tags with styled spans.
Processing order:
& → &.} sequence that appears literally in {close-tag} sentinel strings.<? … ?>) — replaces each block with a placeholder so that
> inside PHP expressions (e.g. $obj->prop) cannot close an HTML tag prematurely.
Each block is stored as entity-escaped text.< / > with sentinels {open-tag} / {close-tag}.{open-tag}letter…{close-tag} and wrap as .tag / .tag-inside spans.< / >.text_coloring(text_viewer: Element, html: string): voidOrchestrates the full highlight pipeline and writes the result into the DOM.
tag_parsing(html).source_coloring(html).text_viewer.innerHTML..tag-inside span to wrap the leading tag name in a .tag-name span.source_coloring(html: string): string
Colorizes source-code constructs. Receives the output of tag_parsing
(which contains real <span> markup). All passes use tokenization
so that earlier-protected regions are immune to later passes.
Pass order:
<span …> / </span>
markup emitted by tag_parsing; restored last.`…`) literals;
stored with source-string wrapping already applied.// single-line (excluding :// in URLs)/* … */ multi-line--[[ … ]] / --[=[ … ]=] multi-line (all level variants)-- single-line (excluding long-comment openings)function name().{ } and the escaped form }.Supported keywords:
| Language | Keywords |
|---|---|
| JavaScript | function var let const if else switch for while break continue return yield null true false |
| Lua | nil and or not repeat until goto local do end if then else elseif while for in |
source_coloring corrupting tag_parsing outputsource_coloring.
Previously, keyword and brace regexes would match characters inside <span class='tag'>
markup, breaking the generated HTML structure.
> breaking tag detectionhtml.replaceAll("?>", "?>") with a full PHP block
tokenization pass in tag_parsing.
The old approach only escaped the closing ?> but left inner >
(e.g. in $obj->prop or htmlspecialchars($x)) unprotected,
causing the tag matcher to misfire on attribute values like
<input value="<?= htmlspecialchars($contact->name) ?>">.
source_coloringnull, true, false, yield).
Removed the ops() parenthesis-suffix helper — plain word-boundary (\b) matching is more correct
and handles all usage patterns (assignments, returns, etc.).
/** … */ JSDoc blocks to all three public functions
documenting parameters, return types, and the multi-pass pipeline order.
Note: the literal */ sequence inside the source_coloring JSDoc
is written as /* … * / (space before /) to avoid prematurely
closing the comment block — a self-referential constraint of the format.
', "
or keywords may be incorrectly colored.$variable, # comments, PHP-only keywords such as
echo, class, foreach) are not yet highlighted.--[[ --[[ ]] ]]) are not handled.