Skip to main content

gallery/
render.rs

1//! Rendering tabs: Markdown, LaTeX, Mermaid, Graphviz, and the live editor
2//! preview sync shared by the gallery.
3
4use omp_tui::{Size, Ui};
5
6pub(crate) const MARKDOWN_TAB: &str = r#"# Rendering Gallery
7
8Everything below is one `<md>` node: **bold**, *italic*, ~~strike~~,
9`code`, [a link](https://example.com/docs), a bare https://example.com
10autolink, and color chips for #C5FFD6, #4A90D9, and `#fff`.
11
12> Quotes wrap with a rail — *and inline styles survive inside them.*
13
14| Feature | State | Notes |
15| --- | --- | --- |
16| tables | done | box borders, pi column widths |
17| math | done | inline and display |
18| mermaid | done | fenced blocks |
19| graphviz | done | `dot`, `graphviz`, and `gv` fences |
20
21```rust
22fn main() {
23    println!("fenced code keeps its fences");
24}
25```
26
27├── markdown
28│   ├── inline.rs
29│   └── table.rs
30└── latex
31
32---
33
341. ordered
352. lists
36   - with nesting
37"#;
38
39pub(crate) const MATH_TAB: &str = r"# Math
40
41Inline: $e^{i\pi} + 1 = 0$, fonts $\mathbb{R}^n \to \mathcal{H}$,
42scripts $x_i^2$, and currency stays put: $5 and $10.
43
44$$
45x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
46$$
47
48$$
49f(x) = \begin{cases} x^2 & x > 0 \\ 0 & \text{otherwise} \end{cases}
50$$
51
52$$
53\sum_{i=0}^{n} x_i \qquad \int_a^b f(x)\,dx \qquad \prod_{k=1}^{n} (1 + x_k)
54$$
55
56$$
57\underbrace{a + b}_{\text{sum}} \qquad \left( \frac{1}{2} \right)^2
58$$
59
60\begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix}
61";
62
63pub(crate) const MERMAID_TAB: &str = r"# Mermaid
64
65```mermaid
66flowchart LR
67  A[Lex] --> B[Parse] --> C[Layout]
68  C --> D[Paint]
69  C --> E[Cache]
70```
71
72```mermaid
73flowchart TD
74  start[Request] --> auth{Authorized?}
75  auth -->|yes| serve[Serve page]
76  auth -->|no| deny[401]
77```
78";
79
80pub(crate) const GRAPHVIZ_TAB: &str = r#"# Graphviz
81
82```dot
83digraph Pipeline {
84  rankdir=LR;
85  node [shape=box];
86
87  request [label="Request", shape=doublecircle];
88  parse [label="{Parse|Validate}", shape=record];
89  route [label="Route"];
90  cache [label="Cache"];
91  reject [label="Reject"];
92  render [label="Render"];
93
94  request -> parse [label="source"];
95  parse -> route [label="valid"];
96  parse -> reject [label="invalid", style=dashed];
97  route -> cache;
98  route -> render;
99  cache -> render [label="hit"];
100}
101```
102
103```graphviz
104graph Runtime {
105  node [shape=box];
106  Agent -- Broker [label="messages"];
107  Broker -- Model;
108  Broker -- Tools;
109  Tools -- Storage;
110}
111```
112"#;
113
114pub(crate) const LIVE_PREFILL: &str =
115	"# Live *markdown* — edit me! Math: $x^2 + y^2 = r^2$, chip: #C5FFD6, **bold**, `code`";
116
117pub(crate) const PANE_IDS: [&str; 4] = ["pane-md", "pane-math", "pane-mermaid", "pane-graphviz"];
118
119/// Fixed pane height for a viewport: tab bar + gaps + footer + scroll
120/// chrome ≈ 8 rows.
121pub(crate) fn pane_height(viewport: Size) -> u16 {
122	viewport.height.saturating_sub(8).max(4)
123}
124
125/// Mirrors the editor's text into the preview `<md>` node when it changed.
126pub(crate) fn sync_preview(ui: &mut Ui, synced: &mut String) {
127	let text = ui.values()["src"].as_str().unwrap_or_default().to_owned();
128	if text != *synced {
129		ui.set_text("preview", text.clone());
130		*synced = text;
131	}
132}