70 lines
1.6 KiB
TypeScript
70 lines
1.6 KiB
TypeScript
|
import React, { ReactNode, useState } from "react";
|
||
|
import { Highlight } from "./highlight";
|
||
|
|
||
|
function buildShadow(highlights: Highlight[], text: string): ReactNode[] {
|
||
|
let remaining_highlights = highlights.slice();
|
||
|
let output: ReactNode[] = [];
|
||
|
let i = 0;
|
||
|
let state = ShadowState.Text;
|
||
|
let buffer = "";
|
||
|
for (let chr of text) {
|
||
|
if (state == ShadowState.Text) {
|
||
|
if (remaining_highlights.length > 0 && i == remaining_highlights[0].start) {
|
||
|
// Start a span
|
||
|
output.push(buffer);
|
||
|
buffer = chr;
|
||
|
state = ShadowState.Highlight;
|
||
|
} else {
|
||
|
// Add a character
|
||
|
buffer += chr;
|
||
|
}
|
||
|
} else if (state == ShadowState.Highlight) {
|
||
|
if (remaining_highlights.length > 0 && i == remaining_highlights[0].end) {
|
||
|
// End the span
|
||
|
output.push(<span className="highlighted">{buffer}</span>);
|
||
|
buffer = chr;
|
||
|
state = ShadowState.Text;
|
||
|
remaining_highlights = remaining_highlights.slice(1);
|
||
|
} else {
|
||
|
// Add a character
|
||
|
buffer += chr;
|
||
|
}
|
||
|
}
|
||
|
++i;
|
||
|
}
|
||
|
|
||
|
if (buffer.length > 0) {
|
||
|
if (state == ShadowState.Text) {
|
||
|
output.push(buffer);
|
||
|
} else if (state == ShadowState.Highlight) {
|
||
|
output.push(<span className="highlighted">{buffer}</span>);
|
||
|
}
|
||
|
}
|
||
|
return output;
|
||
|
}
|
||
|
|
||
|
function unicodeAwareSlice(text: string, start: number, end: number): string {
|
||
|
// Boooo javascript
|
||
|
let i = 0;
|
||
|
let output = "";
|
||
|
for (let chr of text) {
|
||
|
if (i >= end) {
|
||
|
break;
|
||
|
}
|
||
|
if (i >= start) {
|
||
|
output += chr;
|
||
|
}
|
||
|
++i;
|
||
|
}
|
||
|
return output;
|
||
|
}
|
||
|
|
||
|
const enum ShadowState {
|
||
|
Text,
|
||
|
Highlight,
|
||
|
}
|
||
|
|
||
|
export {
|
||
|
buildShadow
|
||
|
}
|