Markdown Math Renderer
markdown.render_math
Overview
You send Markdown with TeX math and we return sanitized HTML with every expression typeset as SVG. We pick up $...$ and \(...\) inline, $$...$$, \[...\] and ```math fences as display, and we deliberately leave math inside code spans and code fences alone. The result always goes through a safelist sanitizer, so scripts, event handlers and dangerous URLs never reach your page. We render and sanitize — we do not evaluate math, execute LaTeX, or generate PDFs. Do not use this for plotting, Mermaid diagrams, or solving expressions. Choosing between this and markdown.render: use this one when you need the expressions on their own as SVG fragments, the result written to a file, a malformed expression to fail the call rather than degrade to source, or more than 100 expressions in one pass. For rendering a document that merely contains math, markdown.render is the better choice — it typesets with this same engine when you set components.math.mode to auto, and it adds grammars, heading anchors, a table of contents, callouts, an image manifest and a sanitizer report that this skill does not have. Accepts file input via file_ref — no need to extract file content first.
Most downstream systems cannot render TeX natively — you need a deterministic, sanitized rendering layer.
Reliability
STRICT and deterministic for identical input and renderer version when math is present. Depends on the MathJax sidecar — you may see INTERNAL_RENDERER_UNAVAILABLE, RENDERER_BUSY, RENDER_TIMEOUT, MATH_RENDERING_FAILED, TOO_MANY_MATH_EXPRESSIONS, INPUT_TOO_LARGE, UNSUPPORTED_OUTPUT_FORMAT, and SANITIZATION_FAILED. MARKDOWN_INVALID_ENCODING is not retryable unchanged: re-encode the file_ref as valid UTF-8. MARKDOWN_COMPLEXITY_LIMIT is not retryable unchanged: split or simplify a document that exceeds the fixed depth or node cap. Other input validation (not retryable): missing markdown and file_ref, invalid outputFormat or theme, or expression count above maxMathExpressions.
Context footprint
Inline input up to 200000 characters or 500000 bytes via file_ref. Output may exceed input size; results above 100000 bytes can be stored as a downloadable file. A successful call costs 5 execution credits.
When to use it
When you need one of the four things this skill does and markdown.render does not: the expressions on their own as SVG fragments without the prose around them, the result stored as a file instead of returned inline, a malformed expression failing the call outright rather than being preserved as source, or more than 100 expressions in a single document. For rendering a document that happens to contain math, markdown.render is the better default: it typesets with this same engine when components.math.mode is auto, and it adds the grammars, heading anchors, table of contents, callouts, image manifest and sanitizer report this skill has no notion of.
When you need to evaluate math, plot functions, or generate PDFs. Also when the job is really a document rather than its equations — use markdown.render; its math component defaults to auto.
Powered by MathJax for math typesetting, commonmark-java for Markdown parsing, and jsoup for HTML sanitization.
Scope
Non-goals
- Does not evaluate or solve math expressions
- Does not plot functions or generate charts
- Does not convert Markdown into LaTeX or PDF documents
- Does not execute arbitrary JavaScript or LaTeX
Properties
Capabilities
Cost & billing
Flat rate per invocation
File handling
File limits
Constraints this skill applies to your input and generated files. The “Limited by” column shows the static source of each cap; none of these can be raised by upgrading your plan.
| Limit | Value | Limited by |
|---|---|---|
| Maximum size per input file | 488.3 KiB | Skill maximum |
How we handle your data
What this means
This skill may temporarily store files or intermediate data only to complete execution. Temporary data is protected and automatically deleted.
Squillify guarantees
- Runs inside Squillify using a self-contained open-source component
- This skill runs inside Squillify.
- Payloads are not sent to an external service by this skill.
- Self contained open source component
- Temporary execution only storage
- Squillify does not permanently store submitted payloads.
- Telemetry records metadata only, not submitted content.
- Submitted payloads are not used for training.
- Submitted payloads are not reviewed by humans.
- This skill does not target sensitive data.
- The response may contain submitted or transformed content.
Your responsibility
Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.
Input schema
| Field | Type | Required | Description |
|---|---|---|---|
| markdown | string | No | The Markdown to render, up to 200000 characters. Math is recognized as $...$ or \(...\) inline and $$...$$, \[...\] or a ```math fence as display; anything inside a code span or code fence is left as code. Omit it only when you send file_ref; sending neither is invalid. If both are present, file_ref wins and the conflict is reported in metadata. |
| file_ref | string | No | A stored Markdown file (squillify://files/f-...) we read instead of inline text, up to 500000 bytes. Handy for LaTeX, since backslashes need no JSON escaping. Omit it when you send markdown — one of the two is required. |
| outputFormat | string | No | Optional. html_svg (default) and html both return one HTML document with the math inlined as SVG; svg_fragments skips the prose and returns just the rendered expressions, one entry per expression. |
| outputToFile | boolean | No | Optional. Set true to always get the result back as file_ref, download_url and size_bytes rather than inline html. Defaults to false, and we switch to a file on our own once the output passes 100000 bytes. |
| theme | string | No | Optional. squillify (default) applies the frozen Squillify Design System presentation; default, scientific-clean, compact, and dark preserve the legacy math wrappers. The value is ignored for svg_fragments. |
| sanitizeHtml | boolean | No | Optional flag recorded in the response as metadata.sanitized. It cannot switch sanitizing off: we always clean the HTML against our safelist and always clean each MathJax SVG. Defaults to true, and leaving it there keeps the flag honest. |
| allowRawHtml | boolean | No | Optional. Set true to let HTML written inside your Markdown through the parser — it still has to survive the safelist, so scripts and event handlers are dropped either way. Defaults to false, which escapes that HTML as text. |
| includeCss | boolean | No | Optional. Set false to omit the Squillify theme stylesheet and the sanitized MathJax style block when the host page already ships them. Defaults to true. |
| profile | string | No | Optional shared Markdown profile: commonmark, gfm, or squillify-safe (default). |
| errorPolicy | string | No | Optional. preserve_source (default) returns malformed TeX as source with a warning; fail rejects the whole document. |
| macros | object | No | Optional document-scoped TeX macro map. At most 64 control-word names; definitions are bounded and reset after the document. When omitted, no caller macros are defined. |
| numberEquations | boolean | No | Optional. Number display expressions in document order and resolve \label/\eqref within this document. Defaults to false. |
| includeAssistiveMathml | boolean | No | Optional. Include sanitized assistive MathML with each SVG. Defaults to true. |
| maxMathExpressions | integer | No | Optional. How many expressions a document may contain before we reject it; defaults to 1000 and is clamped down to 5000 if you ask for more. |
| timeoutMs | integer | No | Optional. Milliseconds we give the typesetter before giving up; defaults to 5000 and is clamped down to 30000 if you ask for more. |
Output schema
| Field | Type | Required | Description |
|---|---|---|---|
| format | string | Yes | The output format we applied, echoing your choice: html, html_svg or svg_fragments. |
| html | string | No | The rendered document for html and html_svg: by default, scoped Squillify Design System CSS plus an article carrying sqfy-markdown-v2 classes, with each expression inlined as SVG. Absent when the result went to a file or you asked for svg_fragments. |
| fragments | array | No | Only for svg_fragments, one object per expression in document order: index (its position, matching the warning index), type ("inline" or "display"), source (the TeX we read, without its delimiters), svg (the sanitized markup, or null when that expression failed) and error, present only on failure. Empty when the document has no math. |
| file_ref | string | No | Where we stored the rendered HTML when the result went to a file — pass it to any skill that reads a file reference. |
| download_url | string | No | A time-limited link to that same stored file, so you can fetch the HTML directly. |
| size_bytes | integer | No | How large the stored HTML is, in bytes. Present only alongside file_ref. |
| math | object | Yes | Expression, inline, display and numbered counts plus ordered warnings. |
| _meta | object | Yes | Pinned profile/parser/renderer provenance, input sizes, node count, sanitization and truncation state. |
API contract
POST /v1/executecurl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"markdown.render_math","input":{"markdown":"The formula is $x^2 + 1$."}}'import { Squillify } from "@squillify/sdk";
const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });
const { output } = await sq.execute("markdown.render_math", {"markdown":"# Hello\n\nWorld","includeCss":false});Errors
| Code | HTTP | Retryable | Description |
|---|---|---|---|
| VALIDATION_ERROR | 400 | No | The request payload failed schema validation. |
| UNAUTHORIZED | 401 | No | Missing or invalid API key. |
| SKILL_NOT_ACCESSIBLE | 403 | No | The API key is not granted access to this skill. |
| SKILL_NOT_AVAILABLE_FOR_PLAN | 403 | No | This skill is not included in your current plan. |
| PLAN_ELIGIBILITY_UNAVAILABLE | 503 | Yes | Plan eligibility could not be decided. Retry after backoff. |
| SKILL_NOT_FOUND | 404 | No | The requested skill or version does not exist. |
| TENANT_RATE_LIMITED | 429 | Yes | Request rate limit exceeded. Retry after backoff. |
| QUOTA_EXCEEDED | 429 | Yes | Plan quota exhausted. Retryable once the quota period resets. |
| EXECUTION_TIMEOUT | 504 | Yes | Execution exceeded the allowed time budget. |
| MARKDOWN_INVALID_ENCODING | 400 | No | The request payload failed this skill's input validation. |
| MARKDOWN_COMPLEXITY_LIMIT | 429 | No | A size, quota, rate, or time limit was exceeded. |
Other limits
| Limit | Value |
|---|---|
| Recommended inline bytes | 32 KiB |
Limitations
- Does not evaluate or solve math expressions
- Does not plot functions or generate charts
- Does not convert Markdown into LaTeX or PDF documents
- Does not execute arbitrary JavaScript or LaTeX
- Evaluating or solving mathematical expressions
- Generating PDF or standalone LaTeX documents
- Rendering Mermaid diagrams or data charts
- Rendering a Markdown document that happens to contain math — that is markdown.render, with components.math.mode set to auto
How to call
POST /v1/execute (requires authentication)
{
"skillKey": "markdown.render_math",
"input": {
"markdown": "# Hello\n\nWorld",
"includeCss": false
}
}Examples
Markdown heading and paragraph — no math expressions
{
"markdown": "# Hello\n\nWorld",
"includeCss": false
}{
"_meta": {
"profile": "squillify-safe",
"profileVersion": "1",
"parser": "commonmark",
"parserVersion": "0.24.0",
"renderer": "mathjax",
"rendererVersion": "4.1.2",
"theme": "squillify",
"themeVersion": "sqfy-markdown-v2",
"cssIncluded": false,
"inputChars": 14,
"inputBytes": 14,
"nodeCount": 4,
"sanitized": true,
"truncated": false
},
"format": "html_svg",
"math": {
"expressionCount": 0,
"inlineCount": 0,
"displayCount": 0,
"numberedCount": 0,
"warnings": []
},
"html": "<article class=\"sqfy-markdown sqfy-markdown-v2 sqfy-theme-squillify sqfy-markdown-math\"><h1>Hello</h1>\n<p>World</p></article>"
}Bold text with the scientific-clean theme
{
"markdown": "Plain **bold** text.",
"theme": "scientific-clean"
}{
"_meta": {
"profile": "squillify-safe",
"profileVersion": "1",
"parser": "commonmark",
"parserVersion": "0.24.0",
"renderer": "mathjax",
"rendererVersion": "4.1.2",
"theme": "scientific-clean",
"themeVersion": "legacy-math-v1",
"cssIncluded": false,
"inputChars": 20,
"inputBytes": 20,
"nodeCount": 5,
"sanitized": true,
"truncated": false
},
"format": "html_svg",
"math": {
"expressionCount": 0,
"inlineCount": 0,
"displayCount": 0,
"numberedCount": 0,
"warnings": []
},
"html": "<article class=\"sqfy-markdown-math sqfy-theme-scientific-clean\"><p>Plain <strong>bold</strong> text.</p></article>"
}Recommended use cases
- Typeset a set of expressions into standalone SVG fragments, with no prose around them
- Render math-heavy content to a stored file instead of an inline response
- Typeset more expressions in a single pass than markdown.render accepts
- Fail a pipeline outright on a malformed expression rather than degrading to source
Avoid for
- Evaluating or solving mathematical expressions
- Generating PDF or standalone LaTeX documents
- Rendering Mermaid diagrams or data charts
- Rendering a Markdown document that happens to contain math — that is markdown.render, with components.math.mode set to auto
Related skills
Composable with
Safety & privacy
- Runs without calling any external service.
- Your payloads are never stored permanently.
- Telemetry captures metadata only — never your payload contents.
- We never train models on your payloads.
- No human reviews your payloads.