Skip to content

memrye/axie

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

51 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

axie (An XML Interpreter Engine)

A fast, extensible XML-to-ASCII rendering engine that converts XML/HTML-like markup into beautifully formatted terminal output. Built in Rust for performance and memory efficiency.

Overview

This engine allows you to describe terminal illustrations using familiar XML syntax, offloading the complex layout and rendering logic to the engine. It's designed to help AI agents and developers render formatted text diagrams, documents, and UI blockouts in their responses.

Documentation

For complete element and attribute reference, see REFERENCE.md.

Architecture

XML Input → Parser → DOM Tree → Layout Engine → Rasterizer → ASCII Output

Core Components

  1. DOM Module (src/dom/): AST structures for elements and text nodes
  2. Parser (src/parser/): XML-like syntax parser with attribute support
  3. Layout Engine (src/layout/): Calculates positions and dimensions using box model
  4. Rasterizer (src/render/): Converts layout tree to 2D character buffer

Usage

CLI

axie '<div width="40"><h1>Hello World</h1><div width="30"><span>Status: </span><span>ONLINE</span></div></div>'

Output:

┌────────────────────────────────────────┐
│HELLO WORLD                             │
│────────────────────────────────────────│
│┌────────────────────────────┐          │
││Status:ONLINE               │          │
│└────────────────────────────┘          │
└────────────────────────────────────────┘

Input Methods

The renderer supports three ways to provide XML input:

1. Direct XML String (for quick testing)

axie '<div width="40"><h1>Hello</h1></div>'

2. File Input (for complex documents)

# Using -f or --file flag
axie -f dashboard.xml
axie --file report.xml 100 --backend=truecolor

3. Stdin Pipe (for integration with other tools)

# Pipe from echo
echo '<div width="30">Hello World</div>' | axie

# Pipe from cat
cat template.xml | axie 80 --backend=plain

# Use with other tools
python generate_dashboard.py | axie | less

Library API

axie can be used as a Rust library for programmatic rendering:

use axie::{render, RenderOptions, BackendType};

fn main() {
    let xml = r#"<div width="40"><h1>Hello World</h1></div>"#;
    
    let options = RenderOptions {
        width: Some(80),
        backend: BackendType::Plain,
        collect_warnings: true,
        track_clickable_areas: false,
    };
    
    match render(xml, &options) {
        Ok(output) => {
            println!("{}", output.rendered);
            println!("Dimensions: {}x{}", 
                output.dimensions.width, 
                output.dimensions.height
            );
        }
        Err(e) => eprintln!("Error: {}", e),
    }
}

RenderOptions

  • width: Target width in characters (None = auto-detect terminal width)
  • backend: Color backend - Auto, TrueColor, Color256, or Plain
  • collect_warnings: Enable warning collection during rendering
  • track_clickable_areas: Track anchor element positions for interactive use

RenderOutput

The render function returns a RenderOutput struct containing:

  • rendered: The formatted terminal output as a string
  • dimensions: Width and height of the rendered output
  • warnings: Any warnings collected during rendering (if enabled)
  • clickable_areas: Positions and URLs of anchor elements (if tracking enabled)

See examples/basic.rs for comprehensive usage examples.

JSON Output Mode

The --json flag enables machine-readable JSON output for CI/CD integration, programmatic processing, and automation workflows. This mode returns structured data including the rendered output, dimensions, warnings, and clickable areas.

axie '<div>Hello</div>' --json

Example output:

{
  "success": true,
  "data": {
    "rendered": "┌───────┐\n│Hello  │\n└───────┘",
    "dimensions": {
      "width": 9,
      "height": 3
    },
    "warnings": [
      {
        "severity": "warning",
        "message": "Content area has zero width due to excessive padding"
      }
    ],
    "clickable_areas": [
      {
        "x": 1,
        "y": 1,
        "width": 5,
        "height": 1,
        "href": "https://example.com",
        "text": "Hello"
      }
    ]
  }
}

Response Fields

Success response:

  • success (boolean): true when rendering succeeds
  • data.rendered (string): The formatted terminal output
  • data.dimensions.width (number): Output width in characters
  • data.dimensions.height (number): Output height in characters
  • data.warnings (array): Warnings collected during rendering, each with:
    • severity: "error", "warning", or "info"
    • message: Human-readable description
  • data.clickable_areas (array): Anchor element positions, each with:
    • x, y: Position coordinates
    • width, height: Area dimensions
    • href: Target URL
    • text: Link text content

Error response:

  • success (boolean): false when rendering fails
  • error.type (string): Error category (e.g., "parse", "render")
  • error.message (string): Human-readable error description
  • error.fatal (boolean): true if error prevents rendering

Notes

  • --json automatically enables warning collection and clickable area tracking
  • Output is always valid JSON, suitable for piping to tools like jq
  • Use --json for headless automation where parsing text output is difficult

Integration Example

Parse output with jq for shell scripting:

# Extract just the rendered output
axie '<div>Hello</div>' --json | jq -r '.data.rendered'

# Check for warnings in CI pipeline
axie '<div>Test</div>' --json | jq '.data.warnings | length'

# Extract clickable link URLs
axie '<div><a href="https://example.com">Link</a></div>' --json | jq '.data.clickable_areas[].href'

Supported Elements

<div> - Block container

  • Renders with borders on all sides
  • Stacks children vertically
  • Supports inline flow for text/span children
  • Use width attribute for explicit width (in character units)
<div width="50">Content here</div>

<span> - Inline container

  • Flows horizontally within parent
  • No borders or padding
  • Useful for styling text segments
<span>Inline text</span>

Headings (<h1> through <h6>)

Six levels of headings with progressive visual weight:

┌─────────┬───────────┬───────────┬───────────┐
│ Element │   Case    │ Underline │   Usage   │
├─────────┼───────────┼───────────┼───────────┤
│h1       │UPPERCASE  │══         │Main title │
│         │           │double     │           │
├─────────┼───────────┼───────────┼───────────┤
│h2       │UPPERCASE  │──         │Major      │
│         │           │single     │section    │
├─────────┼───────────┼───────────┼───────────┤
│h3       │normal     │──         │Subsection │
│         │           │single     │           │
├─────────┼───────────┼───────────┼───────────┤
│h4       │UPPERCASE  │none       │Minor      │
│         │           │           │section    │
├─────────┼───────────┼───────────┼───────────┤
│h5       │normal     │none       │Subheading │
├─────────┼───────────┼───────────┼───────────┤
│h6       │normal     │none       │Small      │
└─────────┴───────────┴───────────┴───────────┘

Features:

  • Block-level elements
  • Automatic text transformation (uppercase for h1, h2, h4)
  • Automatic underline (h1 double, h2/h3 single)
  • Use width attribute for explicit width
<h1>Main Title</h1>
<h2>Section Header</h2>
<h3>Subsection</h3>
<h4>Minor Section</h4>
<h5>Subheading</h5>
<h6>Small Heading</h6>

<table> - Tables

HTML-like tables with rows (<tr>), data cells (<td>), and header cells (<th>):

<table>
  <tr><th>Name</th><th>Status</th></tr>
  <tr><td>Server A</td><td>Online</td></tr>
  <tr><td>Server B</td><td>Offline</td></tr>
</table>

Features:

  • Automatic column width calculation
  • Header cells (<th>) centered by default
  • Border-collapse support via CSS border-collapse: collapse
  • Support for nested content (lists, text) within cells

CSS Properties:

  • border-collapse: collapse/separate - Controls whether cell borders are shared

<ul> / <ol> - Lists

Create bulleted and numbered lists:

<!-- Unordered list -->
<ul>
  <li>First item</li>
  <li>Second item with nested list
    <ul>
      <li>Nested item</li>
    </ul>
  </li>
</ul>

<!-- Ordered list -->
<ol>
  <li>Step one</li>
  <li>Step two</li>
</ol>

Features:

  • Automatic indentation based on nesting level
  • Multiple list styles (disc, circle, square, decimal, alpha, roman)
  • Ordered lists with custom start numbers (start attribute)
  • Deep nesting supported (3+ levels)
  • Tables can be nested inside list items

CSS Properties:

  • list-style-type: disc/circle/square/decimal/lower-alpha/upper-alpha/lower-roman/upper-roman/none

<pre> - Preformatted text

  • Preserves all whitespace exactly as written (spaces, tabs, newlines)
  • No word wrapping - content displayed exactly as-is
  • Perfect for code blocks and ASCII art
  • Supports borders, padding, and background colors
<pre>
function example() {
    return "preserved  whitespace";
}
</pre>

<p> - Paragraph

  • Block-level text container with no borders by default
  • Automatic top and bottom margins (1 row each) for visual separation
  • Supports inline content (text, spans, anchors)
  • Text wraps at word boundaries
<p>This is a paragraph with some text content.</p>
<p>Another paragraph with <span>styled text</span> inside.</p>

Features:

  • Default margins (top=1, bottom=1) create space between paragraphs
  • Margins can be overridden with explicit margin-top or margin-bottom styles
  • No borders by default (unlike <div>)
  • Full support for colors, padding, and text alignment

Text Content

  • Automatically collapsed (multiple spaces become single space)
  • Wraps at word boundaries
  • Long words break if necessary

Styling with style Attribute

The style attribute supports CSS-like syntax for padding, margins, and width:

Padding:

<!-- Uniform padding on all sides -->
<div style="padding: 2">Content</div>

<!-- Vertical and horizontal -->
<div style="padding: 1 2">Content</div>

<!-- Individual sides -->
<div style="padding-top: 1; padding-right: 2">Content</div>

Margins:

<!-- Space between elements -->
<div>First</div>
<div style="margin-top: 2">Second (with 2 row gap)</div>

Border-Box Model: The total width includes content + padding + borders. The specified width is never exceeded:

<!-- Content area will be: 30 - 4 padding - 2 borders = 24 chars -->
<div width="30" style="padding: 2">Content</div>

Width and Height Constraints

Control element dimensions with minimum and maximum constraints:

<!-- Minimum width - element will be at least this wide -->
<div style="min-width: 40">Content</div>

<!-- Maximum width - element will not exceed this width -->
<div style="max-width: 80">Long content that needs constraining</div>

<!-- Combined constraints -->
<div style="min-width: 40; max-width: 100">Responsive content</div>

<!-- Height constraints work similarly -->
<div style="min-height: 5; max-height: 20">Content with height limits</div>

Percentage Widths

Use percentages for fluid, responsive layouts. Percentages are calculated relative to the parent container's available width:

<!-- Half of parent width -->
<div style="width: 50%">Half width</div>

<!-- Quarter of parent width -->
<div style="width: 25%">Quarter width</div>

<!-- Full width of container -->
<div style="width: 100%">Full width</div>

For the root element, percentages are calculated against the terminal width (if available) or otherwise a default of 80 characters.

Overflow Handling

Control how content behaves when it exceeds container boundaries:

<!-- Wrap (default) - content wraps to next line -->
<div style="width: 20; overflow: wrap">Long text wraps automatically</div>

<!-- Clip - content is truncated at boundary -->
<div style="width: 20; overflow: clip">Long text is clipped</div>

<!-- Scroll - content is clipped but marked for scrolling (future) -->
<div style="width: 20; overflow: scroll">Content marked for scroll</div>

Overflow modes affect:

  • Text content: How text is wrapped or clipped
  • Child elements: How nested content is handled

Color Support: Full ANSI color support with CSS-like syntax. Colors can be specified as named colors, hex values, or RGB:

<!-- Text color -->
<span style="color: red">Red text</span>

<!-- Background color -->
<div style="background-color: blue">Blue background</div>

<!-- Border color -->
<div style="border-color: green">Green borders</div>

<!-- Hex colors -->
<span style="color: #ff5733">Custom hex color</span>

<!-- RGB colors -->
<span style="color: rgb(255, 128, 0)">RGB orange</span>

<!-- Combined styling -->
<div style="color: white; background-color: navy; border-color: cyan">  Fully styled box
</div>

Colors inherit from parent elements to children, allowing for nested color schemes.

Border Styles: Control the appearance of borders with CSS-like border-style property:

<!-- Standard styles -->
<div style="border-style: single">Single line (default)</div>
<div style="border-style: double">Double line</div>
<div style="border-style: thick">Thick/heavy lines</div>
<div style="border-style: ascii">ASCII-only (+--+|)</div>
<div style="border-style: dotted">Dotted (· · ·)</div>
<div style="border-style: dashed">Dashed (┄ ┄ ┄)</div>

<!-- Custom bunting with repeating pattern (no quotes needed) -->
<div style="border-style: bunting(~)">Wavy border</div>
<div style="border-style: bunting(=*)">Pattern: =*=*=*</div>
<div style="border-style: bunting(xo)">Pattern: xoxoxo</div>

<!-- Combined with colors -->
<div style="border-style: double; border-color: cyan; color: white; background-color: navy">
  Styled box
</div>

Text Alignment: Control text alignment within containers using CSS-like text-align property:

<!-- Left alignment (default) -->
<div style="text-align: left">Left aligned text</div>

<!-- Center alignment -->
<div style="text-align: center">Center aligned text</div>

<!-- Right alignment -->
<div style="text-align: right">Right aligned text</div>

<!-- Combined with other styles -->
<div style="text-align: center; color: white; background-color: navy">
  Centered styled text
</div>

Text alignment inherits from parent elements. Nested containers automatically align their text to match their parent unless explicitly overridden.

Error Handling: Comprehensive fail-forward error handling system that produces the best possible output even when encountering errors:

<!-- Parser continues despite malformed XML -->
<div width="40"><span>Missing closing tag<div>Still renders</div></span></div>

<!-- Unknown CSS properties generate warnings but don't stop rendering -->
<div style="unknown-property: value; color: red">Valid styles applied</div>

The system distinguishes between:

  • Fatal errors: Only unclosed root tags at EOF (cannot determine document boundaries)
  • Recoverable errors: Malformed markup, unknown styles, invalid values (rendering continues)

CLI flags control verbosity:

# Silent mode - no warnings, zero overhead
axie '<malformed>' --quiet

# Show warnings (default)
axie '<invalid>' --warnings

# Verbose mode - detailed diagnostics
axie '<input>' --verbose

Backend Selection: The renderer automatically detects terminal color capabilities, but you can override this:

# Auto-detect (default)
axie '<div style="color: red">Text</div>'

# Force truecolor (24-bit RGB)
axie '<div style="color: #ff5733">Text</div>' --backend=truecolor

# Force 256-color mode
axie '<div style="color: red">Text</div>' --backend=256

# Disable colors (plain ASCII)
axie '<div style="color: red">Text</div>' --backend=plain

Examples

Server Dashboard

axie '<div width="60"><h1>Server Dashboard</h1><div width="50"><span>CPU: </span><span>45% | </span><span>RAM: </span><span>78% | </span><span>Disk: </span><span>23%</span></div><div width="50">System status and metrics display.</div></div>'

Output:

┌──────────────────────────────────────────────────────────┐
│SERVER DASHBOARD                                          │
│──────────────────────────────────────────────────────────│
│┌────────────────────────────────────────────────┐        │
││CPU:45% |RAM:78% |Disk:23%                      │        │
│└────────────────────────────────────────────────┘        │
│┌────────────────────────────────────────────────┐        │
││System status and metrics display.              │        │
│└────────────────────────────────────────────────┘        │
└──────────────────────────────────────────────────────────┘

Table Example

axie '<div width="40"><table width="40" style="border-collapse: collapse"><tr><th>Name</th><th>Value</th></tr><tr><td>Item A</td><td>100</td></tr><tr><td>Item B</td><td>200</td></tr></table></div>'

Output:

┌──────────────────────────────────────┐
│┌──────────────────┬─────────────────┐│
││       Name       │      Value      ││
│├──────────────────┼─────────────────┤│
││Item A            │100              ││
│├──────────────────┼─────────────────┤│
││Item B            │200              ││
│└──────────────────┴─────────────────┘│
└──────────────────────────────────────┘

List Example

axie '<div width="40"><ul><li>First item</li><li>Second item</li><li>Third item</li></ul></div>'

Output:

┌──────────────────────────────────────┐
│    • First item                      │
│    • Second item                     │
│    • Third item                      │
└──────────────────────────────────────┘

Colored Server Dashboard

axie '<div width="60" style="border-color: cyan"><h1>Server Dashboard</h1><div width="50" style="background-color: navy; color: white"><span style="color: green">● ONLINE</span> | CPU: 45% | RAM: 78%</div></div>' --backend=truecolor

Building

# Development build
cargo build

# Release build (optimized)
cargo build --release

# Run tests
cargo test

# Build library only
cargo build --lib

# Run example
cargo run --example basic

Design Philosophy

  • Performance: Zero-cost abstractions, single-pass layout, buffer reuse
  • Extensibility: Trait-based element system for easy customization
  • Simplicity: Minimal API, explicit over implicit
  • WYTIWYG: What You Type Is What You Get - clear visibility into layout

License

MIT

About

Render Unicode/ASCII text UI with XML/HTML-like markup

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors