3. Specification structure, layers and viewpoints
Contents of DISL 0.1
| Property | Type | Req. | Layer | Description |
|---|---|---|---|---|
$schema |
string | – | – | URI of the DISL JSON Schema. |
disl |
string | ✓ | – | Targeted DISL version, "0.1". |
language |
Language | ✓ | – | Identity, version, locales and limits (3.2). |
imports |
Import[] | – | – | Reused specifications and libraries (3.3). |
functions |
map → Function | – | – | Reusable CEL functions (3.4). |
metamodel |
Metamodel | ✓ | 1 | What can exist (section 4). |
coordinates |
Coordinates | – | 2 | Axes, coordinate systems, snapping (section 5). Default: one free cartesian pixel system without snapping. |
notation |
Notation | – | 3 | How things look (section 6). Default: every node a labelled rectangle, every relation a straight line with an arrow. |
toolbox |
Toolbox | – | 4 | Palette and context tools (7.1–7.4). Default: one tool per concrete type. |
forms |
map → Form | – | 4 | Property and embedded forms (7.5). Default: generated from attributes. |
constraints |
Constraints | – | 5 | Rules (section 8). |
behavior |
Behavior | – | 6 | Hooks, operations, deletion and clipboard policy (section 9). |
layout |
Layout | – | 7 | Automatic layout (section 10). Default: none. |
persistence |
Persistence | – | 8 | Storage (section 11). Default: single JSON file, UUIDv7 ids. |
viewpoints |
map → Viewpoint | – | – | Several diagram kinds over one model (3.5). |
plugins |
map → Plugin | – | – | Declared extensions (section 13). |
doc |
Doc | – | – | Documentation of the language as a whole. |
x-* |
any | – | – | Extensions. |
Only disl, language and metamodel are required. Every other layer has a documented default, so specifications can start tiny and grow.
{
"disl": "0.1",
"language": { "id": "org.example.mindmap", "version": "0.1.0", "label": "Mind map" },
"metamodel": {
"types": { "Idea": { "attributes": { "text": { "type": "string", "required": true } } } },
"relations": { "Branch": { "source": "Idea", "target": "Idea" } }
}
}
This five-line language already yields a usable diagram type: a palette with an Idea tool and a Branch tool, rectangles labelled with text (the first string attribute is the default label), arrows, a generated property form, and JSON persistence.
| Property | Type | Req. | Description |
|---|---|---|---|
id |
qualified identifier | ✓ | Globally unique language id; reverse-DNS style is RECOMMENDED. Recorded in every DID definition. |
version |
SemVer string | ✓ | Version of this language. |
label |
LocalizedText | – | Display name ("State machine"). |
doc |
Doc | – | Language documentation, shown in the runtime's help view. |
defaultLocale |
BCP 47 tag | – | Default "en". |
locales |
string[] | – | Locales for which all LocalizedTexts SHOULD provide translations; validators MAY warn about gaps. |
authors |
{name, email, url}[] |
– | Maintainers (tool engineers). |
license |
SPDX expression | – | License of the specification. |
homepage |
URI | – | Project page. |
icon |
IconRef | – | Icon of the language (file type icon, window title). |
fileExtension |
string | – | Preferred extension of stored diagrams without dot, for example "sm.json". |
limits |
object | – | celCost (per-expression cost limit), maxElements (soft limit, runtimes SHOULD warn beyond it), maxDocumentBytes. |
requires |
object | – | conformance: minimum runtime conformance level ("core", "standard", "full"); features: list of optional feature ids (Appendix B.8) the specification relies on. |
Specifications may import other specifications or libraries — specifications that contain only notation, forms, functions or data types and whose metamodel may be empty.
| Property | Type | Req. | Description |
|---|---|---|---|
from |
URI or relative path | ✓ | Location of the imported specification. |
as |
simple identifier | ✓ | Alias; imported names are referenced as alias.Name. |
version |
SemVer range | – | Acceptable versions of the imported language (for example "^2.1.0"). |
integrity |
string | – | Subresource-integrity hash ("sha256-…"). Runtimes MUST verify it when present and SHOULD require it for remote URIs. |
include |
string[] | – | Layers to import: any of "metamodel", "notation", "forms", "functions", "constraints", "toolbox". Default: all. |
doc |
Doc | – | Why the import exists. |
Imported types may be extended ("extends": "base.Element"), imported styles, shapes and markers referenced, and imported constraints are active unless the import lists include without "constraints". Import cycles are a specification error. Names are never merged implicitly: a local State and lib.State are different types.
The DISL standard library is always available under the reserved alias std without an import (Appendix B): std.roundedRect, std.arrowFilled, std.grid10, and so on. Built-in names MAY also be referenced without the std. prefix when no local name shadows them.
User-defined functions make repeated CEL logic reusable and documented.
{
"functions": {
"displayName": {
"params": [{ "name": "e", "type": "Element" }],
"returns": "string",
"cel": "has(e.name) && e.name != '' ? e.name : e.type + ' ' + e.id.substring(0, 4)",
"doc": "The human-readable name of an element, falling back to type and short id."
},
"workingDaysBetween": {
"params": [{ "name": "a", "type": "timestamp" }, { "name": "b", "type": "timestamp" }],
"returns": "int",
"cel": "workingDays(a, b, 'project')"
}
}
}
| Property | Type | Req. | Description |
|---|---|---|---|
params |
{name, type, doc}[] |
✓ | Positional parameters; type is a CEL type name or a metamodel type name. |
returns |
string | ✓ | CEL result type. |
cel |
string | ✓ | Body; may reference parameters, globally available variables of the calling context are not visible (functions are pure over their parameters, plus diagram and env when declared in uses). |
uses |
string[] | – | Context variables the function may read: "diagram", "env". |
doc |
Doc | – | Documentation. |
Functions are called as displayName(self). A function MAY call functions declared before it in the specification order; recursion (direct or indirect) is a specification error. This preserves CEL's termination guarantee.
A language may offer several diagram kinds over the same model — for example a structure diagram and a timeline of the same project. Each viewpoint selects which types appear, which coordinate system and layout apply, and which toolbox groups are offered. If viewpoints is absent, a single implicit viewpoint main shows everything.
| Property | Type | Description |
|---|---|---|
label, doc, icon |
Display name, documentation, icon. | |
coordinateSystem |
name | Coordinate system of diagrams of this kind (section 5). |
include |
TypeRef[] | Types shown. Default: all. |
exclude |
TypeRef[] | Types hidden. |
toolbox |
string[] | Toolbox group ids offered. Default: all groups. |
layout |
name or LayoutConfig | Layout used (section 10). |
notation |
object | Per-viewpoint notation overrides: nodes, edges, styles maps merged over the global notation. |
canvas |
Canvas | Background, bounds and page settings (6.13). |
default |
boolean | The viewpoint used for new diagrams. Exactly one viewpoint SHOULD be default. |
Elements appear in a view only if their type is included; model elements not shown in any view still exist in the model and are still validated.
Diagram as text (Mermaid)
---
config:
flowchart:
wrappingWidth: 400
rankSpacing: 12
---
flowchart TB
accTitle: Layer overview
accDescr: The eight DISL layers from top to bottom. Layer 1, metamodel, says what exists. Layer 2, coordinates, where it can be. Layer 3, notation, how it looks. Layer 4, toolbox and forms, how it is created and edited. Layer 5, constraints, what is allowed. Layer 6, behavior, what happens. Layer 7, layout, how it is arranged. Layer 8, persistence, how it is stored. Cutting across all layers are doc on everything, CEL everywhere, functions, plugins and viewpoints.
L1["<b>Layer 1 · metamodel</b><br/>types · relations · attributes<br/><i>what exists</i>"]
L2["<b>Layer 2 · coordinates</b><br/>axes · systems · placement · snap<br/><i>where it can be</i>"]
L3["<b>Layer 3 · notation</b><br/>theme · styles · shapes · markers<br/>nodes · edges · labels · ports<br/><i>how it looks</i>"]
L4["<b>Layer 4 · toolbox · forms</b><br/><i>how it is created/edited</i>"]
L5["<b>Layer 5 · constraints</b><br/><i>what is allowed</i>"]
L6["<b>Layer 6 · behavior</b><br/>hooks · operations · policies<br/><i>what happens</i>"]
L7["<b>Layer 7 · layout</b><br/><i>how it is arranged</i>"]
L8["<b>Layer 8 · persistence</b><br/><i>how it is stored</i>"]
X["<b>cross-cutting</b><br/>doc on everything · CEL everywhere<br/>functions · plugins · viewpoints"]
L1 ~~~ L2 ~~~ L3 ~~~ L4 ~~~ L5 ~~~ L6 ~~~ L7 ~~~ L8 ~~~ X
classDef crossCutting stroke-dasharray:4 4
class X crossCuttingDependencies only point upward: notation refers to metamodel types, constraints to metamodel and coordinates, persistence to metamodel and coordinates — never the reverse. A headless validator therefore only needs layers 1, 2, 5 and 8.