opencode-navigator 0.24.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1156 @@
1
+ import {createComponent as _$createComponent4} from "@opentui/solid"
2
+ import {createSignal} from "solid-js"
3
+ function todoConfig(entries){let owner=-1
4
+ for(const [index,entry] of entries.entries()){if(entry.experimental!==undefined)
5
+ owner=index
6
+ }
7
+ const enabled=owner>=0&&entries[owner].experimental?.todo===true
8
+ const candidates=owner>=0?[entries[owner]]:entries
9
+ const files=[...new Set(candidates.flatMap((entry)=>entry.path&&/\.jsonc?$/iu.test(entry.path)?[entry.path]:[]))]
10
+ return{enabled,files,signature:JSON.stringify(entries),unavailable:files.length===0?"OpenCode did not expose an editable JSON/JSONC source for its effective experimental settings.":undefined
11
+ }}
12
+ function createScanner(text,ignoreTrivia=false){const len=text.length
13
+ let pos=0,value="",tokenOffset=0,token=16,lineNumber=0,lineStartOffset=0,tokenLineStartOffset=0,prevTokenLineStartOffset=0,scanError=0
14
+ function scanHexDigits(count,exact){let digits=0
15
+ let value=0
16
+ while(digits<count||!exact){let ch=text.charCodeAt(pos)
17
+ if(ch>=48&&ch<=57){value=value*16 + ch-48
18
+ } else if(ch>=65&&ch<=70){value=value*16 + ch-65 + 10
19
+ } else if(ch>=97&&ch<=102){value=value*16 + ch-97 + 10
20
+ } else{break
21
+ }
22
+ pos++
23
+ digits++
24
+ }
25
+ if(digits<count){value=-1
26
+ }
27
+ return value
28
+ }
29
+ function setPosition(newPosition){pos=newPosition
30
+ value=""
31
+ tokenOffset=0
32
+ token=16
33
+ scanError=0
34
+ }
35
+ function scanNumber(){let start=pos
36
+ if(text.charCodeAt(pos)===48){pos++
37
+ } else{pos++
38
+ while(pos<text.length&&isDigit(text.charCodeAt(pos))){pos++
39
+ }}
40
+ if(pos<text.length&&text.charCodeAt(pos)===46){pos++
41
+ if(pos<text.length&&isDigit(text.charCodeAt(pos))){pos++
42
+ while(pos<text.length&&isDigit(text.charCodeAt(pos))){pos++
43
+ }} else{scanError=3
44
+ return text.substring(start,pos)
45
+ }}
46
+ let end=pos
47
+ if(pos<text.length&&(text.charCodeAt(pos)===69||text.charCodeAt(pos)===101)){pos++
48
+ if(pos<text.length&&text.charCodeAt(pos)===43||text.charCodeAt(pos)===45){pos++
49
+ }
50
+ if(pos<text.length&&isDigit(text.charCodeAt(pos))){pos++
51
+ while(pos<text.length&&isDigit(text.charCodeAt(pos))){pos++
52
+ }
53
+ end=pos
54
+ } else{scanError=3
55
+ }}
56
+ return text.substring(start,end)
57
+ }
58
+ function scanString(){let result="",start=pos
59
+ while(true){if(pos>=len){result += text.substring(start,pos)
60
+ scanError=2
61
+ break
62
+ }
63
+ const ch=text.charCodeAt(pos)
64
+ if(ch===34){result += text.substring(start,pos)
65
+ pos++
66
+ break
67
+ }
68
+ if(ch===92){result += text.substring(start,pos)
69
+ pos++
70
+ if(pos>=len){scanError=2
71
+ break
72
+ }
73
+ const ch2=text.charCodeAt(pos++)
74
+ switch(ch2){case 34:result += '"'
75
+ break
76
+ case 92:result += "\\"
77
+ break
78
+ case 47:result += "/"
79
+ break
80
+ case 98:result += "\b"
81
+ break
82
+ case 102:result += "\f"
83
+ break
84
+ case 110:result += `
85
+ `
86
+ break
87
+ case 114:result += "\r"
88
+ break
89
+ case 116:result += "\t"
90
+ break
91
+ case 117:const ch3=scanHexDigits(4,true)
92
+ if(ch3>=0){result += String.fromCharCode(ch3)
93
+ } else{scanError=4
94
+ }
95
+ break
96
+ default:scanError=5
97
+ }
98
+ start=pos
99
+ continue
100
+ }
101
+ if(ch>=0&&ch<=31){if(isLineBreak(ch)){result += text.substring(start,pos)
102
+ scanError=2
103
+ break
104
+ } else{scanError=6
105
+ }}
106
+ pos++
107
+ }
108
+ return result
109
+ }
110
+ function scanNext(){value=""
111
+ scanError=0
112
+ tokenOffset=pos
113
+ lineStartOffset=lineNumber
114
+ prevTokenLineStartOffset=tokenLineStartOffset
115
+ if(pos>=len){tokenOffset=len
116
+ return token=17
117
+ }
118
+ let code=text.charCodeAt(pos)
119
+ if(isWhiteSpace(code)){do{pos++
120
+ value += String.fromCharCode(code)
121
+ code=text.charCodeAt(pos)
122
+ } while(isWhiteSpace(code))
123
+ return token=15
124
+ }
125
+ if(isLineBreak(code)){pos++
126
+ value += String.fromCharCode(code)
127
+ if(code===13&&text.charCodeAt(pos)===10){pos++
128
+ value += `
129
+ `
130
+ }
131
+ lineNumber++
132
+ tokenLineStartOffset=pos
133
+ return token=14
134
+ }
135
+ switch(code){case 123:pos++
136
+ return token=1
137
+ case 125:pos++
138
+ return token=2
139
+ case 91:pos++
140
+ return token=3
141
+ case 93:pos++
142
+ return token=4
143
+ case 58:pos++
144
+ return token=6
145
+ case 44:pos++
146
+ return token=5
147
+ case 34:pos++
148
+ value=scanString()
149
+ return token=10
150
+ case 47:const start=pos-1
151
+ if(text.charCodeAt(pos + 1)===47){pos += 2
152
+ while(pos<len){if(isLineBreak(text.charCodeAt(pos))){break
153
+ }
154
+ pos++
155
+ }
156
+ value=text.substring(start,pos)
157
+ return token=12
158
+ }
159
+ if(text.charCodeAt(pos + 1)===42){pos += 2
160
+ const safeLength=len-1
161
+ let commentClosed=false
162
+ while(pos<safeLength){const ch=text.charCodeAt(pos)
163
+ if(ch===42&&text.charCodeAt(pos + 1)===47){pos += 2
164
+ commentClosed=true
165
+ break
166
+ }
167
+ pos++
168
+ if(isLineBreak(ch)){if(ch===13&&text.charCodeAt(pos)===10){pos++
169
+ }
170
+ lineNumber++
171
+ tokenLineStartOffset=pos
172
+ }}
173
+ if(!commentClosed){pos++
174
+ scanError=1
175
+ }
176
+ value=text.substring(start,pos)
177
+ return token=13
178
+ }
179
+ value += String.fromCharCode(code)
180
+ pos++
181
+ return token=16
182
+ case 45:value += String.fromCharCode(code)
183
+ pos++
184
+ if(pos===len||!isDigit(text.charCodeAt(pos))){return token=16
185
+ }
186
+ case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:value += scanNumber()
187
+ return token=11
188
+ default:while(pos<len&&isUnknownContentCharacter(code)){pos++
189
+ code=text.charCodeAt(pos)
190
+ }
191
+ if(tokenOffset!==pos){value=text.substring(tokenOffset,pos)
192
+ switch(value){case "true":return token=8
193
+ case "false":return token=9
194
+ case "null":return token=7
195
+ }
196
+ return token=16
197
+ }
198
+ value += String.fromCharCode(code)
199
+ pos++
200
+ return token=16
201
+ }}
202
+ function isUnknownContentCharacter(code){if(isWhiteSpace(code)||isLineBreak(code)){return false
203
+ }
204
+ switch(code){case 125:case 93:case 123:case 91:case 34:case 58:case 44:case 47:return false
205
+ }
206
+ return true
207
+ }
208
+ function scanNextNonTrivia(){let result
209
+ do{result=scanNext()
210
+ } while(result>=12&&result<=15)
211
+ return result
212
+ }
213
+ return{setPosition,getPosition:()=>pos,scan:ignoreTrivia?scanNextNonTrivia:scanNext,getToken:()=>token,getTokenValue:()=>value,getTokenOffset:()=>tokenOffset,getTokenLength:()=>pos-tokenOffset,getTokenStartLine:()=>lineStartOffset,getTokenStartCharacter:()=>tokenOffset-prevTokenLineStartOffset,getTokenError:()=>scanError
214
+ }}
215
+ function isWhiteSpace(ch){return ch===32||ch===9
216
+ }
217
+ function isLineBreak(ch){return ch===10||ch===13
218
+ }
219
+ function isDigit(ch){return ch>=48&&ch<=57
220
+ }
221
+ var CharacterCodes;
222
+ (function(CharacterCodes){CharacterCodes[CharacterCodes["lineFeed"]=10]="lineFeed"
223
+ CharacterCodes[CharacterCodes["carriageReturn"]=13]="carriageReturn"
224
+ CharacterCodes[CharacterCodes["space"]=32]="space"
225
+ CharacterCodes[CharacterCodes["_0"]=48]="_0"
226
+ CharacterCodes[CharacterCodes["_1"]=49]="_1"
227
+ CharacterCodes[CharacterCodes["_2"]=50]="_2"
228
+ CharacterCodes[CharacterCodes["_3"]=51]="_3"
229
+ CharacterCodes[CharacterCodes["_4"]=52]="_4"
230
+ CharacterCodes[CharacterCodes["_5"]=53]="_5"
231
+ CharacterCodes[CharacterCodes["_6"]=54]="_6"
232
+ CharacterCodes[CharacterCodes["_7"]=55]="_7"
233
+ CharacterCodes[CharacterCodes["_8"]=56]="_8"
234
+ CharacterCodes[CharacterCodes["_9"]=57]="_9"
235
+ CharacterCodes[CharacterCodes["a"]=97]="a"
236
+ CharacterCodes[CharacterCodes["b"]=98]="b"
237
+ CharacterCodes[CharacterCodes["c"]=99]="c"
238
+ CharacterCodes[CharacterCodes["d"]=100]="d"
239
+ CharacterCodes[CharacterCodes["e"]=101]="e"
240
+ CharacterCodes[CharacterCodes["f"]=102]="f"
241
+ CharacterCodes[CharacterCodes["g"]=103]="g"
242
+ CharacterCodes[CharacterCodes["h"]=104]="h"
243
+ CharacterCodes[CharacterCodes["i"]=105]="i"
244
+ CharacterCodes[CharacterCodes["j"]=106]="j"
245
+ CharacterCodes[CharacterCodes["k"]=107]="k"
246
+ CharacterCodes[CharacterCodes["l"]=108]="l"
247
+ CharacterCodes[CharacterCodes["m"]=109]="m"
248
+ CharacterCodes[CharacterCodes["n"]=110]="n"
249
+ CharacterCodes[CharacterCodes["o"]=111]="o"
250
+ CharacterCodes[CharacterCodes["p"]=112]="p"
251
+ CharacterCodes[CharacterCodes["q"]=113]="q"
252
+ CharacterCodes[CharacterCodes["r"]=114]="r"
253
+ CharacterCodes[CharacterCodes["s"]=115]="s"
254
+ CharacterCodes[CharacterCodes["t"]=116]="t"
255
+ CharacterCodes[CharacterCodes["u"]=117]="u"
256
+ CharacterCodes[CharacterCodes["v"]=118]="v"
257
+ CharacterCodes[CharacterCodes["w"]=119]="w"
258
+ CharacterCodes[CharacterCodes["x"]=120]="x"
259
+ CharacterCodes[CharacterCodes["y"]=121]="y"
260
+ CharacterCodes[CharacterCodes["z"]=122]="z"
261
+ CharacterCodes[CharacterCodes["A"]=65]="A"
262
+ CharacterCodes[CharacterCodes["B"]=66]="B"
263
+ CharacterCodes[CharacterCodes["C"]=67]="C"
264
+ CharacterCodes[CharacterCodes["D"]=68]="D"
265
+ CharacterCodes[CharacterCodes["E"]=69]="E"
266
+ CharacterCodes[CharacterCodes["F"]=70]="F"
267
+ CharacterCodes[CharacterCodes["G"]=71]="G"
268
+ CharacterCodes[CharacterCodes["H"]=72]="H"
269
+ CharacterCodes[CharacterCodes["I"]=73]="I"
270
+ CharacterCodes[CharacterCodes["J"]=74]="J"
271
+ CharacterCodes[CharacterCodes["K"]=75]="K"
272
+ CharacterCodes[CharacterCodes["L"]=76]="L"
273
+ CharacterCodes[CharacterCodes["M"]=77]="M"
274
+ CharacterCodes[CharacterCodes["N"]=78]="N"
275
+ CharacterCodes[CharacterCodes["O"]=79]="O"
276
+ CharacterCodes[CharacterCodes["P"]=80]="P"
277
+ CharacterCodes[CharacterCodes["Q"]=81]="Q"
278
+ CharacterCodes[CharacterCodes["R"]=82]="R"
279
+ CharacterCodes[CharacterCodes["S"]=83]="S"
280
+ CharacterCodes[CharacterCodes["T"]=84]="T"
281
+ CharacterCodes[CharacterCodes["U"]=85]="U"
282
+ CharacterCodes[CharacterCodes["V"]=86]="V"
283
+ CharacterCodes[CharacterCodes["W"]=87]="W"
284
+ CharacterCodes[CharacterCodes["X"]=88]="X"
285
+ CharacterCodes[CharacterCodes["Y"]=89]="Y"
286
+ CharacterCodes[CharacterCodes["Z"]=90]="Z"
287
+ CharacterCodes[CharacterCodes["asterisk"]=42]="asterisk"
288
+ CharacterCodes[CharacterCodes["backslash"]=92]="backslash"
289
+ CharacterCodes[CharacterCodes["closeBrace"]=125]="closeBrace"
290
+ CharacterCodes[CharacterCodes["closeBracket"]=93]="closeBracket"
291
+ CharacterCodes[CharacterCodes["colon"]=58]="colon"
292
+ CharacterCodes[CharacterCodes["comma"]=44]="comma"
293
+ CharacterCodes[CharacterCodes["dot"]=46]="dot"
294
+ CharacterCodes[CharacterCodes["doubleQuote"]=34]="doubleQuote"
295
+ CharacterCodes[CharacterCodes["minus"]=45]="minus"
296
+ CharacterCodes[CharacterCodes["openBrace"]=123]="openBrace"
297
+ CharacterCodes[CharacterCodes["openBracket"]=91]="openBracket"
298
+ CharacterCodes[CharacterCodes["plus"]=43]="plus"
299
+ CharacterCodes[CharacterCodes["slash"]=47]="slash"
300
+ CharacterCodes[CharacterCodes["formFeed"]=12]="formFeed"
301
+ CharacterCodes[CharacterCodes["tab"]=9]="tab"
302
+ })(CharacterCodes||(CharacterCodes={}));
303
+ var cachedSpaces=new Array(20).fill(0).map((_,index)=>{return " ".repeat(index)
304
+ })
305
+ var maxCachedValues=200
306
+ var cachedBreakLinesWithSpaces={" ":{"\n":new Array(maxCachedValues).fill(0).map((_,index)=>{return `
307
+ ` + " ".repeat(index)
308
+ }),"\r":new Array(maxCachedValues).fill(0).map((_,index)=>{return "\r" + " ".repeat(index)
309
+ }),"\r\n":new Array(maxCachedValues).fill(0).map((_,index)=>{return `\r
310
+ ` + " ".repeat(index)
311
+ })
312
+ },"\t":{"\n":new Array(maxCachedValues).fill(0).map((_,index)=>{return `
313
+ ` + "\t".repeat(index)
314
+ }),"\r":new Array(maxCachedValues).fill(0).map((_,index)=>{return "\r" + "\t".repeat(index)
315
+ }),"\r\n":new Array(maxCachedValues).fill(0).map((_,index)=>{return `\r
316
+ ` + "\t".repeat(index)
317
+ })
318
+ }}
319
+ var supportedEols=[`
320
+ `,"\r",`\r
321
+ `];
322
+ function format(documentText,range,options){let initialIndentLevel
323
+ let formatText
324
+ let formatTextStart
325
+ let rangeStart
326
+ let rangeEnd
327
+ if(range){rangeStart=range.offset
328
+ rangeEnd=rangeStart + range.length
329
+ formatTextStart=rangeStart
330
+ while(formatTextStart>0&&!isEOL(documentText,formatTextStart-1)){formatTextStart--
331
+ }
332
+ let endOffset=rangeEnd
333
+ while(endOffset<documentText.length&&!isEOL(documentText,endOffset)){endOffset++
334
+ }
335
+ formatText=documentText.substring(formatTextStart,endOffset)
336
+ initialIndentLevel=computeIndentLevel(formatText,options)
337
+ } else{formatText=documentText
338
+ initialIndentLevel=0
339
+ formatTextStart=0
340
+ rangeStart=0
341
+ rangeEnd=documentText.length
342
+ }
343
+ const eol=getEOL(options,documentText)
344
+ const eolFastPathSupported=supportedEols.includes(eol)
345
+ let numberLineBreaks=0
346
+ let indentLevel=0
347
+ let indentValue
348
+ if(options.insertSpaces){indentValue=cachedSpaces[options.tabSize||4]??repeat(cachedSpaces[1],options.tabSize||4)
349
+ } else{indentValue="\t"
350
+ }
351
+ const indentType=indentValue==="\t"?"\t":" "
352
+ let scanner=createScanner(formatText,false)
353
+ let hasError=false
354
+ function newLinesAndIndent(){if(numberLineBreaks>1){return repeat(eol,numberLineBreaks) + repeat(indentValue,initialIndentLevel + indentLevel)
355
+ }
356
+ const amountOfSpaces=indentValue.length*(initialIndentLevel + indentLevel)
357
+ if(!eolFastPathSupported||amountOfSpaces>cachedBreakLinesWithSpaces[indentType][eol].length){return eol + repeat(indentValue,initialIndentLevel + indentLevel)
358
+ }
359
+ if(amountOfSpaces<=0){return eol
360
+ }
361
+ return cachedBreakLinesWithSpaces[indentType][eol][amountOfSpaces]
362
+ }
363
+ function scanNext(){let token=scanner.scan()
364
+ numberLineBreaks=0
365
+ while(token===15||token===14){if(token===14&&options.keepLines){numberLineBreaks += 1
366
+ } else if(token===14){numberLineBreaks=1
367
+ }
368
+ token=scanner.scan()
369
+ }
370
+ hasError=token===16||scanner.getTokenError()!==0
371
+ return token
372
+ }
373
+ const editOperations=[]
374
+ function addEdit(text,startOffset,endOffset){if(!hasError&&(!range||startOffset<rangeEnd&&endOffset>rangeStart)&&documentText.substring(startOffset,endOffset)!==text){editOperations.push({offset:startOffset,length:endOffset-startOffset,content:text})
375
+ }}
376
+ let firstToken=scanNext()
377
+ if(options.keepLines&&numberLineBreaks>0){addEdit(repeat(eol,numberLineBreaks),0,0)
378
+ }
379
+ if(firstToken!==17){let firstTokenStart=scanner.getTokenOffset() + formatTextStart
380
+ let initialIndent=indentValue.length*initialIndentLevel<20&&options.insertSpaces?cachedSpaces[indentValue.length*initialIndentLevel]:repeat(indentValue,initialIndentLevel)
381
+ addEdit(initialIndent,formatTextStart,firstTokenStart)
382
+ }
383
+ while(firstToken!==17){let firstTokenEnd=scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart
384
+ let secondToken=scanNext()
385
+ let replaceContent=""
386
+ let needsLineBreak=false
387
+ while(numberLineBreaks===0&&(secondToken===12||secondToken===13)){let commentTokenStart=scanner.getTokenOffset() + formatTextStart
388
+ addEdit(cachedSpaces[1],firstTokenEnd,commentTokenStart)
389
+ firstTokenEnd=scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart
390
+ needsLineBreak=secondToken===12
391
+ replaceContent=needsLineBreak?newLinesAndIndent():""
392
+ secondToken=scanNext()
393
+ }
394
+ if(secondToken===2){if(firstToken!==1){indentLevel--
395
+ }
396
+ if(options.keepLines&&numberLineBreaks>0||!options.keepLines&&firstToken!==1){replaceContent=newLinesAndIndent()
397
+ } else if(options.keepLines){replaceContent=cachedSpaces[1]
398
+ }} else if(secondToken===4){if(firstToken!==3){indentLevel--
399
+ }
400
+ if(options.keepLines&&numberLineBreaks>0||!options.keepLines&&firstToken!==3){replaceContent=newLinesAndIndent()
401
+ } else if(options.keepLines){replaceContent=cachedSpaces[1]
402
+ }} else{switch(firstToken){case 3:case 1:indentLevel++
403
+ if(options.keepLines&&numberLineBreaks>0||!options.keepLines){replaceContent=newLinesAndIndent()
404
+ } else{replaceContent=cachedSpaces[1]
405
+ }
406
+ break
407
+ case 5:if(options.keepLines&&numberLineBreaks>0||!options.keepLines){replaceContent=newLinesAndIndent()
408
+ } else{replaceContent=cachedSpaces[1]
409
+ }
410
+ break
411
+ case 12:replaceContent=newLinesAndIndent()
412
+ break
413
+ case 13:if(numberLineBreaks>0){replaceContent=newLinesAndIndent()
414
+ } else if(!needsLineBreak){replaceContent=cachedSpaces[1]
415
+ }
416
+ break
417
+ case 6:if(options.keepLines&&numberLineBreaks>0){replaceContent=newLinesAndIndent()
418
+ } else if(!needsLineBreak){replaceContent=cachedSpaces[1]
419
+ }
420
+ break
421
+ case 10:if(options.keepLines&&numberLineBreaks>0){replaceContent=newLinesAndIndent()
422
+ } else if(secondToken===6&&!needsLineBreak){replaceContent=""
423
+ }
424
+ break
425
+ case 7:case 8:case 9:case 11:case 2:case 4:if(options.keepLines&&numberLineBreaks>0){replaceContent=newLinesAndIndent()
426
+ } else{if((secondToken===12||secondToken===13)&&!needsLineBreak){replaceContent=cachedSpaces[1]
427
+ } else if(secondToken!==5&&secondToken!==17){hasError=true
428
+ }}
429
+ break
430
+ case 16:hasError=true
431
+ break
432
+ }
433
+ if(numberLineBreaks>0&&(secondToken===12||secondToken===13)){replaceContent=newLinesAndIndent()
434
+ }}
435
+ if(secondToken===17){if(options.keepLines&&numberLineBreaks>0){replaceContent=newLinesAndIndent()
436
+ } else{replaceContent=options.insertFinalNewline?eol:""
437
+ }}
438
+ const secondTokenStart=scanner.getTokenOffset() + formatTextStart
439
+ addEdit(replaceContent,firstTokenEnd,secondTokenStart)
440
+ firstToken=secondToken
441
+ }
442
+ return editOperations
443
+ }
444
+ function repeat(s,count){let result=""
445
+ for(let i=0;i<count; i++){result += s
446
+ }
447
+ return result
448
+ }
449
+ function computeIndentLevel(content,options){let i=0
450
+ let nChars=0
451
+ const tabSize=options.tabSize||4
452
+ while(i<content.length){let ch=content.charAt(i)
453
+ if(ch===cachedSpaces[1]){nChars++
454
+ } else if(ch==="\t"){nChars += tabSize
455
+ } else{break
456
+ }
457
+ i++
458
+ }
459
+ return Math.floor(nChars / tabSize)
460
+ }
461
+ function getEOL(options,text){for(let i=0;i<text.length; i++){const ch=text.charAt(i)
462
+ if(ch==="\r"){if(i + 1<text.length&&text.charAt(i + 1)===`
463
+ `){return `\r
464
+ `
465
+ }
466
+ return "\r"
467
+ } else if(ch===`
468
+ `){return `
469
+ `
470
+ }}
471
+ return options&&options.eol||`
472
+ `
473
+ }
474
+ function isEOL(text,offset){return `\r
475
+ `.indexOf(text.charAt(offset))!==-1
476
+ }
477
+ var ParseOptions;
478
+ (function(ParseOptions){ParseOptions.DEFAULT={allowTrailingComma:false
479
+ }})(ParseOptions||(ParseOptions={}))
480
+ function parseTree(text,errors=[],options=ParseOptions.DEFAULT){let currentParent={type:"array",offset:-1,length:-1,children:[],parent:undefined}
481
+ function ensurePropertyComplete(endOffset){if(currentParent.type==="property"){currentParent.length=endOffset-currentParent.offset
482
+ currentParent=currentParent.parent
483
+ }}
484
+ function onValue(valueNode){currentParent.children.push(valueNode)
485
+ return valueNode
486
+ }
487
+ const visitor={onObjectBegin:(offset)=>{currentParent=onValue({type:"object",offset,length:-1,parent:currentParent,children:[]})
488
+ },onObjectProperty:(name,offset,length)=>{currentParent=onValue({type:"property",offset,length:-1,parent:currentParent,children:[]})
489
+ currentParent.children.push({type:"string",value:name,offset,length,parent:currentParent})
490
+ },onObjectEnd:(offset,length)=>{ensurePropertyComplete(offset + length)
491
+ currentParent.length=offset + length-currentParent.offset
492
+ currentParent=currentParent.parent
493
+ ensurePropertyComplete(offset + length)
494
+ },onArrayBegin:(offset,length)=>{currentParent=onValue({type:"array",offset,length:-1,parent:currentParent,children:[]})
495
+ },onArrayEnd:(offset,length)=>{currentParent.length=offset + length-currentParent.offset
496
+ currentParent=currentParent.parent
497
+ ensurePropertyComplete(offset + length)
498
+ },onLiteralValue:(value,offset,length)=>{onValue({type:getNodeType(value),offset,length,parent:currentParent,value})
499
+ ensurePropertyComplete(offset + length)
500
+ },onSeparator:(sep,offset,length)=>{if(currentParent.type==="property"){if(sep===":"){currentParent.colonOffset=offset
501
+ } else if(sep===","){ensurePropertyComplete(offset)
502
+ }}},onError:(error,offset,length)=>{errors.push({error,offset,length})
503
+ }}
504
+ visit(text,visitor,options)
505
+ const result=currentParent.children[0]
506
+ if(result){delete result.parent
507
+ }
508
+ return result
509
+ }
510
+ function findNodeAtLocation(root,path){if(!root){return
511
+ }
512
+ let node=root
513
+ for(let segment of path){if(typeof segment==="string"){if(node.type!=="object"||!Array.isArray(node.children)){return
514
+ }
515
+ let found=false
516
+ for(const propertyNode of node.children){if(Array.isArray(propertyNode.children)&&propertyNode.children[0].value===segment&&propertyNode.children.length===2){node=propertyNode.children[1]
517
+ found=true
518
+ break
519
+ }}
520
+ if(!found){return
521
+ }} else{const index=segment
522
+ if(node.type!=="array"||index<0||!Array.isArray(node.children)||index>=node.children.length){return
523
+ }
524
+ node=node.children[index]
525
+ }}
526
+ return node
527
+ }
528
+ function visit(text,visitor,options=ParseOptions.DEFAULT){const _scanner=createScanner(text,false)
529
+ const _jsonPath=[]
530
+ let suppressedCallbacks=0
531
+ function toNoArgVisit(visitFunction){return visitFunction?()=>suppressedCallbacks===0&&visitFunction(_scanner.getTokenOffset(),_scanner.getTokenLength(),_scanner.getTokenStartLine(),_scanner.getTokenStartCharacter()):()=>true
532
+ }
533
+ function toOneArgVisit(visitFunction){return visitFunction?(arg)=>suppressedCallbacks===0&&visitFunction(arg,_scanner.getTokenOffset(),_scanner.getTokenLength(),_scanner.getTokenStartLine(),_scanner.getTokenStartCharacter()):()=>true
534
+ }
535
+ function toOneArgVisitWithPath(visitFunction){return visitFunction?(arg)=>suppressedCallbacks===0&&visitFunction(arg,_scanner.getTokenOffset(),_scanner.getTokenLength(),_scanner.getTokenStartLine(),_scanner.getTokenStartCharacter(),()=>_jsonPath.slice()):()=>true
536
+ }
537
+ function toBeginVisit(visitFunction){return visitFunction?()=>{if(suppressedCallbacks>0){suppressedCallbacks++
538
+ } else{let cbReturn=visitFunction(_scanner.getTokenOffset(),_scanner.getTokenLength(),_scanner.getTokenStartLine(),_scanner.getTokenStartCharacter(),()=>_jsonPath.slice())
539
+ if(cbReturn===false){suppressedCallbacks=1
540
+ }}}:()=>true
541
+ }
542
+ function toEndVisit(visitFunction){return visitFunction?()=>{if(suppressedCallbacks>0){suppressedCallbacks--
543
+ }
544
+ if(suppressedCallbacks===0){visitFunction(_scanner.getTokenOffset(),_scanner.getTokenLength(),_scanner.getTokenStartLine(),_scanner.getTokenStartCharacter())
545
+ }}:()=>true
546
+ }
547
+ const onObjectBegin=toBeginVisit(visitor.onObjectBegin),onObjectProperty=toOneArgVisitWithPath(visitor.onObjectProperty),onObjectEnd=toEndVisit(visitor.onObjectEnd),onArrayBegin=toBeginVisit(visitor.onArrayBegin),onArrayEnd=toEndVisit(visitor.onArrayEnd),onLiteralValue=toOneArgVisitWithPath(visitor.onLiteralValue),onSeparator=toOneArgVisit(visitor.onSeparator),onComment=toNoArgVisit(visitor.onComment),onError=toOneArgVisit(visitor.onError)
548
+ const disallowComments=options&&options.disallowComments
549
+ const allowTrailingComma=options&&options.allowTrailingComma
550
+ function scanNext(){while(true){const token=_scanner.scan()
551
+ switch(_scanner.getTokenError()){case 4:handleError(14)
552
+ break
553
+ case 5:handleError(15)
554
+ break
555
+ case 3:handleError(13)
556
+ break
557
+ case 1:if(!disallowComments){handleError(11)
558
+ }
559
+ break
560
+ case 2:handleError(12)
561
+ break
562
+ case 6:handleError(16)
563
+ break
564
+ }
565
+ switch(token){case 12:case 13:if(disallowComments){handleError(10)
566
+ } else{onComment()
567
+ }
568
+ break
569
+ case 16:handleError(1)
570
+ break
571
+ case 15:case 14:break
572
+ default:return token
573
+ }}}
574
+ function handleError(error,skipUntilAfter=[],skipUntil=[]){onError(error)
575
+ if(skipUntilAfter.length + skipUntil.length>0){let token=_scanner.getToken()
576
+ while(token!==17){if(skipUntilAfter.indexOf(token)!==-1){scanNext()
577
+ break
578
+ } else if(skipUntil.indexOf(token)!==-1){break
579
+ }
580
+ token=scanNext()
581
+ }}}
582
+ function parseString(isValue){const value=_scanner.getTokenValue()
583
+ if(isValue){onLiteralValue(value)
584
+ } else{onObjectProperty(value)
585
+ _jsonPath.push(value)
586
+ }
587
+ scanNext()
588
+ return true
589
+ }
590
+ function parseLiteral(){switch(_scanner.getToken()){case 11:const tokenValue=_scanner.getTokenValue()
591
+ let value=Number(tokenValue)
592
+ if(isNaN(value)){handleError(2)
593
+ value=0
594
+ }
595
+ onLiteralValue(value)
596
+ break
597
+ case 7:onLiteralValue(null)
598
+ break
599
+ case 8:onLiteralValue(true)
600
+ break
601
+ case 9:onLiteralValue(false)
602
+ break
603
+ default:return false
604
+ }
605
+ scanNext()
606
+ return true
607
+ }
608
+ function parseProperty(){if(_scanner.getToken()!==10){handleError(3,[],[2,5])
609
+ return false
610
+ }
611
+ parseString(false)
612
+ if(_scanner.getToken()===6){onSeparator(":")
613
+ scanNext()
614
+ if(!parseValue()){handleError(4,[],[2,5])
615
+ }} else{handleError(5,[],[2,5])
616
+ }
617
+ _jsonPath.pop()
618
+ return true
619
+ }
620
+ function parseObject(){onObjectBegin()
621
+ scanNext()
622
+ let needsComma=false
623
+ while(_scanner.getToken()!==2&&_scanner.getToken()!==17){if(_scanner.getToken()===5){if(!needsComma){handleError(4,[],[])
624
+ }
625
+ onSeparator(",")
626
+ scanNext()
627
+ if(_scanner.getToken()===2&&allowTrailingComma){break
628
+ }} else if(needsComma){handleError(6,[],[])
629
+ }
630
+ if(!parseProperty()){handleError(4,[],[2,5])
631
+ }
632
+ needsComma=true
633
+ }
634
+ onObjectEnd()
635
+ if(_scanner.getToken()!==2){handleError(7,[2],[])
636
+ } else{scanNext()
637
+ }
638
+ return true
639
+ }
640
+ function parseArray(){onArrayBegin()
641
+ scanNext()
642
+ let isFirstElement=true
643
+ let needsComma=false
644
+ while(_scanner.getToken()!==4&&_scanner.getToken()!==17){if(_scanner.getToken()===5){if(!needsComma){handleError(4,[],[])
645
+ }
646
+ onSeparator(",")
647
+ scanNext()
648
+ if(_scanner.getToken()===4&&allowTrailingComma){break
649
+ }} else if(needsComma){handleError(6,[],[])
650
+ }
651
+ if(isFirstElement){_jsonPath.push(0)
652
+ isFirstElement=false
653
+ } else{_jsonPath[_jsonPath.length-1]++
654
+ }
655
+ if(!parseValue()){handleError(4,[],[4,5])
656
+ }
657
+ needsComma=true
658
+ }
659
+ onArrayEnd()
660
+ if(!isFirstElement){_jsonPath.pop()
661
+ }
662
+ if(_scanner.getToken()!==4){handleError(8,[4],[])
663
+ } else{scanNext()
664
+ }
665
+ return true
666
+ }
667
+ function parseValue(){switch(_scanner.getToken()){case 3:return parseArray()
668
+ case 1:return parseObject()
669
+ case 10:return parseString(true)
670
+ default:return parseLiteral()
671
+ }}
672
+ scanNext()
673
+ if(_scanner.getToken()===17){if(options.allowEmptyContent){return true
674
+ }
675
+ handleError(4,[],[])
676
+ return false
677
+ }
678
+ if(!parseValue()){handleError(4,[],[])
679
+ return false
680
+ }
681
+ if(_scanner.getToken()!==17){handleError(9,[],[])
682
+ }
683
+ return true
684
+ }
685
+ function getNodeType(value){switch(typeof value){case "boolean":return "boolean"
686
+ case "number":return "number"
687
+ case "string":return "string"
688
+ case "object":{if(!value){return "null"
689
+ } else if(Array.isArray(value)){return "array"
690
+ }
691
+ return "object"
692
+ }
693
+ default:return "null"
694
+ }}
695
+ function setProperty(text,originalPath,value,options){const path=originalPath.slice()
696
+ const errors=[]
697
+ const root=parseTree(text,errors)
698
+ let parent=undefined
699
+ let lastSegment=undefined
700
+ while(path.length>0){lastSegment=path.pop()
701
+ parent=findNodeAtLocation(root,path)
702
+ if(parent===undefined&&value!==undefined){if(typeof lastSegment==="string"){value={[lastSegment]:value}} else{value=[value]
703
+ }} else{break
704
+ }}
705
+ if(!parent){if(value===undefined){throw new Error("Can not delete in empty document")
706
+ }
707
+ return withFormatting(text,{offset:root?root.offset:0,length:root?root.length:0,content:JSON.stringify(value)},options)
708
+ } else if(parent.type==="object"&&typeof lastSegment==="string"&&Array.isArray(parent.children)){const existing=findNodeAtLocation(parent,[lastSegment])
709
+ if(existing!==undefined){if(value===undefined){if(!existing.parent){throw new Error("Malformed AST")
710
+ }
711
+ const propertyIndex=parent.children.indexOf(existing.parent)
712
+ let removeBegin
713
+ let removeEnd=existing.parent.offset + existing.parent.length
714
+ if(propertyIndex>0){let previous=parent.children[propertyIndex-1]
715
+ removeBegin=previous.offset + previous.length
716
+ } else{removeBegin=parent.offset + 1
717
+ if(parent.children.length>1){let next=parent.children[1]
718
+ removeEnd=next.offset
719
+ }}
720
+ return withFormatting(text,{offset:removeBegin,length:removeEnd-removeBegin,content:""},options)
721
+ } else{return withFormatting(text,{offset:existing.offset,length:existing.length,content:JSON.stringify(value)},options)
722
+ }} else{if(value===undefined){return []
723
+ }
724
+ const newProperty=`${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`
725
+ const index=options.getInsertionIndex?options.getInsertionIndex(parent.children.map((p)=>p.children[0].value)):parent.children.length
726
+ let edit
727
+ if(index>0){let previous=parent.children[index-1]
728
+ edit={offset:previous.offset + previous.length,length:0,content:"," + newProperty}} else if(parent.children.length===0){edit={offset:parent.offset + 1,length:0,content:newProperty}} else{edit={offset:parent.offset + 1,length:0,content:newProperty + ","}}
729
+ return withFormatting(text,edit,options)
730
+ }} else if(parent.type==="array"&&typeof lastSegment==="number"&&Array.isArray(parent.children)){const insertIndex=lastSegment
731
+ if(insertIndex===-1){const newProperty=`${JSON.stringify(value)}`
732
+ let edit
733
+ if(parent.children.length===0){edit={offset:parent.offset + 1,length:0,content:newProperty}} else{const previous=parent.children[parent.children.length-1]
734
+ edit={offset:previous.offset + previous.length,length:0,content:"," + newProperty}}
735
+ return withFormatting(text,edit,options)
736
+ } else if(value===undefined&&parent.children.length>=0){const removalIndex=lastSegment
737
+ const toRemove=parent.children[removalIndex]
738
+ let edit
739
+ if(parent.children.length===1){edit={offset:parent.offset + 1,length:parent.length-2,content:""}} else if(parent.children.length-1===removalIndex){let previous=parent.children[removalIndex-1]
740
+ let offset=previous.offset + previous.length
741
+ let parentEndOffset=parent.offset + parent.length
742
+ edit={offset,length:parentEndOffset-2-offset,content:""}} else{edit={offset:toRemove.offset,length:parent.children[removalIndex + 1].offset-toRemove.offset,content:""}}
743
+ return withFormatting(text,edit,options)
744
+ } else if(value!==undefined){let edit
745
+ const newProperty=`${JSON.stringify(value)}`
746
+ if(!options.isArrayInsertion&&parent.children.length>lastSegment){const toModify=parent.children[lastSegment]
747
+ edit={offset:toModify.offset,length:toModify.length,content:newProperty}} else if(parent.children.length===0||lastSegment===0){edit={offset:parent.offset + 1,length:0,content:parent.children.length===0?newProperty:newProperty + ","}} else{const index=lastSegment>parent.children.length?parent.children.length:lastSegment
748
+ const previous=parent.children[index-1]
749
+ edit={offset:previous.offset + previous.length,length:0,content:"," + newProperty}}
750
+ return withFormatting(text,edit,options)
751
+ } else{throw new Error(`Can not ${value === undefined ? "remove" : options.isArrayInsertion ? "insert" : "modify"} Array index ${insertIndex} as length is not sufficient`)
752
+ }} else{throw new Error(`Can not add ${typeof lastSegment !== "number" ? "index" : "property"} to parent of type ${parent.type}`)
753
+ }}
754
+ function withFormatting(text,edit,options){if(!options.formattingOptions){return [edit]
755
+ }
756
+ let newText=applyEdit(text,edit)
757
+ let begin=edit.offset
758
+ let end=edit.offset + edit.content.length
759
+ if(edit.length===0||edit.content.length===0){while(begin>0&&!isEOL(newText,begin-1)){begin--
760
+ }
761
+ while(end<newText.length&&!isEOL(newText,end)){end++
762
+ }}
763
+ const edits=format(newText,{offset:begin,length:end-begin},{...options.formattingOptions,keepLines:false})
764
+ for(let i=edits.length-1;i>=0; i--){const edit=edits[i]
765
+ newText=applyEdit(newText,edit)
766
+ begin=Math.min(begin,edit.offset)
767
+ end=Math.max(end,edit.offset + edit.length)
768
+ end += edit.content.length-edit.length
769
+ }
770
+ const editLength=text.length-(newText.length-end)-begin
771
+ return [{offset:begin,length:editLength,content:newText.substring(begin,end)}]
772
+ }
773
+ function applyEdit(text,edit){return text.substring(0,edit.offset) + edit.content + text.substring(edit.offset + edit.length)
774
+ }
775
+ var ScanError;
776
+ (function(ScanError){ScanError[ScanError["None"]=0]="None"
777
+ ScanError[ScanError["UnexpectedEndOfComment"]=1]="UnexpectedEndOfComment"
778
+ ScanError[ScanError["UnexpectedEndOfString"]=2]="UnexpectedEndOfString"
779
+ ScanError[ScanError["UnexpectedEndOfNumber"]=3]="UnexpectedEndOfNumber"
780
+ ScanError[ScanError["InvalidUnicode"]=4]="InvalidUnicode"
781
+ ScanError[ScanError["InvalidEscapeCharacter"]=5]="InvalidEscapeCharacter"
782
+ ScanError[ScanError["InvalidCharacter"]=6]="InvalidCharacter"
783
+ })(ScanError||(ScanError={}))
784
+ var SyntaxKind;
785
+ (function(SyntaxKind){SyntaxKind[SyntaxKind["OpenBraceToken"]=1]="OpenBraceToken"
786
+ SyntaxKind[SyntaxKind["CloseBraceToken"]=2]="CloseBraceToken"
787
+ SyntaxKind[SyntaxKind["OpenBracketToken"]=3]="OpenBracketToken"
788
+ SyntaxKind[SyntaxKind["CloseBracketToken"]=4]="CloseBracketToken"
789
+ SyntaxKind[SyntaxKind["CommaToken"]=5]="CommaToken"
790
+ SyntaxKind[SyntaxKind["ColonToken"]=6]="ColonToken"
791
+ SyntaxKind[SyntaxKind["NullKeyword"]=7]="NullKeyword"
792
+ SyntaxKind[SyntaxKind["TrueKeyword"]=8]="TrueKeyword"
793
+ SyntaxKind[SyntaxKind["FalseKeyword"]=9]="FalseKeyword"
794
+ SyntaxKind[SyntaxKind["StringLiteral"]=10]="StringLiteral"
795
+ SyntaxKind[SyntaxKind["NumericLiteral"]=11]="NumericLiteral"
796
+ SyntaxKind[SyntaxKind["LineCommentTrivia"]=12]="LineCommentTrivia"
797
+ SyntaxKind[SyntaxKind["BlockCommentTrivia"]=13]="BlockCommentTrivia"
798
+ SyntaxKind[SyntaxKind["LineBreakTrivia"]=14]="LineBreakTrivia"
799
+ SyntaxKind[SyntaxKind["Trivia"]=15]="Trivia"
800
+ SyntaxKind[SyntaxKind["Unknown"]=16]="Unknown"
801
+ SyntaxKind[SyntaxKind["EOF"]=17]="EOF"
802
+ })(SyntaxKind||(SyntaxKind={}))
803
+ var parseTree2=parseTree
804
+ var findNodeAtLocation2=findNodeAtLocation
805
+ var ParseErrorCode;
806
+ (function(ParseErrorCode){ParseErrorCode[ParseErrorCode["InvalidSymbol"]=1]="InvalidSymbol"
807
+ ParseErrorCode[ParseErrorCode["InvalidNumberFormat"]=2]="InvalidNumberFormat"
808
+ ParseErrorCode[ParseErrorCode["PropertyNameExpected"]=3]="PropertyNameExpected"
809
+ ParseErrorCode[ParseErrorCode["ValueExpected"]=4]="ValueExpected"
810
+ ParseErrorCode[ParseErrorCode["ColonExpected"]=5]="ColonExpected"
811
+ ParseErrorCode[ParseErrorCode["CommaExpected"]=6]="CommaExpected"
812
+ ParseErrorCode[ParseErrorCode["CloseBraceExpected"]=7]="CloseBraceExpected"
813
+ ParseErrorCode[ParseErrorCode["CloseBracketExpected"]=8]="CloseBracketExpected"
814
+ ParseErrorCode[ParseErrorCode["EndOfFileExpected"]=9]="EndOfFileExpected"
815
+ ParseErrorCode[ParseErrorCode["InvalidCommentToken"]=10]="InvalidCommentToken"
816
+ ParseErrorCode[ParseErrorCode["UnexpectedEndOfComment"]=11]="UnexpectedEndOfComment"
817
+ ParseErrorCode[ParseErrorCode["UnexpectedEndOfString"]=12]="UnexpectedEndOfString"
818
+ ParseErrorCode[ParseErrorCode["UnexpectedEndOfNumber"]=13]="UnexpectedEndOfNumber"
819
+ ParseErrorCode[ParseErrorCode["InvalidUnicode"]=14]="InvalidUnicode"
820
+ ParseErrorCode[ParseErrorCode["InvalidEscapeCharacter"]=15]="InvalidEscapeCharacter"
821
+ ParseErrorCode[ParseErrorCode["InvalidCharacter"]=16]="InvalidCharacter"
822
+ })(ParseErrorCode||(ParseErrorCode={}))
823
+ function modify(text,path,value,options){return setProperty(text,path,value,options)
824
+ }
825
+ function applyEdits(text,edits){let sortedEdits=edits.slice(0).sort((a,b)=>{const diff=a.offset-b.offset
826
+ if(diff===0){return a.length-b.length
827
+ }
828
+ return diff
829
+ })
830
+ let lastModifiedOffset=text.length
831
+ for(let i=sortedEdits.length-1;i>=0; i--){let e=sortedEdits[i]
832
+ if(e.offset + e.length<=lastModifiedOffset){text=applyEdit(text,e)
833
+ } else{throw new Error("Overlapping edit")
834
+ }
835
+ lastModifiedOffset=e.offset
836
+ }
837
+ return text
838
+ }
839
+ function unique(node,key){const matches=node.children?.filter((property)=>property.children?.[0].value===key)??[]
840
+ if(matches.length>1)
841
+ throw new Error(`Duplicate ${key} fields; edit this configuration manually.`)
842
+ }
843
+ function enableTodoConfig(source){if(source.length>1e6)
844
+ throw new Error("The configuration is too large to edit safely.")
845
+ const prefix=source.startsWith("\uFEFF")?"\uFEFF":""
846
+ const text=source.slice(prefix.length)
847
+ const errors=[]
848
+ const root=parseTree2(text,errors,{allowTrailingComma:true})
849
+ if(errors.length>0||root?.type!=="object")
850
+ throw new Error("The configuration is not a valid JSON/JSONC object.")
851
+ unique(root,"experimental")
852
+ const experimental=findNodeAtLocation2(root,["experimental"])
853
+ if(experimental&&experimental.type!=="object")
854
+ throw new Error("experimental must be an object.")
855
+ if(experimental)
856
+ unique(experimental,"todo")
857
+ const todo=findNodeAtLocation2(root,["experimental","todo"])
858
+ if(todo&&todo.type!=="boolean")
859
+ throw new Error("experimental.todo must be a boolean.")
860
+ const edits=modify(text,["experimental","todo"],true,{formattingOptions:{insertSpaces:!/^\t/mu.test(source),tabSize:2,eol:source.includes(`\r
861
+ `)?`\r
862
+ `:`
863
+ `
864
+ }})
865
+ return prefix + applyEdits(text,edits)
866
+ }
867
+ function createTodoSetupController(input){const [states,setStates]=createSignal({})
868
+ const [files,setFiles]=createSignal({})
869
+ const revisions=new Map
870
+ const writes=new Set
871
+ let active
872
+ const state=(sessionID)=>states()[input.target(sessionID).key]??{status:"idle"}
873
+ const set=(key,value)=>setStates((previous)=>({...previous,[key]:value}))
874
+ const signal=()=>AbortSignal.any([input.signal,AbortSignal.timeout(1e4)])
875
+ const current=(preview)=>!input.signal.aborted&&input.route()===preview.route&&input.target(preview.target.sessionID).key===preview.target.key
876
+ const requireCurrent=(preview)=>{if(!current(preview))
877
+ throw new Error("Session or workspace changed; reopen Todo setup.")
878
+ }
879
+ async function refresh(sessionID){const target=input.target(sessionID)
880
+ const revision=(revisions.get(target.key)??0) + 1
881
+ active=target
882
+ revisions.set(target.key,revision)
883
+ set(target.key,{...state(sessionID),status:"loading",error:undefined})
884
+ try{const config=todoConfig(await input.source.entries(target,signal()))
885
+ if(input.signal.aborted||revisions.get(target.key)!==revision)
886
+ return
887
+ setFiles((previous)=>({...previous,[target.key]:config.files}))
888
+ set(target.key,{status:"ready",enabled:config.enabled,error:config.unavailable})
889
+ } catch{if(!input.signal.aborted&&revisions.get(target.key)===revision)
890
+ set(target.key,{status:"error",error:"Could not read OpenCode Todo configuration. Retry."})
891
+ }}
892
+ const unsubscribe=input.source.subscribe((directory)=>{if(active&&(!directory||directory===active.routing.directory))
893
+ refresh(active.sessionID)
894
+ })
895
+ input.signal.addEventListener("abort",unsubscribe,{once:true})
896
+ async function prepare(sessionID,path){const target=input.target(sessionID)
897
+ const route=input.route()
898
+ const config=todoConfig(await input.source.entries(target,signal()))
899
+ requireCurrent({target,route})
900
+ if(config.enabled)
901
+ throw new Error("Native Todo is already enabled. Refresh the section.")
902
+ if(!config.files.includes(path))
903
+ throw new Error("The configuration source changed; choose its current file.")
904
+ const original=await input.source.read(target,path,signal())
905
+ requireCurrent({target,route})
906
+ return{target,route,path,original,updated:enableTodoConfig(original),sources:config.signature}}
907
+ async function apply(preview){requireCurrent(preview)
908
+ if(writes.has(preview.path))
909
+ throw new Error("This configuration is already being saved.")
910
+ writes.add(preview.path)
911
+ set(preview.target.key,{status:"saving",enabled:false})
912
+ try{const config=todoConfig(await input.source.entries(preview.target,signal()))
913
+ if(config.signature!==preview.sources||!config.files.includes(preview.path))
914
+ throw new Error("Configuration sources changed; reopen the preview.")
915
+ const original=await input.source.read(preview.target,preview.path,signal())
916
+ requireCurrent(preview)
917
+ if(original!==preview.original)
918
+ throw new Error("The configuration file changed; reopen the preview.")
919
+ await input.source.write(preview.target,preview.path,preview.updated,signal())
920
+ const saved=await input.source.read(preview.target,preview.path,signal())
921
+ if(saved!==preview.updated)
922
+ throw new Error("The file changed while saving. Review it before trying again.")
923
+ for(let attempt=0;attempt<6; attempt++){await new Promise((resolve)=>setTimeout(resolve,150))
924
+ const effective=todoConfig(await input.source.entries(preview.target,signal()))
925
+ if(effective.enabled){set(preview.target.key,{status:"ready",enabled:true})
926
+ return
927
+ }}
928
+ throw new Error("Saved experimental.todo=true, but the host has not enabled it. Refresh or restart OpenCode.")
929
+ } catch(error){set(preview.target.key,{status:"error",error:error instanceof Error?error.message:"Could not enable Todo. Refresh to check the current configuration before retrying."
930
+ })
931
+ throw error
932
+ } finally{writes.delete(preview.path)
933
+ }}
934
+ return{state,files:(sessionID)=>files()[input.target(sessionID).key]??[],refresh,prepare,apply,current
935
+ }}
936
+ import {insert as _$insert3} from "@opentui/solid"
937
+ import {memo as _$memo2} from "@opentui/solid"
938
+ import {createElement as _$createElement3} from "@opentui/solid"
939
+ import {createComponent as _$createComponent3} from "@opentui/solid"
940
+ import {Show,createSignal as createSignal3,onCleanup as onCleanup3,onMount} from "solid-js"
941
+ import {SelectionMenu,useDialogs as useDialogs3} from "./tui.js"
942
+ import {memo as _$memo} from "@opentui/solid"
943
+ import {effect as _$effect} from "@opentui/solid"
944
+ import {createTextNode as _$createTextNode} from "@opentui/solid"
945
+ import {insertNode as _$insertNode} from "@opentui/solid"
946
+ import {setProp as _$setProp} from "@opentui/solid"
947
+ import {use as _$use} from "@opentui/solid"
948
+ import {insert as _$insert} from "@opentui/solid"
949
+ import {createComponent as _$createComponent} from "@opentui/solid"
950
+ import {createElement as _$createElement} from "@opentui/solid"
951
+ import {useTerminalDimensions} from "@opentui/solid"
952
+ import {createSignal as createSignal2,onCleanup} from "solid-js"
953
+ import {DialogAction,DialogHeader,DialogSurface,GuardedConfirmation,useDialogs} from "./tui.js"
954
+ function EnableTodoConfirmation(props){const dialogs=useDialogs(props.api)
955
+ const dimensions=useTerminalDimensions()
956
+ let body
957
+ const [busy,setBusy]=createSignal2(false)
958
+ const [error,setError]=createSignal2("")
959
+ const [selected,setSelected]=createSignal2(false)
960
+ let disposed=false
961
+ const confirm=async ()=>{if(busy()||error())
962
+ return
963
+ setBusy(true)
964
+ try{await props.model.apply(props.preview)
965
+ if(!disposed&&props.model.current(props.preview)){dialogs.close()
966
+ props.api.ui.toast({variant:"success",title:"Native Todo enabled",message:"Use chat and todowrite to manage tasks."
967
+ })
968
+ }} catch(error_){if(!disposed)
969
+ setError(error_ instanceof Error?error_.message:"Could not enable Todo. Go back and refresh before retrying.")
970
+ } finally{if(!disposed)
971
+ setBusy(false)
972
+ }}
973
+ const unregister=props.api.keymap.registerLayer({mode:"modal",priority:1100,commands:[{name:"opencode-navigator.todo.enable.switch",run:()=>setSelected(!selected())
974
+ },{name:"opencode-navigator.todo.enable.confirm",run:()=>selected()?void confirm():dialogs.back()
975
+ },{name:"opencode-navigator.todo.enable.page-up",run:()=>body?.scrollBy(-5)
976
+ },{name:"opencode-navigator.todo.enable.page-down",run:()=>body?.scrollBy(5)
977
+ }],bindings:[{key:"left",cmd:"opencode-navigator.todo.enable.switch"
978
+ },{key:"right",cmd:"opencode-navigator.todo.enable.switch"
979
+ },{key:"return",cmd:"opencode-navigator.todo.enable.confirm"
980
+ },{key:"tab",cmd:"opencode-navigator.todo.enable.switch"
981
+ },{key:"pageup",cmd:"opencode-navigator.todo.enable.page-up"
982
+ },{key:"pagedown",cmd:"opencode-navigator.todo.enable.page-down"
983
+ }]
984
+ })
985
+ onCleanup(()=>{disposed=true
986
+ unregister()
987
+ })
988
+ return(()=>{var _el$=_$createElement("box")
989
+ _$insert(_el$,_$createComponent(GuardedConfirmation,{get api(){return props.api
990
+ },title:"Enable native Todo",message:"Set experimental.todo to true",current:()=>props.model.current(props.preview),onConfirm:()=>void confirm(),render:()=>_$createComponent(DialogSurface,{get api(){return props.api
991
+ },lift:true,get children(){return [_$createComponent(DialogHeader,{get api(){return props.api
992
+ },title:"Enable native Todo",icon:"todo",get onBack(){return dialogs.back
993
+ }}),(()=>{var _el$2=_$createElement("scrollbox"),_el$3=_$createElement("box"),_el$4=_$createElement("text"),_el$6=_$createElement("text"),_el$7=_$createElement("text"),_el$9=_$createElement("text"),_el$1=_$createElement("text")
994
+ _$insertNode(_el$2,_el$3)
995
+ _$use((node)=>{body=node
996
+ },_el$2)
997
+ _$setProp(_el$2,"flexShrink",0)
998
+ _$setProp(_el$2,"scrollX",false)
999
+ _$setProp(_el$2,"horizontalScrollbarOptions",{visible:false
1000
+ })
1001
+ _$insertNode(_el$3,_el$4)
1002
+ _$insertNode(_el$3,_el$6)
1003
+ _$insertNode(_el$3,_el$7)
1004
+ _$insertNode(_el$3,_el$9)
1005
+ _$insertNode(_el$3,_el$1)
1006
+ _$setProp(_el$3,"gap",1)
1007
+ _$insertNode(_el$4,_$createTextNode(`OpenCode server configuration`))
1008
+ _$setProp(_el$4,"wrapMode","word")
1009
+ _$setProp(_el$6,"wrapMode","word")
1010
+ _$insert(_el$6,()=>props.preview.path)
1011
+ _$insertNode(_el$7,_$createTextNode(`experimental.todo \u2192 true`))
1012
+ _$insertNode(_el$9,_$createTextNode(`Preserve other settings and JSONC comments. This enables the built-in tool; it does not invoke a model or edit tasks.`))
1013
+ _$setProp(_el$9,"wrapMode","word")
1014
+ _$setProp(_el$1,"wrapMode","word")
1015
+ _$insert(_el$1,error)
1016
+ _$effect((_p$)=>{var _v$=Math.min(10,Math.max(3,dimensions().height-10)),_v$2=props.api.theme.current.textMuted,_v$3=props.api.theme.current.text,_v$4=props.api.theme.current.accent,_v$5=props.api.theme.current.textMuted,_v$6=props.api.theme.current.error
1017
+ _v$!==_p$.e&&(_p$.e=_$setProp(_el$2,"height",_v$,_p$.e))
1018
+ _v$2!==_p$.t&&(_p$.t=_$setProp(_el$4,"fg",_v$2,_p$.t))
1019
+ _v$3!==_p$.a&&(_p$.a=_$setProp(_el$6,"fg",_v$3,_p$.a))
1020
+ _v$4!==_p$.o&&(_p$.o=_$setProp(_el$7,"fg",_v$4,_p$.o))
1021
+ _v$5!==_p$.i&&(_p$.i=_$setProp(_el$9,"fg",_v$5,_p$.i))
1022
+ _v$6!==_p$.n&&(_p$.n=_$setProp(_el$1,"fg",_v$6,_p$.n))
1023
+ return _p$
1024
+ },{e:undefined,t:undefined,a:undefined,o:undefined,i:undefined,n:undefined
1025
+ })
1026
+ return _el$2
1027
+ })(),(()=>{var _el$10=_$createElement("box")
1028
+ _$setProp(_el$10,"id","opencode-navigator.todo.enable.actions")
1029
+ _$setProp(_el$10,"flexDirection","row")
1030
+ _$setProp(_el$10,"gap",1)
1031
+ _$setProp(_el$10,"flexShrink",0)
1032
+ _$insert(_el$10,_$createComponent(DialogAction,{get api(){return props.api
1033
+ },id:"opencode-navigator.todo.enable.cancel",get label(){return error()?"Back and refresh":"Cancel"
1034
+ },icon:"close",get selected(){return !selected()
1035
+ },onSelect:()=>setSelected(false),get onActivate(){return dialogs.back
1036
+ }}),null)
1037
+ _$insert(_el$10,_$createComponent(DialogAction,{get api(){return props.api
1038
+ },id:"opencode-navigator.todo.enable.apply",get label(){return busy()?"Enabling\u2026":"Enable Todo"
1039
+ },icon:"add",get selected(){return selected()
1040
+ },onSelect:()=>setSelected(true),onActivate:()=>void confirm()
1041
+ }),null)
1042
+ return _el$10
1043
+ })()]
1044
+ }})
1045
+ }))
1046
+ return _el$
1047
+ })()
1048
+ }
1049
+ import {effect as _$effect2} from "@opentui/solid"
1050
+ import {insert as _$insert2} from "@opentui/solid"
1051
+ import {setProp as _$setProp2} from "@opentui/solid"
1052
+ import {createElement as _$createElement2} from "@opentui/solid"
1053
+ import {createComponent as _$createComponent2} from "@opentui/solid"
1054
+ import {onCleanup as onCleanup2} from "solid-js"
1055
+ import {DialogAction as DialogAction2,DialogHeader as DialogHeader2,DialogSurface as DialogSurface2,useDialogs as useDialogs2} from "./tui.js"
1056
+ function TodoSetupReadNotice(props){const dialogs=useDialogs2(props.api)
1057
+ const unregister=props.api.keymap.registerLayer({mode:"modal",priority:1100,commands:[{name:"opencode-navigator.todo.setup.retry",run:props.refresh
1058
+ }],bindings:[{key:"return",cmd:"opencode-navigator.todo.setup.retry"
1059
+ }]
1060
+ })
1061
+ onCleanup2(unregister)
1062
+ return _$createComponent2(DialogSurface2,{get api(){return props.api
1063
+ },lift:true,get children(){return [_$createComponent2(DialogHeader2,{get api(){return props.api
1064
+ },title:"Enable native Todo",icon:"todo",get onBack(){return dialogs.back
1065
+ }}),(()=>{var _el$=_$createElement2("text")
1066
+ _$setProp2(_el$,"wrapMode","word")
1067
+ _$insert2(_el$,()=>props.message)
1068
+ _$effect2((_$p)=>_$setProp2(_el$,"fg",props.api.theme.current.textMuted,_$p))
1069
+ return _el$
1070
+ })(),_$createComponent2(DialogAction2,{get api(){return props.api
1071
+ },id:"opencode-navigator.todo.setup.retry",label:"Refresh configuration",icon:"retry",selected:true,onSelect:()=>{},get onActivate(){return props.refresh
1072
+ }})]
1073
+ }})
1074
+ }
1075
+ function NativeTodoSetupDialog(props){const dialogs=useDialogs3(props.api)
1076
+ const [error,setError]=createSignal3("")
1077
+ const [preparing,setPreparing]=createSignal3(false)
1078
+ let disposed=false
1079
+ const state=()=>props.model.state(props.sessionID)
1080
+ const refresh=()=>void props.model.refresh(props.sessionID)
1081
+ onMount(refresh)
1082
+ onCleanup3(()=>{disposed=true
1083
+ })
1084
+ const select=async (path)=>{if(preparing())
1085
+ return
1086
+ setPreparing(true)
1087
+ setError("")
1088
+ try{const preview=await props.model.prepare(props.sessionID,path)
1089
+ if(!disposed&&props.model.current(preview))
1090
+ dialogs.open(()=>_$createComponent3(EnableTodoConfirmation,{get api(){return props.api
1091
+ },get model(){return props.model
1092
+ },preview
1093
+ }))
1094
+ } catch(error_){if(!disposed)
1095
+ setError(error_ instanceof Error?error_.message:"Could not prepare this configuration. Retry.")
1096
+ } finally{if(!disposed)
1097
+ setPreparing(false)
1098
+ }}
1099
+ return(()=>{var _el$=_$createElement3("box")
1100
+ _$insert3(_el$,_$createComponent3(Show,{get when(){return _$memo2(()=>!!(state().status==="ready"&&!error()&&!preparing()))()&&props.model.files(props.sessionID).length>0
1101
+ },get fallback(){return _$createComponent3(TodoSetupReadNotice,{get api(){return props.api
1102
+ },get message(){return _$memo2(()=>!!preparing())()?"Preparing configuration preview\u2026":error()||state().error||"Reading the current OpenCode configuration\u2026"
1103
+ },refresh:()=>{setError("")
1104
+ refresh()
1105
+ }})
1106
+ },get children(){return _$createComponent3(SelectionMenu,{get api(){return props.api
1107
+ },title:"Choose Todo configuration",adaptive:true,lift:true,get options(){return [...props.model.files(props.sessionID).map((path)=>({title:path,value:path,description:"Existing server file. Preview the change before enabling Todo.",icon:"settings"
1108
+ })),{title:"Cancel",value:"",description:"Keep the configuration unchanged",icon:"close"
1109
+ }]
1110
+ },onSelect:(option)=>option.value?void select(option.value):dialogs.back()
1111
+ })
1112
+ }}))
1113
+ return _el$
1114
+ })()
1115
+ }
1116
+ import {createDialogStack} from "./tui.js"
1117
+ import {posix,win32} from "path"
1118
+ var location=(directory)=>({directory})
1119
+ function configFile(path){const paths=/^[a-z]:[\\/]|^\\\\/iu.test(path)?win32:posix
1120
+ if(!paths.isAbsolute(path))
1121
+ throw new Error("OpenCode returned a non-absolute configuration path.")
1122
+ return{location:location(paths.dirname(path)),path:paths.basename(path)}}
1123
+ function createTodoSetupSource(context){return{async entries(target,signal){const entries=await context.client.config.get({location:location(target.routing.directory)},{signal})
1124
+ return entries.flatMap((entry)=>entry.type==="document"?[{path:entry.path,experimental:entry.info.experimental===undefined?undefined:{todo:entry.info.experimental.todo}}]:[])
1125
+ },async read(_target,path,signal){const bytes=await context.client.file.read(configFile(path),{signal})
1126
+ return new TextDecoder("utf-8",{fatal:true,ignoreBOM:true}).decode(bytes)
1127
+ },async write(_target,path,text,signal){await context.client.experimental.file.write({...configFile(path),payload:new TextEncoder().encode(text)},{signal})
1128
+ },subscribe(refresh){const changed=context.data.on("config.updated",(event)=>refresh(event.location?.directory))
1129
+ const connected=context.data.on("server.connected",()=>refresh())
1130
+ return()=>{changed()
1131
+ connected()
1132
+ }}}}
1133
+ function createOpenCodeV2TodoSetup(context,api,preferences,target){const model=createTodoSetupController({source:createTodoSetupSource(context),target,route:()=>JSON.stringify(api.route.current),signal:api.lifecycle.signal
1134
+ })
1135
+ const setup={state:model.state,refresh:model.refresh,configure(sessionID){const current={target:target(sessionID),route:JSON.stringify(api.route.current)
1136
+ }
1137
+ createDialogStack(api,preferences.lspIconStyle,()=>model.current(current),preferences.cornerFont).open(()=>_$createComponent4(NativeTodoSetupDialog,{api,sessionID,model
1138
+ }))
1139
+ }}
1140
+ const sessionID=()=>{const route=api.route.current
1141
+ if(route.name!=="session")
1142
+ return
1143
+ const id=route.params?.sessionID
1144
+ return typeof id==="string"?id:undefined
1145
+ }
1146
+ context.keymap.layer(()=>({mode:"global",commands:[{id:"opencode-navigator.todo.enable",title:"Enable native Todo",group:"Navigator",palette:true,enabled:()=>{const id=sessionID()
1147
+ return Boolean(id&&model.state(id).enabled!==true)
1148
+ },run:()=>{const id=sessionID()
1149
+ if(id)
1150
+ setup.configure(id)
1151
+ }}]
1152
+ }))
1153
+ return setup
1154
+ }
1155
+ export{NativeTodoSetupDialog,createOpenCodeV2TodoSetup,createTodoSetupController
1156
+ }