Rich Content Components

Render markdown, images, diagrams, and pixel graphics in the terminal. Browse the filesystem with keyboard navigation.

1. Markdown

Render markdown files in the terminal. Headings, lists, code blocks, tables, links, and images.

melker --stdout examples/content/markdown.melker -- sample.md
 Welcome to Melker                                         
                                                           
 Melker Engine renders rich terminal UIs from an           
 HTML-inspired document model.                             
                                                           
 Features                                                  
                                                           
    Tables, charts, and heatmaps                          
    Markdown with syntax highlighting                     
    Mermaid diagrams                                      
    File browser with fuzzy search                        
                                                           
 Quick Start                                               
                                                           
                                                     bash  
   melker hello.melker                                     
                                                           
                                                           
  Melker apps run in any ANSI terminal.                   
                                                          

View source

Load a file with the src prop, or pass inline content with text. The onLink handler fires when a user clicks a link, letting you navigate between documents or open URLs in the browser.

markdown.melker
<markdown id="md" src="README.md"
    onLink="$app.handleLink(event)"
    style="text-wrap: wrap" />

<script type="typescript">
    export function handleLink(event: { url: string }) {
        if (event.url.startsWith('http')) {
            $melker.openBrowser(event.url);
            return;
        }
        // Navigate to another .md file within the app
        const md = $melker.getElementById('md');
        md.props.src = event.url;
    }
</script>

Markdown supports GFM extensions (tables, strikethrough), syntax-highlighted code blocks, blockquotes, and images. Images referenced in markdown (![alt](path.png)) are rendered inline using the same pixel graphics as the <img> component. Code blocks with ```mermaid are rendered as interactive diagrams (see next section).

Reference: Component reference

2. Mermaid diagrams

Flowcharts, sequence diagrams, and class diagrams rendered with Unicode box drawing.

melker --stdout examples/content/mermaid.melker
 Git Workflow

  ┌───── Local ─────┐     ┌──── Remote ─────┐
                                         
   ┌─────────────┐       ┌─────────────┐ 
    Working Dir         Remote Repo  
   └─────────────┘       └─────────────┘ 
                                       
        │git add        └────────────────┘
                                
                                
   ┌─────────┐                   
    Staging                    
   └─────────┘      git pull     
                                
          │git commit             
                                
                                
   ┌────────────┐                
    Local Repo ◀────────────────┘
   └────────────┘  
                   
  └─────────────────┘

View source

The <graph> component parses Mermaid syntax and renders it using Unicode box-drawing characters. Place the Mermaid definition directly as the element's text content. Melker can also render .mmd files directly from the command line: melker diagram.mmd.

mermaid.melker
<graph style="overflow: scroll; flex: 1">
flowchart LR
    subgraph Local
        WD[Working Dir] -->|git add| SA[Staging]
        SA -->|git commit| LR[Local Repo]
    end
    subgraph Remote
        RR[Remote Repo]
    end
    LR -->|git push| RR
    RR -->|git pull| LR
</graph>

Mermaid blocks inside markdown code fences (```mermaid) are also rendered as diagrams automatically. Nodes in the diagram are focusable and keyboard-navigable.

In a markdown file
```mermaid
sequenceDiagram
    Client->>Server: GET /api/data
    Server->>DB: Query
    DB-->>Server: Results
    Server-->>Client: JSON response
```

Reference: Mermaid support · Graph architecture

3. Images

Display PNG, JPEG, GIF, and WebP images using Unicode sextant characters (2x3 pixels per cell).

melker --stdout examples/content/img.melker
Image Component

                       Format: PNG
   🬞🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬏    Mode: sextant (2x3 pixels/cell)
 🬞🬩🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬓  Fit: contain (preserves aspect)
 🬯🬰🬰🬰🬞🬭🬭🬏🬭🬰🬰🬰🬞🬭🬭🬏🬮🬰🬰🬮
 🬋🬋🬋🬋🬋🬋🬺🬱🬚🬹🬞🬵🬋🬋🬋🬋🬋🬋
 🬰🬰🬰🬰🬰🬕🬊🬡🬲🬭🬰🬝🬨🬰🬐🬰🬰🬰
 🬋🬋🬋🬋🬋🬃🬌🬉🬬🬋🬄🬎🬋🬃🬋🬋🬋
 🬂🬂🬡🬁🬒🬂🬂🬂🬂🬨🬂🬐🬕🬂🬂
 🬬🬍🬍🬬🬉🬎🬎🬄🬎🬎🬎🬎🬉🬉🬎🬄🬄🬌🬛🬛
 🬁🬬🬬🬎🬎🬎🬎🬎🬎🬎🬎🬎🬎🬊🬎🬆🬆🬆🬎🬆
  🬁🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬆🬂🬀

View source

The <img> component renders images using Unicode block characters. The default sextant mode gives 2x3 pixels per cell, and quadrant mode gives 2x2 pixels per cell with near-universal font support. Supports PNG, JPEG, WebP, and animated GIFs. GIF animation plays automatically and can be disabled with --no-animate-gif. A separate <video> component exists for MP4, RTSP streams, and other video formats (requires FFmpeg).

img.melker
<!-- Fixed size with aspect-correct scaling -->
<img src="logo.png" width="20" height="10"
    style="object-fit: contain" />

<!-- Responsive: fills container width -->
<img src="photo.jpg" width="100%" height="20" />

<!-- Animated GIF -->
<img src="animation.gif" width="40" height="20" />

<!-- Load and error callbacks -->
<img src="image.png" width="30" height="15"
    onLoad="$app.loaded()"
    onError="$app.failed()" />

The object-fit style controls scaling: "contain" preserves aspect ratio, "fill" stretches to fill (default), "cover" fills and crops. Use setSrc(url) to change the image at runtime.

Reference: Component reference

4. Canvas

Pixel-level drawing with shapes, lines, text labels, and SVG paths.

melker --stdout examples/content/canvas.melker
Canvas Drawing

  🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭  🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬏 🬞🬭🬭🬭🬭🬭🬭🬭
  ████40%████████  ███30%██████▌ ▐███20%
  🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂 🬞🬙🬎🬆🬂🬂🬂🬂🬎🬎🬰🬂🬂🬀 🬁🬂🬂🬂🬂🬂🬂🬂
                🬞🬋🬀          🬈🬢
               🬞🬄              🬣
               🬔               🬁🬓
                               
               🬉🬏              🬘
                🬈🬭           🬞🬖🬀
 🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬌🬩🬹🬚🬋🬋🬋🬋🬹🬹🬋🬌🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋
                     🬁🬂🬂🬂🬂

View source

The onPaint handler provides a canvas object with drawing methods. Use fillRect, drawLine, drawCircleCorrected, and drawText for basic shapes. SVG path strings are also supported for curves and complex shapes.

canvas.melker
<canvas id="c" width="40" height="12" gfxMode="sextant"
    onPaint="$app.draw(event.canvas)" />

<script type="typescript">
    export function draw(canvas: any) {
        canvas.clear();
        canvas.setColor('#3b82f6');
        canvas.fillRect(2, 2, 30, 5);
        canvas.setColor('#ffffff');
        canvas.drawText(10, 4, 'Label');
        canvas.setColor('#6366f1');
        canvas.drawCircleCorrected(45, 18, 12);
    }
</script>

Canvas also supports per-pixel shaders via the onShader prop for animated effects (requires "shader": true in the policy), named SVG overlay layers via setSvgOverlay(), and tooltips via onTooltip. The <img> component extends canvas, so all canvas methods are available on images too.

Reference: Component reference

5. Segment display

LCD/LED-style digits and pixel font text using Unicode characters.

melker --stdout examples/content/segment.melker
 7-Segment Display

         ━━━━            ━━━━     ━━━━   ━━━━  
      ┃      ┃ ● ┃    ┃ ┃      ●      ┃ ┃    ┃ 
         ━━━━     ━━━━   ━━━━     ━━━━         
      ┃ ┃      ●      ┃      ┃ ●      ┃ ┃    ┃ 
         ━━━━            ━━━━     ━━━━   ━━━━  

 Pixel Font

 █  █  ████  █     █      ██   
 █  █  █     █     █     █  █  
 ████  ███   █     █     █  █  
 █  █  █     █     █     █  █  
 █  █  █     █     █     █  █  
 █  █  ████  ████  ████   ██   

View source

Four renderers are available. The box-drawing renderer (default) draws clean 7-segment digits with thin lines. rounded adds rounded corners. geometric uses chunky block characters for an LCD look. The pixel renderer uses bitmap font glyphs and supports the full ASCII character set, including accented characters.

segment-display.melker
<!-- 7-segment clock -->
<segment-display value="12:45:30"
    style="height: 5; color: green" />

<!-- Pixel font with custom characters -->
<segment-display value="HELLO" renderer="pixel"
    style="height: 7; color: cyan" />

<!-- LCD effect with visible off-segments -->
<segment-display value="88:88"
    style="color: #00ff00; off-color: #003300" />

<!-- Scrolling marquee -->
<segment-display value="HELLO WORLD"
    scroll="true" scrollSpeed="24"
    style="width: 50" />

Height can be 5 or 7 rows. The pixel renderer uses 3x5 glyphs at height 5 and 5x7 glyphs at height 7. Set off-color to make inactive segments visible (classic LCD panel look). Use pixel-char and off-pixel-char styles to change the fill characters.

Reference: Component reference

6. File browser

A filesystem navigator with fuzzy filtering, keyboard navigation, and single or multiple selection.

melker --stdout examples/content/file-browser.melker
  ┌──────────────────────────────────────────────────────┐
                        Open File                       
  ├──────────────────────────────────────────────────────┤
  ┌────────────────────────────────────────────────────┐
   Path: /home/wistrand/melker                        
   Filter: type to filter...                          
  ┌──────────────────────────────────────────────────┐
   [^] ..                                           
   [D] agent_docs/                                  
   [D] apps/                                        
  └──────────────────────────────────────────────────┘
                                  [ Cancel ] [ Open ] 
  └────────────────────────────────────────────────────┘
  └──────────────────────────────────────────────────────┘

View source

The file browser is typically placed inside a <dialog>. It shows a breadcrumb path, a filter input, a scrollable file list, and action buttons. The onChange handler fires with the selected file path. Requires "read" permission in the policy.

file-browser.melker
<policy>{ "permissions": { "read": ["*"] } }</policy>

<dialog id="dlg" title="Open File" open="false"
    modal="true" width="60" height="18">
    <file-browser id="fb"
        selectionMode="single"
        selectType="file"
        onChange="$app.pick(event)"
        onCancel="$app.closeDialog()"
        maxVisible="10" />
</dialog>

<script type="typescript">
    export function openDialog() {
        $melker.getElementById('dlg').props.open = true;
    }

    export function pick(event: { path: string }) {
        $melker.getElementById('dlg').props.open = false;
        $melker.getElementById('result').setValue(event.path);
    }
</script>

Keyboard: arrows to navigate, Enter to open directory or select file, Backspace to go up, Escape to cancel, any character to start filtering. Space toggles selection in multiple mode.

Reference: File browser architecture

7. Markdown props

Configuration options for the markdown component.

Markdown props
<!-- Load from file -->
<markdown src="docs/README.md" />

<!-- Inline content -->
<markdown text="# Hello\n\nThis is **bold**." />

<!-- GFM tables, text wrapping, link handler -->
<markdown src="file.md"
    enableGfm="true"
    style="text-wrap: wrap"
    onLink="$app.handleLink(event)" />

<!-- Light theme for code blocks -->
<markdown src="file.md" codeTheme="light" />

The src prop loads from a file path or URL. Use text for inline markdown. enableGfm (default true) enables GitHub Flavored Markdown extensions like tables and strikethrough. The onLink event provides event.url and optional event.title.

Change the source at runtime by updating the prop:

Navigate between documents
const md = $melker.getElementById('md');
md.props.src = 'other-file.md';

Reference: Component reference

8. Diagram types

Three Mermaid diagram types are supported.

Flowchart
<graph>
flowchart TD
    A[Input] --> B{Valid?}
    B -->|Yes| C[Process]
    B -->|No| D[Error]
    D --> A
</graph>
Sequence diagram
<graph>
sequenceDiagram
    Client->>Server: Request
    Server->>DB: Query
    DB-->>Server: Results
    Server-->>Client: Response
</graph>
Class diagram
<graph>
classDiagram
    class Animal {
        +name: string
        +speak()
    }
    class Dog {
        +fetch()
    }
    Animal <|-- Dog
</graph>

Flowcharts support subgraphs, decision nodes ({}), and edge labels. The graph component can also load content from a URL with src, or you can run .mmd files directly: melker diagram.mmd.

Reference: Mermaid support

9. File browser props

Configuration for selection mode, file type filtering, and display.

File browser variants
<!-- Directory picker -->
<file-browser selectType="directory"
    selectLabel="Choose Folder"
    onChange="$app.setWorkspace(event.path)" />

<!-- Multiple file selection -->
<file-browser selectionMode="multiple"
    selectType="file"
    onChange="$app.handleFiles(event.paths)" />

<!-- Filter by extension -->
<file-browser extensions="['.ts', '.js']"
    showHidden="true"
    onChange="$app.openFile(event.path)" />

<!-- Standalone without buttons -->
<file-browser path="/home/user/docs"
    showButtons="false"
    maxVisible="15"
    onChange="$app.openFile(event.path)" />

The selectType prop controls what can be selected: "file", "directory", or "both". The filter prop accepts the same modes as combobox: "fuzzy" (default), "prefix", "contains", "exact", or "none".

The onChange event provides event.path (full path), event.name (filename), event.isDirectory, and event.paths (array, for multiple selection). The onError event fires with event.code (PERMISSION_DENIED, NOT_FOUND) and event.message.

Reference: File browser architecture