Skip to content

About

Equations converted between MathML, OMML (Word), MTEF (MathType and Equation Editor 3.0), UnicodeMath (Word's linear format) and LaTeX, in .NET, with MathML as the common representation.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

SharpEquations

CI CodeQL NuGet NuGet downloads GitHub release Renovate Dependabot License: MIT .NET 10 .NET Standard 2.0 Platforms Dependencies Formats

Equations converted between MathML, OMML (Word), MTEF (MathType and Equation Editor 3.0), UnicodeMath (Word's linear format) and LaTeX, in .NET, with MathML as the common representation.

Format Read Write
MathML (presentation; Content MathML is read as the presentation it is written as) ✓ ✓
OMML (Office Math Markup Language, the equations of .docx) ✓ ✓
MTEF (MathType, Equation Editor 3.0) ✓
UnicodeMath ✓ ✓
LaTeX (standard, or as Word writes it) ✓ ✓

SharpEquations targets .NET Standard 2.0 and .NET 10, and depends on nothing but the .NET base library (and System.Memory on .NET Standard 2.0).

Usage

using SharpEquations;

var equation = Equation.Parse(@"\frac{a^2+b^2}{c}", EquationFormat.LaTeX);
string unicodeMath = equation.ToString(EquationFormat.UnicodeMath);   // (a^2+b^2)/c
XElement omml = equation.ToOmml();
string mathML = equation.ToString();
string latex = $"{equation:L}";

string converted = EquationConverter.Convert("x=(-b±√(b^2-4ac))/2a", EquationFormat.UnicodeMath, EquationFormat.LaTeX);

EquationOptions sets the display mode, strict reading, whether formatting is kept, the LaTeX flavor (standard, or the LaTeX of Word's equation editor) and LaTeX macros. An MTEF equation is read from the bytes of the "Equation Native" stream of its OLE object (Equation.Parse(bytes, EquationFormat.Mtef)); reading the OLE object is left to the caller.

Equations compare by their normalized MathML: an equation written in its own format (UnicodeMath, OMML) reads back to the same equation, and one written in another format loses only what that format cannot hold.

Equation editor for Avalonia

SharpEquations.Avalonia is a real-time equation editor in the manner of the RichEditBox of WinUI in math mode and of the equations of Word: UnicodeMath or LaTeX typed at the caret builds up into the equation when a space or an operator ends an argument (a/b␣ becomes a fraction, \alpha␣ α), the caret moves through the slots of the structures, and the equation is read and written as MathML or as an Equation.

<sharp:MathEditBox xmlns:sharp="using:SharpEquations.Avalonia" FontSize="28" InputFormat="UnicodeMath" Equation="{Binding Equation}" />
var editor = new MathEditBox { InputFormat = EquationFormat.LaTeX };
editor.EquationChanged += (_, e) => Console.WriteLine(e.Equation?.ToString(EquationFormat.MathML));
string mathML = editor.GetMath();        // as RichEditTextDocument.GetMath
editor.SetMath(mathML);                  // as RichEditTextDocument.SetMath
editor.ViewMode = MathViewMode.Linear;   // the equation as one line of UnicodeMath (Ctrl+Shift+L)
editor.EquationNumber = "(1)";           // at the right of the line, as #(1) or \tag{1}
string latex = editor.GetSelectedText(EquationFormat.LaTeX)!;
editor.CopyTextFormat = EquationFormat.MathML;   // Ctrl+C pastes as an equation into Word
editor.Editor.InsertLineBreak();         // Shift+Enter: lines aligned at &
editor.Editor.InsertTableRow();          // and columns, in the matrix of the caret

Typing \ and the start of a command opens a floating bar at the caret with its completions (EquationCommands.Complete("al", EquationFormat.UnicodeMath) gives them from the core); the bar also offers structures for the selection, the commands of a table and quick symbols.

The packages are SharpEquations.Avalonia (the controls), SharpEquations.Rendering and SharpEquations.Editing, with the version of SharpEquations.

MathView shows an equation without editing it. Both lay out MathML after MathML Core with the OpenType MATH table of a math font: Cambria Math on Windows, and Libertinus Math (SIL Open Font License), embedded, elsewhere. The editor is three projects, so that the core keeps no dependency: SharpEquations.Editing (the editing model, no user interface), SharpEquations.Rendering (the layout, no user interface) and SharpEquations.Avalonia (the controls). The design is in docs/EDITOR.md; samples/SharpEquations.Avalonia.Demo is a window with the editor and its MathML, UnicodeMath and LaTeX, and samples/SharpEquations.Avalonia.Browser.Demo the same demo in the browser, on WebAssembly (published to GitHub Pages from main; to run it locally: dotnet workload install wasm-tools, then dotnet run --project samples/SharpEquations.Avalonia.Browser.Demo). samples/SharpEquations.Avalonia.MathTools.Demo is a second app around the editor, a set of math tools (a scientific keypad that types into the editor and computes what is typed with AngouriMath, a library of formulas, a unit converter, a solver of triangles), with samples/SharpEquations.Avalonia.Browser.MathTools.Demo in the browser (published under math/ of the same site); what they compute is in samples/SharpEquations.MathTools.Core and samples/SharpEquations.MathTools.Graphing, which have no user interface.

Architecture

How the conversions work, format by format, and how round trips are kept exact: docs/ARCHITECTURE.md.

Building and testing

dotnet build SharpEquations.slnx
dotnet test --solution SharpEquations.slnx

The tests use TUnit; they run on .NET 10 against the .NET 10 build, and against the .NET Standard 2.0 build on .NET 8 (Linux, macOS) or on .NET Framework 4.8.1 (Windows). Their data is in tests/data (see its README).

Releases

CI (.github/workflows/ci.yml) tests every push and pull request on Linux (.NET 10 and .NET 8), Windows (.NET 10 and .NET Framework 4.8.1) and macOS (.NET 10), and packs the NuGet packages (the converter and the three of the editor, with one version). The release version is VersionPrefix in BuildVersion.props: bump it, and merging to main tags vX.Y.Z, creates the GitHub release with the package attached, and publishes it to GitHub Packages and to nuget.org (with Trusted Publishing: the repository variable NUGET_USER names the nuget.org account; without it nuget.org is skipped). A push that keeps the version on purpose says [no-new-version] in its commit message. Every pull request gets a pr-<N>-… pre-release, with the package versioned X.Y.Z-pr.<N>.<run>, replaced on each push and deleted when the pull request closes. Dependabot keeps the GitHub Actions current and Renovate the NuGet dependencies.

License

MIT (see LICENSE). Third-party files (the TEI stylesheets, the ports of UnicodeMathML and of the mathtype gem, the code Parlot generates, test data) keep their licences: see NOTICE.

About

Equations converted between MathML, OMML (Word), MTEF (MathType and Equation Editor 3.0), UnicodeMath (Word's linear format) and LaTeX, in .NET, with MathML as the common representation.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages