public class SyntaxHighlighter extends Object
This class provides an optional, lazy-loaded syntax highlighting engine that
processes fenced code blocks (produced by the Markdown parser in TextUtils)
and wraps language tokens in <span class="hljs-xxx"> elements. The resulting
HTML can be styled with any highlight.js-compatible CSS theme — no client-side
JavaScript is required.
Like the Markdown engine in TextUtils, the highlighter has zero
compile-time dependencies on any highlighting library. At first use, it locates
an uber JAR (np-html-highlighter.jar) containing a Java port of
highlight.js, creates an isolated
URLClassLoader, and interacts with the library entirely via reflection.
When dispose() is called, the class loader is closed and all highlighting
classes become eligible for garbage collection.
Instances are created via create() and must be explicitly disposed via
dispose() when no longer needed. A single instance can process any number
of documents and code blocks. For one-shot usage through the
TextUtils.DocumentBuilder, the builder manages the lifecycle automatically.
Theme CSS files are stored as classpath resources alongside this class (not inside the uber JAR), so they can be loaded without instantiating the highlighting engine. Themes are organized into two sets:
hl/css/curated/.hl/css/extended/.Two complementary lifecycle models are supported:
create() / dispose() —
each caller owns the lifecycle. Suitable for batch processing where each
thread creates its own instance.getInstance() / disposeShared()
— a process-wide instance that is lazily created on first use.
All calls through the singleton are synchronized, making it safe
for concurrent access from multiple threads.A single per-use instance (obtained via create()) is not
thread-safe; each thread should create its own instance, or access must be
externally synchronized. The shared singleton is
thread-safe — all highlighting calls are synchronized on the
singleton instance. Static methods (theme loading, CSS utilities) are always
thread-safe.
The bundled highlighter supports approximately 25 languages including Java, JavaScript, TypeScript, HTML/XML, CSS, JSON, YAML, SQL, Bash, Python, C/C++, PHP, Ruby, Go, Markdown, Properties/INI, and more.
(C) Copyright Mindus SARL, 2026. All rights reserved.
TextUtils,
TextUtils.DocumentBuilder.syntaxHighlight(boolean),
TextUtils.DocumentBuilder.autoDetectLanguage(boolean)| Modifier and Type | Class and Description |
|---|---|
static class |
SyntaxHighlighter.HighlightResult
Result of automatic language detection and highlighting.
|
static class |
SyntaxHighlighter.HighlightTheme
Available CSS themes for syntax-highlighted code blocks.
|
static class |
SyntaxHighlighter.ThemeSet
Identifies which set a theme belongs to.
|
static class |
SyntaxHighlighter.ThemeType
Classification of a highlight theme's visual appearance.
|
| Modifier and Type | Field and Description |
|---|---|
static int |
AUTO_DETECT_MIN_RELEVANCE
Minimum relevance score required for auto-detected language highlighting
to be applied to a bare code block (i.e.
|
static String |
CSS_PREFIX
CSS class prefix used by the highlight engine for token spans.
|
static SyntaxHighlighter.HighlightTheme |
DEFAULT_DARK_THEME
Default highlight theme used when none is specified and the Markdown theme is dark.
|
static SyntaxHighlighter.HighlightTheme |
DEFAULT_LIGHT_THEME
Default highlight theme used when none is specified and the Markdown theme is light.
|
| Modifier and Type | Method and Description |
|---|---|
static void |
clearThemeCache()
Clears the theme CSS cache, freeing memory.
|
static SyntaxHighlighter |
create()
Creates a new syntax highlighter instance.
|
static SyntaxHighlighter.HighlightTheme |
defaultThemeFor(TextUtils.Theme mdTheme)
Selects an appropriate default highlight theme that matches a Markdown
document theme's light/dark classification.
|
void |
dispose()
Releases the class loader and all highlighting engine resources.
|
static void |
disposeShared()
Disposes the shared singleton instance, closing its class loader and
releasing all highlighting engine memory (~200–300 KB).
|
static SyntaxHighlighter.HighlightTheme[] |
getAvailableThemes()
Returns all available themes.
|
static String |
getConflictResolutionCss()
Returns a CSS snippet that resolves padding conflicts between Markdown
document themes and highlight.js code block themes.
|
static SyntaxHighlighter |
getInstance()
Returns the shared singleton instance, creating it (and loading the uber JAR)
on first call.
|
String[] |
getSupportedLanguages()
Returns the list of language identifiers supported by the loaded highlighter.
|
static SyntaxHighlighter.HighlightTheme[] |
getThemes(SyntaxHighlighter.ThemeSet set)
Returns themes from the given set.
|
static SyntaxHighlighter.HighlightTheme[] |
getThemes(SyntaxHighlighter.ThemeType type)
Returns themes matching the given type classification.
|
static SyntaxHighlighter.HighlightTheme[] |
getThemes(SyntaxHighlighter.ThemeType type,
SyntaxHighlighter.ThemeSet set)
Returns themes matching both a type and a set.
|
String |
highlight(String language,
String code)
Highlights a code block for a specific language.
|
SyntaxHighlighter.HighlightResult |
highlightAuto(String code)
Highlights a code block with automatic language detection.
|
String |
highlightCodeBlocks(String html)
Processes an HTML fragment and highlights all fenced code blocks in-place,
with automatic language detection enabled for bare code blocks.
|
String |
highlightCodeBlocks(String html,
boolean autoDetect)
Processes an HTML fragment and highlights all fenced code blocks in-place.
|
boolean |
isDisposed()
Returns
true if this instance has been disposed. |
static boolean |
isSharedLoaded()
Returns
true if the shared singleton is currently loaded and
ready to use. |
static String |
loadThemeCss(SyntaxHighlighter.HighlightTheme theme)
Loads the CSS text for a given highlight theme.
|
public static final String CSS_PREFIX
public static final int AUTO_DETECT_MIN_RELEVANCE
language-xxx class).
When highlightCodeBlocks(String,boolean) encounters a bare
<pre><code> block and auto-detection is enabled, the block is
highlighted only if the detection's relevance score meets or exceeds this threshold. Below this value the
code is left as plain escaped text, avoiding misleading or garbled output
from low-confidence guesses.
The highlight.js engine typically returns relevance values of 0–5 for
plain prose or very short snippets, and 7+ for recognizable code. A
threshold of 5 provides a reasonable balance between false
positives and missed detections.
public static final SyntaxHighlighter.HighlightTheme DEFAULT_LIGHT_THEME
public static final SyntaxHighlighter.HighlightTheme DEFAULT_DARK_THEME
public static SyntaxHighlighter create()
This loads the highlighting engine from the uber JAR into an isolated class loader. The instance must be disposed when no longer needed to release the class loader and its memory.
For one-shot usage through the TextUtils.DocumentBuilder, prefer
.syntaxHighlight(true) which manages the lifecycle automatically.
IllegalStateException - if the uber JAR cannot be found or loaded.public static SyntaxHighlighter getInstance()
All highlighting calls through the returned instance should use the
synchronized keyword on the instance for thread safety, or callers
should be restricted to a single thread. Unlike per-use instances obtained
via create(), the singleton is intended for lightweight, infrequent
highlighting from application code (e.g. rendering a single Markdown
document). For high-throughput batch work, prefer create() to
avoid contention on the shared lock.
Dispose with disposeShared() when the engine is no longer needed
(e.g. at server shutdown). After disposal, the next call to this method
reloads the library.
null).IllegalStateException - if the uber JAR cannot be found or loaded.disposeShared(),
isSharedLoaded()public static void disposeShared()
After this call, the next invocation of getInstance() will
reload the library. CSS theme caches are not affected.
This method is idempotent and safe to call even if no shared instance has been created.
getInstance()public static boolean isSharedLoaded()
true if the shared singleton is currently loaded and
ready to use.getInstance(),
disposeShared()public String highlight(String language, String code)
The input code should be plain text (not HTML-escaped). The output
contains <span class="hljs-xxx"> elements wrapping language tokens.
HTML special characters in the source code are properly escaped in the output.
The language identifier is case-insensitive; it is normalized to lower case before being passed to the underlying engine.
language - The language identifier (e.g. "java", "javascript",
"css", "json", "sql", "bash").
Case-insensitive. If null or empty, falls back to
highlightAuto(String).code - The source code text to highlight.IllegalStateException - if this instance has been disposed.public SyntaxHighlighter.HighlightResult highlightAuto(String code)
The highlighter analyzes the code and selects the best-matching language.
Use the returned SyntaxHighlighter.HighlightResult to access the highlighted HTML,
detected language name, and relevance score.
code - The source code text to highlight.IllegalStateException - if this instance has been disposed.public String[] getSupportedLanguages()
Common identifiers include: java, javascript, typescript,
css, html, xml, json, yaml, sql,
bash, python, c, cpp, php, ruby,
go, markdown, properties.
IllegalStateException - if this instance has been disposed.public String highlightCodeBlocks(String html)
This convenience overload delegates to
highlightCodeBlocks(html, true).
html - An HTML fragment containing zero or more code blocks.IllegalStateException - if this instance has been disposed.highlightCodeBlocks(String,boolean)public String highlightCodeBlocks(String html, boolean autoDetect)
This method performs up to two passes over the HTML:
<pre><code class="language-xxx"> blocks (as produced by
commonmark) and highlights them using the declared language. This
pass always runs.autoDetect is
true, scans for bare <pre><code> blocks (no
language-xxx class) and uses highlightAuto(String)
to guess the language. Only results whose
relevance score meets or
exceeds AUTO_DETECT_MIN_RELEVANCE are applied; below the
threshold the block is left as plain escaped text to avoid garbled
output from low-confidence guesses.The same highlighter instance is used for all code blocks in the fragment, ensuring the engine is initialized exactly once regardless of how many code blocks are present.
html - An HTML fragment containing zero or more code blocks.autoDetect - true to enable automatic language detection for
bare code blocks; false to leave them untouched.IllegalStateException - if this instance has been disposed.public boolean isDisposed()
true if this instance has been disposed.public void dispose()
After this call, the instance is no longer usable. Calling any highlighting
method will throw IllegalStateException. The class loader is closed,
making all loaded classes eligible for garbage collection.
This method is idempotent — calling it multiple times has no effect.
public static String loadThemeCss(SyntaxHighlighter.HighlightTheme theme)
Results are cached after first load. This method does not require a
SyntaxHighlighter instance — theme CSS files are classpath
resources that can be loaded at any time.
theme - The highlight theme to load.null if the theme's CSS resource cannot be found.public static void clearThemeCache()
Subsequent calls to loadThemeCss(HighlightTheme) will reload from
classpath resources.
public static String getConflictResolutionCss()
When both a Markdown document theme (from TextUtils.Theme) and a
syntax highlight theme are active in the same document, the document theme
may apply its own padding and background to <pre> elements, which
conflicts with the highlight theme's code.hljs styling. Injecting
this snippet after both theme CSS blocks ensures the highlight theme
controls code block appearance without double padding.
Example usage:
sb.append("<style>\n").append(docThemeCss).append("\n</style>\n");
sb.append("<style>\n").append(hlThemeCss).append("\n</style>\n");
sb.append("<style>\n").append(SyntaxHighlighter.getConflictResolutionCss())
.append("\n</style>\n");
public static SyntaxHighlighter.HighlightTheme[] getAvailableThemes()
public static SyntaxHighlighter.HighlightTheme[] getThemes(SyntaxHighlighter.ThemeType type)
type - The desired theme type (LIGHT, DARK, or NEUTRAL).public static SyntaxHighlighter.HighlightTheme[] getThemes(SyntaxHighlighter.ThemeSet set)
set - The desired theme set (CURATED or EXTENDED).public static SyntaxHighlighter.HighlightTheme[] getThemes(SyntaxHighlighter.ThemeType type, SyntaxHighlighter.ThemeSet set)
type - The desired theme type.set - The desired theme set.public static SyntaxHighlighter.HighlightTheme defaultThemeFor(TextUtils.Theme mdTheme)
If the Markdown theme is light, returns DEFAULT_LIGHT_THEME.
If dark, returns DEFAULT_DARK_THEME. For NONE or unknown
themes, defaults to the light theme.
mdTheme - The Markdown document theme (from TextUtils.Theme).Phantom® and NetPhantom® are registered trademarks of Mindus SARL.
© 2026 Mindus SARL. All rights reserved.