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.
Architecture fit. The package is a headless computation library: XML in, numeric/symbolic result out. That is a clean fit for a Laravel app if it is treated as a domain service behind an interface, not as a dependency smeared across controllers. It belongs in a bounded context (grading, formula validation, scientific calculation) and should be reached through a single application-level contract — e.g. MathExpressionEvaluator::evaluate(string $mathml): Result. The library's value is that it consumes a standards-based format (W3C Content MathML) rather than a bespoke DSL, which keeps the persistence/modeling layer free of evaluator-specific structures: MathML can be stored in the DB and rendered with a separate Presentation-MathML/MathJax pipeline.
Integration feasibility. Mechanically trivial — a Composer require plus a service-provider binding. The gating questions are not architectural but logistical:
mercurysolutions/mathml does not match the repository path renaudclosset/MathML. Confirm whether Packagist metadata, the GitHub repo, and the published tarball are actually the same code, and whether one is a fork of the other. Vendor/repo mismatch is a classic supply-chain signal for an unmaintained or re-published package.opportunity: 14.01 score against a score: 0.055 tells the real story: the problem space is underserved, the artifact is not trustworthy as-is. This is a build-vs-adopt input, not an adoption recommendation.Technical risk.
LIBXML_NONET, no LIBXML_NOENT, no DTD loading). Verify the library does this internally rather than leaving it to the caller — most small PHP parsers do not.eval(), call_user_func on user-supplied names, or dynamic method resolution from csymbol content is a code-execution risk. Any csymbol extension mechanism must be an allowlist.bcmath/gmp). Expect silent rounding, integer overflow at 2^63, division-by-zero behavior that may be exception or INF, and platform-dependent float formatting. For grading or financial-adjacent math these are correctness bugs, not edge cases.piecewise, set theory, calculus (int, diff), linear algebra, csymbol for domain-specific symbols. Coverage is almost certainly partial. Unknown coverage becomes your product's functional ceiling, and unsupported constructs must fail loudly, not return a partially simplified expression silently.Key questions for due diligence. What PHP versions and ext-* are required? Does it have a test suite and green CI? How are parse errors and unsupported operators surfaced? Is recursion depth bounded (stack exhaustion on deeply nested MathML)? Which Content MathML operator set is implemented, and is there a csymbol allowlist hook? Does it evaluate, simplify symbolically, or both? Is XML parsing hardened, and can it be configured to reject DTDs? What is the license, and who is the maintainer's commit cadence over the last 24 months? What is the actual Packagist download count versus the GitHub stars?
Stack fit. Plain Composer package — no framework coupling, which is the correct shape. Wrap it: register a singleton in a service provider, expose configuration for allowed operators, recursion depth, timeout, and numeric mode, and optionally a facade for ergonomics. Do not let MathML\* classes appear in controllers, models, or Blade. Evaluation should run inside a queued job for anything user-initiated and be cached by a hash of the normalized MathML, since parsing and evaluation are pure functions — a cache is free correctness-preserving latency removal.
Migration path. The migration is from "no evaluator" or "ad-hoc eval/regex arithmetic" to a bounded service, so the sequencing matters more than the source system.
MathExpressionEvaluator with a typed result object (value, error kind, warnings). Build the adapter over this package behind that interface before any caller uses it.Compatibility. Confirm PHP 8.1/8.2/8.3 support against your Laravel 10/11 target; a stale constraint here ends the evaluation immediately. Check ext-dom, ext-libxml, and whether ext-bcmath improves precision. If the package is PHP 7-only, the realistic options are a small compatibility patch on a vendored fork or outright rejection.
Sequencing for a fork. Given the adoption signals, assume you will vendor. Copy the source into app/Support/MathML or a private VCS fork, add PHPUnit coverage around the operator table, add the XML hardening flags, and pin your own tag. Prefer this over depending on an unmaintained upstream you cannot patch — but only after the spike proves the operator coverage is sufficient, because forking a library that only implements half of Content MathML buys you a maintenance burden and a product limitation.
Contingency. If the spike fails on coverage or security, the fallback is a sidecar: Node mathjs or a Python SymPy service behind the same MathExpressionEvaluator contract. Because you defined the interface first, that swap is an adapter change, not a rewrite. This is the strongest argument for the contract-first sequencing.
Maintenance. The dominant cost is owning an effectively unmaintained dependency. Expect to pin an exact version, then fork. Budget ongoing effort for the operator table, PHP-version bumps, and XML-hardening patches that upstream may never take. The codebase is small, which caps the pain, but the responsibility transfer is real and should be acknowledged in planning rather than discovered in month six. Record the fork point and upstream commit hash in the repo.
Support. No vendor SLA, no security disclosure process, no release cadence to rely on. Treat it as community source with no backstop. Security patches to libxml matter more than patches to this package, so keep the base image current; a PHP/libxml CVE is your actual exposure surface.
Scaling. Evaluation is CPU-bound, stateless, and embarrassingly parallel — it scales horizontally with queue workers and adds no datastore pressure. The constraints are per-request cost (parse dominates for large documents) and adversarial inputs: deeply nested or very large MathML is a cheap DoS vector. Enforce a byte-size cap, a nesting-depth cap, an operator-count cap, and a wall-clock timeout on every call. Cache by normalized-input hash; the hit rate for graded assessments is typically high because question stems repeat.
Failure modes to design for. Malformed or non-well-formed XML; unknown csymbol or unsupported operator (must be an explicit UnsupportedOperator error, never a silent numeric coercion); division by zero and 0^0 semantics; float overflow to INF/NAN leaking into user-visible results; stack exhaustion on pathological nesting; unbounded parse time; XXE/DTD payloads; and locale-dependent decimal formatting in the output path. Each maps to a distinct error type in your result object so the UI can say "we could not evaluate this" instead of showing NAN.
Ramp-up. The API surface is small — a competent Laravel developer is productive in a day. The real ramp is domain knowledge: Content MathML's distinction from Presentation MathML, the csymbol extension model, and the arithmetic semantics of the implemented subset. Whoever owns this should read the W3C Content MathML spec sections for the operator set you actually expose. Document the supported operator allowlist in the repo; it is simultaneously your product spec, your test matrix, and your user-facing "what can this grade" answer.
How can I help you explore Laravel packages today?