Skip to documentation
SLOP

tiny.termtex.renderer

Reference tiny.termtex renderer

Defined in tiny.termtex.

API (6)

Actions

Public operations.

Types and contracts

Public types and contracts.

No direct callersNo direct callstiny.termtexrenderer
Static calls · unresolved targets: unknown · external targets: unknown.

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

Definitions1
Public names1
Members0
Version26.7.0
Revisiondaab053ee433