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)
|