Class TextUtils

java.lang.Object
co.mindus.utils.TextUtils

public class TextUtils extends Object
Text utilities providing Markdown-to-HTML conversion using the commonmark-java library.

commonmark is referenced directly: iizi-markdown.jar is on the application class path (and on com.iizix.core's bundle class path in the Designer), so the parser and renderer are ordinary compile-time types. They are built lazily on first use and cached for subsequent calls.

Until 2026-08-12 this class loaded the library through an isolated URLClassLoader and drove it entirely by reflection, so that the jar could be found at a filesystem location without being on the class path. That layer was removed once the jar was placed on the class path in every environment. Consequence to be aware of: a missing jar is now a NoClassDefFoundError at class load, not a contained IllegalStateException at first use.

Themes

Full-document output supports a two-layer theme system:

  1. Document themes (TextUtils.Theme) — control the overall page appearance (fonts, headings, tables, blockquotes, background). Six built-in themes are provided as three light/dark pairs:
    Document themes
    LightDarkStyle
    BASICBASIC_DARKSystem fonts, minimal borders
    MODERNMODERN_DARKInter font, soft shadows, gradient HRs
    GITHUBGITHUB_DARKGitHub-inspired, rounded code blocks
    Use TextUtils.Theme.NONE for bare unstyled HTML.
  2. Syntax highlight themes (SyntaxHighlighter.HighlightTheme) — control the colors of syntax-highlighted code blocks. 77 themes are available (16 curated + 61 extended), covering popular styles like GitHub, Monokai, Nord, Dracula, Solarized, Atom One, VS Code, and many more. See SyntaxHighlighter.HighlightTheme for the full catalog.

When using the TextUtils.DocumentBuilder, the highlight theme is auto-selected to match the document theme's brightness (light document → GITHUB, dark document → GITHUB_DARK). Override with TextUtils.DocumentBuilder.highlightTheme(SyntaxHighlighter.HighlightTheme).

For full-document output with CSS theming, use parseMarkdownToDocument(String) or the TextUtils.DocumentBuilder obtained via documentBuilder().

All public methods are thread-safe.

(C) Copyright Mindus SARL, 2026. All rights reserved.

Author:
Christopher Mindus
See Also:
  • Field Details

  • Constructor Details

    • TextUtils

      public TextUtils()
  • Method Details

    • parseMarkdownToHtml

      public static String parseMarkdownToHtml(String markdown)
      Parses a Markdown string and renders it to HTML.

      This is the primary entry point. The first call triggers lazy initialization of the Markdown engine (detecting Java version, loading the appropriate library).

      Parameters:
      markdown - The Markdown text to convert.
      Returns:
      The resulting HTML string.
      Throws:
      IllegalStateException - if the Markdown engine could not be initialized.
      RuntimeException - if the Markdown conversion itself fails.
    • getLoadedVersion

      public static String getLoadedVersion()
      Returns the version descriptor of the loaded commonmark library, or null if not yet initialized.
    • getLoadedExtensions

      public static String[] getLoadedExtensions()
      Returns the list of successfully loaded extension class names, or null if not yet initialized.
    • isInitialized

      public static boolean isInitialized()
      Returns true if the Markdown engine is initialized and ready.
    • dispose

      public static void dispose()
      Releases the cached parser and renderer. Intended for server shutdown.

      Since commonmark is loaded by the application class loader there is no class loader to close; this simply drops the cached engine, and the next call re-initializes it.

    • parseMarkdownToDocument

      public static String parseMarkdownToDocument(String markdown)
      Parses Markdown and wraps the resulting HTML in a complete HTML document using the default theme with inline CSS.

      Equivalent to documentBuilder().markdown(markdown).build().

      Parameters:
      markdown - The Markdown text to convert.
      Returns:
      A complete HTML document string.
    • documentBuilder

      public static TextUtils.DocumentBuilder documentBuilder()
      Creates a new TextUtils.DocumentBuilder for configuring full-document output.

      Usage example:

      String html = TextUtils.documentBuilder()
          .markdown(text)
          .title("My Report")
          .theme(TextUtils.Theme.GITHUB)
          .inlineCss(true)
          .build();
      
      Returns:
      A new builder instance.
    • loadThemeCss

      public static String loadThemeCss(TextUtils.Theme theme)
      Loads the CSS text for a given theme. The result is cached after first load.
      Parameters:
      theme - The theme to load.
      Returns:
      The CSS text, or null if the theme is TextUtils.Theme.NONE or the resource could not be read.
    • loadCssFromFile

      public static String loadCssFromFile(File cssFile)
      Loads a CSS file from the filesystem and returns its content.
      Parameters:
      cssFile - The CSS file to read.
      Returns:
      The CSS text, or null if the file does not exist or cannot be read.
    • getAvailableThemes

      public static TextUtils.Theme[] getAvailableThemes()
      Returns all available themes (excluding TextUtils.Theme.NONE).
    • escapeNonAscii

      public static String escapeNonAscii(String html)
      Replaces all non-ASCII characters (codepoints above U+007E) in an HTML string with numeric character references (&#xNNNN;).

      This makes the output safe for any HTTP transport regardless of the Content-Type charset sent by the web server. Without this, browsers that receive HTML without an explicit charset=UTF-8 header may fall back to ISO-8859-1 or Windows-1252, producing mojibake for multi-byte UTF-8 sequences.

      Characters typically affected

      • U+21A9 (↩) — footnote backlink arrow injected by the CommonMark footnotes extension
      • U+2014 (—) — em-dash from Markdown content
      • Any other non-ASCII character present in Markdown source text or injected by CommonMark extensions at render time

      The method includes a fast-path: if the input contains no characters above U+007E, it is returned as-is with zero allocation.

      Usage example:

      String html = TextUtils.parseMarkdownToHtml(markdown);
      html = TextUtils.escapeNonAscii(html);  // safe for any Content-Type
      
      Parameters:
      html - The HTML string to process. May be a fragment or a complete document.
      Returns:
      The same HTML with all characters above U+007E replaced by &#xNNNN; entities, or the original string unchanged if it is already pure ASCII.