SVG Chemistry Renderer
Relevant source files
The following files were used as context for generating this wiki page:
The SVG Chemistry Renderer is a specialized package (packages/renderer-svg) within the cheMD ecosystem designed to transform structured chemical data—specifically molecules and reactions—into visual SVG assets. It operates as a late-stage consumer in the cheMD pipeline, utilizing resolved semantic AST nodes and independent render profiles to produce high-quality, export-safe vector graphics.
The renderer is built on a "Hard Architectural Boundary" that separates semantic content (the "what") from visual styling (the "how"). It supports a variety of rendering modes, including simple sketch segments for linear SMILES, aromatic atom preservation, and complex reaction layouts with arrows and conditions. While RDKit.js serves as the primary backend engine via an adapter boundary, the system is designed to be engine-agnostic to support future integrations like Ketcher or Indigo.
Sources: chemd-v0.1-architecture.md:20-35, chemd-v0.1-architecture.md:73-77, packages/renderer-svg/tests/renderer-svg.test.ts
Core Architecture and Data Flow
The SVG Renderer sits at the end of a multi-stage compilation pipeline. It does not parse raw text; instead, it receives normalized semantic nodes that have already been processed by the parser and resolver.
Rendering Pipeline
The following diagram illustrates how raw chemical data is transformed into a visual SVG:
The diagram shows the transition from semantic nodes through style resolution to the final SVG output via internal generators or external adapters.
Sources: chemd-v0.1-architecture.md:92-105, packages/renderer-svg/tests/renderer-svg.test.ts:47-60
Interface and Contracts
The renderer exposes two primary functions as its public API:
renderMoleculeSvg(input, options, adapterPayload)renderReactionSvg(input, options, adapterPayload)
These functions consume a RenderOptions object which is strictly separated from the semantic data. This ensures that changing a font size or bond length does not alter the underlying chemical meaning.
Sources: chemd-v0.1-architecture.md:213-214, chemd-v0.1-architecture.md:126-127
Molecule Rendering Logic
The molecule renderer handles the translation of SMILES strings into visual structures. It employs a tiered approach based on the complexity of the input.
Rendering Features
- Sketch Segments: For simple molecules, the renderer can produce linear sketch segments with round linecaps.
- Aromatic Preservation: Lowercase atom symbols (e.g.,
c1ccccc1) are preserved as aromatic indicators in the output rather than being converted to uppercase. - Ring Notation: Supports multi-digit ring closure notation using the percent syntax (e.g.,
%12). - Fallback Mechanism: If a SMILES string uses unsupported syntax (like specific stereochemistry tokens in v0.1), the renderer produces a readable fallback block with diagnostic information.
Sources: packages/renderer-svg/tests/renderer-svg.test.ts:47-111
Render Options Mapping
The generic RenderOptions are mapped to an AdapterPayload used by engines like RDKit. The following table details key mapping targets:
| Generic Option | Description | Adapter Mapping Example (RDKit) |
|---|---|---|
bondLength | Target length of bonds | fixedBondLength |
bondLineWidth | Width of bond lines | bondLineWidth |
fontSize | Base atom label size | fixedFontSize |
monochrome | Toggle for color mode | monochrome |
backgroundColor | Canvas background | backgroundColor |
Sources: chemd-render-profile-v0.1-spec.md:144-149, packages/renderer-svg/tests/renderer-svg.test.ts:114-147
Reaction Rendering and Layout
Reaction rendering involves managing multiple chemical species and structural elements like arrows and separators.
Layout Components
- Reaction Sides: Components are grouped into
reactantsandproducts. - Plus Separators: Multiple fragments on either side are separated by plus signs (
chemd-reaction-side__plus). - Reaction Arrow: A central arrow connects the two sides, often featuring a
marker-endfor the arrowhead. - Conditions: Metadata such as temperature, solvent, and time can be placed above or below the arrow.
Sources: packages/renderer-svg/tests/renderer-svg.test.ts:168-185, packages/renderer-svg/tests/renderer-svg.test.ts:228-241
Component Interaction
The relationship between the renderer and other system components during a reaction render is shown below:
This sequence demonstrates how the SVG Renderer depends on both the Resolver for data and the Render Profile for styling.
Sources: chemd-v0.1-architecture.md:255-263, packages/compiler/tests/compiler.test.ts:12-35
Security and Sanitization
As the renderer handles external data (SMILES) and configuration (Render Options), it implements strict sanitization to ensure "Export Safety."
- Adapter Payload Sanitization: The renderer validates and clamps incoming adapter fields. For example, it prevents
NaNor infinite values for bond lengths and sanitizes background colors to prevent script injection via CSS/SVG attributes. - Safe Links: When rendering labels or captions that might contain links, the system utilizes a
sanitizeHrefutility to blockjavascript:protocols. - SMILES Validation: Unexpected tokens in SMILES trigger a safe fallback UI rather than a system crash.
Sources: packages/renderer-svg/tests/renderer-svg.test.ts:114-147, packages/renderer-html/src/index.ts:109-138, chemd-v0.1-architecture.md:297-300
Integration with Export Pipelines
The SVG output is a core part of the cheMD export strategy.
- HTML Preview: The HTML renderer (
packages/renderer-html) embeds SVG output directly into the document view within<div class="chemd-graphic">containers. - DOCX Bridge: For Word export, the system can either embed these SVGs or provide raster fallbacks via the
docx-bridgepayload. - JSON Serialization: The finalized SVG string or its generation metadata is included in the JSON export produced by the compiler.
Sources: packages/renderer-html/src/index.ts:718-735, packages/compiler/tests/compiler.test.ts:36-54, chemd-v0.1-architecture.md:204-208
The SVG Chemistry Renderer provides the visual bridge between abstract chemical data and human-readable documentation. By maintaining a strict separation between semantic data and render profiles, it allows cheMD to support diverse output styles—from internal notebook previews to publication-quality graphics—without requiring changes to the underlying source markdown.