nixos-config/modules/nginx-interactive-index/listing.js

94 lines
3.0 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

// SPDX-FileCopyrightText: 2021-2024 Simon Bruder <simon@sbruder.de>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
document.addEventListener('DOMContentLoaded', () => {
function humanFileSize(size) {
if (size === 0) {
return "0B";
}
if (size < 0) {
return null;
}
const base = Math.floor(Math.log2(size) / 10)
const unit = ["B", "KiB", "MiB", "GiB", "TiB"][base]
const relative = size / 2**(10*base)
return relative.toFixed(3) + "" + unit
}
function textToA(line) {
let outerElement = document.createElement('div')
outerElement.innerHTML = line
return outerElement.getElementsByTagName('a')[0]
}
function parseLine(line) {
const href = textToA(line).href
const filename = href.substr(-1) === '/' ? decodeURIComponent(href.split('/').slice(-2, -1)[0]) : decodeURIComponent(href.split('/').pop())
const size = line.split(' ').pop()
return {
href: href,
filename: filename,
size: size
}
}
function processLine(line) {
meta = parseLine(line)
return `<tr><td><a href="${meta.href}">${meta.filename}</a></td><td>${meta.size === '-' ? '-' : humanFileSize(meta.size)}</td></tr>`
}
function addZebraStripes(rows) {
// this should be done in CSS, but AFAIU it does not support limiting
// :nth-child to elements matching a previous :not selector
rows.forEach((row, idx) => {
if (idx % 2 === 0) {
row.classList.add("zebra-stripe")
} else {
row.classList.remove("zebra-stripe")
}
})
}
const collator = new Intl.Collator('kn', {numeric: true})
// transform plain text to table
document.querySelector('pre').outerHTML = '<table><thead><tr><th>Name</th><th>Size</th></tr></thead><tbody><tr><td><a href="..">..</a></td><td>-</td></tr>' + document.querySelector('pre').innerHTML
.split('\n')
.filter(line => line !== '')
.filter(line => line !== '<a href="../">../</a>')
.map(processLine)
.sort(collator.compare)
.join('\n') + '</tbody></table>'
let searchField = document.createElement('input')
searchField.id = 'search-field'
searchField.autofocus = true
document.querySelector('body').insertBefore(searchField, document.querySelector('table'))
const rows = Array.from(document.querySelectorAll('tbody tr'))
addZebraStripes(rows)
document.querySelector('#search-field').addEventListener("input", e => {
const searchValue = e.target.value.toLowerCase()
rows.forEach(row => {
const file = row.querySelector('td:nth-child(1) a').innerText
if (!file.toLowerCase().includes(searchValue)) {
row.classList.add("hidden")
} else {
row.classList.remove("hidden")
}
})
const visibleRows = rows.filter(row => !row.classList.contains("hidden"))
if (visibleRows.length === 1) {
const target = visibleRows[0].querySelector('td a').href
if (target.substr(-1) === '/') {
window.location = target
}
}
addZebraStripes(visibleRows)
})
})