HTML Rendering ============== Classes for rendering Viper data as HTML in web and desktop applications. **When to use**: Use ``DocumentNode`` to traverse nested Viper documents with full metadata. Use ``Html`` to generate styled HTML output for Flask web apps or Qt desktop apps (via ``QTextEdit.setHtml()``). Quick Start ----------- .. code-block:: python from flask import Flask, render_template from dsviper import CommitDatabase, DocumentNode, Html, ValueKey app = Flask(__name__) @app.get("/document/") def document_view(instance_id): db = CommitDatabase.open("model.cdb") db.definitions().inject() # Create key and get document accessor key = ValueKey.create(MYAPP_C_Entity, str(instance_id)) attachment_getting = db.state(db.last_commit_id()).attachment_getting() # Build document tree for all attachments nodes = DocumentNode.create_documents(key, attachment_getting) # Render as collapsible HTML details content = Html.documents_details(nodes, show_type=True) return render_template("document.html", content=content) DocumentNode Tree ----------------- ``DocumentNode`` provides a recursive tree structure for navigating Viper documents: .. code-block:: python from dsviper import DocumentNode # Create tree from a key nodes = DocumentNode.create_documents(key, attachment_getting) for node in nodes: print(f"{node.string_component()}: {node.string_value()}") # Type introspection for conditional rendering if node.is_editable(): if node.is_boolean(): render_checkbox(node) elif node.is_string(): render_text_input(node) elif node.is_enumeration(): render_select(node) # Recursive traversal if node.is_expandable(): for child in node.children(): render_node(child) Custom HTML Rendering --------------------- Build custom renderers using ``DocumentNode`` metadata: .. code-block:: python from dsviper import DocumentNode, ValueKey, ValueEnumeration def render_node(node: DocumentNode, level: int = 0) -> str: indent = " " * level html = "" if node.is_expandable(): # Collapsible container html += f'{indent}
' html += f'{node.string_component()}' for child in node.children(): html += render_node(child, level + 1) html += f'{indent}
' else: # Leaf value html += f'{indent}
{node.string_component()} = ' if node.is_editable(): # Editable field with form input html += f'' else: html += node.string_value() html += '
' return html Node metadata available: .. list-table:: :header-rows: 1 :widths: 30 70 * - Method - Description * - ``path()`` - Path to this node (for ``update()`` mutations) * - ``key()`` - Document key (for identifying the document) * - ``attachment()`` - Attachment containing this document * - ``uuid()`` - Unique ID for this node (useful for HTML element IDs) * - ``is_editable()`` - Whether this field can be modified * - ``is_expandable()`` - Whether this node has children * - ``children()`` - Child nodes for containers/structures Html Helpers ------------ The ``Html`` class provides ready-to-use rendering: .. code-block:: python from dsviper import Html, DocumentNode # Render documents as collapsible details nodes = DocumentNode.create_documents(key, attachment_getting) content = Html.documents_details(nodes, show_type=True) # Render a single value with syntax highlighting html = Html.value(my_structure) # Pretty-print with indentation html = Html.value_pretty(my_structure, show_type=True) # Render DSM schema as HTML html = Html.dsm_definitions(dsm_defs, show_documentation=True) # Build complete HTML document page = Html.document( title="My Document", style=Html.style(), body=Html.body(content) ) Qt Desktop Integration ---------------------- The same ``Html`` helpers work in Qt/PySide6 applications via ``QTextEdit``: .. code-block:: python from PySide6.QtWidgets import QTextEdit from dsviper import Html, CommitDatabase # In a Qt dialog or widget class InspectDialog: def __init__(self): self.text_edit = QTextEdit() def show_definitions(self, db: CommitDatabase): # Get DSM definitions with HTML formatting dsm_defs = db.definitions().to_dsm_definitions() content = Html.dsm_definitions(dsm_defs, show_documentation=True) # Build complete HTML document style = Html.style() body = Html.body(content) document = Html.document("DSM Definitions", style, body) # Display in QTextEdit self.text_edit.setHtml(document) def show_value(self, value): content = Html.value(value, use_description=True) document = Html.document("Value", Html.style(), Html.body(content)) self.text_edit.setHtml(document) This pattern is used by ``cdbe.py`` (CDB Editor) and ``dbe.py`` (Database Editor) to display definitions and values with syntax highlighting. Choosing the Right Approach --------------------------- .. list-table:: :header-rows: 1 :widths: 35 25 40 * - Use Case - API - Note * - Quick document display - ``Html.documents_details()`` - Ready-to-use collapsible view * - Custom form builder - ``DocumentNode`` traversal - Full control over rendering * - Value debugging - ``Html.value_pretty()`` - Syntax-highlighted output * - Schema documentation - ``Html.dsm_definitions()`` - Display DSM structure * - Qt desktop display - ``Html.document()`` + ``setHtml()`` - Works with QTextEdit DocumentNode ------------ .. autosummary:: :toctree: generated/ :nosignatures: dsviper.DocumentNode Html ---- .. autosummary:: :toctree: generated/ :nosignatures: dsviper.Html