tiny.termtex.renderer
Defined in tiny.termtex.
API (6)
Actions
Public operations.
Types and contracts
Public types and contracts.
Source
Source: lib/termtex/src/render.zig
zig
const std = @import("std");const alloc_arena = @import("alloc_arena");const flat = @import("flat.zig");const image = @import("image.zig");const layout = @import("layout.zig");const parse = @import("parse.zig");pub const Options = struct {};pub const Rendered = struct { arena: alloc_arena.Arena, rows: []const []const u8, width: usize, height: usize, baseline: usize, pub fn deinit(self: *Rendered) void { self.arena.deinit(); self.* = undefined; } pub fn toOwnedString(self: *const Rendered, allocator: std.mem.Allocator) std.mem.Allocator.Error![]u8 { var out: std.ArrayListUnmanaged(u8) = .empty; errdefer out.deinit(allocator); for (self.rows, 0..) |row, index| { if (index != 0) try out.append(allocator, '\n'); try out.appendSlice(allocator, row); } return out.toOwnedSlice(allocator); }};pub fn render(allocator: std.mem.Allocator, source: []const u8, options: Options) !Rendered { _ = options; var arena = alloc_arena.Arena.init(allocator); errdefer arena.deinit(); const expr = try parse.parse(arena.allocator(), source); const box = try layout.layout(arena.allocator(), expr); const rendered_rows = try layout.rows(arena.allocator(), box); return .{ .arena = arena, .rows = rendered_rows, .width = box.width, .height = box.height, .baseline = box.baseline, };}pub fn renderAlloc(allocator: std.mem.Allocator, source: []const u8, options: Options) ![]u8 { var rendered = try render(allocator, source, options); defer rendered.deinit(); return rendered.toOwnedString(allocator);}pub fn renderInlineAlloc(allocator: std.mem.Allocator, source: []const u8, options: Options) ![]u8 { _ = options; return flat.renderAlloc(allocator, source);}pub fn renderImage(allocator: std.mem.Allocator, source: []const u8, options: image.Options) !image.Image { return image.render(allocator, source, options);}test "render scripts as baseline-aware rows" { const rendered = try renderAlloc(std.testing.allocator, "x_i^2", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\ 2 \\x \\ i , rendered);}test "render fractions as text cells" { const rendered = try renderAlloc(std.testing.allocator, "\\frac{a+b}{c}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\ a+b \\───── \\ c , rendered);}test "render large operator limits vertically" { const rendered = try renderAlloc(std.testing.allocator, "\\sum_{i=0}^{n}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\ n \\ ∑ \\i=0 , rendered);}test "render explicit limits without stealing scripts" { const rendered = try renderAlloc(std.testing.allocator, "\\sum\\limits_{i=0}^{n}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\ n \\ ∑ \\i=0 , rendered);}test "render explicit nolimits as side scripts" { const rendered = try renderAlloc(std.testing.allocator, "\\sum\\nolimits_{i=0}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\∑ \\ i=0 , rendered);}test "render operatorname star limits vertically" { const rendered = try renderAlloc(std.testing.allocator, "\\operatorname*{argmin}_{x}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\argmin \\ x , rendered);}test "render inline math compactly" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\alpha_i^2 + \\frac{x}{y}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("αᵢ²+x⁄y", rendered);}test "render inline math alphabets" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\mathbb{N}\\subseteq\\mathbb{R},\\mathcal{F}:\\mathbf{x}\\mapsto\\boldsymbol{\\alpha}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("ℕ⊆ℝ,ℱ:𝐱↦𝜶", rendered);}test "render inline unicode math alphabet aliases" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\symbfup{A}\\symsfup{B}\\symbfsfup{C}\\symbfsfit{D}\\symbbit{Ddeijx}\\symnormal{z}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("𝐀𝖡𝗖𝘿ⅅⅆⅇⅈⅉxz", rendered);}test "render inline explicit math spacing" { const rendered = try renderInlineAlloc(std.testing.allocator, "A\\,B\\:C\\;D\\quad E\\qquad F\\!G\\hspace{0.5em}H\\hspace{9mu}I~J\\thinspace K", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("A B C D E FG H I J K", rendered);}test "render cell math spacing widths" { const rendered = try renderAlloc(std.testing.allocator, "A\\quad B\\qquad C", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("A B C", rendered);}test "render text compatibility commands" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\textsc{E-App}\\;\\textrm{where}\\;\\texttt{fn}\\;\\textsf{A}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("ᴇ-ᴀᴘᴘ where 𝚏𝚗 𝖠", rendered);}test "render scientific and PL paper symbol idioms" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\Gamma\\vdash e:\\tau\\Longrightarrow e'\\in\\mathcal{V}\\cup\\{\\bot\\}\\iff e\\notin\\emptyset\\dots", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("Γ⊢e:τ⟹e'∈𝒱∪{⊥}⇔e∉∅…", rendered);}test "render wrapper and invisible paper commands" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\DeclareMathOperator{\\dom}{dom}\\phantom{x}\\hspace*{1em}\\mathop{\\mathrm{dom}}\\limits_{x\\in X}\\mathrel{\\multimap}\\top\\notag\\label{eq:step}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("dom_(x∈X)⊸⊤", rendered);}test "render additional PL relation aliases" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\trianglelefteq\\;\\nRightarrow\\;A\\lessapprox B\\;C\\ggg D\\;\\circledast", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("⊴ ⇏ A⪅B C⋙D ⊛", rendered);}test "operatorname star consumes limits marker" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\operatorname*{argmin}_{\\theta\\in\\mathbb{R}}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("argmin_(θ∈ℝ)", rendered);}test "render not relation idioms" { const rendered = try renderInlineAlloc(std.testing.allocator, "x\\not\\equiv y\\land z\\not P", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("x≢y∧z¬P", rendered);}test "render semantics bracket and transition idioms" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\llbracket e \\rrbracket_\\rho\\leadsto v'\\rightsquigarrow v\\prime", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("⟦e⟧_(ρ)↝v'⇝v′", rendered);}test "render modulo paper idioms" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\gcd(a,b)\\equiv a\\bmod b\\pmod{2^n}+c\\mod{m}+d\\pod{k}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("gcd(a,b)≡a mod b (mod 2ⁿ)+c mod m+d (k)", rendered);}test "render equation tags beside display math" { const rendered = try renderAlloc(std.testing.allocator, "\\sum_{i=0}^{n}\\tag{S}\\label{eq:sum}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\ n \\ ∑ (S) \\i=0 , rendered);}test "render unresolved references compactly" { const rendered = try renderInlineAlloc(std.testing.allocator, "x=y\\tag*{E-App}+\\eqref{eq:main}+\\ref{thm:main}+\\autoref{sec:intro}+\\Cref{lem:one}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("x=y E-App+(?)+?+?+?", rendered);}test "render PL inference rules" { const rendered = try renderAlloc(std.testing.allocator, "\\inferrule*[right=\\textsc{E-App}]{\\Gamma\\vdash e\\Downarrow\\lambda x.e \\\\ \\Gamma\\vdash v\\in\\mathcal{V}}{\\Gamma\\vdash e\\;v\\Downarrow e'}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\ Γ⊢e⇓λx.e \\ Γ⊢v∈𝒱 \\────────── ᴇ-ᴀᴘᴘ \\ Γ⊢e v⇓e' , rendered);}test "render proof-style infer compactly inline" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\infer[Ax]{C}{A\\\\B}+\\inference{P\\\\Q}{R}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("(A;B)⁄(C) Ax+(P;Q)⁄(R)", rendered);}test "render labeled arrows vertically" { const rendered = try renderAlloc(std.testing.allocator, "\\xrightarrow[\\alpha]{\\beta}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\β \\→ \\α , rendered);}test "render labeled arrows in rows" { const rendered = try renderAlloc(std.testing.allocator, "A\\xRightarrow{*}B", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\ * \\A⇒B , rendered);}test "render labeled arrows compactly inline" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\xleftarrow[\\ell]{r}+\\xmapsto{f}+\\xlongrightarrow{\\textsc{step}}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("←_(ℓ)^(r)+↦^(f)+⟶^(ꜱᴛᴇᴘ)", rendered);}test "render parenthesized matrix environment" { const rendered = try renderAlloc(std.testing.allocator, "\\begin{pmatrix} a & b \\\\ c & d \\end{pmatrix}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\⎛a b⎞ \\⎝c d⎠ , rendered);}test "render cases environment with left brace" { const rendered = try renderAlloc(std.testing.allocator, "\\begin{cases} x & x \\ge 0 \\\\ -x & x < 0 \\end{cases}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\⎧x x≥0 \\⎩-x x<0 , rendered);}test "render aligned environment cells" { const rendered = try renderAlloc(std.testing.allocator, "\\begin{aligned} x &= y+1 \\\\ &= z \\end{aligned}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\x =y+1 \\ =z , rendered);}test "render matrix environments compactly inline" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\begin{bmatrix} a & b \\\\ c & d \\end{bmatrix}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("[a,b;c,d]", rendered);}test "render array environment after column spec" { const rendered = try renderAlloc(std.testing.allocator, "\\begin{array}{cc} a & b \\\\ c & d \\end{array}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\a b \\c d , rendered);}test "render binomial coefficients" { const rendered = try renderAlloc(std.testing.allocator, "\\binom{n}{k}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\⎛ n ⎞ \\⎜───⎟ \\⎝ k ⎠ , rendered);}test "render primitive over fractions" { const rendered = try renderAlloc(std.testing.allocator, "{a+b\\over c}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\ a+b \\───── \\ c , rendered);}test "render primitive choose and atop stacks" { const choose = try renderAlloc(std.testing.allocator, "{n\\choose k}", .{}); defer std.testing.allocator.free(choose); try std.testing.expectEqualStrings( \\⎛n⎞ \\⎝k⎠ , choose); const atop = try renderAlloc(std.testing.allocator, "{x\\atop y}", .{}); defer std.testing.allocator.free(atop); try std.testing.expectEqualStrings( \\x \\y , atop);}test "render primitive brack and brace stacks" { const brack = try renderAlloc(std.testing.allocator, "{a\\brack b}", .{}); defer std.testing.allocator.free(brack); try std.testing.expectEqualStrings( \\⎡a⎤ \\⎣b⎦ , brack); const brace = try renderAlloc(std.testing.allocator, "{x\\brace y}", .{}); defer std.testing.allocator.free(brace); try std.testing.expectEqualStrings( \\⎧x⎫ \\⎩y⎭ , brace);}test "render primitive fractions inside delimiters and inline" { const display = try renderAlloc(std.testing.allocator, "\\left( a \\over b \\right)", .{}); defer std.testing.allocator.free(display); try std.testing.expectEqualStrings( \\⎛ a ⎞ \\⎜───⎟ \\⎝ b ⎠ , display); const inline_math = try renderInlineAlloc(std.testing.allocator, "{n\\choose k}+{a\\over b}+{x\\atop y}", .{}); defer std.testing.allocator.free(inline_math); try std.testing.expectEqualStrings("(n;k)+a⁄b+x;y", inline_math);}test "render left right delimiters around tall fractions" { const rendered = try renderAlloc(std.testing.allocator, "\\left(\\frac{x}{y}\\right)", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\⎛ x ⎞ \\⎜───⎟ \\⎝ y ⎠ , rendered);}test "render left right delimiters around matrices" { const rendered = try renderAlloc(std.testing.allocator, "\\left[\\begin{matrix} a & b \\\\ c & d \\end{matrix}\\right]", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\⎡a b⎤ \\⎣c d⎦ , rendered);}test "render middle and big delimiter idioms inline" { const set = try renderInlineAlloc(std.testing.allocator, "\\left\\{x\\middle|x\\in A\\right\\}", .{}); defer std.testing.allocator.free(set); try std.testing.expectEqualStrings("{x|x∈A}", set); const sized = try renderInlineAlloc(std.testing.allocator, "\\bigl( x \\bigr]", .{}); defer std.testing.allocator.free(sized); try std.testing.expectEqualStrings("(x]", sized);}test "render angle delimiters inline" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\left\\langle x \\right\\rangle", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("⟨x⟩", rendered);}test "render over and under annotations" { const overset = try renderAlloc(std.testing.allocator, "\\overset{*}{\\to}", .{}); defer std.testing.allocator.free(overset); try std.testing.expectEqualStrings( \\* \\→ , overset); const underset = try renderAlloc(std.testing.allocator, "\\underset{n\\to\\infty}{\\lim}", .{}); defer std.testing.allocator.free(underset); try std.testing.expectEqualStrings( \\lim \\n→∞ , underset);}test "render braces with centered labels" { const over = try renderAlloc(std.testing.allocator, "\\overbrace{a+b}^{n}", .{}); defer std.testing.allocator.free(over); try std.testing.expectEqualStrings( \\ n \\⏞⏞⏞ \\a+b , over); const under = try renderAlloc(std.testing.allocator, "\\underbrace{a+b}_{n}", .{}); defer std.testing.allocator.free(under); try std.testing.expectEqualStrings( \\a+b \\⏟⏟⏟ \\ n , under);}test "render boxed and underline annotations" { const boxed = try renderAlloc(std.testing.allocator, "\\boxed{x+y}", .{}); defer std.testing.allocator.free(boxed); try std.testing.expectEqualStrings( \\┌─────┐ \\│ x+y │ \\└─────┘ , boxed); const underline = try renderAlloc(std.testing.allocator, "\\underline{x+y}", .{}); defer std.testing.allocator.free(underline); try std.testing.expectEqualStrings( \\x+y \\─── , underline);}test "render additional accents" { const rendered = try renderAlloc(std.testing.allocator, "\\ddot{x}+\\tilde{y}+\\check{z}+\\overleftarrow{AB}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\¨ ~ ˇ ← \\x+y+z+AB , rendered);}test "render substacked limits" { const rendered = try renderAlloc(std.testing.allocator, "\\sum_{\\substack{i=0\\\\j=0}}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings( \\ ∑ \\i=0 \\j=0 , rendered);}test "render annotations compactly inline" { const rendered = try renderInlineAlloc(std.testing.allocator, "\\binom{n}{k}+\\overset{*}{\\to}+\\boxed{x}", .{}); defer std.testing.allocator.free(rendered); try std.testing.expectEqualStrings("(n⁄k)+overset(*,→)+[x]", rendered);}test { std.testing.refAllDecls(@This());}Source: lib/termtex/src/root.zig:16
zig
pub const renderer = @import("render.zig");Audit
| Definitions | 1 |
|---|---|
| Public names | 1 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |