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
|
selectedTokenizer
|
||||||
);
|
);
|
||||||
|
|
||||||
let selectionStart: number = Number.NEGATIVE_INFINITY;
|
const selection =
|
||||||
let selectionEnd: number = Number.NEGATIVE_INFINITY;
|
results.cursors?.length === 2
|
||||||
if ((results.cursors?.length ?? 0) > 0) {
|
? {
|
||||||
selectionStart = results.cursors![0].position;
|
start: results.cursors[0].position,
|
||||||
selectionEnd = results.cursors![1].position;
|
end: results.cursors[1].position,
|
||||||
}
|
side: leftCursors ? 'left' : 'right',
|
||||||
const isSelection = selectionStart !== selectionEnd;
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const selectionSide = leftCursors ? 'left' : 'right';
|
|
||||||
const fragment = document.createDocumentFragment();
|
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;
|
let currentPosition = 0;
|
||||||
if (selectionEnd === 0) {
|
if (selection?.end === 0) {
|
||||||
fragment.appendChild(createSelectionOverlay(selectionSide === 'left', isSelection));
|
appendCaret();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const { text, history } of results.history) {
|
for (const { text, history } of results.history) {
|
||||||
const isDelete = history === 'RemovedFromLeft' || history === 'RemovedFromRight';
|
const isDelete = history === 'RemovedFromLeft' || history === 'RemovedFromRight';
|
||||||
let spanChars: string[] = [];
|
if (isDelete || !selection) {
|
||||||
let currentClass = '';
|
appendSpan(text, history);
|
||||||
|
continue;
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = '';
|
mergedTextArea.innerHTML = '';
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ $gradient-end: #e0e7ef;
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
user-select: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
|
|
@ -76,13 +75,6 @@ header > h1 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1,
|
|
||||||
code,
|
|
||||||
p,
|
|
||||||
p * {
|
|
||||||
user-select: text;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
code {
|
||||||
background: $code-bg;
|
background: $code-bg;
|
||||||
color: $code-text;
|
color: $code-text;
|
||||||
|
|
@ -121,6 +113,7 @@ main {
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-group {
|
.radio-group {
|
||||||
|
user-select: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -265,6 +258,7 @@ main {
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
|
user-select: none;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
@ -309,7 +303,6 @@ textarea {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
resize: none;
|
resize: none;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
user-select: text;
|
|
||||||
caret-color: $primary-blue;
|
caret-color: $primary-blue;
|
||||||
outline: 2px solid transparent;
|
outline: 2px solid transparent;
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
|
|
@ -334,7 +327,6 @@ textarea:focus {
|
||||||
|
|
||||||
#merged {
|
#merged {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
user-select: text;
|
|
||||||
|
|
||||||
> * {
|
> * {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
@ -349,14 +341,9 @@ textarea:focus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.Unchanged {
|
|
||||||
user-select: text;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Left,
|
.Left,
|
||||||
.AddedFromLeft,
|
.AddedFromLeft,
|
||||||
.RemovedFromLeft {
|
.RemovedFromLeft {
|
||||||
user-select: text;
|
|
||||||
background: $green;
|
background: $green;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -381,7 +368,6 @@ textarea:focus {
|
||||||
.Right,
|
.Right,
|
||||||
.AddedFromRight,
|
.AddedFromRight,
|
||||||
.RemovedFromRight {
|
.RemovedFromRight {
|
||||||
user-select: text;
|
|
||||||
background: $light-blue;
|
background: $light-blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -396,6 +382,7 @@ $CARET_WIDTH: 2;
|
||||||
$DOT_RADIUS: 4;
|
$DOT_RADIUS: 4;
|
||||||
|
|
||||||
.selection-caret {
|
.selection-caret {
|
||||||
|
user-select: none;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
|
|
||||||
|
|
@ -453,7 +440,6 @@ $DOT_RADIUS: 4;
|
||||||
top: -1.3em;
|
top: -1.3em;
|
||||||
left: calc(-#{$CARET_WIDTH} / 2 * 1px);
|
left: calc(-#{$CARET_WIDTH} / 2 * 1px);
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
user-select: none;
|
|
||||||
color: white;
|
color: white;
|
||||||
padding: 0 2px;
|
padding: 0 2px;
|
||||||
transition: opacity 0.3s ease-in-out;
|
transition: opacity 0.3s ease-in-out;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue