Fix creation of shadow div.

If two highlights started at the same index, it would sometimes not render both of them.
This commit is contained in:
Tom Alexander 2024-01-27 19:22:31 -05:00
parent 5feac8e4d7
commit 8627181480
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
1 changed files with 31 additions and 38 deletions

View File

@ -2,36 +2,32 @@ import React, { ReactNode, useState } from "react";
import { Highlight } from "./highlight"; import { Highlight } from "./highlight";
function buildShadow(highlights: Highlight[], text: string): ReactNode[] { function buildShadow(highlights: Highlight[], text: string): ReactNode[] {
let remaining_highlights = highlights.slice();
let output: ReactNode[] = []; let output: ReactNode[] = [];
let i = 0; let i = 0;
let state = ShadowState.Text; let state = ShadowState.Text;
let buffer = ""; let buffer = "";
for (let chr of text) { for (let chr of text) {
if (state == ShadowState.Text) { const thisCharHighlighted = isInHighlight(highlights, i);
if ( if (state == ShadowState.Text && thisCharHighlighted) {
remaining_highlights.length > 0 && // Start a span
i == remaining_highlights[0].start output.push(buffer);
) { buffer = chr;
// Start a span state = ShadowState.Highlight;
output.push(buffer); } else if (state == ShadowState.Text && !thisCharHighlighted) {
buffer = chr; // Add a character
state = ShadowState.Highlight; buffer += chr;
} else { } else if (state == ShadowState.Highlight && thisCharHighlighted) {
// Add a character // Add a character
buffer += chr; buffer += chr;
} } else if (state == ShadowState.Highlight && !thisCharHighlighted) {
} else if (state == ShadowState.Highlight) { // End the span
if (remaining_highlights.length > 0 && i == remaining_highlights[0].end) { output.push(
// End the span <span key={i} className="highlighted">
output.push(<span key={i} className="highlighted">{buffer}</span>); {buffer}
buffer = chr; </span>,
state = ShadowState.Text; );
remaining_highlights = remaining_highlights.slice(1); buffer = chr;
} else { state = ShadowState.Text;
// Add a character
buffer += chr;
}
} }
++i; ++i;
} }
@ -40,26 +36,23 @@ function buildShadow(highlights: Highlight[], text: string): ReactNode[] {
if (state == ShadowState.Text) { if (state == ShadowState.Text) {
output.push(buffer); output.push(buffer);
} else if (state == ShadowState.Highlight) { } else if (state == ShadowState.Highlight) {
output.push(<span className="highlighted">{buffer}</span>); output.push(
<span key={i} className="highlighted">
{buffer}
</span>,
);
} }
} }
return output; return output;
} }
function unicodeAwareSlice(text: string, start: number, end: number): string { function isInHighlight(highlights: Highlight[], offset: number): boolean {
// Boooo javascript for (const highlight of highlights) {
let i = 0; if (highlight.start <= offset && offset < highlight.end) {
let output = ""; return true;
for (let chr of text) {
if (i >= end) {
break;
} }
if (i >= start) {
output += chr;
}
++i;
} }
return output; return false;
} }
const enum ShadowState { const enum ShadowState {