Pikchr – vollständige Lerndokumentation

Diese Datei fasst vollständig zusammen, was ich über das Projekt Pikchr gelernt habe: Sprache, Parser, Rendering, Text/Fit-Verhalten, Build-Prozess, Integrationsoptionen, Sicherheitsmodell, Projektstruktur, Browser-Experimente, Live-Update-Ideen und konkrete strategische Empfehlungen.

Fokus dieser Dokumentation ist nicht nur eine Wiederholung der offiziellen Projektbeschreibung, sondern eine technische und praktische Synthese aus Code-Analyse, Dokumentationslektüre, Build-Tests und den im Verlauf gebauten Prototypen.

Projekt: Pikchr Kontext: /Users/danielmoll/work/pikchar Stand: 2026-04-10 Format: Single HTML File

1. Executive Summary

Pikchr ist eine kleine, bemerkenswert dichte, C-basierte DSL zur Erzeugung von Diagrammen als SVG. Sie ist PIC-inspiriert, aber klar auf das moderne Web ausgerichtet: Markdown-Einbettung, sicheres SVG, begrenzte Komplexität, keine Shell-Escapes, kein Copy-File-Missbrauch, keine Schleifen, keine Ifs.

Die zentrale Überraschung des Projekts ist nicht nur, dass es Diagramme erzeugt, sondern dass es sehr nah an einer allgemeinen semantischen Bild- und Layoutsprache operiert. Mit Boxen, Linien, Splines, relativer Positionierung, Text, Farben, Auto-Fit und Makros kann Pikchr weit mehr als „nur Kästchendiagramme“.

Kernaussage: Pikchr ist klein genug, um verstanden zu werden, aber stark genug, um daraus Wireframes, Dashboard-Mockups, Architekturdiagramme, semantische SVG-Oberflächen und sogar live aktualisierte Diagramm-Interfaces abzuleiten.

Für privacy-first interne Live-Dashboards empfehle ich nicht den exotischen No-JS-HTTP-Stream als Produktionslösung, sondern ein serverseitiges Modell: State serverseitig aggregieren → Pikchr serverseitig rendern → SVG per SSE an dünnen Client ausliefern. Der Browser bekommt dann nur die gerenderte Sicht auf den Zustand, nicht die Rohtelemetrie.

2. Was Pikchr ist

2.1 Grundidentität

  • PIKCHR steht für eine PIC-ähnliche Diagramm-Markup-Sprache.
  • Autor: D. Richard Hipp (auch SQLite).
  • Lizenz: Zero-Clause BSD.
  • Ausgabeformat: SVG.
  • Einsatzidee: Diagramme in Markdown bzw. technischen Dokumentationen.
  • Implementierung: C99 + Lemon Parsergenerator.

2.2 Designphilosophie

  • Single-pass: Ein Objekt darf nur frühere Objekte referenzieren.
  • Einfaches mentales Modell: Kein Constraint Solver, kein komplexes Layoutsystem.
  • Sicherheit für Web-Kontext: Keine Shell-Kommandos, keine Dateiinserts, keine Schleifen.
  • Relative statt absolute Beschreibung: Layout wird bevorzugt in Beziehungen statt in Koordinaten beschrieben.

2.3 Der eigentliche Reiz

Pikchr ist nicht nur interessant, weil es SVG erzeugt, sondern weil es visuelle Struktur semantisch beschreibt. Diese Eigenschaft macht es besonders spannend für Diagramme, aber auch für experimentelles Webdesign, statische Interfaces, live aktualisierte Systemdarstellungen und deklarative Visualisierungssysteme.

3. Projektstruktur

Datei / Ordner Bedeutung
pikchr.y Zentrale Quelldatei: Lemon-Grammatik + sehr großer C-Implementierungsblock.
pikchr.h.in Öffentliche Header-Vorlage.
Makefile Generiert pikchr.c und baut CLI / Testartefakte.
lemon.c Lemon Parsergenerator.
lempar.c Lemon Parser-Template.
doc/ Offizielle Doku in vielen kleinen Markdown-Dateien.
examples/ Kleine Beispielskripte.
tests/ Über 100 Testfälle in Pikchr.
fiddle/ WASM-basierte Browser-Fiddle-App.
homepage.md Projektnahe Start-/Infoseite.

3.1 Bemerkenswerte Beobachtung

Der Großteil der eigentlichen Logik sitzt in einer einzigen Datei (pikchr.y). Das macht das Projekt einerseits konzentriert und elegant, andererseits auch ungewöhnlich dicht. Wer es wirklich verstehen will, kommt mit einer intensiven Lektüre dieser Datei erstaunlich weit.

4. Build- und Laufmodell

4.1 Klassischer Build

make clean
make pikchr

Dabei passiert im Kern:

  1. lemon wird gebaut.
  2. mkversion erzeugt VERSION.h.
  3. lemon pikchr.y erzeugt pikchr.c.
  4. Dann wird die CLI mit -DPIKCHR_SHELL kompiliert.

4.2 CLI-Modi

  • ./pikchr file.pikchr → HTML-Hülle mit SVG und Source-View.
  • ./pikchr --svg-only file.pikchr → reines SVG.
  • ./pikchr --dark-mode ... → invertierte Farbwelt.
  • ./pikchr --dont-stop ... → mehrere Dateien trotz Fehlern weiter verarbeiten.

4.3 Weitere Build-Ziele

  • pikchrfuzz für Fuzzer-Build.
  • piktcl für Tcl-Bindings.
  • WASM-Fiddle über fiddle/GNUmakefile und emcc.

5. Öffentliche API

char *pikchr(
  const char *zText,
  const char *zClass,
  unsigned int mFlags,
  int *pnWidth,
  int *pnHeight
);

const char *pikchr_version(void);

5.1 Verhalten

  • Input: nullterminierter Pikchr-Quelltext.
  • Output: per malloc() allokierter String.
  • Bei Erfolg: SVG.
  • Bei Fehler: Fehlermeldungstext statt SVG.
  • *pnWidth / *pnHeight geben SVG-Größe zurück oder negative Werte bei Fehlern.

5.2 Flags

Flag Bedeutung
PIKCHR_PLAINTEXT_ERRORS Fehlertext als Plaintext statt HTML.
PIKCHR_DARK_MODE Farben auf Dark-Mode-Nutzung hin transformieren.

6. Sprachmodell

6.1 Grundstruktur

Ein Pikchr-Dokument ist eine Folge von Statements, getrennt durch Newlines oder Semikolons.

line; box "Hello"; arrow

6.2 Statement-Typen

  • Objektdefinitionen
  • Richtungswechsel: right, down, left, up
  • Variablenzuweisungen
  • Makrodefinitionen
  • print-Statements
  • assert-Statements
  • Labels für Objekte oder freie Positionen

6.3 Single-pass

Das Layout ist absichtlich einfach: ein Objekt kennt nur die Objekte, die vorher schon definiert wurden. Das macht Pikchr sehr vorhersehbar und erklärt auch, warum relative Referenzen so wichtig sind.

7. Objekte, Attribute, Positionierung

7.1 Objektklassen

Klasse Typ Bemerkung
box Block Rechteck, optional mit Radius.
circle Block Kreis mit gekoppelten Width/Height/Radius-Regeln.
ellipse Block Ellipse.
oval Block Racetrack-/Kapsel-artig.
diamond Block Diamantform.
cylinder Block Zylinder mit Endkappenradius.
file Block Dokument-/Datei-Symbol.
dot Block Kleiner Punkt.
text Block Textobjekt, auch implizit via String als Statement.
line Linie Pfad ohne Pfeilspitze.
arrow Linie Wie line, aber mit Pfeil an Standardseite.
spline Linie Mehrsegmentiger Pfad mit Rundungen.
arc Linie Tatsächlich als Quadratic Bezier angenähert, nicht als echter Arc.
move Linie Unsichtbarer Abstandshalter.

7.2 Ankerpunkte

Blockobjekte besitzen übliche Anker:

.n .ne .e .se .s .sw .w .nw .c .start .end

7.3 Attribute

Form / Größe

  • width / wid
  • height / ht
  • radius / rad
  • diameter
  • fit

Stil

  • color
  • fill
  • thickness
  • thin, thick, solid
  • dashed, dotted, invis

Pfad / Linie

  • from, to, then, go
  • heading
  • chop
  • close
  • <-, ->, <->
  • cw, ccw

Position

  • at
  • with .edge at ...
  • relative Positionen: left/right/above/below
  • Zwischenpositionen: 1/2<A,B> bzw. between

8. Ausdrücke, Variablen, Funktionen

8.1 Arithmetik

expr + expr
expr - expr
expr * expr
expr / expr
(expr)
+expr
-expr

8.2 Built-in Funktionen

  • abs()
  • cos()
  • sin()
  • int()
  • min(), max()
  • sqrt()
  • dist(position, position)

8.3 Variablen

Wichtige built-ins u. a.:

Variable Bedeutung
boxwid, boxht, boxrad Default-Boxmaße.
circlerad Default-Kreisradius.
linewid, lineht Default-Linienmaße.
thickness Default-Linienstärke.
color, fill Default-Farben.
charwid, charht Textgrößenheuristik.
fontscale Skalierung der Textdarstellung.
margin, leftmargin, ... Außenabstand um das Diagramm.
scale Skaliert die SVG-Ausgabegröße.

8.4 Maßeinheiten

Numerische Literale können Suffixe haben:

cm  mm  in  px  pt  pc

9. Text, Auto-Fit und Bounding Boxes

9.1 Warum das bemerkenswert ist

Pikchr kennt die echte Browser-Fontmetrik nicht. Trotzdem schafft es das Projekt, Text oft überraschend gut zu schätzen und daraus brauchbare Boxgrößen abzuleiten. Genau diese Stelle ist eine der beeindruckendsten technischen Leistungen des Codes.

9.2 Wie Text intern geschätzt wird

  • ASCII-Zeichen haben eine interne Breitentabelle (awChar[]).
  • Monospace wird separat behandelt.
  • Entities und UTF-8 werden berücksichtigt.
  • charwid und charht skalieren die Heuristik.
  • big, small, bold, italic, mono beeinflussen die Schätzung.

9.3 Auto-Fit-Algorithmus

Wichtige Funktionen:

  • pik_text_length() – Breitenabschätzung.
  • pik_append_txt(..., pBox) – berechnet Text-Bounding-Boxen ohne tatsächlich zu rendern.
  • pik_size_to_fit() – errechnet aus Textgröße passende Objektmaße.
  • xFit() je Objektklasse – wendet Fit-Regeln objektspezifisch an.

9.4 Wichtige Erkenntnis

Kein pixelperfektes Font-Matching: Pikchr kann Text nicht exakt so messen wie der Browser, weil es die echte Font Engine, Kerning und exakte Render-Metrik nicht kennt. Es ist eine Heuristik, keine exakte Browser-Replikation. Dennoch ist die Schätzung in vielen Fällen erstaunlich gut.

9.5 Warum trotzdem Padding sichtbar ist

Selbst wenn nur Text gerendert wird, fügt Pikchr am Ende noch Diagrammränder hinzu (margin plus einen Sicherheitsabstand basierend auf thickness). Deshalb ist ein „text only“-SVG nicht vollkommen auf die Glyph-Bounds zugeschnitten.

10. Rendering-Pipeline intern

10.1 Objektmodell

Jedes Statement erzeugt ein PObj. Alle Objekte landen in einer PList. Eine globale Struktur Pik hält den Zustand des laufenden Renderings.

10.2 Typische Phasen

  1. Tokenisierung des Input-Strings.
  2. Parsing via Lemon.
  3. Objekte werden sukzessiv erzeugt und positioniert.
  4. Nach Statementende werden Attribute fixiert und Bounding Boxes berechnet.
  5. Nach komplettem Parse wird eine Gesamt-Bounding-Box aufgebaut.
  6. Dann wird SVG generiert.

10.3 Wichtige interne Strukturen

Typ Rolle
Pik Gesamtkontext eines Renderlaufs.
PObj Ein Diagrammobjekt.
PList Liste von Diagrammobjekten.
PClass Vtable-artige Klassendefinition pro Objekttyp.
PToken Tokenizer-/Parser-Token.
PVar Variableinträge.
PMacro Makrodefinitionen.

10.4 Schöne Designentscheidung

Jede Objektklasse implementiert Verhalten über ein kleines Methodenset (xInit, xFit, xRender, xCheck, xOffset, xChop). Dadurch ist das System überraschend erweiterbar, obwohl alles in einer Datei lebt.

11. Tokenizer, Parser und Makros

11.1 Tokenizer

Der Tokenizer erkennt unter anderem:

  • Strings in Anführungszeichen
  • Zahlen mit Units
  • Hex-Farbwerte
  • Kommentare: #, //, /* ... */
  • Unicode-/HTML-Aliasse für Pfeile
  • Uppercase-Labels vs lowercase-Variablen

11.2 Parser

Lemon erzeugt einen LALR(1)-Parser. Die Grammatik sitzt in pikchr.y. Pikchr ist damit formal genug, um sehr klar lesbar zu bleiben, ohne in klassische Compiler-Komplexität abzudriften.

11.3 Makros

define NAME { ... }

Makros unterstützen bis zu 9 Parameter ($1$9).

  • Rekursion wird verhindert.
  • Makros zählen gegen das Token-Limit.
  • Argumente werden kontextbewusst geparst.

12. Security- und Safety-Modell

12.1 Sehr bewusste Web-Sicherheit

Pikchr ist auffällig defensiv designt. Weggelassen wurden absichtlich:

  • sh – keine Shell-Kommandos
  • copy – keine Dateiinserts
  • for, if – keine Kontrollflusskonstrukte
  • sprintf() – keine problematische Stringformatierung

12.2 Token-Limit

Es gibt ein bewusstes Token-Limit (PIKCHR_TOKEN_LIMIT, Default 100000), um DoS-artige Makroexplosionen zu begrenzen.

12.3 Fazit

Pikchr ist nicht „sicher, weil klein“, sondern weil es in vielen Punkten absichtlich so gebaut wurde, dass gewisse Klassen von Missbrauch gar nicht erst auftreten können.

13. Wichtige Unterschiede zu klassischem PIC

  • Neue Objekttypen: oval, diamond, cylinder, file, dot.
  • Units wie cm, mm, px usw.
  • color und fill als CSS-ähnliche Farbsprache.
  • fit und Auto-Fit um Text.
  • same as object als Erweiterung.
  • chop mit neuer Semantik.
  • Mehr Textattribute und modernere Textkontrolle.
  • Variablen wie fontscale, margin, charwid, charht.
  • Pikchr verschiebt den .end-Anker des vorherigen Objekts bei Richtungswechseln anders als PIC.
  • Variablen in []-Containern werden nach Verlassen nicht restauriert.

14. Browser- und Playground-Experimente

14.1 WASM-Fiddle

Das Repository enthält eine Browser-Fiddle, die eigentlich per Emscripten/WASM funktioniert. In meinem Kontext war emcc nicht installiert, daher habe ich zunächst stattdessen eine Browser-Playground-Lösung mit nativer CLI-Render-Pipeline aufgebaut.

14.2 CLI + Browser Hybrid

Es wurde ein lokaler Playground umgesetzt:

  • Browser-Editor als HTML
  • lokaler Python-Server
  • Server ruft native ./pikchr --svg-only - auf
  • Browser zeigt das SVG an

Das ist kein WASM, aber praktisch ein „browser UI over native CLI renderer“.

14.3 Fiddle Auto-Render Bug

Beim offiziellen Fiddle-Code wurde eine Schwäche im „render while typing“-Modus gefunden:

  • zu stark auf keydown statt input gestützt
  • kleiner Fehler in der Tastencode-Filterlogik
  • behoben durch Umstellung auf robustere Input-Event-Nutzung

15. Dashboards, SVG und Live-Interfaces

15.1 Wichtige Erkenntnis

Mit Pikchr lassen sich nicht nur Diagramme, sondern erstaunlich überzeugend auch Dashboard-Mockups, semantische Oberflächen und grafische Systemräume bauen. Es ist nicht dasselbe wie HTML/CSS-Layout, aber visuell kann man sehr weit kommen.

15.2 Gebaute Experimente

  • Plausible-artiges Dashboard als Pikchr-SVG
  • Light/Dark-Varianten
  • „Pure“ SVG-Version mit minimaler HTML-Hülle
  • Fake-live HTML-Demo mit SVG-Mutationen
  • Control-room/System-flow Diagramm für privacy-first Architektur

15.3 Strategischer Wert

Pikchr ist besonders stark, wenn nicht DOM-Interaktivität und Accessibility das Hauptziel sind, sondern eine server-autorisierte, semantische, visuelle Zustandsdarstellung. Gerade für Architektur, Monitoring, Produkt-Analytics-Mockups und Systemkartierung ist das hochinteressant.

16. No-JS Streaming & Live-Update-Strategien

16.1 Fake-live im Browser

Ein erster Live-Effekt wurde über vorgerendertes SVG plus Browser-JS realisiert. Dabei wurden nur Zahlen, Bars, Linienpfade und Labels aktualisiert. Das zeigt: Schon ohne komplettes Neu-Rendern ist ein lebendiges Dashboard möglich.

16.2 No-JS HTTP/1.1 Stream

Danach wurde ein bewusst radikaler Prototyp gebaut: multipart/x-mixed-replace mit SVG-Frames über HTTP/1.1, ohne Frontend-JS für die Updates. Das ist architektonisch poetisch und experimentell reizvoll:

  • Server rendert Zustände in Pikchr
  • Server streamt komplette SVG-Frames
  • Browser konsumiert Stream als Bildressource
Aber: Für Produktion ist dieser Weg zu exotisch und browserabhängig. Als Forschungs-/Kunst-/Konzept-Ansatz großartig, als robuste Standardarchitektur eher nicht erste Wahl.

16.3 Drei Laufzeitmodelle

Modell Beschreibung Bewertung
Pre-render + SVG mutieren Pikchr nur beim Build, Browser ändert Teile im DOM. Gut für Demos und leichte Interaktivität.
Server-side render bei Zustandswechsel Server rendert neues SVG pro Update. Sehr sauber für privacy-first interne Dashboards.
WASM im Browser Browser rendert Pikchr lokal. Später interessant, aber komplexer.

17. Production-Architektur-Empfehlung

17.1 Entscheidungskriterium: Privacy first

Unter dem Leitwert privacy first lautet meine Empfehlung klar:

Server-side render + SSE + auth-geschütztes internes Dashboard

17.2 Warum SSE zuerst und nicht WebSocket

  • einfacher
  • einseitig Server → Client, was für Dashboards oft reicht
  • leichter hinter Reverse Proxies
  • weniger moving parts
  • leichter zu härten und zu debuggen

17.3 Empfohlener Datenfluss

  1. Events / Rohtelemetrie werden serverseitig ingestet.
  2. Ein Aggregator erzeugt einen renderbaren Zustand.
  3. Ein isolierter Renderer erzeugt daraus Pikchr bzw. SVG.
  4. Der Browser erhält nur Snapshot-SVG und Live-Updates.
  5. Rohdaten verlassen den Server nicht.

17.4 Iterationsstrategie

  1. Start: komplettes SVG per Update austauschen.
  2. Später: falls nötig Teilupdates und weichere Client-Animationen.
  3. Noch später: optional WASM oder Hybridmodell evaluieren.

18. Hardening-Checkliste

18.1 Rendering

  • nicht direkt im Request-Thread rendern
  • Worker-Prozess oder Sandbox
  • Timeouts, Memory-Limits, CPU-Limits

18.2 Streaming

  • max. gleichzeitige Clients
  • Idle-Timeouts
  • Slow-Client-Handling
  • Backpressure beachten

18.3 Zugriff

  • Auth vor Dashboard
  • nicht öffentlich ohne Schutz deployen
  • TLS/HTTPS erzwingen

18.4 Reverse Proxy

  • Buffering für Streams deaktivieren
  • Cache auf Live-Endpunkten deaktivieren
  • saubere Timeouts definieren

18.5 Sicherheits-Header

  • Cache-Control: no-store
  • X-Content-Type-Options: nosniff
  • CSP
  • Referrer-Policy

19. Im Verlauf erzeugte Artefakte

Während der Exploration wurden mehrere Dateien erzeugt:

Datei Zweck
playground.html Browser-Playground-Oberfläche.
playground_server.py Lokaler HTTP-Server, der native CLI aufruft.
dashboard_mockup.pikchr Erster größerer Dashboard-Versuch.
dashboard_mockup.html Gerenderter Dashboard-Mockup-Prototyp.
dashboard_v1.pikchr Reduzierte Dashboard-Version.
dashboard_v1_light.pikchr Light-Theme-Version.
dashboard_v1.html Light/Dark HTML-Demo.
dashboard_v1_pure.html Nahezu reines SVG-Frontend.
dashboard_fake_live.html Fake-live Dashboard mit SVG-Mutationen.
stream_dashboard_server.py No-JS HTTP/1.1 Streaming-Prototyp mit SVG-Frames.
control_room_flow.pikchr Privacy-first System-/Control-Room-Architekturdiagramm.
control_room_flow.html Gerenderte HTML-Fassung des Architekturdiagramms.

20. Schlussfazit

Pikchr ist ein außergewöhnlich spannendes Projekt, weil es mehrere seltene Eigenschaften vereint:

  • klein genug, um als Ganzes verstehbar zu bleiben
  • formal genug, um ernsthaft einsetzbar zu sein
  • sicher genug, um im Webkontext Sinn zu ergeben
  • flexibel genug, um über klassische Diagramme hinauszuwachsen

Die wichtigste persönliche Erkenntnis aus dieser Analyse ist wahrscheinlich diese:

Pikchr ist nicht nur ein Diagrammwerkzeug. Es ist eine kleine deklarative Sprache für semantische Bildräume, Systemzustände und strukturierte SVG-Oberflächen.

Genau deshalb taucht es plötzlich in Bereichen auf, die zunächst überraschend wirken: Dashboard-Mockups, technische Storytelling-Flächen, Architekturansichten, Monitoring, Live-Systembilder, experimentelles Webdesign und privacy-first Visualisierungssysteme.

Wenn man es produktiv ernst nimmt, würde ich Pikchr nicht als universellen HTML/CSS-Ersatz denken, sondern als server-authoritative rendering layer für klar definierte Zustandsbilder. In dieser Rolle ist es nicht nur interessant, sondern potenziell sehr stark.