How best to approach text annotation (overlapping highlights of text)?

I put together an example that uses different color backgrounds on s to display there being multiple overlapping highlights. It does make a few simplifying assumptions, though:

  • Annotations are assigned to a paragraph, and annotations cannot spread across multiple paragraphs.
  • Plain text only, no rich text.
  • It doesn’t actually show the annotations.

The basic approach that it follows is to turn the Annotations for a paragraph into a list of “breakpoints”, or places where the styling changes (breakpointsForAnnotation). It then recurses down the list of style change breakpoints, making a element for the current set of style information (makeSpans, makeSpansHelper).

Getting rid of the “each annotation is only in one paragraph” part could be done by using List.Extra.mapAccuml instead of List.indexedMap inside of viewParagraphs and allowing viewParagraph to pass along some sort of state record from paragraph to paragraph (i.e. how many characters have passed in the total text so far, what is the current style state).

Incorporating rich text into this really depends on how the rich text is represented in the Elm code. After all, Html.text "<strong>Hello</strong>" shows all 22 characters of that instead of the one word in bold. In theory, things like “marking text as bold” can be represented as “style change breakpoints”, although you have to be somewhat careful with how you keep track of your style change state so that things like <strong><strong>Hello, </strong>world!</strong> work correctly.

If most of the style information (bold, italics, paragraph breaks, etc) are in the text in the form of tags, then you are probably going to need some sort of parser to turn that into an AST or other intermediate representation, like jxxcarlson/meenylatex or mweiss/elm-rte-toolkit or jxxcarlson/elm-markdown or dillonkearns/elm-markdown or dillonkearns/elm-review-html-to-elm have. If the AST can then be flattened into a giant block of text and a series of style change breakpoints, then the above strategy will still work from that point. Alternatively, you could carefully fold your annotations into the AST (a single annotation could result in multiple AST entries, depending on how much of the existing AST it stretches across) and then just render the AST.

I hope that this was helpful, or sparked some other useful ideas. Good luck!

2 Likes