Highlighting text.

This commit is contained in:
Tom Alexander 2024-01-22 21:59:59 -05:00
parent 7390132d02
commit bbf8ab0966
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
3 changed files with 84 additions and 7 deletions

View File

@ -49,4 +49,9 @@
height: 100%;
pointer-events: none;
color: transparent;
white-space: pre-wrap;
.highlighted {
background: #ffff00;
}
}

View File

@ -1,6 +1,7 @@
import React, { useState } from "react";
import React, { ReactNode, useState } from "react";
import "./Editor.css";
import { Highlight } from "./highlight";
import { buildShadow } from "./shadow";
function Editor({ defaultValue = "I have a text value." }) {
function handleChange(event: React.ChangeEvent<HTMLTextAreaElement>) {
@ -13,17 +14,19 @@ function Editor({ defaultValue = "I have a text value." }) {
const [highlights, setHighlights] = useState<Array<Highlight>>([]);
function addHighlight(start: number, end: number) {
setHighlights([...highlights, new Highlight(start, end)]);
let new_highlights = [...highlights, new Highlight(start, end)];
new_highlights.sort(function (a,b) {
if (a.start < b.start) return -1;
if (a.start > b.start) return 1;
return 0;
});
setHighlights(new_highlights);
}
function clearHighlights() {
setHighlights([]);
}
function buildShadow() {
// foo
}
if (highlights.length === 0) {
addHighlight(1, 5);
}
@ -36,7 +39,7 @@ function Editor({ defaultValue = "I have a text value." }) {
className="Editor-textarea"
value={value}
/>
<div className="Editor-underlay">{value}</div>
<div className="Editor-underlay">{buildShadow(highlights, value)}</div>
</div>
<div className="Editor-ast"></div>
</div>

69
src/shadow.tsx Normal file
View File

@ -0,0 +1,69 @@
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
}