{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://graphghan.milo.cat/schema/chart.schema.json",
  "title": "Graphghan chart document, schema 2 or 3",
  "description": "One pixel chart at one gauge. Readers must ignore unknown keys at every level. See docs/chart-format.md.",
  "type": "object",
  "required": ["schema", "pattern", "chart", "palette", "rows", "gauge", "technique"],
  "properties": {
    "schema": { "enum": [2, 3] },
    "pattern": {
      "type": "object",
      "required": ["id", "title", "version"],
      "properties": {
        "id": { "type": "string", "pattern": "^[a-z0-9-]+$" },
        "title": { "type": "string", "minLength": 1 },
        "version": { "type": "string", "minLength": 1 },
        "author": { "type": "string" },
        "license": { "type": "string" },
        "dedication": { "type": "string" },
        "quote": { "type": "string" },
        "url": { "type": "string", "format": "uri" },
        "craft": { "enum": ["crochet", "knit", "tunisian", "cross-stitch"] },
        "language": { "type": "string", "minLength": 2 }
      }
    },
    "chart": {
      "type": "object",
      "required": ["id", "width", "height"],
      "properties": {
        "id": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" },
        "variant": { "type": "string" },
        "gauge_key": { "type": "string" },
        "width": { "type": "integer", "minimum": 1 },
        "height": { "type": "integer", "minimum": 1 },
        "cell": {
          "type": "object",
          "required": ["kind"],
          "properties": {
            "kind": { "enum": ["stitch", "block", "tile", "motif", "pair"] }
          }
        }
      }
    },
    "generator": {
      "type": "object",
      "properties": { "name": { "type": "string" }, "version": { "type": "string" } }
    },
    "palette": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/paletteItem" } },
    "rows": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/runString" } },
    "layers": { "type": "object", "additionalProperties": { "$ref": "#/$defs/layer" } },
    "gauge": {
      "type": "object",
      "required": ["stitches", "rows", "over"],
      "properties": {
        "stitches": { "type": "number", "exclusiveMinimum": 0 },
        "rows": { "type": "number", "exclusiveMinimum": 0 },
        "over": {
          "type": "object",
          "required": ["value", "unit"],
          "properties": { "value": { "type": "number", "exclusiveMinimum": 0 }, "unit": { "enum": ["in", "cm"] } }
        },
        "stitch": { "type": "string" },
        "hook": { "type": "string" },
        "yarn_weight": { "type": "string" },
        "unit": { "enum": ["stitches", "tiles", "repeats", "rounds"] },
        "stitch_name": { "type": "string", "minLength": 1 },
        "terms": { "enum": ["US", "UK"] },
        "terms_also": { "enum": ["US", "UK"] },
        "boundary": {
          "type": "object",
          "required": ["kind", "chain"],
          "properties": {
            "kind": { "enum": ["turn", "join", "rejoin", "spiral", "return"] },
            "chain": { "type": "integer", "minimum": 0 },
            "counts_as_stitch": { "type": "boolean" },
            "color": { "enum": ["next", "current"] }
          }
        }
      }
    },
    "foundation": {
      "type": "object",
      "required": ["chain"],
      "properties": {
        "chain": { "type": "integer", "minimum": 1 },
        "first_stitch_in": { "type": "integer", "minimum": 1 },
        "note": { "type": "string" }
      }
    },
    "technique": {
      "type": "object",
      "required": ["type"],
      "properties": {
        "type": { "type": "string", "minLength": 1 },
        "start": { "enum": ["bottom", "top"] },
        "first_side": { "enum": ["RS", "WS"] },
        "rs_direction": { "enum": ["rtl", "ltr"] },
        "turn": { "type": "boolean" }
      }
    },
    "passes": { "type": "array", "items": { "$ref": "#/$defs/pass" } },
    "instructions": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["title", "text"],
        "properties": { "title": { "type": "string" }, "text": { "type": "string" } }
      }
    },
    "written": { "type": "array", "items": { "type": "string" } },
    "stats": { "type": "object" },
    "ext": { "type": "object" }
  },
  "$defs": {
    "code": { "type": "string", "pattern": "^[A-Za-z]{1,3}$" },
    "runString": { "type": "string", "pattern": "^([0-9]+[A-Za-z]{1,3})+$" },
    "paletteItem": {
      "type": "object",
      "required": ["code", "name", "hex"],
      "properties": {
        "code": { "$ref": "#/$defs/code" },
        "name": { "type": "string", "minLength": 1 },
        "hex": { "type": "string", "pattern": "^#[0-9A-Fa-f]{6}$" },
        "yarn": {
          "type": "object",
          "properties": {
            "brand": { "type": "string" }, "line": { "type": "string" }, "colorway": { "type": "string" },
            "weight": { "type": "string" }, "lot": { "type": "string" }, "note": { "type": "string" }
          }
        },
        "thread": {
          "type": "object",
          "required": ["system", "number"],
          "properties": { "system": { "type": "string" }, "number": { "type": "string" } }
        },
        "use": { "type": "string" },
        "stitch": { "type": "boolean" },
        "symbol": { "type": "string" }
      }
    },
    "layer": {
      "type": "object",
      "required": ["legend", "rows"],
      "properties": {
        "legend": { "type": "object", "additionalProperties": { "type": "string" } },
        "rows": { "type": "array", "items": { "$ref": "#/$defs/runString" } }
      }
    },
    "run": {
      "type": "object",
      "required": ["code", "count"],
      "properties": {
        "code": { "$ref": "#/$defs/code" },
        "count": { "type": "integer", "minimum": 1 },
        "x0": { "type": "integer", "minimum": 0 }
      }
    },
    "pass": {
      "type": "object",
      "required": ["label", "runs"],
      "properties": {
        "label": { "type": "string" },
        "side": { "enum": ["RS", "WS", null] },
        "direction": { "enum": ["rtl", "ltr", null] },
        "grid_row": { "type": ["integer", "null"], "minimum": 0 },
        "runs": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/run" } }
      }
    }
  }
}
