Render Profile Architecture
Relevant source files
The following files were used as context for generating this wiki page:
The Render Profile Architecture in cheMD defines a system for controlling the visual rendering style of chemical structures and reactions without altering the underlying semantic meaning of the document. It serves as a configuration layer that separates "what" is being described (molecules, reactions, experimental data) from "how" it appears in different outputs like HTML previews, SVG assets, or DOCX exports.
This architecture ensures that the same source document can be rendered using various presets, such as a balanced Electronic Lab Notebook (ELN) preview, a monochrome publication-ready style (e.g., ACS), or high-visibility slides for presentations.
Sources: chemd-render-profile-v0.1-spec.md:1-15, chemd-v0.1-architecture.md:12.1
Core Architectural Principle: Semantic Separation
A fundamental rule of the cheMD architecture is the "Hard Boundary" between the Semantic AST and Render Options. Semantic blocks (like molecule or reaction) are strictly forbidden from owning style properties such as bond lengths or line widths.
Semantic AST vs. Render Options
| Category | Contains |
|---|---|
| Semantic AST | Frontmatter metadata, molecule, reaction, result, references, and template structures. |
| Render Options | Profile IDs, resolved tokens (bond length, font size, monochrome mode, background color), and adapter-specific values. |
Sources: chemd-v0.1-architecture.md:4.1-4.3, chemd-v0.1-spec.md:5.1-5.2
The Render Selection Pipeline
The system operates as a multi-stage pipeline where render profile resolution occurs after the semantic AST is normalized but before the final rendering stage.
This flow ensures that style resolution is independent of semantic object parsing.
Sources: chemd-v0.1-architecture.md:5.0-5.1
Render Profile Schema and Configuration
A render profile is a JSON-compatible object that specifies settings across three main categories: structure geometry, reaction layout, and export defaults.
Canonical Profile Structure
The profile configuration is organized into specific sub-objects:
structure: Controls bond length, line width, multiple bond offsets, hash spacing, font size, and color modes.reaction: Configures arrow length, component gaps, and condition placement.export: Defines image formats (SVG/PNG), margins, and DPI for raster outputs.
Sources: chemd-render-profile-v0.1-spec.md:40-80
Configuration Data Model
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the profile (e.g., eln-default). |
extends | string | Parent profile ID for inheritance. |
structure.bondLength | number | Target bond length in pixels or renderer units. |
structure.monochrome | boolean | Toggles between color and black-and-white mode. |
reaction.arrowLength | number | Preferred length for reaction arrows. |
export.imageFormat | string | Target format: svg or png. |
Sources: chemd-render-profile-v0.1-spec.md:55-75
Resolution and Inheritance Logic
Profiles support a hierarchical inheritance model. The final RenderOptions object used by renderers is produced by merging several layers of configuration.
Merge Priority
The resolution order (later values override earlier ones) is:
- Built-in Base Defaults: Hardcoded system values.
- Parent Profile Chain: Traversed via the
extendskey. - Selected Profile: The profile specifically named in the document.
- Document Overrides: Specific values provided in the YAML frontmatter.
Implementation of Frontmatter Selection
The packages/parser extracts these settings from the YAML frontmatter using two primary keys:
render_profile: Specifies the base ID.render_overrides: A mapping of specific paths (e.g.,structure.bondLineWidth) to values.
// Example from packages/parser/src/frontmatter/parse-frontmatter.ts
if (key === "render_profile") {
return mergeRenderSelection(currentSelection, { profileId: value.trim() });
}
if (key === "render_overrides") {
// Validates paths like structure.bondLineWidth and ensures scalar values
}
Sources: packages/parser/src/frontmatter/parse-frontmatter.ts:145-165, chemd-v0.1-spec.md:5.3
Adapter Mapping and Rendering
Generic render profile fields are designed to be renderer-agnostic. Each specific renderer package (e.g., renderer-svg) includes an adapter that maps these generic values to engine-specific parameters.
Adapter Targets
The architecture explicitly supports mapping to chemical drawing engines like RDKit.js:
structure.bondLineWidthmaps to RDKitbondLineWidth.structure.bondLengthmaps to RDKitfixedBondLength.structure.fontSizemaps to RDKitfixedFontSize.
Sources: chemd-render-profile-v0.1-spec.md:105-115, chemd-v0.1-architecture.md:14.2
Rendering Process Sequence
The renderer-html package consumes the resolved options to generate the final view.
Validation and Error Handling
The system includes robust diagnostics to handle invalid profile selections:
W_UNKNOWN_RENDER_PROFILE: Triggered if a selected ID is not found in the registry, causing a fallback to the default profile.E_INVALID_RENDER_PROFILE_VALUE: Triggered if an override value does not match the expected type (e.g., a string provided for a numeric bond length).- Cycle Detection: Inheritance loops in
extendsmust produce an error.
Sources: chemd-render-profile-v0.1-spec.md:95-100, packages/compiler/tests/compiler.test.ts:85-100, chemd-v0.1-architecture.md:15.2
Summary
The Render Profile Architecture is a decoupled configuration system that enables multi-target rendering of chemical data. By enforcing a strict separation between semantic AST nodes and visual style properties, the project ensures that experimental data remains portable and machine-readable while allowing high-quality, customizable visual output across web, print, and presentation platforms.