Back to devlogs
Plugin · obsidian

Building S-Calc: a live calculator inside an Obsidian note

/ / 4 min read

How I built S-Calc, an Obsidian plugin that evaluates each line of an s-calc code block and prints the answer inline in your theme accent colour. The build story: the engine, live currency, the CodeMirror editor layer, and the 0.6.0 release.

S-Calc is an Obsidian plugin
On this page

S-Calc is an Obsidian plugin I shipped in a day. You write expressions inside an s-calc code block, and each line's result appears on the right of that line, in your theme accent colour, updating as you type and in reading view. It works the way Soulver and Numi do, but native to Obsidian and following your theme. Here is how it came together.

The idea

Writing notes always involves small calculations: a price minus a discount, a unit conversion, a currency amount, a date a few weeks out. The usual flow is to alt-tab to a calculator, work it out, and copy the number back. That breaks the writing and drops the context the number belongs to. Obsidian had no built-in way to do the math in the note.

So I scoped one thing: an s-calc code block that computes each line and shows the result inline, live in the editor, in the theme accent colour. I picked mathjs for the arithmetic and units, chrono-node for dates, and a free currency API for live rates.

Stripping the template

I started from a Svelte plugin template. A code-block processor needs none of Svelte, Tailwind, or shadcn, so the first job was removing them and their build steps. I rewrote the esbuild config to plain bundling and set the plugin identity. The finished plugin has two runtime dependencies.

The engine

The core is a pure evaluate(lines) function. It runs each line against a shared scope, so a label on one line and the sum/prev keywords carry down the block. Before it hands anything to mathjs, it preprocesses the parts a math library can't read directly: percentage phrases, in/to conversions, and date arithmetic. Then it evaluates with mathjs, falls back to chrono-node when a line is a date, and formats the output.

The conversions had two traps. mathjs treats in as an alias for inch, and operator precedence fought the natural phrasing, so both needed working around. I verified every example from the reference screenshot end to end before moving on.

What it covers: arithmetic with parentheses, variables and labels (write Price: 10, reuse Price later), sum and prev, percentages including reverse ones like 20% of what is 30, unit conversion like 2 kg in lb, and natural-language dates like next friday + 2 weeks and today + 90 days.

Currencies

I registered every currency the rate feed returns as a mathjs unit, including less common ones like KWD and LBP. Each gets name aliases and case variants, so 4 GBP in Euro resolves, and an alias-to-ISO map turns the answer back into a clean code. The rates come from open.er-api.com, a free endpoint with no key, fetched once per session. So 50 KWD in LBP works alongside the arithmetic.

The UI

The live-while-typing part is a CodeMirror 6 view plugin. It finds the s-calc fences, evaluates each block, and paints a right-aligned result widget per line. A separate reading-view code-block processor renders the same results in the finished note. When the currency rates finish loading, currency lines recompute so they aren't left blank.

Styling reads Obsidian's own theme variables, so results use --text-accent and match light and dark mode with no rebuild. Blank lines and lines starting with # or // are ignored.

Releasing

Obsidian requires the release tag to equal the manifest version with no v prefix, so I bumped to a matching tag and attached main.js, manifest.json, and styles.css. I switched the licence to MIT and shipped 0.6.0, then submitted it to the community marketplace, where it is now listed. The engine has an assert-based self-check covering arithmetic, unit conversion, percentages, and variables.

Open items

The marketplace scan flagged a few warnings worth clearing: any-typed calls at the mathjs boundary, the node:assert import in the dev-only self-check, and missing release-artifact attestations. None break the plugin, but they're on the list.

Frequently asked questions

How do I use S-Calc? Add a code block with the language s-calc and write one expression per line. Each line's result shows on the right, live as you type and in reading view. Blank lines and lines starting with # or // are ignored.

What can it calculate? Arithmetic with parentheses, variables and labels, running totals with sum and prev, percentages including reverse ones like 20% of what is 30, unit conversion such as 2 kg in lb, live currency like 50 KWD in LBP, and natural-language dates like today + 90 days.

Where does the currency rate come from? It fetches USD-based rates once per session from open.er-api.com, a free endpoint with no key. Every currency the feed returns is registered, including less common ones like KWD and LBP, and you can reference them by ISO code or common name.

Is it on the Obsidian marketplace? Yes. It is listed in the community plugin marketplace as s-calc, currently at 0.6.0, and the source is on GitHub under the MIT licence.

Does it work while I'm typing? Yes. A CodeMirror 6 editor extension recomputes and repaints results as you edit, and a separate reading-view renderer shows them in the rendered note.

FAQ

Frequently asked

Add a code block with the language s-calc and write one expression per line. Each line's result shows on the right, live as you type and in reading view. Blank lines and lines starting with # or // are ignored.

Arithmetic with parentheses, variables and labels, running totals with sum and prev, percentages including reverse ones like 20% of what is 30, unit conversion such as 2 kg in lb, live currency like 50 KWD in LBP, and natural-language dates like today + 90 days.

It fetches USD-based rates once per session from open.er-api.com, a free endpoint with no key. Every currency the feed returns is registered, including less common ones like KWD and LBP, and you can reference them by ISO code or common name.

Yes. It is listed in the community plugin marketplace as s-calc, currently at version 0.6.0, and the source is on GitHub under the MIT licence.

Yes. A CodeMirror 6 editor extension recomputes and repaints results as you edit, and a separate reading-view renderer shows them in the rendered note.

Following along? Let's talk.

Start a conversation →