@@ -58,3 +58,169 @@ test("extracts name with complex regex pattern", async () => {
5858 const annotation = annotations [ 0 ]
5959 expect ( annotation . name ) . toEqual ( "tooltip" )
6060} )
61+
62+ // start/end range marker tests
63+
64+ test ( "start/end creates block annotation spanning the range" , async ( ) => {
65+ const code = [
66+ "let a = 1" ,
67+ "// !focus(start)" ,
68+ "let b = 2" ,
69+ "let c = 3" ,
70+ "// !focus(end)" ,
71+ "let d = 4" ,
72+ ] . join ( "\n" )
73+ const { code : resultCode , annotations } = await splitAnnotationsAndCode (
74+ code ,
75+ "javascript" ,
76+ "!" ,
77+ )
78+ expect ( resultCode ) . not . toContain ( "!focus" )
79+ expect ( annotations ) . toHaveLength ( 1 )
80+ const a = annotations [ 0 ]
81+ expect ( a . name ) . toEqual ( "focus" )
82+ expect ( a . ranges ) . toHaveLength ( 1 )
83+ const range = a . ranges [ 0 ]
84+ // after removing 2 comment lines, the code is 4 lines
85+ // "let b = 2" is line 2, "let c = 3" is line 3
86+ expect ( range . fromLineNumber ) . toEqual ( 2 )
87+ expect ( range . toLineNumber ) . toEqual ( 3 )
88+ } )
89+
90+ test ( "start/end preserves query string" , async ( ) => {
91+ const code = [
92+ "// !box(start) myquery" ,
93+ "let x = 1" ,
94+ "// !box(end)" ,
95+ ] . join ( "\n" )
96+ const { annotations } = await splitAnnotationsAndCode (
97+ code ,
98+ "javascript" ,
99+ "!" ,
100+ )
101+ expect ( annotations ) . toHaveLength ( 1 )
102+ expect ( annotations [ 0 ] . name ) . toEqual ( "box" )
103+ expect ( annotations [ 0 ] . query ) . toEqual ( "myquery" )
104+ } )
105+
106+ test ( "start/end works with other annotations" , async ( ) => {
107+ const code = [
108+ "// !mark" ,
109+ "let a = 1" ,
110+ "// !focus(start)" ,
111+ "let b = 2" ,
112+ "let c = 3" ,
113+ "// !focus(end)" ,
114+ "let d = 4" ,
115+ ] . join ( "\n" )
116+ const { annotations } = await splitAnnotationsAndCode (
117+ code ,
118+ "javascript" ,
119+ "!" ,
120+ )
121+ expect ( annotations ) . toHaveLength ( 2 )
122+ const mark = annotations . find ( ( a ) => a . name === "mark" )
123+ const focus = annotations . find ( ( a ) => a . name === "focus" )
124+ expect ( mark ) . toBeDefined ( )
125+ expect ( focus ) . toBeDefined ( )
126+ expect ( focus ! . ranges [ 0 ] . fromLineNumber ) . toBeDefined ( )
127+ expect ( focus ! . ranges [ 0 ] . toLineNumber ) . toBeDefined ( )
128+ } )
129+
130+ test ( "multiple start/end pairs of same name" , async ( ) => {
131+ const code = [
132+ "let a = 1" ,
133+ "// !focus(start)" ,
134+ "let b = 2" ,
135+ "// !focus(end)" ,
136+ "let c = 3" ,
137+ "// !focus(start)" ,
138+ "let d = 4" ,
139+ "// !focus(end)" ,
140+ "let e = 5" ,
141+ ] . join ( "\n" )
142+ const { annotations } = await splitAnnotationsAndCode (
143+ code ,
144+ "javascript" ,
145+ "!" ,
146+ )
147+ expect ( annotations ) . toHaveLength ( 2 )
148+ expect ( annotations [ 0 ] . name ) . toEqual ( "focus" )
149+ expect ( annotations [ 1 ] . name ) . toEqual ( "focus" )
150+ // The two ranges should not overlap
151+ const r0 = annotations [ 0 ] . ranges [ 0 ]
152+ const r1 = annotations [ 1 ] . ranges [ 0 ]
153+ expect ( r0 . toLineNumber ) . toBeLessThan ( r1 . fromLineNumber )
154+ } )
155+
156+ test ( "different annotation names with start/end" , async ( ) => {
157+ const code = [
158+ "// !focus(start)" ,
159+ "let a = 1" ,
160+ "// !mark(start)" ,
161+ "let b = 2" ,
162+ "// !mark(end)" ,
163+ "let c = 3" ,
164+ "// !focus(end)" ,
165+ ] . join ( "\n" )
166+ const { annotations } = await splitAnnotationsAndCode (
167+ code ,
168+ "javascript" ,
169+ "!" ,
170+ )
171+ expect ( annotations ) . toHaveLength ( 2 )
172+ const focus = annotations . find ( ( a ) => a . name === "focus" )
173+ const mark = annotations . find ( ( a ) => a . name === "mark" )
174+ expect ( focus ) . toBeDefined ( )
175+ expect ( mark ) . toBeDefined ( )
176+ } )
177+
178+ test ( "start/end removes comment lines from code" , async ( ) => {
179+ const code = [
180+ "let a = 1" ,
181+ "// !focus(start)" ,
182+ "let b = 2" ,
183+ "// !focus(end)" ,
184+ "let c = 3" ,
185+ ] . join ( "\n" )
186+ const { code : resultCode } = await splitAnnotationsAndCode (
187+ code ,
188+ "javascript" ,
189+ "!" ,
190+ )
191+ const lines = resultCode . split ( "\n" )
192+ expect ( lines ) . toHaveLength ( 3 )
193+ expect ( lines [ 0 ] ) . toContain ( "let a = 1" )
194+ expect ( lines [ 1 ] ) . toContain ( "let b = 2" )
195+ expect ( lines [ 2 ] ) . toContain ( "let c = 3" )
196+ } )
197+
198+ test ( "start/end works with Python comments" , async ( ) => {
199+ const code = [
200+ "x = 1" ,
201+ "# !focus(start)" ,
202+ "y = 2" ,
203+ "z = 3" ,
204+ "# !focus(end)" ,
205+ "w = 4" ,
206+ ] . join ( "\n" )
207+ const { annotations } = await splitAnnotationsAndCode ( code , "python" , "!" )
208+ expect ( annotations ) . toHaveLength ( 1 )
209+ expect ( annotations [ 0 ] . name ) . toEqual ( "focus" )
210+ expect ( annotations [ 0 ] . ranges [ 0 ] . fromLineNumber ) . toEqual ( 2 )
211+ expect ( annotations [ 0 ] . ranges [ 0 ] . toLineNumber ) . toEqual ( 3 )
212+ } )
213+
214+ test ( "start/end works with block comments" , async ( ) => {
215+ const code = [
216+ "int a = 1;" ,
217+ "/* !mark(start) */" ,
218+ "int b = 2;" ,
219+ "int c = 3;" ,
220+ "/* !mark(end) */" ,
221+ "int d = 4;" ,
222+ ] . join ( "\n" )
223+ const { annotations } = await splitAnnotationsAndCode ( code , "c" , "!" )
224+ expect ( annotations ) . toHaveLength ( 1 )
225+ expect ( annotations [ 0 ] . name ) . toEqual ( "mark" )
226+ } )
0 commit comments