-
Notifications
You must be signed in to change notification settings - Fork 232
Expand file tree
/
Copy pathjsonschema2md.py
More file actions
87 lines (70 loc) · 2.51 KB
/
jsonschema2md.py
File metadata and controls
87 lines (70 loc) · 2.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import json
import sys
from argparse import ArgumentParser, FileType
def describe_array(prop: dict) -> str:
extra = ""
if "items" in prop:
unique_qualifier = ""
if "uniqueItems" in prop:
unique_qualifier = "unique" if prop["uniqueItems"] else "non-unique"
item_type = describe_type(prop["items"])
extra = " ".join(filter(bool, ["of", unique_qualifier, item_type, "items"]))
return extra
def describe_number(prop: dict) -> str:
extra = []
if "minimum" in prop:
extra.append(f">= {prop['minimum']}")
if "maximum" in prop:
extra.append(f"<= {prop['maximum']}")
return ",".join(extra)
EXTRA_DESCRIPTORS = {
"array": describe_array,
"number": describe_number,
}
def describe_type(prop: dict) -> str:
prop_type = prop["type"]
types = prop_type if isinstance(prop_type, list) else [prop_type]
if "null" in types:
types.remove("null")
if len(types) == 1:
prop_type = types[0]
parts = [f"`{prop_type}`"]
for option in types:
if option in EXTRA_DESCRIPTORS:
parts.append(EXTRA_DESCRIPTORS[option](prop))
if "enum" in prop:
allowed_values = [f"`{value!r}`" for value in prop["enum"]]
parts.append("(one of: " + ", ".join(allowed_values) + ")")
return " ".join(parts)
def convert_schema(schema: dict, source: str = None) -> str:
lines = [
f"# {schema['title']}",
schema["description"],
"",
"| **Configuration Key** | **Type** | **Description** | **Default** ",
"|----|----|----|----|",
]
for key, prop in schema["properties"].items():
description = prop.get("description", "")
default = json.dumps(prop.get("default", ""))
lines.append(
f"| `{key}` | {describe_type(prop)} | {description} | `{default}` |"
)
if source:
lines.append(
f"\nThis documentation was generated from `{source}`."
" Please do not edit this file directly."
)
# ensure empty line at the end
lines.append("")
return "\n".join(lines)
def main(argv) -> None:
parser = ArgumentParser()
parser.add_argument("schema", type=FileType())
parser.add_argument("markdown", type=FileType("w+"), default=sys.stdout)
arguments = parser.parse_args(argv[1:])
schema = json.loads(arguments.schema.read())
markdown = convert_schema(schema, source=arguments.schema.name)
arguments.markdown.write(markdown)
if __name__ == "__main__":
main(sys.argv)