mirror of
https://github.com/zulip/zulip.git
synced 2025-11-12 18:06:44 +00:00
api docs: Redesign visuals for documenting arguments.
The previous system for documenting arguments was very ugly if any of the examples or descriptions were wrong. After thinking about this for a while, I concluded the core problem was that a table was the wrong design element to use for API parameters, and we'd be much better off with individual card-type widgets instead. This rewrites the API arguments documentation implementation to use a basic sort of card-like system with some basic styling; I think the result is a lot more readable, and it's a lot more clear how we would add additional OpenAPI details (like parameter types) to the documentation.
This commit is contained in:
@@ -291,6 +291,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
/* Copied from rendered_markdown.scss */
|
||||||
|
font-size: 0.857em;
|
||||||
|
unicode-bidi: embed;
|
||||||
|
direction: ltr;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
padding: 0px 4px;
|
||||||
|
background-color: hsl(0, 0%, 100%);
|
||||||
|
}
|
||||||
|
|
||||||
.code-section {
|
.code-section {
|
||||||
ol {
|
ol {
|
||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
|
|||||||
@@ -1717,14 +1717,27 @@ input.new-organization-button {
|
|||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table .json-api-example {
|
.api-argument {
|
||||||
width: fit-content;
|
.api-argument-name {
|
||||||
max-width: 300px;
|
font-family: monospace;
|
||||||
word-wrap: break-word;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.table .json-api-example code {
|
.api-argument-example-label {
|
||||||
white-space: pre-wrap;
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-argument-required {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 12px;
|
||||||
|
color: hsl(14, 75%, 60%);
|
||||||
|
}
|
||||||
|
.api-argument-optional {
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
color: hsl(0, 0%, 47%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.desktop-redirect-box {
|
.desktop-redirect-box {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import ujson
|
import json
|
||||||
|
|
||||||
from django.utils.html import escape as escape_html
|
from django.utils.html import escape as escape_html
|
||||||
from markdown.extensions import Extension
|
from markdown.extensions import Extension
|
||||||
@@ -67,7 +67,7 @@ class APIArgumentsTablePreprocessor(Preprocessor):
|
|||||||
raise e
|
raise e
|
||||||
else:
|
else:
|
||||||
with open(filename, 'r') as fp:
|
with open(filename, 'r') as fp:
|
||||||
json_obj = ujson.load(fp)
|
json_obj = json.load(fp)
|
||||||
arguments = json_obj[doc_name]
|
arguments = json_obj[doc_name]
|
||||||
|
|
||||||
if arguments:
|
if arguments:
|
||||||
@@ -89,29 +89,17 @@ class APIArgumentsTablePreprocessor(Preprocessor):
|
|||||||
return lines
|
return lines
|
||||||
|
|
||||||
def render_table(self, arguments: List[Dict[str, Any]]) -> List[str]:
|
def render_table(self, arguments: List[Dict[str, Any]]) -> List[str]:
|
||||||
|
# TODO: Fix naming now that this no longer renders a table.
|
||||||
table = []
|
table = []
|
||||||
beginning = """
|
argument_template = """
|
||||||
<table class="table">
|
<div class="api-argument">
|
||||||
<thead>
|
<p class="api-argument-name"><strong>{argument}</strong> {required}</p>
|
||||||
<tr>
|
<div class="api-example">
|
||||||
<th>Argument</th>
|
<span class="api-argument-example-label">Example</span>: <code>{example}</code>
|
||||||
<th>Example</th>
|
</div>
|
||||||
<th>Required</th>
|
<div class="api-description">{description}</div>
|
||||||
<th>Description</th>
|
<hr />
|
||||||
</tr>
|
</div>"""
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
"""
|
|
||||||
tr = """
|
|
||||||
<tr>
|
|
||||||
<td><code>{argument}</code></td>
|
|
||||||
<td class="json-api-example"><code>{example}</code></td>
|
|
||||||
<td>{required}</td>
|
|
||||||
<td>{description}</td>
|
|
||||||
</tr>
|
|
||||||
"""
|
|
||||||
|
|
||||||
table.append(beginning)
|
|
||||||
|
|
||||||
md_engine = markdown.Markdown(extensions=[])
|
md_engine = markdown.Markdown(extensions=[])
|
||||||
|
|
||||||
@@ -125,23 +113,20 @@ class APIArgumentsTablePreprocessor(Preprocessor):
|
|||||||
|
|
||||||
default = argument.get('schema', {}).get('default')
|
default = argument.get('schema', {}).get('default')
|
||||||
if default is not None:
|
if default is not None:
|
||||||
description += '\nDefaults to `{}`.'.format(ujson.dumps(default))
|
description += '\nDefaults to `{}`.'.format(json.dumps(default))
|
||||||
|
|
||||||
# TODO: Swagger allows indicating where the argument goes
|
# TODO: OpenAPI allows indicating where the argument goes
|
||||||
# (path, querystring, form data...). A column in the table should
|
# (path, querystring, form data...). We should document this detail.
|
||||||
# be added for this.
|
table.append(argument_template.format(
|
||||||
table.append(tr.format(
|
|
||||||
argument=argument.get('argument') or argument.get('name'),
|
argument=argument.get('argument') or argument.get('name'),
|
||||||
# Show this as JSON to avoid changing the quoting style, which
|
# Show this as JSON to avoid changing the quoting style, which
|
||||||
# may cause problems with JSON encoding.
|
# may cause problems with JSON encoding.
|
||||||
example=escape_html(ujson.dumps(argument['example'])),
|
example=escape_html(json.dumps(argument['example'])),
|
||||||
required='Yes' if argument.get('required') else 'No',
|
required='<span class="api-argument-required">required</span>' if argument.get('required')
|
||||||
|
else '<span class="api-argument-optional">optional</span>',
|
||||||
description=md_engine.convert(description),
|
description=md_engine.convert(description),
|
||||||
))
|
))
|
||||||
|
|
||||||
table.append("</tbody>")
|
|
||||||
table.append("</table>")
|
|
||||||
|
|
||||||
return table
|
return table
|
||||||
|
|
||||||
def makeExtension(*args: Any, **kwargs: str) -> MarkdownArgumentsTableGenerator:
|
def makeExtension(*args: Any, **kwargs: str) -> MarkdownArgumentsTableGenerator:
|
||||||
|
|||||||
@@ -1328,39 +1328,13 @@ paths:
|
|||||||
|
|
||||||
example: [
|
example: [
|
||||||
{
|
{
|
||||||
"id":1,
|
"id": 4,
|
||||||
"value":"short text data"
|
"value": "vim"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id":2,
|
"id": 5,
|
||||||
"value":"long text data"
|
"value": "1909-04-05"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id":3,
|
|
||||||
"value":"short text data"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":4,
|
|
||||||
"value":"vim"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":5,
|
|
||||||
"value":"1909-3-5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":6,
|
|
||||||
"value":"https:\/\/zulipchat.com"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":7,
|
|
||||||
"value":[
|
|
||||||
12
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id":8,
|
|
||||||
"value":"cordelia"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
required: false
|
required: false
|
||||||
|
|
||||||
@@ -2419,8 +2393,9 @@ paths:
|
|||||||
example: ['message']
|
example: ['message']
|
||||||
- name: narrow
|
- name: narrow
|
||||||
in: query
|
in: query
|
||||||
description: A JSON-encoded array of length 2 indicating the narrow
|
description: |
|
||||||
for which you'd like to receive events for. For instance, to
|
A JSON-encoded array of length 2 indicating the narrow
|
||||||
|
for which you'd like to receive events. For instance, to
|
||||||
receive events for the stream `Denmark`, you would specify
|
receive events for the stream `Denmark`, you would specify
|
||||||
`narrow=['stream', 'Denmark']`. Another example is
|
`narrow=['stream', 'Denmark']`. Another example is
|
||||||
`narrow=['is', 'private']` for private messages.
|
`narrow=['is', 'private']` for private messages.
|
||||||
@@ -2951,7 +2926,7 @@ paths:
|
|||||||
description: |
|
description: |
|
||||||
Whether the stream is limited to announcements.
|
Whether the stream is limited to announcements.
|
||||||
|
|
||||||
**Changes**: Deprecated in Zulip 2.2, use stream_post_policy instead.
|
**Changes**: Deprecated in Zulip 2.2, use `stream_post_policy` instead.
|
||||||
schema:
|
schema:
|
||||||
type: boolean
|
type: boolean
|
||||||
example: true
|
example: true
|
||||||
@@ -2965,7 +2940,7 @@ paths:
|
|||||||
* 2 => Only administrators can post.
|
* 2 => Only administrators can post.
|
||||||
* 3 => Only new members can post.
|
* 3 => Only new members can post.
|
||||||
|
|
||||||
**Changes**: New in Zulip 2.2, replacing the previous is_announcement_only
|
**Changes**: New in Zulip 2.2, replacing the previous `is_announcement_only`
|
||||||
boolean.
|
boolean.
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
@@ -2973,7 +2948,9 @@ paths:
|
|||||||
required: false
|
required: false
|
||||||
- name: history_public_to_subscribers
|
- name: history_public_to_subscribers
|
||||||
in: query
|
in: query
|
||||||
description: The new state for the history_public_to_subscribers.
|
description: |
|
||||||
|
Whether subscribers have access to full stream history, even before they joined
|
||||||
|
the stream.
|
||||||
schema:
|
schema:
|
||||||
type: boolean
|
type: boolean
|
||||||
example: true
|
example: true
|
||||||
|
|||||||
Reference in New Issue
Block a user