@wiremark/core
v0.1.0
Published
Core parser, layout engine, and hand-drawn SVG renderer for the wiremark wireframe DSL. Pure JS, no host dependencies.
Downloads
313
Maintainers
Readme
Wiremark Core
wiremark is a text-based, markdown-embeddable wireframing format — think
"YAML-flavored, MUI-inspired": a hierarchy of familiar
component names, indented to show containment, rendered as a hand-drawn
(Balsamiq-style) SVG. A wireframe lives inside a fenced ```wireframe block:
```wireframe
Wireframe mobile
Stack column gap=2
Typography h4 "Sign in"
TextField "Email"
TextField "Password"
Button "Sign in" contained to=#dashboard
```@wiremark/core is the engine behind that block: the parser, layout solver,
and SVG renderer, in pure JavaScript.
Full language documentation — guides, the component reference, and the icon gallery — lives at docs.wiremark.dev.
Do you need this package?
wiremark is normally used through a host tool that finds the ```wireframe
block for you. The first of these is
@wiremark/cli, which renders
.wiremark files to SVG from the command line; adapters for specific tools
(markdown renderers, editors, and more) are forthcoming, and we'll keep adding
them as best we can.
Use @wiremark/core directly when you want to add wiremark to your own
markdown renderer, editor, or pipeline. Core knows nothing about markdown:
your adapter finds the fenced block, hands the text inside it to core, and
gets back an SVG. The CLI is a worked example of exactly that — its
source
is a thin wrapper over this package.
Install
npm install @wiremark/coreUsage
import { render } from '@wiremark/core';
const { svg, diagnostics } = render(source); // source = the text inside the fencerender takes wiremark source and returns the SVG as a string. Structural
problems the author must fix (tabs in indentation, unknown components,
unquoted text) throw a WiremarkError; anything softer (an unknown icon name,
a missing link target) degrades gracefully and is reported in diagnostics.
The other entry points:
import { parse, toFlowGraph, toMermaid } from '@wiremark/core';
const doc = parse(source); // validated document: frames + diagnostics
const graph = toFlowGraph(doc); // navigation graph inferred from to=#id links
const mermaid = toMermaid(doc); // the same graph, as a Mermaid flowchartrender also accepts an already-parsed document, and a file with several
frames renders as a flow chart with frame-to-frame connectors.
For dark-mode hosts, pass theme: render(source, { theme: 'dark' })
switches the whole palette (strokes, paper, fills) while geometry and the
hand-drawn look stay identical. The default is 'light', and any unrecognized
value falls back to it — never an error. The dark background is opaque;
embedders that want a seamless surround should match the dark paper color,
#1e2127.
Icon props accept built-in Material icon names
out of the box. To add your own, pass icons (a flat name-to-SVG map or
Iconify icon packs) or a loadIcon callback in the options to render/parse
— see the icons guide.
For editor and tooling hosts, pass interactive: true. It wraps each rendered
element (and frame) in a <g> tagged with data-wm-line — the element's line in
the wiremark source — plus data-wm-id and data-wm-component where they apply.
Nothing is injected into the SVG and nothing runs; it stays inert markup. Your host
attaches its own click listener and reads the attributes back:
const { svg } = render(source, { interactive: true });
container.innerHTML = svg;
container.querySelector('svg').addEventListener('click', (e) => {
const g = e.target.closest('[data-wm-line]'); // innermost element under the cursor
if (!g) return;
onPick({
line: Number(g.dataset.wmLine),
id: g.dataset.wmId ?? null,
component: g.dataset.wmComponent ?? null,
});
});The default is off, so output is byte-for-byte identical when you don't pass it. In
interactive mode a to= link is exposed as data-wm-to instead of a live <a>, so
your click handling isn't competing with in-page fragment navigation.
Browser bundle
The package also ships a self-contained, dependency-free IIFE build for
script-tag and webview embedders (IDE preview panels, browser extensions),
exposing the same API as a wiremark global:
<script src="wiremark.browser.js"></script>
<script>
const { svg, diagnostics } = wiremark.render(source);
</script>From Node tooling, resolve its path with
require.resolve('@wiremark/core/browser') (it lives at
dist/wiremark.browser.js inside the package). It needs no DOM — rendering is
pure string-in, string-out.
Good to know
- Pure ESM, Node >= 18.
- One runtime dependency (roughjs, for the hand-drawn look).
- Deterministic output: the same source always renders the same SVG, so it's diff- and cache-friendly.
