1. Purpose & Motivation¶
Problem Solved¶
The HTML Rendering domain provides visual representation of Viper types and values with CSS-styled syntax highlighting. It solves the challenge of displaying complex type hierarchies and structured data in a human-readable format for:
- Web-based UIs: Interactive commit database editors, documentation browsers
- Documentation export: Generating standalone HTML files for sharing/archiving
- Debugging tools: Inspecting types and values with clear visual distinction (type annotations, syntax coloring)
Without HTML rendering, developers would see plain-text representations lacking: - Syntax highlighting (keywords, types, numbers, strings, UUIDs) - Hyperlinks (navigating between related types/documents) - Hierarchical structure (collapsible details/summary for nested data) - Customizable themes (CSS-based styling, light/dark modes)
Use Cases¶
Developers use the HTML domain when they need to:
- Build web editors: Create browser-based tools for viewing/editing commit databases (e.g.,
web_cdbeapplication) - Export documentation: Generate self-contained HTML files documenting DSM schemas, type hierarchies, or database snapshots
- Debug type errors: Visually inspect complex types (e.g.,
Map<String, Vec<Int32, 3>>) with color-coded structure - Render values in UIs: Display structured data (concepts, attachments, collections) with proper formatting and type annotations
- Generate reports: Create formatted output for CI/CD pipelines, test results, or code reviews
Position in Architecture¶
Utility Layer - The HTML domain is an optional rendering layer that sits above the Type and Value System. It does not modify types or values, only provides visual representation.
┌─────────────────────────────────────────────────────┐
│ Application Layer │
│ (web_cdbe, documentation tools) │
└──────────────────────┬──────────────────────────────┘
│ uses
▼
┌─────────────────────────────────────────────────────┐
│ HTML Rendering (Utility) │
│ • HtmlRenderer (semantic utilities) │
│ • HtmlTypeRenderer (type → HTML) │
│ • HtmlValueRenderer (value → HTML) │
│ • HtmlDocumentDetailsRender (hierarchical docs) │
└──────────────────────┬──────────────────────────────┘
│ depends on
▼
┌─────────────────────────────────────────────────────┐
│ Foundation Layer 0 │
│ • Type System (TypeCode, Type hierarchy) │
│ • Value System (Value hierarchy, iterators) │
└─────────────────────────────────────────────────────┘
Key characteristics: - Optional: Applications don't need HTML rendering for core functionality - Stateless: All functions are pure (no side effects, safe for concurrent use) - Read-only: Never modifies types or values, only renders them - Not used by Viper runtime: Zero core dependencies (0 includes from Viper_.hpp to Viper_Html.hpp)
2. Domain Overview¶
Scope¶
The HTML domain provides capabilities for:
- Type rendering: Convert
Typeobjects to styled HTML strings (e.g.,Vec<Float, 3>→<span class="clr_viper_type">Vec</span><...>) - Value rendering: Convert
Valueobjects to HTML with three modes (representation/description/pretty) - Document rendering: Render hierarchical
DocumentNodetrees with collapsible details/summary - Semantic utilities: Build custom HTML with Viper vocabulary (keywords, operators, numbers, strings, UUIDs)
- CSS styling: Provide default dark theme with 12 semantic color classes
Out of scope: - JavaScript interactivity (HTML only, no client-side scripting) - Data modification (read-only rendering) - Non-HTML formats (JSON, XML, Markdown - see JSON Support domain)
Key Concepts¶
- Three Rendering Modes - Different verbosity levels for different use cases:
- Representation: Value only, compact display (e.g.,
42,"hello") - Description: Value + type annotation for debugging (e.g.,
42:Int32,"hello":String) -
Pretty: Formatted output with optional type display, proper spacing for nested structures
-
Semantic CSS Classes - HTML uses 12 predefined classes for syntax highlighting:
clr_keyword: Language keywords (true,false,Key)clr_viper_type: Built-in types (Int32,Vec,Map)clr_user_type: User-defined types (Concepts, Clubs, Enumerations, Structures)clr_number: Numeric literalsclr_string: String contentclr_quote: String delimitersclr_uuid: UUIDs and blob IDsclr_operator: Operators (=,:,{,},[,],<,>)clr_comment: Documentation strings-
clr_docstr: Multi-line docstrings -
HTML Safety - All content is escaped to prevent XSS attacks:
<→<,>→>(viaHtmlRenderer::escape())- Angle brackets in types (
Vec<Float>) are rendered as<and> -
User strings are automatically escaped before rendering
-
Visitor Pattern - Type and value rendering use visitor-like dispatch:
- Switch on
TypeCodeto select appropriate rendering function - Each TypeCode (31 total) has dedicated render function (e.g.,
renderTypeVec,renderValueMap) -
Recursive rendering for generic types (Vec, Map, Tuple, Optional, etc.)
-
Composite Rendering - Hierarchical documents rendered recursively:
- Leaf nodes:
<div>fieldName = value</div> - Composite nodes:
<details><summary>fieldName</summary>...(children)...</details> - Automatic collapsing (level 0 open, others closed)
External Dependencies¶
Uses (Foundation Layer 0):
- Type System - Reads Type objects via type->typeCode, casts to specific types (TypeVec*, TypeMap*, etc.)
- Value System - Reads Value objects via value->typeCode(), value->representation(), iterators for collections
- StringHelper - Utility for string joining (StringHelper::join(elements))
- Lexicon - Viper vocabulary constants (Lexicon::Vec, Lexicon::Map, Lexicon::Key)
Used By (Application Layer):
- DSM domain - DSMDefinitionsRendererHtml uses HTML rendering to export DSM schemas to HTML
- web_cdbe - Web-based commit database editor uses HTML rendering for interactive document browsing
- Python bindings - P_Viper_Html exposes 8 methods to Python (Html.type(), Html.value(), Html.value_pretty(), etc.)
Coupling strength: Weak unidirectional (HTML → Type/Value, no reverse dependencies)
3. Functional Decomposition¶
3.1 Sub-domains¶
The HTML domain is organized into 5 functional sub-domains:
1. Semantic Utility Functions (HtmlRenderer)¶
Provides low-level HTML building blocks with semantic CSS classes. All functions are stateless (pure namespace functions, no classes).
Components:
- Semantic spans: keyword(), user_type(), viper_type(), number(), string(), quote(), uuid(), comment()
- Operators: op(), obr(), cbr(), och(), cch(), ocr(), ccr(), opa(), cpa(), eq()
- Structural elements: span(), odiv(), cdiv(), docstr()
- Special characters: sp() (non-breaking space), nl (newline), tq() (triple quotes)
- Safety: escape() - HTML-escape user content (< → <, > → >)
- Document builders: style(), body(), document()
Pattern: Utility Functions (stateless namespace functions)
2. Type Rendering (HtmlTypeRenderer)¶
Converts Type objects to HTML strings with CSS styling. Handles all 31 TypeCodes exhaustively.
Components:
- Public API: render(std::shared_ptr<Type> const &) - Single entry point
- Dispatch: Switch on type->typeCode to select renderer
- Renderers: One per TypeCode (31 total):
- Primitives: renderTypePrimitive() (Void, Bool, UInt8-64, Int8-64, Float, Double, String, UUId, etc.)
- Generic types: renderTypeVec(), renderTypeMat(), renderTypeTuple(), renderTypeOptional(), renderTypeVector(), renderTypeSet(), renderTypeMap(), renderTypeXArray(), renderTypeVariant()
- User types: renderTypeConcept(), renderTypeClub(), renderTypeEnumeration(), renderTypeStructure()
- DSM types: renderTypeKey()
Pattern: Visitor Pattern (switch-based dispatch on TypeCode)
Example:
// Vec<Float, 3> → <span class="clr_viper_type">Vec</span><<span class="clr_viper_type">Float</span>, <span class="clr_number">3</span>>
std::string renderTypeVec(TypeVec * type) {
return viper_type(Lexicon::Vec) + och() + renderType(type->elementType) + cm + number(type->size) + cch();
}
3. Value Rendering - Description Mode (HtmlValueRenderer)¶
Converts Value objects to HTML with two modes: representation (value only) or description (value + type).
Components:
- Public API:
- representation(Value const &) - Value only (compact)
- description(Value const &) - Value + type annotation (debugging)
- Dispatch: Private reprValue() and descValue() functions switch on value->typeCode()
- Renderers: One pair per TypeCode (31 × 2 = 62 functions):
- reprBool() / descBool()
- reprNumber() / descNumber()
- reprString() / descString()
- reprVec() / descVec() (recursive for elements)
- reprMap() / descMap() (recursive for key-value pairs)
- ... (31 TypeCodes total)
Pattern: Visitor Pattern + Strategy Pattern (two rendering strategies)
Complexity: 452 lines (most complex component due to 31 TypeCodes × 2 modes)
Example:
// Representation: "hello"
std::string reprString(ValueString const * value) {
return quote(value->representation()); // <span class="clr_quote">"hello"</span>
}
// Description: "hello":String
std::string descString(ValueString const * value) {
return desc(reprString(value), value); // "hello":<span class="clr_viper_type">String</span>
}
4. Value Rendering - Pretty Mode (HtmlValueRendererPretty)¶
Formatted value rendering with optional type display. Uses std::stringstream for efficient string building.
Components:
- Public API: render(Value const &, bool showType) - Single entry point with type toggle
- Dispatch: Private renderValue() switches on value->typeCode()
- Renderers: One per TypeCode (31 total):
- renderBool(), renderNumber(), renderString(), renderVec(), renderMap(), etc.
- All use renderValueType() helper to conditionally append type annotation
- Formatting: Proper spacing, indentation for nested structures
Pattern: Strategy Pattern (alternative to description mode with different formatting)
Complexity: 369 lines (second most complex)
Example:
std::string renderString(ValueString const * value, bool showType) {
std::stringstream ss;
ss << quote(value->representation());
if (showType)
ss << co + HtmlTypeRenderer::render(value->type()); // :<type>
return ss.str();
}
5. Document Details Rendering (HtmlDocumentDetailsRender)¶
Renders hierarchical DocumentNode trees with collapsible HTML5 <details>/<summary> elements.
Components:
- Public API: html(std::vector<DocumentNode> const &, bool showType) - Entry point
- Private API: render_node() - Recursive tree traversal
- Leaf rendering: <div>fieldName = value:type</div>
- Composite rendering: <details><summary>fieldName:type</summary>...(children)...</details>
- Auto-collapse: Level 0 open, others closed
Pattern: Composite Pattern (recursive tree traversal)
Complexity: 91 lines (simplest component)
Example:
void render_node(DocumentNode const & node, bool showType, std::stringstream & ss, int level) {
if (node->children.empty()) {
// Leaf: simple div
ss << odiv() << node->stringComponent << " = " << render_value(node);
if (showType) render_type(node->value->type(), ss);
ss << cdiv();
} else {
// Composite: collapsible details
auto const is_open = (level == 0) ? "open" : "";
ss << "<details " << is_open << "><summary>" << node->stringComponent;
if (showType) render_type(node->value->type(), ss);
ss << "</summary><div class='details_indent'>";
for (auto const & child : node->children)
render_node(child, showType, ss, level + 1); // Recursive
ss << "</div></details>";
}
}
3.2 Key Components (Entry Points)¶
| Component | Purpose | Entry Point File | Key APIs |
|---|---|---|---|
| HtmlRenderer | Semantic HTML utilities | Viper_HtmlRenderer.hpp |
keyword(), number(), string(), uuid(), escape(), style(), document() |
| HtmlTypeRenderer | Type → HTML | Viper_HtmlTypeRenderer.hpp |
render(Type) |
| HtmlValueRenderer | Value → HTML (2 modes) | Viper_HtmlValueRenderer.hpp |
representation(Value), description(Value) |
| HtmlValueRendererPretty | Value → HTML (pretty) | Viper_HtmlValueRendererPretty.hpp |
render(Value, showType) |
| HtmlDocumentDetailsRender | Document tree → HTML | Viper_HtmlDocumentDetailsRender.hpp |
html(documents, showType) |
Python Bindings: All components exposed via P_Viper_Html with 8 static methods on Html class.
3.3 Component Map (Visual)¶
┌────────────────────────────────────────────────────────────────┐
│ HTML Rendering Pipeline │
└────────────────────────────────────────────────────────────────┘
Input: Type/Value/DocumentNode objects
│
├─► HtmlTypeRenderer ──────────────┐
│ • Switch on TypeCode │
│ • Dispatch to render<Type>() │
│ • Recursive for generics │
│ │
├─► HtmlValueRenderer ──────────────┤
│ • representation() mode │ All use
│ • description() mode ├──► HtmlRenderer utilities
│ • Switch on typeCode │ • keyword()
│ │ • number()
├─► HtmlValueRendererPretty ────────┤ • string()
│ • render(showType) mode │ • uuid()
│ • Formatted output │ • op()
│ • Stringstream building │ • escape()
│ │
└─► HtmlDocumentDetailsRender ──────┘
• Composite pattern
• Recursive tree traversal
• <details>/<summary>
│
▼
Output: HTML string with CSS classes
│
├─► Wrap in document()
│ • style() → <style>...</style>
│ • body() → <body>...</body>
│ • document() → <!DOCTYPE html>...
│
▼
Complete HTML5 document
4. Developer Usage Patterns¶
4.1 Core Scenarios¶
Each scenario extracted from real usage (web_cdbe, Python API, C++ patterns).
Scenario 1: Type Rendering in Web UI¶
When to use: Display Type information in browser-based tools (web editors, documentation browsers)
Source: python/web_cdbe/html_documents_renderer.py:179 → render_type()
from dsviper import Html, TypeInt32, TypeVec, TypeFloat
# Render primitive type
type_html = Html.type(TypeInt32.make())
# Result: <span class="clr_viper_type">Int32</span>
# Render generic type (recursive)
vec_type = TypeVec.make(TypeFloat.make(), 3)
vec_html = Html.type(vec_type)
# Result: <span class="clr_viper_type">Vec</span><<span class="clr_viper_type">Float</span>, <span class="clr_number">3</span>>
Key APIs: Html.type(type)
CSS classes used: clr_viper_type, clr_number, clr_operator (for <, >)
Scenario 2: Value Rendering - Description Mode (Debugging)¶
When to use: Debugging - need to see both value AND type to understand what went wrong
Source: Migration Guide 1.2.0 + HtmlValueRenderer::description() pattern
from dsviper import Html, ValueString, ValueInt32, ValueVec
# String with type annotation
value_str = ValueString.make("hello")
html = Html.value(value_str, use_description=True)
# Result: <span class="clr_quote">"hello"</span>:<span class="clr_viper_type">String</span>
# Number with type annotation
value_int = ValueInt32.make(42)
html = Html.value(value_int, use_description=True)
# Result: <span class="clr_number">42</span>:<span class="clr_viper_type">Int32</span>
# Vec with type annotation (recursive)
value_vec = ValueVec.make(TypeFloat.make(), 3)
value_vec.set(0, 1.0)
value_vec.set(1, 2.0)
value_vec.set(2, 3.0)
html = Html.value(value_vec, use_description=True)
# Result: (<span class="clr_number">1.0</span>, <span class="clr_number">2.0</span>, <span class="clr_number">3.0</span>):<span class="clr_viper_type">Vec</span><...>
Key APIs: Html.value(value, use_description=True)
CSS classes used: clr_quote, clr_string, clr_number, clr_viper_type, clr_operator
Scenario 3: Value Rendering - Representation Mode (Compact Display)¶
When to use: Compact display for tables, summaries, or dense UIs where type is implicit
Source: Migration Guide 1.2.0 + HtmlValueRenderer::representation() pattern
from dsviper import Html, ValueString, ValueInt32, ValueBool
# String (no type)
value_str = ValueString.make("hello")
html = Html.value(value_str, use_description=False)
# Result: <span class="clr_quote">"hello"</span>
# Number (no type)
value_int = ValueInt32.make(42)
html = Html.value(value_int, use_description=False)
# Result: <span class="clr_number">42</span>
# Boolean (no type)
value_bool = ValueBool.make(True)
html = Html.value(value_bool, use_description=False)
# Result: <span class="clr_keyword">true</span>
Key APIs: Html.value(value, use_description=False)
Use case: Table cells, inline display, tooltips
Scenario 4: Pretty Rendering with Optional Type Display¶
When to use: Formatted output for documentation, reports, or when readability is critical
Source: Migration Guide 1.2.0 + HtmlValueRendererPretty::render() pattern
from dsviper import Html, ValueMap, ValueString, ValueInt32
# Create a Map<String, Int32> value
map_type = TypeMap.make(TypeString.make(), TypeInt32.make())
map_value = ValueMap.make(map_type)
map_value.insert(ValueString.make("age"), ValueInt32.make(42))
map_value.insert(ValueString.make("count"), ValueInt32.make(100))
# Pretty rendering WITH type display
html = Html.value_pretty(map_value, show_type=True)
# Result: Formatted map with proper spacing and type annotations
# {
# <span class="clr_quote">"age"</span>: <span class="clr_number">42</span>:<span class="clr_viper_type">Int32</span>,
# <span class="clr_quote">"count"</span>: <span class="clr_number">100</span>:<span class="clr_viper_type">Int32</span>
# }:<span class="clr_viper_type">Map</span><...>
# Pretty rendering WITHOUT type display (cleaner)
html = Html.value_pretty(map_value, show_type=False)
# Result: {
# <span class="clr_quote">"age"</span>: <span class="clr_number">42</span>,
# <span class="clr_quote">"count"</span>: <span class="clr_number">100</span>
# }
Key APIs: Html.value_pretty(value, show_type)
Difference from description mode: Better formatting (spacing, indentation), stringstream building
Scenario 5: Complete HTML Document Generation¶
When to use: Export standalone HTML files for sharing, archiving, or offline viewing
Source: Migration Guide 1.2.0 + HtmlRenderer::document() implementation
from dsviper import Html, TypeInt32, TypeVec, TypeFloat
# Step 1: Generate CSS styling (default dark theme)
style = Html.style()
# Result: <style>
# .clr_keyword { color: #FF7AB2; }
# .clr_viper_type { color: #D0A8FF; }
# .clr_number { color: #CFBE69; }
# ... (12 CSS classes)
# </style>
# Step 2: Build content
content = "<h1>Viper Type Documentation</h1>"
content += "<h2>Primitive Types</h2>"
content += "<p>" + Html.type(TypeInt32.make()) + "</p>"
content += "<h2>Generic Types</h2>"
vec_type = TypeVec.make(TypeFloat.make(), 3)
content += "<p>" + Html.type(vec_type) + "</p>"
# Step 3: Wrap in body
body = Html.body(content)
# Result: <body class='clr_background clr_text'>
# ... content ...
# </body>
# Step 4: Create complete HTML5 document
html_doc = Html.document(
title="Viper Type Documentation",
style=style,
body=body
)
# Result: <!DOCTYPE html>
# <html lang='en'>
# <head>
# <meta charset='UTF-8'>
# <meta name='viewport' content='width=device-width, initial-scale=1'>
# <style>...</style>
# <title>Viper Type Documentation</title>
# </head>
# <body class='clr_background clr_text'>...</body>
# </html>
# Step 5: Save to file
with open("documentation.html", "w") as f:
f.write(html_doc)
Key APIs: Html.style(), Html.body(content), Html.document(title, style, body)
Use case: CI/CD reports, documentation export, offline viewers
Scenario 6: Document Details Rendering (Hierarchical Structures)¶
When to use: Render hierarchical documents with collapsible sections (commit database web editor)
Source: python/web_cdbe/html_documents_renderer.py + HtmlDocumentDetailsRender::html() + Migration Guide 1.2.0
from dsviper import Html, DocumentNode, Database
# Load documents from database
database = Database.open("mydb.sqlite")
documents = database.get_documents(concept_runtime_id)
# Render with collapsible details/summary (HTML5)
html = Html.documents_details(documents, show_type=True)
# Result: <details open>
# <summary>fieldName:<span class="clr_viper_type">Type</span></summary>
# <div class="details_indent">
# <div>subfield = <span class="clr_number">42</span>:<span class="clr_viper_type">Int32</span></div>
# <details>
# <summary>nested:<span class="clr_viper_type">Structure</span></summary>
# ... (recursive children) ...
# </details>
# </div>
# </details>
# Without type display (cleaner for end users)
html = Html.documents_details(documents, show_type=False)
# Result: <details open>
# <summary>fieldName</summary>
# <div class="details_indent">
# <div>subfield = <span class="clr_number">42</span></div>
# ...
# </div>
# </details>
Key APIs: Html.documents_details(documents, show_type)
Features:
- Collapsible: Level 0 open by default, others closed (user can expand)
- Recursive: Handles arbitrary depth
- Type annotations: Optional (show_type=True/False)
Scenario 7: Custom HTML Building with Semantic Utilities¶
When to use: Build custom HTML layouts with Viper vocabulary and semantic styling
Source: python/web_cdbe/html_renderer.py (utility module) + HtmlRenderer C++ pattern
# Note: This uses Python utility module (web_cdbe/html_renderer.py)
# which mirrors C++ HtmlRenderer semantics
from html_renderer import keyword, number, uuid, string, op, sp
# Build custom output with semantic styling
output = keyword("true") # <span class="clr_keyword">true</span>
output += sp() #
output += op("=") # <span class="clr_operator">=</span>
output += sp() #
output += number("42") # <span class="clr_number">42</span>
# Result: <span class="clr_keyword">true</span> <span class="clr_operator">=</span> <span class="clr_number">42</span>
# Build type-like display
type_display = keyword("Key") + op("<") + string("Person") + op(">")
# Result: <span class="clr_keyword">Key</span><span class="clr_operator"><</span><span class="clr_string">Person</span><span class="clr_operator">></span>
# UUID rendering
uuid_display = uuid("123e4567-e89b-12d3-a456-426614174000")
# Result: <span class="clr_uuid">123e4567-e89b-12d3-a456-426614174000</span>
Key functions: keyword(), number(), string(), uuid(), op(), sp()
Use case: Web editor custom layouts, inline displays, tooltips
Note: Python module html_renderer.py is a lightweight clone (49 lines) for web_cdbe - does NOT bind C++ HtmlRenderer directly.
4.2 Integration Patterns¶
Pattern 1: Web-Based Commit Database Editor (web_cdbe)¶
Real-world application: python/web_cdbe/ (193 lines in html_documents_renderer.py)
Architecture:
Flask Web App (app.py)
│
├─► HtmlDocumentsRenderer (custom)
│ • Uses Html.type() for type annotations
│ • Uses html_renderer utilities (semantic styling)
│ • Builds interactive forms (<input>, <select>)
│ • Renders collapsible document trees
│
└─► Templates (Jinja2)
• abstractions.html
• keys.html
• documents.html
Key insight: HTML domain is composable - applications can use low-level utilities (keyword(), number()) OR high-level renderers (Html.type(), Html.documents_details()) as needed.
Pattern 2: DSM Schema Export (DSMDefinitionsRendererHtml)¶
Real-world application: Viper_DSMDefinitionsRendererHtml.cpp (used by DSM domain)
Flow:
DSMDefinitions (parsed .dsm schema)
│
└─► DSMDefinitionsRendererHtml
• Iterates concepts, structures, attachments, functions
• Uses HtmlRenderer utilities for keywords, types, operators
• Generates styled HTML with documentation strings
• Wraps in Html::document()
│
▼
Standalone HTML file (myschema.dsm.html)
Key insight: HTML rendering enables schema documentation export for review, CI/CD, or offline reference.
4.3 CSS Styling Customization¶
The default dark theme can be customized by replacing Html.style():
# Default dark theme (provided by Html.style())
custom_style = """
<style>
.clr_keyword { color: #FF7AB2; } /* Pink */
.clr_viper_type { color: #D0A8FF; } /* Purple */
.clr_number { color: #CFBE69; } /* Yellow */
.clr_string { color: #A3C2A3; } /* Green */
.clr_quote { color: #F06860; } /* Red */
.clr_uuid { color: #D78147; } /* Orange */
.clr_operator { color: #41A0C0; } /* Blue */
... (12 classes total)
</style>
"""
# Light theme (custom)
light_theme = """
<style>
.clr_background { background: #FFFFFF; }
.clr_text { color: #000000; }
.clr_keyword { color: #AF00DB; }
.clr_viper_type { color: #0000FF; }
.clr_number { color: #098658; }
... (customize all 12 classes)
</style>
"""
# Use custom theme
html_doc = Html.document(
title="Light Theme Documentation",
style=light_theme, # Replace default
body=Html.body(content)
)
12 CSS classes to customize:
1. clr_background - Document background
2. clr_text - Default text color
3. clr_keyword - Language keywords
4. clr_viper_type - Built-in types
5. clr_user_type - User-defined types
6. clr_number - Numeric literals
7. clr_string - String content
8. clr_quote - String delimiters
9. clr_uuid - UUIDs and blob IDs
10. clr_operator - Operators
11. clr_comment - Inline comments
12. clr_docstr - Multi-line docstrings
4.4 Test Suite Reference¶
No dedicated unit tests - HTML domain is a visual output utility, difficult to test without browser rendering.
Testing approach: - Manual verification: Open generated HTML in browser, inspect colors/structure - Integration tests: web_cdbe application serves as real-world test (193 lines of usage) - Visual regression: Compare screenshots of rendered HTML (not implemented)
Real-world usage examples:
- python/web_cdbe/html_documents_renderer.py (193 lines) - Full integration example
- python/web_cdbe/html_renderer.py (49 lines) - Semantic utilities usage
- src/Viper/Viper_DSMDefinitionsRendererHtml.cpp - C++ integration example
5. Technical Constraints¶
Performance Considerations¶
- Fast rendering (<10ms per value): Suitable for interactive web UIs
- Stateless functions: No object allocation, no constructor/destructor overhead
- Stringstream building: Efficient string concatenation (O(n) not O(n²))
-
No caching: Every call is independent (trade-off: simplicity over speed)
-
Recursive rendering: Handles arbitrary depth for generic types
- Vec
- Stack depth risk: Real types rarely exceed 10 levels
-
No tail-call optimization: C++ switch-based dispatch
-
CSS overhead: ~50 lines of CSS per document
- Acceptable for single-page exports
- For multi-document sites, extract CSS to separate file and link
Thread Safety¶
Completely thread-safe (all functions are stateless):
- ✅ Concurrent rendering: Multiple threads can call
Html.type(),Html.value()simultaneously - ✅ No shared state: All functions are pure (no global variables, no static members)
- ✅ Read-only: Never modifies Type/Value objects, only reads them
Safe patterns:
// Safe: Concurrent rendering from multiple threads
#pragma omp parallel for
for (int i = 0; i < values.size(); ++i) {
auto html = HtmlValueRenderer::representation(values[i]); // Thread-safe
results[i] = html;
}
Error Handling¶
No exceptions thrown - HTML rendering always succeeds:
- Unknown TypeCode: Cannot occur - switch covers all 31 TypeCodes exhaustively (compiler warning if case missing)
- Null Type/Value: Caller responsibility - HTML renderers assume valid pointers
- Invalid UTF-8: String content passed through as-is (HTML escaping preserves bytes)
Error prevention:
- Exhaustive switch: switch (typeCode) { case TypeCode::Bool: ... case TypeCode::String: ... } covers all cases
- Compiler enforces completeness: Missing case → warning/error
Memory Model¶
Viper reference semantics (all objects passed as std::shared_ptr):
-
Type rendering:
cpp std::string render(std::shared_ptr<Type> const & type); // Type is shared_ptr → no copy, no ownership transfer -
Value rendering:
cpp std::string representation(std::shared_ptr<Value const> const & value); // Value is const → read-only, safe for concurrent access -
DocumentNode rendering:
cpp std::string html(std::vector<std::shared_ptr<DocumentNode>> const & documents); // Vector of shared_ptr → no deep copy
Ownership: HTML renderers NEVER take ownership (all parameters are const & or const shared_ptr)
HTML Safety (XSS Prevention)¶
Critical constraint: All user content MUST be HTML-escaped to prevent XSS attacks.
Escape rules (HtmlRenderer::escape()):
std::string escape(std::string const & content) {
auto result{content};
StringHelper::replaceAll(result, "<", "<"); // < → <
StringHelper::replaceAll(result, ">", ">"); // > → >
return result;
}
Where escaping occurs:
- ✅ Type names: User-defined types (Concepts, Enumerations, Structures) - names escaped
- ✅ String values: ValueString::representation() already escapes, then wrapped in <span>
- ✅ Documentation: Docstrings (docstr()) escape content before rendering
- ✅ Operators: och() and cch() render as < and > (not < and >)
Example:
# Malicious string with HTML tags
value = ValueString.make("<script>alert('XSS')</script>")
# Safe rendering (tags escaped)
html = Html.value(value, use_description=False)
# Result: <span class="clr_quote">"<script>alert('XSS')</script>"</span>
# Browser displays: "<script>alert('XSS')</script>" as text (not executed)
Security guarantee: HTML domain never generates executable JavaScript - pure HTML + CSS only.
CSS Class Stability¶
12 CSS classes are part of public API - breaking changes require major version bump:
clr_background,clr_text,clr_keyword,clr_viper_type,clr_user_type,clr_number,clr_string,clr_quote,clr_uuid,clr_operator,clr_comment,clr_docstr
Backwards compatibility: Applications relying on these classes (e.g., web_cdbe) expect stable names.
Versioning: If class names change, archive old Html.style() as Html.style_v1() for compatibility.
6. Cross-References¶
Related Documentation¶
doc/Migration_Guide_1.2.0.md- DocumentsHtmlclass Python API (8 methods:dsm_definitions(),value(),value_pretty(),type(),style(),body(),document(),documents_details())doc/Migration_Guide_dsviper_to_Viper.md- MentionsDSMDefinitionsRendererHtmlfor schema exportdoc/Internal_Viper.md- References HTML as representation format optiondoc/domains/Dsm.md- Documents DSM rendering capability (DSMDefinitionsRenderer with HTML output)doc/domains/Type_And_Value_System.md- Foundation Layer 0 documentation (HTML depends on Type/Value)
Dependencies¶
This domain USES (Foundation Layer 0):
- Type System - Reads Type objects via type->typeCode, casts to specific types (TypeVec*, TypeMap*, TypeConcept*, etc.)
- Entry point: src/Viper/Viper_Type.hpp
- Usage: Switch on TypeCode, recursive rendering for generic types
- Value System - Reads Value objects via value->typeCode(), value->representation(), iterators for collections
- Entry point: src/Viper/Viper_Value.hpp
- Usage: Visitor pattern for all 31 TypeCodes, representation/description modes
- StringHelper - String manipulation utilities (join(), replaceAll())
- Entry point: src/Viper/Viper_StringHelper.hpp
- Usage: HTML escaping, array element joining
- Lexicon - Viper vocabulary constants (Lexicon::Vec, Lexicon::Map, Lexicon::Key, etc.)
- Entry point: src/Viper/Viper_Lexicon.hpp
- Usage: Type name rendering
This domain is USED BY (Application Layer):
- DSM domain - DSMDefinitionsRendererHtml exports DSM schemas to styled HTML
- File: src/Viper/Viper_DSMDefinitionsRendererHtml.cpp
- Usage: Iterates DSM definitions, renders with HTML utilities
- web_cdbe application - Web-based commit database editor (Python Flask app)
- Files: python/web_cdbe/html_documents_renderer.py (193 lines), python/web_cdbe/html_renderer.py (49 lines)
- Usage: Interactive document browsing with Html.type(), collapsible trees, semantic styling
- Python bindings - P_Viper_Html exposes 8 methods to Python
- Files: src/P_Viper/P_Viper_Html.hpp, src/P_Viper/P_Viper_Html.cpp
- Methods: Html.dsm_definitions(), Html.value(), Html.value_pretty(), Html.type(), Html.style(), Html.body(), Html.document(), Html.documents_details()
Coupling strength: Weak unidirectional (HTML → Type/Value for rendering, no reverse dependencies)
Key Type References¶
C++ Headers (Entry Points):
- src/Viper/Viper_HtmlRenderer.hpp - Semantic utility functions (30+), CSS styling, document builders
- src/Viper/Viper_HtmlTypeRenderer.hpp - Type rendering with visitor pattern
- src/Viper/Viper_HtmlValueRenderer.hpp - Value rendering (representation/description modes)
- src/Viper/Viper_HtmlValueRendererPretty.hpp - Pretty rendering with optional type display
- src/Viper/Viper_HtmlDocumentDetailsRender.hpp - Hierarchical document rendering with composite pattern
C++ Implementations:
- src/Viper/Viper_HtmlRenderer.cpp (184 lines) - Utility functions, escape, style, document
- src/Viper/Viper_HtmlTypeRenderer.cpp (155 lines) - Type visitor pattern
- src/Viper/Viper_HtmlValueRenderer.cpp (452 lines) - Value visitor pattern (31 TypeCodes × 2 modes)
- src/Viper/Viper_HtmlValueRendererPretty.cpp (369 lines) - Pretty rendering with stringstream
- src/Viper/Viper_HtmlDocumentDetailsRender.cpp (91 lines) - Composite pattern for documents
Python Bindings:
- src/P_Viper/P_Viper_Html.hpp - Python type definition (P_Viper_Html)
- src/P_Viper/P_Viper_Html.cpp - 8 static methods exposed to Python
Python Type Hints:
- dsviper_wheel/__init__.pyi - Python type stubs for Html class (8 methods)
Real-World Examples:
- python/web_cdbe/html_documents_renderer.py (193 lines) - Full integration example with Flask
- python/web_cdbe/html_renderer.py (49 lines) - Semantic utilities clone
- src/Viper/Viper_DSMDefinitionsRendererHtml.cpp - C++ integration for DSM export
Document Metadata¶
Methodology Version: v1.3.1 (Slug-Based Deterministic Naming) Generated Date: 2025-11-14 Last Updated: 2025-11-14 Review Status: ✅ Complete Test Files Analyzed: 0 dedicated test files (visual output domain) Real-World Usage: 3 examples (web_cdbe: 193 lines, html_renderer.py: 49 lines, DSMDefinitionsRendererHtml.cpp) Golden Examples: 7 scenarios extracted C++ Files: 10 total (5 headers + 5 implementations) Python Bindings: 2 files (P_Viper_Html.hpp, P_Viper_Html.cpp)
Changelog:
- v1.0 (2025-11-14): Initial documentation following /document-domain v1.3.1
- Phase 0.5 audit: Identified 5 components, 10 C++ files, 2 bindings, no unit tests
- Phase 0.75 C++ analysis: Identified 4 design patterns (Utility Functions, Visitor, Strategy, Composite)
- Phase 1 golden scenarios: 7 extracted from web_cdbe (193 lines), Python API (Migration Guide 1.2.0), C++ patterns
- Phase 5 implementation: 6 sections completed (~900 lines)
- Emphasis: Three rendering modes (representation/description/pretty), HTML safety (XSS prevention), CSS styling
Regeneration Trigger:
- When /document-domain reaches v2.0 (methodology changes)
- When HTML domain API changes significantly (new rendering modes, breaking CSS class changes)
- When new TypeCodes added (requires updating visitor pattern in all renderers)
Appendix: Domain Statistics¶
C++ Files: 10 (5 headers + 5 implementations) - Headers: HtmlRenderer.hpp (184 impl lines), HtmlTypeRenderer.hpp (155), HtmlValueRenderer.hpp (452), HtmlValueRendererPretty.hpp (369), HtmlDocumentDetailsRender.hpp (91) - Total implementation lines: 1,251
Python Bindings: 2 files - P_Viper_Html.hpp, P_Viper_Html.cpp (8 methods exposed)
Real-World Usage: 3 examples - web_cdbe/html_documents_renderer.py (193 lines) - web_cdbe/html_renderer.py (49 lines) - Viper_DSMDefinitionsRendererHtml.cpp
Sub-domains: 5 1. Semantic Utility Functions (HtmlRenderer) 2. Type Rendering (HtmlTypeRenderer) 3. Value Rendering - Description Mode (HtmlValueRenderer) 4. Value Rendering - Pretty Mode (HtmlValueRendererPretty) 5. Document Details Rendering (HtmlDocumentDetailsRender)
Design Patterns: 4 1. Utility Functions (stateless namespace functions) 2. Visitor Pattern (switch on TypeCode, 31 renderers) 3. Strategy Pattern (three rendering modes: representation/description/pretty) 4. Composite Pattern (recursive document tree traversal)
CSS Classes: 12 semantic classes (public API)
- Color: clr_keyword, clr_viper_type, clr_user_type, clr_number, clr_string, clr_quote, clr_uuid, clr_operator, clr_comment, clr_docstr
- Layout: clr_background, clr_text
Key Characteristics: - Stateless (thread-safe, no shared state) - Fast rendering (<10ms per value) - HTML-safe (XSS prevention via escape()) - Exhaustive (covers all 31 TypeCodes) - Composable (low-level utilities + high-level renderers)
Note: This domain has no dedicated unit tests due to its visual output nature. Testing is performed manually (browser inspection) and through real-world integration (web_cdbe application).