HTML Renderer
Relevant source files
The following files were used as context for generating this wiki page:
The HTML Renderer is a core output module of the chemd system responsible for transforming a resolved Abstract Syntax Tree (AST) into a human-readable HTML preview. It serves as the primary visualization layer for the Electronic Lab Notebook (ELN), consuming a ChemdDocument and a set of RenderOptions to produce a structured document enhanced with chemical diagrams and formatted experimental data.
The renderer is designed as the final stage of a multi-stage pipeline, following the parser and resolver. It handles both standard Markdown elements (headings, lists, tables) and domain-specific structured blocks (molecules, reactions, analysis results) by generating semantic HTML with specific CSS classes (e.g., chemd-block, chemd-markdown).
Sources: chemd-v0.1-architecture.md:6.1, chemd-v0.1-architecture.md:13.1, packages/renderer-html/src/index.ts:792-817
Architecture and Data Flow
The HTML Renderer operates by traversing the children of a ChemdDocument. Each node type is dispatched to a specific rendering function. The rendering process is "profile-aware," meaning it consumes a RenderOptions object to ensure the visual output adheres to a specific render profile (e.g., "eln-default" or "publication-acs").
Rendering Pipeline
The following diagram illustrates the flow from a resolved document to the final HTML string:
The rendering process integrates external SVG renderers for chemical structures while maintaining overall document flow.
Sources: packages/renderer-html/src/index.ts:756-790, chemd-v0.1-architecture.md:5
Markdown Transformation
The renderer implements a custom Markdown transformation layer to convert MarkdownNode content into HTML. Unlike standard Markdown parsers, it specifically handles chemd extensions like inline chemistry and resolved references.
Inline Element Handling
The renderer processes several types of inline tokens within Markdown text:
- Inline Chemistry: Converts
:chem[...]syntax into<span class="chem-inline">elements. - References: Replaces
@id.fieldor@meta.keytokens with their resolved values (e.g., a yield percentage or project title). - Styling: Supports bold (
**), italics (*), and strikethrough (~~) via regex-based replacement. - Safety: Sanitizes link
hrefattributes to preventjavascript:injection, while allowing standard protocols likehttp,https, andmailto.
Sources: packages/renderer-html/src/index.ts:10-100, packages/renderer-html/src/index.ts:251-300
Block-Level Elements
The renderer manually parses and renders common Markdown block structures:
| Element | HTML Tag / Class | Logic Highlights |
|---|---|---|
| Headings | <h1-6> | Uses chemd-markdown--h[1-6] classes. |
| Lists | <ul>, <ol> | Supports nesting and task lists (checkboxes). |
| Tables | <table> | Supports alignment (left, center, right) via : syntax. |
| Quotes | <blockquote> | Recursively renders nested Markdown nodes. |
| Code | <pre><code> | Preserves whitespace; supports language data attributes. |
Sources: packages/renderer-html/src/index.ts:470-692, packages/renderer-html/tests/renderer-html.test.ts:133-170
Structured Block Rendering
Chemical and experimental data blocks are rendered as <section> elements with specific BEM-style classes.
Chemical Graphics
For reaction and molecule blocks, the renderer calls the @chemd/renderer-svg package to generate SVG content. This content is then embedded within a div.chemd-graphic wrapper. The SVG generation respects the fixedBondLength and other styling parameters defined in the RenderOptions.
Field Lists
Experimental metadata (e.g., temperatures, times, amounts) is rendered using a definition list (<dl>) with the class chemd-fields. Each field is wrapped in a div.chemd-field containing a <dt> (label) and <dd> (value).
Visual representation of the relationship between structured blocks and their rendered components.
Sources: packages/renderer-html/src/index.ts:699-754, packages/renderer-html/tests/renderer-html.test.ts:30-70
Diagnostics Integration
The renderer includes a diagnostic reporting section at the end of the document. If the ChemdDocument contains errors or warnings (e.g., E_DUPLICATE_ID or W_UNRESOLVED_REFERENCE), they are rendered as an unordered list:
- Severity: Captured in a
data-severityattribute. - Content: Displays the diagnostic code and the human-readable message.
Sources: packages/renderer-html/src/index.ts:803-812, chemd-v0.1-spec.md:22
Key Implementation Snippets
Document Wrapper
The entry point renderHtml wraps the entire output in an <article> tag, preserving the render profile ID for CSS targeting.
// packages/renderer-html/src/index.ts:792-817
export const renderHtml = (
document: ChemdDocument,
options: RenderOptions,
adapterPayload?: RenderAdapterPayload
): string => {
const resolvedAdapterPayload = adapterPayload ?? mapRenderOptionsToAdapterPayload(options);
const body = document.children.map((child) => renderNode(child, options, resolvedAdapterPayload)).join("\n");
return [
`<article class="chemd-document" data-profile="${escapeHtml(options.profileId)}">`,
`<header><h1>${escapeHtml(String(document.meta.title))}</h1><p>${escapeHtml(String(document.meta.date))}</p></header>`,
`<section class="chemd-body">${body}</section>`,
diagnostics,
`</article>`
].join("");
};
Table Rendering Alignment
The renderer detects separator lines (e.g., | :--- | ---: |) to apply inline styles for cell alignment.
// packages/renderer-html/src/index.ts:511-525
const alignments: MarkdownTableAlignment[] = separatorCells.map((cell) => ({
horizontal: cell.startsWith(":") && cell.endsWith(":")
? "center"
: cell.endsWith(":")
? "right"
: cell.startsWith(":")
? "left"
: undefined
}));
Conclusion
The HTML Renderer provides a robust and extensible way to visualize chemical experiment data. By separating semantic content from render profiles and utilizing a structured pipeline, it ensures that documents remain readable across different contexts, from internal lab notebook previews to publication-ready formats. Its primary strength lies in the seamless integration of standard Markdown with complex chemical objects and a rigorous diagnostic system.