Aller au contenu

Runtime Architecture

This page describes how TikZJax detects, schedules, compiles, caches, and inserts diagrams in the browser.

TikZJax runs TeX entirely on the client. It does not require a server-side LaTeX installation or a remote rendering service.

For user-facing worker-pool behavior, see Parallel Rendering and the Worker Pool.


Architecture overview

A diagram follows this general pipeline:

TikZ source in the document
        |
        v
source discovery and normalization
        |
        v
global and local configuration merge
        |
        v
render identity generation
        |
        +-- persistent SVG cache hit
        |           |
        |           v
        |      insert cached SVG
        |
        +-- cache miss
                    |
                    v
           pending-job deduplication
                    |
                    v
             global render queue
                    |
                    v
        adaptive Web Worker pool
                    |
                    v
          TeX WebAssembly engine
                    |
                    v
               DVI output
                    |
                    v
          DVI-to-SVG conversion
                    |
                    v
             SVG insertion
                    |
                    v
   target palette resolution, ordered SVG adaptation, and event

The main browser thread coordinates discovery, caching, scheduling, DOM updates, and theme handling.

TeX compilation and DVI conversion run inside isolated Web Workers.


Main runtime components

TikZJax is divided into two principal execution environments.

Main browser thread

The main TikZJax bundle runs in the page and manages:

  • source discovery;
  • configuration;
  • persistent SVG caching;
  • render scheduling;
  • worker-pool lifecycle;
  • DOM observation;
  • generated SVG insertion;
  • theme detection, palette resolution, optional target styling, ordered SVG color adaptation, and foreground/background contrast correction;
  • error fallbacks;
  • completion events.

Rendering workers

Each rendering worker manages:

  • WebAssembly initialization;
  • the TeX runtime;
  • the virtual filesystem;
  • runtime TeX dependencies;
  • generated LaTeX documents;
  • TeX compilation;
  • DVI output;
  • DVI-to-SVG conversion;
  • worker-local dependency caching.

The two environments communicate through worker messages.


Main runtime files

The distribution contains files such as:

dist/tikzjax.js
dist/tikzjax.min.js
dist/run-tex.js
dist/run-tex.min.js
dist/fonts.css
dist/fonts.min.css
dist/tex.wasm.gz
dist/core.dump.gz
dist/tex_files/
dist/assets/broken-image.svg

Main-thread bundle

Production:

tikzjax.min.js

Debugging:

tikzjax.js

Worker script

The rendering worker is normally created from:

run-tex.js

The minified worker file may also be distributed for deployment workflows.

TeX runtime

tex.wasm.gz
core.dump.gz

These files provide the WebAssembly TeX engine and its initial dumped state.

Runtime TeX files

tex_files/

This directory contains compressed TeX packages, TikZ libraries, font data, and other files loaded on demand.

Styling and fallback assets

fonts.min.css
assets/broken-image.svg

The stylesheet supports generated SVG text and fonts. The image is used when rendering cannot complete successfully.

All runtime files should come from the same TikZJax release.


Main-thread architecture

Source discovery

TikZJax recognizes two source families.

HTML blocks

<script type="text/tikz">
\begin{tikzpicture}
    \draw (0,0) circle (1);
\end{tikzpicture}
</script>

Fenced-block output

TikZJax recognizes generated <pre> elements with classes such as:

language-tikzjax
tikzjax
language-tikz
tikz

For example, MkDocs can transform:

```tikzjax
\begin{tikzpicture}
    \draw (0,0) circle (1);
\end{tikzpicture}
```

into a recognizable HTML source element.

When a nested <code> element exists, TikZJax extracts its text content as the TeX source.


Initial page scan

After initialization, TikZJax scans the document for supported source blocks.

For each newly discovered source, it:

  1. extracts the exact source text;
  2. reads local data-* attributes;
  3. builds the effective configuration;
  4. creates or updates the loading wrapper;
  5. generates the rendering identity;
  6. checks the persistent cache;
  7. joins an existing pending job or creates a new one.

Workers are initialized lazily only when uncached rendering work exists.

page scan
    |
    +-- no diagrams
    |       |
    |       v
    |   no worker initialization
    |
    +-- only cached diagrams
    |       |
    |       v
    |   insert cached SVGs
    |
    +-- uncached diagrams
            |
            v
       initialize required workers

Source normalization and processing state

TikZJax tracks discovered source elements so that the same element is not processed repeatedly.

This is important because the document may be rescanned after:

  • DOM mutations;
  • MkDocs navigation;
  • content-tab activation;
  • delayed component rendering;
  • theme-related updates.

A source that has already been converted into a TikZJax wrapper is not treated as a new source merely because an ancestor changed.


Configuration architecture

Effective configuration

The configuration of one diagram is constructed from:

TikZJax defaults
< initial global configuration
< later partial global configuration
< local diagram configuration

Plain objects are merged recursively.

Arrays are combined without duplicate entries.

Scalar values are replaced by later values.

Local configuration affects only the current diagram.

See Global and Local Configuration.


Configuration responsibilities

Some options control the complete runtime:

assetBaseUrl
workerMode
workerUrl
workerPool
theme

Other values become part of an individual rendering job:

texPackages
tikzLibraries
addToPreamble
tkzTab
renderTimeout
maxRetries
restartWorkerOnFail
showConsole
debugTimings

A diagram cannot create an independent local worker pool. Pool sizing and worker initialization are global runtime concerns.

Theme detection, configured targets, palette resolution, target styling, SVG color adaptation, foreground/background contrast correction, and theme observation are also global runtime concerns. This includes theme.adaptiveColors, theme.adaptiveColors.contrast, and theme.adaptiveFills.

A local diagram configuration does not create a separate page-level theme environment and cannot override these theme stages for only one diagram.


Local attribute processing

Local attributes are interpreted in a deterministic order:

data-options
< data-tikzjax-options
< data-tex
< data-tex-packages
< data-tikz-libraries
< data-add-to-preamble
< data-tkz-tab
< dedicated scalar attributes

Dedicated attributes therefore override equivalent values from a general local JSON object.

The resulting effective configuration is serialized into the dataset sent to the worker.

tkz-tab preamble generation

The effective tkzTab object belongs to the configuration of an individual rendering job.

TikZJax generates a dedicated preamble fragment before the effective custom tex.addToPreamble string.

This generated fragment has two roles.

Public helper macros

The configured values remain available through public TeX macros such as:

\tikzjaxTkzTabLineWidth
\tikzjaxTkzTabFont
\tikzjaxTkzTabLgt
\tikzjaxTkzTabFirstColumnWidth
\tikzjaxTkzTabEspcl
\tikzjaxTkzTabVariableRowHeight
\tikzjaxTkzTabSignRowHeight
\tikzjaxTkzTabVariationRowHeight
\tikzjaxTkzTabImageRowHeight
\tikzjaxTkzTabAntecedentRowHeight

The row-height values remain helper macros because the runtime cannot infer the semantic type of every required label/height row passed to \tkzTabInit.

Automatic native defaults

When tkzTab.autoApply is enabled, supported values are also converted into native tkz-tab defaults.

The generated preamble can:

  • refresh the package default line width;
  • preset native \tkzTabInit keys such as lw, lgt, and espcl;
  • pass serialized scalar options to \tkzTabSetup;
  • pass serialized scalar options to \tkzTabColors;
  • append the configured font to TikZ nodes used by the table.

The native first-column width is resolved from:

tkzTab.firstColumnWidth
?? tkzTab.lgt

Values in tkzTab.init override corresponding automatically derived lw, lgt, and espcl values.

Explicit options written directly in the TeX source remain the highest-priority values:

\tkzTabInit[
    lw=0.8pt,
    lgt=4
]

Setting tkzTab.autoApply to false disables the native-default commands but keeps the public helper macros.

The generated commands are guarded so that ordinary diagrams remain valid when the tkz-tab package is not loaded.


Rendering identity and caching

Rendering identity

The persistent rendering identity is based on:

exact source
+
serialized effective worker dataset

It distinguishes diagrams that have the same TeX source but different dependencies or local settings.

For example:

<script
  type="text/tikz"
  data-tikz-libraries="calc"
>
...
</script>

and:

<script
  type="text/tikz"
  data-tikz-libraries="positioning"
>
...
</script>

produce different rendering identities.


Scheduler-only values

A value used only for main-thread scheduling does not need to affect the compiled SVG.

For example:

data-render-priority="-10"

is consumed by the scheduler and removed before the worker dataset is serialized.

Changing only the explicit queue priority therefore does not change the generated diagram or its persistent SVG identity.


Persistent SVG cache

TikZJax stores generated SVG markup in IndexedDB.

Database: TikzJax
Object store: svgImages

On a cache hit:

source discovery
    |
    v
IndexedDB lookup
    |
    v
cached SVG insertion

No worker compilation is required.

On a cache miss, the diagram continues to pending-job grouping and scheduling.

See Cache and Performance.


Cache bypass

A diagram with:

data-disable-cache="true"

bypasses persistent SVG reuse and is sent through the rendering path again.

This does not disable:

  • worker-local TeX dependency caching;
  • WebAssembly runtime reuse;
  • the browser HTTP cache.

Pending-job architecture

Pending-job deduplication

Several identical sources may be discovered before their first rendering has completed.

TikZJax groups matching targets around one pending job:

target A ─┐
target B ─┼──> one pending render
target C ─┘

After the worker returns one SVG result, TikZJax applies it to every target in the group.

This prevents several workers from compiling the same rendering input simultaneously.


Pending-job identity

Two targets can share one pending job only when they have the same:

  • exact source;
  • worker dataset;
  • cache behavior;
  • effective rendering configuration.

A different package list, preamble, library list, or relevant local option creates another job.


Completed cache versus pending group

These mechanisms operate at different stages:

persistent cache:
reuse an already completed SVG

pending-job deduplication:
share one render currently in progress

A successful pending job can subsequently populate the persistent cache.


Render queue architecture

Central queue

All uncached, non-duplicated jobs enter one global queue.

source A ─┐
source B ─┼──> central queue ──> worker pool
source C ─┤
source D ─┘

The queue coordinates:

  • priority;
  • worker availability;
  • dependency affinity;
  • retries;
  • timeouts;
  • worker restarts;
  • grouped targets.

There is no separate independent queue for each source block.


Viewport priority

The scheduler calculates a priority from the source element's relationship with the current viewport.

Typical classes are:

Priority Source state
0 Intersects the viewport
1 Near the viewport
2 Farther from the viewport
3 Hidden or disconnected

Lower values are selected first.

An explicit data-render-priority value can override the automatic priority.


Reprioritization

The queue can be reprioritized as:

  • the user scrolls;
  • a hidden tab becomes visible;
  • dynamic content is inserted;
  • an element moves into or away from the viewport.

Jobs that have already started are not normally interrupted solely because another source receives a better priority.


Completion order

Parallel jobs can complete in any order.

document order:
A, B, C

completion order:
B, C, A

Each SVG is still inserted into its correct target wrapper.

Application code must not assume source-order completion.


Adaptive worker-pool architecture

Pool purpose

A Web Worker can execute only one TeX compilation at a time.

TikZJax therefore uses several isolated workers to compile independent diagrams concurrently.

global queue
    |
    +-- worker 1 --> diagram A
    +-- worker 2 --> diagram B
    +-- worker 3 --> diagram C

One diagram is never divided between workers.


Pool configuration

The main pool settings are:

window.TikzJaxOptions = {
    workerPool: {
        enabled: true,
        maxWorkers: 3,
        reserveCpuCores: 1,
        useDeviceMemory: true,
        initializationRetries: 1
    }
};

The nested alias is:

window.TikzJaxOptions = {
    worker: {
        pool: {
            enabled: true,
            maxWorkers: 3
        }
    }
};

The root workerPool value takes precedence.


Effective pool size

The effective number of workers is bounded by:

  • pending and active workload;
  • maxWorkers;
  • available logical processor information;
  • reserveCpuCores;
  • optional device-memory limits.

Conceptually:

effective worker count =
max(
    1,
    min(
        active workload,
        configured maximum,
        CPU-based limit,
        memory-based limit
    )
)

When no uncached work exists, the runtime does not need to initialize rendering workers.


Lazy initialization

Worker initialization is deferred until the queue contains work.

The pool can grow as required, up to its calculated limit.

one pending job
    |
    v
one worker required
many pending jobs
    |
    v
pool grows toward effective limit

TikZJax does not need to create every possible worker in advance.


Worker states

A worker can conceptually be in one of these states:

initializing
idle
busy
failed
restarting
terminated

Initializing

The worker script, WebAssembly module, core dump, and TeX environment are being prepared.

Idle

The worker is ready to receive a job.

Busy

The worker is processing one diagram.

Failed

The worker encountered an initialization, runtime, communication, or timeout failure.

Restarting

The failed worker is being replaced.

Terminated

The worker is no longer part of the active runtime.


One active job per worker

A worker does not process two TeX compilations concurrently.

worker 1:
diagram A
    |
    v
diagram D
    |
    v
diagram G

Concurrency exists between workers.


Dependency affinity

When several workers are suitable for a job, the scheduler can prefer a worker that already has useful dependencies cached.

Example:

job requires:
chemfig

worker 1:
idle
chemfig prepared

worker 2:
idle
chemfig not prepared

Worker 1 is the preferred candidate.

Dependency affinity is only a tie-breaker after scheduling priority and worker availability.

TikZJax does not intentionally leave useful capacity idle for a long period merely to wait for a better cache match.


Worker initialization

Worker startup mode

Workers can be created in one of three modes.

Mode Behavior
auto Direct for same-origin URLs, Blob for cross-origin URLs
direct Use new Worker(workerUrl)
blob Fetch worker source and create a Blob URL

The configured worker mode applies to every member of the pool.


Initialization message

After a worker is created, the main thread supplies initialization information such as:

  • asset base URL;
  • WebAssembly file location;
  • core dump location;
  • TeX file root;
  • runtime behavior options.

The worker must report successful initialization before it becomes idle and eligible for jobs.


Initialization retries

Worker startup failures are governed by:

workerPool: {
    initializationRetries: 1
}

These retries are separate from maxRetries, which applies to diagram rendering.

If initialization cannot succeed after the allowed attempts, that worker cannot join the active pool.


Worker runtime architecture

WebAssembly TeX engine

Each worker initializes a TeX engine from:

tex.wasm.gz

The worker also loads:

core.dump.gz

The dump provides the base TeX state used by TikZJax.

The WebAssembly instance and TeX engine remain associated with that worker for subsequent jobs.


Virtual filesystem

Each worker owns an isolated virtual filesystem.

It contains:

  • base runtime files;
  • files restored from the core dump;
  • dynamically downloaded package files;
  • generated input.tex;
  • generated intermediate files;
  • the output DVI file.

Another worker cannot directly access this filesystem.


Worker-local TeX file cache

Optional packages and TikZ libraries are stored as compressed runtime files under:

tex_files/

When TeX requests a missing file, the worker can:

  1. resolve its runtime URL;
  2. fetch the compressed file;
  3. decompress it;
  4. insert it into the virtual filesystem;
  5. remember the prepared file for later jobs.

The in-memory prepared-file cache belongs to that worker.

worker 1:
- physics.sty
- amsmath.sty

worker 2:
- chemfig.sty
- simplekv.sty

Isolation between workers

Workers do not directly share:

  • TeX virtual filesystems;
  • decompressed package files;
  • initialized TeX state;
  • job-specific macros;
  • generated files.

The browser may reuse compressed HTTP responses, but each worker maintains its own prepared runtime state.


Runtime reuse

An initialized worker can process multiple diagrams:

initialize worker
    |
    v
render diagram A
    |
    v
clean job files
    |
    v
render diagram D

Reusable runtime files remain available, while job-specific files are cleaned between compilations.


Generated LaTeX document

Document construction

For every job, the worker builds a complete LaTeX document.

Conceptually:

\documentclass{article}

% Required base packages
\usepackage{tikz}

% Effective TeX packages
\usepackage{amsfonts}
\usepackage{physics}
\usepackage[options]{another-package}

% Effective TikZ libraries
\usetikzlibrary{
    arrows.meta,
    positioning
}

% TikZJax-generated tkz-tab preamble
% - public helper macros
% - native defaults when autoApply is enabled

% Effective custom preamble
\newcommand{\R}{\mathbb{R}}

\begin{document}

% Exact user source

\end{document}

The exact order and support code are generated by the worker implementation.


Package generation

The effective package object:

{
    amsfonts: "",
    xcolor: "dvipsnames"
}

conceptually becomes:

\usepackage{amsfonts}
\usepackage[dvipsnames]{xcolor}

Packages loaded locally are merged with globally configured packages for the current job.


TikZ-library generation

The effective library list:

[
    "arrows.meta",
    "calc",
    "positioning"
]

conceptually becomes:

\usetikzlibrary{
    arrows.meta,
    calc,
    positioning
}

Duplicate names are removed during configuration merging.


Custom preamble

The effective tex.addToPreamble string is inserted before \begin{document}.

A local data-add-to-preamble value is a scalar override of the global custom preamble for that diagram.

The complete TikZJax-generated tkz-tab preamble is inserted separately before the effective custom preamble. It contains the public helper macros and, when tkzTab.autoApply is enabled, the guarded native-default commands.


User source

The exact extracted source is inserted into the document body.

TikZJax does not require the source to contain a tikzpicture environment in every case.

For example, some packages provide their own top-level commands:

\chemfig{H_3C-CH_2-OH}

or:

\pgfspectra[element=H]

TeX execution

Compilation

The worker writes the generated document to:

input.tex

It then invokes the WebAssembly TeX engine.

The engine can request runtime files while compiling.

Successful compilation produces:

input.dvi

Compilation failures can include:

  • undefined commands;
  • missing packages;
  • missing TikZ libraries;
  • malformed TeX;
  • unavailable runtime files;
  • resource exhaustion;
  • timeout.

Console forwarding

A diagram with:

data-show-console="true"

can request forwarding of TeX console output to the browser console.

This is useful for identifying:

  • missing files;
  • package errors;
  • undefined control sequences;
  • TeX warnings;
  • compilation stages.

Timing collection

With timing diagnostics enabled, the worker can report stages such as:

TeX compilation
DVI conversion
total worker processing

Timing information is sent back with or alongside the result and logged by the runtime.


DVI conversion

DVI output

The TeX engine produces a DVI document rather than directly generating browser SVG.

The worker reads the DVI bytes and passes them to the DVI conversion layer.


dvi2html

TikZJax uses @rod2ik/dvi2html to convert the DVI output into HTML and SVG markup suitable for insertion into the page.

Conceptually:

input.dvi
    |
    v
DVI parser and converter
    |
    v
SVG/HTML string

The result is sent from the worker to the main thread.


Result handling

Successful result

The worker response contains the generated markup and associated job information.

The main thread:

  1. validates the response;
  2. resolves the pending job;
  3. stores the result in IndexedDB when caching is enabled;
  4. inserts the SVG into every grouped target;
  5. applies wrapper and helper classes;
  6. resolves the active theme and configured target palette;
  7. optionally styles configured page targets;
  8. applies the ordered wrapper and SVG theme pipeline;
  9. dispatches the completion event;
  10. marks the worker idle;
  11. schedules the next queued job.

Generated wrapper

Output is placed inside a wrapper similar to:

<span class="tikzjax-wrapper mathjax_ignore">
    <svg>...</svg>
</span>

While rendering, the wrapper also carries a loading state such as:

tikzjax-loading

The mathjax_ignore class helps prevent later MathJax rescans from reprocessing generated TikZJax output.


Helper containers

If a source is inside:

<div class="tikzjax-container">

TikZJax applies visible overflow behavior to the generated SVG.

Inside:

<div class="tikzjax-scaled-container">

the SVG also receives full-width and full-height behavior.


Theme architecture

Theme handling runs on the main browser thread after SVG insertion. It does not require another TeX compilation and does not run inside the rendering workers.

Configured target discovery

When theme.selector is defined, TikZJax evaluates it with:

document.querySelectorAll(
    theme.selector
)

The selector can therefore identify:

  • one page-level application container;
  • several independent theme regions;
  • a custom diagram zone;
  • a nested element selected with a compound CSS selector.

Every matching element becomes a configured theme target.

For one rendered wrapper, TikZJax associates the matching target that is either the wrapper itself or contains it.

An invalid selector produces a browser-console warning and yields no configured targets. It does not stop source discovery, rendering, caching, or worker scheduling.


Theme detection

After SVG insertion, TikZJax determines the applicable light or dark theme.

Theme detection can use:

  • the configured target;
  • a configured attribute;
  • configured dark and light classes;
  • nearby theme attributes;
  • MkDocs Material's color-scheme attribute;
  • fallback settings;
  • system theme preference when enabled.

Detection and target styling are separate responsibilities.

A configured selector can participate in detection even when:

theme.applyTargetStyles === false

See Themes.


Palette resolution

After resolving the light or dark state, TikZJax selects the corresponding palette.

light theme
    |
    +-- lightBackgroundColor
    |
    +-- lightTextColor
dark theme
    |
    +-- darkBackgroundColor
    |
    +-- darkTextColor

Built-in fallback values are:

light background: #ffffff
light text:       #000000

dark background:  #1b1e2b
dark text:        #ffffff

The resolved text color becomes the default foreground color used by the TikZJax wrapper and adaptive SVG content.

The resolved background color is used as a fallback when TikZJax cannot obtain a usable computed background from the configured target or its ancestors.


Optional target styling

Target styling is controlled by:

theme.applyTargetStyles

Its default value is:

false

When disabled, TikZJax does not impose page-level background or text colors on the configured targets.

This preserves the styling authority of existing frameworks, including MkDocs Material.

When enabled, TikZJax applies the resolved palette to every element matched by theme.selector:

background-color: <resolved background>;
color: <resolved text color>;

It also publishes:

--tikzjax-theme-background-color
--tikzjax-theme-text-color
--tikzjax-background-color

These values are target-scoped and inherited by descendants.

TikZJax does not automatically create or recolor arbitrary component borders.


Separation between page styling and SVG adaptation

The configured page target and the generated diagram are handled at different levels:

configured page target
    |
    +-- optional background and text styling
    |
    +-- published CSS custom properties
            |
            v
      TikZJax wrapper
            |
            +-- resolved foreground color
            |
            +-- effective background variable
                    |
                    v
              generated SVG
                    |
                    +-- black/white normalization
                    |
                    +-- very-light fill adaptation
                    |
                    +-- explicit chromatic color adaptation
                    |
                    +-- foreground/background contrast correction

With applyTargetStyles: false, only wrapper and SVG adaptation occur.

With applyTargetStyles: true, target styling occurs in addition to wrapper and SVG adaptation.

Elements outside theme.selector remain controlled by the page's own CSS.


Ordered SVG adaptation pipeline

Theme adaptation happens on the main browser thread after SVG generation and insertion.

For every theme application, TikZJax performs the relevant stages in this order:

1. one-time black/white normalization
2. restore any previous contrast correction
3. adapt very light non-text fills
4. adapt explicit chromatic fill, stroke, and color values
5. correct detected foreground/background contrast

The first stage recognizes ordinary generated black and white values and applies TikZJax's existing foreground/background conventions. Pure black and pure white remain separate from adaptiveColors.

The second stage restores fills saved by a previous contrast pass. This prevents repeated Dark-mode applications from progressively darkening an already corrected background.

The third stage is theme.adaptiveFills. It converts very light non-text fills into darker Dark-mode fills before general chromatic adaptation.

The fourth stage is theme.adaptiveColors. In Dark mode, parseable explicit chromatic fill, stroke, and color values can be transformed into lighter, more vivid variants while preserving their perceived color family. Light mode restores the stored original chromatic values.

The fifth stage is theme.adaptiveColors.contrast. It can darken a detected filled background when the visible foreground/background contrast is below the configured minimum ratio.

All color stages are recomputed from stored original SVG values rather than from the previously transformed result.


Black and white normalization

Typical black/white normalization includes:

  • default black text changed to the active wrapper foreground;
  • ordinary black strokes and fills changed to theme-compatible foreground values;
  • selected white backgrounds made transparent or otherwise handled by the existing white-background rules.

The literal black and white values used to recognize ordinary generated SVG content remain detection markers. Configurable palette colors do not redefine which source colors are classified as default black or white.


Very-light fill adaptation

theme.adaptiveFills is a separate Dark-mode stage for very light non-text fills.

It runs before adaptiveColors, so a very light fill converted into a darker background is not immediately lightened again by the general chromatic fill transformation.

Text nodes and rectangular mathematical rules associated with text are excluded from this stage.

Light mode restores the stored fill from before the adaptiveFills transformation.


Explicit chromatic color adaptation

theme.adaptiveColors is enabled by default.

The stage processes ordinary parseable SVG values used by:

fill
stroke
color

It excludes:

  • pure black and pure white;
  • currentColor;
  • none;
  • transparent paint;
  • CSS variables;
  • gradients, patterns, and other url(...) paint servers.

In Dark mode, perceptual lightness, saturation, and optional hue-family shifts are computed from the stored source color.

In Light mode, the stored original chromatic value is restored exactly.

Disabling adaptiveColors also disables its nested contrast stage, but it does not disable the separate adaptiveFills stage.


Foreground/background contrast correction

The contrast stage runs only when:

active theme = dark
adaptiveColors is enabled
contrast.enabled is enabled

No additional configuration option is required for the expanded foreground detection.

TikZJax evaluates three common SVG arrangements:

  1. an SVG <text> element painted over a previously painted filled shape;
  2. a bright neutral stroke belonging to the same element as its background fill;
  3. a small bright-neutral vector shape painted over a larger previously painted filled shape.

For text and separate vector details, TikZJax searches common filled shapes painted earlier, compares screen-space geometry, and selects the smallest valid containing background.

For a same-element fill/stroke pair, no containment search is required.

The contrast calculation can use:

  • the resolved foreground fill or stroke;
  • the resolved background fill;
  • fill opacity;
  • stroke opacity;
  • element opacity;
  • the effective page background;
  • relative luminance.

When the ratio is below theme.adaptiveColors.contrast.minimumRatio, TikZJax reduces the background fill's HSL lightness while preserving its hue, saturation, and alpha.

The foreground text, stroke, or vector detail is not recolored by this stage.

Chromatic vector accents, such as a red target point, are deliberately excluded from the bright-neutral outline and vector-detail heuristic.

A modified background receives:

data-tikzjax-contrast-adjusted="true"

The original fill and inline fill style are stored so that the correction can be restored before the next theme application.

containmentTolerance affects only the association of separate text or vector details with a background shape. It does not affect a direct fill/stroke comparison on one SVG element.


Theme observation

TikZJax observes relevant theme changes and schedules updates to:

  • configured targets when target styling is enabled;
  • already rendered wrappers;
  • already rendered SVG elements.

Theme updates do not require recompiling the TeX source.

theme attribute or class changes
    |
    v
detect new theme
    |
    v
resolve new palette
    |
    +-- optionally restyle configured targets
    |
    +-- update wrappers
    |
    +-- restore previous adaptive corrections
    |
    +-- recompute fills, explicit colors, and contrast

A cached SVG follows the same main-thread theme path after insertion as a freshly rendered SVG. The persistent cache stores generated SVG markup before page-specific theme adaptation, so the same cached rendering can be adapted to the currently active theme after insertion.


Dynamic-content architecture

Central MutationObserver

TikZJax uses a central DOM observer rather than creating one observer per diagram.

The observer detects added nodes that may contain:

script[type="text/tikz"]
pre.language-tikzjax
pre.tikzjax
pre.language-tikz
pre.tikz

Detected candidates are added to a central processing queue.


Mutation batching

DOM mutations may arrive in bursts.

TikZJax batches or schedules processing so that many related changes do not immediately trigger redundant full scans.

mutation A ─┐
mutation B ─┼──> central mutation queue --> scheduled scan
mutation C ─┘

This is useful for frontend frameworks and documentation themes that insert several nodes at once.


MkDocs content tabs

TikZJax listens for interactions commonly associated with MkDocs Material content tabs.

When hidden tab content becomes visible, TikZJax schedules a rescan and reprioritizes newly visible diagrams.

Those diagrams join the same global render queue and worker pool as the rest of the page.


Client-side navigation

On sites using client-side page replacement, newly inserted page content is detected through the same DOM-observation system.

Previously processed elements are not rendered again unless they are replaced with new source elements.


Error architecture

Failure categories

A render can fail during:

  • worker creation;
  • worker initialization;
  • asset loading;
  • package loading;
  • TeX compilation;
  • DVI generation;
  • DVI conversion;
  • worker communication;
  • timeout;
  • result insertion.

The main thread associates failures with the relevant job and worker.


Timeouts

Each rendering attempt has a finite timeout.

job starts
    |
    v
timeout timer starts
    |
    +-- result arrives --> clear timer
    |
    +-- timer expires --> fail attempt

A timed-out worker is not considered safe for immediate reuse and is replaced before processing later work.


Render retries

maxRetries controls retries after the initial attempt.

initial attempt
    |
    +-- success
    |
    +-- failure
            |
            v
         retry 1

A retried job can be assigned after worker recovery or replacement.

Retries do not correct invalid TeX source.


Worker restart

When restart behavior is enabled, a failed worker is terminated and replaced.

worker failure
    |
    v
remove worker from active pool
    |
    v
terminate failed runtime
    |
    v
initialize replacement
    |
    v
continue queue

Other workers can continue their current jobs.


Fallback image

After all permitted attempts fail, the target is replaced with the configured fallback image.

Priority:

bundled fallback
< global brokenImageSrc
< later global update
< local data-broken-image-src

Grouped targets can each receive their appropriate fallback handling.

See Fallback and Error Images.


Completion event

After successful SVG insertion, TikZJax dispatches:

tikzjax-load-finished

The event:

  • originates from the generated SVG;
  • bubbles through the document;
  • is emitted for cached and freshly rendered SVGs;
  • is emitted once for each target;
  • does not guarantee document-order delivery.
document.addEventListener(
    "tikzjax-load-finished",
    function (event) {
        const svg = event.target;

        console.log(
            "TikZJax diagram ready:",
            svg
        );
    }
);

Cleanup and lifecycle

Per-job cleanup

After compilation, a worker removes or resets job-specific files such as:

input.tex
input.dvi
temporary TeX outputs

Reusable runtime files remain available in the worker cache.


Worker restart cleanup

Terminating a worker discards:

  • its WebAssembly runtime;
  • its virtual filesystem;
  • decompressed TeX files;
  • job state;
  • message handlers associated with that worker.

Page cleanup

When the page unloads or TikZJax is torn down, the runtime can:

  • disconnect DOM observers;
  • disconnect theme observers;
  • cancel scheduled scans;
  • reject or clear pending jobs;
  • clear timeout handles;
  • revoke Blob worker URLs;
  • terminate active workers.

This prevents page-level runtime state from surviving after the document is no longer active.


End-to-end sequence

The following sequence summarizes a fresh uncached render:

1. Main thread discovers source
2. Main thread extracts source and local attributes
3. Main thread merges global and local configuration
4. Main thread builds render identity
5. Main thread checks IndexedDB
6. Main thread checks matching pending jobs
7. Main thread creates a new queued job
8. Scheduler calculates viewport priority
9. Pool initializes or selects a worker
10. Main thread sends source and dataset
11. Worker builds input.tex
12. Worker resolves TeX dependencies
13. Worker runs WebAssembly TeX
14. Worker reads input.dvi
15. Worker converts DVI to SVG/HTML
16. Worker sends the result to the main thread
17. Main thread stores the SVG in IndexedDB
18. Main thread inserts the SVG into grouped targets
19. Main thread resolves the active theme and target palette
20. Main thread optionally styles configured page targets
21. Main thread applies black/white normalization, adaptive fills, adaptive colors, and foreground/background contrast correction
22. Main thread dispatches tikzjax-load-finished
23. Worker returns to the idle pool

A cached render skips steps 6 through 16.

A target joining an existing pending job skips the creation of a duplicate queue entry.


Design goals

The architecture is designed to provide:

  • browser responsiveness;
  • client-side rendering;
  • bounded parallelism;
  • predictable resource use;
  • failure isolation;
  • persistent SVG reuse;
  • dynamic-content support;
  • local dependency isolation;
  • compatibility with documentation frameworks;
  • progressive rendering of long pages.

The worker pool improves throughput, while viewport priority improves perceived performance.

Persistent SVG caching avoids compilation entirely when a matching result already exists.

Local package declarations reduce unnecessary TeX preamble work across the pool.