diff --git a/swh/web/api/apidoc.py b/swh/web/api/apidoc.py --- a/swh/web/api/apidoc.py +++ b/swh/web/api/apidoc.py @@ -63,6 +63,7 @@ self.reqheaders_set = set() self.resheaders_set = set() self.field_list_visited = False + self.current_json_obj = None def process_paragraph(self, par): """ @@ -82,8 +83,12 @@ # remove parsed document markups par = re.sub('<[^<]+?>', '', par) # api urls cleanup to generate valid links afterwards - par = re.sub(r'\(\w+\)', '', par) - par = re.sub(r'\[.*\]', '', par) + subs_made = 1 + while subs_made: + (par, subs_made) = re.subn(r'(:http:.*)(\(\w+\))', r'\1', par) + subs_made = 1 + while subs_made: + (par, subs_made) = re.subn(r'(:http:.*)(\[.*\])', r'\1', par) par = par.replace('//', '/') # transform references to api endpoints into valid rst links par = re.sub(':http:get:`([^,]*)`', r'`<\1>`_', par) @@ -135,6 +140,7 @@ 'type': field_data[1], 'doc': text}) self.inputs_set.add(field_data[2]) + self.current_json_obj = self.data['inputs'][-1] # Response type if (field_data[0] in self.response_json_array_roles or field_data[0] in self.response_json_object_roles): @@ -150,6 +156,7 @@ 'type': field_data[1], 'doc': text}) self.returns_set.add(field_data[2]) + self.current_json_obj = self.data['returns'][-1] # Status Codes if field_data[0] in self.status_code_roles: if field_data[1] not in self.status_codes_set: @@ -218,6 +225,14 @@ if isinstance(child, docutils.nodes.paragraph): line_text = self.process_paragraph(str(child)) self.data['description'] += '\t* %s\n' % line_text + elif self.current_json_obj: + self.current_json_obj['doc'] += '\n\n' + for child in node.traverse(): + # process list item + if isinstance(child, docutils.nodes.paragraph): + line_text = self.process_paragraph(str(child)) + self.current_json_obj['doc'] += '\t\t* %s\n' % line_text + self.current_json_obj = None def visit_warning(self, node): text = self.process_paragraph(str(node)) diff --git a/swh/web/assets/src/bundles/webapp/webapp.css b/swh/web/assets/src/bundles/webapp/webapp.css --- a/swh/web/assets/src/bundles/webapp/webapp.css +++ b/swh/web/assets/src/bundles/webapp/webapp.css @@ -507,6 +507,12 @@ margin: 10px; } +.swh-apidoc .swh-rst blockquote { + border: 0; + margin: 0; + padding: 0; +} + a.toggle-col { text-decoration: none; } diff --git a/swh/web/common/middlewares.py b/swh/web/common/middlewares.py --- a/swh/web/common/middlewares.py +++ b/swh/web/common/middlewares.py @@ -3,10 +3,11 @@ # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information -from bs4 import BeautifulSoup from htmlmin import minify import sentry_sdk +from swh.web.common.utils import prettify_html + class HtmlPrettifyMiddleware(object): """ @@ -22,11 +23,10 @@ if 'text/html' in response.get('Content-Type', ''): if hasattr(response, 'content'): content = response.content - response.content = BeautifulSoup(content, 'lxml').prettify() + response.content = prettify_html(content) elif hasattr(response, 'streaming_content'): content = b''.join(response.streaming_content) - response.streaming_content = \ - BeautifulSoup(content, 'lxml').prettify() + response.streaming_content = prettify_html(content) return response diff --git a/swh/web/common/swh_templatetags.py b/swh/web/common/swh_templatetags.py --- a/swh/web/common/swh_templatetags.py +++ b/swh/web/common/swh_templatetags.py @@ -6,8 +6,6 @@ import json import re -from inspect import cleandoc - from django import template from django.core.serializers.json import DjangoJSONEncoder from django.utils.safestring import mark_safe @@ -21,12 +19,12 @@ @register.filter -def safe_docstring_display(docstring): +def docstring_display(docstring): """ Utility function to htmlize reST-formatted documentation in browsable api. """ - return rst_to_html(cleandoc(docstring)) + return rst_to_html(docstring) @register.filter diff --git a/swh/web/common/utils.py b/swh/web/common/utils.py --- a/swh/web/common/utils.py +++ b/swh/web/common/utils.py @@ -14,6 +14,8 @@ import docutils.parsers.rst import docutils.utils +from bs4 import BeautifulSoup + from docutils.core import publish_parts from docutils.writers.html5_polyglot import Writer, HTMLTranslator @@ -477,3 +479,16 @@ pp = publish_parts(rst, writer=_HTML_WRITER, settings_overrides=settings) return f'
\n' - ' \n' - ' Input array of pids\n' - ' \n' - ' \n' - '
\n' - '\n' - ' \n' - ' an array of objects containing the following keys:\n' - ' \n' - ' \n' - '
type (string): swh object type
sha1_git (string): swh object sha1_git
found (boolean): whether the object was found or not
\n' + ' Input array of pids\n' + '
\n' + '\n' + ' an object containing the following keys:\n' + '
\n' + '\n' + '\n' + '\n' + '
\n' + '- \n' + '
\n' + '\n' + ' \n' + ' <swh_pid> (object)\n' + ' \n' + ' : an object whose keys are input persistent identifiers' + ' and values objects with the following keys:\n' + '
\n' + '\n' + '\n' + '\n' + '
\n' + '- \n' + '
\n' + '\n' + ' \n' + ' known (bool)\n' + ' \n' + ' : whether the object was found\n' + '
\n' + '
This is my list header:
\n' + '\n' '\n' '\n' '
\n' '- \n' '
Here is item 1, with a continuation\n' 'line right here
- \n' '
Here is item 2
Here is something that is not part of the list
\n' + '