{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "description": "IPython Notebook v3.0 JSON schema.",
  "type": "object",
  "additionalProperties": false,
  "required": ["metadata", "nbformat_minor", "nbformat", "worksheets"],
  "properties": {
    "metadata": {
      "description": "Notebook root-level metadata.",
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "kernel_info": {
          "description": "Kernel information.",
          "type": "object",
          "required": ["name", "language"],
          "properties": {
            "name": {
              "description": "Name of the kernel specification.",
              "type": "string"
            },
            "language": {
              "description": "The programming language which this kernel runs.",
              "type": "string"
            },
            "codemirror_mode": {
              "description": "The codemirror mode to use for code in this language.",
              "type": "string"
            }
          }
        },
        "signature": {
          "description": "Hash of the notebook.",
          "type": "string"
        }
      }
    },
    "nbformat_minor": {
      "description": "Notebook format (minor number). Incremented for backward compatible changes to the notebook format.",
      "type": "integer",
      "minimum": 0
    },
    "nbformat": {
      "description": "Notebook format (major number). Incremented between backwards incompatible changes to the notebook format.",
      "type": "integer",
      "minimum": 3,
      "maximum": 3
    },
    "orig_nbformat": {
      "description": "Original notebook format (major number) before converting the notebook between versions.",
      "type": "integer",
      "minimum": 1
    },
    "orig_nbformat_minor": {
      "description": "Original notebook format (minor number) before converting the notebook between versions.",
      "type": "integer",
      "minimum": 0
    },
    "worksheets": {
      "description": "Array of worksheets",
      "type": "array",
      "items": { "$ref": "#/definitions/worksheet" }
    }
  },

  "definitions": {
    "worksheet": {
      "additionalProperties": false,
      "required": ["cells"],
      "properties": {
        "cells": {
          "description": "Array of cells of the current notebook.",
          "type": "array",
          "items": {
            "type": "object",
            "oneOf": [
              { "$ref": "#/definitions/raw_cell" },
              { "$ref": "#/definitions/markdown_cell" },
              { "$ref": "#/definitions/heading_cell" },
              { "$ref": "#/definitions/code_cell" }
            ]
          }
        },
        "metadata": {
          "type": "object",
          "description": "metadata of the current worksheet"
        }
      }
    },
    "raw_cell": {
      "description": "Notebook raw nbconvert cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["raw"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true,
          "properties": {
            "format": {
              "description": "Raw cell metadata format for nbconvert.",
              "type": "string"
            },
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          }
        },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "markdown_cell": {
      "description": "Notebook markdown cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "source"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["markdown", "html"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "properties": {
            "name": { "$ref": "#/definitions/misc/metadata_name" },
            "tags": { "$ref": "#/definitions/misc/metadata_tags" }
          },
          "additionalProperties": true
        },
        "source": { "$ref": "#/definitions/misc/source" }
      }
    },

    "heading_cell": {
      "description": "Notebook heading cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "source", "level"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["heading"]
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true
        },
        "source": { "$ref": "#/definitions/misc/source" },
        "level": {
          "description": "Level of heading cells.",
          "type": "integer",
          "minimum": 1
        }
      }
    },

    "code_cell": {
      "description": "Notebook code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["cell_type", "input", "outputs", "language"],
      "properties": {
        "cell_type": {
          "description": "String identifying the type of cell.",
          "enum": ["code"]
        },
        "language": {
          "description": "The cell's language (always Python)",
          "type": "string"
        },
        "collapsed": {
          "description": "Whether the cell is collapsed/expanded.",
          "type": "boolean"
        },
        "metadata": {
          "description": "Cell-level metadata.",
          "type": "object",
          "additionalProperties": true
        },
        "input": { "$ref": "#/definitions/misc/source" },
        "outputs": {
          "description": "Execution, display, or stream outputs.",
          "type": "array",
          "items": { "$ref": "#/definitions/output" }
        },
        "prompt_number": {
          "description": "The code cell's prompt number. Will be null if the cell has not been run.",
          "type": ["integer", "null"],
          "minimum": 0
        }
      }
    },
    "output": {
      "type": "object",
      "oneOf": [
        { "$ref": "#/definitions/pyout" },
        { "$ref": "#/definitions/display_data" },
        { "$ref": "#/definitions/stream" },
        { "$ref": "#/definitions/pyerr" }
      ]
    },
    "pyout": {
      "description": "Result of executing a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "prompt_number"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["pyout"]
        },
        "prompt_number": {
          "description": "A result's prompt number.",
          "type": ["integer"],
          "minimum": 0
        },
        "text": { "$ref": "#/definitions/misc/multiline_string" },
        "latex": { "$ref": "#/definitions/misc/multiline_string" },
        "png": { "$ref": "#/definitions/misc/multiline_string" },
        "jpeg": { "$ref": "#/definitions/misc/multiline_string" },
        "svg": { "$ref": "#/definitions/misc/multiline_string" },
        "html": { "$ref": "#/definitions/misc/multiline_string" },
        "javascript": { "$ref": "#/definitions/misc/multiline_string" },
        "json": { "$ref": "#/definitions/misc/multiline_string" },
        "pdf": { "$ref": "#/definitions/misc/multiline_string" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      },
      "patternProperties": {
        "^[a-zA-Z0-9]+/[a-zA-Z0-9\\-\\+\\.]+$": {
          "description": "mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "display_data": {
      "description": "Data displayed as a result of code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["display_data"]
        },
        "text": { "$ref": "#/definitions/misc/multiline_string" },
        "latex": { "$ref": "#/definitions/misc/multiline_string" },
        "png": { "$ref": "#/definitions/misc/multiline_string" },
        "jpeg": { "$ref": "#/definitions/misc/multiline_string" },
        "svg": { "$ref": "#/definitions/misc/multiline_string" },
        "html": { "$ref": "#/definitions/misc/multiline_string" },
        "javascript": { "$ref": "#/definitions/misc/multiline_string" },
        "json": { "$ref": "#/definitions/misc/multiline_string" },
        "pdf": { "$ref": "#/definitions/misc/multiline_string" },
        "metadata": { "$ref": "#/definitions/misc/output_metadata" }
      },
      "patternProperties": {
        "[a-zA-Z0-9]+/[a-zA-Z0-9\\-\\+\\.]+$": {
          "description": "mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "stream": {
      "description": "Stream output from a code cell.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "stream", "text"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["stream"]
        },
        "stream": {
          "description": "The stream type/destination.",
          "type": "string"
        },
        "text": {
          "description": "The stream's text output, represented as an array of strings.",
          "$ref": "#/definitions/misc/multiline_string"
        }
      }
    },

    "pyerr": {
      "description": "Output of an error that occurred during code cell execution.",
      "type": "object",
      "additionalProperties": false,
      "required": ["output_type", "ename", "evalue", "traceback"],
      "properties": {
        "output_type": {
          "description": "Type of cell output.",
          "enum": ["pyerr"]
        },
        "ename": {
          "description": "The name of the error.",
          "type": "string"
        },
        "evalue": {
          "description": "The value, or message, of the error.",
          "type": "string"
        },
        "traceback": {
          "description": "The error's traceback, represented as an array of strings.",
          "type": "array",
          "items": { "type": "string" }
        }
      }
    },

    "misc": {
      "metadata_name": {
        "description": "The cell's name. If present, must be a non-empty string.",
        "type": "string",
        "pattern": "^.+$"
      },
      "metadata_tags": {
        "description": "The cell's tags. Tags must be unique, and must not contain commas.",
        "type": "array",
        "uniqueItems": true,
        "items": {
          "type": "string",
          "pattern": "^[^,]+$"
        }
      },
      "source": {
        "description": "Contents of the cell, represented as an array of lines.",
        "$ref": "#/definitions/misc/multiline_string"
      },
      "prompt_number": {
        "description": "The code cell's prompt number. Will be null if the cell has not been run.",
        "type": ["integer", "null"],
        "minimum": 0
      },
      "mimetype": {
        "patternProperties": {
          "^[a-zA-Z0-9\\-\\+]+/[a-zA-Z0-9\\-\\+]+": {
            "description": "The cell's mimetype output (e.g. text/plain), represented as either an array of strings or a string.",
            "$ref": "#/definitions/misc/multiline_string"
          }
        }
      },
      "output_metadata": {
        "description": "Cell output metadata.",
        "type": "object",
        "additionalProperties": true
      },
      "multiline_string": {
        "oneOf": [
          { "type": "string" },
          {
            "type": "array",
            "items": { "type": "string" }
          }
        ]
      }
    }
  }
}
