mirror of https://github.com/zulip/zulip.git
openapi: Create markdown extension for rendering endpoint descriptions.
Add function in openapi.py to access endpoint descriptions written in zulip.yaml. Use this function for creating a markdown extension for rendering endpoint descriptions written in zulip.yaml. We use this extension for a single endpoint to get test coverage.
This commit is contained in:
parent
cfe427b3f7
commit
64c6bab276
|
@ -1,9 +1,6 @@
|
|||
# Add an emoji reaction
|
||||
|
||||
Add an [emoji reaction](/help/emoji-reactions) to a message.
|
||||
|
||||
`POST {{ api_url }}/v1/messages/{message_id}/reactions`
|
||||
|
||||
{generate_api_description(/messages/{message_id}/reactions:post)}
|
||||
|
||||
## Usage examples
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import re
|
||||
from markdown.extensions import Extension
|
||||
from markdown.preprocessors import Preprocessor
|
||||
from typing import Any, Dict, Optional, List
|
||||
import markdown
|
||||
|
||||
from zerver.openapi.openapi import get_openapi_description
|
||||
|
||||
MACRO_REGEXP = re.compile(r'\{generate_api_description(\(\s*(.+?)\s*\))}')
|
||||
|
||||
class APIDescriptionGenerator(Extension):
|
||||
def __init__(self, api_url: Optional[str]) -> None:
|
||||
self.config = {
|
||||
'api_url': [
|
||||
api_url,
|
||||
'API URL to use when rendering api links'
|
||||
]
|
||||
}
|
||||
|
||||
def extendMarkdown(self, md: markdown.Markdown, md_globals: Dict[str, Any]) -> None:
|
||||
md.preprocessors.add(
|
||||
'generate_api_description', APIDescriptionPreprocessor(md, self.getConfigs()), '_begin'
|
||||
)
|
||||
|
||||
class APIDescriptionPreprocessor(Preprocessor):
|
||||
def __init__(self, md: markdown.Markdown, config: Dict[str, Any]) -> None:
|
||||
super().__init__(md)
|
||||
self.api_url = config['api_url']
|
||||
|
||||
def run(self, lines: List[str]) -> List[str]:
|
||||
done = False
|
||||
while not done:
|
||||
for line in lines:
|
||||
loc = lines.index(line)
|
||||
match = MACRO_REGEXP.search(line)
|
||||
|
||||
if match:
|
||||
function = match.group(2)
|
||||
text = self.render_description(function)
|
||||
# The line that contains the directive to include the macro
|
||||
# may be preceded or followed by text or tags, in that case
|
||||
# we need to make sure that any preceding or following text
|
||||
# stays the same.
|
||||
line_split = MACRO_REGEXP.split(line, maxsplit=0)
|
||||
preceding = line_split[0]
|
||||
following = line_split[-1]
|
||||
text = [preceding] + text + [following]
|
||||
lines = lines[:loc] + text + lines[loc+1:]
|
||||
break
|
||||
else:
|
||||
done = True
|
||||
return lines
|
||||
|
||||
def render_description(self, function: str) -> List[str]:
|
||||
description: List[str] = []
|
||||
path, method = function.rsplit(':', 1)
|
||||
description_dict = get_openapi_description(path, method)
|
||||
description_dict = description_dict.replace('{{api_url}}', self.api_url)
|
||||
description.extend(description_dict.splitlines())
|
||||
return description
|
||||
|
||||
def makeExtension(*args: Any, **kwargs: str) -> APIDescriptionGenerator:
|
||||
return APIDescriptionGenerator(*args, **kwargs)
|
|
@ -79,6 +79,12 @@ def get_openapi_fixture(endpoint: str, method: str,
|
|||
response = '200'
|
||||
return (get_schema(endpoint, method, response)['example'])
|
||||
|
||||
def get_openapi_description(endpoint: str, method: str) -> str:
|
||||
"""Fetch a description from the full spec object.
|
||||
"""
|
||||
description = openapi_spec.spec()['paths'][endpoint][method.lower()]['description']
|
||||
return description
|
||||
|
||||
def get_openapi_paths() -> Set[str]:
|
||||
return set(openapi_spec.spec()['paths'].keys())
|
||||
|
||||
|
|
|
@ -818,7 +818,9 @@ paths:
|
|||
/messages/{message_id}/reactions:
|
||||
post:
|
||||
description: |
|
||||
Add an emoji reaction to a message.
|
||||
Add an [emoji reaction](/help/emoji-reactions) to a message.
|
||||
|
||||
`POST {{ api_url }}/v1/messages/{message_id}/reactions`
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/MessageId'
|
||||
- name: emoji_name
|
||||
|
|
|
@ -12,6 +12,7 @@ from jinja2.exceptions import TemplateNotFound
|
|||
import zerver.lib.bugdown.fenced_code
|
||||
import zerver.lib.bugdown.api_arguments_table_generator
|
||||
import zerver.lib.bugdown.api_code_examples
|
||||
import zerver.lib.bugdown.api_description
|
||||
import zerver.lib.bugdown.nested_code_blocks
|
||||
import zerver.lib.bugdown.tabbed_sections
|
||||
import zerver.lib.bugdown.help_settings_links
|
||||
|
@ -126,6 +127,9 @@ def render_markdown_path(markdown_file_path: str,
|
|||
extensions = extensions + [zerver.lib.bugdown.api_code_examples.makeExtension(
|
||||
api_url=context["api_url"],
|
||||
)]
|
||||
extensions = extensions + [zerver.lib.bugdown.api_description.makeExtension(
|
||||
api_url=context["api_url"],
|
||||
)]
|
||||
if not any(doc in markdown_file_path for doc in docs_without_macros):
|
||||
extensions = extensions + [md_macro_extension]
|
||||
|
||||
|
|
Loading…
Reference in New Issue