1. Introduction
Contents of DISL 0.2
DISL (Diagram Specification Language) is a declarative, JSON-based language in which a tool engineer specifies a diagram type — not individual diagrams, but the kind of diagram people can draw, and everything a runtime needs in order to support it:
- what can appear in a diagram: element types, their attributes, containment and relationships (metamodel);
- where things can be placed: coordinate systems whose axes may be numeric, temporal (dates and timestamps) or categorical, how element positions relate to model data, and the snapping rules that make positions discrete on one axis, the other, or both (coordinates);
- how everything looks: shapes from elementary primitives to finely parameterised paths and composites, labels, compartments, embedded form widgets, and edges with arbitrary line styles, arrowheads and labels at their start, middle and end (notation);
- which tools users get: toolbox groups, context tools, templates and property forms (toolbox and forms);
- what is allowed: rules written in CEL, with severities, messages, quick fixes and the choice between preventing a gesture and reporting a finding afterwards (constraints);
- what happens when users act: hooks and operations (behavior);
- how diagrams are arranged automatically (layout);
- and how a diagram is stored: format, identifiers, file split, ordering, precision, migrations and collaboration (persistence). The stored diagrams themselves are DID definitions, specified by DID, the Diagram Definition Language (DID-specification.md).
A single DISL file — a specification — is a complete, portable, machine-validated description of a diagram type: a visual language and how it is worked with. Every aspect of it may carry human-readable documentation, so a specification doubles as the reference manual of its language and as the source of help texts inside the runtime.
DISL sits between the tool engineers who specify a diagram type and the software that lets others use it.
Diagram as text (Mermaid)
flowchart TB
accTitle: How DISL is intended to be used
accDescr: A tool engineer writes a DISL specification. A runtime loads the specification, and the specification also feeds docs and code generators, CI validators, format converters and AI context. The runtime reads and writes DID definitions, the diagrams users draw.
engineer["<b>Tool engineer</b><br/>domain expert, tool builder,<br/>standards body, AI assistant"]
specification["<b>DISL specification</b><br/>my-lang.dis<br/>checked by JSON Schema<br/>+ CEL type checker"]
runtime["<b>Runtime</b><br/>web, desktop, IDE, headless<br/>toolbox, canvas, forms,<br/>snapping, rules, save"]
consumers["Docs & code generators,<br/>CI validators, format<br/>converters, AI context"]
definitions["<b>DID definitions</b><br/>the diagrams users draw,<br/>deterministic, versioned, migrated"]
engineer -- writes --> specification
specification -- loads --> runtime
specification -- feeds --> consumers
runtime -- reads / writes --> definitionsA typical workflow:
- Write a specification. A tool engineer writes
my-lang.disby hand with IDE support from the JSON Schema (validation, completion, hover help), or generates it from an existing source such as a class model, an ontology or an older tool configuration. Specifications can import shared libraries of shapes, markers, styles and types (section 3.3). - Validate it. A validator checks the specification against the JSON Schema, resolves names and imports, flattens inheritance, and type-checks every CEL expression in the context in which it will be evaluated (section 12). Errors and warnings are reported with the JSON Pointer of the offending node.
- Load it into a runtime. A conforming runtime needs no language-specific code: palette, canvas, rendering, snapping, property forms, validation and saving all come from the specification. Whatever the declarative core cannot express is delegated to named, versioned plugins (section 13) rather than to embedded scripts.
- Draw. End users create diagrams of the type, stored as DID definitions, that conform to the specification. The runtime surfaces the specification's documentation as tooltips, field help, explanations of findings and a help view, so users learn the language while using it.
- Persist and evolve. DID definitions are written exactly as the persistence layer prescribes, so they are deterministic, diff-friendly and readable by any other conforming runtime. When the language evolves, declared migrations upgrade old DID definitions automatically.
The same specification serves other consumers too:
- documentation generators that render a language reference with rendered samples of every shape;
- code generators that produce typed APIs, database schemas or JSON Schemas for DID definitions;
- headless validators in CI pipelines that check DID definitions without drawing them;
- converters to and from other formats (BPMN DI, draw.io, Ecore, SVG, PlantUML);
- AI assistants that read the specification to understand what a diagram may contain, which rules apply and how to produce a valid DID definition.
| Reader | Most relevant sections |
|---|---|
| Tool engineers | 1–11, 17, Appendix B |
| Runtime implementers | All, especially 5, 6, 12, 14, 15; DID |
| Converter and generator makers | 3, 4, 11, 12, Appendix A, DID |
| Reviewers and standards bodies | 1, 14–16, Appendix D |
- Declarative first, escape hatches second. The common 90 % of diagram types must be expressible without code. The remaining 10 % is reached through named plugins with declared parameters, never through embedded general-purpose scripts.
- Layered separation of concerns. Each layer answers one question and can be read, reviewed, reused and replaced independently. Meaning (metamodel) is strictly separated from appearance (notation) and from placement (view data).
- One expression language. Every dynamic value — label text, visibility, conditional styles, geometry of custom shapes, marker choice, constraint rules, default values, snapping functions, placement bindings — is a CEL expression. CEL is side-effect free, non-Turing-complete, guaranteed to terminate, statically typable, and has mature implementations in Go, Java, C++, JavaScript/TypeScript, Python, Rust and .NET.
- Self-describing. Every object may carry a
doc. Documentation is part of the language, not an afterthought, and runtimes are expected to show it to users. - Domain-true coordinates. Positions are stored in the units of their axis — pixels, millimetres, timestamps, category identifiers — never only in screen pixels, so stored diagrams keep their meaning when zoom level, scale or renderer change.
- Deterministic persistence. Two conforming runtimes saving the same diagram with the same specification MUST produce byte-identical output.
- Extensible without forking. Vendor extensions live under
x-keys and plugin names; unknown extensions are ignored, never fatal, and are preserved on round trips. - Progressive complexity. Every construct has a shorthand for the simple case (
"shape": "ellipse") and a full object form for fine control ("shape": {"type": "ellipse", "params": {...}}). A usable diagram type needs fewer than fifty lines of DISL.
- DISL is not a general-purpose UI framework. It specifies diagram types, including forms embedded in diagram elements and property inspectors, but not arbitrary application screens.
- DISL does not prescribe a rendering technology. SVG, Canvas 2D, WebGL, native toolkits and print pipelines are all valid targets.
- DISL does not define execution or simulation semantics of the modelled language (for example, how a state machine runs). Such information MAY be carried in extensions. A specification MAY play a simulated run of its own, stepwise and outside the model's history (9.6); DISL defines how such a run is declared and played, not what the modelled language means.
- DID definitions are not a lingua franca for unrelated software; a DID definition is always interpreted relative to its specification.
DISL deliberately borrows proven ideas:
| Source | Idea adopted |
|---|---|
| Eclipse Sirius, GMF | Split into model, graphical, tooling and mapping definitions; viewpoints |
| MetaEdit+ (GOPPRR) | Small, closed meta-metamodel of objects, relationships, ports and properties |
| OMG Diagram Definition, BPMN DI | Strict separation of semantic model and diagram interchange data |
| GLSP, Sprotty | Runtime-agnostic, client/server-friendly diagram description |
| SVG, CSS | Paint, stroke, dash, marker and text vocabulary; cascading styles and states |
| draw.io / mxGraph | Parameter handles on shapes; jump-overs; rich marker catalogue |
| Vega-Lite, D3 scales | Axes as scales from domain values (numbers, time, categories) to screen space |
| ELK | Layout algorithm catalogue and option pass-through |
| CEL, Kubernetes validation rules | Safe, typed expressions for validation and computed values |
| JSON Schema | Machine-checkable structure and IDE tooling |
| Yjs, Automerge | CRDT-based collaboration hooks |