Highlighting text.
This commit is contained in:
parent
7390132d02
commit
bbf8ab0966
@ -49,4 +49,9 @@
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
color: transparent;
|
||||
white-space: pre-wrap;
|
||||
|
||||
.highlighted {
|
||||
background: #ffff00;
|
||||
}
|
||||
}
|
||||
|
@ -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
69
src/shadow.tsx
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user