{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://gocharting.com/docs/scripting/reference/language-map.schema.json",
  "title": "Lipi Language Map",
  "description": "A factual map from constructs of other chart-script languages to Lipi, GoCharting's chart-script language. Direction: to Lipi only. One record per concept and language.",
  "type": "object",
  "required": ["schema_version", "data_release", "direction", "lipi", "languages", "categories", "concepts", "mappings"],
  "properties": {
    "$schema": { "type": "string" },
    "schema_version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
    "data_release": { "type": "string", "format": "date" },
    "direction": { "const": "to_lipi" },
    "lipi": {
      "type": "object",
      "required": ["language_version", "reference_version", "compiler_build", "reference_url"],
      "properties": {
        "language_version": { "type": "integer" },
        "reference_version": { "type": "string" },
        "compiler_build": { "type": "string" },
        "reference_url": { "type": "string", "format": "uri" }
      }
    },
    "languages": {
      "type": "object",
      "description": "Keyed by language id; listed after Lipi in alphabetical order of display name.",
      "additionalProperties": {
        "type": "object",
        "required": ["name", "owner", "docs_version_verified", "docs_home", "hosts"],
        "properties": {
          "name": { "type": "string" },
          "owner": { "type": "string" },
          "docs_version_verified": { "type": "string" },
          "docs_home": { "type": "string", "format": "uri" },
          "hosts": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
          "detect": {
            "description": "Code signals for the code-only language detector (reference/language-map/detect.mjs): each a regular expression (JavaScript syntax, multiline), its weight, and whether (raw) it is matched against the text with strings and block comments removed but line comments kept, rather than with every comment and string removed.",
            "type": "array",
            "items": {
              "type": "object",
              "required": ["pattern", "weight"],
              "additionalProperties": false,
              "properties": {
                "pattern": { "type": "string", "minLength": 1 },
                "weight": { "type": "number", "exclusiveMinimum": 0 },
                "raw": { "type": "boolean" }
              }
            }
          }
        }
      }
    },
    "categories": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id", "title", "intro"],
        "properties": { "id": { "type": "string" }, "title": { "type": "string" }, "intro": { "type": "string" } }
      }
    },
    "concepts": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id", "category", "title", "definition", "lipi"],
        "properties": {
          "id": { "type": "string", "pattern": "^[a-z0-9]+(\\.[a-z0-9_-]+)+$" },
          "category": { "type": "string" },
          "title": { "type": "string" },
          "definition": { "type": "string" },
          "lipi": {
            "oneOf": [
              {
                "type": "object",
                "required": ["symbols"],
                "properties": {
                  "symbols": { "type": "array", "items": { "type": "string" } },
                  "facts": { "type": "array", "items": { "type": "string", "pattern": "^F-\\d+$" } },
                  "note": { "type": "string" },
                  "example": { "type": "string" }
                }
              },
              { "type": "object", "required": ["absent_reason"], "properties": { "absent_reason": { "type": "string" } } }
            ]
          }
        }
      }
    },
    "mappings": {
      "type": "array",
      "items": { "$ref": "#/$defs/mapping" }
    }
  },
  "$defs": {
    "source": { "enum": ["present", "absent", "unresolved"] },
    "relation": { "enum": ["exact", "equivalent_with_caveat", "different_semantics", "composite", "no_lipi_equivalent"] },
    "axis": { "enum": ["history_indexing", "bar_timing", "warmup_and_na", "numeric_types", "htf_access", "state_and_side_effects"] },
    "verified": { "enum": ["documented", "unresolved"] },
    "evidence": {
      "type": "object",
      "required": ["url", "fragment", "accessed"],
      "properties": {
        "url": { "type": "string", "format": "uri" },
        "fragment": { "type": "string" },
        "accessed": { "type": "string", "format": "date" }
      }
    },
    "mapping": {
      "type": "object",
      "required": ["concept", "language", "source", "evidence", "verified"],
      "properties": {
        "concept": { "type": "string" },
        "language": { "type": "string" },
        "source": { "$ref": "#/$defs/source" },
        "construct": { "type": "string" },
        "signature": { "type": "string" },
        "relation": { "$ref": "#/$defs/relation" },
        "note": { "type": "string" },
        "differences": {
          "type": "array",
          "items": { "type": "object", "required": ["axis", "note"], "properties": { "axis": { "$ref": "#/$defs/axis" }, "note": { "type": "string" } } }
        },
        "evidence": { "$ref": "#/$defs/evidence" },
        "verified": { "$ref": "#/$defs/verified" }
      },
      "if": { "properties": { "source": { "const": "present" } } },
      "then": { "required": ["construct", "relation"] },
      "else": { "not": { "anyOf": [{ "required": ["relation"] }, { "required": ["construct"] }, { "required": ["differences"] }] }, "required": ["note"] }
    }
  }
}
