Renderers#
A renderer decides what a calculation looks like. handcalcs parses your code once, and the renderer turns the parsed calculation into Markdown, LaTeX, HTML, plain text, an Excel workbook, a Word document, or anything else you write a renderer for.
Choosing a renderer#
Renderer |
Name |
Produces |
Use it for |
|---|---|---|---|
|
Markdown text with |
Jupyter (the default), MyST/Sphinx, Quarto, any Markdown + MathJax/KaTeX site |
|
|
A LaTeX fragment |
|
|
|
An HTML fragment with a scoped stylesheet, no math engine needed |
Web apps, emails, HTML reports, Jupyter |
|
|
Unicode text |
Terminals, logs, test snapshots, plain-text reports |
|
|
A live |
Handing a calculation to someone who works in Excel |
|
|
A |
Reports in Word (or Google Docs), from a script or a notebook |
|
|
A nested Python list |
Building your own renderer, debugging |
Using one#
Every renderer is a class in handcalcs.renderers. Pass an instance to an interface:
from handcalcs import HandCalcs
from handcalcs.renderers import HTMLRenderer
html = HandCalcs(renderer=HTMLRenderer())(source)
In Jupyter, choose by name:
%hc_default_renderer html
Or set the default for each interface in the configuration:
default_renderer for a bare HandCalcs() and @handcalc() (default ascii), jupyter_renderer for %%render.
The same calculation, five ways#
Roots
# Roots
$$\begin{aligned} a &= 2 \; &b &= -7 \; &c_{0} &= 3 \; \end{aligned}$$
$$\begin{aligned} x_{1} &= \frac{-b + \sqrt{b^{2} - 4 \cdot a \cdot c_{0}}}{2 \cdot a} = \frac{-\left(-7\right) + \sqrt{\left(-7\right)^{2} - 4 \cdot 2 \cdot 3}}{2 \cdot 2} = 3 \\ &\quad\text{(Larger root)} \end{aligned}$$
Roots
| a | = | 2 | b | = | -7 | c0 | = | 3 |
<div class="handcalcs"><style>.handcalcs{--hc-accent:#0B5F66;--hc-accent-dark:#91CFD4;--hc-guide-1:#85B8BD;--hc-guide-2:#D5B386;--hc-guide-3:#A8B0C7;}:is([data-jp-theme-light="false"],.vscode-dark,.vscode-high-contrast,[data-theme="dark"]) .handcalcs{--hc-accent-text:var(--hc-accent-dark);--hc-tint:color-mix(in srgb,var(--hc-accent) 30%,transparent);--hc-highlight:color-mix(in srgb,var(--hc-accent) 38%,transparent);}.handcalcs{--hc-gap:0.35em;--hc-indent:1.5em;--hc-param-gap:2em;--hc-eq-gap:0.3em;--hc-accent-text:var(--hc-accent);--hc-tint:color-mix(in srgb,var(--hc-accent) 9%,transparent);--hc-highlight:color-mix(in srgb,var(--hc-accent) 12%,transparent);--hc-muted:color-mix(in srgb,currentColor 60%,transparent);--hc-chip:color-mix(in srgb,currentColor 6%,transparent);display:flex;flex-direction:column;gap:var(--hc-gap);line-height:1.6;font-variant-numeric:tabular-nums;}.handcalcs :where(.hc-block,.hc-body){display:flex;flex-direction:column;gap:var(--hc-gap);}.handcalcs :where(.hc-body){margin-inline-start:0.55em;padding-inline-start:calc(var(--hc-indent) - 0.55em);border-inline-start:2px solid var(--hc-guide);--hc-guide:var(--hc-guide-1);}.handcalcs :where(.hc-body .hc-body){--hc-guide:var(--hc-guide-2);}.handcalcs :where(.hc-body .hc-body .hc-body){--hc-guide:var(--hc-guide-3);}.handcalcs :where(.hc-body .hc-body .hc-body .hc-body){--hc-guide:var(--hc-guide-1);}.handcalcs :where(.hc-body .hc-body .hc-body .hc-body .hc-body){--hc-guide:var(--hc-guide-2);}.handcalcs :where(.hc-line,.hc-header,.hc-comment){margin-block:0;}.handcalcs :where(.hc-header){background:var(--hc-tint);border-radius:4px;padding:0.1em 0.5em;}.handcalcs :where(.hc-header)::before{content:"\25B8";color:var(--hc-accent-text);margin-inline-end:0.4em;}.handcalcs :where(.hc-kw){color:var(--hc-accent-text);}.handcalcs :where(.hc-result){color:var(--hc-accent-text);background:var(--hc-highlight);font-weight:600;padding:0 0.25em;border-radius:3px;-webkit-box-decoration-break:clone;box-decoration-break:clone;}.handcalcs :where(.hc-note){color:var(--hc-muted);}.handcalcs :where(.hc-check){font-weight:700;}.handcalcs :where(.hc-pass){color:#1A7F37;}.handcalcs :where(.hc-fail){color:#CF222E;}.handcalcs :where(.hc-import){align-self:start;font-family:var(--jp-code-font-family,ui-monospace,SFMono-Regular,Menlo,Consolas,monospace);font-size:0.85em;color:var(--hc-muted);background:var(--hc-chip);padding:0.05em 0.5em;border-radius:3px;}.handcalcs :where(.hc-comment,.hc-note) :where(code){font-size:0.9em;background:var(--hc-chip);padding:0 0.25em;border-radius:3px;}.handcalcs table.hc-params{margin:0;border:0;border-collapse:separate;border-spacing:0;table-layout:auto;width:auto;align-self:center;font-size:inherit;color:inherit;font-variant-numeric:tabular-nums;background:var(--hc-tint);border-radius:4px;padding:0.1em 0.6em;}.handcalcs table.hc-params.hc-multiline{align-self:start;background:none;border-radius:0;padding:0 0 0 0.5em;border-inline-start:2px solid var(--hc-accent-text);}.handcalcs table.hc-params tr:nth-child(n){background:none;}.handcalcs table.hc-params td{padding:0;border:0;vertical-align:baseline;line-height:inherit;white-space:normal;max-width:none;}.handcalcs table.hc-params td.hc-param-id{text-align:right;padding-inline-end:var(--hc-eq-gap);}.handcalcs table.hc-params td.hc-param-eq{text-align:center;}.handcalcs table.hc-params td.hc-param-val{text-align:left;padding-inline-start:var(--hc-eq-gap);}.handcalcs table.hc-params td.hc-param-gap{width:var(--hc-param-gap);}.handcalcs table.hc-params td.hc-param-comment{text-align:left;padding-inline-start:var(--hc-eq-gap);}.handcalcs :where(.hc-pre){white-space:pre;}.handcalcs :where(.hc-matrix){display:inline-table;vertical-align:middle;border-inline:1px solid currentColor;border-radius:0.2em;padding:0 0.15em;}.handcalcs :where(.hc-matrix-row){display:table-row;}.handcalcs :where(.hc-matrix-cell){display:table-cell;text-align:right;padding:0 0.3em;line-height:1.2;}</style><h1>Roots</h1><table class="hc-params"><tr><td class="hc-param-id">a</td><td class="hc-param-eq">=</td><td class="hc-param-val">2</td><td class="hc-param-comment"></td><td class="hc-param-gap"></td><td class="hc-param-id">b</td><td class="hc-param-eq">=</td><td class="hc-param-val">-7</td><td class="hc-param-comment"></td><td class="hc-param-gap"></td><td class="hc-param-id">c<sub>0</sub></td><td class="hc-param-eq">=</td><td class="hc-param-val">3</td><td class="hc-param-comment"></td></tr></table><div class="hc-line">x<sub>1</sub> = (-b + √(b<sup>2</sup> - 4 · a · c<sub>0</sub>)) / (2 · a) = (-(-7) + √((-7)<sup>2</sup> - 4 · 2 · 3)) / (2 · 2) = <span class="hc-result">3</span> <span class="hc-note">(Larger root)</span></div></div>
Roots
\section*{Roots}
\medskip
\noindent$\displaystyle
\begin{aligned}[t]
a &= 2 \; &b &= -7 \; &c_{0} &= 3 \;
\end{aligned}$
\medskip
\medskip
\noindent$\displaystyle
\begin{aligned}[t]
x_{1} &= \frac{-b + \sqrt{b^{2} - 4 \cdot a \cdot c_{0}}}{2 \cdot a} = \frac{-\left(-7\right) + \sqrt{\left(-7\right)^{2} - 4 \cdot 2 \cdot 3}}{2 \cdot 2} = 3 \\
&\quad\text{(Larger root)}
\end{aligned}$
\medskip
=====
Roots
=====
a = 2 b = -7 c_0 = 3
x_1 = (-b + √(b² - 4 * a * c_0)) / (2 * a) = (-(-7) + √((-7)² - 4 * 2 * 3)) / (2 * 2) = 3 (Larger root)
['# Roots',
'a = 2 b = -7 c_0 = 3',
['',
[['x_1',
'=',
'(-b + sqrt(b ** 2 - 4 * a * c_0)) / (2 * a)',
'=',
'(-(-7) + sqrt((-7) ** 2 - 4 * 2 * 3)) / (2 * 2)',
'=',
'3',
'(Larger root)']]]]
The source for all five:
## Roots
a = 2; b = -7; c_0 = 3
x_1 = (-b + sqrt(b**2 - 4*a*c_0)) / (2*a) # Larger root
Going further#
Change how a built-in renderer looks: Customizing a renderer.
Write a renderer for a new format: Building a renderer.