{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://casoon.github.io/chartlet/schema/v1.json",
"title": "chartlet v1 specification",
"type": "object",
"additionalProperties": false,
"required": ["schemaVersion", "type", "title"],
"properties": {
"schemaVersion": { "const": 1 },
"type": {
"enum": ["bar", "line", "time", "topicmap", "atlas", "stripes", "calendar", "rangebar", "multiples", "sequence", "flow", "state", "architecture", "tree", "boxplot", "timeline", "waterfall", "waffle", "parliament", "treemap", "sankey", "survival", "scatter"]
},
"orientation": { "enum": ["vertical", "horizontal"], "default": "vertical" },
"title": { "type": "string", "minLength": 1, "maxLength": 200 },
"description": { "type": "string", "minLength": 1, "maxLength": 1000 },
"source": { "type": "string", "minLength": 1, "maxLength": 300 },
"theme": { "enum": ["light", "dark"], "default": "light" },
"locale": {
"description": "Language of the texts chartlet generates (description, legend additions, tooltips, HTML figure and table) and of the number format.",
"enum": ["en", "de"],
"default": "en"
},
"categoryAxis": { "$ref": "#/$defs/categoryAxis" },
"valueAxis": { "$ref": "#/$defs/valueAxis" },
"timeAxis": { "$ref": "#/$defs/timeAxis" },
"panes": {
"description": "Time charts are drawn from 1 to 4 panes stacked on one time axis, small multiples from 2 to 12 titled panes.",
"type": "array",
"minItems": 1,
"maxItems": 12,
"items": { "$ref": "#/$defs/pane" }
},
"columns": {
"description": "Grid columns of a type: \"multiples\" chart; defaults to up to three.",
"type": "integer",
"minimum": 1,
"maximum": 6
},
"stripes": {
"description": "The yearly values of a type: \"stripes\" chart.",
"$ref": "#/$defs/stripes"
},
"calendar": {
"description": "The daily values of a type: \"calendar\" chart.",
"$ref": "#/$defs/calendar"
},
"sparkline": {
"description": "type: \"time\" only: draw only the lines and areas of one pane, without axes, title or legend, at 60–600 × 16–200 pixels.",
"type": "boolean",
"default": false
},
"tooltips": {
"description": "type: \"time\" only: \"observations\" (default) gives every observation a tooltip while observations stand at least 4 pixels apart, on an invisible target where no marker is drawn; \"markers\" gives tooltips only to drawn markers, which keeps dense lines small.",
"enum": ["observations", "markers"],
"default": "observations"
},
"legend": {
"description": "type: \"time\" only: top (default) names the series in a legend above the plot; end names each line at its last observation, right of the plot.",
"enum": ["top", "end"],
"default": "top"
},
"independentAxes": {
"description": "type: \"multiples\" only: every panel gets its own value axis instead of one shared one.",
"type": "boolean",
"default": false
},
"boxDisplay": {
"description": "type: \"boxplot\": how the observations are drawn: boxes with whiskers (the default), violins (the estimated density with the box inside) or strips (every observation as a point). Violins and strips need `values` on every box.",
"enum": ["box", "violin", "strip"],
"default": "box"
},
"patterns": {
"description": "type: \"bar\" with series: draw every other series as an outline, so that series differ in form as well as in color.",
"type": "boolean",
"default": false
},
"stack": {
"description": "Stacks the series of a type: \"bar\" chart: \"normal\" by value, \"percent\" as shares of each category's total.",
"enum": ["normal", "percent"]
},
"references": {
"description": "Reference lines across a type: \"bar\" or \"rangebar\" chart, such as an average, a target or the line of no effect.",
"type": "array",
"maxItems": 4,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["value", "label"],
"properties": {
"value": { "type": "number" },
"label": { "type": "string", "minLength": 1, "maxLength": 60 }
}
}
},
"ranges": {
"description": "The spans of a type: \"rangebar\" chart, one per category.",
"type": "array",
"minItems": 1,
"maxItems": 100,
"items": { "$ref": "#/$defs/range" }
},
"scatter": {
"description": "The points of a type: \"scatter\" chart.",
"$ref": "#/$defs/scatter"
},
"survival": {
"description": "The groups of a type: \"survival\" chart.",
"$ref": "#/$defs/survival"
},
"sankey": {
"description": "The links of a type: \"sankey\" chart.",
"$ref": "#/$defs/sankey"
},
"treemap": {
"description": "The items of a type: \"treemap\" chart.",
"$ref": "#/$defs/treemap"
},
"parliament": {
"description": "The parties of a type: \"parliament\" chart.",
"$ref": "#/$defs/parliament"
},
"waffle": {
"description": "The parts of a type: \"waffle\" chart.",
"$ref": "#/$defs/waffle"
},
"waterfall": {
"description": "The steps of a type: \"waterfall\" chart.",
"$ref": "#/$defs/waterfall"
},
"timeline": {
"description": "The items and markers of a type: \"timeline\" chart.",
"$ref": "#/$defs/timeline"
},
"boxes": {
"description": "The boxes of a type: \"boxplot\" chart, one per category: observations (values) from which the box is computed, or the five numbers of a box computed elsewhere.",
"type": "array",
"minItems": 1,
"maxItems": 100,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["label"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 200 },
"values": { "description": "5 to 1000 observations. The box runs from the first to the third quartile (linear interpolation), the whiskers to the most extreme observations within 1.5 times that distance, every other observation is a point.", "type": "array", "minItems": 5, "maxItems": 1000, "items": { "type": "number" } },
"min": { "type": "number" },
"q1": { "type": "number" },
"median": { "type": "number" },
"q3": { "type": "number" },
"max": { "type": "number" },
"outliers": { "description": "Points beyond the whiskers of a box given by its five numbers.", "type": "array", "items": { "type": "number" } }
}
}
},
"sequence": {
"description": "The participants and messages of a type: \"sequence\" diagram.",
"$ref": "#/$defs/sequence"
},
"flow": {
"description": "The steps and edges of a type: \"flow\" chart.",
"$ref": "#/$defs/flow"
},
"state": {
"description": "The states and transitions of a type: \"state\" diagram.",
"$ref": "#/$defs/state"
},
"architecture": {
"description": "The components, connections and boundaries of a type: \"architecture\" diagram.",
"$ref": "#/$defs/architecture"
},
"tree": {
"description": "The nodes of a type: \"tree\" diagram.",
"$ref": "#/$defs/tree"
},
"topicmap": {
"description": "Topic areas of a type: \"topicmap\" chart.",
"$ref": "#/$defs/topicMap"
},
"atlas": {
"description": "The knowledge landscape of a type: \"atlas\" chart.",
"$ref": "#/$defs/atlas"
},
"width": { "type": "integer", "minimum": 200, "maximum": 2400, "default": 800 },
"height": { "type": "integer", "minimum": 160, "maximum": 1600, "default": 450 },
"mobile": {
"description": "A second layout for narrow containers. The HTML profile shows it below the breakpoint by a container query; the SVG profile renders it with the variant option.",
"type": "object",
"additionalProperties": false,
"required": ["width"],
"properties": {
"width": { "type": "integer", "minimum": 200, "maximum": 600 },
"height": { "type": "integer", "minimum": 160, "maximum": 1600, "default": 360 },
"breakpoint": {
"description": "Container width in CSS pixels below which the mobile variant is shown.",
"type": "integer",
"minimum": 320,
"maximum": 1600,
"default": 640
},
"columns": {
"description": "type: \"multiples\" only: grid columns of the mobile variant.",
"type": "integer",
"minimum": 1,
"maximum": 6
}
}
},
"showValues": { "type": "boolean", "default": true },
"showTitle": {
"description": "false leaves the drawn title out of the SVG profile and gives its space to the chart; the title stays the accessible name. The HTML profile never draws the title: its figcaption is the visible title.",
"type": "boolean",
"default": true
},
"data": {
"description": "Single-series data. Use either data or categories with series.",
"type": "array",
"minItems": 1,
"maxItems": 100,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["label", "value"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 200 },
"value": { "$ref": "#/$defs/value" },
"lower": { "description": "Bar charts of one series without groups: the lower end of an error bar through the end of the bar; upper goes with it, and the value lies between them.", "type": "number" },
"upper": { "type": "number" },
"group": { "description": "Bar charts only: the group a bar belongs to, one palette color and legend entry per group (at most 4). Either every point names a group or none does.", "type": "string", "minLength": 1, "maxLength": 60 }
}
}
},
"categories": {
"description": "Unique category labels shared by all series, or by all panels of small multiples of bars (at most 20 there).",
"type": "array",
"minItems": 1,
"maxItems": 100,
"uniqueItems": true,
"items": { "type": "string", "minLength": 1, "maxLength": 200 }
},
"series": {
"description": "Named series with one value per category; null marks a missing value.",
"type": "array",
"minItems": 1,
"maxItems": 4,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["name", "values"],
"properties": {
"name": { "type": "string", "minLength": 1, "maxLength": 100 },
"values": { "type": "array", "items": { "$ref": "#/$defs/value" } }
}
}
},
"zoomSteps": {
"description": "Optional pre-computed zoom variants, selectable in the HTML profile. A bar or line chart names categories by index, a time chart names a window by timestamps.",
"type": "array",
"minItems": 2,
"maxItems": 4,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["label", "from", "to"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 40 },
"from": {
"description": "First category index, or on a time chart the first timestamp of the window.",
"anyOf": [{ "type": "integer", "minimum": 0 }, { "$ref": "#/$defs/timeValue" }]
},
"to": {
"description": "Last category index, or on a time chart the last timestamp of the window.",
"anyOf": [{ "type": "integer", "minimum": 0 }, { "$ref": "#/$defs/timeValue" }]
}
}
}
}
},
"allOf": [
{
"oneOf": [
{
"required": ["data"],
"not": { "anyOf": [{ "required": ["categories"] }, { "required": ["series"] }] }
},
{
"required": ["categories", "series"],
"not": { "required": ["data"] }
},
{
"required": ["panes"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] }
]
}
},
{
"required": ["topicmap"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["atlas"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["stripes"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["calendar"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["parliament"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["treemap"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["sankey"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["survival"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["scatter"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["waffle"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["waterfall"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["timeline"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["boxes"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["ranges"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["sequence"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["flow"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["state"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["architecture"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
},
{
"required": ["tree"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["panes"] }
]
}
}
]
},
{
"if": { "properties": { "type": { "const": "stripes" } } },
"then": { "required": ["stripes"] },
"else": { "not": { "required": ["stripes"] } }
},
{
"if": { "properties": { "type": { "const": "calendar" } } },
"then": { "required": ["calendar"] },
"else": { "not": { "required": ["calendar"] } }
},
{
"if": { "properties": { "type": { "const": "rangebar" } } },
"then": { "required": ["ranges"] },
"else": { "not": { "required": ["ranges"] } }
},
{
"if": { "properties": { "type": { "const": "parliament" } } },
"then": { "required": ["parliament"] },
"else": { "not": { "required": ["parliament"] } }
},
{
"if": { "properties": { "type": { "const": "treemap" } } },
"then": { "required": ["treemap"] },
"else": { "not": { "required": ["treemap"] } }
},
{
"if": { "properties": { "type": { "const": "sankey" } } },
"then": { "required": ["sankey"] },
"else": { "not": { "required": ["sankey"] } }
},
{
"if": { "properties": { "type": { "const": "survival" } } },
"then": { "required": ["survival"] },
"else": { "not": { "required": ["survival"] } }
},
{
"if": { "properties": { "type": { "const": "scatter" } } },
"then": { "required": ["scatter"] },
"else": { "not": { "required": ["scatter"] } }
},
{
"if": { "properties": { "type": { "const": "waffle" } } },
"then": { "required": ["waffle"] },
"else": { "not": { "required": ["waffle"] } }
},
{
"if": { "properties": { "type": { "const": "waterfall" } } },
"then": { "required": ["waterfall"] },
"else": { "not": { "required": ["waterfall"] } }
},
{
"if": { "properties": { "type": { "const": "timeline" } } },
"then": {
"required": ["timeline"],
"not": {
"anyOf": [
{ "required": ["zoomSteps"] },
{ "required": ["orientation"] },
{ "required": ["categoryAxis"] },
{ "required": ["valueAxis"] },
{ "required": ["timeAxis"] },
{ "required": ["topicmap"] },
{ "required": ["atlas"] }
]
}
},
"else": { "not": { "required": ["timeline"] } }
},
{
"if": { "properties": { "type": { "const": "boxplot" } } },
"then": { "required": ["boxes"] },
"else": { "not": { "required": ["boxes"] } }
},
{
"if": { "properties": { "type": { "const": "sequence" } } },
"then": {
"required": ["sequence"],
"not": {
"anyOf": [
{ "required": ["zoomSteps"] },
{ "required": ["orientation"] },
{ "required": ["categoryAxis"] },
{ "required": ["valueAxis"] },
{ "required": ["timeAxis"] },
{ "required": ["topicmap"] },
{ "required": ["atlas"] }
]
}
},
"else": { "not": { "required": ["sequence"] } }
},
{
"if": { "properties": { "type": { "const": "flow" } } },
"then": {
"required": ["flow"],
"not": {
"anyOf": [
{ "required": ["zoomSteps"] },
{ "required": ["orientation"] },
{ "required": ["categoryAxis"] },
{ "required": ["valueAxis"] },
{ "required": ["timeAxis"] },
{ "required": ["topicmap"] },
{ "required": ["atlas"] }
]
}
},
"else": { "not": { "required": ["flow"] } }
},
{
"if": { "properties": { "type": { "const": "state" } } },
"then": {
"required": ["state"],
"not": {
"anyOf": [
{ "required": ["zoomSteps"] },
{ "required": ["orientation"] },
{ "required": ["categoryAxis"] },
{ "required": ["valueAxis"] },
{ "required": ["timeAxis"] },
{ "required": ["topicmap"] },
{ "required": ["atlas"] }
]
}
},
"else": { "not": { "required": ["state"] } }
},
{
"if": { "properties": { "type": { "const": "architecture" } } },
"then": {
"required": ["architecture"],
"not": {
"anyOf": [
{ "required": ["zoomSteps"] },
{ "required": ["orientation"] },
{ "required": ["categoryAxis"] },
{ "required": ["valueAxis"] },
{ "required": ["timeAxis"] },
{ "required": ["topicmap"] },
{ "required": ["atlas"] }
]
}
},
"else": { "not": { "required": ["architecture"] } }
},
{
"if": { "properties": { "type": { "const": "tree" } } },
"then": {
"required": ["tree"],
"not": {
"anyOf": [
{ "required": ["zoomSteps"] },
{ "required": ["orientation"] },
{ "required": ["categoryAxis"] },
{ "required": ["valueAxis"] },
{ "required": ["timeAxis"] },
{ "required": ["topicmap"] },
{ "required": ["atlas"] }
]
}
},
"else": { "not": { "required": ["tree"] } }
},
{
"if": { "properties": { "type": { "const": "multiples" } } },
"then": {
"required": ["panes"],
"properties": { "panes": { "minItems": 2 } },
"not": {
"anyOf": [
{ "required": ["orientation"] },
{ "required": ["categoryAxis"] },
{ "required": ["zoomSteps"] },
{ "required": ["topicmap"] },
{ "required": ["atlas"] }
]
}
},
"else": { "not": { "required": ["columns"] } }
},
{
"if": { "properties": { "type": { "const": "line" } } },
"then": { "not": { "anyOf": [{ "required": ["orientation"] }, { "required": ["series"] }] } }
},
{
"if": { "properties": { "type": { "const": "time" } } },
"then": {
"required": ["panes"],
"properties": { "panes": { "maxItems": 4 } },
"not": {
"anyOf": [
{ "required": ["orientation"] },
{ "required": ["categoryAxis"] },
{ "required": ["valueAxis"] },
{ "required": ["topicmap"] }
]
}
}
},
{
"if": { "properties": { "type": { "enum": ["bar", "line"] } } },
"then": {
"properties": {
"zoomSteps": {
"items": {
"properties": {
"from": { "type": "integer", "minimum": 0 },
"to": { "type": "integer", "minimum": 0 }
}
}
}
},
"not": {
"anyOf": [
{ "required": ["panes"] },
{ "required": ["timeAxis"] },
{ "required": ["topicmap"] }
]
}
}
},
{
"if": { "properties": { "type": { "const": "topicmap" } } },
"then": {
"required": ["topicmap"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["categories"] },
{ "required": ["series"] },
{ "required": ["zoomSteps"] },
{ "required": ["panes"] },
{ "required": ["orientation"] },
{ "required": ["categoryAxis"] },
{ "required": ["valueAxis"] },
{ "required": ["timeAxis"] }
]
}
}
}
],
"$defs": {
"identifier": {
"description": "What other parts of a diagram refer to an element by: a letter, then letters, digits, hyphens or underscores.",
"type": "string",
"pattern": "^[A-Za-z][A-Za-z0-9_-]{0,63}$"
},
"sequence": {
"description": "A sequence diagram. orientation auto draws it in portrait (participants side by side, time running down) where that fits the canvas, in landscape (participants one below the other, time running right) where only that fits, and otherwise in the orientation that grows the canvas less; a canvas too small for the diagram grows, with the warning canvas_too_small.",
"type": "object",
"additionalProperties": false,
"required": ["participants", "messages"],
"properties": {
"participants": {
"type": "array",
"minItems": 1,
"maxItems": 12,
"items": { "$ref": "#/$defs/participant" }
},
"messages": {
"description": "The messages in the order they are sent.",
"type": "array",
"minItems": 1,
"maxItems": 60,
"items": { "$ref": "#/$defs/message" }
},
"fragments": {
"description": "Frames around runs of consecutive messages; two fragments either nest or do not overlap, at most three deep.",
"type": "array",
"maxItems": 12,
"items": { "$ref": "#/$defs/fragment" }
},
"numbered": {
"description": "Numbers the messages in round badges at the start of their arrows.",
"type": "boolean",
"default": false
},
"orientation": { "enum": ["auto", "portrait", "landscape"], "default": "auto" }
}
},
"flow": {
"description": "A flow chart, laid out in layers along the flow: down in portrait, right in landscape. orientation auto takes portrait where that fits the canvas, landscape where only that fits, and otherwise the one that grows the canvas less (canvas_too_small). Edges may form cycles; an edge back is drawn against the flow.",
"type": "object",
"additionalProperties": false,
"required": ["nodes"],
"properties": {
"nodes": {
"type": "array",
"minItems": 1,
"maxItems": 40,
"items": { "$ref": "#/$defs/flowNode" }
},
"edges": {
"type": "array",
"maxItems": 80,
"items": { "$ref": "#/$defs/flowEdge" }
},
"lanes": {
"description": "Bands across the flow; once there are lanes, every step names one.",
"type": "array",
"maxItems": 8,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["id", "label"],
"properties": {
"id": { "$ref": "#/$defs/identifier" },
"label": { "type": "string", "minLength": 1, "maxLength": 40 }
}
}
},
"groups": {
"description": "Frames around steps of one lane; a step belongs to at most one group.",
"type": "array",
"maxItems": 8,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["label", "nodes"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 40 },
"nodes": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/identifier" } }
}
}
},
"mainPath": {
"description": "The usual way through the flow, as step ids joined by edges: kept in line and drawn stronger.",
"type": "array",
"items": { "$ref": "#/$defs/identifier" }
},
"orientation": { "enum": ["auto", "portrait", "landscape"], "default": "auto" }
}
},
"state": {
"description": "A state diagram, laid out like a flow chart. A composite state is a frame around the states that name it with in; transitions, initial and mainPath name states that are not composite. initial names the state the machine starts in and draws a dot with an arrow into it; final states get a double outline, choices a diamond. Transitions are written event [guard] / action.",
"type": "object",
"additionalProperties": false,
"required": ["states"],
"properties": {
"states": {
"type": "array",
"minItems": 1,
"maxItems": 40,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["id", "label"],
"properties": {
"id": { "$ref": "#/$defs/identifier" },
"label": { "type": "string", "minLength": 1, "maxLength": 60 },
"sublabel": { "type": "string", "minLength": 1, "maxLength": 60 },
"kind": { "enum": ["state", "choice", "composite"], "default": "state" },
"final": { "type": "boolean", "default": false },
"in": { "$ref": "#/$defs/identifier" }
}
}
},
"transitions": {
"type": "array",
"maxItems": 80,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["from", "to"],
"properties": {
"from": { "$ref": "#/$defs/identifier" },
"to": { "$ref": "#/$defs/identifier" },
"event": { "type": "string", "minLength": 1, "maxLength": 40 },
"guard": { "type": "string", "minLength": 1, "maxLength": 40 },
"action": { "type": "string", "minLength": 1, "maxLength": 40 },
"dash": { "enum": ["solid", "dashed", "dotted"], "default": "solid" }
}
}
},
"initial": { "$ref": "#/$defs/identifier" },
"mainPath": {
"description": "The usual way through the states, as ids joined by transitions: kept in line and drawn stronger.",
"type": "array",
"items": { "$ref": "#/$defs/identifier" }
},
"orientation": { "enum": ["auto", "portrait", "landscape"], "default": "auto" }
}
},
"scatter": {
"description": "A scatter plot: points on two numeric axes, in up to 4 groups (on every point or none, one palette color each), with up to 8 lines across the plot at a value of x or y and names beside labeled points. Up to 5000 points; above 300 they are drawn small without tooltips, and above 100 the data table lists only the labeled points, or the 20 highest.",
"type": "object",
"additionalProperties": false,
"required": ["points"],
"properties": {
"points": {
"type": "array",
"minItems": 1,
"maxItems": 5000,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["x", "y"],
"properties": {
"x": { "type": "number" },
"y": { "type": "number" },
"group": { "type": "string", "minLength": 1, "maxLength": 60 },
"label": { "type": "string", "minLength": 1, "maxLength": 60 }
}
}
},
"lines": {
"type": "array",
"maxItems": 8,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["axis", "value"],
"properties": {
"axis": { "enum": ["x", "y"] },
"value": { "type": "number" },
"label": { "type": "string", "minLength": 1, "maxLength": 100 }
}
}
},
"xTitle": { "type": "string", "minLength": 1, "maxLength": 100 },
"yTitle": { "type": "string", "minLength": 1, "maxLength": 100 },
"regression": { "type": "boolean", "default": false, "description": "Draw the least-squares line through the points, one for each group; on a logarithmic axis it is fitted to the logarithms." },
"xScale": { "enum": ["linear", "log"], "default": "linear" },
"yScale": { "enum": ["linear", "log"], "default": "linear" }
}
},
"survival": {
"description": "Kaplan-Meier curves: for every group the share still without the event, from observed times; an observation with `event: false` is cut off (censored) and marked on the curve. Up to 4 groups with 2–2000 observations each; `confidence` draws the 95% band (log-log, Greenwood), `atRisk` (default true) writes the number at risk under the time axis.",
"type": "object",
"additionalProperties": false,
"required": ["groups"],
"properties": {
"groups": {
"type": "array",
"minItems": 1,
"maxItems": 4,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["label", "observations"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 100 },
"observations": {
"type": "array",
"minItems": 2,
"maxItems": 2000,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["time"],
"properties": {
"time": { "type": "number", "minimum": 0 },
"event": { "type": "boolean", "default": true }
}
}
}
}
}
},
"confidence": { "type": "boolean", "default": false },
"logRank": { "type": "boolean", "default": false, "description": "Test whether the curves differ (log-rank, Mantel-Cox; needs two or more groups) and write the statistic and p in the plot and the description." },
"atRisk": { "type": "boolean", "default": true },
"timeTitle": { "type": "string", "minLength": 1, "maxLength": 100 }
}
},
"sankey": {
"description": "A Sankey diagram: nodes in columns by the longest path to them, joined by bands as thick as the flow. The nodes are the labels the links name; up to 100 links and 40 nodes, no link from a node to itself, one link for each pair, no cycle.",
"type": "object",
"additionalProperties": false,
"required": ["links"],
"properties": {
"nodes": {
"type": "array",
"maxItems": 40,
"description": "Nodes whose column, color or order the specification fixes; they come first, in this order.",
"items": {
"type": "object",
"additionalProperties": false,
"required": ["label"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 100 },
"column": { "type": "integer", "minimum": 0, "maximum": 7 },
"color": { "type": "integer", "minimum": 1, "maximum": 4 }
}
}
},
"order": { "enum": ["auto", "listed"], "default": "auto", "description": "auto orders the nodes of a column to cross few bands; listed keeps the order of nodes, then of the links." },
"links": {
"type": "array",
"minItems": 1,
"maxItems": 100,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["from", "to", "value"],
"properties": {
"from": { "type": "string", "minLength": 1, "maxLength": 100 },
"to": { "type": "string", "minLength": 1, "maxLength": 100 },
"value": { "type": "number", "exclusiveMinimum": 0 }
}
}
}
}
},
"treemap": {
"description": "A treemap: rectangles whose areas follow the values of the items, packed by the squarified method; the names and values stand inside the rectangles that have room. Up to 100 items (parts included) with positive values; an optional group (up to 4, on every item or on none) colors the rectangles and shows a legend; or items with children, nested up to three levels, colored by the item at the top.",
"type": "object",
"additionalProperties": false,
"required": ["items"],
"properties": {
"items": {
"type": "array",
"minItems": 1,
"maxItems": 100,
"items": { "$ref": "#/$defs/treemapItem" }
}
}
},
"treemapItem": {
"type": "object",
"additionalProperties": false,
"required": ["label"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 100 },
"value": { "type": "number", "exclusiveMinimum": 0, "description": "The value of a leaf; an item with children has none." },
"group": { "type": "string", "minLength": 1, "maxLength": 60 },
"children": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/treemapItem" }, "description": "The parts of this item, drawn inside its rectangle; up to three levels deep. A nested treemap takes its colors from the items at the top and has no groups." }
}
},
"parliament": {
"description": "A parliament: the seats of an assembly as dots in a semicircle, in blocks by party from left to right in the order of the list. Up to 8 parties and 800 seats; majority marks the seat that makes a majority, coalition (labels of parties) rings their seats and sums them.",
"type": "object",
"additionalProperties": false,
"required": ["parties"],
"properties": {
"parties": {
"type": "array",
"minItems": 1,
"maxItems": 8,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["label", "seats"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 100 },
"seats": { "type": "integer", "minimum": 1, "maximum": 800 }
}
}
},
"majority": { "type": "boolean", "default": false },
"coalition": { "type": "array", "items": { "type": "string" } }
}
},
"waffle": {
"description": "A waffle: a grid of squares that each stand for the same share of a whole, filled by the parts in reading order, each part with at least one square. Up to 4 parts; cells 10–400 (default 100), columns 2–40; a total above the sum of the parts leaves the squares of the rest.",
"type": "object",
"additionalProperties": false,
"required": ["parts"],
"properties": {
"parts": {
"type": "array",
"minItems": 1,
"maxItems": 4,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["label", "value"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 100 },
"value": { "type": "number", "exclusiveMinimum": 0 }
}
}
},
"cells": { "type": "integer", "minimum": 10, "maximum": 400, "default": 100 },
"columns": { "type": "integer", "minimum": 2, "maximum": 40 },
"total": { "type": "number", "exclusiveMinimum": 0 }
}
},
"waterfall": {
"description": "A waterfall: a running total that rises and falls step by step. A delta adds its value, a start sets the total as a bar from zero, a total shows the running total (and, if it names a value, that value must equal it).",
"type": "object",
"additionalProperties": false,
"required": ["steps"],
"properties": {
"steps": {
"type": "array",
"minItems": 2,
"maxItems": 40,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["label"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 100 },
"value": { "type": "number" },
"kind": { "enum": ["delta", "start", "total"], "default": "delta" }
}
}
}
}
},
"timeline": {
"description": "A timeline: phases (start and end), milestones (at), dashed marker lines for days that matter, and which items follow which. Days are ISO 8601 dates, optionally with a time, or Unix seconds. Either every item names a group or none does (at most 4); `after` names the ids of earlier or later items, in no circle.",
"type": "object",
"additionalProperties": false,
"required": ["items"],
"properties": {
"items": {
"type": "array",
"minItems": 1,
"maxItems": 60,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["label"],
"properties": {
"id": { "$ref": "#/$defs/identifier" },
"label": { "type": "string", "minLength": 1, "maxLength": 100 },
"start": { "$ref": "#/$defs/timeValue" },
"end": { "$ref": "#/$defs/timeValue" },
"at": { "$ref": "#/$defs/timeValue" },
"group": { "type": "string", "minLength": 1, "maxLength": 60 },
"after": { "type": "array", "items": { "$ref": "#/$defs/identifier" } }
}
}
},
"markers": {
"type": "array",
"maxItems": 6,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["label", "at"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 60 },
"at": { "$ref": "#/$defs/timeValue" }
}
}
}
}
},
"tree": {
"description": "A tree: one root and, below it, nodes that each name their parent; the children of a node keep the order of the list. Identifiers are unique, exactly one node has neither a parent nor a partner, the parents run to the root without a circle, and the tree goes at most twelve levels below the root.",
"type": "object",
"additionalProperties": false,
"required": ["nodes"],
"properties": {
"nodes": {
"type": "array",
"minItems": 1,
"maxItems": 150,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["id", "label"],
"properties": {
"id": { "$ref": "#/$defs/identifier" },
"label": { "type": "string", "minLength": 1, "maxLength": 60 },
"sublabel": { "type": "string", "minLength": 1, "maxLength": 60 },
"parent": { "$ref": "#/$defs/identifier" },
"link": { "description": "What joins the node to its parent, such as a share; not on the root.", "type": "string", "minLength": 1, "maxLength": 40 },
"kind": { "enum": ["unit", "person", "external"], "default": "unit" },
"partner": { "description": "The id of the node this one is joined to as a couple: they stand side by side and the children of either hang from the middle of the line between them. A partner has no parent, and is not itself named as a partner.", "$ref": "#/$defs/identifier" }
}
}
},
"orientation": { "enum": ["auto", "portrait", "landscape"], "default": "auto" }
}
},
"architecture": {
"description": "An architecture diagram, laid out like a flow chart: components joined by connections inside boundaries that nest by naming the boundary they lie in. Identifiers are unique among components and boundaries; every boundary holds at least one component, directly or in a boundary inside it.",
"type": "object",
"additionalProperties": false,
"required": ["components"],
"properties": {
"components": {
"type": "array",
"minItems": 1,
"maxItems": 40,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["id", "label"],
"properties": {
"id": { "$ref": "#/$defs/identifier" },
"label": { "type": "string", "minLength": 1, "maxLength": 60 },
"sublabel": { "type": "string", "minLength": 1, "maxLength": 60 },
"kind": {
"enum": ["person", "frontend", "service", "database", "queue", "storage", "cache", "external", "security"],
"default": "service"
},
"in": { "$ref": "#/$defs/identifier" }
}
}
},
"connections": {
"type": "array",
"maxItems": 80,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["from", "to"],
"properties": {
"from": { "$ref": "#/$defs/identifier" },
"to": { "$ref": "#/$defs/identifier" },
"label": { "type": "string", "minLength": 1, "maxLength": 60 },
"technology": { "type": "string", "minLength": 1, "maxLength": 40 },
"dash": { "enum": ["solid", "dashed", "dotted"], "default": "solid" }
}
}
},
"boundaries": {
"description": "Frames such as a cloud region, a network or a system, nesting at most four deep.",
"type": "array",
"maxItems": 12,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["id", "label"],
"properties": {
"id": { "$ref": "#/$defs/identifier" },
"label": { "type": "string", "minLength": 1, "maxLength": 60 },
"in": { "$ref": "#/$defs/identifier" }
}
}
},
"mainPath": {
"description": "The usual way a request takes, as component ids joined by connections: kept in line and drawn stronger.",
"type": "array",
"items": { "$ref": "#/$defs/identifier" }
},
"orientation": { "enum": ["auto", "portrait", "landscape"], "default": "auto" }
}
},
"flowNode": {
"description": "A step; each kind has its own shape.",
"type": "object",
"additionalProperties": false,
"required": ["id", "label"],
"properties": {
"id": { "$ref": "#/$defs/identifier" },
"label": { "type": "string", "minLength": 1, "maxLength": 60 },
"sublabel": { "type": "string", "minLength": 1, "maxLength": 60 },
"kind": {
"enum": ["start", "end", "process", "decision", "io", "subprocess", "store", "external"],
"default": "process"
},
"lane": { "$ref": "#/$defs/identifier" }
}
},
"flowEdge": {
"type": "object",
"additionalProperties": false,
"required": ["from", "to"],
"properties": {
"from": { "$ref": "#/$defs/identifier" },
"to": { "$ref": "#/$defs/identifier" },
"label": { "type": "string", "minLength": 1, "maxLength": 60 },
"dash": { "enum": ["solid", "dashed", "dotted"], "default": "solid" }
}
},
"participant": {
"description": "A participant; each kind has its own shape.",
"type": "object",
"additionalProperties": false,
"required": ["id", "label"],
"properties": {
"id": { "$ref": "#/$defs/identifier" },
"label": { "type": "string", "minLength": 1, "maxLength": 60 },
"sublabel": { "type": "string", "minLength": 1, "maxLength": 60 },
"kind": {
"enum": ["actor", "service", "database", "queue", "external"],
"default": "service"
}
}
},
"message": {
"description": "A message from one participant to another, or to itself. A call activates its receiver until the receiver replies.",
"type": "object",
"additionalProperties": false,
"required": ["from", "to", "label"],
"properties": {
"from": { "$ref": "#/$defs/identifier" },
"to": { "$ref": "#/$defs/identifier" },
"label": { "type": "string", "minLength": 1, "maxLength": 80 },
"kind": { "enum": ["call", "reply", "async"], "default": "call" }
}
},
"fragment": {
"description": "A frame around the messages from and to, counted from 0 and included. Only alt has further branches, each starting at a later message inside the frame.",
"type": "object",
"additionalProperties": false,
"required": ["kind", "from", "to"],
"properties": {
"kind": { "enum": ["alt", "opt", "loop", "par", "critical", "break"] },
"label": { "type": "string", "minLength": 1, "maxLength": 60 },
"from": { "type": "integer", "minimum": 0 },
"to": { "type": "integer", "minimum": 0 },
"else": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": ["from"],
"properties": {
"from": { "type": "integer", "minimum": 0 },
"label": { "type": "string", "minLength": 1, "maxLength": 60 }
}
}
}
}
},
"value": {
"anyOf": [
{ "type": "null" },
{ "const": 0 },
{ "type": "number", "minimum": 1e-100, "maximum": 1e100 },
{ "type": "number", "minimum": -1e100, "maximum": -1e-100 }
]
},
"categoryAxis": {
"type": "object",
"additionalProperties": false,
"properties": {
"title": { "type": "string", "minLength": 1, "maxLength": 100 }
}
},
"valueAxis": {
"type": "object",
"additionalProperties": false,
"properties": {
"title": { "type": "string", "minLength": 1, "maxLength": 100 },
"format": { "enum": ["number", "percent"], "default": "number" },
"decimals": {
"description": "Fixed decimal places for values in labels, tooltips, description and data table; axis ticks follow the tick step.",
"type": "integer",
"minimum": 0,
"maximum": 6
},
"min": {
"description": "The axis reaches at least down to this value. Ends are rounded outward to a tick; bars always start at zero.",
"type": "number"
},
"max": {
"description": "The axis reaches at least up to this value.",
"type": "number"
},
"scale": {
"description": "linear (default) or log: powers of ten evenly spaced; every value must be above zero.",
"enum": ["linear", "log"],
"default": "linear"
},
"step": {
"description": "Distance between two ticks, instead of a round step chosen from the values.",
"type": "number",
"exclusiveMinimum": 0
},
"exact": {
"description": "min and max are the ends of the axis; every value has to lie between them.",
"type": "boolean",
"default": false
},
"unit": {
"description": "Time charts and small multiples: the unit of the values, written after the top tick label and after the column names of the data table, instead of a title above the plot.",
"type": "string",
"minLength": 1,
"maxLength": 20
},
"reverse": {
"description": "Run the axis the other way: larger values down or left.",
"type": "boolean",
"default": false
},
"thousandsSeparator": {
"description": "Separate thousands in every written value: 12,500 (en) or 12.500 (de).",
"type": "boolean",
"default": false
}
}
},
"timeAxis": {
"description": "The time axis of a type: \"time\" chart: Unix seconds or ISO 8601 timestamps.",
"type": "object",
"additionalProperties": false,
"properties": {
"timezone": {
"description": "UTC or a fixed offset such as +02:00. Timestamps without their own offset are read as wall-clock time in this zone.",
"type": "string",
"pattern": "^(UTC|utc|Z|[+-](0[0-9]|1[0-4]):[0-5][0-9])$",
"default": "UTC"
},
"gaps": {
"description": "show keeps the distances in time; collapse places every observed timestamp at the same distance from the next, so days without observations (weekends, holidays) take no space.",
"enum": ["show", "collapse"],
"default": "show"
},
"title": { "type": "string", "minLength": 1, "maxLength": 100 },
"precision": {
"description": "How finely tooltips, the data table and the description name an observation; absent, the coarsest form that tells the observations apart.",
"enum": ["year", "month", "day", "minute"]
},
"min": {
"description": "A position the time axis reaches at least, such as a round year before the first observation; it extends the axis and never cuts an observation off. Not with collapsed gaps.",
"$ref": "#/$defs/timeValue"
},
"max": {
"description": "A position the time axis reaches at least after the last observation. Not with collapsed gaps.",
"$ref": "#/$defs/timeValue"
},
"step": {
"description": "The distance between time ticks: whole years (1–1000) on a calendar axis, units on a numeric axis; ticks sit on its multiples. Labels that would overlap are left out.",
"type": "number",
"exclusiveMinimum": 0
},
"kind": {
"description": "calendar (default): timestamps. number: every time is a plain number, such as a distance or an age in millions of years.",
"enum": ["calendar", "number"],
"default": "calendar"
},
"reverse": {
"description": "Run the axis from right to left, the largest position at the left.",
"type": "boolean",
"default": false
}
}
},
"timeValue": {
"description": "Unix seconds between 1700-01-01 and 2200-01-01, an ISO 8601 date such as 2026-03-01 or 2026-03-01T12:00:00Z, or a year such as 1850 (January 1st).",
"anyOf": [
{ "type": "integer", "minimum": -8520336000, "maximum": 7258118399 },
{ "type": "string", "pattern": "^[0-9]{4}$" },
{ "type": "string", "minLength": 10, "maxLength": 25 }
]
},
"stripes": {
"description": "Warming stripes: one value per consecutive year from firstYear on; null leaves a year empty. The diverging scale has eight equal steps on either side of reference; min and max default to the largest distance from reference, and values beyond them take the outermost step.",
"type": "object",
"additionalProperties": false,
"required": ["firstYear", "values"],
"properties": {
"firstYear": { "type": "integer", "minimum": 1, "maximum": 9999 },
"values": {
"type": "array",
"minItems": 1,
"maxItems": 500,
"items": { "$ref": "#/$defs/value" }
},
"reference": { "type": "number", "default": 0 },
"min": { "type": "number" },
"max": { "type": "number" },
"yearLabels": {
"description": "Label the first and the last year under the stripes.",
"type": "boolean",
"default": true
},
"stretch": {
"description": "The stripes alone, filling the canvas without margins, title or year labels, in an SVG that stretches to the box the page gives it.",
"type": "boolean",
"default": false
}
}
},
"calendar": {
"description": "A calendar heatmap of one year. A day that is absent or null stays an empty cell. reference, min and max work as for stripes.",
"type": "object",
"additionalProperties": false,
"required": ["year", "days"],
"properties": {
"year": { "type": "integer", "minimum": 1700, "maximum": 2199 },
"layout": {
"description": "months: twelve rows of up to 31 days; weeks: seven weekday rows, one column per week.",
"enum": ["months", "weeks"],
"default": "months"
},
"days": {
"type": "array",
"minItems": 1,
"maxItems": 366,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["date", "value"],
"properties": {
"date": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
"value": { "$ref": "#/$defs/value" }
}
}
},
"reference": { "type": "number", "default": 0 },
"min": { "type": "number" },
"max": { "type": "number" }
}
},
"range": {
"description": "One span of a rangebar chart; mid must lie between low and high.",
"type": "object",
"additionalProperties": false,
"required": ["label", "low", "high"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 200 },
"low": { "type": "number" },
"high": { "type": "number" },
"mid": { "type": "number" },
"weight": { "description": "A forest plot: the central mark becomes a square whose area follows the weight. Above zero; needs mid.", "type": "number", "exclusiveMinimum": 0 },
"summary": { "description": "An overall result such as a pooled effect: drawn as a diamond from low to high, widest at mid, which it needs.", "type": "boolean", "default": false },
"modeled": { "type": "boolean", "default": false },
"group": {
"description": "The group of the span, drawn in its own palette color with a legend entry. Either every range names a group or none does; at most 4 groups.",
"type": "string",
"minLength": 1,
"maxLength": 60
}
}
},
"pane": {
"type": "object",
"additionalProperties": false,
"properties": {
"title": {
"description": "Heading of a small-multiples panel; required there, not allowed in a time chart, whose panes are named by their valueAxis title.",
"type": "string",
"minLength": 1,
"maxLength": 100
},
"note": {
"description": "Small multiples only: a short finding under the panel title, such as a verdict; up to two lines, also in the description.",
"type": "string",
"minLength": 1,
"maxLength": 160
},
"noteEmphasis": {
"description": "Small multiples, with a note: draws the note in the text color and semibold instead of muted.",
"type": "boolean",
"default": false
},
"heightRatio": {
"description": "Time charts: the pane's share of the plot height against the other panes. Small multiples keep the default.",
"type": "integer",
"minimum": 1,
"maximum": 10,
"default": 1
},
"values": {
"description": "Small multiples of bars: the panel's value for each of the chart's categories, in their order; null marks a missing value. Instead of layers.",
"type": "array",
"maxItems": 100,
"items": { "$ref": "#/$defs/value" }
},
"valueAxis": { "$ref": "#/$defs/valueAxis" },
"stack": {
"description": "Time charts: \"normal\" stacks the pane's area layers in layer order, each on top of the ones before it. At least two area layers with the same times and curve, a value of zero or more at every time, no lower/upper band.",
"const": "normal"
},
"layers": {
"description": "Up to 6 data layers (8 in a stacked pane) — on a time chart at most 4 line and area layers of the whole chart without their own color — and up to 6 annotation layers (zones, reference lines and point markers together).",
"type": "array",
"minItems": 1,
"maxItems": 14,
"items": { "$ref": "#/$defs/layer" }
}
}
},
"layer": {
"description": "One layer of a pane. Which fields apply depends on mark.",
"type": "object",
"additionalProperties": false,
"required": ["mark"],
"properties": {
"mark": {
"description": "line and area draw data, point draws a dot per observation and no line; ohlc draws candlesticks (time charts only); band is a zone; annotation is a reference line or, with both time and value, a point marker.",
"enum": ["line", "area", "point", "ohlc", "band", "annotation"]
},
"name": { "type": "string", "minLength": 1, "maxLength": 100 },
"color": {
"description": "#rgb, #rrggbb, #rrggbbaa, var(--name) or var(--name, #hex); the print variant draws the hex fallback. Anything else is reported and replaced by the neutral tone.",
"type": "string",
"minLength": 1,
"maxLength": 100
},
"points": {
"description": "Observations of a line or area layer.",
"type": "array",
"minItems": 1,
"maxItems": 2000,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["time", "value"],
"properties": {
"time": { "$ref": "#/$defs/timeValue" },
"value": {
"description": "null marks a missing observation: the line, its area and its band break there.",
"$ref": "#/$defs/value"
},
"lower": {
"description": "Lower edge of the uncertainty band; give lower and upper on every point of a layer that has a value, or on none. A point whose value is null has no band.",
"type": "number"
},
"upper": { "description": "Upper edge of the uncertainty band.", "type": "number" }
}
}
},
"data": {
"description": "Candlesticks of an ohlc layer, with increasing time; low at or below open and close, high at or above them.",
"type": "array",
"minItems": 2,
"maxItems": 2000,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["time", "open", "high", "low", "close"],
"properties": {
"time": { "$ref": "#/$defs/timeValue" },
"open": { "type": "number" },
"high": { "type": "number" },
"low": { "type": "number" },
"close": { "type": "number" }
}
}
},
"from": {
"description": "Start of a zone; missing, the zone begins at the plot's left edge.",
"$ref": "#/$defs/timeValue"
},
"to": {
"description": "End of a zone, after from; missing, the zone ends at the plot's right edge.",
"$ref": "#/$defs/timeValue"
},
"top": {
"description": "Upper edge of a zone, above bottom; missing, the zone reaches the top of the plot.",
"type": "number"
},
"bottom": {
"description": "Lower edge of a zone; missing, the zone reaches the bottom of the plot.",
"type": "number"
},
"time": {
"description": "Time of a vertical reference line or of a point marker.",
"$ref": "#/$defs/timeValue"
},
"value": {
"description": "Value of a horizontal reference line or of a point marker.",
"type": "number"
},
"label": {
"description": "Text of a reference line, point marker or zone; required there.",
"type": "string",
"minLength": 1,
"maxLength": 100
},
"shape": {
"description": "Symbol of a point marker; circle by default. Only a point marker takes one.",
"enum": ["triangle-up", "triangle-down", "square", "circle", "diamond"]
},
"modeled": {
"description": "A line from a model: drawn dashed unless dash says otherwise, its band hatched, and named modeled in legend and description.",
"type": "boolean",
"default": false
},
"stroke": {
"description": "Line weight; thin sets a line back, for example single years under their mean, bold brings one forward, medium suits the lines of small panels.",
"enum": ["regular", "thin", "medium", "bold"],
"default": "regular"
},
"dash": {
"description": "Line pattern. Defaults to dashed for a modeled line and solid for any other.",
"enum": ["solid", "dashed", "dotted"]
},
"curve": {
"description": "Line and area only: linear (default) joins observations directly; step holds each value until the next observation.",
"enum": ["linear", "step"],
"default": "linear"
},
"precision": {
"description": "Data layers on a calendar axis: how this layer's times are written in tooltips, the table and the description; overrides timeAxis.precision.",
"enum": ["year", "month", "day", "minute"]
},
"stepEnd": {
"description": "Line and area with curve \"step\": where the last step ends; the last value holds until then. No observation of its own: no marker, tooltip or table row.",
"$ref": "#/$defs/timeValue"
},
"markers": {
"description": "Line and area only: false draws no markers, such as for a fitted line; tooltips stay on invisible targets.",
"type": "boolean"
}
},
"allOf": [
{
"if": { "properties": { "mark": { "enum": ["line", "area", "point"] } }, "required": ["mark"] },
"then": {
"required": ["points"],
"not": {
"anyOf": [
{ "required": ["data"] },
{ "required": ["from"] },
{ "required": ["to"] },
{ "required": ["top"] },
{ "required": ["bottom"] },
{ "required": ["time"] },
{ "required": ["value"] },
{ "required": ["label"] },
{ "required": ["shape"] }
]
}
}
},
{
"if": { "properties": { "mark": { "const": "ohlc" } }, "required": ["mark"] },
"then": {
"description": "Candlesticks: rising candles are hollow, falling ones filled, in --chartlet-rise and --chartlet-fall.",
"required": ["data"],
"not": {
"anyOf": [
{ "required": ["points"] },
{ "required": ["color"] },
{ "required": ["from"] },
{ "required": ["to"] },
{ "required": ["top"] },
{ "required": ["bottom"] },
{ "required": ["time"] },
{ "required": ["value"] },
{ "required": ["label"] },
{ "required": ["shape"] },
{ "required": ["modeled"] },
{ "required": ["stroke"] },
{ "required": ["dash"] }
]
}
}
},
{
"if": { "properties": { "mark": { "const": "annotation" } }, "required": ["mark"] },
"then": {
"description": "A reference line: value draws a horizontal one, time a vertical one; both draw a point marker, which alone takes a shape. label is required.",
"required": ["label"],
"anyOf": [{ "required": ["value"] }, { "required": ["time"] }],
"if": { "not": { "required": ["time", "value"] } },
"then": { "not": { "required": ["shape"] } },
"not": {
"anyOf": [
{ "required": ["name"] },
{ "required": ["points"] },
{ "required": ["data"] },
{ "required": ["from"] },
{ "required": ["to"] },
{ "required": ["top"] },
{ "required": ["bottom"] },
{ "required": ["modeled"] },
{ "required": ["stroke"] },
{ "required": ["dash"] }
]
}
}
},
{
"if": { "properties": { "mark": { "const": "band" } }, "required": ["mark"] },
"then": {
"description": "A zone between bottom and top, from and to, or both; a missing edge is the plot's edge. label is required.",
"required": ["label"],
"anyOf": [{ "required": ["bottom", "top"] }, { "required": ["from", "to"] }],
"not": {
"anyOf": [
{ "required": ["name"] },
{ "required": ["points"] },
{ "required": ["data"] },
{ "required": ["time"] },
{ "required": ["value"] },
{ "required": ["shape"] },
{ "required": ["modeled"] },
{ "required": ["stroke"] },
{ "required": ["dash"] }
]
}
}
}
]
},
"topic": {
"description": "One topic or island of a type: \"topicmap\" chart.",
"type": "object",
"additionalProperties": false,
"required": ["label", "value"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 200 },
"value": { "type": "number", "minimum": 1, "maximum": 1e100 },
"points": {
"description": "Number of paths through this topic; drawn as points inside its area.",
"type": "integer",
"minimum": 0,
"default": 0
},
"tooltip": { "type": "string", "minLength": 1, "maxLength": 300 }
}
},
"topicLink": {
"description": "A neighborhood between two topics or islands, drawn as a route.",
"type": "object",
"additionalProperties": false,
"required": ["from", "to"],
"properties": {
"from": { "type": "string", "minLength": 1 },
"to": { "type": "string", "minLength": 1 },
"weight": { "type": "number", "minimum": 0, "maximum": 1, "default": 1 }
}
},
"cartouche": {
"description": "The legend box printed on the map.",
"type": "object",
"additionalProperties": false,
"required": ["heading", "meta"],
"properties": {
"heading": { "type": "string", "minLength": 1, "maxLength": 100 },
"meta": { "type": "string", "minLength": 1, "maxLength": 200 },
"corner": {
"enum": ["bottomRight", "bottomLeft", "topRight", "topLeft"],
"default": "bottomRight"
}
}
},
"atlas": {
"description": "Realms of neighbouring regions, holding places. Where a region lies says as much as how large it is.",
"type": "object",
"additionalProperties": false,
"required": ["realms"],
"properties": {
"realms": {
"type": "array",
"minItems": 1,
"maxItems": 8,
"items": { "$ref": "#/$defs/realm" }
},
"links": {
"description": "Kinship between two regions, named by label and valid across realm borders.",
"type": "array",
"items": { "$ref": "#/$defs/topicLink" }
},
"seed": { "type": "integer", "minimum": 0, "default": 0 },
"areaDamping": {
"description": "The exponent a region's area follows: 1 is proportional to its value, 0.5 its square root.",
"type": "number",
"minimum": 0.2,
"maximum": 1,
"default": 0.5
},
"contours": {
"description": "Contour lines from the density of places.",
"type": "boolean",
"default": true
}
}
},
"realm": {
"type": "object",
"additionalProperties": false,
"required": ["label", "regions"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 200 },
"regions": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#/$defs/region" }
},
"tooltip": { "type": "string", "minLength": 1, "maxLength": 300 }
}
},
"region": {
"type": "object",
"additionalProperties": false,
"required": ["label", "value"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 200 },
"value": { "type": "number", "minimum": 1 },
"places": {
"type": "array",
"items": { "$ref": "#/$defs/place" }
},
"tooltip": { "type": "string", "minLength": 1, "maxLength": 300 }
}
},
"place": {
"type": "object",
"additionalProperties": false,
"required": ["label"],
"properties": {
"label": { "type": "string", "minLength": 1, "maxLength": 200 },
"weight": {
"description": "How prominent the point is. 1 is an ordinary place.",
"type": "number",
"minimum": 0.25,
"maximum": 4,
"default": 1
},
"tooltip": { "type": "string", "minLength": 1, "maxLength": 300 }
}
},
"topicMap": {
"type": "object",
"additionalProperties": false,
"required": ["topics"],
"properties": {
"topics": {
"type": "array",
"minItems": 1,
"maxItems": 40,
"items": { "$ref": "#/$defs/topic" }
},
"links": {
"type": "array",
"items": { "$ref": "#/$defs/topicLink" }
},
"islands": {
"description": "Fringe topics, drawn as small fixed-size islands rather than area-proportional landmasses.",
"type": "array",
"maxItems": 6,
"items": { "$ref": "#/$defs/topic" }
},
"seed": { "type": "integer", "minimum": 0, "default": 0 },
"cartouche": { "$ref": "#/$defs/cartouche" },
"graticule": { "type": "boolean", "default": true },
"compass": { "type": "boolean", "default": true },
"depthBands": {
"description": "Number of depth-line rings drawn around each coastline.",
"type": "integer",
"minimum": 0,
"maximum": 3,
"default": 2
}
}
}
}
}