A vibe coded tangled fork which supports pijul.
at 16f25ff5d55581ae0d83cbeac370393a081e2763 289 lines 11 kB view raw
1{{ define "repo/fragments/diff" }} 2 <style> 3 #filesToggle:checked ~ div label[for="filesToggle"] .show-text { display: none; } 4 #filesToggle:checked ~ div label[for="filesToggle"] .hide-text { display: inline; } 5 #filesToggle:not(:checked) ~ div label[for="filesToggle"] .hide-text { display: none; } 6 #filesToggle:checked ~ div div#files { width: fit-content; max-width: 15vw; } 7 #filesToggle:not(:checked) ~ div div#files { width: 0; display: none; margin-right: 0; } 8 #filesToggle:not(:checked) ~ div div#resize-files { display: none; } 9 </style> 10 11 {{ template "diffTopbar" . }} 12 {{ block "diffLayout" . }} {{ end }} 13 {{ template "fragments/resizable" }} 14 {{ template "activeFileHighlight" }} 15 {{ template "fragments/line-quote-button" }} 16{{ end }} 17 18{{ define "diffTopbar" }} 19 {{ $diff := index . 0 }} 20 {{ $opts := index . 1 }} 21 {{ $root := "" }} 22 {{ if gt (len .) 2 }} 23 {{ $root = index . 2 }} 24 {{ end }} 25 26 {{ block "filesCheckbox" $ }} {{ end }} 27 {{ block "subsCheckbox" $ }} {{ end }} 28 29 <!-- top bar --> 30 <div class="sticky top-0 z-30 bg-slate-100 dark:bg-gray-900 flex items-center gap-2 col-span-full h-12 p-2 {{ if $root }}mt-4{{ end }}"> 31 <!-- left panel toggle --> 32 {{ template "filesToggle" . }} 33 34 <!-- stats --> 35 {{ $stat := $diff.Stats }} 36 {{ $count := len $diff.ChangedFiles }} 37 {{ template "repo/fragments/diffStatPill" $stat }} 38 <span class="text-xs text-gray-600 dark:text-gray-400 hidden md:inline-flex">{{ $count }} changed file{{ if ne $count 1 }}s{{ end }}</span> 39 40 {{ if $root }} 41 {{ if $root.IsInterdiff }} 42 <!-- interdiff indicator --> 43 <div class="flex items-center gap-2 before:content-['|'] before:text-gray-300 dark:before:text-gray-600 before:mr-2"> 44 <span class="text-xs text-gray-600 dark:text-gray-400 uppercase tracking-wide">Interdiff</span> 45 <a 46 href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $root.Pull.PullId }}/round/{{ sub $root.ActiveRound 1 }}" 47 class="px-2 py-0.5 bg-white dark:bg-gray-700 rounded font-mono text-xs hover:bg-gray-50 dark:hover:bg-gray-600 border border-gray-300 dark:border-gray-600" 48 > 49 #{{ sub $root.ActiveRound 1 }} 50 </a> 51 <span class="text-gray-400 text-xs"></span> 52 <a 53 href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $root.Pull.PullId }}/round/{{ $root.ActiveRound }}" 54 class="px-2 py-0.5 bg-white dark:bg-gray-700 rounded font-mono text-xs hover:bg-gray-50 dark:hover:bg-gray-600 border border-gray-300 dark:border-gray-600" 55 > 56 #{{ $root.ActiveRound }} 57 </a> 58 </div> 59 {{ else if ne $root.ActiveRound nil }} 60 <!-- diff round indicator --> 61 <div class="flex items-center gap-2 before:content-['|'] before:text-gray-300 dark:before:text-gray-600 before:mr-2"> 62 <span class="text-xs text-gray-600 dark:text-gray-400 uppercase tracking-wide">Diff</span> 63 <span class="px-2 py-0.5 bg-white dark:bg-gray-700 rounded font-mono text-xs border border-gray-300 dark:border-gray-600"> 64 <span class="hidden md:inline">round </span>#{{ $root.ActiveRound }} 65 </span> 66 </div> 67 {{ end }} 68 {{ end }} 69 70 <!-- spacer --> 71 <div class="flex-grow"></div> 72 73 <!-- collapse diffs --> 74 {{ template "collapseToggle" }} 75 76 <!-- diff options --> 77 {{ template "repo/fragments/diffOpts" $opts }} 78 79 <!-- right panel toggle --> 80 {{ block "subsToggle" $ }} {{ end }} 81 </div> 82 83{{ end }} 84 85{{ define "resize-grip" }} 86 {{ $id := index . 0 }} 87 {{ $target := index . 1 }} 88 {{ $direction := index . 2 }} 89 <div id="{{ $id }}" 90 data-resizer="vertical" 91 data-target="{{ $target }}" 92 data-direction="{{ $direction }}" 93 class="resizer-vertical hidden md:flex w-4 sticky top-12 max-h-screen flex-col items-center justify-center group"> 94 <div class="w-1 h-16 group-hover:h-24 group-[.resizing]:h-24 transition-all rounded-full bg-gray-400 dark:bg-gray-500 group-hover:bg-gray-500 group-hover:dark:bg-gray-400"></div> 95 </div> 96{{ end }} 97 98{{ define "diffLayout" }} 99 {{ $diff := index . 0 }} 100 {{ $opts := index . 1 }} 101 102 <div class="flex col-span-full flex-grow"> 103 <!-- left panel --> 104 <div id="files" class="w-0 hidden md:block overflow-hidden sticky top-12 max-h-screen overflow-y-auto pb-12"> 105 <section class="overflow-x-auto text-sm px-6 py-2 border border-gray-200 dark:border-gray-700 w-full mx-auto min-h-full rounded bg-white dark:bg-gray-800 drop-shadow-sm"> 106 {{ template "repo/fragments/fileTree" $diff.FileTree }} 107 </section> 108 </div> 109 110 {{ template "resize-grip" (list "resize-files" "files" "before") }} 111 112 <!-- main content --> 113 <div id="diff-files" class="flex-1 min-w-0 sticky top-12 pb-12"> 114 {{ template "diffFiles" (list $diff $opts) }} 115 </div> 116 117 </div> 118{{ end }} 119 120{{ define "diffFiles" }} 121 {{ $diff := index . 0 }} 122 {{ $opts := index . 1 }} 123 {{ $files := $diff.ChangedFiles }} 124 {{ $isSplit := $opts.Split }} 125 <div class="flex flex-col gap-4"> 126 {{ if eq (len $files) 0 }} 127 <div class="text-center text-gray-500 dark:text-gray-400 py-8"> 128 <p>No differences found between the selected revisions.</p> 129 </div> 130 {{ else }} 131 {{ range $idx, $file := $files }} 132 {{ template "diffFile" (list $idx $file $isSplit) }} 133 {{ end }} 134 {{ end }} 135 </div> 136{{ end }} 137 138{{ define "diffFile" }} 139 {{ $idx := index . 0 }} 140 {{ $file := index . 1 }} 141 {{ $isSplit := index . 2 }} 142 {{ $isGenerated := false }} 143 {{ with $file }} 144 {{ $n := .Names }} 145 {{ if $n.New }} 146 {{ $isGenerated = isGenerated $n.New }} 147 {{ else if $n.Old }} 148 {{ $isGenerated = isGenerated $n.Old }} 149 {{ end }} 150 <details {{ if not $isGenerated }}open{{ end }} id="file-{{ .Id }}" class="group border border-gray-200 dark:border-gray-700 w-full mx-auto rounded bg-white dark:bg-gray-800 drop-shadow-sm" tabindex="{{ add $idx 1 }}"> 151 <summary class="list-none cursor-pointer sticky top-12 group-open:border-b border-gray-200 dark:border-gray-700"> 152 <div id="diff-file-header" class="rounded cursor-pointer bg-white dark:bg-gray-800 flex justify-between"> 153 <div id="left-side-items" class="p-2 flex gap-2 items-center overflow-x-auto"> 154 <span class="group-open:hidden inline">{{ i "chevron-right" "w-4 h-4" }}</span> 155 <span class="hidden group-open:inline">{{ i "chevron-down" "w-4 h-4" }}</span> 156 {{ template "repo/fragments/diffStatPill" .Stats }} 157 158 <div class="flex gap-2 items-center overflow-x-auto"> 159 {{ if and $n.New $n.Old (ne $n.New $n.Old)}} 160 {{ $n.Old }} {{ i "arrow-right" "w-4 h-4" }} {{ $n.New }} 161 {{ else if $n.New }} 162 {{ $n.New }} 163 {{ else }} 164 {{ $n.Old }} 165 {{ end }} 166 {{ if $isGenerated }} 167 <span class="text-gray-400 dark:text-gray-500" title="Generated files are collapsed by default"> 168 {{ i "circle-question-mark" "size-4" }} 169 </span> 170 {{ end }} 171 </div> 172 </div> 173 </div> 174 </summary> 175 176 <div class="transition-all duration-700 ease-in-out"> 177 {{ $reason := .CanRender }} 178 {{ if $reason }} 179 <p class="text-center text-gray-400 dark:text-gray-500 p-4">{{ $reason }}</p> 180 {{ else }} 181 {{ if $isSplit }} 182 {{- template "repo/fragments/splitDiff" .Split -}} 183 {{ else }} 184 {{- template "repo/fragments/unifiedDiff" . -}} 185 {{ end }} 186 {{- end -}} 187 </div> 188 </details> 189 {{ end }} 190{{ end }} 191 192{{ define "filesCheckbox" }} 193 <input type="checkbox" id="filesToggle" class="peer/files hidden" checked/> 194{{ end }} 195 196{{ define "filesToggle" }} 197 <label title="Toggle filetree panel" for="filesToggle" class="hidden md:inline-flex items-center justify-center rounded cursor-pointer text-normal font-normal normalcase"> 198 <span class="show-text">{{ i "panel-left-open" "size-4" }}</span> 199 <span class="hide-text">{{ i "panel-left-close" "size-4" }}</span> 200 </label> 201{{ end }} 202 203{{ define "collapseToggle" }} 204 <label 205 title="Expand/Collapse diffs" 206 for="collapseToggle" 207 class="btn font-normal normal-case p-2" 208 > 209 <input type="checkbox" id="collapseToggle" class="peer/collapse hidden" checked/> 210 <span class="peer-checked/collapse:hidden inline-flex items-center gap-2"> 211 {{ i "fold-vertical" "w-4 h-4" }} 212 <span class="hidden md:inline">expand all</span> 213 </span> 214 <span class="peer-checked/collapse:inline-flex hidden flex items-center gap-2"> 215 {{ i "unfold-vertical" "w-4 h-4" }} 216 <span class="hidden md:inline">collapse all</span> 217 </span> 218 </label> 219 <script> 220 document.addEventListener('DOMContentLoaded', function() { 221 const checkbox = document.getElementById('collapseToggle'); 222 const details = document.querySelectorAll('details[id^="file-"]'); 223 224 checkbox.addEventListener('change', function() { 225 details.forEach(detail => { 226 detail.open = checkbox.checked; 227 }); 228 }); 229 230 details.forEach(detail => { 231 detail.addEventListener('toggle', function() { 232 const allOpen = Array.from(details).every(d => d.open); 233 const allClosed = Array.from(details).every(d => !d.open); 234 235 if (allOpen) { 236 checkbox.checked = true; 237 } else if (allClosed) { 238 checkbox.checked = false; 239 } 240 }); 241 }); 242 }); 243 </script> 244{{ end }} 245 246{{ define "activeFileHighlight" }} 247 <script> 248 document.addEventListener('DOMContentLoaded', function() { 249 const diffFiles = document.querySelectorAll('details[id^="file-"]'); 250 const filetreeLinks = document.querySelectorAll('.filetree-link'); 251 if (diffFiles.length === 0 || filetreeLinks.length === 0) return; 252 253 const linkMap = new Map(); 254 filetreeLinks.forEach(link => { 255 const path = link.getAttribute('data-path'); 256 if (path) linkMap.set('file-' + path, link); 257 }); 258 259 let currentActive = null; 260 function setActive(link) { 261 if (link && link !== currentActive) { 262 if (currentActive) currentActive.classList.remove('font-bold'); 263 link.classList.add('font-bold'); 264 currentActive = link; 265 } 266 } 267 268 filetreeLinks.forEach(link => { 269 link.addEventListener('click', () => setActive(link)); 270 }); 271 272 const topbar = document.querySelector('.sticky.top-0.z-30'); 273 const headerHeight = topbar ? topbar.offsetHeight : 0; 274 275 function updateActiveFile() { 276 for (const file of diffFiles) { 277 const rect = file.getBoundingClientRect(); 278 if (rect.top <= headerHeight && rect.bottom > headerHeight) { 279 setActive(linkMap.get(file.id)); 280 return; 281 } 282 } 283 } 284 285 document.addEventListener('scroll', updateActiveFile); 286 updateActiveFile(); 287 }); 288 </script> 289{{ end }}