Skip to content

Instantly share code, notes, and snippets.

@tarleb
Last active January 26, 2023 03:26
Show Gist options
  • Save tarleb/bcb4b31e35263fcbc6cf7e533670c1cf to your computer and use it in GitHub Desktop.
Save tarleb/bcb4b31e35263fcbc6cf7e533670c1cf to your computer and use it in GitHub Desktop.
Schema for pandoc json
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"Attr": {
"type": "array",
"items": [
{"type": "string"},
{"type": "array", "items": {"type": "string"}},
{
"type": "array",
"items": {
"type": "array",
"items": [
{"type": "string"},
{"type": "string"}
]
}
}
]
},
"ListAttributes": {
"type": "array",
"items": [
{"type": "integer"},
{
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": [
"DefaultStyle", "Example", "Decimal",
"LowerRoman", "UpperRoman",
"LowerAlpha", "UpperAlpha"
]
}
}
},
{
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": [
"DefaultDelim", "Period",
"OneParen", "TwoParens"
]
}
}
}
]
},
"Alignment": {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": [
"AlignLeft", "AlignRight", "AlignCenter", "AlignDefault"
]
}
}
},
"TableCell": {
"type": "array",
"items": {"$ref": "#/definitions/Block"}
},
"Target": {
"type": "array",
"items": [
{"type": "string"},
{"type": "string"}
]
},
"Citation": {
"type": "object",
"properties": {
"citationId": {"type": "string"},
"citationPrefix": {
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
},
"citationSuffix": {
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
},
"citationMode": {"$ref": "#/definitions/CitationMode"},
"citationNoteNum": {"type": "integer"},
"citationHash": {"type": "integer"}
}
},
"CitationMode": {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": ["AuthorInText", "SuppressAuthor", "NormalCitation"]
}
}
},
"MathType": {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": ["DisplayMath", "InlineMath"]
}
}
},
"QuoteType": {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": ["SingleQuote", "DoubleQuote"]
}
}
},
"Block": {
"oneOf": [{
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "Plain"},
"c": {
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "Para"},
"c": {
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "LineBlock"},
"c": {
"type": "array",
"items": {
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
}
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "CodeBlock"},
"c": {
"type": "array",
"items": [{
"$ref": "#/definitions/Attr"
}, {
"type": "string"
}]
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "RawBlock"},
"c": {
"type": "array",
"items": [{"type": "string"}, {"type": "string"}]
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "BlockQuote"},
"c": {
"type": "array",
"items": {"$ref": "#/definitions/Block"}
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "OrderedList"},
"c": {
"type": "array",
"items": [
{"$ref": "#/definitions/ListAttributes"},
{
"type": "array",
"items": {
"type": "array",
"items": {"$ref": "#/definitions/Block"}
}
}
]
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "BulletList"},
"c": {
"type": "array",
"items": {
"type": "array",
"items": {"$ref": "#/definitions/Block"}
}
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "DefinitionList"},
"c": {
"type": "array",
"items": {
"type": "array",
"items": [
{
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
} , {
"type": "array",
"items": {
"type": "array",
"items": {"$ref": "#/definitions/Block"}
}
}
]
}
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "Header"},
"c": {
"type": "array",
"items": [
{
"type": "integer"
}, {
"$ref": "#/definitions/Attr"
}, {
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
}
]
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "enum": ["HorizontalRule", "Null"]}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "Table"},
"c": {
"type": "array",
"items": [{
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
}, {
"type": "array",
"items": {"$ref": "#/definitions/Alignment"}
}, {
"type": "array",
"items": {"type": "number"}
}, {
"type": "array",
"items": {"$ref": "#/definitions/TableCell"}
}, {
"type": "array",
"items": {
"type": "array",
"items": {"$ref": "#/definitions/TableCell"}
}
}]
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "Div"},
"c": {
"type": "array",
"items": [{
"$ref": "#/definitions/Attr"
}, {
"type": "array",
"items": {"$ref": "#/definitions/Block"}
}]
}
}
}]
},
"Inline": {
"anyOf": [{
"type": "object",
"properties": {
"t": {"type": "string", "pattern": "Str"},
"c": {"type": "string"}
}
}, {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": [
"Emph", "Strong", "Strikeout", "Superscript",
"Subscript", "SmallCaps"
]
},
"c": {
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
}
}
}, {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": ["Quoted"]
},
"c": {
"type": "array",
"items": [
{
"$ref": "#/definitions/QuoteType"
}, {
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
}
]
}
}
}, {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": ["Cite"]
},
"c": {
"type": "array",
"items": [
{
"type": "array",
"items": {"$ref": "#/definitions/Citation"}
}, {
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
}
]
}
}
}, {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": ["Code"]
},
"c": {
"type": "array",
"items": [
{
"$ref": "#/definitions/Attr"
}, {
"type": "string"
}
]
}
}
}, {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": ["Math"]
},
"c": {
"type": "array",
"items": [
{
"$ref": "#/definitions/MathType"
}, {
"type": "string"
}
]
}
}
}, {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": ["RawInline"]
},
"c": {
"type": "array",
"items": [
{
"type": "string"
}, {
"type": "string"
}
]
}
}
}, {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": ["Image", "Link"]
},
"c": {
"type": "array",
"items": [
{
"$ref": "#/definitions/Attr"
}, {
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
}, {
"$ref": "#/definitions/Target"
}
]
}
}
}, {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": ["Span"]
},
"c": {
"type": "array",
"items": [
{
"$ref": "#/definitions/Attr"
}, {
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
}
]
}
}
}, {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": ["Note"]
},
"c": {
"type": "array",
"items": {"$ref": "#/definitions/Block"}
}
}
}, {
"type": "object",
"properties": {
"t": {
"type": "string",
"enum": [
"Space", "SoftBreak", "LineBreak"
]
}
}
}]
},
"MetaValue": {
"oneOf": [{
"type": "object",
"properties": {
"t": {"type": "string", "enum": ["MetaBool"]},
"c": {"type": "boolean"}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "enum": ["MetaString"]},
"c": {"type": "string"}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "enum": ["MetaList"]},
"c": {
"type": "array",
"items": {"$ref": "#/definitions/MetaValue"}
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "enum": ["MetaMap"]},
"c": {
"type": "object",
"additionalProperties": {"$ref": "#/definitions/MetaValue"}
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "enum": ["MetaBlocks"]},
"c": {
"type": "array",
"items": {"$ref": "#/definitions/Block"}
}
}
}, {
"type": "object",
"properties": {
"t": {"type": "string", "enum": ["MetaInlines"]},
"c": {
"type": "array",
"items": {"$ref": "#/definitions/Inline"}
}
}
}]
},
"Meta": {
"type": "object",
"additionalProperties": {"$ref": "#/definitions/MetaValue"}
}
},
"title": "pandoc",
"type": "object",
"properties": {
"blocks": {
"type": "array",
"items": {"$ref": "#/definitions/Block"}
},
"meta": {"$ref": "#/definitions/Meta"},
"pandoc-api-version": {
"type": "array",
"items": {"type": "number"}
}
}
}
import Data.Aeson (Value(..), decodeStrict, toJSON)
import Data.Maybe (fromMaybe)
import Data.Monoid ((<>))
import Text.Pandoc.Arbitrary ()
import Text.Pandoc.Definition (Pandoc)
import Test.QuickCheck
import Test.QuickCheck.Monadic (monadicIO, run)
import Test.Tasty (TestTree, defaultMain, testGroup)
import Test.Tasty.QuickCheck (testProperty)
import qualified JSONSchema.Draft4 as D4
import qualified Data.ByteString as BS
import qualified Data.List.NonEmpty as NE
main :: IO ()
main = do
bts <- BS.readFile "./pandoc-schema.json"
let schema = fromMaybe (error "Invalid schema JSON.") (decodeStrict bts)
schemaWithURI = D4.SchemaWithURI schema Nothing
defaultMain $ testGroup "pandoc-schema" (tests schemaWithURI)
tests :: D4.SchemaWithURI D4.Schema -> [TestTree]
tests schema = [ testProperty "arbitrary Pandoc" (prop_pandocJson schema) ]
prop_pandocJson :: D4.SchemaWithURI D4.Schema -> Pandoc -> Property
prop_pandocJson schemaWithURI pd = monadicIO $ do
res <- run $ D4.fetchHTTPAndValidate schemaWithURI (toJSON pd)
case res of
Right () -> pure ()
Left (D4.HVRequest _) -> error ("Error fetching a referenced schema"
<> " (either during IO or parsing).")
Left (D4.HVSchema _) -> error "Our 'schema' itself was invalid."
Left x -> do {run (print x) ; error "nope"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment