d23464c0 Andy McCall 1 month ago ↶
1
2
( function ( ) {
3
" use strict" ;
4
5
var p = location . pathname , best = null ;
6
document . querySelectorAll ( " .band a" ) . forEach ( function ( a ) {
7
var h = a . getAttribute ( " href" ) ;
8
if ( h !== " /" && ( p === h || p . indexOf ( h + " /" ) === 0 ) && ( ! best || h . length > best . getAttribute ( " href" ) . length ) ) best = a ;
9
} ) ;
10
if ( best ) best . classList . add ( " on" ) ;
11
16ee5d19 Andy McCall 18 days ago ↶
12
13
14
15
var menus = document . querySelectorAll ( " [data-tab-menu]" ) ;
16
function closeMenus ( except ) {
17
menus . forEach ( function ( m ) { if ( m !== except ) m . open = false ; } ) ;
18
}
19
menus . forEach ( function ( m ) {
20
m . addEventListener ( " toggle" , function ( ) { if ( m . open ) closeMenus ( m ) ; } ) ;
21
} ) ;
22
if ( menus . length ) {
23
document . addEventListener ( " click" , function ( ev ) {
24
if ( ! ev . target . closest || ! ev . target . closest ( " [data-tab-menu]" ) ) closeMenus ( null ) ;
25
} ) ;
26
document . addEventListener ( " keydown" , function ( ev ) {
27
if ( ev . key !== " Escape" ) return ;
28
var open = document . querySelector ( " [data-tab-menu][open]" ) ;
29
if ( open ) { open . open = false ; open . querySelector ( " summary" ) . focus ( ) ; }
30
} ) ;
31
}
32
14530604 Andy McCall 1 month ago ↶
33
34
35
function load ( src , css ) {
36
return new Promise ( function ( ok ) {
37
if ( css ) { var l = document . createElement ( " link" ) ; l . rel = " stylesheet" ; l . href = css ; document . head . appendChild ( l ) ; }
38
var s = document . createElement ( " script" ) ; s . src = src ; s . onload = ok ; document . head . appendChild ( s ) ;
39
} ) ;
40
}
41
if ( document . querySelector ( " textarea.code" ) ) load ( " /static/vendor/editor.js" ) ;
42
var mds = document . querySelectorAll ( " textarea.md" ) ;
ffb67a81 Andy McCall 22 days ago
43
44
45
14530604 Andy McCall 1 month ago ↶
46
if ( mds . length ) load ( " /static/vendor/easymde.min.js" , " /static/vendor/easymde.min.css" ) . then ( function ( ) {
47
var E = window . EasyMDE ;
ffb67a81 Andy McCall 22 days ago
48
function svg ( d ) { return ' <svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">' + d + ' </svg>' ; }
49
var I = {
50
bold : svg ( ' <path d="M4.5 2.5h4.25a2.75 2.75 0 0 1 0 5.5H4.5zM4.5 8h5a2.75 2.75 0 0 1 0 5.5h-5z"/>' ) ,
51
italic : svg ( ' <path d="M6.5 2.5h6M3.5 13.5h6M10 2.5l-4 11"/>' ) ,
52
strike : svg ( ' <path d="M2.5 8h11M11 4.5c-.5-1.2-1.7-2-3.2-2-1.9 0-3.3 1-3.3 2.6 0 .9.4 1.5 1.2 2M5 11.5c.5 1.2 1.8 2 3.3 2 2 0 3.4-1.1 3.4-2.7"/>' ) ,
53
heading : svg ( ' <path d="M3.5 2.5v11M12.5 2.5v11M3.5 8h9"/>' ) ,
54
quote : svg ( ' <path d="M2.5 3.5h11M5.5 8h8M5.5 12.5h8M2.5 7v6"/>' ) ,
55
code : svg ( ' <path d="M5.5 4.5 2 8l3.5 3.5M10.5 4.5 14 8l-3.5 3.5"/>' ) ,
56
link : svg ( ' <path d="M7 9a3 3 0 0 0 4.2.3l2-2a3 3 0 0 0-4.2-4.2l-1 1M9 7a3 3 0 0 0-4.2-.3l-2 2a3 3 0 0 0 4.2 4.2l1-1"/>' ) ,
57
ul : svg ( ' <path d="M6 4h7.5M6 8h7.5M6 12h7.5"/><circle cx="2.75" cy="4" r=".75" fill="currentColor"/><circle cx="2.75" cy="8" r=".75" fill="currentColor"/><circle cx="2.75" cy="12" r=".75" fill="currentColor"/>' ) ,
58
ol : svg ( ' <path d="M6.5 4h7M6.5 8h7M6.5 12h7M2 2.5h1v3M2 7.5h1.5L2 9.5h1.5M2 10.5h1.5v3H2M2 12h1.5"/>' ) ,
59
task : svg ( ' <rect x="2" y="2.5" width="4" height="4" rx=".75"/><path d="m2.75 11 1 1 1.75-2M8.5 4.5h5M8.5 11.5h5"/>' ) ,
60
table : svg ( ' <rect x="2" y="2.5" width="12" height="11" rx="1"/><path d="M2 6.5h12M2 10h12M6.5 6.5v7"/>' ) ,
61
full : svg ( ' <path d="M2.5 6V2.5H6M10 2.5h3.5V6M13.5 10v3.5H10M6 13.5H2.5V10"/>' )
62
} ;
63
function b ( name , action , title , icon , text ) { return { name : name , action : action , title : title , icon : icon ? ' <span class="mde-ico">' + icon + ' </span>' : undefined , text : text , className : " mde-btn" + ( text ? " mde-text" : " " ) } ; }
64
function task ( ed ) {
65
var cm = ed . codemirror , from = cm . getCursor ( " from" ) , to = cm . getCursor ( " to" ) ;
66
for ( var l = from . line ; l <= to . line ; l ++ ) {
67
var line = cm . getLine ( l ) , m = line . match ( / ^ ( \s * ) [ -*] \[ [ xX] \] / ) ;
68
if ( m ) cm . replaceRange ( m [ 1 ] , { line : l , ch : 0 } , { line : l , ch : m [ 0 ] . length } ) ;
69
else cm . replaceRange ( " - [ ] " , { line : l , ch : ( line . match ( / ^ \s * / ) || [ " " ] ) [ 0 ] . length } ) ;
70
}
71
cm . focus ( ) ;
72
}
73
var toolbar = [ b ( " preview" , E . togglePreview , " Preview" , null , " Preview" ) , " |" ,
74
b ( " bold" , E . toggleBold , " Bold (Ctrl+B)" , I . bold ) , b ( " italic" , E . toggleItalic , " Italic (Ctrl+I)" , I . italic ) , b ( " strikethrough" , E . toggleStrikethrough , " Strikethrough" , I . strike ) , b ( " heading" , E . toggleHeadingSmaller , " Heading" , I . heading ) , " |" ,
75
b ( " quote" , E . toggleBlockquote , " Quote" , I . quote ) , b ( " code" , E . toggleCodeBlock , " Code" , I . code ) , b ( " link" , E . drawLink , " Link (Ctrl+K)" , I . link ) , " |" ,
76
b ( " unordered-list" , E . toggleUnorderedList , " Bullet list" , I . ul ) , b ( " ordered-list" , E . toggleOrderedList , " Numbered list" , I . ol ) , b ( " task-list" , task , " Task list" , I . task ) , b ( " table" , E . drawTable , " Table" , I . table ) , " |" ,
77
b ( " fullscreen" , E . toggleFullScreen , " Fullscreen" , I . full ) ] ;
78
mds . forEach ( function ( t ) {
79
t . _mde = new E ( { element : t , spellChecker : false , status : false , forceSync : true , autoDownloadFontAwesome : false , toolbar : toolbar ,
80
placeholder : t . getAttribute ( " placeholder" ) || " Write in Markdown…" , minHeight : " 120px" , sideBySideFullscreen : false } ) ;
81
var c = t . _mde . element . parentNode . querySelector ( " .EasyMDEContainer" ) || t . nextElementSibling ;
82
if ( c && c . classList . contains ( " EasyMDEContainer" ) ) {
83
var f = document . createElement ( " div" ) ;
84
f . className = " mde-foot small mute" ;
85
f . innerHTML = ' <span>Markdown supported</span><span class="mde-md" title="Markdown" aria-hidden="true">M↓</span>' ;
86
c . appendChild ( f ) ;
87
}
88
} ) ;
4f37afcc Andy McCall 1 month ago ↶
89
90
window . addEventListener ( " hashchange" , function ( ) { mds . forEach ( function ( t ) { if ( t . _mde ) setTimeout ( function ( ) { t . _mde . codemirror . refresh ( ) ; } , 0 ) ; } ) ; } ) ;
14530604 Andy McCall 1 month ago ↶
91
} ) ;
92
84751769 Andy McCall 1 month ago ↶
93
94
95
96
97
var diagrams = document . querySelectorAll ( " pre > code.language-mermaid" ) ;
98
if ( diagrams . length ) load ( " /static/vendor/mermaid.min.js" ) . then ( function ( ) {
99
var m = window . mermaid , dark = document . documentElement . dataset . theme === " dark" ;
100
m . initialize ( { startOnLoad : false , securityLevel : " strict" , suppressErrorRendering : true , theme : dark ? " dark" : " default" } ) ;
101
diagrams . forEach ( function ( code , i ) {
102
var pre = code . parentNode , source = code . textContent ;
103
m . render ( " mermaid-" + i , source ) . then ( function ( r ) {
104
var fig = document . createElement ( " figure" ) ;
105
fig . className = " mermaid-diagram" ;
106
fig . innerHTML = r . svg ;
107
fig . setAttribute ( " aria-label" , " Diagram" ) ;
108
pre . replaceWith ( fig ) ;
109
} ) . catch ( function ( e ) {
110
var note = document . createElement ( " p" ) ;
111
note . className = " small warn" ;
112
note . textContent = " This diagram could not be drawn: " + ( ( e && e . message ) || e ) ;
113
pre . after ( note ) ;
114
} ) ;
115
} ) ;
116
} ) ;
117
f3e5e2bc Andy McCall 25 days ago ↶
118
119
120
121
var frames = document . querySelectorAll ( " iframe.rep-frame" ) ;
122
var themeToFrames = function ( ) {
123
frames . forEach ( function ( f ) { if ( f . contentWindow ) f . contentWindow . postMessage ( { oxygenhubTheme : document . documentElement . dataset . theme || " dark" } , " *" ) ; } ) ;
124
} ;
125
if ( frames . length ) window . addEventListener ( " message" , function ( e ) {
126
frames . forEach ( function ( f ) {
127
if ( e . source !== f . contentWindow ) return ;
128
var r = e . data && e . data . oxygenhubReport ;
129
if ( ! r ) return ;
130
if ( r . ready ) themeToFrames ( ) ;
131
if ( typeof r . height === " number" && r . height > 0 ) {
132
f . style . height = Math . min ( Math . max ( r . height , 120 ) , 40000 ) + " px" ;
133
f . classList . add ( " sized" ) ;
134
}
135
} ) ;
136
} ) ;
137
95b525b0 Andy McCall 24 days ago ↶
138
139
140
141
142
if ( frames . length ) window . addEventListener ( " message" , function ( e ) {
143
frames . forEach ( function ( f ) {
144
if ( e . source !== f . contentWindow ) return ;
145
var ask = e . data && e . data . oxygenhubAsk ;
146
if ( ! ask ) return ;
147
var runs = [ ] ; try { runs = JSON . parse ( f . dataset . reportRuns || " []" ) ; } catch ( _ ) { }
148
var current = Number ( f . dataset . reportCurrent ) ;
149
var reply = function ( body ) { f . contentWindow . postMessage ( { oxygenhubAnswer : { n : ask . n , value : body . value , error : body . error } } , " *" ) ; } ;
150
var meta = function ( r ) { return { run : r . run , bookmark : r . bookmark , created_ms : r . created_ms , summary : r . summary , current : r . id === current } ; } ;
151
if ( ask . what === " run" ) {
152
var r = runs . filter ( function ( x ) { return x . id === current ; } ) [ 0 ] ;
153
reply ( { value : r ? meta ( r ) : null } ) ;
154
} else if ( ask . what === " history" && typeof ask . dataset === " string" && / ^ [ A-Za-z0-9. _+-] + ( \/ [ A-Za-z0-9. _+-] + ) * $ / . test ( ask . dataset ) ) {
155
Promise . all ( runs . map ( function ( r ) {
156
return fetch ( r . files + " /data/" + ask . dataset ) . then ( function ( res ) { return res . ok ? res . text ( ) : null ; } ) . catch ( function ( ) { return null ; } )
157
. then ( function ( text ) { var m = meta ( r ) ; m . text = text ; return m ; } ) ;
158
} ) ) . then ( function ( all ) { reply ( { value : all . filter ( function ( x ) { return x . text !== null ; } ) } ) ; } ) ;
159
} else {
160
reply ( { error : " ask for run, or history with a file name under data/" } ) ;
161
}
162
} ) ;
163
} ) ;
164
165
166
167
var tl = document . querySelector ( " [data-timeline]" ) ;
168
if ( tl ) {
169
var stops = Array . prototype . slice . call ( tl . querySelectorAll ( " [data-tl-stop]" ) ) ;
170
var at = stops . findIndex ( function ( a ) { return a . classList . contains ( " on" ) ; } ) ;
171
var go = function ( i , play ) {
172
if ( i < 0 || i >= stops . length ) return ;
173
var u = new URL ( stops [ i ] . href , location . href ) ;
174
if ( play ) u . searchParams . set ( " play" , play ) ; else u . searchParams . delete ( " play" ) ;
175
location . href = u . toString ( ) ;
176
} ;
177
document . addEventListener ( " keydown" , function ( e ) {
178
if ( e . target . closest ( " input, select, textarea, [contenteditable]" ) ) return ;
179
if ( e . key === " ArrowLeft" ) { e . preventDefault ( ) ; go ( at - 1 , tl . dataset . play ) ; }
180
if ( e . key === " ArrowRight" ) { e . preventDefault ( ) ; go ( at + 1 , tl . dataset . play ) ; }
181
} ) ;
182
var speed = tl . querySelector ( " [data-tl-speed]" ) , button = tl . querySelector ( " [data-tl-play]" ) ;
183
if ( button ) button . addEventListener ( " click" , function ( ) {
184
if ( tl . dataset . play ) { go ( at , null ) ; return ; }
185
go ( at >= stops . length - 1 ? 0 : at + 1 , speed ? speed . value : " 2" ) ;
186
} ) ;
187
if ( speed ) speed . addEventListener ( " change" , function ( ) { if ( tl . dataset . play ) go ( at , speed . value ) ; } ) ;
188
if ( tl . dataset . play ) {
189
var next = at + 1 ;
190
if ( next < stops . length ) setTimeout ( function ( ) { go ( next , tl . dataset . play ) ; } , Number ( tl . dataset . play ) * 1000 ) ;
191
else setTimeout ( function ( ) { go ( at , null ) ; } , Number ( tl . dataset . play ) * 1000 ) ;
192
}
193
}
194
c40c2d3e Andy McCall 1 month ago ↶
195
196
var toggle = document . querySelector ( " [data-theme-toggle]" ) ;
197
if ( toggle ) {
d98a93c1 Andy McCall 1 month ago ↶
198
var root = document . documentElement , order = [ " light" , " dark" , " auto" ] , glyph = { dark : " ◐" , light : " ☀" , auto : " ◑" } ;
c40c2d3e Andy McCall 1 month ago ↶
199
var show = function ( ) {
d98a93c1 Andy McCall 1 month ago ↶
200
var p = root . dataset . themePref || " light" ;
c40c2d3e Andy McCall 1 month ago ↶
201
toggle . title = " Theme: " + p + " (click to change)" ;
202
toggle . setAttribute ( " aria-label" , toggle . title ) ;
203
toggle . firstElementChild . textContent = glyph [ p ] ;
204
} ;
205
show ( ) ;
206
toggle . addEventListener ( " click" , function ( ) {
d98a93c1 Andy McCall 1 month ago ↶
207
var p = order [ ( order . indexOf ( root . dataset . themePref || " light" ) + 1 ) % order . length ] ;
c40c2d3e Andy McCall 1 month ago ↶
208
document . cookie = " theme=" + p + " ; path=/; max-age=31536000; samesite=lax" ;
209
root . dataset . themePref = p ;
210
root . dataset . theme = p === " auto" ? ( window . matchMedia && matchMedia ( " (prefers-color-scheme: light)" ) . matches ? " light" : " dark" ) : p ;
211
show ( ) ;
f3e5e2bc Andy McCall 25 days ago ↶
212
themeToFrames ( ) ;
c40c2d3e Andy McCall 1 month ago ↶
213
} ) ;
214
}
215
9df855f2 Andy McCall 1 month ago ↶
216
217
var diffs = document . querySelectorAll ( " table.code.diff" ) ;
218
if ( diffs . length ) {
219
var pane = function ( tr , col , side ) {
220
var n = document . createElement ( " td" ) , t = document . createElement ( " td" ) ;
221
n . className = " n" ; t . className = " t" + ( side === " right" ? " mid" : " " ) ;
222
if ( ! tr ) { n . className += " none" ; t . className += " none" ; return [ n , t ] ; }
223
var kind = tr . classList . contains ( " add" ) ? " add" : tr . classList . contains ( " del" ) ? " del" : " ctx" ;
224
if ( kind !== " ctx" ) { n . className += " " + kind ; t . className += " " + kind ; }
225
n . textContent = tr . cells [ col ] . textContent ;
226
t . innerHTML = tr . cells [ 3 ] . innerHTML ;
227
228
if ( side === " left" ) t . querySelectorAll ( " .linecomment" ) . forEach ( function ( d ) { d . remove ( ) ; } ) ;
229
return [ n , t ] ;
230
} ;
231
var split = function ( table ) {
232
var s = document . createElement ( " table" ) ;
233
s . className = " code diff split" ;
234
s . innerHTML = ' <colgroup><col class="n"><col><col class="n"><col></colgroup>' ;
235
var rows = [ ] . slice . call ( table . rows ) , i = 0 ;
236
var add = function ( l , r ) {
237
var tr = s . insertRow ( ) ;
238
pane ( l , 0 , " left" ) . concat ( pane ( r , 1 , " right" ) ) . forEach ( function ( c ) { tr . appendChild ( c ) ; } ) ;
239
} ;
240
while ( i < rows . length ) {
241
var r = rows [ i ] ;
242
if ( r . classList . contains ( " del" ) || r . classList . contains ( " add" ) ) {
243
var dels = [ ] , adds = [ ] ;
244
while ( i < rows . length && rows [ i ] . classList . contains ( " del" ) ) dels . push ( rows [ i ++ ] ) ;
245
while ( i < rows . length && rows [ i ] . classList . contains ( " add" ) ) adds . push ( rows [ i ++ ] ) ;
246
for ( var k = 0 ; k < Math . max ( dels . length , adds . length ) ; k ++ ) add ( dels [ k ] , adds [ k ] ) ;
247
continue ;
248
}
249
if ( r . classList . contains ( " gap" ) || r . querySelector ( " td.thread" ) ) {
250
var tr = s . insertRow ( ) , td = tr . insertCell ( ) ;
251
tr . className = r . className ; td . colSpan = 4 ; td . className = r . cells [ r . cells . length - 1 ] . className ;
252
td . innerHTML = r . cells [ r . cells . length - 1 ] . innerHTML ;
253
} else {
254
add ( r , r ) ;
255
}
256
i ++ ;
257
}
258
return s ;
259
} ;
260
var cookieMode = ( document . cookie . match ( / ( ?: ^ | ; ) diff=( split| unified) / ) || [ ] ) [ 1 ] || " unified" ;
261
var apply = function ( mode ) {
262
diffs . forEach ( function ( t ) {
263
if ( mode === " split" && ! t . _split ) { t . _split = split ( t ) ; t . parentNode . insertBefore ( t . _split , t . nextSibling ) ; }
264
t . hidden = mode === " split" ;
265
if ( t . _split ) t . _split . hidden = mode !== " split" ;
266
} ) ;
267
document . querySelectorAll ( " [data-diff-mode]" ) . forEach ( function ( a ) { a . classList . toggle ( " on" , a . getAttribute ( " data-diff-mode" ) === mode ) ; } ) ;
268
} ;
269
document . querySelectorAll ( " [data-diff-modes], [data-diff-collapse]" ) . forEach ( function ( e ) { e . hidden = false ; } ) ;
270
document . querySelectorAll ( " [data-diff-mode]" ) . forEach ( function ( a ) {
271
a . addEventListener ( " click" , function ( ev ) {
272
ev . preventDefault ( ) ;
273
var mode = a . getAttribute ( " data-diff-mode" ) ;
274
document . cookie = " diff=" + mode + " ; path=/; max-age=31536000; samesite=lax" ;
275
apply ( mode ) ;
276
} ) ;
277
} ) ;
278
document . querySelectorAll ( " [data-diff-collapse]" ) . forEach ( function ( a ) {
279
a . addEventListener ( " click" , function ( ev ) {
280
ev . preventDefault ( ) ;
281
var files = document . querySelectorAll ( " details.file-diff" ) , anyOpen = [ ] . some . call ( files , function ( d ) { return d . open ; } ) ;
282
files . forEach ( function ( d ) { d . open = ! anyOpen ; } ) ;
283
a . textContent = anyOpen ? " expand all" : " collapse all" ;
284
} ) ;
285
} ) ;
286
apply ( cookieMode ) ;
287
}
288
64caed18 Andy McCall 1 month ago ↶
289
290
var navLinks = document . querySelectorAll ( " .section-nav a[href^='#']" ) ;
291
if ( navLinks . length && " IntersectionObserver" in window ) {
292
var byId = { } ;
293
navLinks . forEach ( function ( a ) { byId [ a . getAttribute ( " href" ) . slice ( 1 ) ] = a ; } ) ;
294
var io = new IntersectionObserver ( function ( entries ) {
295
entries . forEach ( function ( e ) {
296
if ( e . isIntersecting && byId [ e . target . id ] ) {
297
navLinks . forEach ( function ( a ) { a . classList . remove ( " on" ) ; } ) ;
298
byId [ e . target . id ] . classList . add ( " on" ) ;
299
}
300
} ) ;
301
} , { rootMargin : " 0px 0px -70% 0px" } ) ;
302
Object . keys ( byId ) . forEach ( function ( id ) { var el = document . getElementById ( id ) ; if ( el ) io . observe ( el ) ; } ) ;
303
}
304
84e3c096 Andy McCall 10 days ago ↶
305
306
d23464c0 Andy McCall 1 month ago ↶
307
document . querySelectorAll ( " [data-copy]" ) . forEach ( function ( b ) {
84e3c096 Andy McCall 10 days ago ↶
308
var glyph = b . classList . contains ( " copy-btn" ) , timer ;
309
if ( glyph ) { b . setAttribute ( " data-tip" , " Copy to clipboard" ) ; b . title = " " ; }
d23464c0 Andy McCall 1 month ago ↶
310
b . addEventListener ( " click" , function ( ) {
311
navigator . clipboard . writeText ( b . getAttribute ( " data-copy" ) ) . then ( function ( ) {
84e3c096 Andy McCall 10 days ago ↶
312
clearTimeout ( timer ) ;
313
if ( glyph ) {
314
b . classList . add ( " copied" ) ; b . setAttribute ( " data-tip" , " Copied!" ) ; b . setAttribute ( " aria-label" , " Copied!" ) ;
315
timer = setTimeout ( function ( ) { b . classList . remove ( " copied" ) ; b . setAttribute ( " data-tip" , " Copy to clipboard" ) ; b . setAttribute ( " aria-label" , " Copy to clipboard" ) ; } , 2000 ) ;
316
} else {
317
var t = b . getAttribute ( " data-label" ) || b . textContent ; b . setAttribute ( " data-label" , t ) ;
318
b . textContent = " copied" ; timer = setTimeout ( function ( ) { b . textContent = t ; } , 1200 ) ;
319
}
d23464c0 Andy McCall 1 month ago ↶
320
} ) ;
321
} ) ;
322
} ) ;
323
324
325
var tree = document . querySelector ( " table.tree[data-last]" ) ;
326
if ( tree ) {
327
var paths = [ ] . map . call ( tree . querySelectorAll ( " tr[data-path]" ) , function ( r ) { return r . getAttribute ( " data-path" ) ; } ) ;
328
if ( paths . length ) {
329
fetch ( tree . getAttribute ( " data-last" ) + " ?paths=" + encodeURIComponent ( paths . join ( " ," ) ) , { credentials : " same-origin" } )
330
. then ( function ( r ) { return r . json ( ) ; } )
331
. then ( function ( rows ) {
332
rows . forEach ( function ( c ) {
333
var tr = tree . querySelector ( ' tr[data-path="' + CSS . escape ( c . path ) + ' "]' ) ;
334
if ( ! tr ) return ;
335
var a = tr . querySelector ( " td.last a" ) , t = tr . querySelector ( " td.age" ) ;
336
if ( a ) { a . textContent = c . title ; a . href = tree . getAttribute ( " data-change" ) + c . hash ; }
337
if ( t ) { t . textContent = c . ago ; t . title = c . when ; }
338
} ) ;
339
} ) . catch ( function ( ) { } ) ;
340
}
341
}
342
343
344
function mark ( ) {
345
var m = location . hash . match ( / ^ #L( \d + ) ( ?: -L( \d + ) ) ? $ / ) ;
346
document . querySelectorAll ( " tr.hl" ) . forEach ( function ( r ) { r . classList . remove ( " hl" ) ; } ) ;
6ae41081 Andy McCall 1 month ago ↶
347
if ( ! m ) { showBar ( 0 , 0 ) ; return ; }
d23464c0 Andy McCall 1 month ago ↶
348
var a = + m [ 1 ] , b = + ( m [ 2 ] || m [ 1 ] ) ;
349
for ( var i = Math . min ( a , b ) ; i <= Math . max ( a , b ) ; i ++ ) {
350
var row = document . getElementById ( " L" + i ) ;
351
if ( row ) row . classList . add ( " hl" ) ;
352
}
353
var first = document . getElementById ( " L" + Math . min ( a , b ) ) ;
354
if ( first && ! mark . done ) { first . scrollIntoView ( { block : " center" } ) ; mark . done = true ; }
6ae41081 Andy McCall 1 month ago ↶
355
showBar ( Math . min ( a , b ) , Math . max ( a , b ) ) ;
356
}
357
358
var bar = document . querySelector ( " .linebar" ) ;
359
function showBar ( a , b ) {
360
if ( ! bar ) return ;
361
bar . hidden = ! a ;
362
if ( ! a ) return ;
363
bar . querySelector ( " [data-linebar-label]" ) . textContent = a === b ? " Line " + a : " Lines " + a + " –" + b ;
364
bar . setAttribute ( " data-range" , a + " -" + b ) ;
365
}
366
function flash ( btn ) { var t = btn . textContent ; btn . textContent = " Copied" ; setTimeout ( function ( ) { btn . textContent = t ; } , 1200 ) ; }
367
if ( bar ) {
368
bar . querySelector ( " [data-copy-lines]" ) . addEventListener ( " click" , function ( ev ) {
369
var r = bar . getAttribute ( " data-range" ) . split ( " -" ) , out = [ ] ;
370
for ( var i = + r [ 0 ] ; i <= + r [ 1 ] ; i ++ ) { var row = document . getElementById ( " L" + i ) ; if ( row ) out . push ( row . querySelector ( " td.t" ) . textContent ) ; }
371
navigator . clipboard . writeText ( out . join ( " \n " ) + " \n " ) . then ( function ( ) { flash ( ev . target ) ; } ) ;
372
} ) ;
373
var pl = bar . querySelector ( " [data-copy-permalink]" ) ;
374
if ( pl ) pl . addEventListener ( " click" , function ( ) {
375
navigator . clipboard . writeText ( new URL ( document . body . getAttribute ( " data-permalink" ) , location . href ) . href + location . hash ) . then ( function ( ) { flash ( pl ) ; } ) ;
376
} ) ;
d23464c0 Andy McCall 1 month ago ↶
377
}
6ae41081 Andy McCall 1 month ago ↶
378
function permalink ( ) { var p = document . body . getAttribute ( " data-permalink" ) ; return p ? p + location . hash : null ; }
d23464c0 Andy McCall 1 month ago ↶
379
window . addEventListener ( " hashchange" , mark ) ;
380
mark ( ) ;
381
document . querySelectorAll ( " table.code td.n" ) . forEach ( function ( td ) {
382
td . addEventListener ( " click" , function ( e ) {
383
var n = td . parentNode . id ;
384
if ( e . shiftKey && location . hash . match ( / ^ #L( \d + ) / ) ) location . hash = location . hash . replace ( / ^ #( L\d + ) . * / , " $1-" + n ) ;
385
else location . hash = n ;
386
} ) ;
387
} ) ;
388
42fa9554 Andy McCall 1 month ago ↶
389
390
var liveUrl = document . body . getAttribute ( " data-flow-live" ) ;
391
if ( liveUrl ) {
392
var tick = function ( ) {
393
var after = [ ] . map . call ( document . querySelectorAll ( " details[data-job]" ) , function ( d ) {
394
return d . getAttribute ( " data-job" ) + " :" + d . querySelector ( " [data-log]" ) . getAttribute ( " data-seq" ) ;
395
} ) . join ( " ," ) ;
396
fetch ( liveUrl + " ?after=" + after , { headers : { accept : " application/json" } } )
397
. then ( function ( r ) { return r . json ( ) ; } )
398
. then ( function ( s ) {
399
s . jobs . forEach ( function ( j ) {
400
var cls = " st-" + j . status ;
401
var node = document . querySelector ( " [data-job-node='" + j . id + " ']" ) ;
402
if ( node ) {
403
node . setAttribute ( " class" , " node " + cls ) ;
404
node . querySelector ( " [data-glyph]" ) . textContent = j . glyph ;
405
node . querySelector ( " [data-meta]" ) . textContent = j . status + " · " + j . duration ;
406
}
407
var d = document . querySelector ( " details[data-job='" + j . id + " ']" ) ;
408
if ( ! d ) return ;
409
d . className = " panel flow-job " + cls ;
410
var g = d . querySelector ( " summary [data-glyph]" ) ;
411
g . className = " flow-glyph " + cls ; g . textContent = j . glyph ;
412
d . querySelector ( " summary [data-meta]" ) . textContent = j . status + ( j . exit_code !== null ? " · exit " + j . exit_code : " " ) + " · " + j . duration ;
413
if ( j . status === " running" || j . status === " failed" ) d . open = true ;
858eca0d Andy McCall 15 days ago ↶
414
415
if ( j . status !== " queued" ) [ ] . forEach . call ( d . querySelectorAll ( " [data-queued-note]" ) , function ( p ) { p . remove ( ) ; } ) ;
42fa9554 Andy McCall 1 month ago ↶
416
var log = d . querySelector ( " [data-log]" ) ;
417
var stick = log . scrollTop + log . clientHeight >= log . scrollHeight - 4 ;
d9b3b846 Andy McCall 22 days ago ↶
418
419
420
var open = log . querySelector ( " details[data-open-group]" ) ;
421
var secs = function ( ms ) { return Math . floor ( ms / 1000 ) + " ." + Math . floor ( ms % 1000 / 100 ) + " s" ; } ;
422
var close = function ( t ) {
423
if ( ! open ) return ;
424
open . removeAttribute ( " data-open-group" ) ; open . open = false ;
425
var took = document . createElement ( " span" ) ; took . className = " took" ; took . textContent = " " + secs ( t - Number ( open . getAttribute ( " data-from" ) ) ) ;
426
open . querySelector ( " summary" ) . appendChild ( took ) ; open = null ;
427
} ;
42fa9554 Andy McCall 1 month ago ↶
428
j . lines . forEach ( function ( l ) {
d9b3b846 Andy McCall 22 days ago ↶
429
var tt = document . createElement ( " span" ) ; tt . className = " t" ; tt . textContent = secs ( l . t ) ;
430
if ( l . text . indexOf ( " ::group::" ) === 0 ) {
431
close ( l . t ) ;
432
open = document . createElement ( " details" ) ; open . className = " log-group" ; open . open = true ;
433
open . setAttribute ( " data-open-group" , " " ) ; open . setAttribute ( " data-from" , l . t ) ;
434
var sum = document . createElement ( " summary" ) ; sum . className = " ln" ;
435
sum . appendChild ( tt ) ; sum . appendChild ( document . createTextNode ( l . text . slice ( 9 ) . trim ( ) ) ) ;
436
open . appendChild ( sum ) ; log . appendChild ( open ) ;
437
} else if ( l . text . trim ( ) === " ::endgroup::" ) {
438
close ( l . t ) ;
439
} else {
440
var ln = document . createElement ( " span" ) ; ln . className = " ln s-" + l . stream ;
441
ln . appendChild ( tt ) ; ln . appendChild ( document . createTextNode ( l . text ) ) ;
442
var into = open || log ;
443
into . appendChild ( ln ) ; into . appendChild ( document . createTextNode ( " \n " ) ) ;
444
}
42fa9554 Andy McCall 1 month ago ↶
445
log . setAttribute ( " data-seq" , l . seq ) ;
446
} ) ;
447
if ( stick && j . lines . length ) log . scrollTop = log . scrollHeight ;
448
} ) ;
449
var st = document . querySelector ( " [data-run-status]" ) ; if ( st ) st . textContent = s . status ;
450
if ( s . live ) setTimeout ( tick , 1500 ) ; else setTimeout ( function ( ) { location . reload ( ) ; } , 800 ) ;
451
} )
452
. catch ( function ( ) { setTimeout ( tick , 5000 ) ; } ) ;
453
} ;
454
setTimeout ( tick , 1500 ) ;
455
}
456
d23464c0 Andy McCall 1 month ago ↶
457
458
var pending = null ;
459
document . addEventListener ( " keydown" , function ( e ) {
460
if ( e . target && / ^ ( INPUT| TEXTAREA| SELECT) $ / . test ( e . target . tagName ) ) return ;
461
if ( e . key === " /" ) { var s = document . querySelector ( " input[name=q]" ) ; if ( s ) { e . preventDefault ( ) ; s . focus ( ) ; } return ; }
6ae41081 Andy McCall 1 month ago ↶
462
if ( e . key === " y" && ! e . ctrlKey && ! e . metaKey && ! e . altKey && permalink ( ) ) { history . replaceState ( null , " " , permalink ( ) ) ; pending = null ; return ; }
d23464c0 Andy McCall 1 month ago ↶
463
if ( e . key === " ?" ) { var k = document . getElementById ( " keys" ) ; if ( k ) k . hidden = ! k . hidden ; return ; }
464
var repo = document . body . getAttribute ( " data-repo" ) ;
465
if ( pending === " g" && repo ) {
466
var to = { c : " " , p : " /proposals" , i : " /issues" , h : " /changes/" + ( document . body . getAttribute ( " data-ref" ) || " main" ) , b : " /bookmarks" , t : " /trust" } [ e . key ] ;
467
if ( to !== undefined ) location . href = repo + to ;
468
pending = null ; return ;
469
}
470
pending = e . key === " g" ? " g" : null ;
471
} ) ;
5e6d6484 Andy McCall 1 month ago ↶
472
473
474
475
476
var live = document . querySelector ( " [data-resolve-live]" ) ;
477
if ( live && window . EventSource && window . fetch ) {
478
var url = live . getAttribute ( " data-resolve-live" ) , csrf = live . getAttribute ( " data-csrf" ) ;
479
var client = Math . random ( ) . toString ( 36 ) . slice ( 2 ) + Date . now ( ) . toString ( 36 ) ;
480
var present = document . querySelector ( " [data-live-present]" ) , landed = document . querySelector ( " [data-live-landed]" ) ;
481
var applying = false ;
482
var fieldsOf = function ( region ) {
483
return region === " keep"
484
? { radios : live . querySelectorAll ( ' input[name="keep"]' ) , text : null }
485
: { radios : live . querySelectorAll ( ' input[name="r' + region + ' "]' ) , text : live . querySelector ( ' textarea[name="t' + region + ' "]' ) } ;
486
} ;
487
var apply = function ( region , c ) {
488
var f = fieldsOf ( region ) ;
489
applying = true ;
490
f . radios . forEach ( function ( r ) { r . checked = r . value === c . choice ; } ) ;
491
if ( f . text && c . choice === " text" ) f . text . value = c . text ;
492
applying = false ;
493
var sec = f . radios . length ? f . radios [ 0 ] . closest ( " section" ) : null ;
494
if ( sec ) sec . setAttribute ( " title" , " chosen by " + c . by ) ;
495
} ;
496
var send = function ( region , choice , text ) {
497
fetch ( url , { method : " POST" , headers : { " content-type" : " application/json" } , credentials : " same-origin" ,
498
body : JSON . stringify ( { _csrf : csrf , client : client , region : region , choice : choice , text : text || " " } ) } ) ;
499
} ;
500
var timers = { } ;
501
live . addEventListener ( " change" , function ( ev ) {
502
var t = ev . target ;
503
if ( applying || ! t . name || t . type !== " radio" ) return ;
504
var region = t . name === " keep" ? " keep" : t . name . slice ( 1 ) ;
505
var ta = live . querySelector ( ' textarea[name="t' + region + ' "]' ) ;
506
send ( region , t . value , t . value === " text" && ta ? ta . value : " " ) ;
507
} ) ;
508
live . addEventListener ( " input" , function ( ev ) {
509
var t = ev . target ;
510
if ( applying || t . tagName !== " TEXTAREA" ) return ;
511
var region = t . name . slice ( 1 ) ;
512
live . querySelectorAll ( ' input[name="r' + region + ' "]' ) . forEach ( function ( r ) { r . checked = r . value === " text" ; } ) ;
513
clearTimeout ( timers [ region ] ) ;
514
timers [ region ] = setTimeout ( function ( ) { send ( region , " text" , t . value ) ; } , 400 ) ;
515
} ) ;
516
var es = new EventSource ( url + " ?client=" + encodeURIComponent ( client ) ) ;
517
var showPresent = function ( names ) {
518
present . hidden = names . length < 2 ;
519
present . textContent = " Resolving together: " + names . join ( " , " ) + " . Choices are shared as you make them; the last choice for a conflict wins." ;
520
} ;
521
es . addEventListener ( " snapshot" , function ( e ) {
522
var d = JSON . parse ( e . data ) ;
523
showPresent ( d . present ) ;
524
Object . keys ( d . choices ) . forEach ( function ( r ) { apply ( r , d . choices [ r ] ) ; } ) ;
525
if ( d . keep ) apply ( " keep" , d . keep ) ;
526
} ) ;
527
es . addEventListener ( " presence" , function ( e ) { showPresent ( JSON . parse ( e . data ) . present ) ; } ) ;
528
es . addEventListener ( " choice" , function ( e ) {
529
var d = JSON . parse ( e . data ) ;
530
if ( d . client !== client ) apply ( d . region , d . choice ) ;
531
} ) ;
532
es . addEventListener ( " landed" , function ( e ) {
533
var d = JSON . parse ( e . data ) ;
534
es . close ( ) ;
535
landed . hidden = false ;
536
landed . textContent = " " ;
537
landed . appendChild ( document . createTextNode ( d . by + " committed the resolution: " ) ) ;
538
var a = document . createElement ( " a" ) ;
539
a . href = d . url ;
540
a . textContent = " see the change" ;
541
landed . appendChild ( a ) ;
542
live . querySelectorAll ( " input, textarea, button" ) . forEach ( function ( x ) { x . disabled = true ; } ) ;
543
} ) ;
544
}
2bfe5ef6 Andy McCall 1 month ago ↶
545
546
547
548
549
var plan = document . querySelector ( " [data-plan]" ) ;
550
if ( plan && window . fetch ) {
551
var panel = document . querySelector ( " [data-plan-panel]" ) , from = null , moved = false ;
552
plan . querySelectorAll ( " [data-change]" ) . forEach ( function ( a ) {
553
a . style . cursor = " grab" ;
554
a . addEventListener ( " pointerdown" , function ( ev ) { from = a . getAttribute ( " data-change" ) ; moved = false ; ev . preventDefault ( ) ; } ) ;
555
a . addEventListener ( " pointermove" , function ( ) { if ( from ) moved = true ; } ) ;
556
a . addEventListener ( " click" , function ( ev ) { if ( moved ) ev . preventDefault ( ) ; } ) ;
557
} ) ;
558
document . addEventListener ( " pointerup" , function ( ev ) {
559
var start = from ;
560
from = null ;
561
if ( ! start ) return ;
562
var el = document . elementFromPoint ( ev . clientX , ev . clientY ) , onto = el && el . closest ? el . closest ( " [data-change]" ) : null ;
563
if ( ! onto || onto . getAttribute ( " data-change" ) === start ) return ;
564
var body = new URLSearchParams ( { _csrf : plan . getAttribute ( " data-csrf" ) , change : start , target : onto . getAttribute ( " data-change" ) } ) ;
565
fetch ( plan . getAttribute ( " data-plan" ) , { method : " POST" , credentials : " same-origin" , body : body } )
566
. then ( function ( r ) { return r . json ( ) ; } )
567
. then ( function ( d ) {
568
panel . hidden = false ;
569
panel . textContent = " " ;
570
if ( d . error ) { panel . textContent = d . error ; return ; }
571
d . options . forEach ( function ( o ) {
572
var p = document . createElement ( " p" ) ;
573
p . appendChild ( document . createTextNode ( o . summary + " " ) ) ;
574
var a = document . createElement ( " a" ) ;
575
a . href = o . vscode ;
576
a . textContent = " Apply in VS Code" ;
577
p . appendChild ( a ) ;
578
var code = document . createElement ( " pre" ) ;
579
code . className = " snippet" ;
580
code . textContent = o . command ;
581
panel . appendChild ( p ) ;
582
panel . appendChild ( code ) ;
583
} ) ;
584
} ) ;
585
} ) ;
586
}
cb71e18e Andy McCall 1 month ago ↶
587
588
589
590
document . querySelectorAll ( " [data-menu-filter]" ) . forEach ( function ( input ) {
591
var items = input . closest ( " .menu-pop" ) . querySelectorAll ( " .menu-item" ) ;
592
input . addEventListener ( " input" , function ( ) {
593
var q = input . value . trim ( ) . toLowerCase ( ) ;
594
items . forEach ( function ( it ) { it . hidden = q !== " " && it . textContent . toLowerCase ( ) . indexOf ( q ) < 0 ; } ) ;
595
} ) ;
596
} ) ;
597
document . querySelectorAll ( " details.menu" ) . forEach ( function ( d ) {
598
d . addEventListener ( " toggle" , function ( ) {
599
var f = d . querySelector ( " [data-menu-filter]" ) ;
600
if ( d . open && f ) f . focus ( ) ;
601
} ) ;
602
} ) ;
603
document . addEventListener ( " click" , function ( ev ) {
604
document . querySelectorAll ( " details.menu[open]" ) . forEach ( function ( d ) { if ( ! d . contains ( ev . target ) ) d . open = false ; } ) ;
605
} ) ;
4f37afcc Andy McCall 1 month ago ↶
606
607
608
function copied ( btn , text ) {
609
if ( navigator . clipboard ) navigator . clipboard . writeText ( text ) . then ( function ( ) {
610
var was = btn . textContent ; btn . textContent = " Copied" ; setTimeout ( function ( ) { btn . textContent = was ; } , 1200 ) ;
611
} ) ;
612
var d = btn . closest ( " details" ) ; if ( d ) d . open = false ;
613
}
614
document . querySelectorAll ( " [data-copy-link]" ) . forEach ( function ( b ) {
615
b . addEventListener ( " click" , function ( ) { copied ( b , location . origin + location . pathname + location . search + b . getAttribute ( " data-copy-link" ) ) ; } ) ;
616
} ) ;
617
document . querySelectorAll ( " [data-copy-text]" ) . forEach ( function ( b ) {
618
b . addEventListener ( " click" , function ( ) { copied ( b , b . getAttribute ( " data-copy-text" ) ) ; } ) ;
619
} ) ;
620
document . querySelectorAll ( ' .menu-actions a[href^="#"]' ) . forEach ( function ( a ) {
621
a . addEventListener ( " click" , function ( ) { var d = a . closest ( " details" ) ; if ( d ) d . open = false ; } ) ;
622
} ) ;
ed89fae5 Andy McCall 1 month ago ↶
623
624
625
626
627
document . addEventListener ( " submit" , function ( e ) {
628
var sec = e . target . closest ? e . target . closest ( " section[id], form[id], details[id], div[id]" ) : null ;
629
if ( ! sec || ! sec . id ) return ;
630
try { sessionStorage . setItem ( " oxy-return" , location . pathname + " #" + sec . id ) ; } catch ( err ) { }
631
} ) ;
632
try {
633
var back = sessionStorage . getItem ( " oxy-return" ) ;
634
if ( back && back . indexOf ( location . pathname + " #" ) === 0 ) {
635
sessionStorage . removeItem ( " oxy-return" ) ;
636
var target = document . getElementById ( back . split ( " #" ) [ 1 ] ) ;
637
if ( target ) {
638
var flash = document . querySelector ( " main > .note, main > .error, .sections > .note, .sections > .error" ) ;
639
if ( flash && ! target . contains ( flash ) ) target . parentNode . insertBefore ( flash , target ) ;
640
target . scrollIntoView ( { block : " start" } ) ;
641
}
642
}
643
} catch ( err ) { }
155cab14 Andy McCall 1 month ago ↶
644
16626c0d Andy McCall 24 days ago ↶
645
646
647
648
649
650
var SPIN = [ " ⠋" , " ⠙" , " ⠹" , " ⠸" , " ⠼" , " ⠴" , " ⠦" , " ⠧" , " ⠇" , " ⠏" ] ;
651
var waitTimer = 0 , spinTimer = 0 , pointer = null , mark = null ;
652
document . addEventListener ( " pointermove" , function ( e ) {
653
pointer = e . pointerType === " mouse" ? { x : e . clientX , y : e . clientY } : null ;
654
if ( mark && pointer ) place ( ) ;
655
} , { passive : true } ) ;
656
function place ( ) {
657
if ( pointer ) { mark . style . left = pointer . x + 14 + " px" ; mark . style . top = pointer . y + 14 + " px" ; mark . classList . remove ( " corner" ) ; }
658
else mark . classList . add ( " corner" ) ;
659
}
660
function waiting ( ) {
661
clearTimeout ( waitTimer ) ;
662
waitTimer = setTimeout ( function ( ) {
663
if ( ! mark ) {
664
var logo = document . querySelector ( " header .brand svg" ) ;
665
mark = document . createElement ( " div" ) ;
666
mark . className = " oxy-wait-mark" ;
667
mark . setAttribute ( " role" , " status" ) ;
668
mark . setAttribute ( " aria-label" , " Working" ) ;
669
if ( logo ) mark . appendChild ( logo . cloneNode ( true ) ) ;
670
document . body . appendChild ( mark ) ;
671
}
672
place ( ) ;
673
document . documentElement . classList . add ( " oxy-wait" ) ;
674
} , 300 ) ;
675
}
676
function busy ( button , form ) {
677
if ( ! button ) return ;
678
var label = button . getAttribute ( " data-busy" ) || button . textContent . trim ( ) ;
679
button . dataset . idle = button . innerHTML ;
680
button . style . minWidth = button . offsetWidth + " px" ;
681
button . textContent = label + " " ;
682
var glyph = document . createElement ( " span" ) ;
683
glyph . className = " oxy-spin" ;
684
glyph . setAttribute ( " aria-hidden" , " true" ) ;
685
glyph . textContent = SPIN [ 0 ] ;
686
button . appendChild ( glyph ) ;
687
button . setAttribute ( " aria-busy" , " true" ) ;
688
var i = 0 ;
689
clearInterval ( spinTimer ) ;
690
spinTimer = setInterval ( function ( ) { glyph . textContent = SPIN [ ++ i % SPIN . length ] ; } , 80 ) ;
691
692
693
setTimeout ( function ( ) { button . disabled = true ; } , 0 ) ;
694
form . dataset . sending = " 1" ;
695
}
696
document . addEventListener ( " submit" , function ( e ) {
697
var form = e . target ;
698
if ( form . dataset . sending ) { e . preventDefault ( ) ; return ; }
699
if ( e . defaultPrevented || ( form . target && form . target !== " _self" ) ) return ;
700
if ( ( form . getAttribute ( " method" ) || " get" ) . toLowerCase ( ) === " post" ) {
701
busy ( e . submitter || form . querySelector ( " button[type=submit], button:not([type])" ) , form ) ;
702
}
703
waiting ( ) ;
704
} ) ;
705
document . addEventListener ( " click" , function ( e ) {
706
if ( e . defaultPrevented || e . button !== 0 || e . metaKey || e . ctrlKey || e . shiftKey || e . altKey ) return ;
707
var a = e . target . closest ? e . target . closest ( " a[href]" ) : null ;
708
if ( ! a || a . hasAttribute ( " download" ) || ( a . target && a . target !== " _self" ) ) return ;
709
var url = new URL ( a . href , location . href ) ;
710
if ( url . origin !== location . origin ) return ;
711
if ( url . pathname === location . pathname && url . search === location . search && url . hash ) return ;
712
waiting ( ) ;
713
} ) ;
714
715
window . addEventListener ( " pageshow" , function ( e ) {
716
if ( ! e . persisted ) return ;
717
clearTimeout ( waitTimer ) ;
718
clearInterval ( spinTimer ) ;
719
document . documentElement . classList . remove ( " oxy-wait" ) ;
720
document . querySelectorAll ( " [aria-busy=true][data-idle]" ) . forEach ( function ( b ) {
721
b . innerHTML = b . dataset . idle ;
722
b . disabled = false ;
723
b . removeAttribute ( " aria-busy" ) ;
724
b . style . minWidth = " " ;
725
if ( b . form ) delete b . form . dataset . sending ;
726
} ) ;
727
} ) ;
728
155cab14 Andy McCall 1 month ago ↶
729
730
731
732
document . querySelectorAll ( " [data-preset-select]" ) . forEach ( function ( sel ) {
733
var form = sel . form ;
734
function apply ( ) {
735
var o = sel . options [ sel . selectedIndex ] ;
736
if ( ! o || ! o . value ) return ;
737
var name = form . querySelector ( " [name=name]" ) , ep = form . querySelector ( " [name=endpoint]" ) , api = form . querySelector ( " [name=api]" ) ;
738
name . placeholder = o . dataset . name ; ep . value = o . dataset . endpoint ; api . value = o . dataset . api ;
739
}
740
sel . addEventListener ( " change" , apply ) ;
741
apply ( ) ;
742
} ) ;
743
document . querySelectorAll ( " [data-list-models]" ) . forEach ( function ( b ) {
744
b . addEventListener ( " click" , function ( ) {
745
var form = b . form , input = document . getElementById ( b . dataset . for ) ;
746
var list = document . getElementById ( b . dataset . for + " -list" ) , note = document . querySelector ( " [data-models-note='" + b . dataset . for + " ']" ) ;
747
var body = new URLSearchParams ( ) ;
748
body . set ( " _csrf" , b . dataset . csrf ) ;
749
[ " endpoint" , " api" , " token" , " preset" ] . forEach ( function ( k ) { var el = form . querySelector ( " [name=" + k + " ]" ) ; if ( el ) body . set ( k , el . value ) ; } ) ;
750
if ( b . dataset . id ) body . set ( " id" , b . dataset . id ) ;
751
if ( note ) note . textContent = " Asking the provider…" ;
752
fetch ( b . dataset . listModels , { method : " POST" , body : body , credentials : " same-origin" } )
753
. then ( function ( r ) { return r . json ( ) ; } )
754
. then ( function ( j ) {
755
if ( j . models ) {
756
list . innerHTML = " " ;
757
j . models . forEach ( function ( m ) { var o = document . createElement ( " option" ) ; o . value = m ; list . appendChild ( o ) ; } ) ;
758
if ( note ) note . textContent = j . models . length + " models: pick one in the Model field." ;
759
input . focus ( ) ;
760
} else if ( note ) {
761
note . textContent = " No list: " + ( j . error || " unknown" ) + " . Type the model's name." ;
762
}
763
} )
764
. catch ( function ( ) { if ( note ) note . textContent = " The hub could not ask; type the model's name." ; } ) ;
765
} ) ;
766
} ) ;
d23464c0 Andy McCall 1 month ago ↶
767
} ) ( ) ;
67be8ac0 Andy McCall 20 days ago ↶
768
769
a2ef53c5 Andy McCall 20 days ago ↶
770
771
772
67be8ac0 Andy McCall 20 days ago ↶
773
774
775
( function ( ) {
776
var marked = document . querySelectorAll ( " [data-live][data-fragment]" ) ;
777
if ( ! marked . length || ! window . EventSource || ! window . fetch ) return ;
778
var topics = { } ;
b5a0a69b Andy McCall 20 days ago ↶
779
780
var topicsOf = function ( el ) { return el . getAttribute ( " data-live" ) . split ( / \s + / ) . filter ( Boolean ) ; } ;
781
Array . prototype . forEach . call ( marked , function ( el ) { topicsOf ( el ) . forEach ( function ( t ) { topics [ t ] = true ; } ) ; } ) ;
67be8ac0 Andy McCall 20 days ago ↶
782
var typingIn = function ( el ) {
783
var a = document . activeElement ;
784
return a && el . contains ( a ) && ( a . tagName === " TEXTAREA" || ( a . tagName === " INPUT" && a . type !== " hidden" ) ) && a . value ;
785
} ;
a2ef53c5 Andy McCall 20 days ago ↶
786
787
788
789
var stale = [ ] , timer = null , fetching = false ;
790
var swapFrom = function ( doc ) {
791
var todo = stale ;
792
stale = [ ] ;
793
todo . forEach ( function ( el ) {
794
if ( typingIn ( el ) ) {
795
el . addEventListener ( " focusout" , function again ( ) {
796
el . removeEventListener ( " focusout" , again ) ;
797
refresh ( el ) ;
798
} ) ;
799
return ;
800
}
801
var name = el . getAttribute ( " data-fragment" ) ;
802
var fresh = doc . querySelector ( ' [data-fragment="' + name + ' "]' ) ;
803
if ( fresh ) el . innerHTML = fresh . innerHTML ;
804
} ) ;
805
} ;
806
var flush = function ( ) {
807
timer = null ;
808
if ( fetching || ! stale . length ) return ;
809
fetching = true ;
810
fetch ( location . href , { credentials : " same-origin" , headers : { " X-Fragment" : " page" } } )
67be8ac0 Andy McCall 20 days ago ↶
811
. then ( function ( r ) { return r . ok ? r . text ( ) : null ; } )
812
. then ( function ( html ) {
a2ef53c5 Andy McCall 20 days ago ↶
813
fetching = false ;
814
if ( html !== null ) swapFrom ( new DOMParser ( ) . parseFromString ( html , " text/html" ) ) ;
815
if ( stale . length ) timer = setTimeout ( flush , 300 ) ;
67be8ac0 Andy McCall 20 days ago ↶
816
} )
a2ef53c5 Andy McCall 20 days ago ↶
817
. catch ( function ( ) { fetching = false ; } ) ;
818
} ;
819
var refresh = function ( el ) {
820
if ( stale . indexOf ( el ) < 0 ) stale . push ( el ) ;
821
if ( ! timer ) timer = setTimeout ( flush , 300 ) ;
67be8ac0 Andy McCall 20 days ago ↶
822
} ;
823
var es = new EventSource ( " /live?topics=" + encodeURIComponent ( Object . keys ( topics ) . join ( " ," ) ) ) ;
824
es . addEventListener ( " change" , function ( e ) {
825
var d ;
826
try { d = JSON . parse ( e . data ) ; } catch ( err ) { return ; }
827
Array . prototype . forEach . call ( marked , function ( el ) {
b5a0a69b Andy McCall 20 days ago ↶
828
if ( topicsOf ( el ) . indexOf ( d . topic ) >= 0 ) refresh ( el ) ;
67be8ac0 Andy McCall 20 days ago ↶
829
} ) ;
830
} ) ;
831
832
es . addEventListener ( " reload" , function ( ) {
833
Array . prototype . forEach . call ( marked , refresh ) ;
834
} ) ;
835
} ) ( ) ;
119fd17d Andy McCall 19 days ago ↶
836
e97500b7 Andy McCall 18 days ago ↶
837
838
839
840
841
( function ( ) {
842
" use strict" ;
843
var parts = document . querySelectorAll ( " [data-refresh][data-fragment]" ) ;
844
if ( ! parts . length || ! window . fetch || ! window . DOMParser ) return ;
845
var every = Math . max ( 10 , parseInt ( parts [ 0 ] . getAttribute ( " data-refresh" ) , 10 ) || 30 ) * 1000 ;
846
var busy = false ;
847
var inUse = function ( el ) {
848
var a = document . activeElement ;
849
return a && el . contains ( a ) && / ^ ( SELECT| INPUT| TEXTAREA) $ / . test ( a . tagName ) ;
850
} ;
851
var tick = function ( ) {
852
if ( busy || document . hidden ) return ;
853
busy = true ;
854
fetch ( location . href , { credentials : " same-origin" , headers : { " X-Fragment" : " page" } } )
855
. then ( function ( r ) { return r . ok ? r . text ( ) : null ; } )
856
. then ( function ( html ) {
857
busy = false ;
858
if ( html === null ) return ;
859
var doc = new DOMParser ( ) . parseFromString ( html , " text/html" ) ;
860
Array . prototype . forEach . call ( parts , function ( el ) {
861
if ( inUse ( el ) ) return ;
862
var fresh = doc . querySelector ( ' [data-fragment="' + el . getAttribute ( " data-fragment" ) + ' "]' ) ;
863
if ( fresh ) el . innerHTML = fresh . innerHTML ;
864
} ) ;
865
} )
866
. catch ( function ( ) { busy = false ; } ) ;
867
} ;
868
setInterval ( tick , every ) ;
869
document . addEventListener ( " visibilitychange" , function ( ) { if ( ! document . hidden ) tick ( ) ; } ) ;
870
} ) ( ) ;
871
119fd17d Andy McCall 19 days ago ↶
872
873
874
875
876
( function ( ) {
877
" use strict" ;
878
if ( ! window . fetch || ! window . TextDecoder || ! window . URLSearchParams ) return ;
879
document . querySelectorAll ( " button.agent-btn[data-stream]" ) . forEach ( function ( btn ) {
880
btn . addEventListener ( " click" , function ( e ) {
881
var form = btn . form , area = form && form . querySelector ( ' textarea[name="body"]' ) ;
882
if ( ! form || ! area ) return ;
883
e . preventDefault ( ) ;
884
function get ( ) { return area . _mde ? area . _mde . value ( ) : area . value ; }
885
function show ( t ) { if ( area . _mde ) area . _mde . value ( t ) ; else area . value = t ; }
c43e4f63 Andy McCall 10 days ago ↶
886
887
888
var titleField = form . querySelector ( ' input[name="title"]' ) ;
889
function untitled ( t ) { return t . replace ( / ^ \s * title:[ ^ \n ] * ( \n \s * | $ ) / i , " " ) ; }
119fd17d Andy McCall 19 days ago ↶
890
var before = get ( ) , text = " " ;
891
var box = ( area . _mde && area . parentNode . querySelector ( " .EasyMDEContainer" ) ) || area ;
892
var note = form . querySelector ( " .draft-note" ) ;
893
if ( ! note ) { note = document . createElement ( " p" ) ; note . className = " draft-note small mute" ; box . parentNode . insertBefore ( note , box . nextSibling ) ; }
894
note . textContent = btn . value + " is drafting the description…" ;
895
var buttons = form . querySelectorAll ( " button.agent-btn" ) ;
896
buttons . forEach ( function ( b ) { b . disabled = true ; } ) ;
897
var data = new URLSearchParams ( new FormData ( form ) ) ;
898
data . set ( " assistant" , btn . value ) ;
899
var finished = false ;
900
function end ( message , keep ) { finished = true ; if ( ! keep ) show ( before ) ; note . textContent = message ; }
901
fetch ( btn . dataset . stream , { method : " POST" , body : data , credentials : " same-origin" } )
902
. then ( function ( r ) {
903
if ( ! r . ok || ! r . body ) throw new Error ( " the hub answered " + r . status ) ;
904
var reader = r . body . getReader ( ) , dec = new TextDecoder ( ) , buf = " " ;
905
function pump ( ) {
906
return reader . read ( ) . then ( function ( res ) {
907
if ( res . done ) { if ( ! finished ) end ( btn . value + " stopped before finishing." , text !== " " ) ; return ; }
908
buf += dec . decode ( res . value , { stream : true } ) ;
909
var i ;
910
while ( ( i = buf . indexOf ( " \n \n " ) ) >= 0 ) {
911
var block = buf . slice ( 0 , i ) , kind = " message" , payload = " " ;
912
buf = buf . slice ( i + 2 ) ;
913
block . split ( " \n " ) . forEach ( function ( l ) {
914
if ( l . indexOf ( " event:" ) === 0 ) kind = l . slice ( 6 ) . trim ( ) ;
915
else if ( l . indexOf ( " data:" ) === 0 ) payload += l . slice ( 5 ) . trim ( ) ;
916
} ) ;
917
if ( ! payload ) continue ;
918
var v ;
919
try { v = JSON . parse ( payload ) ; } catch ( _ ) { continue ; }
c43e4f63 Andy McCall 10 days ago ↶
920
if ( kind === " part" ) { text += v ; show ( untitled ( text ) ) ; }
921
else if ( kind === " title" ) {
922
if ( titleField && ( ! titleField . value . trim ( ) || titleField . value === titleField . defaultValue ) ) titleField . value = v ;
923
}
119fd17d Andy McCall 19 days ago ↶
924
else if ( kind === " done" ) { show ( v ) ; end ( " Drafted by " + btn . value + " ; nothing is saved until you save the proposal." , true ) ; return ; }
925
else if ( kind === " error" ) { end ( v , false ) ; return ; }
926
}
927
return pump ( ) ;
928
} ) ;
929
}
930
return pump ( ) ;
931
} )
932
. catch ( function ( err ) { end ( btn . value + " did not answer: " + err . message + " ." , false ) ; } )
933
. then ( function ( ) { buttons . forEach ( function ( b ) { b . disabled = false ; } ) ; } ) ;
934
} ) ;
935
} ) ;
a7aa76ac Andy McCall 18 days ago
936
937
938
939
940
941
document . addEventListener ( " click" , function ( e ) {
942
var el = e . target . closest && e . target . closest ( " [data-confirm]" ) ;
943
if ( el && el . tagName !== " FORM" && ! window . confirm ( el . getAttribute ( " data-confirm" ) ) ) {
944
e . preventDefault ( ) ;
945
e . stopImmediatePropagation ( ) ;
946
}
947
} , true ) ;
948
document . addEventListener ( " submit" , function ( e ) {
949
var f = e . target ;
950
if ( f . hasAttribute && f . hasAttribute ( " data-confirm" ) && ! window . confirm ( f . getAttribute ( " data-confirm" ) ) ) e . preventDefault ( ) ;
951
} , true ) ;
952
document . addEventListener ( " change" , function ( e ) {
953
var el = e . target ;
954
if ( el . hasAttribute && el . hasAttribute ( " data-autosubmit" ) && el . form ) el . form . submit ( ) ;
955
} ) ;
956
function selectAll ( e ) {
957
var el = e . target ;
958
if ( el . hasAttribute && el . hasAttribute ( " data-select" ) && el . select ) el . select ( ) ;
959
}
960
document . addEventListener ( " focusin" , selectAll ) ;
961
document . addEventListener ( " click" , selectAll ) ;
962
963
964
( function ( ) {
965
var sel = document . querySelector ( " [data-mail-service]" ) ;
966
if ( ! sel ) return ;
967
var show = function ( ) {
968
document . querySelectorAll ( " .mail-panel [data-for]" ) . forEach ( function ( el ) {
969
el . hidden = el . getAttribute ( " data-for" ) . split ( " " ) . indexOf ( sel . value ) < 0 ;
970
} ) ;
971
} ;
972
sel . addEventListener ( " change" , show ) ;
973
show ( ) ;
974
} ) ( ) ;
d366306d Andy McCall 16 days ago ↶
975
976
977
978
979
( function ( ) {
980
var list = document . querySelector ( " [data-drop-files]" ) ;
981
var add = document . querySelector ( " [data-drop-add]" ) ;
982
if ( ! list || ! add ) return ;
983
function wire ( row ) {
984
var rm = row . querySelector ( " [data-drop-remove]" ) ;
985
if ( ! rm ) return ;
986
rm . hidden = false ;
987
rm . addEventListener ( " click" , function ( ) {
988
if ( list . querySelectorAll ( " [data-drop-file]" ) . length > 1 ) row . remove ( ) ;
989
else row . querySelectorAll ( " input, textarea" ) . forEach ( function ( f ) { f . value = " " ; } ) ;
990
} ) ;
991
}
992
list . querySelectorAll ( " [data-drop-file]" ) . forEach ( wire ) ;
993
add . hidden = false ;
994
add . addEventListener ( " click" , function ( ) {
995
var rows = list . querySelectorAll ( " [data-drop-file]" ) ;
996
var row = rows [ rows . length - 1 ] . cloneNode ( true ) ;
997
row . querySelectorAll ( " input, textarea" ) . forEach ( function ( f ) { f . value = " " ; f . textContent = " " ; } ) ;
998
list . appendChild ( row ) ;
999
wire ( row ) ;
1000
row . querySelector ( " input" ) . focus ( ) ;
1001
} ) ;
1002
} ) ( ) ;
1003
1004
1005
1006
1007
1008
( function ( ) {
1009
var nav = document . querySelector ( " [data-settings-anchors]" ) ;
1010
var hash = location . hash . slice ( 1 ) ;
1011
if ( ! nav || ! / ^ [ a-z-] + $ / . test ( hash ) ) return ;
1012
var moved = { " history-scan" : " push-protection" , " flow-priority" : " runs" , " flow-supersede" : " runs" , " agent-gates" : " gates" } ;
1013
var link = nav . querySelector ( ' a[data-slug="' + ( moved [ hash ] || hash ) + ' "]' ) ;
1014
if ( link && link . getAttribute ( " aria-current" ) !== " page" ) location . replace ( link . getAttribute ( " href" ) + " #" + hash ) ;
1015
} ) ( ) ;
119fd17d Andy McCall 19 days ago ↶
1016
} ) ( ) ;