|
2 | 2 |
|
3 | 3 | import html |
4 | 4 | import operator |
5 | | -from collections.abc import Mapping, Sequence |
| 5 | +from collections.abc import Callable, Mapping, Sequence |
6 | 6 | from functools import reduce |
7 | 7 |
|
8 | 8 | from python_hiccup.transform import CONTENT_TAG, transform |
@@ -60,12 +60,16 @@ def _is_content(element: str) -> bool: |
60 | 60 | return element == CONTENT_TAG |
61 | 61 |
|
62 | 62 |
|
| 63 | +def _is_raw(content: str | Callable) -> bool: |
| 64 | + return callable(content) and content.__name__ == "raw_content" |
| 65 | + |
| 66 | + |
63 | 67 | def _to_html(tag: Mapping, parent: str = "") -> list: |
64 | 68 | element = next(iter(tag.keys())) |
65 | 69 | child = next(iter(tag.values())) |
66 | 70 |
|
67 | 71 | if _is_content(element): |
68 | | - return [_escape(str(child), parent)] |
| 72 | + return child() if _is_raw(child) else [_escape(str(child), parent)] |
69 | 73 |
|
70 | 74 | attributes = reduce(_to_attributes, tag.get("attributes", []), "") |
71 | 75 | bool_attributes = reduce(_to_bool_attributes, tag.get("boolean_attributes", []), "") |
@@ -96,3 +100,12 @@ def render(data: Sequence) -> str: |
96 | 100 | transformed_html: list = reduce(operator.iadd, matrix, []) |
97 | 101 |
|
98 | 102 | return "".join(transformed_html) |
| 103 | + |
| 104 | + |
| 105 | +def raw(content: str | float) -> Callable: |
| 106 | + """Content that should not be escaped when rendering HTML elements.""" |
| 107 | + |
| 108 | + def raw_content() -> str | float: |
| 109 | + return content |
| 110 | + |
| 111 | + return raw_content |
0 commit comments