robo-html 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- robo_html/__init__.py +5 -0
- robo_html/renderer.py +83 -0
- robo_html-0.1.0.dist-info/METADATA +7 -0
- robo_html-0.1.0.dist-info/RECORD +5 -0
- robo_html-0.1.0.dist-info/WHEEL +4 -0
robo_html/__init__.py
ADDED
robo_html/renderer.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Render a self-contained HTML report from a template and canonical JSON data."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import copy
|
|
6
|
+
import json
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any, Mapping
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class HtmlReportGenerator:
|
|
12
|
+
"""Render report data into a caller-supplied standalone HTML template.
|
|
13
|
+
|
|
14
|
+
The application owns its branding/template and canonical report data model.
|
|
15
|
+
``robo-html`` owns only the generic rendering and safe JSON embedding.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
DEFAULT_DATA_PLACEHOLDER = "__ROBO_REPORT_DATA_JSON__"
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def _load_template(cls, template_path: Path, data_placeholder: str) -> str:
|
|
22
|
+
template = Path(template_path).read_text(encoding="utf-8")
|
|
23
|
+
if data_placeholder not in template:
|
|
24
|
+
raise ValueError(
|
|
25
|
+
f"HTML report template {template_path} does not contain "
|
|
26
|
+
f"the required placeholder {data_placeholder!r}."
|
|
27
|
+
)
|
|
28
|
+
return template
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def _prepare_data(data: Mapping[str, Any]) -> dict[str, Any]:
|
|
32
|
+
"""Return an isolated JSON-ready copy without application mutation."""
|
|
33
|
+
prepared = copy.deepcopy(dict(data))
|
|
34
|
+
if not isinstance(prepared.get("results", []), list):
|
|
35
|
+
prepared["results"] = []
|
|
36
|
+
return prepared
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def _serialize_for_html(data: Mapping[str, Any]) -> str:
|
|
40
|
+
"""Serialize JSON safely for an ``application/json`` script element."""
|
|
41
|
+
payload = json.dumps(data, ensure_ascii=False, default=str)
|
|
42
|
+
return (
|
|
43
|
+
payload.replace("&", "\\u0026")
|
|
44
|
+
.replace("<", "\\u003c")
|
|
45
|
+
.replace(">", "\\u003e")
|
|
46
|
+
.replace("\u2028", "\\u2028")
|
|
47
|
+
.replace("\u2029", "\\u2029")
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def generate(
|
|
52
|
+
cls,
|
|
53
|
+
data: Mapping[str, Any],
|
|
54
|
+
*,
|
|
55
|
+
template_path: Path,
|
|
56
|
+
data_placeholder: str = DEFAULT_DATA_PLACEHOLDER,
|
|
57
|
+
) -> str:
|
|
58
|
+
"""Render one self-contained HTML document from canonical report data."""
|
|
59
|
+
prepared = cls._prepare_data(data)
|
|
60
|
+
template = cls._load_template(Path(template_path), data_placeholder)
|
|
61
|
+
return template.replace(
|
|
62
|
+
data_placeholder,
|
|
63
|
+
cls._serialize_for_html(prepared),
|
|
64
|
+
1,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def generate_from_json(
|
|
69
|
+
cls,
|
|
70
|
+
json_path: Path,
|
|
71
|
+
*,
|
|
72
|
+
template_path: Path,
|
|
73
|
+
data_placeholder: str = DEFAULT_DATA_PLACEHOLDER,
|
|
74
|
+
) -> str:
|
|
75
|
+
"""Render HTML from a persisted canonical JSON report."""
|
|
76
|
+
data = json.loads(Path(json_path).read_text(encoding="utf-8"))
|
|
77
|
+
if not isinstance(data, dict):
|
|
78
|
+
raise ValueError(f"Report JSON must contain an object: {json_path}")
|
|
79
|
+
return cls.generate(
|
|
80
|
+
data,
|
|
81
|
+
template_path=template_path,
|
|
82
|
+
data_placeholder=data_placeholder,
|
|
83
|
+
)
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
robo_html/__init__.py,sha256=oqMk2i9ej3lghUPEMOQyCQJDaXZG05zksfoT5X0uIS8,126
|
|
2
|
+
robo_html/renderer.py,sha256=dRvyIzydRC3ytiRphPrDvCV0voBWapjc9nMhQjVfrXk,2865
|
|
3
|
+
robo_html-0.1.0.dist-info/METADATA,sha256=Bx-H56wGQg2Ryt-9zbH4rmMQkPBjh_sbSRTy3k2DFhM,256
|
|
4
|
+
robo_html-0.1.0.dist-info/WHEEL,sha256=L-WvLdSBvJWHXv5zrQxDvNRnIgoBzLUpcbuiw19KCuQ,88
|
|
5
|
+
robo_html-0.1.0.dist-info/RECORD,,
|