Highlighting Proofread Results
This time we’re going to display results of proofreading. We will highlight issues in a text panel.
The source code for this post is available in the 06-highlighting-proofread-results
folder in the elm-proofreading repository.
Highlighting Text with Problems
I want to highlight problem places in a text. As an input, we’ve got a text and list of comments. Each comment contains an offset
, which is a start index for a problem in a text, and a length
of a problem text.
Let’s consider the following text. There are two misspelled words we need to highlight:
text
—“I like Wensdeys and Thusrdays.”comments
— [ { message: “Possible spelling mistake found”, offset: 7, length: 8, }, { message: “Possible spelling mistake found”, offset: 20, length: 9, } ]
And here’s the output that I’d like to have:
To get this view we’d need the following HTML markup:
Everything is wrapped into the <div>
tag with proofread-panel
CSS class that draws a border. Each comment is wrapped in a <span>
tag with the comment
CSS class applied to it. All the text parts between comments are wrapped in <span>
tags with text
CSS class.
The viewCommentsPanel
function does exactly that—it recieves a text string and a list of comments, and returns Elm HTML elements that form a needed markup.
The viewCommentsPanel
function declares a div
element and calls the viewHighlightedText
function to get a list of child elements for this div
.
The viewHighlightedText
is where all the magic happens. It gets a string with a text, a list of comments, and an index. The index stores the last part of a text that has already been processed. Let’s look at the function code before digging on:
First of all, we check the comments list. If it’s not empty, we destructing a list to get next comment
and a rest of comments (xComments List
). Then we get a text between the last processed index and a beginning of a comment (i.e. leftText
), and a text that we’ve got a comment for (i.e. commentText
). After that, we construct a list that contains a span
with a leftText
, a span
with a commentText
, and the result returned by the recursive call of the viewHighlightedText
function. For the recursive call, we pass a text, a list with a rest of comments, and an index of the letter right after the processed comment.
In case if the viewHighlightedText
with an empty list of comments, we return a span
with a rest of text.
Here is how it will work for our text
I like Wensdeys and Thusrdays.
Step 1
- Input (text, lastProcessedIndex, and two comments):
- I like Wensdeys and Thusrdays.
- 0
- [ { message: “Possible spelling mistake found”, offset: 7, length: 8, }, { message: “Possible spelling mistake found”, offset: 20, length: 9, } ]
- Work
- take the first comment from the list (with
offset
equal to 7 andlength
equal to 8); leftText
would be “I like “;commentText
would be “Wensdeys”;commentEndIndex
would be 15 (i.e. right after the “Wensdeys”);- create a
span
forleftText
“I like “; - create a
span
forcommentText
“Wensdeys”; - call the
viewHighlightedText
function recursively passing the initial text, the rest of comments (i.e. a list with the second comment), and a lastProcessedIndex of 15.
- take the first comment from the list (with
Step 2
- Input (text, lastProcessedIndex, and a list with one comment):
- I like Wensdeys and Thusrdays.
- 15
- [ { message: “Possible spelling mistake found”, offset: 20, length: 9, } ]
- Work
- take the first comment from the list with (
offset
equal to 20 andlength
equal to 9); leftText
would be “ and “;commentText
would be “Thusrdays”;commentEndIndex
would be 29 (i.e. right after the “Thusrdays”);- create a
span
forleftText
“ and “; - create a
span
forcommentText
“Thusrdays”; - call the
viewHighlightedText
function recursively passing the same text, the rest of comments (i.e. an empty list), and a lastProcessedIndex of 29.
- take the first comment from the list with (
Step 3
- Input (text, lastProcessedIndex, and an empty list of comments):
- I like Wensdeys and Thusrdays.
- 29
- [ ]
- Work
- the list of comments is empty;
- take
restOfText
text from thelastProcessedIndex
till the end of text; - create a
span
forrestofText
, which is just period “.”; - return a span joined with an empty list. Note: we cannot return just
span
because the function should return a list, and not a single element. So we join it with an empty list.
- Result
- the function returns a list with five
<span>
elements.
- the function returns a list with five
Now, all we need is to implement CSS rules for text
and comment
classes. In our case, I just set a background color for commented text to make it visible.
In the last post, we will allow selecting comments and will show a description for them.
Stay tuned!