| import streamlit.components.v1 | |
| from htbuilder import HtmlElement, div, span, styles | |
| from htbuilder.units import px, rem, em | |
| def annotation(body, label="", background="#ddd", color="#333", **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 | |
| The color to use for the background "chip" containing this annotation. | |
| color : string | |
| The color to use for the body and label text. | |
| **style : dict | |
| Any CSS you want to use to customize the containing "chip". | |
| 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") | |
| """ | |
| if "font_family" not in style: | |
| style["font_family"] = "sans-serif" | |
| return span( | |
| style=styles( | |
| background=background, | |
| border_radius=rem(0.33), | |
| color=color, | |
| padding=(rem(0.17), rem(0.67)), | |
| display="inline-flex", | |
| justify_content="center", | |
| align_items="center", | |
| **style, | |
| ) | |
| )( | |
| body, | |
| span( | |
| style=styles( | |
| color=color, | |
| font_size=em(0.67), | |
| opacity=0.5, | |
| padding_left=rem(0.5), | |
| text_transform="uppercase", | |
| margin_bottom=px(-2), | |
| ) | |
| )(label), | |
| ) | |
| def annotated_text(*args, **kwargs): | |
| """Writes test with annotations into your Streamlit app. | |
| Parameters | |
| ---------- | |
| *args : str, tuple or htbuilder.HtmlElement | |
| Arguments can be: | |
| - strings, to draw the string as-is on the screen. | |
| - tuples of the form (main_text, annotation_text, background, color) where | |
| background and foreground colors are optional and should be an CSS-valid string such as | |
| "#aabbcc" or "rgb(10, 20, 30)" | |
| - HtmlElement objects in case you want to customize the annotations further. In particular, | |
| you can import the `annotation()` function from this module to easily produce annotations | |
| whose CSS you can customize via keyword arguments. | |
| Examples | |
| -------- | |
| >>> annotated_text( | |
| ... "This ", | |
| ... ("is", "verb", "#8ef"), | |
| ... " some ", | |
| ... ("annotated", "adj", "#faa"), | |
| ... ("text", "noun", "#afa"), | |
| ... " for those of ", | |
| ... ("you", "pronoun", "#fea"), | |
| ... " who ", | |
| ... ("like", "verb", "#8ef"), | |
| ... " this sort of ", | |
| ... ("thing", "noun", "#afa"), | |
| ... ) | |
| >>> annotated_text( | |
| ... "Hello ", | |
| ... annotation("world!", "noun", color="#8ef", border="1px dashed red"), | |
| ... ) | |
| """ | |
| out = div( | |
| style=styles( | |
| font_family="sans-serif", | |
| line_height="1.45", | |
| font_size=px(16), | |
| text_align="right", | |
| ) | |
| ) | |
| for arg in args: | |
| if isinstance(arg, str): | |
| out(arg) | |
| elif isinstance(arg, HtmlElement): | |
| out(arg) | |
| elif isinstance(arg, tuple): | |
| out(annotation(*arg)) | |
| else: | |
| raise Exception("Oh noes!") | |
| streamlit.components.v1.html(str(out), **kwargs) | |
| def shorten_text(text, n, reverse=False): | |
| if text.isspace() or text == "": | |
| return text | |
| if reverse: | |
| text = text[::-1] | |
| words = iter(text.split()) | |
| lines, current = [], next(words) | |
| for word in words: | |
| if len(current) + 1 + len(word) > n: | |
| break | |
| else: | |
| current += " " + word | |
| lines.append(current) | |
| if reverse: | |
| return lines[0][::-1] | |
| return lines[0] | |
| def annotate_answer(result): | |
| annotated_text( | |
| shorten_text( | |
| result["original"][: result["new_start"]], | |
| 500, | |
| reverse=True, | |
| ), | |
| (result["new_answer"], "جواب", "#8ef"), | |
| shorten_text(result["original"][result["new_end"] :], 500) + " ...... إلخ", | |
| ) | |