Skip to content

Commit de0a153

Browse files
fix(lint-framework): SuggestionKind.InsertAfter removing text (#2693)
1 parent 42f4f2b commit de0a153

1 file changed

Lines changed: 37 additions & 20 deletions

File tree

packages/lint-framework/src/lint/computeLintBoxes.ts

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Span } from 'harper.js';
1+
import { type Span, SuggestionKind } from 'harper.js';
22
import { domRectToBox, type IgnorableLintBox, isBottomEdgeInBox, shrinkBoxToFit } from './Box';
33
import { getRangeForTextSpan } from './domUtils';
44
import {
@@ -9,7 +9,12 @@ import {
99
isFormEl,
1010
} from './editorUtils';
1111
import TextFieldRange from './TextFieldRange';
12-
import { applySuggestion, type UnpackedLint, type UnpackedSuggestion } from './unpackLint';
12+
import {
13+
applySuggestion,
14+
type UnpackedLint,
15+
type UnpackedSpan,
16+
type UnpackedSuggestion,
17+
} from './unpackLint';
1318

1419
export default function computeLintBoxes(
1520
el: HTMLElement,
@@ -70,8 +75,7 @@ export default function computeLintBoxes(
7075
const current = isFormEl(el)
7176
? (el as HTMLInputElement | HTMLTextAreaElement).value
7277
: (el.textContent ?? '');
73-
const newValue = applySuggestion(current, lint.span, sug);
74-
replaceValue(el, newValue, lint.span, sug.replacement_text);
78+
replaceValue(el, lint.span, suggestionToReplacementText(sug, lint.span, current));
7579
},
7680
ignoreLint: opts.ignoreLint ? () => opts.ignoreLint!(lint.context_hash) : undefined,
7781
});
@@ -83,26 +87,37 @@ export default function computeLintBoxes(
8387
}
8488
}
8589

90+
/** Transform an arbitrary suggestion to the equivalent replacement text. */
91+
function suggestionToReplacementText(
92+
sug: UnpackedSuggestion,
93+
span: UnpackedSpan,
94+
source: string,
95+
): string {
96+
switch (sug.kind) {
97+
case SuggestionKind.Replace:
98+
return sug.replacement_text;
99+
case SuggestionKind.Remove:
100+
return '';
101+
case SuggestionKind.InsertAfter:
102+
return source.slice(span.start, span.end) + sug.replacement_text;
103+
}
104+
}
105+
86106
function replaceValue(
87107
el: HTMLElement,
88-
value: string,
89-
span?: { start: number; end: number },
90-
replacementText?: string,
108+
span: { start: number; end: number },
109+
replacementText: string,
91110
) {
92-
if (isFormEl(el) && span && replacementText !== undefined) {
111+
if (isFormEl(el)) {
93112
replaceFormElementValue(el as HTMLTextAreaElement | HTMLInputElement, span, replacementText);
94-
} else if (getLexicalRoot(el) != null && span && replacementText !== undefined) {
113+
} else if (getLexicalRoot(el) != null) {
95114
replaceLexicalValue(el, span, replacementText);
96-
} else if (getDraftRoot(el) != null && span && replacementText !== undefined) {
115+
} else if (getDraftRoot(el) != null) {
97116
replaceDraftValue(el, span, replacementText);
98-
} else if (
99-
(getSlateRoot(el) != null || getCkEditorRoot(el) != null) &&
100-
span &&
101-
replacementText !== undefined
102-
) {
117+
} else if (getSlateRoot(el) != null || getCkEditorRoot(el) != null) {
103118
replaceRichTextEditorValue(el, span, replacementText);
104119
} else {
105-
replaceGenericContentEditable(el, value, span, replacementText);
120+
replaceGenericContentEditable(el, span, replacementText);
106121
}
107122

108123
el.dispatchEvent(new Event('change', { bubbles: true }));
@@ -251,9 +266,8 @@ function replaceTextInRange(doc: Document, sel: Selection, range: Range, replace
251266

252267
function replaceGenericContentEditable(
253268
el: HTMLElement,
254-
value: string,
255-
span?: { start: number; end: number },
256-
replacementText?: string,
269+
span: { start: number; end: number },
270+
replacementText: string,
257271
) {
258272
if (span && replacementText !== undefined) {
259273
const setup = selectSpanInEditor(el, span);
@@ -266,6 +280,9 @@ function replaceGenericContentEditable(
266280
}
267281

268282
// Fallback: replace entire content
269-
el.textContent = value;
283+
el.textContent = applySuggestion(el.textContent, span, {
284+
kind: SuggestionKind.Replace,
285+
replacement_text: replacementText,
286+
});
270287
el.dispatchEvent(new InputEvent('input', { bubbles: true }));
271288
}

0 commit comments

Comments
 (0)