vowl-wasm
An ontology visualisation engine in Rust, compiled to WebAssembly.
It turns an OWL ontology into something a browser can draw: parse the ontology, build a typed graph from it, settle that graph with a force-directed layout, and hand the result to JavaScript — either as structured data, or as a pointer into WASM linear memory that a rendering worker reads without copying.
Attribution
This is a clean-room Rust reimplementation of the VOWL visual notation
defined by VisualDataWeb/WebVOWL
(MIT, © 2014–2019 Vincent Link, Steffen Lohmann, Eduard Marbach, Stefan Negru,
Vitalis Wiens). WebVOWL is the origin of the visual notation and of the ontology
JSON shape this crate reads; none of its JavaScript, fixtures, or assets are
vendored here. Both licence notices are carried in LICENSE.
This crate is not affiliated with or endorsed by the WebVOWL project or TIB.
Install
[]
= "0.1"
From JavaScript, via the published bundle:
Rust usage
use WebVowl;
let mut vowl = new;
vowl.load_ontology.expect;
vowl.init_simulation.expect;
vowl.run_simulation.expect;
assert_eq!;
JavaScript usage
import init from '@dreamlab-ai/vowl-wasm';
await ;
const vowl = ;
vowl.;
vowl.;
vowl.;
console.log;
For a rendering worker, NggExplorer avoids per-frame serialisation entirely:
import init from '@dreamlab-ai/vowl-wasm';
const wasm = await ;
const explorer = ;
explorer.;
// A zero-copy view over the live position buffer.
const positions = ;
while
The view is invalidated by the next loadCsr and by any WASM memory growth —
re-read positionsPtr() after either.
Public API
This is the frozen 0.1.0 surface. Names and signatures will not change without a major version bump.
WebVowl — always available
| JavaScript | Purpose |
|---|---|
new WebVowl() |
Construct an empty instance |
loadOntology(json) |
Parse the ontology and build the graph |
initSimulation() |
Seed the force simulation |
runSimulation(n) |
Advance n steps |
tick() |
Advance one step |
isFinished() |
Has the layout settled? |
getAlpha() |
Current annealing temperature |
setCenter(x, y) |
Move the layout centre |
setLinkDistance(d) |
Spring rest length |
setChargeStrength(s) |
Repulsion strength |
getNodeCount() / getEdgeCount() |
Graph size |
getStatistics() |
Degree, connected components, OWL2 metrics |
getMetadata() |
Ontology header: IRI, version, title, description |
Filtering, folding and pinning are also always available: filterByDegree,
filterHierarchy, toggleDatatypes, toggleSetOperators, resetVisibility,
getNodeDegree, pinNode, unpinNode, isPinned, resetPins,
getPinnedCount.
Feature-gated
| JavaScript | Feature |
|---|---|
new NggExplorer() — loadCsr, tick, isFinished, getAlpha, nodeCount, edgeCount, positionsPtr, positionsLen, writePositionsInto, setParam, reheat |
ngg1 |
parseMarkdownOntology(md), validateOWL2(md) |
markdown-ontology |
checkNodeClick(origin, direction) |
interaction |
getGraphData() |
debug-serde |
Features
Every optional feature is off by default. The general-purpose engine — OWL/JSON parsing, the graph model, force layout (Barnes-Hut quadtree and the CSR simulation), OWL2 validation, pinning and statistics — is always compiled.
| Feature | Default | What it adds |
|---|---|---|
ngg1 |
off | NGG1 binary tier format and the NggExplorer zero-copy binding |
markdown-ontology |
off | Markdown ontology parser and the filesystem loader built on it |
interaction |
off | Ray-sphere hit testing for click and selection |
debug-serde |
off | Legacy full-graph serde export, for diagnostics |
parallel |
off | Data-parallel ontology loading via rayon. Native only |
simd |
off | WASM SIMD128 force accumulation; needs the simd128 target feature |
Each feature compiles standalone, and the combinations are checked in CI.
The published npm bundle is built with --features ngg1,markdown-ontology,interaction,
because that is what the DreamLab corpus explorer needs. parallel, simd and
debug-serde stay off in the published bundle; build from source to enable them.
Building
# The published bundle
pkg/ is a build artefact and is not committed. CI uploads it as a workflow
artifact, and tagged releases attach it as vowl-wasm-<version>-pkg.tgz.
MSRV: 1.85.
Migrating from webvowl-wasm / @dreamlab-ai/webvowl-wasm
This crate replaces three divergent in-tree copies of webvowl-wasm. Migrating:
-
Package name.
webvowl-wasm→@dreamlab-ai/vowl-wasm. Replace anyfile:path dependency with a real semver pin. -
Generated file names change, because the crate's lib name changed from
webvowl_wasmtovowl_wasm:Before After webvowl_wasm.jsvowl_wasm.jswebvowl_wasm.d.tsvowl_wasm.d.tswebvowl_wasm_bg.wasmvowl_wasm_bg.wasmAnything that references those files by path — a bundler
optimizeDepsentry, a hand-writteninit(url)call, a CDN URL, a CSP hash — needs updating. Importing the package by name is unaffected. -
Version resets to 0.1.0. Neither of the old copies (1.0.0 and 0.3.4) described this API, so the numbering starts over. There is no implied compatibility with either.
-
Feature gates.
NggExplorer, the markdown parser andcheckNodeClickwere unconditional before and are now behindngg1,markdown-ontologyandinteraction. The published bundle enables all three, so a consumer of the npm package sees no change; a consumer building from source must ask for them. -
Layout defaults changed.
LayoutConfig::default()now carries general-purpose force constants rather than values tuned for one 1,155-node ontology. The old numbers are available asLayoutConfig::large_graph(). This affectsWebVowlonly —NggExplorerandCsrSimulationhave their own parameters and are unchanged.
Licence
MIT. See LICENSE, which carries both this project's notice and
the upstream WebVOWL notice.