Spaces:
Sleeping
Sleeping
import html | |
from htbuilder import H, HtmlElement, styles | |
from htbuilder.units import unit | |
# Only works in 3.7+: from htbuilder import div, span | |
div = H.div | |
span = H.span | |
# Only works in 3.7+: from htbuilder.units import px, rem, em | |
px = unit.px | |
rem = unit.rem | |
em = unit.em | |
# Colors from the Streamlit palette. | |
# These are red-70, orange-70, ..., violet-70, gray-70. | |
PALETTE = [ | |
"#ff4b4b", | |
"#ffa421", | |
"#ffe312", | |
"#21c354", | |
"#00d4b1", | |
"#00c0f2", | |
"#1c83e1", | |
"#803df5", | |
"#808495", | |
] | |
OPACITIES = [ | |
"33", "66", | |
] | |
def annotation(body, label="", background=None, color=None, **style): | |
"""Build an HtmlElement span object with the given body and annotation label. | |
The end result will look something like this: | |
[body | label] | |
Parameters | |
---------- | |
body : string | |
The string to put in the "body" part of the annotation. | |
label : string | |
The string to put in the "label" part of the annotation. | |
background : string or None | |
The color to use for the background "chip" containing this annotation. | |
If None, will use a random color based on the label. | |
color : string or None | |
The color to use for the body and label text. | |
If None, will use the document's default text color. | |
style : dict | |
Any CSS you want to apply to the containing "chip". This is useful for things like | |
Examples | |
-------- | |
Produce a simple annotation with default colors: | |
# >>> annotation("apple", "fruit") | |
Produce an annotation with custom colors: | |
# >>> annotation("apple", "fruit", background="#FF0", color="black") | |
Produce an annotation with crazy CSS: | |
# >>> annotation("apple", "fruit", background="#FF0", border="1px dashed red") | |
""" | |
color_style = {} | |
if color: | |
color_style['color'] = color | |
if not background: | |
label_sum = sum(ord(c) for c in label) | |
background_color = PALETTE[label_sum % len(PALETTE)] | |
background_opacity = OPACITIES[label_sum % len(OPACITIES)] | |
background = background_color + background_opacity | |
return ( | |
span( | |
style=styles( | |
background=background, | |
border_radius=rem(0.33), | |
padding=(rem(0.125), rem(0.5)), | |
overflow="hidden", | |
**color_style, | |
**style, | |
))( | |
html.escape(body), | |
span( | |
style=styles( | |
padding_left=rem(0.5), | |
text_transform="uppercase", | |
))( | |
span( | |
style=styles( | |
font_size=em(0.67), | |
opacity=0.5, | |
))( | |
html.escape(label), | |
), | |
), | |
) | |
) | |
def get_annotated_html(*args): | |
"""Writes text with annotations into an HTML string. | |
Parameters | |
---------- | |
*args : see annotated_text() | |
Returns | |
------- | |
str | |
An HTML string. | |
""" | |
out = div() | |
for arg in args: | |
if isinstance(arg, str): | |
out(html.escape(arg)) | |
elif isinstance(arg, HtmlElement): | |
out(arg) | |
elif isinstance(arg, tuple): | |
out(annotation(*arg)) | |
else: | |
raise Exception("Bad input") | |
return str(out) |