templatags: rendering of $id/$ref in jsonschema (#81643)
gitea/passerelle/pipeline/head This commit looks good
Details
gitea/passerelle/pipeline/head This commit looks good
Details
This commit is contained in:
parent
8266740b52
commit
a9f2956db7
|
@ -110,7 +110,10 @@ def censor(string):
|
|||
return re.sub(r'://([^/]*):([^/]*?)@', r'://\1:***@', string)
|
||||
|
||||
|
||||
def render_json_schema(schema):
|
||||
def render_json_schema(schema, anchor_map=None):
|
||||
if anchor_map is None:
|
||||
anchor_map = {}
|
||||
|
||||
if not isinstance(schema, dict):
|
||||
if schema is True:
|
||||
return mark_safe('<em>%s</em>') % _('always valid')
|
||||
|
@ -133,6 +136,11 @@ def render_json_schema(schema):
|
|||
def html_type(s):
|
||||
return '<span class="type">%s</span>' % s
|
||||
|
||||
def to_id(ref):
|
||||
_ref = ref.lstrip('#')
|
||||
_id = id(anchor_map.get(_ref))
|
||||
return f'schema-object-{_ref}-{_id}'
|
||||
|
||||
if 'anyOf' in schema:
|
||||
return many_of('anyOf', schema['anyOf'])
|
||||
|
||||
|
@ -145,10 +153,17 @@ def render_json_schema(schema):
|
|||
original_schema = schema
|
||||
schema = schema.copy()
|
||||
schema.pop('$schema', None)
|
||||
schema.pop('$id', None)
|
||||
_anchor = schema.pop('$anchor', None)
|
||||
if _anchor:
|
||||
anchor_map.setdefault(_anchor, original_schema)
|
||||
title = schema.pop('title', None)
|
||||
description = schema.pop('description', None)
|
||||
typ = schema.pop('type', None)
|
||||
_ref = schema.pop('$ref', None)
|
||||
if _ref and _ref.startswith('#'):
|
||||
target_schema = anchor_map.get(_ref[1:], {})
|
||||
target_title = target_schema.get('title') or target_schema.get('description') or 'referenced schema'
|
||||
return format_html('<a href="#{}">{}</a>', to_id(_ref), target_title)
|
||||
if typ == 'null':
|
||||
return mark_safe(html_type('null'))
|
||||
if typ == 'string':
|
||||
|
@ -181,10 +196,12 @@ def render_json_schema(schema):
|
|||
if typ == 'array':
|
||||
s = html_type('array') + ' '
|
||||
if 'items' in schema:
|
||||
s += render_json_schema(schema['items'])
|
||||
s += render_json_schema(schema['items'], anchor_map)
|
||||
return mark_safe(s)
|
||||
if typ == 'object':
|
||||
s = html_type('object')
|
||||
if _anchor:
|
||||
s += f'<a id="{to_id(_anchor)}"></a>'
|
||||
unflatten = schema.pop('unflatten', False)
|
||||
merge_extra = schema.pop('merge_extra', False)
|
||||
properties = schema.pop('properties', {})
|
||||
|
@ -211,6 +228,9 @@ def render_json_schema(schema):
|
|||
def render_property_schema(key, html, sub):
|
||||
nonlocal s
|
||||
|
||||
_anchor = sub.get('$anchor', None)
|
||||
if _anchor:
|
||||
anchor_map.setdefault(_anchor, sub.copy())
|
||||
required = key in required_keys
|
||||
sub_description = sub.pop('description', '')
|
||||
sub_title = sub.pop('title', '')
|
||||
|
@ -226,7 +246,7 @@ def render_json_schema(schema):
|
|||
if sub_title or '\n' in sub_description:
|
||||
s += format_html('\n<p class="description">{}</p>', sub_description)
|
||||
if sub:
|
||||
s += format_html('\n{0}', render_json_schema(sub))
|
||||
s += format_html('\n{0}', render_json_schema(sub, anchor_map))
|
||||
s += '</li>'
|
||||
|
||||
if properties or pattern_properties:
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import inspect
|
||||
import re
|
||||
|
||||
from django.apps import apps
|
||||
from django.utils import translation
|
||||
|
@ -99,3 +100,29 @@ def test_render_oneof_property_required():
|
|||
],
|
||||
}
|
||||
assert "<b>oneOf</b> [ <em>required 'a'</em> | <em>required 'b'</em> ]" in render_json_schema(schema)
|
||||
|
||||
|
||||
def test_render_json_schema_anchor():
|
||||
SCHEMA = {
|
||||
'$schema': 'http://json-schema.org/draft-04/schema#',
|
||||
'type': 'object',
|
||||
'required': ['foo'],
|
||||
'additionalProperties': False,
|
||||
'properties': {
|
||||
'foo': {
|
||||
'type': 'object',
|
||||
'$anchor': 'foo',
|
||||
'title': 'foo object',
|
||||
'properties': {'a': {'type': 'string'}},
|
||||
},
|
||||
'zorglub': {
|
||||
'$ref': '#foo',
|
||||
},
|
||||
},
|
||||
}
|
||||
# Check that no unicode crash occurs
|
||||
with translation.override('fr'):
|
||||
fragment = render_json_schema(SCHEMA)
|
||||
match = re.search(r'id="(schema-object-foo-[^"]+)"', fragment)
|
||||
assert match
|
||||
assert f'href="#{match.group(1)}">foo object</a>' in fragment
|
||||
|
|
Loading…
Reference in New Issue