hi there, this is a test

dit is een quote van iemand

van mij haha
title
content
dat ging niet goed

huh

war

arara

a

rar

ar

a

r

ar

a

r

ara

tabelhahaen t werkt gewoon goed?
wowhuhWOW
function render_list_recursive($items, $tag) {
    $html = "<$tag>";
    foreach ($items as $item) {
        if (is_array($item)) {
            $content = $item['content'] ?? '';
            $nested  = !empty($item['items']) ? render_list_recursive($item['items'], $tag) : '';
            $html .= "<li>{$content}{$nested}</li>";
        } else {
            $html .= "<li>{$item}</li>";
        }
    }
    $html .= "</$tag>";
    return $html;
}

function render_blocks($json_string) {
    if (!str_starts_with(trim($json_string), '{')) {
        return nl2br($json_string);
    }

    $data = json_decode($json_string, true);
    if (!$data || !isset($data['blocks'])) return "";

    $html = "";
    $blocks = $data['blocks'];
    $count = count($blocks);
    
    // Timeline State Tracker
    $in_timeline = false;

    for ($i = 0; $i < $count; $i++) {
        $block = $blocks[$i];
        $type = $block['type'];
        
        // Auto-wrap Timeline Items
        if ($type === 'timeline_item') {
            if (!$in_timeline) {
                $html .= '<div class="terminal-timeline">';
                $in_timeline = true;
            }
        } else {
            if ($in_timeline) {
                $html .= '</div>'; 
                $in_timeline = false;
            }
        }

        switch ($type) {
            case 'header':
                $level = $block['data']['level'];
                $text  = $block['data']['text'];
                $html .= "<h{$level}>{$text}</h{$level}>";
                break;

            case 'paragraph':
                $html .= "<p>{$block['data']['text']}</p>";
                break;

            case 'list':
                $style = $block['data']['style'] ?? 'unordered';
                $tag   = ($style === 'ordered') ? 'ol' : 'ul';
                $items = $block['data']['items'] ?? [];
                $html .= render_list_recursive($items, $tag);
                break;

            case 'image':
                $url = $block['data']['url'];
                $caption = $block['data']['caption'] ?? '';
                $html .= "<figure><img src='{$url}' alt='{$caption}'><figcaption>{$caption}</figcaption></figure>";
                break;
                
            case 'code':
                $code = htmlspecialchars($block['data']['code']);
                $html .= "<pre><code>{$code}</code></pre>";
                break;

            case 'quote':
                $text = $block['data']['text'];
                $caption = $block['data']['caption'] ?? '';
                $html .= "<blockquote><p>{$text}</p><footer><cite>{$caption}</cite></footer></blockquote>";
                break;

            case 'table':
                $content = $block['data']['content'] ?? [];
                if (!empty($content)) {
                    $html .= "<table><tbody>";
                    foreach ($content as $row) {
                        $html .= "<tr>";
                        foreach ($row as $cell) {
                            $html .= "<td>{$cell}</td>";
                        }
                        $html .= "</tr>";
                    }
                    $html .= "</tbody></table>";
                }
                break;

            // --- Custom Terminal Components ---
            
            case 'alert':
                $type = $block['data']['type']; 
                $msg  = $block['data']['message'];
                $class = 'terminal-alert';
                if ($type === 'primary') $class .= ' terminal-alert-primary';
                if ($type === 'error')   $class .= ' terminal-alert-error';
                $html .= "<div class='{$class}'>{$msg}</div>";
                break;

            case 'card':
                $head = $block['data']['header'];
                $body = $block['data']['body'];
                $html .= "<div class='terminal-card'><header>{$head}</header><div>{$body}</div></div>";
                break;

            case 'timeline_item':
                $head = $block['data']['header'];
                $body = $block['data']['body'];
                $html .= "<div class='terminal-card'><header>{$head}</header><div>{$body}</div></div>";
                break;

            case 'btn':
                $text  = $block['data']['text'];
                $url   = $block['data']['url'];
                $style = $block['data']['style'];
                $ghost = $block['data']['ghost'];
                $isBlock = $block['data']['block'];
                
                $class = 'btn';
                if ($style === 'primary') $class .= ' btn-primary';
                if ($style === 'error')   $class .= ' btn-error';
                if ($ghost) $class .= ' btn-ghost';
                if ($isBlock) $class .= ' btn-block';
                
                $html .= "<a href='{$url}' class='{$class}' role='button'>{$text}</a>";
                break;

            case 'progress':
                $pct = $block['data']['percent'];
                $showLabel = $block['data']['showLabel'];
                $class = 'progress-bar';
                if ($showLabel) $class .= ' progress-bar-show-percent';
                $labelAttr = $showLabel ? "data-filled='{$pct}%'" : "";
                
                $html .= "<div class='{$class}'><div class='progress-bar-filled' style='width:{$pct}%' {$labelAttr}></div></div>";
                break;

            case 'media':
                $align = $block['data']['align'];
                $img   = $block['data']['image'];
                $head  = $block['data']['header'];
                $body  = $block['data']['body'];
                
                $html .= "<div class='terminal-media'>";
                if ($align === 'left') {
                    $html .= "<div class='terminal-media-left'><div class='terminal-avatarholder'><img src='{$img}'></div></div>";
                }
                
                $html .= "<div class='terminal-media-body'>
                            <div class='terminal-media-heading'>{$head}</div>
                            <div class='terminal-media-content'>{$body}</div>
                          </div>";
                          
                if ($align === 'right') {
                    $html .= "<div class='terminal-media-right'><div class='terminal-avatarholder'><img src='{$img}'></div></div>";
                }
                $html .= "</div>";
                break;

            case 'dl':
                $items = $block['data']['items'];
                if (!empty($items)) {
                    $html .= "<dl>";
                    foreach ($items as $item) {
                        $html .= "<dt>{$item['term']}</dt><dd>{$item['desc']}</dd>";
                    }
                    $html .= "</dl>";
                }
                break;
        }
    }
    
    // Close timeline if still open
    if ($in_timeline) {
        $html .= '</div>';
    }

    return $html;
}
Date / Title
Event details...
Date / Title
Event details...
Heading
term
description
more terms
more description?