tiny.zen.math.mathml
Defined in math.
API (1)
Actions
Public operations.
Source
Source: lib/zen/src/math/mathml.zig
zig
const std = @import("std");const zen = @import("../root.zig");const parse = @import("parse.zig");const html = zen.html;const Allocator = std.mem.Allocator;pub fn append(out: *std.ArrayList(u8), allocator: Allocator, node: parse.Node) Allocator.Error!void { switch (node) { .row => |items| { if (items.len == 1) return append(out, allocator, items[0]); try out.appendSlice(allocator, "<mrow>"); for (items) |item| try append(out, allocator, item); try out.appendSlice(allocator, "</mrow>"); }, .ident => |ident| { if (ident.upright) { try out.appendSlice(allocator, "<mi mathvariant=\"normal\">"); } else { try out.appendSlice(allocator, "<mi>"); } try html.appendEscaped(out, allocator, ident.text); try out.appendSlice(allocator, "</mi>"); }, .number => |text| { try out.appendSlice(allocator, "<mn>"); try html.appendEscaped(out, allocator, text); try out.appendSlice(allocator, "</mn>"); }, .operator => |operator| { try out.appendSlice(allocator, "<mo"); if (operator.stretchy) try out.appendSlice(allocator, " stretchy=\"true\""); if (operator.rigid) try out.appendSlice(allocator, " stretchy=\"false\""); if (operator.movable_word) try out.appendSlice(allocator, " movablelimits=\"true\""); try out.append(allocator, '>'); try html.appendEscaped(out, allocator, operator.text); try out.appendSlice(allocator, "</mo>"); }, .space => |width| { try out.appendSlice(allocator, "<mspace width=\""); try out.appendSlice(allocator, width); try out.appendSlice(allocator, "\"/>"); }, .text => |text| { try out.appendSlice(allocator, "<mtext>"); try html.appendEscaped(out, allocator, text); try out.appendSlice(allocator, "</mtext>"); }, .frac => |frac| { try out.appendSlice(allocator, "<mfrac>"); try append(out, allocator, frac.first.*); try append(out, allocator, frac.second.*); try out.appendSlice(allocator, "</mfrac>"); }, .radical => |radical| { if (radical.index) |index| { try out.appendSlice(allocator, "<mroot>"); try append(out, allocator, radical.radicand.*); try append(out, allocator, index.*); try out.appendSlice(allocator, "</mroot>"); } else { try out.appendSlice(allocator, "<msqrt>"); try append(out, allocator, radical.radicand.*); try out.appendSlice(allocator, "</msqrt>"); } }, .scripts => |scripts| { const tag = scriptTag(scripts); try out.append(allocator, '<'); try out.appendSlice(allocator, tag); try out.append(allocator, '>'); try append(out, allocator, scripts.base.*); if (scripts.sub) |sub| try append(out, allocator, sub.*); if (scripts.sup) |sup| try append(out, allocator, sup.*); try out.appendSlice(allocator, "</"); try out.appendSlice(allocator, tag); try out.append(allocator, '>'); }, .accent => |accent| { try out.appendSlice(allocator, "<mover accent=\"true\">"); try append(out, allocator, accent.base.*); try out.appendSlice(allocator, "<mo>"); try html.appendEscaped(out, allocator, accent.mark); try out.appendSlice(allocator, "</mo></mover>"); }, .table => |table| try appendTable(out, allocator, table), }}fn appendTable(out: *std.ArrayList(u8), allocator: Allocator, table: parse.Table) Allocator.Error!void { const fenced = table.env.open != null or table.env.close != null; if (fenced) try out.appendSlice(allocator, "<mrow>"); if (table.env.open) |text| try appendFence(out, allocator, text); try out.appendSlice(allocator, "<mtable"); if (table.env.display_cells) try out.appendSlice(allocator, " displaystyle=\"true\""); if (table.env.class) |class| { try out.appendSlice(allocator, " class=\""); try out.appendSlice(allocator, class); try out.append(allocator, '"'); } try out.append(allocator, '>'); for (table.rows) |row| { try out.appendSlice(allocator, "<mtr>"); for (row) |cell| { try out.appendSlice(allocator, "<mtd>"); for (cell.row) |item| try append(out, allocator, item); try out.appendSlice(allocator, "</mtd>"); } try out.appendSlice(allocator, "</mtr>"); } try out.appendSlice(allocator, "</mtable>"); if (table.env.close) |text| try appendFence(out, allocator, text); if (fenced) try out.appendSlice(allocator, "</mrow>");}fn appendFence(out: *std.ArrayList(u8), allocator: Allocator, text: []const u8) Allocator.Error!void { try out.appendSlice(allocator, "<mo stretchy=\"true\">"); try html.appendEscaped(out, allocator, text); try out.appendSlice(allocator, "</mo>");}fn scriptTag(scripts: parse.Scripts) []const u8 { const both = scripts.sub != null and scripts.sup != null; if (scripts.limits) { if (both) return "munderover"; return if (scripts.sub != null) "munder" else "mover"; } if (both) return "msubsup"; return if (scripts.sub != null) "msub" else "msup";}test "mathml emits scripts by placement preference" { var parsed = try parse.parse(std.testing.allocator, "\\sum_{i}^{n} x_i", null); defer parsed.deinit(); var out: std.ArrayList(u8) = .empty; defer out.deinit(std.testing.allocator); try append(&out, std.testing.allocator, parsed.root); try std.testing.expectEqualStrings( "<mrow><munderover><mo>∑</mo><mi>i</mi><mi>n</mi></munderover>" ++ "<msub><mi>x</mi><mi>i</mi></msub></mrow>", out.items, );}test "mathml emits fenced matrices" { var parsed = try parse.parse(std.testing.allocator, "\\begin{pmatrix} a & b \\\\ & 1 \\end{pmatrix}", null); defer parsed.deinit(); var out: std.ArrayList(u8) = .empty; defer out.deinit(std.testing.allocator); try append(&out, std.testing.allocator, parsed.root); try std.testing.expectEqualStrings( "<mrow><mo stretchy=\"true\">(</mo><mtable>" ++ "<mtr><mtd><mi>a</mi></mtd><mtd><mi>b</mi></mtd></mtr>" ++ "<mtr><mtd></mtd><mtd><mn>1</mn></mtd></mtr>" ++ "</mtable><mo stretchy=\"true\">)</mo></mrow>", out.items, );}test "mathml emits cases with a lone brace and class" { var parsed = try parse.parse(std.testing.allocator, "\\begin{cases} x & y \\end{cases}", null); defer parsed.deinit(); var out: std.ArrayList(u8) = .empty; defer out.deinit(std.testing.allocator); try append(&out, std.testing.allocator, parsed.root); try std.testing.expectEqualStrings( "<mrow><mo stretchy=\"true\">{</mo><mtable class=\"zen-cases\">" ++ "<mtr><mtd><mi>x</mi></mtd><mtd><mi>y</mi></mtd></mtr>" ++ "</mtable></mrow>", out.items, );}test "mathml emits aligned with display cells" { var parsed = try parse.parse(std.testing.allocator, "\\begin{aligned} a &= b \\\\ &= c \\end{aligned}", null); defer parsed.deinit(); var out: std.ArrayList(u8) = .empty; defer out.deinit(std.testing.allocator); try append(&out, std.testing.allocator, parsed.root); try std.testing.expectEqualStrings( "<mtable displaystyle=\"true\" class=\"zen-aligned\">" ++ "<mtr><mtd><mi>a</mi></mtd><mtd><mo>=</mo><mi>b</mi></mtd></mtr>" ++ "<mtr><mtd></mtd><mtd><mo>=</mo><mi>c</mi></mtd></mtr>" ++ "</mtable>", out.items, );}test "mathml escapes text content" { var parsed = try parse.parse(std.testing.allocator, "a < b \\text{ & so }", null); defer parsed.deinit(); var out: std.ArrayList(u8) = .empty; defer out.deinit(std.testing.allocator); try append(&out, std.testing.allocator, parsed.root); try std.testing.expectEqualStrings( "<mrow><mi>a</mi><mo><</mo><mi>b</mi><mtext> & so </mtext></mrow>", out.items, );}Source: lib/zen/src/math/root.zig:3
zig
pub const mathml = @import("mathml.zig");Complete caller list for math.mathml.append
7 direct callers.
lib.zen.src.math.mathml.appendTable[function] — private source atlib/zen/src/math/mathml.zig:90in nearest public ownertiny.zen.math.mathmllib.zen.src.math.mathml.test_mathml_emits_aligned_with_display_cells[function] — test source atlib/zen/src/math/mathml.zig:174in nearest public ownertiny.zen.math.mathmllib.zen.src.math.mathml.test_mathml_emits_cases_with_a_lone_brace_and_class[function] — test source atlib/zen/src/math/mathml.zig:160in nearest public ownertiny.zen.math.mathmllib.zen.src.math.mathml.test_mathml_emits_fenced_matrices[function] — test source atlib/zen/src/math/mathml.zig:145in nearest public ownertiny.zen.math.mathmllib.zen.src.math.mathml.test_mathml_emits_scripts_by_placement_preference[function] — test source atlib/zen/src/math/mathml.zig:132in nearest public ownertiny.zen.math.mathmllib.zen.src.math.mathml.test_mathml_escapes_text_content[function] — test source atlib/zen/src/math/mathml.zig:189in nearest public ownertiny.zen.math.mathmllib.zen.src.math.root.render[function] — private source atlib/zen/src/math/root.zig:21in nearest public ownertiny.zen.math
Audit
| Definitions | 2 |
|---|---|
| Public names | 2 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |