organic_ast_explorer/src/shadow.tsx

65 lines
1.6 KiB
TypeScript

import React, { ReactNode } from "react";
import { Highlight } from "./highlight";
import styles from "./Editor.module.css";
function buildShadow(highlights: Highlight[], text: string): ReactNode[] {
let output: ReactNode[] = [];
let i = 0;
let state = ShadowState.Text;
let buffer = "";
for (let chr of text) {
const thisCharHighlighted = isInHighlight(highlights, i);
if (state == ShadowState.Text && thisCharHighlighted) {
// Start a span
output.push(buffer);
buffer = chr;
state = ShadowState.Highlight;
} else if (state == ShadowState.Text && !thisCharHighlighted) {
// Add a character
buffer += chr;
} else if (state == ShadowState.Highlight && thisCharHighlighted) {
// Add a character
buffer += chr;
} else if (state == ShadowState.Highlight && !thisCharHighlighted) {
// End the span
output.push(
<span key={i} className={styles.EditorHighlighted}>
{buffer}
</span>,
);
buffer = chr;
state = ShadowState.Text;
}
++i;
}
if (buffer.length > 0) {
if (state == ShadowState.Text) {
output.push(buffer);
} else if (state == ShadowState.Highlight) {
output.push(
<span key={i} className={styles.EditorHighlighted}>
{buffer}
</span>,
);
}
}
return output;
}
function isInHighlight(highlights: Highlight[], offset: number): boolean {
for (const highlight of highlights) {
if (highlight.start <= offset && offset < highlight.end) {
return true;
}
}
return false;
}
const enum ShadowState {
Text,
Highlight,
}
export { buildShadow };