lispgram
v0.6.2
Published
A lispy surface language compiler and SVG visualizer for NCF diagrams.
Maintainers
Readme
lispgram
lispgram is a small JavaScript package that gives you:
- a user-facing lispy surface language
- a compiler from that surface language into NCF
- a lightweight SVG visualizer that can render either Lispgram source or raw NCF
NCF stays the internal representation. Author-facing source compiles into:
(cy
(nodes ...)
(edges ...))Supported surface forms
; initialize a node
(P)
; initialize a node with a label
(P{hi})
; parent/child relationships
(X Y Z)
(X Y (Z P))
(X (Y (Z P)))
; arrows
(-> e A B)
(-> e{hi} A B)
; fan-out
(-> e A [B C D])
; fan-in
(-> e [A B C] D)What this starter implements
- nodes with optional
{label}suffixes - parent/child trees compiled to
(@parent X) - arrows compiled as NCF arrow carrier nodes with:
(@class "arrow")(@class "arrowFrom")(@class "arrowTo")
- fan-in / fan-out expansion to
edgeId_1,edgeId_2, ... - raw NCF passthrough
- browser auto-initialization for
<pre class="lispgram">...</pre>blocks - heuristic SVG routing for parallel, anti-parallel, and higher-order arrows
- compound/container labels rendered only in the header band
Install
npm install lispgramBrowser usage
<pre class="lispgram">
(Y X)
(-> f A B)
(-> g B A)
(-> h X Y)
</pre>
<script type="module">
import lispgram from "lispgram";
lispgram.initialize({
startOnLoad: true,
showArrowGlyphs: true,
clickToFocus: true
});
</script>Library usage
import lispgram from "lispgram";
const source = `
(Y X)
(-> f A B)
(-> g B A)
(-> h X Y)
`;
const ncfString = lispgram.toNCF(source);
const ncfDoc = lispgram.toNCFDoc(source);Render into a DOM node:
import { render } from "lispgram";
render(document.querySelector("#app"), `
(P A B)
(-> left A B)
(-> right B A)
`);API
parseDocument(source)
Parses Lispgram surface syntax into an AST.
compileLispgram(source)
Returns:
{
ast,
doc
}where doc is the normalized NCF JS object.
toNCFDoc(source)
Compiles Lispgram source to an NCF document object. If the input is already raw NCF, it is parsed and returned.
toNCF(source)
Compiles Lispgram source into an NCF string.
parseNCF(source)
Parses raw NCF.
emitNCFDoc(doc)
Serializes an NCF doc object back to text.
render(target, source, options?)
Renders Lispgram or NCF into an SVG inside target.
initialize(options?)
Finds matching elements and auto-renders them.
Options:
{
selector: ".lispgram",
startOnLoad: true,
showNCF: false,
showArrowGlyphs: false,
clickToFocus: true,
arrowGlyphRadius: 5.75,
width: "100%",
height: 480
}Per-diagram overrides are also available with data attributes:
<pre class="lispgram"
data-lispgram-arrow-glyphs="true"
data-lispgram-click-focus="true"
data-lispgram-arrow-glyph-radius="6.5">
(-> f A B)
</pre>Notes
This package is intentionally small and readable. It is a good base for:
- improving the layout engine
- extending the surface language
- adding richer styling directives
- expanding support for higher-order arrows and editor UX
Dev visualizer
The package now includes a browser-based dev tool with Lispgram + raw NCF input, compiled/normalized NCF output, orthogonal routing, wiring overlay, arrow-node glyphs, click focus, zoom, and fit-to-view.
Run it from the repo with:
npm run dev:visualizerThen open:
http://localhost:4173/examples/devtool.htmlThe dev tool accepts either Lispgram surface syntax or raw NCF. When the input is Lispgram, it compiles it to NCF first and shows the normalized NCF in the side panel.
It can also run as a standalone static page. examples/devtool.html now auto-loads the local ../src/index.js module when it is available and otherwise falls back to:
https://unpkg.com/lispgram/src/index.jsThat means you can open the file directly, host it from any static site, or copy examples/devtool-standalone.html by itself and still use the package from unpkg.
Optional query param overrides:
?module=localforces the local repo module?module=unpkgforces the unpkg module
Development
npm testFocus behavior
When clickToFocus is enabled, clicking a node, compound, edge path, edge label, or arrow glyph focuses that element within its own diagram. clickToFocus defaults to true; set data-lispgram-click-focus="false" or pass clickToFocus: false to disable it.
Demo
go to repo root directory
python -m http.servernavigate to examples/basic.html in browser
Browser script Drop-in use
<pre class="lispgram">
(lispgram
(A)
(-> e X Y)
)
</pre>
<script type="module">
import lispgram from "https://unpkg.com/lispgram/src/index.js";
lispgram.initialize({
startOnLoad: true,
showArrowGlyphs: true,
clickToFocus: true,
arrowGlyphRadius: 5.75
});
</script>