From c2d8cd7f5a8a19af8756006481c7156609f20aaf Mon Sep 17 00:00:00 2001 From: mDuo13 Date: Tue, 1 Oct 2019 17:01:08 -0700 Subject: [PATCH] OpenAPI spec parsing: add custom templates w/ warning --- dactyl-config.yml | 1 + .../template-openapi_data_type.md | 64 +++++++++++ .../template-openapi_data_types_toc.md | 11 ++ .../template-openapi_endpoint.md | 107 ++++++++++++++++++ .../template-openapi_endpoint_tag_toc.md | 17 +++ .../template-openapi_endpoint_toc.md | 51 +++++++++ tool/template-github-edit.html | 48 ++++---- 7 files changed, 276 insertions(+), 23 deletions(-) create mode 100644 tool/openapi_templates_alpha/template-openapi_data_type.md create mode 100644 tool/openapi_templates_alpha/template-openapi_data_types_toc.md create mode 100644 tool/openapi_templates_alpha/template-openapi_endpoint.md create mode 100644 tool/openapi_templates_alpha/template-openapi_endpoint_tag_toc.md create mode 100644 tool/openapi_templates_alpha/template-openapi_endpoint_toc.md diff --git a/dactyl-config.yml b/dactyl-config.yml index 9a0f8b7378..23d1a5c154 100644 --- a/dactyl-config.yml +++ b/dactyl-config.yml @@ -2844,6 +2844,7 @@ pages: # API reference generator makes multiple files here - openapi_specification: https://raw.githubusercontent.com/ripple/xrp-api/master/api-doc.yml + openapi_md_template_path: tool/openapi_templates_alpha/ api_slug: xrp-api funnel: Docs doc_type: References diff --git a/tool/openapi_templates_alpha/template-openapi_data_type.md b/tool/openapi_templates_alpha/template-openapi_data_type.md new file mode 100644 index 0000000000..b095cf1caa --- /dev/null +++ b/tool/openapi_templates_alpha/template-openapi_data_type.md @@ -0,0 +1,64 @@ +# {{title}} + +{{description}} + +**Warning:** {{spec.info.title}} is early alpha software. API methods and data formats are likely to change frequently in ways that break backwards compatibility. + +{% if type is defined %}- **Type:** {{type|title}} +{% elif oneOf is defined %}- **Possible Types:** +{% for option in oneOf -%} +{% if option.enum is defined %} + - One of the following {% if option.type is defined %}{{option.type|title}}s{% else %}values{% endif %}: +{% for suboption in option.enum %} + - `{{suboption}}` +{% endfor -%} +{% else %} + - {{option.type|title}} +{% endif -%} +{% endfor -%} +{% elif anyOf is defined %}- **Possible Types:** +{% for option in anyOf -%} +{% if option.enum is defined %} + - Any of the following {% if option.type is defined %}{{option.type|title}}s{% else %}values{% endif %}: +{% for suboption in option.enum %} + - `{{suboption}}` +{% endfor -%} +{% else %} + - {{option.type|title}} +{% endif -%} +{% endfor -%} +{% elif allOf is defined %}- **Possible Types:** +{% for option in allOf -%} +{% if option.enum is defined %} + - Must qualify as all of the following {% if option.type is defined %}{{option.type|title}}s{% else %}values{% endif %}: +{% for suboption in option.enum %} + - `{{suboption}}` +{% endfor -%} +{% else %} + - {{option.type|title}} +{% endif -%} +{% endfor -%} +{% endif -%} +{% if enum is defined %}- **Possible Values:** +{% for option in enum %} + - `{{option}}` +{% endfor %}{% endif %} +{% if pattern is defined %}- **Pattern:** `{{pattern}}` +{% endif -%} +{% if example is defined %}- **Example:** `{{example}}` +{% endif -%} + +{% if properties is defined %} +This type can contain the following fields: + +| Field | Type | Required? | Description | +|-------|------|-----------|-------------| +{%- for name,field in properties.items() %} +| `{{name}}` | {{field.type|title}}{% if "items" in field.keys() and "title" in field["items"].keys() %} of [{{field["items"].title}}]({{type_link(field["items"].title)}}){% endif %} {% if field["title"] is defined %}([{{field.title}}]({{type_link(field.title)}})){% endif %} | {{"Required" if name in required else "Optional"}} | {{field.description}} | +{%- endfor %} + +{% if additionalProperties is defined and additionalProperties == True %}This type MUST NOT contain any additional fields.{% endif %} + +{% elif type == "array" and items is defined %} +Each member of the array is a ***TODO*** {{items}} +{% endif %} diff --git a/tool/openapi_templates_alpha/template-openapi_data_types_toc.md b/tool/openapi_templates_alpha/template-openapi_data_types_toc.md new file mode 100644 index 0000000000..2b396ac3dd --- /dev/null +++ b/tool/openapi_templates_alpha/template-openapi_data_types_toc.md @@ -0,0 +1,11 @@ +# {{api_title}} Data Types + +**Warning:** {{spec.info.title}} is early alpha software. API methods and data formats are likely to change frequently in ways that break backwards compatibility. + +The following data types are defined for this API: + +| Name | Type | Description | +|------|------|-------------| +{%- for key,schema in schemas %} +| `{{schema.title}}` | {{schema.type|title}}{% if "items" in schema.keys() and "title" in schema["items"].keys() %} of [{{schema["items"].title}}]({{type_link(schema["items"].title)}}){% endif %} {% if schema["title"] is defined %}([{{schema.title}}]({{type_link(schema.title)}})){% endif %} | {% if schema.description is defined %}{{schema.description}}{% endif %} | +{%- endfor %} diff --git a/tool/openapi_templates_alpha/template-openapi_endpoint.md b/tool/openapi_templates_alpha/template-openapi_endpoint.md new file mode 100644 index 0000000000..d9a11c2d9d --- /dev/null +++ b/tool/openapi_templates_alpha/template-openapi_endpoint.md @@ -0,0 +1,107 @@ +# {{summary}} + +{{description}} + +**Warning:** {{spec.info.title}} is early alpha software. API methods and data formats are likely to change frequently in ways that break backwards compatibility. + +## Request Format + +``` +{{method|upper}} {{path}} +{%- if method in ["post","put","delete"] and requestBody is defined %} + +{{ x_example_request_body }} +{% endif %} +``` + +{% if path_params|length %} +This API method uses the following path parameters: + +| Field | Value | Required? | Description | +|---|---|---|---| +{%- for param in path_params %} +| `{{param.name}}` | {% if param.schema is defined %}{% if param.schema.oneOf is defined %}(Varies){% else %}{{param.schema.type|title}}{% endif %} {% if param.schema["title"] is defined %}([{{param.schema.title}}]({{type_link(param.schema.title)}})){% endif %}{% else %}(Unspecified){% endif %} | {{"Required" if param.required else "Optional"}} | {{param.description}} | +{%- endfor %} + +{% endif %} + +{% if query_params|length %} +This API method uses the following query parameters: + +| Field | Value | Required? | Description | +|---|---|---|---| +{%- for param in query_params %} +| `{{param.name}}` | {% if param.schema is defined %}{% if param.schema.oneOf is defined %}(Varies){% else %}{{param.schema.type|title}}{% if "items" in param.schema.keys() and "title" in param.schema["items"].keys() %} of [{{param.schema["items"].title}}]({{type_link(param.schema["items"].title)}}){% endif %}{% endif %} {% if param.schema["title"] is defined %}([{{param.schema.title}}]({{type_link(param.schema.title)}})){% endif %}{% else %}(Unspecified){% endif %} | {{"Required" if param.required else "Optional"}} | {{param.description}} | +{%- endfor %} + +{% endif %} + +{% if requestBody is defined %} +{{requestBody.description}} + +{% if requestBody.content is defined %} + +{% for mediatype,thisbody in requestBody.content.items() %} +{% if thisbody.schema is defined %} +**Media type:** {{mediatype|replace("*","\*")}} + +{% if thisbody.schema.title is defined %} +Formatted as a [{{thisbody.schema.title}}]({{type_link(thisbody.schema.title)}}) +{% endif %} +{% if thisbody.schema.properties is defined %} +The request uses the following fields: + +| Field | Type | Required? | Description | +|-------|------|-----------|-------------| +{%- for name,field in thisbody.schema.properties.items() %} +| `{{name}}` | {{field.type|title}}{% if "items" in field.keys() and "title" in field["items"].keys() %} of [{{field["items"].title}}]({{type_link(field["items"].title)}}){% endif %} {% if field["title"] is defined %}([{{field.title}}]({{type_link(field.title)}})){% endif %} | {{"Required" if name in required else "May be omitted"}} | {% if field.description is defined %}{{field.description}}{% endif %} | +{%- endfor %} +{% endif %} + +{% endif %} +{% endfor %} +{% endif %} +{% endif %} + +## Response Formats + +{% for response_code, response in responses.items() %} +### {{response_code}} {{HTTP_STATUS_CODES[response_code]}} + +{{ response.description}} + +{% if response.content is defined %} +{% for mediatype,thisbody in response.content.items() %} +{% if thisbody.schema is defined %} +**Media type:** {{mediatype|replace("*","\*")}} + +{% if thisbody.schema.title is defined %} +Formatted as a [{{thisbody.schema.title}}]({{type_link(thisbody.schema.title)}}) +{% endif %} +{% if thisbody.schema.properties is defined %} +The response uses the following fields: + +| Field | Type | Required? | Description | +|-------|------|-----------|-------------| +{%- for name,field in thisbody.schema.properties.items() %} +| `{{name}}` | {{field.type|title}}{% if "items" in field.keys() and "title" in field["items"].keys() %} of [{{field["items"].title}}]({{type_link(field["items"].title)}}){% endif %} {% if field["title"] is defined %}([{{field.title}}]({{type_link(field.title)}})){% endif %} | {{"Required" if name in required else "May be omitted"}} | {% if field.description is defined %}{{field.description}}{% endif %} | +{%- endfor %} +{% endif %}{# TODO: handle allOf, etc. #} + +{% if thisbody.examples is defined and thisbody.examples|length > 0 %} +#### Example Response(s) + +{% for body_name,body_sample in thisbody.examples %} +_{{body_name}}_ + +``` +{{body_sample|pprint}} +``` +{% endfor %} +{% endif %} + +{% endif %} +{% endfor %} + +{% endif %} +{% endfor %} diff --git a/tool/openapi_templates_alpha/template-openapi_endpoint_tag_toc.md b/tool/openapi_templates_alpha/template-openapi_endpoint_tag_toc.md new file mode 100644 index 0000000000..875b7f1b15 --- /dev/null +++ b/tool/openapi_templates_alpha/template-openapi_endpoint_tag_toc.md @@ -0,0 +1,17 @@ +# {{info.title}} {{info.version}} {{tag.name|title}} Methods + +{{tag.description}} + +**Warning:** {{info.title}} is early alpha software. API methods and data formats are likely to change frequently in ways that break backwards compatibility. + +| Summary | Path | +|:--------|:-----| +{%- set reflinks = [] -%} +{%- for path,method,endpoint in endpoints_by_tag(tag.name) %} +{%- set _ = reflinks.append("["+endpoint.summary+"]: "+method_link(path, method, endpoint) ) %} +| [{{endpoint.summary}}][] | [`{{method|upper}} {{path}}`][{{endpoint.summary}}] | +{%- endfor %} + +{% for reflink in reflinks -%} +{{reflink}} +{% endfor %} diff --git a/tool/openapi_templates_alpha/template-openapi_endpoint_toc.md b/tool/openapi_templates_alpha/template-openapi_endpoint_toc.md new file mode 100644 index 0000000000..659f972357 --- /dev/null +++ b/tool/openapi_templates_alpha/template-openapi_endpoint_toc.md @@ -0,0 +1,51 @@ +# {{info.title}} {{info.version}} Methods + +{{info.description}} + +**Warning:** {{spec.info.title}} is early alpha software. API methods and data formats are likely to change frequently in ways that break backwards compatibility. + +{% if tags %} +View API methods by category: + +{% for tag in tags %} +- [{{tag.name|title}} Methods](#{{slugify(tag.name)|lower}}-methods) +{% endfor %} +{% endif %} + +{% for tag in tags %} +{% if endpoints_by_tag(tag.name)|list|length %} +## {{tag.name|title}} Methods + +{{tag.description}} + +| Summary | Path | +|:--------|:-----| +{%- set reflinks = [] -%} +{%- for path,method,endpoint in endpoints_by_tag(tag.name) %} +{%- set _ = reflinks.append("["+endpoint.summary+"]: "+method_link(path, method, endpoint) ) %} +| [{{endpoint.summary}}][] | [`{{method|upper}} {{path}}`][{{endpoint.summary}}] | +{%- endfor %} + +{% for reflink in reflinks -%} +{{reflink}} +{% endfor %} + +{% endif %} +{% endfor %} + +{% if endpoints_by_tag("Uncategorized")|list|length %} +## Uncategorized Methods + +| Name | Path | Summary | +|:-----|:-----|:--------| +{%- set reflinks = [] -%} +{%- for path,method,endpoint in endpoints_by_tag("Uncategorized") %} +{%- set _ = reflinks.append("["+endpoint.operationId+"]: "+method_link(path, method, endpoint) ) %} +| [{{endpoint.operationId}}][] | [`{{method|upper}} {{path}}`][{{endpoint.operationId}}] | {{endpoint.summary}} | +{%- endfor %} + +{% for reflink in reflinks -%} +{{reflink}} +{% endfor %} + +{% endif %} diff --git a/tool/template-github-edit.html b/tool/template-github-edit.html index 6f1b924307..7404caf067 100644 --- a/tool/template-github-edit.html +++ b/tool/template-github-edit.html @@ -1,26 +1,28 @@
- {% set have_edit_link = False %} - {% if currentpage.md is defined %} - {% if currentpage.md.startswith("http://") or - currentpage.md.startswith("https://") %} - {# Leave have_edit_link = False #} - {% else %} - {% set have_edit_link = True %} - {% set githuburl = target.github_forkurl + "/edit/" - + target.github_branch - + "/content/" + currentpage.md %} - {% endif %} - {% elif currentpage.template is defined %} - {% set have_edit_link = True %} - {% set githuburl = target.github_forkurl + "/edit/" - + target.github_branch + "/tool/" + currentpage.template %} + {% if target.github_forkurl is defined %} + {% set have_edit_link = False %} + {% if currentpage.md is defined %} + {% if currentpage.md.startswith("http://") or + currentpage.md.startswith("https://") %} + {# Leave have_edit_link = False #} + {% else %} + {% set have_edit_link = True %} + {% set githuburl = target.github_forkurl + "/edit/" + + target.github_branch + + "/content/" + currentpage.md %} + {% endif %} + {% elif currentpage.template is defined %} + {% set have_edit_link = True %} + {% set githuburl = target.github_forkurl + "/edit/" + + target.github_branch + "/tool/" + currentpage.template %} + {% endif %} + {% if target.is_pr_build is defined and target.is_pr_build and have_edit_link %} + {% set githuburl = githuburl + "?pr=/ripple/ripple-dev-portal/pull/" + + target.github_pr_id %} + {% endif %} + {% if not have_edit_link %} + {% set githuburl = target.github_forkurl %} + {% endif %} + Edit {% endif %} - {% if target.is_pr_build is defined and target.is_pr_build and have_edit_link %} - {% set githuburl = githuburl + "?pr=/ripple/ripple-dev-portal/pull/" - + target.github_pr_id %} - {% endif %} - {% if not have_edit_link %} - {% set githuburl = target.github_forkurl %} - {% endif %} - Edit