Menu

Aussom Highlighter Usage Guide

The highlighter module adds syntax highlighting for Aussom source code to any browser page. It tokenizes a source string with a regex-based lexer and returns a styled HNode tree that you insert into the DOM. Two built-in themes (dark and light) mirror the VS Code color palette, and a custom-theme map lets you override any token color.


Table of Contents

  1. Setup
  2. Basic Usage
  3. Intermediate Usage
  4. Advanced Usage
  5. DOM Insertion Gotcha
  6. CSS Classes Reference
  7. Token Types Reference
  8. Tips

Setup

Add include highlighter; to your Aussom script block. Because highlighter depends on hnodes and util, those modules are loaded automatically. You still need include html; in the page so the DOM element types (Element, Text, etc.) are available.

include html;
include highlighter;

The order matters: html must come before highlighter.


Basic Usage

Minimal example -- dark theme, no extras

include html;
include highlighter;

class Main {
    public main(args) {
        container = Doc.getElementById("output");

        code = "x = 42;\nc.log(x);";
        h = new Highlighter();
        container.add(h.highlight(code).obj);
    }
}

new Highlighter() with no arguments defaults to the dark theme, no line numbers, and no copy button. highlight(code) returns a Div HNode. Call .obj on it before passing to container.add() -- see the DOM Insertion Gotcha for why.

Choosing a theme

Pass "dark" or "light" as the first argument:

hDark  = new Highlighter("dark");
hLight = new Highlighter("light");

null and omitting the argument both default to "dark".


Intermediate Usage

Line numbers and copy button

The constructor takes three optional parameters:

Highlighter(Theme = null, bool ShowLineNumbers = false, bool ShowCopyButton = false)

Enable both extras:

h = new Highlighter("dark", true, true);
container.add(h.highlight(code).obj);

The copy button uses navigator.clipboard.writeText via an inline onclick attribute. It requires the page to be served over HTTPS or localhost (the Clipboard API is not available on plain file:// URLs in most browsers).

Switching themes after construction

setTheme(Theme) accepts the same arguments as the constructor and returns this, so calls can be chained:

h = new Highlighter();
h.setTheme("light");
container.add(h.highlight(code).obj);

Re-rendering on theme change

Because highlight() builds a new DOM tree every time it is called, re-rendering with a different theme is a matter of clearing the container and calling highlight() again:

public renderAll(string theme) {
    container = Doc.getElementById("output");
    container.clear();
    h = new Highlighter(theme, true, false);
    for (snippet : this.snippets) {
        container.add(h.highlight(snippet).obj);
    }
}

The Highlighter instance can be reused across multiple highlight() calls with the same theme.

Using the Tokenizer directly

Tokenizer.tokenize(Code) returns a list of maps, each with "type" and "text" keys. This is useful if you want to analyze tokens without producing any DOM output.

t = new Tokenizer();
tokens = t.tokenize("x = 42;");
for (tok : tokens) {
    c.log(tok.get("type") + " : " + tok.get("text"));
}

Sample output:

ident      : x
ws         :
operator   : =
ws         :
number     : 42
punctuation: ;

Token types are string constants. TokenType is a static class that provides named constants if you prefer not to hard-code the strings:

if (tok.get("type") == TokenType.KEYWORD) { ... }

Advanced Usage

Custom themes

Pass a map of {tokenType: colorString} as the theme. Missing token types fall back to the dark-theme defaults, so you only need to supply the colors you want to override.

myTheme = {
    "keyword":  "#ff79c6",
    "string":   "#f1fa8c",
    "number":   "#bd93f9",
    "comment":  "#6272a4",
    "doc":      "#6272a4",
    "ident":    "#f8f8f2",
    "operator": "#ff79c6",
    "unknown":  "#ff5555"
};
h = new Highlighter(myTheme, true, true);
container.add(h.highlight(code).obj);

The background, header, label, and border colors are not part of the token color map. When a custom map is supplied, those values are taken from the dark-theme defaults (#1e1e1e background, #2d2d30 header, etc.). There is currently no API to override them through the constructor; post-process the returned HNode if you need different chrome colors.

Post-processing the returned HNode

highlight() returns a Div HNode. You can modify it before inserting it into the DOM:

result = h.highlight(code);
result.setStyle("margin-bottom", "0");
result.setStyle("border-radius", "0");
container.add(result.obj);

The full DOM structure produced is:

Div.aus-highlighter          (outermost wrapper)
  Div.aus-header
    Span.aus-lang-label      ("aussom")
    Button.aus-copy-btn      (optional)
  Pre.aus-pre
    Code.aus-code
      Span.aus-line          (one per source line)
        Span.aus-line-num    (optional, non-selectable)
        Span.aus-token.aus-{type}  (one per token)

All classes and inline styles are applied at build time so the output is self-contained. You can add CSS rules that target the class names to override individual properties.

Styling with CSS

Because highlight() uses both class names and inline styles, CSS specificity may require !important to override inline values:

.aus-highlighter {
    font-size: 13px !important;
    border-radius: 0 !important;
}
.aus-line-num {
    min-width: 3em !important;
}

To highlight only certain token types differently, target the combined class:

.aus-token.aus-keyword { font-weight: bold; }
.aus-token.aus-unknown { text-decoration: underline wavy red; }

Highlighting code embedded in triple-quoted Aussom strings

When the source snippet itself contains """, the Aussom triple-quote sequence would terminate the outer literal. Escape each inner " as \":

code = """block = \"\"\"line one
line two\"\"\";""";
h = new Highlighter();
container.add(h.highlight(code).obj);

The highlighter receives the string with literal """ characters and tokenizes them as a triple-quoted string literal correctly.


DOM Insertion Gotcha

highlight() returns an HNode Div object, not a raw DOM element. When you add it to a container obtained from Doc.getElementById(), you must call .obj on the result to extract the underlying Element extern:

container = Doc.getElementById("output");

// WRONG -- throws "Unexpected extern object type" at runtime:
container.add(h.highlight(code));

// CORRECT:
container.add(h.highlight(code).obj);

Doc.getElementById() returns a raw Element extern whose .add() method is implemented in Java. That method only accepts other Element, Text, Video, or Img externs. Passing a plain Aussom HNode wrapper causes the type check to fail.

The same rule applies when adding any other HNode to a Doc.getElementById() container:

lbl = new P();
lbl.setHtml("Label");
container.add(lbl.obj);   // extract the Element

This issue does not arise when adding HNodes to other HNodes (e.g., inside highlight() itself), because HNode.add() is an Aussom method that extracts .obj internally.


CSS Classes Reference

Class Element Description
aus-highlighter div Outermost code window wrapper
aus-header div Header bar (label + optional copy button)
aus-lang-label span Language tag ("aussom") in the header
aus-copy-btn button Copy-to-clipboard button (when enabled)
aus-pre pre Scrollable code area
aus-code code Inner code block
aus-line span One block-level span per source line
aus-line-num span Line number gutter cell (when enabled)
aus-token span Present on every token span
aus-{type} span Token-type class (e.g., aus-keyword)

Token Types Reference

Type TokenType constant What it matches
doc TokenType.DOC /** ... */ doc comments
comment TokenType.COMMENT /* ... */ and // ... comments
string TokenType.STRING "...", '...', and """...""" literals
number TokenType.NUMBER Integer and floating-point literals
keyword TokenType.KEYWORD Reserved words (class, if, return, ...)
boolean TokenType.BOOLEAN true and false
operator TokenType.OPERATOR Operators (=, +=, ==, &&, ...)
punctuation TokenType.PUNCTUATION Delimiters (;, ,, (, {, ...)
ident TokenType.IDENT Identifiers not matched by other types
ws TokenType.WS Spaces, tabs, and form feeds
unknown TokenType.UNKNOWN Any character that matches no pattern (shown in red)

newline tokens are consumed internally to split lines and are not present in token spans.


Tips

Reuse the Highlighter instance. Each new Highlighter(...) call sets up the theme and options once. Calling highlight() multiple times on the same instance is safe and efficient.

Prefer triple-quoted strings for multi-line snippets. Aussom's """...""" literals preserve newlines exactly, making them the natural choice for source code snippets:

code = """public greet(string Name) {
    c.log("Hello, " + Name + "!");
}""";

Unknown tokens do not abort highlighting. If the source contains a character that the lexer cannot match (for example $), the highlighter emits a single unknown token for that character and continues from the next position. The rest of the snippet is highlighted normally. This error-recovery behavior means partially valid or experimental code still renders usefully.

The copy button requires a secure context. navigator.clipboard.writeText is only available over HTTPS or on localhost. On plain file:// pages the button renders but the write silently fails (the .catch handler suppresses the error). Disable the copy button (ShowCopyButton = false) if you are serving from file:// and want to avoid confusion.

Line numbers are non-selectable. The line number spans have user-select: none and -webkit-user-select: none applied inline, so selecting and copying code does not include the line numbers.

Custom themes only override token colors. Background, header, border, and label colors are fixed to the dark-theme values when a custom map is supplied. To change those, call setStyle() on the returned HNode after highlight():

result = h.highlight(code);
result.setStyle("background", "#282a36");
container.add(result.obj);