@@ -6,70 +6,6 @@ type Position = {
66 char : number ;
77} ;
88
9- function checkPosition ( position : Position , lines : Element [ ] ) : Position {
10- const { line, span, char } = position ;
11- const lineElement = lines [ line ] ;
12- const spanElement = lineElement . children [ span ] ?? lineElement ;
13- const text = spanElement . textContent ?? '' ;
14-
15- const nextPosition = { line, span, char } ;
16-
17- if ( char >= text . length ) {
18- nextPosition . char = 0 ;
19- nextPosition . span = span + 1 ;
20- }
21-
22- if ( nextPosition . span >= lineElement . children . length ) {
23- nextPosition . char = 0 ;
24- nextPosition . span = 0 ;
25- nextPosition . line = line + 1 ;
26- }
27-
28- return nextPosition ;
29- }
30-
31- function nextPosition ( position : Position , lines : Element [ ] ) : Position {
32- const { line, span, char } = position ;
33- const lineElement = lines [ line ] ;
34- const spanElement = lineElement . children [ span ] ?? lineElement ;
35- const text = spanElement . textContent ?? '' ;
36-
37- const nextPosition = { line, span, char : char + 1 } ;
38-
39- if ( char + 1 >= text . length ) {
40- nextPosition . char = 0 ;
41- nextPosition . span = span + 1 ;
42-
43- if ( nextPosition . span >= lineElement . children . length ) {
44- nextPosition . span = 0 ;
45- nextPosition . line = line + 1 ;
46- }
47- }
48-
49- return nextPosition ;
50- }
51-
52- function isAtEndOfText ( position : Position , lines : Element [ ] ) : boolean {
53- return position . line >= lines . length - 1 && isAtEndOfLine ( position , lines ) ;
54- }
55-
56- function isAtEndOfLine ( position : Position , lines : Element [ ] ) : boolean {
57- const line = lines [ position . line ] ;
58- return position . span >= line . children . length - 1 && isAtEndOfSpan ( position , lines ) ;
59- }
60-
61- function isAtEndOfSpan ( position : Position , lines : Element [ ] ) : boolean {
62- const line = lines [ position . line ] ;
63- const span = line . children [ position . span ] ?? line ;
64- return position . char >= ( span . textContent ?? '' ) . length - 1 ;
65- }
66-
67- function getCurrentSpan ( position : Position , lines : Element [ ] ) : HTMLElement {
68- const line = lines [ position . line ] ;
69-
70- return ( line . children [ position . span ] as HTMLElement ) ?? line ;
71- }
72-
739/**
7410 * Temporary updates the highlight overlay to reflect the changes between two text strings,
7511 * waiting for the actual update to be applied. This way, the user can immediately see the changes,
@@ -253,3 +189,91 @@ export function speculativeHighlightUpdate(from: string, to: string, currentHTML
253189
254190 return tree . innerHTML ;
255191}
192+
193+ /**
194+ * Create a new span at the end of the line element.
195+ * @param line The line element to append the span to.
196+ * @returns A new span element.
197+ */
198+ function createSpan ( line : Element ) : HTMLElement {
199+ const span = document . createElement ( 'span' ) ;
200+ line . appendChild ( span ) ;
201+ return span ;
202+ }
203+
204+ /**
205+ * Check whether the current position is valid, which means that the
206+ * the character index is within the text of the span, the span index is within the line,
207+ * @param position The position to check
208+ * @param lines The lines to work on.
209+ * @returns The next valid position.
210+ */
211+ function checkPosition ( position : Position , lines : Element [ ] ) : Position {
212+ const { line, span, char } = position ;
213+ const lineElement = lines [ line ] ;
214+ const spanElement = Array . from ( lineElement . children ) . at ( span ) ;
215+ const text = spanElement ?. textContent ?? '' ;
216+
217+ const nextPosition = { line, span, char } ;
218+
219+ if ( char >= text . length ) {
220+ nextPosition . char = 0 ;
221+ nextPosition . span = span + 1 ;
222+ }
223+
224+ if ( nextPosition . span >= lineElement . children . length ) {
225+ nextPosition . char = 0 ;
226+ nextPosition . span = 0 ;
227+ nextPosition . line = line + 1 ;
228+ }
229+
230+ return nextPosition ;
231+ }
232+
233+ /**
234+ * Get the next position in the tree.
235+ * @param position Current position
236+ * @param lines The lines to work on.
237+ * @returns The next position.
238+ */
239+ function nextPosition ( position : Position , lines : Element [ ] ) : Position {
240+ const { line, span, char } = position ;
241+ const lineElement = lines [ line ] ;
242+ const spanElement = lineElement . children [ span ] ?? createSpan ( lineElement ) ;
243+ const text = spanElement . textContent ?? '' ;
244+
245+ const nextPosition = { line, span, char : char + 1 } ;
246+
247+ if ( char + 1 >= text . length ) {
248+ nextPosition . char = 0 ;
249+ nextPosition . span = span + 1 ;
250+
251+ if ( nextPosition . span >= lineElement . children . length ) {
252+ nextPosition . span = 0 ;
253+ nextPosition . line = line + 1 ;
254+ }
255+ }
256+
257+ return nextPosition ;
258+ }
259+
260+ function isAtEndOfText ( position : Position , lines : Element [ ] ) : boolean {
261+ return position . line >= lines . length - 1 && isAtEndOfLine ( position , lines ) ;
262+ }
263+
264+ function isAtEndOfLine ( position : Position , lines : Element [ ] ) : boolean {
265+ const line = lines [ position . line ] ;
266+ return position . span >= line . children . length - 1 && isAtEndOfSpan ( position , lines ) ;
267+ }
268+
269+ function isAtEndOfSpan ( position : Position , lines : Element [ ] ) : boolean {
270+ const line = lines [ position . line ] ;
271+ const span = line . children [ position . span ] ?? line ;
272+ return position . char >= ( span . textContent ?? '' ) . length - 1 ;
273+ }
274+
275+ function getCurrentSpan ( position : Position , lines : Element [ ] ) : HTMLElement {
276+ const line = lines [ position . line ] ;
277+
278+ return ( line . children [ position . span ] as HTMLElement ) ?? createSpan ( line ) ;
279+ }
0 commit comments