elmo
ELectronics MOdeling — schematics as code
About
A text DSL for describing circuits that renders as schematics — embeddable in Markdown code fences, in the spirit of Mermaid and PlantUML.
elmo
title "555 astable"
part U1 ic "NE555" pkg=DIP-8 {
left 2:TRIG 6:THRES 7:DISCH
right 3:OUT 4:~RESET
top 8:VCC
bottom 1:GND
}
part R1 res 10k
part R2 res 47k
power VCC = U1.VCC U1.~RESET R1.1
gnd GND = U1.GND
net n_thres = U1.THRES U1.TRIG R2.2
wire U1.OUT -> R1.1The full language is specified in docs/language-spec.md (v0.1-final).
Features
- Layout & routing — elkjs places components by signal flow and routes signal nets as orthogonal wires, with junction dots where wires tee. Power and ground render as symbols and are never routed.
- ~45 iconic symbols — passives (R/C/L, ferrite, fuse, crystal, thermistor, varistor, pot, transformer), diodes (incl. zener/schottky/TVS/bridge), transistors and FETs (BJT/Darlington/IGBT/MOSFET/JFET), sources, switches, relay, antenna.
ic/connector/modare pin-labelled boxes; unknown kinds fall back to a box. - Orientation & placement —
rotate/mirror, connection-driven auto-rotation, andplace/near/grouphints. - Imports — split designs across files with namespaces; rails stay global.
- Theming —
theme dark|light|mono, else responsive to the viewer's preference. - Exports — netlist and BOM from the same source, using pass-through metadata.
- Everywhere — markdown-it and remark plugins, a browser bundle, and a CLI.
Packages
| Package | What it does |
|---|---|
@emdzej/elmo-core | Parse the DSL → IR → layout → SVG. Async render(source) entry point. |
@emdzej/elmo-markdown-it | markdown-it plugin (two-phase renderElmo) turning ```elmo fences into inline SVG |
@emdzej/elmo-remark | remark/unified plugin (async) for the MDX/Docusaurus/Astro ecosystem |
@emdzej/elmo-browser | Client-side bundle — drop elmo.min.js on a page, Mermaid-style |
@emdzej/elmo-cli | elmo command — render, check, and export netlist/BOM from .elmo files |
Usage
ts
import { render } from "@emdzej/elmo-core";
const { svg, diagnostics } = await render(source);ts
import MarkdownIt from "markdown-it";
import elmo, { renderElmo } from "@emdzej/elmo-markdown-it";
const md = new MarkdownIt().use(elmo);
const html = await renderElmo(md, markdownWithElmoFences);Split a design across files with import:
elmo
import "psu.elmo" as psu
part U2 mod "ESP32-WROOM" { left 1:GND 2:3V3 }
wire psu.U1.OUT -- U2.3V3
gnd GND = psu.U1.GND U2.GNDRoadmap
Post-v1: buses/vectors and hierarchical sub-sheets.
Current version 0.3.1. Packages publish to npm on release; the docs site with live diagrams is at elmo.emdzej.pl.
Stack: TypeScript, elkjs, pnpm + Turborepo
