Converts Raxol.Core buffers to HTML for Phoenix LiveView rendering.
This module provides efficient buffer-to-HTML conversion with performance optimizations for 60fps rendering (< 16ms per frame).
Features
- Virtual DOM-style diffing (only update changed cells)
- Character and style caching for performance
- CSS class generation for theming
- Inline style support for custom colors
- Accessibility features (ARIA labels)
Performance
Target: < 16ms per frame for 60fps Actual: ~2-5ms for typical 80x24 buffers
Examples
# Basic conversion
buffer = Raxol.Core.Buffer.create_blank_buffer(80, 24)
buffer = Raxol.Core.Buffer.write_at(buffer, 5, 3, "Hello, World!")
html = Raxol.LiveView.TerminalBridge.buffer_to_html(buffer)
# With theme
html = Raxol.LiveView.TerminalBridge.buffer_to_html(buffer, theme: :nord)
# With custom CSS classes
html = Raxol.LiveView.TerminalBridge.buffer_to_html(buffer,
css_prefix: "terminal",
use_inline_styles: false
)Integration with LiveView
defmodule MyAppWeb.TerminalLive do
use MyAppWeb, :live_view
alias Raxol.LiveView.TerminalBridge
def mount(_params, _session, socket) do
buffer = Raxol.Core.Buffer.create_blank_buffer(80, 24)
{:ok, assign(socket, buffer: buffer)}
end
def render(assigns) do
~H"""
<div class="terminal-container">
<%= raw(TerminalBridge.buffer_to_html(@buffer, theme: :dracula)) %>
</div>
"""
end
end
Summary
Functions
Generates CSS transition rules from animation hints on positioned elements.
Converts a buffer to HTML with diff highlighting (for debugging).
Converts a buffer to HTML string.
Converts a style map to CSS classes.
Converts a style map to inline CSS styles.
Types
@type aria_mode() :: :log | :application
@type html_opts() :: [ theme: theme(), css_prefix: String.t(), use_inline_styles: boolean(), show_cursor: boolean(), cursor_position: {non_neg_integer(), non_neg_integer()} | nil, cursor_style: :block | :underline | :bar, aria_mode: aria_mode(), a11y_map: %{optional(String.t()) => map()} ]
@type theme() ::
:nord
| :dracula
| :solarized_dark
| :solarized_light
| :monokai
| :synthwave84
| :gruvbox_dark
| :one_dark
| :tokyo_night
| :catppuccin
| :default
Functions
Generates CSS transition rules from animation hints on positioned elements.
Takes a list of positioned element maps (output of LayoutEngine) and
extracts animation hints from elements that have an :id field. Returns
a <style> block with CSS transition rules targeting [data-raxol-id]
selectors, plus a prefers-reduced-motion media query.
Returns an empty string if no elements carry animation hints.
Examples
elements = [
%{id: "panel", type: :box, animation_hints: [
%{property: :opacity, duration_ms: 300, easing: :ease_out_cubic, delay_ms: 0}
]}
]
css = animation_css(elements)
# => "<style>[data-raxol-id=\"panel\"] { transition: opacity 300ms cubic-bezier(...) 0ms; }\n..."
Converts a buffer to HTML with diff highlighting (for debugging).
Useful for visualizing which cells changed between frames.
Examples
old_buffer = Raxol.Core.Buffer.create_blank_buffer(80, 24)
new_buffer = Raxol.Core.Buffer.write_at(old_buffer, 5, 3, "Changed")
html = buffer_diff_to_html(old_buffer, new_buffer)
# Changed cells will have "raxol-diff-changed" class
Converts a buffer to HTML string.
Options
:theme- Color theme to use (default: :default):css_prefix- CSS class prefix (default: "raxol"):use_inline_styles- Use inline styles instead of classes (default: false):show_cursor- Show cursor indicator (default: false):cursor_position- Cursor position {x, y} (default: nil):cursor_style- Cursor style (default: :block):aria_mode- Coarse container semantics (default::log).:logwraps the terminal in<pre role="log" aria-live="polite">so screen readers announce output as it changes.:applicationemits<pre role="application">with no live region, so per-element ARIA and a dedicated announcement region drive announcements instead of a whole-screen re-read.:a11y_map-id -> accessibility_nodemap (fromRaxol.Core.Accessibility.Projection.by_id/1). Spans whosedata-raxol-idmatches an entry get per-element ARIA (role/aria-label/aria-disabled/aria-checked/aria-selected/aria-expanded/aria-required).
Examples
buffer = Raxol.Core.Buffer.create_blank_buffer(80, 24)
html = buffer_to_html(buffer)
# => "<pre class=\"raxol-terminal\">...</pre>"
html = buffer_to_html(buffer, theme: :nord, show_cursor: true, cursor_position: {5, 3})
# => "<pre class=\"raxol-terminal raxol-theme-nord\">...</pre>"
Converts a style map to CSS classes.
Examples
iex> style = %{bold: true, fg_color: :blue}
iex> style_to_classes(style, "raxol")
"raxol-bold raxol-fg-blue"
Converts a style map to inline CSS styles.
Examples
iex> style = %{bold: true, fg_color: {255, 0, 0}}
iex> style_to_inline(style)
"font-weight: bold; color: rgb(255, 0, 0);"