Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mathml Laravel Package

mercurysolutions/mathml

A Laravel package for working with MathML, making it easy to render mathematical notation and equations in your PHP applications. Integrates cleanly with Blade views for displaying math content.

View on GitHub
Deep Wiki
Context7

Getting Started

Pull the package in with Composer and confirm what PHP versions it actually supports before you build around it:

composer require mercurysolutions/mathml
// composer.json — pin it. Five stars and zero dependents means you are the QA team.
"mercurysolutions/mathml": "dev-master#<commit-sha>"

Then open src/ and read it end to end — it is a small library, and the README is thin. You are looking for two things: the parser (MathML string → element tree) and the calculator/evaluator (tree → value). Typical entry points look like Parser::parse($xml) / Calculator::calculate($mathml), but confirm the exact class names and method signatures with grep -rn "public function" src/ before wiring anything into your app.

The mental model to hold: this library consumes Content MathML — the semantic dialect built from <apply>, <ci>, <cn>, <plus/> — not the presentation dialect made of <mrow>, <msup>, <mo>. Your first end-to-end use case should be a hand-written expression:

use MercurySolutions\MathML\Parser;      // verify FQCN
use MercurySolutions\MathML\Calculator;  // verify FQCN

$xml = <<<XML
<math xmlns="http://www.w3.org/1998/Math/MathML">
  <apply>
    <plus/>
    <ci>x</ci>
    <cn>2</cn>
  </apply>
</math>
XML;

$calculator = new Calculator();
$result = $calculator->calculate($xml); // evaluate with whatever binding API exists

Get that running in a scratch script or a single Pest/PHPUnit test before you touch a controller. That one test is your canary for every version bump.

Implementation Patterns

Wrap it in one service class. With 0 dependents, treat the package as a swappable detail. Put a thin adapter between your domain and the library:

final class MathExpressionEvaluator
{
    public function __construct(private Calculator $calculator) {}

    public function evaluate(string $mathml, array $variables = []): int|float
    {
        // bind $variables into the tree, or return the raw evaluated value
        return $this->calculator->calculate($mathml);
    }
}

Bind it in a service provider so controllers, jobs, and Blade components all get the same configured instance.

Store MathML, evaluate on demand. Keep the raw MathML string in a text column (plus a result cache column and an evaluated_at timestamp). Evaluating at write time locks in bugs and stale variable bindings; evaluating at read time lets you fix the interpreter and re-run. Parse trees are deterministic, so memoize by hash('xxh3', $mathml) if hot paths need it.

Bind variables at the edges, not in the tree. Whatever <ci>-resolution mechanism the package offers, prefer a context array keyed by identifier name. If it doesn't offer one, walk the tree yourself and substitute <ci> nodes with <cn> nodes before calculating — that keeps the library stateless and testable.

Generate Content MathML upstream. Formula editors are the usual source. MathType and Wiris export Content MathML natively; MathLive and MathQuill typically emit Presentation MathML or LaTeX and need a conversion step. Validate at the form-request layer by attempting a parse and failing the request with a clear message, rather than letting garbage reach the calculator.

Compare with tolerance. If you're using this for answer-checking (<eq/> or manual comparison), never compare floats with ===. Evaluate both sides, then abs($a - $b) < 1e-9.

Test with fixtures. Drop a handful of .mathml files in tests/fixtures/ covering each operator you rely on, and assert against them. This is your regression suite when a dev-master update lands.

Gotchas and Tips

  • Presentation MathML is not parsed. The single most common failure. If the input starts with <mrow> or <msup>, you have the wrong dialect. Check for <apply> in the source before blaming the library.
  • The namespace is effectively required. <math xmlns="http://www.w3.org/1998/Math/MathML"> — stripping it on the way through a WYSIWYG is a classic silent breakage.
  • <cn> is typed, not just a number. It carries type="integer|real|rational|e-notation|complex-cartesian|complex-polar" and a base attribute, and rationals use <sep/> inside: <cn type="rational">1<sep/>3</cn>. Assume the parser handles the common integer/real cases and verify the exotic ones yourself.
  • XXE. The parser almost certainly uses DOM/SimpleXML under the hood. Reject input containing <!DOCTYPE before handing it over, or ensure entity loading is disabled (LIBXML_NONET, and libxml_disable_entity_loader on older PHP). MathML arrives from users; treat it as untrusted XML.
  • Unsupported operators throw. Wrap calculate() in a try/catch and fall back to rendering the MathML visually (MathJax in the browser) instead of showing a number. A 500 on an unknown <log/> variant is a bad look.
  • Division by zero and domain errors. Expect exceptions or INF/NAN depending on the code path — trap before the value escapes into your UI or database.
  • Integer vs float return types drift. <plus/> on two <cn> integers may return int, mixed expressions return float. Normalize at your adapter boundary so downstream code has one contract.
  • No arbitrary precision. For anything financial or precision-sensitive, this is the wrong tool — reach for BCMath or brick/math. Tree-walking evaluation buys you safety over eval(), not numerical rigor.
  • Look for the function registry before forking. If the calculator exposes an operator/function map, register your custom <apply> handlers there. If it's a hardcoded match statement, subclass or vendor-copy — do not patch vendor/.
  • Instance state. If the calculator accumulates state between calls, don't share it as a singleton across a queue worker. Instantiate per evaluation unless you've confirmed it's stateless.
  • Documentation debt is the real risk. With this dependency count, nothing upstream will catch a breaking change. Pin the commit, keep your own fixture suite green, and keep the adapter thin enough that replacing the package is an afternoon, not a sprint.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings