1- import type { Span } from 'harper.js' ;
1+ import { type Span , SuggestionKind } from 'harper.js' ;
22import { domRectToBox , type IgnorableLintBox , isBottomEdgeInBox , shrinkBoxToFit } from './Box' ;
33import { getRangeForTextSpan } from './domUtils' ;
44import {
@@ -9,7 +9,12 @@ import {
99 isFormEl ,
1010} from './editorUtils' ;
1111import 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
1419export 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+
86106function 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
252267function 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