feat(web): show the latest tag in its own summary rail block
- commit
- 08e63884b6d8316c4c508c604d5fcdfdd75f48bc
- author
- brice · · 2026-10-11 12:46 UTC
- parent
- 5e5d8fb
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
37 files · +500 -297
M cmd/ermite/testdata/web/blob-binary.html +4 -4
| @@ -209,7 +209,7 @@ | |||
| 209 | 209 | <kbd>u</kbd> | |
| 210 | 210 | <kbd>x</kbd> | |
| 211 | 211 | </dt> | |
| 212 | - | <dd>diff: split / unified / collapse all</dd> | |
| 212 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 213 | 213 | </div> | |
| 214 | 214 | <div> | |
| 215 | 215 | <dt> | |
| @@ -383,9 +383,9 @@ | |||
| 383 | 383 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 384 | 384 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 385 | 385 | }; | |
| 386 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 387 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 388 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 386 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 387 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 388 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 389 | 389 | k-permalink from:body -> { | |
| 390 | 390 | let b = document.body.dataset; | |
| 391 | 391 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -209,7 +209,7 @@ | |||||
| 209 | <kbd>u</kbd> | 209 | <kbd>u</kbd> | ||
| 210 | <kbd>x</kbd> | 210 | <kbd>x</kbd> | ||
| 211 | </dt> | 211 | </dt> | ||
| 212 | - | <dd>diff: split / unified / collapse all</dd> | 212 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 213 | </div> | 213 | </div> | ||
| 214 | <div> | 214 | <div> | ||
| 215 | <dt> | 215 | <dt> | ||
| @@ -383,9 +383,9 @@ | |||||
| 383 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 383 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 384 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 384 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 385 | }; | 385 | }; | ||
| 386 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 386 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 387 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 387 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 388 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 388 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 389 | k-permalink from:body -> { | 389 | k-permalink from:body -> { | ||
| 390 | let b = document.body.dataset; | 390 | let b = document.body.dataset; | ||
| 391 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 391 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/blob-code.html +4 -4
| @@ -279,7 +279,7 @@ | |||
| 279 | 279 | <kbd>u</kbd> | |
| 280 | 280 | <kbd>x</kbd> | |
| 281 | 281 | </dt> | |
| 282 | - | <dd>diff: split / unified / collapse all</dd> | |
| 282 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 283 | 283 | </div> | |
| 284 | 284 | <div> | |
| 285 | 285 | <dt> | |
| @@ -453,9 +453,9 @@ | |||
| 453 | 453 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 454 | 454 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 455 | 455 | }; | |
| 456 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 457 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 458 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 456 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 457 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 458 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 459 | 459 | k-permalink from:body -> { | |
| 460 | 460 | let b = document.body.dataset; | |
| 461 | 461 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -279,7 +279,7 @@ | |||||
| 279 | <kbd>u</kbd> | 279 | <kbd>u</kbd> | ||
| 280 | <kbd>x</kbd> | 280 | <kbd>x</kbd> | ||
| 281 | </dt> | 281 | </dt> | ||
| 282 | - | <dd>diff: split / unified / collapse all</dd> | 282 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 283 | </div> | 283 | </div> | ||
| 284 | <div> | 284 | <div> | ||
| 285 | <dt> | 285 | <dt> | ||
| @@ -453,9 +453,9 @@ | |||||
| 453 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 453 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 454 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 454 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 455 | }; | 455 | }; | ||
| 456 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 456 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 457 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 457 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 458 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 458 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 459 | k-permalink from:body -> { | 459 | k-permalink from:body -> { | ||
| 460 | let b = document.body.dataset; | 460 | let b = document.body.dataset; | ||
| 461 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 461 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/blob-empty.html +4 -4
| @@ -209,7 +209,7 @@ | |||
| 209 | 209 | <kbd>u</kbd> | |
| 210 | 210 | <kbd>x</kbd> | |
| 211 | 211 | </dt> | |
| 212 | - | <dd>diff: split / unified / collapse all</dd> | |
| 212 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 213 | 213 | </div> | |
| 214 | 214 | <div> | |
| 215 | 215 | <dt> | |
| @@ -383,9 +383,9 @@ | |||
| 383 | 383 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 384 | 384 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 385 | 385 | }; | |
| 386 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 387 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 388 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 386 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 387 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 388 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 389 | 389 | k-permalink from:body -> { | |
| 390 | 390 | let b = document.body.dataset; | |
| 391 | 391 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -209,7 +209,7 @@ | |||||
| 209 | <kbd>u</kbd> | 209 | <kbd>u</kbd> | ||
| 210 | <kbd>x</kbd> | 210 | <kbd>x</kbd> | ||
| 211 | </dt> | 211 | </dt> | ||
| 212 | - | <dd>diff: split / unified / collapse all</dd> | 212 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 213 | </div> | 213 | </div> | ||
| 214 | <div> | 214 | <div> | ||
| 215 | <dt> | 215 | <dt> | ||
| @@ -383,9 +383,9 @@ | |||||
| 383 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 383 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 384 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 384 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 385 | }; | 385 | }; | ||
| 386 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 386 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 387 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 387 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 388 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 388 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 389 | k-permalink from:body -> { | 389 | k-permalink from:body -> { | ||
| 390 | let b = document.body.dataset; | 390 | let b = document.body.dataset; | ||
| 391 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 391 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/blob-image.html +4 -4
| @@ -211,7 +211,7 @@ | |||
| 211 | 211 | <kbd>u</kbd> | |
| 212 | 212 | <kbd>x</kbd> | |
| 213 | 213 | </dt> | |
| 214 | - | <dd>diff: split / unified / collapse all</dd> | |
| 214 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 215 | 215 | </div> | |
| 216 | 216 | <div> | |
| 217 | 217 | <dt> | |
| @@ -385,9 +385,9 @@ | |||
| 385 | 385 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 386 | 386 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 387 | 387 | }; | |
| 388 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 389 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 390 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 388 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 389 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 390 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 391 | 391 | k-permalink from:body -> { | |
| 392 | 392 | let b = document.body.dataset; | |
| 393 | 393 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -211,7 +211,7 @@ | |||||
| 211 | <kbd>u</kbd> | 211 | <kbd>u</kbd> | ||
| 212 | <kbd>x</kbd> | 212 | <kbd>x</kbd> | ||
| 213 | </dt> | 213 | </dt> | ||
| 214 | - | <dd>diff: split / unified / collapse all</dd> | 214 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 215 | </div> | 215 | </div> | ||
| 216 | <div> | 216 | <div> | ||
| 217 | <dt> | 217 | <dt> | ||
| @@ -385,9 +385,9 @@ | |||||
| 385 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 385 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 386 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 386 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 387 | }; | 387 | }; | ||
| 388 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 388 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 389 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 389 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 390 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 390 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 391 | k-permalink from:body -> { | 391 | k-permalink from:body -> { | ||
| 392 | let b = document.body.dataset; | 392 | let b = document.body.dataset; | ||
| 393 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 393 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/blob-markdown.html +4 -4
| @@ -276,7 +276,7 @@ | |||
| 276 | 276 | <kbd>u</kbd> | |
| 277 | 277 | <kbd>x</kbd> | |
| 278 | 278 | </dt> | |
| 279 | - | <dd>diff: split / unified / collapse all</dd> | |
| 279 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 280 | 280 | </div> | |
| 281 | 281 | <div> | |
| 282 | 282 | <dt> | |
| @@ -450,9 +450,9 @@ | |||
| 450 | 450 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 451 | 451 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 452 | 452 | }; | |
| 453 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 454 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 455 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 453 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 454 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 455 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 456 | 456 | k-permalink from:body -> { | |
| 457 | 457 | let b = document.body.dataset; | |
| 458 | 458 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -276,7 +276,7 @@ | |||||
| 276 | <kbd>u</kbd> | 276 | <kbd>u</kbd> | ||
| 277 | <kbd>x</kbd> | 277 | <kbd>x</kbd> | ||
| 278 | </dt> | 278 | </dt> | ||
| 279 | - | <dd>diff: split / unified / collapse all</dd> | 279 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 280 | </div> | 280 | </div> | ||
| 281 | <div> | 281 | <div> | ||
| 282 | <dt> | 282 | <dt> | ||
| @@ -450,9 +450,9 @@ | |||||
| 450 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 450 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 451 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 451 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 452 | }; | 452 | }; | ||
| 453 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 453 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 454 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 454 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 455 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 455 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 456 | k-permalink from:body -> { | 456 | k-permalink from:body -> { | ||
| 457 | let b = document.body.dataset; | 457 | let b = document.body.dataset; | ||
| 458 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 458 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/blob-svg.html +4 -4
| @@ -234,7 +234,7 @@ | |||
| 234 | 234 | <kbd>u</kbd> | |
| 235 | 235 | <kbd>x</kbd> | |
| 236 | 236 | </dt> | |
| 237 | - | <dd>diff: split / unified / collapse all</dd> | |
| 237 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 238 | 238 | </div> | |
| 239 | 239 | <div> | |
| 240 | 240 | <dt> | |
| @@ -408,9 +408,9 @@ | |||
| 408 | 408 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 409 | 409 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 410 | 410 | }; | |
| 411 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 412 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 413 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 411 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 412 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 413 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 414 | 414 | k-permalink from:body -> { | |
| 415 | 415 | let b = document.body.dataset; | |
| 416 | 416 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -234,7 +234,7 @@ | |||||
| 234 | <kbd>u</kbd> | 234 | <kbd>u</kbd> | ||
| 235 | <kbd>x</kbd> | 235 | <kbd>x</kbd> | ||
| 236 | </dt> | 236 | </dt> | ||
| 237 | - | <dd>diff: split / unified / collapse all</dd> | 237 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 238 | </div> | 238 | </div> | ||
| 239 | <div> | 239 | <div> | ||
| 240 | <dt> | 240 | <dt> | ||
| @@ -408,9 +408,9 @@ | |||||
| 408 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 408 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 409 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 409 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 410 | }; | 410 | }; | ||
| 411 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 411 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 412 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 412 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 413 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 413 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 414 | k-permalink from:body -> { | 414 | k-permalink from:body -> { | ||
| 415 | let b = document.body.dataset; | 415 | let b = document.body.dataset; | ||
| 416 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 416 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/blob-text.html +4 -4
| @@ -229,7 +229,7 @@ | |||
| 229 | 229 | <kbd>u</kbd> | |
| 230 | 230 | <kbd>x</kbd> | |
| 231 | 231 | </dt> | |
| 232 | - | <dd>diff: split / unified / collapse all</dd> | |
| 232 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 233 | 233 | </div> | |
| 234 | 234 | <div> | |
| 235 | 235 | <dt> | |
| @@ -403,9 +403,9 @@ | |||
| 403 | 403 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 404 | 404 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 405 | 405 | }; | |
| 406 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 407 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 408 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 406 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 407 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 408 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 409 | 409 | k-permalink from:body -> { | |
| 410 | 410 | let b = document.body.dataset; | |
| 411 | 411 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -229,7 +229,7 @@ | |||||
| 229 | <kbd>u</kbd> | 229 | <kbd>u</kbd> | ||
| 230 | <kbd>x</kbd> | 230 | <kbd>x</kbd> | ||
| 231 | </dt> | 231 | </dt> | ||
| 232 | - | <dd>diff: split / unified / collapse all</dd> | 232 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 233 | </div> | 233 | </div> | ||
| 234 | <div> | 234 | <div> | ||
| 235 | <dt> | 235 | <dt> | ||
| @@ -403,9 +403,9 @@ | |||||
| 403 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 403 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 404 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 404 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 405 | }; | 405 | }; | ||
| 406 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 406 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 407 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 407 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 408 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 408 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 409 | k-permalink from:body -> { | 409 | k-permalink from:body -> { | ||
| 410 | let b = document.body.dataset; | 410 | let b = document.body.dataset; | ||
| 411 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 411 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/blob-too-large.html +4 -4
| @@ -209,7 +209,7 @@ | |||
| 209 | 209 | <kbd>u</kbd> | |
| 210 | 210 | <kbd>x</kbd> | |
| 211 | 211 | </dt> | |
| 212 | - | <dd>diff: split / unified / collapse all</dd> | |
| 212 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 213 | 213 | </div> | |
| 214 | 214 | <div> | |
| 215 | 215 | <dt> | |
| @@ -383,9 +383,9 @@ | |||
| 383 | 383 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 384 | 384 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 385 | 385 | }; | |
| 386 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 387 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 388 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 386 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 387 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 388 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 389 | 389 | k-permalink from:body -> { | |
| 390 | 390 | let b = document.body.dataset; | |
| 391 | 391 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -209,7 +209,7 @@ | |||||
| 209 | <kbd>u</kbd> | 209 | <kbd>u</kbd> | ||
| 210 | <kbd>x</kbd> | 210 | <kbd>x</kbd> | ||
| 211 | </dt> | 211 | </dt> | ||
| 212 | - | <dd>diff: split / unified / collapse all</dd> | 212 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 213 | </div> | 213 | </div> | ||
| 214 | <div> | 214 | <div> | ||
| 215 | <dt> | 215 | <dt> | ||
| @@ -383,9 +383,9 @@ | |||||
| 383 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 383 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 384 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 384 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 385 | }; | 385 | }; | ||
| 386 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 386 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 387 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 387 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 388 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 388 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 389 | k-permalink from:body -> { | 389 | k-permalink from:body -> { | ||
| 390 | let b = document.body.dataset; | 390 | let b = document.body.dataset; | ||
| 391 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 391 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/blob-trojan.html +4 -4
| @@ -276,7 +276,7 @@ | |||
| 276 | 276 | <kbd>u</kbd> | |
| 277 | 277 | <kbd>x</kbd> | |
| 278 | 278 | </dt> | |
| 279 | - | <dd>diff: split / unified / collapse all</dd> | |
| 279 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 280 | 280 | </div> | |
| 281 | 281 | <div> | |
| 282 | 282 | <dt> | |
| @@ -450,9 +450,9 @@ | |||
| 450 | 450 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 451 | 451 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 452 | 452 | }; | |
| 453 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 454 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 455 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 453 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 454 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 455 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 456 | 456 | k-permalink from:body -> { | |
| 457 | 457 | let b = document.body.dataset; | |
| 458 | 458 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -276,7 +276,7 @@ | |||||
| 276 | <kbd>u</kbd> | 276 | <kbd>u</kbd> | ||
| 277 | <kbd>x</kbd> | 277 | <kbd>x</kbd> | ||
| 278 | </dt> | 278 | </dt> | ||
| 279 | - | <dd>diff: split / unified / collapse all</dd> | 279 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 280 | </div> | 280 | </div> | ||
| 281 | <div> | 281 | <div> | ||
| 282 | <dt> | 282 | <dt> | ||
| @@ -450,9 +450,9 @@ | |||||
| 450 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 450 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 451 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 451 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 452 | }; | 452 | }; | ||
| 453 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 453 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 454 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 454 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 455 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 455 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 456 | k-permalink from:body -> { | 456 | k-permalink from:body -> { | ||
| 457 | let b = document.body.dataset; | 457 | let b = document.body.dataset; | ||
| 458 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 458 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/commit-big.html +7 -5
| @@ -109,7 +109,9 @@ | |||
| 109 | 109 | </a> | |
| 110 | 110 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | |
| 111 | 111 | </a> | |
| 112 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | |
| 112 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> | |
| 113 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |
| 114 | + | <kbd aria-hidden="true">x</kbd> | |
| 113 | 115 | </button> | |
| 114 | 116 | </div> | |
| 115 | 117 | <p class="notice">this diff is incomplete: 1 file is too large to show. the totals above count everything; clone the repository to read the rest.</p> | |
| @@ -244,7 +246,7 @@ | |||
| 244 | 246 | <kbd>u</kbd> | |
| 245 | 247 | <kbd>x</kbd> | |
| 246 | 248 | </dt> | |
| 247 | - | <dd>diff: split / unified / collapse all</dd> | |
| 249 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 248 | 250 | </div> | |
| 249 | 251 | <div> | |
| 250 | 252 | <dt> | |
| @@ -418,9 +420,9 @@ | |||
| 418 | 420 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 419 | 421 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 420 | 422 | }; | |
| 421 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 422 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 423 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 423 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 424 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 425 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 424 | 426 | k-permalink from:body -> { | |
| 425 | 427 | let b = document.body.dataset; | |
| 426 | 428 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -109,7 +109,9 @@ | |||||
| 109 | </a> | 109 | </a> | ||
| 110 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | 110 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | ||
| 111 | </a> | 111 | </a> | ||
| 112 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | 112 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> |
| 113 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |||
| 114 | + | <kbd aria-hidden="true">x</kbd> | |||
| 113 | </button> | 115 | </button> | ||
| 114 | </div> | 116 | </div> | ||
| 115 | <p class="notice">this diff is incomplete: 1 file is too large to show. the totals above count everything; clone the repository to read the rest.</p> | 117 | <p class="notice">this diff is incomplete: 1 file is too large to show. the totals above count everything; clone the repository to read the rest.</p> | ||
| @@ -244,7 +246,7 @@ | |||||
| 244 | <kbd>u</kbd> | 246 | <kbd>u</kbd> | ||
| 245 | <kbd>x</kbd> | 247 | <kbd>x</kbd> | ||
| 246 | </dt> | 248 | </dt> | ||
| 247 | - | <dd>diff: split / unified / collapse all</dd> | 249 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 248 | </div> | 250 | </div> | ||
| 249 | <div> | 251 | <div> | ||
| 250 | <dt> | 252 | <dt> | ||
| @@ -418,9 +420,9 @@ | |||||
| 418 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 420 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 419 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 421 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 420 | }; | 422 | }; | ||
| 421 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 423 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 422 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 424 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 423 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 425 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 424 | k-permalink from:body -> { | 426 | k-permalink from:body -> { | ||
| 425 | let b = document.body.dataset; | 427 | let b = document.body.dataset; | ||
| 426 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 428 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/commit-binary.html +7 -5
| @@ -105,7 +105,9 @@ | |||
| 105 | 105 | </a> | |
| 106 | 106 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | |
| 107 | 107 | </a> | |
| 108 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | |
| 108 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> | |
| 109 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |
| 110 | + | <kbd aria-hidden="true">x</kbd> | |
| 109 | 111 | </button> | |
| 110 | 112 | </div> | |
| 111 | 113 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | |
| @@ -239,7 +241,7 @@ | |||
| 239 | 241 | <kbd>u</kbd> | |
| 240 | 242 | <kbd>x</kbd> | |
| 241 | 243 | </dt> | |
| 242 | - | <dd>diff: split / unified / collapse all</dd> | |
| 244 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 243 | 245 | </div> | |
| 244 | 246 | <div> | |
| 245 | 247 | <dt> | |
| @@ -413,9 +415,9 @@ | |||
| 413 | 415 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 414 | 416 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 415 | 417 | }; | |
| 416 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 417 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 418 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 418 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 419 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 420 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 419 | 421 | k-permalink from:body -> { | |
| 420 | 422 | let b = document.body.dataset; | |
| 421 | 423 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -105,7 +105,9 @@ | |||||
| 105 | </a> | 105 | </a> | ||
| 106 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | 106 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | ||
| 107 | </a> | 107 | </a> | ||
| 108 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | 108 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> |
| 109 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |||
| 110 | + | <kbd aria-hidden="true">x</kbd> | |||
| 109 | </button> | 111 | </button> | ||
| 110 | </div> | 112 | </div> | ||
| 111 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | 113 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | ||
| @@ -239,7 +241,7 @@ | |||||
| 239 | <kbd>u</kbd> | 241 | <kbd>u</kbd> | ||
| 240 | <kbd>x</kbd> | 242 | <kbd>x</kbd> | ||
| 241 | </dt> | 243 | </dt> | ||
| 242 | - | <dd>diff: split / unified / collapse all</dd> | 244 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 243 | </div> | 245 | </div> | ||
| 244 | <div> | 246 | <div> | ||
| 245 | <dt> | 247 | <dt> | ||
| @@ -413,9 +415,9 @@ | |||||
| 413 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 415 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 414 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 416 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 415 | }; | 417 | }; | ||
| 416 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 418 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 417 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 419 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 418 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 420 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 419 | k-permalink from:body -> { | 421 | k-permalink from:body -> { | ||
| 420 | let b = document.body.dataset; | 422 | let b = document.body.dataset; | ||
| 421 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 423 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/commit-merge.html +7 -5
| @@ -104,7 +104,9 @@ | |||
| 104 | 104 | </a> | |
| 105 | 105 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | |
| 106 | 106 | </a> | |
| 107 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | |
| 107 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> | |
| 108 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |
| 109 | + | <kbd aria-hidden="true">x</kbd> | |
| 108 | 110 | </button> | |
| 109 | 111 | </div> | |
| 110 | 112 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | |
| @@ -278,7 +280,7 @@ | |||
| 278 | 280 | <kbd>u</kbd> | |
| 279 | 281 | <kbd>x</kbd> | |
| 280 | 282 | </dt> | |
| 281 | - | <dd>diff: split / unified / collapse all</dd> | |
| 283 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 282 | 284 | </div> | |
| 283 | 285 | <div> | |
| 284 | 286 | <dt> | |
| @@ -452,9 +454,9 @@ | |||
| 452 | 454 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 453 | 455 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 454 | 456 | }; | |
| 455 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 456 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 457 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 457 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 458 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 459 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 458 | 460 | k-permalink from:body -> { | |
| 459 | 461 | let b = document.body.dataset; | |
| 460 | 462 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -104,7 +104,9 @@ | |||||
| 104 | </a> | 104 | </a> | ||
| 105 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | 105 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | ||
| 106 | </a> | 106 | </a> | ||
| 107 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | 107 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> |
| 108 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |||
| 109 | + | <kbd aria-hidden="true">x</kbd> | |||
| 108 | </button> | 110 | </button> | ||
| 109 | </div> | 111 | </div> | ||
| 110 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | 112 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | ||
| @@ -278,7 +280,7 @@ | |||||
| 278 | <kbd>u</kbd> | 280 | <kbd>u</kbd> | ||
| 279 | <kbd>x</kbd> | 281 | <kbd>x</kbd> | ||
| 280 | </dt> | 282 | </dt> | ||
| 281 | - | <dd>diff: split / unified / collapse all</dd> | 283 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 282 | </div> | 284 | </div> | ||
| 283 | <div> | 285 | <div> | ||
| 284 | <dt> | 286 | <dt> | ||
| @@ -452,9 +454,9 @@ | |||||
| 452 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 454 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 453 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 455 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 454 | }; | 456 | }; | ||
| 455 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 457 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 456 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 458 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 457 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 459 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 458 | k-permalink from:body -> { | 460 | k-permalink from:body -> { | ||
| 459 | let b = document.body.dataset; | 461 | let b = document.body.dataset; | ||
| 460 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 462 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/commit-modify-split.html +7 -5
| @@ -111,7 +111,9 @@ And <b>html</b> & "quotes".</pre> | |||
| 111 | 111 | </a> | |
| 112 | 112 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" aria-current="true" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | |
| 113 | 113 | </a> | |
| 114 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | |
| 114 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> | |
| 115 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |
| 116 | + | <kbd aria-hidden="true">x</kbd> | |
| 115 | 117 | </button> | |
| 116 | 118 | </div> | |
| 117 | 119 | <div id="diffs" data-diff="split"> | |
| @@ -399,7 +401,7 @@ And <b>html</b> & "quotes".</pre> | |||
| 399 | 401 | <kbd>u</kbd> | |
| 400 | 402 | <kbd>x</kbd> | |
| 401 | 403 | </dt> | |
| 402 | - | <dd>diff: split / unified / collapse all</dd> | |
| 404 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 403 | 405 | </div> | |
| 404 | 406 | <div> | |
| 405 | 407 | <dt> | |
| @@ -573,9 +575,9 @@ And <b>html</b> & "quotes".</pre> | |||
| 573 | 575 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 574 | 576 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 575 | 577 | }; | |
| 576 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 577 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 578 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 578 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 579 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 580 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 579 | 581 | k-permalink from:body -> { | |
| 580 | 582 | let b = document.body.dataset; | |
| 581 | 583 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -111,7 +111,9 @@ And <b>html</b> & "quotes".</pre> | |||||
| 111 | </a> | 111 | </a> | ||
| 112 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" aria-current="true" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | 112 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" aria-current="true" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | ||
| 113 | </a> | 113 | </a> | ||
| 114 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | 114 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> |
| 115 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |||
| 116 | + | <kbd aria-hidden="true">x</kbd> | |||
| 115 | </button> | 117 | </button> | ||
| 116 | </div> | 118 | </div> | ||
| 117 | <div id="diffs" data-diff="split"> | 119 | <div id="diffs" data-diff="split"> | ||
| @@ -399,7 +401,7 @@ And <b>html</b> & "quotes".</pre> | |||||
| 399 | <kbd>u</kbd> | 401 | <kbd>u</kbd> | ||
| 400 | <kbd>x</kbd> | 402 | <kbd>x</kbd> | ||
| 401 | </dt> | 403 | </dt> | ||
| 402 | - | <dd>diff: split / unified / collapse all</dd> | 404 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 403 | </div> | 405 | </div> | ||
| 404 | <div> | 406 | <div> | ||
| 405 | <dt> | 407 | <dt> | ||
| @@ -573,9 +575,9 @@ And <b>html</b> & "quotes".</pre> | |||||
| 573 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 575 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 574 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 576 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 575 | }; | 577 | }; | ||
| 576 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 578 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 577 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 579 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 578 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 580 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 579 | k-permalink from:body -> { | 581 | k-permalink from:body -> { | ||
| 580 | let b = document.body.dataset; | 582 | let b = document.body.dataset; | ||
| 581 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 583 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/commit-modify.html +7 -5
| @@ -111,7 +111,9 @@ And <b>html</b> & "quotes".</pre> | |||
| 111 | 111 | </a> | |
| 112 | 112 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | |
| 113 | 113 | </a> | |
| 114 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | |
| 114 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> | |
| 115 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |
| 116 | + | <kbd aria-hidden="true">x</kbd> | |
| 115 | 117 | </button> | |
| 116 | 118 | </div> | |
| 117 | 119 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | |
| @@ -399,7 +401,7 @@ And <b>html</b> & "quotes".</pre> | |||
| 399 | 401 | <kbd>u</kbd> | |
| 400 | 402 | <kbd>x</kbd> | |
| 401 | 403 | </dt> | |
| 402 | - | <dd>diff: split / unified / collapse all</dd> | |
| 404 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 403 | 405 | </div> | |
| 404 | 406 | <div> | |
| 405 | 407 | <dt> | |
| @@ -573,9 +575,9 @@ And <b>html</b> & "quotes".</pre> | |||
| 573 | 575 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 574 | 576 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 575 | 577 | }; | |
| 576 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 577 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 578 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 578 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 579 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 580 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 579 | 581 | k-permalink from:body -> { | |
| 580 | 582 | let b = document.body.dataset; | |
| 581 | 583 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -111,7 +111,9 @@ And <b>html</b> & "quotes".</pre> | |||||
| 111 | </a> | 111 | </a> | ||
| 112 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | 112 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | ||
| 113 | </a> | 113 | </a> | ||
| 114 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | 114 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> |
| 115 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |||
| 116 | + | <kbd aria-hidden="true">x</kbd> | |||
| 115 | </button> | 117 | </button> | ||
| 116 | </div> | 118 | </div> | ||
| 117 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | 119 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | ||
| @@ -399,7 +401,7 @@ And <b>html</b> & "quotes".</pre> | |||||
| 399 | <kbd>u</kbd> | 401 | <kbd>u</kbd> | ||
| 400 | <kbd>x</kbd> | 402 | <kbd>x</kbd> | ||
| 401 | </dt> | 403 | </dt> | ||
| 402 | - | <dd>diff: split / unified / collapse all</dd> | 404 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 403 | </div> | 405 | </div> | ||
| 404 | <div> | 406 | <div> | ||
| 405 | <dt> | 407 | <dt> | ||
| @@ -573,9 +575,9 @@ And <b>html</b> & "quotes".</pre> | |||||
| 573 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 575 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 574 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 576 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 575 | }; | 577 | }; | ||
| 576 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 578 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 577 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 579 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 578 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 580 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 579 | k-permalink from:body -> { | 581 | k-permalink from:body -> { | ||
| 580 | let b = document.body.dataset; | 582 | let b = document.body.dataset; | ||
| 581 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 583 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/commit-rename.html +7 -5
| @@ -105,7 +105,9 @@ | |||
| 105 | 105 | </a> | |
| 106 | 106 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | |
| 107 | 107 | </a> | |
| 108 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | |
| 108 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> | |
| 109 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |
| 110 | + | <kbd aria-hidden="true">x</kbd> | |
| 109 | 111 | </button> | |
| 110 | 112 | </div> | |
| 111 | 113 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | |
| @@ -304,7 +306,7 @@ | |||
| 304 | 306 | <kbd>u</kbd> | |
| 305 | 307 | <kbd>x</kbd> | |
| 306 | 308 | </dt> | |
| 307 | - | <dd>diff: split / unified / collapse all</dd> | |
| 309 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 308 | 310 | </div> | |
| 309 | 311 | <div> | |
| 310 | 312 | <dt> | |
| @@ -478,9 +480,9 @@ | |||
| 478 | 480 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 479 | 481 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 480 | 482 | }; | |
| 481 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 482 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 483 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 483 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 484 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 485 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 484 | 486 | k-permalink from:body -> { | |
| 485 | 487 | let b = document.body.dataset; | |
| 486 | 488 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -105,7 +105,9 @@ | |||||
| 105 | </a> | 105 | </a> | ||
| 106 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | 106 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | ||
| 107 | </a> | 107 | </a> | ||
| 108 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | 108 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> |
| 109 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |||
| 110 | + | <kbd aria-hidden="true">x</kbd> | |||
| 109 | </button> | 111 | </button> | ||
| 110 | </div> | 112 | </div> | ||
| 111 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | 113 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | ||
| @@ -304,7 +306,7 @@ | |||||
| 304 | <kbd>u</kbd> | 306 | <kbd>u</kbd> | ||
| 305 | <kbd>x</kbd> | 307 | <kbd>x</kbd> | ||
| 306 | </dt> | 308 | </dt> | ||
| 307 | - | <dd>diff: split / unified / collapse all</dd> | 309 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 308 | </div> | 310 | </div> | ||
| 309 | <div> | 311 | <div> | ||
| 310 | <dt> | 312 | <dt> | ||
| @@ -478,9 +480,9 @@ | |||||
| 478 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 480 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 479 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 481 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 480 | }; | 482 | }; | ||
| 481 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 483 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 482 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 484 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 483 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 485 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 484 | k-permalink from:body -> { | 486 | k-permalink from:body -> { | ||
| 485 | let b = document.body.dataset; | 487 | let b = document.body.dataset; | ||
| 486 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 488 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/commit-root.html +7 -5
| @@ -103,7 +103,9 @@ | |||
| 103 | 103 | </a> | |
| 104 | 104 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | |
| 105 | 105 | </a> | |
| 106 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | |
| 106 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> | |
| 107 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |
| 108 | + | <kbd aria-hidden="true">x</kbd> | |
| 107 | 109 | </button> | |
| 108 | 110 | </div> | |
| 109 | 111 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | |
| @@ -620,7 +622,7 @@ | |||
| 620 | 622 | <kbd>u</kbd> | |
| 621 | 623 | <kbd>x</kbd> | |
| 622 | 624 | </dt> | |
| 623 | - | <dd>diff: split / unified / collapse all</dd> | |
| 625 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 624 | 626 | </div> | |
| 625 | 627 | <div> | |
| 626 | 628 | <dt> | |
| @@ -794,9 +796,9 @@ | |||
| 794 | 796 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 795 | 797 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 796 | 798 | }; | |
| 797 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 798 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 799 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 799 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 800 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 801 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 800 | 802 | k-permalink from:body -> { | |
| 801 | 803 | let b = document.body.dataset; | |
| 802 | 804 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -103,7 +103,9 @@ | |||||
| 103 | </a> | 103 | </a> | ||
| 104 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | 104 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | ||
| 105 | </a> | 105 | </a> | ||
| 106 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | 106 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> |
| 107 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |||
| 108 | + | <kbd aria-hidden="true">x</kbd> | |||
| 107 | </button> | 109 | </button> | ||
| 108 | </div> | 110 | </div> | ||
| 109 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | 111 | <div id="diffs" data-diff="unified" hx-live="this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff"> | ||
| @@ -620,7 +622,7 @@ | |||||
| 620 | <kbd>u</kbd> | 622 | <kbd>u</kbd> | ||
| 621 | <kbd>x</kbd> | 623 | <kbd>x</kbd> | ||
| 622 | </dt> | 624 | </dt> | ||
| 623 | - | <dd>diff: split / unified / collapse all</dd> | 625 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 624 | </div> | 626 | </div> | ||
| 625 | <div> | 627 | <div> | ||
| 626 | <dt> | 628 | <dt> | ||
| @@ -794,9 +796,9 @@ | |||||
| 794 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 796 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 795 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 797 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 796 | }; | 798 | }; | ||
| 797 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 799 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 798 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 800 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 799 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 801 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 800 | k-permalink from:body -> { | 802 | k-permalink from:body -> { | ||
| 801 | let b = document.body.dataset; | 803 | let b = document.body.dataset; | ||
| 802 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 804 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/commit-trojan.html +7 -5
| @@ -106,7 +106,9 @@ | |||
| 106 | 106 | </a> | |
| 107 | 107 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | |
| 108 | 108 | </a> | |
| 109 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | |
| 109 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> | |
| 110 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |
| 111 | + | <kbd aria-hidden="true">x</kbd> | |
| 110 | 112 | </button> | |
| 111 | 113 | </div> | |
| 112 | 114 | <p class="notice">this diff holds invisible characters (direction controls, zero-width characters). They are shown as <span class="inv"><U+XXXX></span> markers, never applied.</p> | |
| @@ -413,7 +415,7 @@ | |||
| 413 | 415 | <kbd>u</kbd> | |
| 414 | 416 | <kbd>x</kbd> | |
| 415 | 417 | </dt> | |
| 416 | - | <dd>diff: split / unified / collapse all</dd> | |
| 418 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 417 | 419 | </div> | |
| 418 | 420 | <div> | |
| 419 | 421 | <dt> | |
| @@ -587,9 +589,9 @@ | |||
| 587 | 589 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 588 | 590 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 589 | 591 | }; | |
| 590 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 591 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 592 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 592 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 593 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 594 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 593 | 595 | k-permalink from:body -> { | |
| 594 | 596 | let b = document.body.dataset; | |
| 595 | 597 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -106,7 +106,9 @@ | |||||
| 106 | </a> | 106 | </a> | ||
| 107 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | 107 | <a href="/diffs/commit/SHA40?view=split" class="btn vbtn" data-view="split" aria-keyshortcuts="d" hx-on:click="event.preventDefault(); document.body.dispatchEvent(new CustomEvent('k-' + this.dataset.view))" :aria-current="q('#diffs').attr['data-diff'] === 'split' ? 'true' : false">Split<kbd aria-hidden="true">d</kbd> | ||
| 108 | </a> | 108 | </a> | ||
| 109 | - | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn">Collapse all<kbd aria-hidden="true">x</kbd> | 109 | + | <button type="button" aria-keyshortcuts="x" hx-on:click="document.body.dispatchEvent(new CustomEvent('k-collapse'))" class="btn"> |
| 110 | + | <span hx-live="this.textContent = q('[data-file][open]').count || !q('[data-file]').count ? 'Collapse all' : 'Expand all'">Collapse all</span> | |||
| 111 | + | <kbd aria-hidden="true">x</kbd> | |||
| 110 | </button> | 112 | </button> | ||
| 111 | </div> | 113 | </div> | ||
| 112 | <p class="notice">this diff holds invisible characters (direction controls, zero-width characters). They are shown as <span class="inv"><U+XXXX></span> markers, never applied.</p> | 114 | <p class="notice">this diff holds invisible characters (direction controls, zero-width characters). They are shown as <span class="inv"><U+XXXX></span> markers, never applied.</p> | ||
| @@ -413,7 +415,7 @@ | |||||
| 413 | <kbd>u</kbd> | 415 | <kbd>u</kbd> | ||
| 414 | <kbd>x</kbd> | 416 | <kbd>x</kbd> | ||
| 415 | </dt> | 417 | </dt> | ||
| 416 | - | <dd>diff: split / unified / collapse all</dd> | 418 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 417 | </div> | 419 | </div> | ||
| 418 | <div> | 420 | <div> | ||
| 419 | <dt> | 421 | <dt> | ||
| @@ -587,9 +589,9 @@ | |||||
| 587 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 589 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 588 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 590 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 589 | }; | 591 | }; | ||
| 590 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 592 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 591 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 593 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 592 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 594 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 593 | k-permalink from:body -> { | 595 | k-permalink from:body -> { | ||
| 594 | let b = document.body.dataset; | 596 | let b = document.body.dataset; | ||
| 595 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 597 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/commits-page2.html +4 -4
| @@ -238,7 +238,7 @@ | |||
| 238 | 238 | <kbd>u</kbd> | |
| 239 | 239 | <kbd>x</kbd> | |
| 240 | 240 | </dt> | |
| 241 | - | <dd>diff: split / unified / collapse all</dd> | |
| 241 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 242 | 242 | </div> | |
| 243 | 243 | <div> | |
| 244 | 244 | <dt> | |
| @@ -398,9 +398,9 @@ | |||
| 398 | 398 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 399 | 399 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 400 | 400 | }; | |
| 401 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 402 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 403 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 401 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 402 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 403 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 404 | 404 | k-permalink from:body -> { | |
| 405 | 405 | let b = document.body.dataset; | |
| 406 | 406 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -238,7 +238,7 @@ | |||||
| 238 | <kbd>u</kbd> | 238 | <kbd>u</kbd> | ||
| 239 | <kbd>x</kbd> | 239 | <kbd>x</kbd> | ||
| 240 | </dt> | 240 | </dt> | ||
| 241 | - | <dd>diff: split / unified / collapse all</dd> | 241 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 242 | </div> | 242 | </div> | ||
| 243 | <div> | 243 | <div> | ||
| 244 | <dt> | 244 | <dt> | ||
| @@ -398,9 +398,9 @@ | |||||
| 398 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 398 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 399 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 399 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 400 | }; | 400 | }; | ||
| 401 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 401 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 402 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 402 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 403 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 403 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 404 | k-permalink from:body -> { | 404 | k-permalink from:body -> { | ||
| 405 | let b = document.body.dataset; | 405 | let b = document.body.dataset; | ||
| 406 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 406 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/commits-path.html +4 -4
| @@ -253,7 +253,7 @@ | |||
| 253 | 253 | <kbd>u</kbd> | |
| 254 | 254 | <kbd>x</kbd> | |
| 255 | 255 | </dt> | |
| 256 | - | <dd>diff: split / unified / collapse all</dd> | |
| 256 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 257 | 257 | </div> | |
| 258 | 258 | <div> | |
| 259 | 259 | <dt> | |
| @@ -413,9 +413,9 @@ | |||
| 413 | 413 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 414 | 414 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 415 | 415 | }; | |
| 416 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 417 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 418 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 416 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 417 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 418 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 419 | 419 | k-permalink from:body -> { | |
| 420 | 420 | let b = document.body.dataset; | |
| 421 | 421 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -253,7 +253,7 @@ | |||||
| 253 | <kbd>u</kbd> | 253 | <kbd>u</kbd> | ||
| 254 | <kbd>x</kbd> | 254 | <kbd>x</kbd> | ||
| 255 | </dt> | 255 | </dt> | ||
| 256 | - | <dd>diff: split / unified / collapse all</dd> | 256 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 257 | </div> | 257 | </div> | ||
| 258 | <div> | 258 | <div> | ||
| 259 | <dt> | 259 | <dt> | ||
| @@ -413,9 +413,9 @@ | |||||
| 413 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 413 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 414 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 414 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 415 | }; | 415 | }; | ||
| 416 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 416 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 417 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 417 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 418 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 418 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 419 | k-permalink from:body -> { | 419 | k-permalink from:body -> { | ||
| 420 | let b = document.body.dataset; | 420 | let b = document.body.dataset; | ||
| 421 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 421 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/commits-root.html +4 -4
| @@ -1040,7 +1040,7 @@ | |||
| 1040 | 1040 | <kbd>u</kbd> | |
| 1041 | 1041 | <kbd>x</kbd> | |
| 1042 | 1042 | </dt> | |
| 1043 | - | <dd>diff: split / unified / collapse all</dd> | |
| 1043 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 1044 | 1044 | </div> | |
| 1045 | 1045 | <div> | |
| 1046 | 1046 | <dt> | |
| @@ -1200,9 +1200,9 @@ | |||
| 1200 | 1200 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 1201 | 1201 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 1202 | 1202 | }; | |
| 1203 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 1204 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 1205 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 1203 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 1204 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 1205 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 1206 | 1206 | k-permalink from:body -> { | |
| 1207 | 1207 | let b = document.body.dataset; | |
| 1208 | 1208 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -1040,7 +1040,7 @@ | |||||
| 1040 | <kbd>u</kbd> | 1040 | <kbd>u</kbd> | ||
| 1041 | <kbd>x</kbd> | 1041 | <kbd>x</kbd> | ||
| 1042 | </dt> | 1042 | </dt> | ||
| 1043 | - | <dd>diff: split / unified / collapse all</dd> | 1043 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 1044 | </div> | 1044 | </div> | ||
| 1045 | <div> | 1045 | <div> | ||
| 1046 | <dt> | 1046 | <dt> | ||
| @@ -1200,9 +1200,9 @@ | |||||
| 1200 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 1200 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 1201 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 1201 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 1202 | }; | 1202 | }; | ||
| 1203 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 1203 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 1204 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 1204 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 1205 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 1205 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 1206 | k-permalink from:body -> { | 1206 | k-permalink from:body -> { | ||
| 1207 | let b = document.body.dataset; | 1207 | let b = document.body.dataset; | ||
| 1208 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 1208 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/commits-small.html +4 -4
| @@ -385,7 +385,7 @@ | |||
| 385 | 385 | <kbd>u</kbd> | |
| 386 | 386 | <kbd>x</kbd> | |
| 387 | 387 | </dt> | |
| 388 | - | <dd>diff: split / unified / collapse all</dd> | |
| 388 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 389 | 389 | </div> | |
| 390 | 390 | <div> | |
| 391 | 391 | <dt> | |
| @@ -565,9 +565,9 @@ | |||
| 565 | 565 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 566 | 566 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 567 | 567 | }; | |
| 568 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 569 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 570 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 568 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 569 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 570 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 571 | 571 | k-permalink from:body -> { | |
| 572 | 572 | let b = document.body.dataset; | |
| 573 | 573 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -385,7 +385,7 @@ | |||||
| 385 | <kbd>u</kbd> | 385 | <kbd>u</kbd> | ||
| 386 | <kbd>x</kbd> | 386 | <kbd>x</kbd> | ||
| 387 | </dt> | 387 | </dt> | ||
| 388 | - | <dd>diff: split / unified / collapse all</dd> | 388 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 389 | </div> | 389 | </div> | ||
| 390 | <div> | 390 | <div> | ||
| 391 | <dt> | 391 | <dt> | ||
| @@ -565,9 +565,9 @@ | |||||
| 565 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 565 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 566 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 566 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 567 | }; | 567 | }; | ||
| 568 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 568 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 569 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 569 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 570 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 570 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 571 | k-permalink from:body -> { | 571 | k-permalink from:body -> { | ||
| 572 | let b = document.body.dataset; | 572 | let b = document.body.dataset; | ||
| 573 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 573 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/empty.html +4 -4
| @@ -162,7 +162,7 @@ | |||
| 162 | 162 | <kbd>u</kbd> | |
| 163 | 163 | <kbd>x</kbd> | |
| 164 | 164 | </dt> | |
| 165 | - | <dd>diff: split / unified / collapse all</dd> | |
| 165 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 166 | 166 | </div> | |
| 167 | 167 | <div> | |
| 168 | 168 | <dt> | |
| @@ -259,9 +259,9 @@ | |||
| 259 | 259 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 260 | 260 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 261 | 261 | }; | |
| 262 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 263 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 264 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 262 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 263 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 264 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 265 | 265 | k-permalink from:body -> { | |
| 266 | 266 | let b = document.body.dataset; | |
| 267 | 267 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -162,7 +162,7 @@ | |||||
| 162 | <kbd>u</kbd> | 162 | <kbd>u</kbd> | ||
| 163 | <kbd>x</kbd> | 163 | <kbd>x</kbd> | ||
| 164 | </dt> | 164 | </dt> | ||
| 165 | - | <dd>diff: split / unified / collapse all</dd> | 165 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 166 | </div> | 166 | </div> | ||
| 167 | <div> | 167 | <div> | ||
| 168 | <dt> | 168 | <dt> | ||
| @@ -259,9 +259,9 @@ | |||||
| 259 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 259 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 260 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 260 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 261 | }; | 261 | }; | ||
| 262 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 262 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 263 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 263 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 264 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 264 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 265 | k-permalink from:body -> { | 265 | k-permalink from:body -> { | ||
| 266 | let b = document.body.dataset; | 266 | let b = document.body.dataset; | ||
| 267 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 267 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/home.html +4 -4
| @@ -192,7 +192,7 @@ | |||
| 192 | 192 | <kbd>u</kbd> | |
| 193 | 193 | <kbd>x</kbd> | |
| 194 | 194 | </dt> | |
| 195 | - | <dd>diff: split / unified / collapse all</dd> | |
| 195 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 196 | 196 | </div> | |
| 197 | 197 | <div> | |
| 198 | 198 | <dt> | |
| @@ -295,9 +295,9 @@ | |||
| 295 | 295 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 296 | 296 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 297 | 297 | }; | |
| 298 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 299 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 300 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 298 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 299 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 300 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 301 | 301 | k-permalink from:body -> { | |
| 302 | 302 | let b = document.body.dataset; | |
| 303 | 303 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -192,7 +192,7 @@ | |||||
| 192 | <kbd>u</kbd> | 192 | <kbd>u</kbd> | ||
| 193 | <kbd>x</kbd> | 193 | <kbd>x</kbd> | ||
| 194 | </dt> | 194 | </dt> | ||
| 195 | - | <dd>diff: split / unified / collapse all</dd> | 195 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 196 | </div> | 196 | </div> | ||
| 197 | <div> | 197 | <div> | ||
| 198 | <dt> | 198 | <dt> | ||
| @@ -295,9 +295,9 @@ | |||||
| 295 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 295 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 296 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 296 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 297 | }; | 297 | }; | ||
| 298 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 298 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 299 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 299 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 300 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 300 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 301 | k-permalink from:body -> { | 301 | k-permalink from:body -> { | ||
| 302 | let b = document.body.dataset; | 302 | let b = document.body.dataset; | ||
| 303 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 303 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/not-found-page.html +4 -4
| @@ -151,7 +151,7 @@ | |||
| 151 | 151 | <kbd>u</kbd> | |
| 152 | 152 | <kbd>x</kbd> | |
| 153 | 153 | </dt> | |
| 154 | - | <dd>diff: split / unified / collapse all</dd> | |
| 154 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 155 | 155 | </div> | |
| 156 | 156 | <div> | |
| 157 | 157 | <dt> | |
| @@ -242,9 +242,9 @@ | |||
| 242 | 242 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 243 | 243 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 244 | 244 | }; | |
| 245 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 246 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 247 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 245 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 246 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 247 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 248 | 248 | k-permalink from:body -> { | |
| 249 | 249 | let b = document.body.dataset; | |
| 250 | 250 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -151,7 +151,7 @@ | |||||
| 151 | <kbd>u</kbd> | 151 | <kbd>u</kbd> | ||
| 152 | <kbd>x</kbd> | 152 | <kbd>x</kbd> | ||
| 153 | </dt> | 153 | </dt> | ||
| 154 | - | <dd>diff: split / unified / collapse all</dd> | 154 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 155 | </div> | 155 | </div> | ||
| 156 | <div> | 156 | <div> | ||
| 157 | <dt> | 157 | <dt> | ||
| @@ -242,9 +242,9 @@ | |||||
| 242 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 242 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 243 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 243 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 244 | }; | 244 | }; | ||
| 245 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 245 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 246 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 246 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 247 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 247 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 248 | k-permalink from:body -> { | 248 | k-permalink from:body -> { | ||
| 249 | let b = document.body.dataset; | 249 | let b = document.body.dataset; | ||
| 250 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 250 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/not-found.html +4 -4
| @@ -151,7 +151,7 @@ | |||
| 151 | 151 | <kbd>u</kbd> | |
| 152 | 152 | <kbd>x</kbd> | |
| 153 | 153 | </dt> | |
| 154 | - | <dd>diff: split / unified / collapse all</dd> | |
| 154 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 155 | 155 | </div> | |
| 156 | 156 | <div> | |
| 157 | 157 | <dt> | |
| @@ -242,9 +242,9 @@ | |||
| 242 | 242 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 243 | 243 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 244 | 244 | }; | |
| 245 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 246 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 247 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 245 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 246 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 247 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 248 | 248 | k-permalink from:body -> { | |
| 249 | 249 | let b = document.body.dataset; | |
| 250 | 250 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -151,7 +151,7 @@ | |||||
| 151 | <kbd>u</kbd> | 151 | <kbd>u</kbd> | ||
| 152 | <kbd>x</kbd> | 152 | <kbd>x</kbd> | ||
| 153 | </dt> | 153 | </dt> | ||
| 154 | - | <dd>diff: split / unified / collapse all</dd> | 154 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 155 | </div> | 155 | </div> | ||
| 156 | <div> | 156 | <div> | ||
| 157 | <dt> | 157 | <dt> | ||
| @@ -242,9 +242,9 @@ | |||||
| 242 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 242 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 243 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 243 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 244 | }; | 244 | }; | ||
| 245 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 245 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 246 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 246 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 247 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 247 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 248 | k-permalink from:body -> { | 248 | k-permalink from:body -> { | ||
| 249 | let b = document.body.dataset; | 249 | let b = document.body.dataset; | ||
| 250 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 250 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/refs.html +4 -4
| @@ -276,7 +276,7 @@ | |||
| 276 | 276 | <kbd>u</kbd> | |
| 277 | 277 | <kbd>x</kbd> | |
| 278 | 278 | </dt> | |
| 279 | - | <dd>diff: split / unified / collapse all</dd> | |
| 279 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 280 | 280 | </div> | |
| 281 | 281 | <div> | |
| 282 | 282 | <dt> | |
| @@ -466,9 +466,9 @@ | |||
| 466 | 466 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 467 | 467 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 468 | 468 | }; | |
| 469 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 470 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 471 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 469 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 470 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 471 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 472 | 472 | k-permalink from:body -> { | |
| 473 | 473 | let b = document.body.dataset; | |
| 474 | 474 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -276,7 +276,7 @@ | |||||
| 276 | <kbd>u</kbd> | 276 | <kbd>u</kbd> | ||
| 277 | <kbd>x</kbd> | 277 | <kbd>x</kbd> | ||
| 278 | </dt> | 278 | </dt> | ||
| 279 | - | <dd>diff: split / unified / collapse all</dd> | 279 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 280 | </div> | 280 | </div> | ||
| 281 | <div> | 281 | <div> | ||
| 282 | <dt> | 282 | <dt> | ||
| @@ -466,9 +466,9 @@ | |||||
| 466 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 466 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 467 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 467 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 468 | }; | 468 | }; | ||
| 469 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 469 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 470 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 470 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 471 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 471 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 472 | k-permalink from:body -> { | 472 | k-permalink from:body -> { | ||
| 473 | let b = document.body.dataset; | 473 | let b = document.body.dataset; | ||
| 474 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 474 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/summary.html +17 -6
| @@ -127,14 +127,25 @@ | |||
| 127 | 127 | </dd> | |
| 128 | 128 | <dt>branch</dt> | |
| 129 | 129 | <dd>main · 2 branches</dd> | |
| 130 | - | <dt>tag</dt> | |
| 131 | - | <dd>v0.2.0 · AGO · 2 tags</dd> | |
| 132 | 130 | <dt>created</dt> | |
| 133 | 131 | <dd> | |
| 134 | 132 | <time datetime="STAMP">STAMP</time> | |
| 135 | 133 | </dd> | |
| 136 | 134 | </dl> | |
| 137 | 135 | </section> | |
| 136 | + | <section aria-labelledby="r-tag"> | |
| 137 | + | <h2 id="r-tag">Tags <span class="count">2</span> | |
| 138 | + | <a href="/demo/refs">View all</a> | |
| 139 | + | </h2> | |
| 140 | + | <div class="latest-tag"> | |
| 141 | + | <a class="tag-name" href="/demo/tree/v0.2.0"> | |
| 142 | + | <span class="ico i-tag" aria-hidden="true"> | |
| 143 | + | </span>v0.2.0</a> | |
| 144 | + | <span class="pill">latest</span> | |
| 145 | + | <time class="dim" datetime="STAMP" title="STAMP">AGO</time> | |
| 146 | + | <p class="tag-sub dim">add main.go</p> | |
| 147 | + | </div> | |
| 148 | + | </section> | |
| 138 | 149 | <section aria-labelledby="r-recent"> | |
| 139 | 150 | <h2 id="r-recent">Recent commits <a href="/demo/commits/main">View all</a> | |
| 140 | 151 | </h2> | |
| @@ -281,7 +292,7 @@ | |||
| 281 | 292 | <kbd>u</kbd> | |
| 282 | 293 | <kbd>x</kbd> | |
| 283 | 294 | </dt> | |
| 284 | - | <dd>diff: split / unified / collapse all</dd> | |
| 295 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 285 | 296 | </div> | |
| 286 | 297 | <div> | |
| 287 | 298 | <dt> | |
| @@ -471,9 +482,9 @@ | |||
| 471 | 482 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 472 | 483 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 473 | 484 | }; | |
| 474 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 475 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 476 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 485 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 486 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 487 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 477 | 488 | k-permalink from:body -> { | |
| 478 | 489 | let b = document.body.dataset; | |
| 479 | 490 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -127,14 +127,25 @@ | |||||
| 127 | </dd> | 127 | </dd> | ||
| 128 | <dt>branch</dt> | 128 | <dt>branch</dt> | ||
| 129 | <dd>main · 2 branches</dd> | 129 | <dd>main · 2 branches</dd> | ||
| 130 | - | <dt>tag</dt> | |||
| 131 | - | <dd>v0.2.0 · AGO · 2 tags</dd> | |||
| 132 | <dt>created</dt> | 130 | <dt>created</dt> | ||
| 133 | <dd> | 131 | <dd> | ||
| 134 | <time datetime="STAMP">STAMP</time> | 132 | <time datetime="STAMP">STAMP</time> | ||
| 135 | </dd> | 133 | </dd> | ||
| 136 | </dl> | 134 | </dl> | ||
| 137 | </section> | 135 | </section> | ||
| 136 | + | <section aria-labelledby="r-tag"> | |||
| 137 | + | <h2 id="r-tag">Tags <span class="count">2</span> | |||
| 138 | + | <a href="/demo/refs">View all</a> | |||
| 139 | + | </h2> | |||
| 140 | + | <div class="latest-tag"> | |||
| 141 | + | <a class="tag-name" href="/demo/tree/v0.2.0"> | |||
| 142 | + | <span class="ico i-tag" aria-hidden="true"> | |||
| 143 | + | </span>v0.2.0</a> | |||
| 144 | + | <span class="pill">latest</span> | |||
| 145 | + | <time class="dim" datetime="STAMP" title="STAMP">AGO</time> | |||
| 146 | + | <p class="tag-sub dim">add main.go</p> | |||
| 147 | + | </div> | |||
| 148 | + | </section> | |||
| 138 | <section aria-labelledby="r-recent"> | 149 | <section aria-labelledby="r-recent"> | ||
| 139 | <h2 id="r-recent">Recent commits <a href="/demo/commits/main">View all</a> | 150 | <h2 id="r-recent">Recent commits <a href="/demo/commits/main">View all</a> | ||
| 140 | </h2> | 151 | </h2> | ||
| @@ -281,7 +292,7 @@ | |||||
| 281 | <kbd>u</kbd> | 292 | <kbd>u</kbd> | ||
| 282 | <kbd>x</kbd> | 293 | <kbd>x</kbd> | ||
| 283 | </dt> | 294 | </dt> | ||
| 284 | - | <dd>diff: split / unified / collapse all</dd> | 295 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 285 | </div> | 296 | </div> | ||
| 286 | <div> | 297 | <div> | ||
| 287 | <dt> | 298 | <dt> | ||
| @@ -471,9 +482,9 @@ | |||||
| 471 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 482 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 472 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 483 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 473 | }; | 484 | }; | ||
| 474 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 485 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 475 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 486 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 476 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 487 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 477 | k-permalink from:body -> { | 488 | k-permalink from:body -> { | ||
| 478 | let b = document.body.dataset; | 489 | let b = document.body.dataset; | ||
| 479 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 490 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/tree-nested.html +4 -4
| @@ -221,7 +221,7 @@ | |||
| 221 | 221 | <kbd>u</kbd> | |
| 222 | 222 | <kbd>x</kbd> | |
| 223 | 223 | </dt> | |
| 224 | - | <dd>diff: split / unified / collapse all</dd> | |
| 224 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 225 | 225 | </div> | |
| 226 | 226 | <div> | |
| 227 | 227 | <dt> | |
| @@ -401,9 +401,9 @@ | |||
| 401 | 401 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 402 | 402 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 403 | 403 | }; | |
| 404 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 405 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 406 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 404 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 405 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 406 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 407 | 407 | k-permalink from:body -> { | |
| 408 | 408 | let b = document.body.dataset; | |
| 409 | 409 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -221,7 +221,7 @@ | |||||
| 221 | <kbd>u</kbd> | 221 | <kbd>u</kbd> | ||
| 222 | <kbd>x</kbd> | 222 | <kbd>x</kbd> | ||
| 223 | </dt> | 223 | </dt> | ||
| 224 | - | <dd>diff: split / unified / collapse all</dd> | 224 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 225 | </div> | 225 | </div> | ||
| 226 | <div> | 226 | <div> | ||
| 227 | <dt> | 227 | <dt> | ||
| @@ -401,9 +401,9 @@ | |||||
| 401 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 401 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 402 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 402 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 403 | }; | 403 | }; | ||
| 404 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 404 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 405 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 405 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 406 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 406 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 407 | k-permalink from:body -> { | 407 | k-permalink from:body -> { | ||
| 408 | let b = document.body.dataset; | 408 | let b = document.body.dataset; | ||
| 409 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 409 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/tree-root.html +4 -4
| @@ -448,7 +448,7 @@ | |||
| 448 | 448 | <kbd>u</kbd> | |
| 449 | 449 | <kbd>x</kbd> | |
| 450 | 450 | </dt> | |
| 451 | - | <dd>diff: split / unified / collapse all</dd> | |
| 451 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 452 | 452 | </div> | |
| 453 | 453 | <div> | |
| 454 | 454 | <dt> | |
| @@ -700,9 +700,9 @@ | |||
| 700 | 700 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 701 | 701 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 702 | 702 | }; | |
| 703 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 704 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 705 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 703 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 704 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 705 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 706 | 706 | k-permalink from:body -> { | |
| 707 | 707 | let b = document.body.dataset; | |
| 708 | 708 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -448,7 +448,7 @@ | |||||
| 448 | <kbd>u</kbd> | 448 | <kbd>u</kbd> | ||
| 449 | <kbd>x</kbd> | 449 | <kbd>x</kbd> | ||
| 450 | </dt> | 450 | </dt> | ||
| 451 | - | <dd>diff: split / unified / collapse all</dd> | 451 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 452 | </div> | 452 | </div> | ||
| 453 | <div> | 453 | <div> | ||
| 454 | <dt> | 454 | <dt> | ||
| @@ -700,9 +700,9 @@ | |||||
| 700 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 700 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 701 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 701 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 702 | }; | 702 | }; | ||
| 703 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 703 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 704 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 704 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 705 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 705 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 706 | k-permalink from:body -> { | 706 | k-permalink from:body -> { | ||
| 707 | let b = document.body.dataset; | 707 | let b = document.body.dataset; | ||
| 708 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 708 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/tree-slash-ref.html +4 -4
| @@ -218,7 +218,7 @@ | |||
| 218 | 218 | <kbd>u</kbd> | |
| 219 | 219 | <kbd>x</kbd> | |
| 220 | 220 | </dt> | |
| 221 | - | <dd>diff: split / unified / collapse all</dd> | |
| 221 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 222 | 222 | </div> | |
| 223 | 223 | <div> | |
| 224 | 224 | <dt> | |
| @@ -398,9 +398,9 @@ | |||
| 398 | 398 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 399 | 399 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 400 | 400 | }; | |
| 401 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 402 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 403 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 401 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 402 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 403 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 404 | 404 | k-permalink from:body -> { | |
| 405 | 405 | let b = document.body.dataset; | |
| 406 | 406 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -218,7 +218,7 @@ | |||||
| 218 | <kbd>u</kbd> | 218 | <kbd>u</kbd> | ||
| 219 | <kbd>x</kbd> | 219 | <kbd>x</kbd> | ||
| 220 | </dt> | 220 | </dt> | ||
| 221 | - | <dd>diff: split / unified / collapse all</dd> | 221 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 222 | </div> | 222 | </div> | ||
| 223 | <div> | 223 | <div> | ||
| 224 | <dt> | 224 | <dt> | ||
| @@ -398,9 +398,9 @@ | |||||
| 398 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 398 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 399 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 399 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 400 | }; | 400 | }; | ||
| 401 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 401 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 402 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 402 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 403 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 403 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 404 | k-permalink from:body -> { | 404 | k-permalink from:body -> { | ||
| 405 | let b = document.body.dataset; | 405 | let b = document.body.dataset; | ||
| 406 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 406 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M cmd/ermite/testdata/web/tree-subdir.html +4 -4
| @@ -243,7 +243,7 @@ | |||
| 243 | 243 | <kbd>u</kbd> | |
| 244 | 244 | <kbd>x</kbd> | |
| 245 | 245 | </dt> | |
| 246 | - | <dd>diff: split / unified / collapse all</dd> | |
| 246 | + | <dd>diff: split / unified / collapse or expand all</dd> | |
| 247 | 247 | </div> | |
| 248 | 248 | <div> | |
| 249 | 249 | <dt> | |
| @@ -429,9 +429,9 @@ | |||
| 429 | 429 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | |
| 430 | 430 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | |
| 431 | 431 | }; | |
| 432 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | |
| 433 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | |
| 434 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | |
| 432 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 433 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); | |
| 434 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; | |
| 435 | 435 | k-permalink from:body -> { | |
| 436 | 436 | let b = document.body.dataset; | |
| 437 | 437 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | |
| @@ -243,7 +243,7 @@ | |||||
| 243 | <kbd>u</kbd> | 243 | <kbd>u</kbd> | ||
| 244 | <kbd>x</kbd> | 244 | <kbd>x</kbd> | ||
| 245 | </dt> | 245 | </dt> | ||
| 246 | - | <dd>diff: split / unified / collapse all</dd> | 246 | + | <dd>diff: split / unified / collapse or expand all</dd> |
| 247 | </div> | 247 | </div> | ||
| 248 | <div> | 248 | <div> | ||
| 249 | <dt> | 249 | <dt> | ||
| @@ -429,9 +429,9 @@ | |||||
| 429 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | 429 | let i = ns.findIndex(n => n.getBoundingClientRect().top > innerHeight / 3); | ||
| 430 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | 430 | let n = ns[i < 0 ? 0 : i]; n.closest('details') && (n.closest('details').open = true); n.scrollIntoView({ block: 'center' }) | ||
| 431 | }; | 431 | }; | ||
| 432 | - | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); | 432 | + | k-split from:body -> q('[data-diff]').attr['data-diff'] = 'split'; sessionStorage.setItem('diff', 'split'); q('[data-file]').arr().forEach(d => d.open = true); |
| 433 | - | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); | 433 | + | k-unified from:body -> q('[data-diff]').attr['data-diff'] = 'unified'; sessionStorage.setItem('diff', 'unified'); q('[data-file]').arr().forEach(d => d.open = true); |
| 434 | - | k-collapse from:body -> q('[data-file]').arr().forEach(d => d.open = false); | 434 | + | k-collapse from:body -> { let fs = q('[data-file]').arr(), open = !fs.some(d => d.open); fs.forEach(d => d.open = open) }; |
| 435 | k-permalink from:body -> { | 435 | k-permalink from:body -> { | ||
| 436 | let b = document.body.dataset; | 436 | let b = document.body.dataset; | ||
| 437 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | 437 | if (!b.sha) { b.flash = 'no ref to pin on this page'; await timeout('2s'); b.flash = ''; return } | ||
M internal/adapters/web/pages.templ +15 -0
| @@ -59,6 +59,21 @@ templ summaryRail(p SummaryPage) { | |||
| 59 | 59 | </section> | |
| 60 | 60 | <section aria-labelledby="r-facts"><h2 id="r-facts">About</h2>@Facts(p.Facts) | |
| 61 | 61 | </section> | |
| 62 | + | if p.Latest != nil { | |
| 63 | + | <section aria-labelledby="r-tag"> | |
| 64 | + | <h2 id="r-tag">Tags <span class="count">{ itoa(p.Latest.Count) }</span> <a href={ templ.SafeURL(p.Latest.RefsHref) }>View all</a></h2> | |
| 65 | + | if p.Latest.Name != "" { | |
| 66 | + | <div class="latest-tag"> | |
| 67 | + | <a class="tag-name" href={ templ.SafeURL(p.Latest.Href) }><span class="ico i-tag" aria-hidden="true"></span>{ p.Latest.Name }</a> | |
| 68 | + | <span class="pill">latest</span> | |
| 69 | + | <time class="dim" datetime={ p.Latest.WhenAt } title={ p.Latest.WhenAt }>{ p.Latest.When }</time> | |
| 70 | + | if p.Latest.Subject != "" { | |
| 71 | + | <p class="tag-sub dim">{ p.Latest.Subject }</p> | |
| 72 | + | } | |
| 73 | + | </div> | |
| 74 | + | } | |
| 75 | + | </section> | |
| 76 | + | } | |
| 62 | 77 | if len(p.Recent) > 0 { | |
| 63 | 78 | <section aria-labelledby="r-recent"><h2 id="r-recent">Recent commits <a href={ templ.SafeURL(p.AllHref) }>View all</a></h2>@CommitRows(p.Recent) | |
| 64 | 79 | </section> | |
| @@ -59,6 +59,21 @@ templ summaryRail(p SummaryPage) { | |||||
| 59 | </section> | 59 | </section> | ||
| 60 | <section aria-labelledby="r-facts"><h2 id="r-facts">About</h2>@Facts(p.Facts) | 60 | <section aria-labelledby="r-facts"><h2 id="r-facts">About</h2>@Facts(p.Facts) | ||
| 61 | </section> | 61 | </section> | ||
| 62 | + | if p.Latest != nil { | |||
| 63 | + | <section aria-labelledby="r-tag"> | |||
| 64 | + | <h2 id="r-tag">Tags <span class="count">{ itoa(p.Latest.Count) }</span> <a href={ templ.SafeURL(p.Latest.RefsHref) }>View all</a></h2> | |||
| 65 | + | if p.Latest.Name != "" { | |||
| 66 | + | <div class="latest-tag"> | |||
| 67 | + | <a class="tag-name" href={ templ.SafeURL(p.Latest.Href) }><span class="ico i-tag" aria-hidden="true"></span>{ p.Latest.Name }</a> | |||
| 68 | + | <span class="pill">latest</span> | |||
| 69 | + | <time class="dim" datetime={ p.Latest.WhenAt } title={ p.Latest.WhenAt }>{ p.Latest.When }</time> | |||
| 70 | + | if p.Latest.Subject != "" { | |||
| 71 | + | <p class="tag-sub dim">{ p.Latest.Subject }</p> | |||
| 72 | + | } | |||
| 73 | + | </div> | |||
| 74 | + | } | |||
| 75 | + | </section> | |||
| 76 | + | } | |||
| 62 | if len(p.Recent) > 0 { | 77 | if len(p.Recent) > 0 { | ||
| 63 | <section aria-labelledby="r-recent"><h2 id="r-recent">Recent commits <a href={ templ.SafeURL(p.AllHref) }>View all</a></h2>@CommitRows(p.Recent) | 78 | <section aria-labelledby="r-recent"><h2 id="r-recent">Recent commits <a href={ templ.SafeURL(p.AllHref) }>View all</a></h2>@CommitRows(p.Recent) | ||
| 64 | </section> | 79 | </section> | ||
M internal/adapters/web/pages_templ.go +281 -151 generated file: collapsed
M internal/adapters/web/static/css/20-shell.css +11 -0
| @@ -20,6 +20,7 @@ | |||
| 20 | 20 | .i-branch { --i: url(icons/branch.svg); } | |
| 21 | 21 | .i-search { --i: url(icons/search.svg); } | |
| 22 | 22 | .i-file { --i: url(icons/file.svg); } | |
| 23 | + | .i-tag { --i: url(icons/tag.svg); } | |
| 23 | 24 | ||
| 24 | 25 | .pill { | |
| 25 | 26 | display: inline-flex; align-items: center; height: 20px; padding: 0 var(--s2); margin-left: var(--s1); | |
| @@ -123,6 +124,16 @@ | |||
| 123 | 124 | .rail section > :not(h2) { margin: var(--s3) var(--s4); } | |
| 124 | 125 | .rail section > .list { margin: var(--s2) 0; } | |
| 125 | 126 | .rail section > p + p { margin-top: calc(-1 * var(--s2)); } | |
| 127 | + | .rail h2 .count + a { margin-left: auto; } | |
| 128 | + | ||
| 129 | + | /* newest tag in the summary rail */ | |
| 130 | + | .latest-tag { | |
| 131 | + | display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2); font-size: var(--fs-s); | |
| 132 | + | & .tag-name { display: inline-flex; align-items: center; gap: 6px; font: 700 var(--fs) / 20px var(--mono); color: var(--ink-hi); text-decoration: none; } | |
| 133 | + | & .tag-name:hover { text-decoration: underline; } | |
| 134 | + | & time { margin-left: auto; } | |
| 135 | + | & .tag-sub { flex-basis: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } | |
| 136 | + | } | |
| 126 | 137 | ||
| 127 | 138 | .kv { | |
| 128 | 139 | display: grid; grid-template-columns: max-content minmax(0, 1fr); column-gap: var(--s4); row-gap: var(--s1); | |
| @@ -20,6 +20,7 @@ | |||||
| 20 | .i-branch { --i: url(icons/branch.svg); } | 20 | .i-branch { --i: url(icons/branch.svg); } | ||
| 21 | .i-search { --i: url(icons/search.svg); } | 21 | .i-search { --i: url(icons/search.svg); } | ||
| 22 | .i-file { --i: url(icons/file.svg); } | 22 | .i-file { --i: url(icons/file.svg); } | ||
| 23 | + | .i-tag { --i: url(icons/tag.svg); } | |||
| 23 | 24 | ||||
| 24 | .pill { | 25 | .pill { | ||
| 25 | display: inline-flex; align-items: center; height: 20px; padding: 0 var(--s2); margin-left: var(--s1); | 26 | display: inline-flex; align-items: center; height: 20px; padding: 0 var(--s2); margin-left: var(--s1); | ||
| @@ -123,6 +124,16 @@ | |||||
| 123 | .rail section > :not(h2) { margin: var(--s3) var(--s4); } | 124 | .rail section > :not(h2) { margin: var(--s3) var(--s4); } | ||
| 124 | .rail section > .list { margin: var(--s2) 0; } | 125 | .rail section > .list { margin: var(--s2) 0; } | ||
| 125 | .rail section > p + p { margin-top: calc(-1 * var(--s2)); } | 126 | .rail section > p + p { margin-top: calc(-1 * var(--s2)); } | ||
| 127 | + | .rail h2 .count + a { margin-left: auto; } | |||
| 128 | + | ||||
| 129 | + | /* newest tag in the summary rail */ | |||
| 130 | + | .latest-tag { | |||
| 131 | + | display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2); font-size: var(--fs-s); | |||
| 132 | + | & .tag-name { display: inline-flex; align-items: center; gap: 6px; font: 700 var(--fs) / 20px var(--mono); color: var(--ink-hi); text-decoration: none; } | |||
| 133 | + | & .tag-name:hover { text-decoration: underline; } | |||
| 134 | + | & time { margin-left: auto; } | |||
| 135 | + | & .tag-sub { flex-basis: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } | |||
| 136 | + | } | |||
| 126 | 137 | ||||
| 127 | .kv { | 138 | .kv { | ||
| 128 | display: grid; grid-template-columns: max-content minmax(0, 1fr); column-gap: var(--s4); row-gap: var(--s1); | 139 | display: grid; grid-template-columns: max-content minmax(0, 1fr); column-gap: var(--s4); row-gap: var(--s1); | ||
A internal/adapters/web/static/icons/tag.svg +1 -0
| @@ -0,0 +1,1 @@ | |||
| 1 | + | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 2.5v5l6.5 6.5 5-5L7 2.5z"/><circle cx="5" cy="5.5" r="1"/></svg> | |
| @@ -0,0 +1,1 @@ | |||||
| 1 | + | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 2.5v5l6.5 6.5 5-5L7 2.5z"/><circle cx="5" cy="5.5" r="1"/></svg> | |||
M internal/adapters/web/summary.go +20 -12
| @@ -61,7 +61,8 @@ func (s *Server) summary(ctx context.Context, r *http.Request) (templ.Component, | |||
| 61 | 61 | p.Recent = append(p.Recent, row) | |
| 62 | 62 | } | |
| 63 | 63 | ||
| 64 | - | p.Facts = s.facts(ctx, d, now) | |
| 64 | + | p.Facts = s.facts(d, now) | |
| 65 | + | p.Latest = s.latest(ctx, d) | |
| 65 | 66 | ||
| 66 | 67 | if rd, err := s.readme(ctx, d, ref); err != nil { | |
| 67 | 68 | return nil, 0, err | |
| @@ -78,24 +79,31 @@ func (s *Server) summary(ctx context.Context, r *http.Request) (templ.Component, | |||
| 78 | 79 | } | |
| 79 | 80 | ||
| 80 | 81 | // maxTagDates is the most tags whose commit dates are read to name the | |
| 81 | - | // latest one; with more, the fact shows the count only. | |
| 82 | + | // latest one; with more, the rail shows the count only. | |
| 82 | 83 | const maxTagDates = 20 | |
| 83 | 84 | ||
| 85 | + | // latest is the newest tag of the repository for the rail, nil without tags. | |
| 86 | + | func (s *Server) latest(ctx context.Context, d *repoData) *LatestTag { | |
| 87 | + | n := len(d.tags) | |
| 88 | + | if n == 0 { | |
| 89 | + | return nil | |
| 90 | + | } | |
| 91 | + | lt := &LatestTag{Count: n, RefsHref: repoHref(d.name(), "refs")} | |
| 92 | + | if n <= maxTagDates { | |
| 93 | + | if name, c := latestTag(d.tags, s.commitsOf(ctx, d.name(), d.tags)); name != "" { | |
| 94 | + | lt.Name, lt.Href = name, repoHref(d.name(), "tree", name) | |
| 95 | + | lt.Subject, lt.When, lt.WhenAt = c.subject, c.when, c.whenAt | |
| 96 | + | } | |
| 97 | + | } | |
| 98 | + | return lt | |
| 99 | + | } | |
| 100 | + | ||
| 84 | 101 | // facts are the key/value rows of the rail. | |
| 85 | - | func (s *Server) facts(ctx context.Context, d *repoData, now time.Time) []Fact { | |
| 102 | + | func (s *Server) facts(d *repoData, now time.Time) []Fact { | |
| 86 | 103 | fs := []Fact{ | |
| 87 | 104 | lastPushFact(d.repo, now), | |
| 88 | 105 | {Key: "branch", Val: d.head.GetShortName() + " · " + plural(len(d.branches), "branch", "branches")}, | |
| 89 | 106 | } | |
| 90 | - | if n := len(d.tags); n > 0 { | |
| 91 | - | val := plural(n, "tag", "tags") | |
| 92 | - | if n <= maxTagDates { | |
| 93 | - | if name, c := latestTag(d.tags, s.commitsOf(ctx, d.name(), d.tags)); name != "" { | |
| 94 | - | val = name + " · " + c.when + " · " + val | |
| 95 | - | } | |
| 96 | - | } | |
| 97 | - | fs = append(fs, Fact{Key: "tag", Val: val}) | |
| 98 | - | } | |
| 99 | 107 | if c := d.repo.GetCreatedAt(); c.IsValid() { | |
| 100 | 108 | fs = append(fs, Fact{Key: "created", Val: absolute(c.AsTime()), Time: rfc3339(c.AsTime())}) | |
| 101 | 109 | } | |
| @@ -61,7 +61,8 @@ func (s *Server) summary(ctx context.Context, r *http.Request) (templ.Component, | |||||
| 61 | p.Recent = append(p.Recent, row) | 61 | p.Recent = append(p.Recent, row) | ||
| 62 | } | 62 | } | ||
| 63 | 63 | ||||
| 64 | - | p.Facts = s.facts(ctx, d, now) | 64 | + | p.Facts = s.facts(d, now) |
| 65 | + | p.Latest = s.latest(ctx, d) | |||
| 65 | 66 | ||||
| 66 | if rd, err := s.readme(ctx, d, ref); err != nil { | 67 | if rd, err := s.readme(ctx, d, ref); err != nil { | ||
| 67 | return nil, 0, err | 68 | return nil, 0, err | ||
| @@ -78,24 +79,31 @@ func (s *Server) summary(ctx context.Context, r *http.Request) (templ.Component, | |||||
| 78 | } | 79 | } | ||
| 79 | 80 | ||||
| 80 | // maxTagDates is the most tags whose commit dates are read to name the | 81 | // maxTagDates is the most tags whose commit dates are read to name the | ||
| 81 | - | // latest one; with more, the fact shows the count only. | 82 | + | // latest one; with more, the rail shows the count only. |
| 82 | const maxTagDates = 20 | 83 | const maxTagDates = 20 | ||
| 83 | 84 | ||||
| 85 | + | // latest is the newest tag of the repository for the rail, nil without tags. | |||
| 86 | + | func (s *Server) latest(ctx context.Context, d *repoData) *LatestTag { | |||
| 87 | + | n := len(d.tags) | |||
| 88 | + | if n == 0 { | |||
| 89 | + | return nil | |||
| 90 | + | } | |||
| 91 | + | lt := &LatestTag{Count: n, RefsHref: repoHref(d.name(), "refs")} | |||
| 92 | + | if n <= maxTagDates { | |||
| 93 | + | if name, c := latestTag(d.tags, s.commitsOf(ctx, d.name(), d.tags)); name != "" { | |||
| 94 | + | lt.Name, lt.Href = name, repoHref(d.name(), "tree", name) | |||
| 95 | + | lt.Subject, lt.When, lt.WhenAt = c.subject, c.when, c.whenAt | |||
| 96 | + | } | |||
| 97 | + | } | |||
| 98 | + | return lt | |||
| 99 | + | } | |||
| 100 | + | ||||
| 84 | // facts are the key/value rows of the rail. | 101 | // facts are the key/value rows of the rail. | ||
| 85 | - | func (s *Server) facts(ctx context.Context, d *repoData, now time.Time) []Fact { | 102 | + | func (s *Server) facts(d *repoData, now time.Time) []Fact { |
| 86 | fs := []Fact{ | 103 | fs := []Fact{ | ||
| 87 | lastPushFact(d.repo, now), | 104 | lastPushFact(d.repo, now), | ||
| 88 | {Key: "branch", Val: d.head.GetShortName() + " · " + plural(len(d.branches), "branch", "branches")}, | 105 | {Key: "branch", Val: d.head.GetShortName() + " · " + plural(len(d.branches), "branch", "branches")}, | ||
| 89 | } | 106 | } | ||
| 90 | - | if n := len(d.tags); n > 0 { | |||
| 91 | - | val := plural(n, "tag", "tags") | |||
| 92 | - | if n <= maxTagDates { | |||
| 93 | - | if name, c := latestTag(d.tags, s.commitsOf(ctx, d.name(), d.tags)); name != "" { | |||
| 94 | - | val = name + " · " + c.when + " · " + val | |||
| 95 | - | } | |||
| 96 | - | } | |||
| 97 | - | fs = append(fs, Fact{Key: "tag", Val: val}) | |||
| 98 | - | } | |||
| 99 | if c := d.repo.GetCreatedAt(); c.IsValid() { | 107 | if c := d.repo.GetCreatedAt(); c.IsValid() { | ||
| 100 | fs = append(fs, Fact{Key: "created", Val: absolute(c.AsTime()), Time: rfc3339(c.AsTime())}) | 108 | fs = append(fs, Fact{Key: "created", Val: absolute(c.AsTime()), Time: rfc3339(c.AsTime())}) | ||
| 101 | } | 109 | } | ||
M internal/adapters/web/view.go +11 -0
| @@ -141,6 +141,17 @@ type SummaryPage struct { | |||
| 141 | 141 | Readme *Readme | |
| 142 | 142 | Outline []Heading | |
| 143 | 143 | AllHref string | |
| 144 | + | // Latest is the newest tag, nil when the repository has none. | |
| 145 | + | Latest *LatestTag | |
| 146 | + | } | |
| 147 | + | ||
| 148 | + | // LatestTag is the newest tag of a repository, shown in the summary rail. | |
| 149 | + | // Name is empty when there are too many tags to date them; Count and | |
| 150 | + | // RefsHref still lead to the full list. | |
| 151 | + | type LatestTag struct { | |
| 152 | + | Name, Href, Subject, When, WhenAt string | |
| 153 | + | Count int | |
| 154 | + | RefsHref string | |
| 144 | 155 | } | |
| 145 | 156 | ||
| 146 | 157 | // RefRow is a branch or a tag in the refs table. | |
| @@ -141,6 +141,17 @@ type SummaryPage struct { | |||||
| 141 | Readme *Readme | 141 | Readme *Readme | ||
| 142 | Outline []Heading | 142 | Outline []Heading | ||
| 143 | AllHref string | 143 | AllHref string | ||
| 144 | + | // Latest is the newest tag, nil when the repository has none. | |||
| 145 | + | Latest *LatestTag | |||
| 146 | + | } | |||
| 147 | + | ||||
| 148 | + | // LatestTag is the newest tag of a repository, shown in the summary rail. | |||
| 149 | + | // Name is empty when there are too many tags to date them; Count and | |||
| 150 | + | // RefsHref still lead to the full list. | |||
| 151 | + | type LatestTag struct { | |||
| 152 | + | Name, Href, Subject, When, WhenAt string | |||
| 153 | + | Count int | |||
| 154 | + | RefsHref string | |||
| 144 | } | 155 | } | ||
| 145 | 156 | ||||
| 146 | // RefRow is a branch or a tag in the refs table. | 157 | // RefRow is a branch or a tag in the refs table. | ||