Simplify
This commit is contained in:
parent
4d977fc70d
commit
a050ec252b
2 changed files with 58 additions and 65 deletions
|
|
@ -99,65 +99,72 @@ function updateMergedText(): void {
|
|||
selectedTokenizer
|
||||
);
|
||||
|
||||
let selectionStart: number = Number.NEGATIVE_INFINITY;
|
||||
let selectionEnd: number = Number.NEGATIVE_INFINITY;
|
||||
if ((results.cursors?.length ?? 0) > 0) {
|
||||
selectionStart = results.cursors![0].position;
|
||||
selectionEnd = results.cursors![1].position;
|
||||
}
|
||||
const isSelection = selectionStart !== selectionEnd;
|
||||
const selection =
|
||||
results.cursors?.length === 2
|
||||
? {
|
||||
start: results.cursors[0].position,
|
||||
end: results.cursors[1].position,
|
||||
side: leftCursors ? 'left' : 'right',
|
||||
}
|
||||
: undefined;
|
||||
|
||||
const selectionSide = leftCursors ? 'left' : 'right';
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
function appendSpan(text: string, className: string): void {
|
||||
if (text.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const span = document.createElement('span');
|
||||
span.className = className;
|
||||
span.textContent = text;
|
||||
fragment.appendChild(span);
|
||||
}
|
||||
|
||||
function appendCaret(): void {
|
||||
if (!selection) {
|
||||
return;
|
||||
}
|
||||
|
||||
fragment.appendChild(
|
||||
createSelectionOverlay(
|
||||
selection.side === 'left',
|
||||
selection.start !== selection.end
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
let currentPosition = 0;
|
||||
if (selectionEnd === 0) {
|
||||
fragment.appendChild(createSelectionOverlay(selectionSide === 'left', isSelection));
|
||||
if (selection?.end === 0) {
|
||||
appendCaret();
|
||||
}
|
||||
|
||||
for (const { text, history } of results.history) {
|
||||
const isDelete = history === 'RemovedFromLeft' || history === 'RemovedFromRight';
|
||||
let spanChars: string[] = [];
|
||||
let currentClass = '';
|
||||
|
||||
const flushSpan = () => {
|
||||
if (spanChars.length > 0) {
|
||||
const span = document.createElement('span');
|
||||
span.className = currentClass;
|
||||
span.textContent = spanChars.join('');
|
||||
fragment.appendChild(span);
|
||||
spanChars = [];
|
||||
}
|
||||
};
|
||||
|
||||
for (const character of text) {
|
||||
let className = history;
|
||||
if (
|
||||
!isDelete &&
|
||||
selectionStart <= currentPosition &&
|
||||
currentPosition < selectionEnd
|
||||
) {
|
||||
className += ` selection-${selectionSide}`;
|
||||
}
|
||||
|
||||
if (className !== currentClass) {
|
||||
flushSpan();
|
||||
currentClass = className;
|
||||
}
|
||||
spanChars.push(character);
|
||||
|
||||
if (!isDelete) {
|
||||
if (currentPosition === selectionEnd - 1) {
|
||||
flushSpan();
|
||||
fragment.appendChild(
|
||||
createSelectionOverlay(selectionSide === 'left', isSelection)
|
||||
);
|
||||
}
|
||||
currentPosition++;
|
||||
}
|
||||
if (isDelete || !selection) {
|
||||
appendSpan(text, history);
|
||||
continue;
|
||||
}
|
||||
|
||||
flushSpan();
|
||||
// Reconcile positions count Unicode scalars, rather than UTF-16 code units.
|
||||
const chars = [...text];
|
||||
const start = Math.max(0, Math.min(chars.length, selection.start - currentPosition));
|
||||
const end = Math.max(0, Math.min(chars.length, selection.end - currentPosition));
|
||||
appendSpan(chars.slice(0, start).join(''), history);
|
||||
appendSpan(
|
||||
chars.slice(start, end).join(''),
|
||||
`${history} selection-${selection.side}`
|
||||
);
|
||||
|
||||
if (
|
||||
currentPosition < selection.end &&
|
||||
selection.end <= currentPosition + chars.length
|
||||
) {
|
||||
appendCaret();
|
||||
}
|
||||
|
||||
appendSpan(chars.slice(end).join(''), history);
|
||||
currentPosition += chars.length;
|
||||
}
|
||||
|
||||
mergedTextArea.innerHTML = '';
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ $gradient-end: #e0e7ef;
|
|||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
html,
|
||||
|
|
@ -76,13 +75,6 @@ header > h1 {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
h1,
|
||||
code,
|
||||
p,
|
||||
p * {
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
code {
|
||||
background: $code-bg;
|
||||
color: $code-text;
|
||||
|
|
@ -121,6 +113,7 @@ main {
|
|||
}
|
||||
|
||||
.radio-group {
|
||||
user-select: none;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
justify-content: center;
|
||||
|
|
@ -265,6 +258,7 @@ main {
|
|||
}
|
||||
|
||||
label {
|
||||
user-select: none;
|
||||
display: inline-block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 600;
|
||||
|
|
@ -309,7 +303,6 @@ textarea {
|
|||
box-sizing: border-box;
|
||||
resize: none;
|
||||
cursor: text;
|
||||
user-select: text;
|
||||
caret-color: $primary-blue;
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
|
|
@ -334,7 +327,6 @@ textarea:focus {
|
|||
|
||||
#merged {
|
||||
width: 100%;
|
||||
user-select: text;
|
||||
|
||||
> * {
|
||||
position: relative;
|
||||
|
|
@ -349,14 +341,9 @@ textarea:focus {
|
|||
}
|
||||
}
|
||||
|
||||
.Unchanged {
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.Left,
|
||||
.AddedFromLeft,
|
||||
.RemovedFromLeft {
|
||||
user-select: text;
|
||||
background: $green;
|
||||
}
|
||||
|
||||
|
|
@ -381,7 +368,6 @@ textarea:focus {
|
|||
.Right,
|
||||
.AddedFromRight,
|
||||
.RemovedFromRight {
|
||||
user-select: text;
|
||||
background: $light-blue;
|
||||
}
|
||||
|
||||
|
|
@ -396,6 +382,7 @@ $CARET_WIDTH: 2;
|
|||
$DOT_RADIUS: 4;
|
||||
|
||||
.selection-caret {
|
||||
user-select: none;
|
||||
position: relative;
|
||||
z-index: 1000;
|
||||
|
||||
|
|
@ -453,7 +440,6 @@ $DOT_RADIUS: 4;
|
|||
top: -1.3em;
|
||||
left: calc(-#{$CARET_WIDTH} / 2 * 1px);
|
||||
font-size: 0.9em;
|
||||
user-select: none;
|
||||
color: white;
|
||||
padding: 0 2px;
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
|
|
|
|||
Loading…
Reference in a new issue