Skip to content

Commit 3914853

Browse files
committed
Remove js
1 parent ae98857 commit 3914853

File tree

4 files changed

+75
-80
lines changed

4 files changed

+75
-80
lines changed

djangocms_rest/cms_toolbars.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,3 @@
66
class RestToolbar(CMSToolbar):
77
class Media:
88
css = {"all": ("djangocms_rest/highlight.css",)}
9-
js = ("djangocms_rest/toggles.js",)

djangocms_rest/plugin_rendering.py

Lines changed: 66 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import Any, Dict, Iterable, Optional, TypeVar
22

33
from django.db import models
4-
from django.utils.html import escape, mark_safe
4+
from django.utils.html import escape, escapejs, mark_safe
55

66
from cms.plugin_rendering import ContentRenderer
77
from rest_framework import serializers
@@ -70,55 +70,94 @@ def render_cms_plugin(
7070
return serializer_cls(plugin_instance, context=context).data
7171

7272

73+
# Template for a collapsable key-value pair
74+
DETAILS_TEMPLATE = (
75+
'<details open><summary><span class="key">"{key}"</span>: {open}</summary>'
76+
'<div class="indent">{value}</div></details>{close}<span class="sep">,</span>'
77+
)
78+
79+
# Template for a collapsable object/list
80+
OBJ_TEMPLATE = (
81+
'<details open><summary>{open}</summary>'
82+
'<div class="indent">{value}</div></details>{close}<span class="sep">,</span>'
83+
)
84+
85+
# Tempalte for a single line key-value pair
86+
SIMPLE_TEMPLATE = (
87+
'<span class="key">"{key}"</span>: {value}<span class="sep">,</span>'
88+
)
89+
90+
def escapestr(s: str) -> str:
91+
"""
92+
Escape a string for safe HTML rendering.
93+
"""
94+
return escape(s).replace('&quot;', '&bsol;&quot;').replace('\n', '&bsol;n')
95+
96+
7397
def highlight_data(json_data: Any) -> str:
7498
"""
7599
Highlight JSON data using Pygments.
76100
"""
77101
if isinstance(json_data, str):
78-
classes = "str"
79-
if len(json_data) > 100:
80-
classes += " ellipsis"
81-
return f'<span class="{classes}">"{escape(json_data)}"</span>'
102+
ellipsis = ""
103+
if len(json_data) > 60:
104+
return f'<span class="str">"<span class="ellipsis">{escapestr(json_data)}</span>"</span>'
105+
return f'<span class="str">"{escapestr(json_data)}"</span>'
82106
if isinstance(json_data, (int, float)):
83107
return f'<span class="num">{json_data}</span>'
84108
if isinstance(json_data, bool):
85109
return f'<span class="bool">{str(json_data).lower()}</span>'
86110
if json_data is None:
87111
return '<span class="null">null</span>'
88112
if isinstance(json_data, dict):
89-
return highlight_json(json_data)
113+
return OBJ_TEMPLATE.format(**highlight_json(json_data)) if json_data else '{}'
90114
if isinstance(json_data, list):
91-
return highlight_list(json_data)
115+
return OBJ_TEMPLATE.format(**highlight_list(json_data)) if json_data else '[]'
92116

93117
return f'<span class="obj">{json_data}</span>'
94118

95119

96120
def highlight_json(
97121
json_data: Dict[str, Any], children: Iterable | None = None, field: str = "children"
98-
) -> str:
122+
) -> dict[str, str]:
99123
has_children = children is not None
100124
if field in json_data:
101125
del json_data[field]
102126

103-
if not json_data and not has_children:
104-
return "{}"
105127
items = [
106-
f'<div class="js-kvp"><span class="toggle"></span><span class="key">"{escape(key)}"</span>: '
107-
f'{highlight_data(value)}<span class="sep">,</span></div>'
128+
DETAILS_TEMPLATE.format(
129+
key=escape(key),
130+
value=highlight_data(value),
131+
open='',
132+
close='',
133+
) if isinstance(value, (dict, list)) and value else SIMPLE_TEMPLATE.format(
134+
key=escape(key),
135+
value=highlight_data(value),
136+
)
108137
for key, value in json_data.items()
109138
]
110139
if has_children:
111-
rendered_children = (
112-
f'<div class="js-kvp"><span class="toggle"></span><span class="children">"{field}"</span>: '
113-
f'[<div class="indent">{", ".join(children)}</div></div>]'
140+
rendered_children = DETAILS_TEMPLATE.format(
141+
key=escape(field),
142+
value=''.join(children),
143+
open='[',
144+
close=']',
114145
)
115146
items.append(rendered_children)
116-
return f'{{<div class="indent">{"".join(items)}</div>}}'
147+
return {
148+
"open": '{',
149+
"close": '}',
150+
"value": "<br>".join(items),
151+
}
117152

118153

119-
def highlight_list(json_data: list) -> str:
154+
def highlight_list(json_data: list) -> dict[str, str]:
120155
items = [highlight_data(item) for item in json_data]
121-
return f'[<div class="indent">{",<br>".join(items)}</div>]'
156+
return {
157+
"open": '[',
158+
"close": ']',
159+
"value": ''.join(items),
160+
}
122161

123162

124163
class RESTRenderer(ContentRenderer):
@@ -140,7 +179,7 @@ def render_plugin(
140179
)
141180
for child in getattr(instance, "child_plugin_instances", [])
142181
] or None
143-
content = highlight_json(data, children=children)
182+
content = OBJ_TEMPLATE.format(**highlight_json(data, children=children))
144183

145184
if editable:
146185
content = self.plugin_edit_template.format(
@@ -169,11 +208,13 @@ def render_plugins(
169208
render_plugins=False,
170209
).data
171210

172-
yield highlight_json(
173-
placeholder_data,
174-
children=super().render_plugins(
175-
placeholder, language, context, editable=editable, template=template
176-
),
177-
field="content",
211+
yield OBJ_TEMPLATE.format(
212+
**highlight_json(
213+
placeholder_data,
214+
children=super().render_plugins(
215+
placeholder, language, context, editable=editable, template=template
216+
),
217+
field="content",
218+
)
178219
)
179220
yield "</div>"

djangocms_rest/static/djangocms_rest/highlight.css

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,14 @@
3232
.ellipsis {
3333
display: inline-block; /* or block, depending on your needs */
3434
text-overflow: ellipsis;
35-
max-width: 100ch;
35+
max-width: 60ch;
3636
overflow: hidden;
3737
white-space: nowrap;
3838
vertical-align: bottom; /* optional, for better alignment */
3939
}
40+
.ellipsis-toggle {
41+
cursor: pointer;
42+
}
4043
.key, .children {
4144
color: var(--key-color, red);
4245
font-weight: bold;
@@ -47,44 +50,14 @@
4750
.indent {
4851
padding-inline-start: 2em;
4952
border-inline-start: 1px solid var(--dca-gray-lightest, #f2f2f2);
53+
& > .sep:last-child {
54+
display: none;
55+
}
5056
}
5157
}
5258

5359
.rest-placeholder {
54-
.js-kvp:last-child > .sep {
55-
display: none;
56-
}
57-
.toggle {
58-
display: none
59-
}
60-
.js-kvp:has(.indent) {
61-
position: relative;
62-
&.hidden > .indent {
63-
max-height: 0;
64-
transition: max-height 0.3s linear;
65-
}
66-
}
67-
div.indent {
68-
max-height: attr(data-scroll-height px);
69-
transition: max-height 0.3s linear;
70-
overflow: hidden;
71-
}
72-
.js-kvp:has(.indent) > .toggle {
73-
&::before {
74-
content: "\2014"; /* em dash (—) */
75-
}
76-
width: 1.5em;
77-
height: 1.5em;
78-
cursor: pointer;
79-
display: inline-block;
80-
margin-inline-end: 0.5em;
81-
transition: transform 0.2s ease-in-out;
82-
position: absolute;
83-
inset-inline-start: -1.5em;
84-
color: var(--dca-gray-light);
85-
font-weight: bold;
86-
}
87-
.js-kvp.hidden:has(.indent) > .toggle::before {
88-
content: "+";
60+
summary {
61+
margin-inline-start: -1.2em;
8962
}
9063
}

djangocms_rest/static/djangocms_rest/toggles.js

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)