<!DOCTYPE html>
<html lang="en">
    <head>
	    <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta charset="UTF-8"/> 
        <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
        <meta name="description" content="Trap.moe Mirrors.">
        <meta name="author" content="Lightemerald"/>
        <meta name="keywords" content="arch, linux, archlinux, mirrors, mirror"/>
        <title>Trap.moe Mirrors</title>
        <link rel="shortcut icon" href="https://fonts.gstatic.com/s/i/materialicons/drive_file_move/v17/24px.svg" crossorigin="anonymous">
        <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" crossorigin="anonymous">
        <!-- <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic" crossorigin="anonymous"> -->
        <link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.css" as="style" crossorigin="anonymous">
        <link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.4.1/milligram.css" as="style" crossorigin="anonymous">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.css" crossorigin="anonymous">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.4.1/milligram.css" crossorigin="anonymous">
        <!-- <link rel="preload" href="https://cdn.jsdelivr.net/npm/picnic" as="style" crossorigin="anonymous">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/picnic" crossorigin="anonymous"> -->
        <!-- <link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/min/1.5.0/entireframework.min.css" as="style" crossorigin="anonymous">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/min/1.5.0/entireframework.min.css" crossorigin="anonymous"> -->
        <!-- <link rel="preload" href="https://cdn.jsdelivr.net/npm/sscaffold-css@0.1.1/sscaffold.min.css" integrity="sha256-tNrNp6fPTVnhpywTjgNV4jCx6W9d1wuALpwVmAQEYcs=" as="style" crossorigin="anonymous"> 
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sscaffold-css@0.1.1/sscaffold.min.css" integrity="sha256-tNrNp6fPTVnhpywTjgNV4jCx6W9d1wuALpwVmAQEYcs=" crossorigin="anonymous"> -->
        <link rel="stylesheet" media="bogus">
        <script>
            window.$ = document.querySelector.bind(document);
            window.$$ = document.querySelectorAll.bind(document);
            Node.prototype.on = window.on = function (name, fn) {
                this.addEventListener(name, fn);
            }
            NodeList.prototype.__proto__ = Array.prototype;
            NodeList.prototype.on = NodeList.prototype.addEventListener = function (name, fn) {
                this.forEach(function (elem, i) {
                    elem.on(name, fn);
                });
            }

            /**
             * Format bytes as human-readable text.
             * @param bytes Number of bytes.
             * @param si True to use metric (SI) units, aka powers of 1000. False to use binary (IEC), aka powers of 1024.
             * @param dp Number of decimal places to display.
             * @return Formatted string.
             */
            function humanFileSize(bytes, si=false, dp=1) {
                const thresh = si ? 1000 : 1024;

                if (Math.abs(bytes) < thresh) {
                    return bytes + ' B';
                }
            
                const units = si 
                ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] 
                : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
                let u = -1;
                const r = 10**dp;
            
                do {
                    bytes /= thresh;
                    ++u;
                } while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
                
                return bytes.toFixed(dp) + ' ' + units[u];
            }

            function setSortable(c = 'th') {
                const getCellValue = function(tr, idx) {
                    return tr.children[idx].innerText || tr.children[idx].textContent;
                }

                const comparer = function(idx, asc) { 
                    return function(a, b) {
                        return (function (v1, v2) {
                            return v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2)
                        })(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx));
                    }
                }

                $$(c).forEach(function(th) {
                    th.addEventListener('click', (function(e) {
                        let i = (e.target.tagName == 'SPAN'? e.target : e.target.querySelector('span'));
                        const table = th.closest('table');
                        const tbody = table.querySelector('tbody');
                        
                        if (table) {
                            const is = table.querySelectorAll('th span');
                            if (is) {
                                is.forEach(s => s.style.transform = 'scaleY(1)');
                                is.forEach(s => s.textContent = 'filter_list');
                            }
                            if (i) {
                                i.textContent = 'sort';
                                i.style.transform = this.asc? 'scaleY(-1)' : 'scaleY(1)';
                            }
                            Array.from(tbody.querySelectorAll('tr'))
                                .sort(comparer(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
                                .forEach(tr => tbody.appendChild(tr));
                        }}
                    ))
                });
            }

            function filterTable(v = '', l = 0, c = 'table tbody tr', e = 'td') {
                const tr = $$(c);
                let cc = 0;
                v = v.toLowerCase();
               
		if (l && v && v.length < l) { return; }
 
                while (cc < tr.length) {
                    let td = tr[cc].getElementsByTagName(e),
                        dpl = 'none';
                        ccc = 0;

                    while (ccc < td.length) {
                        let txt = (td[ccc].textContent || td[ccc].innerText).toLowerCase();
                        if (txt.indexOf(v) > -1) {
                            dpl = '';
                        }
                        ++ccc;
                    }
                    tr[cc].style.display = dpl;
                    ++cc;
                }
            }
            
            function getData(c = '#idx-json') {
                const cdom = $(c);
                if (cdom.textContent.indexOf('[') >= 0) {
                    return JSON.parse(cdom.textContent);
                }
            }

            function setTheme(v = '') {
                $('#idx-theme').href = v? `https://cdn.jsdelivr.net/npm/milligram-themes@0.0.2/src/${v}.min.css` : v;
            }

            function getHref(u = '') {
                return u + window.location.search;
            }

            function setEnv(s = '#idx-filter', t = '#idx-stheme') {
                const pathname = window.location.pathname,
                    prm = new URLSearchParams(window.location.search);

                document.removeEventListener('DOMContentLoaded', main);
                
                window.language = prm.has('l') || 'sv-SE';

                if (prm.has('b')) {
                    $('section').style.backgroundImage = `url("${decodeURIComponent(prm.get('b'))}")`;
                }

                if (prm.has('t')) {
                    setTheme($(t).value = prm.get('t'));
                }

                $(t).addEventListener('change', function(e) {
                    setTheme(e.target.value);
                    prm.delete('t');
                    prm.append('t', e.target.value);
                    history.replaceState('', '', `${window.location.pathname}?${prm.toString()}`);
                });

                $(s).addEventListener('keyup', function(e) { filterTable(e.target.value, 3); });
                
                setSortable();

                $('#idx-path').innerHTML = '<small>' +
                    pathname.split('/').reduce(function(a, v, i, o) {
                        return a += ` / <a href="#" onclick="window.open(getHref('/${o.slice(1, i+1).join('/')}'),'_self')">${v}</a> `;
                    }) +
                    `<a title="Back" href="#" onclick="window.open(getHref('${pathname.substring(0, pathname.slice(0,-1).lastIndexOf('/'))}'),'_self')"><span class="material-icons">arrow_back_ios_new</span></a>` +
                '</small>'
            }

            function setData(a = [], n = [0,0,0,0], p = 15000, m = 1, c = 'table tbody', f = 'footer') {
                const pathname = window.location.pathname;
                let tblHtm = '';
                
                while (n[0] < a.length) {
                    let entry = a[n[0]];
                        mtime = new Date(entry.mtime),
                        entry.mtime = mtime.toLocaleString(window.language),  //`${mtime.toLocaleDateString()}  ${mtime.toLocaleTimeString()}`,
                        entry.ext = entry.name.substr(entry.name.lastIndexOf('.')+1).toUpperCase(),
                        url = `${pathname}${entry.name}`;

                    if (entry.type == 'directory') {
                        ++n[1];
                        tblHtm += `<tr>
                            <td><span class="material-icons" title="Folder">folder</span><span class="dn">${entry.type}</span></td>
                            <td><div title="...${entry.name.substr(-10)}"><a href="#" onclick="window.open(getHref('${url}'),'_self')">${entry.name}</a></div></td>
                            <td>${entry.mtime}</td>
                            <td></td>
                        </tr>`;
                    } else {
                        ++n[2];
                        n[3] += entry.size;
                        tblHtm += `<tr>
                            <td><span class="material-icons" title="${entry.ext} File">insert_drive_file</span><span class="dn">${entry.type}</span></td>
                            <td><div title="...${entry.name.substr(-10)}"><a download="${entry.name}" href="${url}">${entry.name}</a></div>
                                    <span class="fr"><a download="${entry.name}" href="${url}"><span class="material-icons" title="Save ${entry.ext}">download</span></a>
                                    <a href="${url}" target="_blank"><span class="material-icons" title="Open ${entry.ext}">open_in_browser</span></a></span>
                            </td>
                            <td>${entry.mtime}</td>
                            <td>${humanFileSize(entry.size, true, 2)}</td>
                        </tr>`;
                    }
                    
                    if (n[0] && n[0] != a.length-1 && n[0]%p === 0) {
                        $(c).innerHTML += tblHtm;
                        if (a.length >= p && n[0] == p) { $('.load').remove(); }
                        ++n[0];
                        setTimeout(function() {
                            setData(a,n);
                        }, m);
                        return;
                    }

                    ++n[0];
                    if (a.length < p && n[0] == a.length) { $('.load').remove(); }
                }

                $(c).innerHTML += tblHtm;
                if (n[0] == a.length) {
                    $(f).innerHTML = `<span class="material-icons">folder_open</span><span>${n[1]}</span>
                        <span class="material-icons">description</span><span>${n[2]}</span>
                        <span class="material-icons">account_tree</span><span>${(n[1]+n[2])}<strong> : </strong> &nbsp;&nbsp;&nbsp;${humanFileSize(n[3], true, 3)}</span>`;
                    a = null;
                }
            }

            function main() {
                const jsn = getData();
                setEnv();
                if (jsn) {    
                    setData(jsn);
                } else if (window.location.pathname.endsWith('.html')) {
                    alert('Is NGINX autoindexing?');
                }
            }

            document.addEventListener('wheel', function (e) {
                document.querySelector('main').scrollTop += e.deltaY;
                e.preventDefault();
            }, { passive: false });

            document.addEventListener('DOMContentLoaded', main);
        </script>
        <style>
            html, body{text-align: left; overflow: hidden; height: 100%; margin: 0; display: flex; flex-direction: column; flex-wrap: nowrap; flex-direction: column;}
            header{flex-shrink: 0;}
            header ul{border-bottom:solid 1px #ccc; margin: 7px; display: flex; align-items: stretch; justify-content: space-between;}
            header li{display:inline; margin:0 20px; white-space: nowrap;}
            main{overflow: auto scroll; flex-grow: 1; padding: 8px 10px; display: flex; justify-content: center; align-items: flex-start; scroll-snap-type: y mandatory;}
            footer{flex-shrink: 0; text-align: right; margin:0; border-top: solid 1px #ccc; z-index: 4;}
            table{width: calc(100vw / 1.618);}
            th{position: sticky; top: 0px; z-index: 2; white-space: nowrap; cursor: pointer;}
            th span.material-icons{vertical-align: top; padding: 0 0 0 1em;}
            th:first-child{padding: unset;}
            td:first-child{width: 32px;}
            td:nth-child(n+3){width: 1%; white-space: nowrap;}
            td:nth-child(2){display: grid; grid-template-columns: 1fr auto;}
            td:nth-child(2) div{overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
            tr{transition: all 0.2s ease 0s; scroll-snap-align: start;}
            tr:hover{box-shadow: 0px 5px 40px -10px rgba(0,0,0,0.5);}
            span.material-icons + span{vertical-align: middle; padding: 0 2em 0 1em;}
            section{width: 99%; height: 99%; position: fixed; left: 0; right: 0; z-index: 1; background-size: cover; background-repeat: no-repeat; background-attachment: fixed; background-position: center; filter: blur(3px); opacity: 0.13}
            article{z-index: 3;}
            #idx-filter{width: unset;}
            #idx-path{vertical-align: text-top;}
            #idx-path span{font-size: 16px; vertical-align: text-bottom; padding: 0 1em;}
            #idx-json{display: none;}
            #idx-stheme{width: auto;}
            .header{background-color: #fff;}
            .material-icons{vertical-align: middle;}
            .fs36{font-size: 36px;}
            .dn{display: none;}
            .fr{float: right;}
            .load {position: fixed; left: 0px; top: 0px; width: 100%; height: 100%; background: #EEE; z-index: 9999}
            .lds {display: inline-block; width: 80px; height: 80px; position: fixed; left: 47.5%; top: 47.5%;}
            .lds:after {content: " "; display: block; width: 64px; height: 64px; margin: 8px; border-radius: 50%; border: 6px solid #ccc; border-color: #ccc transparent; animation: lds 1.2s linear infinite;}
            @keyframes lds {0% {transform: rotate(0deg);}100% {transform: rotate(360deg);}}
        </style>
        <link id="idx-theme" rel="stylesheet" href="" crossorigin="anonymous">
    </head>
    <body>
        <div class="load">
            <div class="lds"></div>
        </div>
        <header>
            <ul>
                <li>
                    <span class="material-icons fs36">drive_file_move</span>
                    <span id="idx-path"></span>
                </li>
                <li></li>
                <li></li>
                <li></li>
                <li>
                    <span class="material-icons">filter_alt</span>
                    <input id="idx-filter" type="text" placeholder="Filter">
                </li>
                <li>
                    <span class="material-icons">palette</span>
                    <select id="idx-stheme">
                        <option value="aqua">Aqua</option>
                        <option value="black">Black</option>
                        <option value="blue">Blue</option>
                        <option value="dark2">Dark</option>
                        <option value="" selected>Default</option>
                        <option value="fuchsia">Fuchsia</option>
                        <option value="gray">Gray</option>
                        <option value="green">Green</option>
                        <option value="lime">Lime</option>
                        <option value="maroon">Maroon</option>
                        <option value="navy">Navy</option>
                        <option value="olive">Olive</option>
                        <option value="orange">Orange</option>
                        <option value="purple">Purple</option>
                        <option value="red">Red</option>
                        <option value="silver">Silver</option>
                        <option value="teal">Teal</option>
                        <option value="yellow">Yellow</option>
                    </select>
                </li>
            </ul>
        </header>
        <main>
            <section></section>
            <article>
                <table>
                    <thead>
                        <tr>
                            <th class="header"><span class="material-icons">filter_list</span></th>
                            <th class="header">Name<span class="material-icons">filter_list</span></th>
                            <th class="header">Date<span class="material-icons">filter_list</span></th>
                            <th class="header">Size<span class="material-icons">filter_list</span></th>
                        </tr>
                    </thead>
                    <tbody></tbody>
                </table>
            </article>
        </main>
        <footer>
            <div id="idx-json">
[
{ "name":"community-staging", "type":"directory", "mtime":"Sat, 11 Sep 2010 16:28:50 GMT" },
{ "name":"core", "type":"directory", "mtime":"Fri, 14 Sep 2007 15:35:22 GMT" },
{ "name":"core-staging", "type":"directory", "mtime":"Fri, 19 May 2023 12:48:38 GMT" },
{ "name":"core-testing", "type":"directory", "mtime":"Fri, 19 May 2023 12:48:38 GMT" },
{ "name":"extra", "type":"directory", "mtime":"Wed, 22 Sep 2010 04:59:16 GMT" },
{ "name":"extra-staging", "type":"directory", "mtime":"Fri, 19 May 2023 12:41:55 GMT" },
{ "name":"extra-testing", "type":"directory", "mtime":"Fri, 19 May 2023 12:41:54 GMT" },
{ "name":"gnome-unstable", "type":"directory", "mtime":"Fri, 12 Feb 2010 21:35:31 GMT" },
{ "name":"images", "type":"directory", "mtime":"Sun, 15 Mar 2026 12:16:37 GMT" },
{ "name":"iso", "type":"directory", "mtime":"Sun, 01 Mar 2026 10:57:34 GMT" },
{ "name":"kde-unstable", "type":"directory", "mtime":"Fri, 18 Dec 2009 17:36:26 GMT" },
{ "name":"latest", "type":"directory", "mtime":"Sat, 12 Apr 2025 11:29:09 GMT" },
{ "name":"multilib", "type":"directory", "mtime":"Tue, 24 Aug 2010 18:14:16 GMT" },
{ "name":"multilib-staging", "type":"directory", "mtime":"Sat, 14 Jan 2012 19:09:19 GMT" },
{ "name":"multilib-testing", "type":"directory", "mtime":"Sat, 11 Sep 2010 16:28:50 GMT" },
{ "name":"pool", "type":"directory", "mtime":"Tue, 23 May 2023 08:50:22 GMT" },
{ "name":"staging", "type":"directory", "mtime":"Tue, 17 Aug 2010 05:51:59 GMT" },
{ "name":"testing", "type":"directory", "mtime":"Fri, 18 Sep 2009 20:31:33 GMT" },
{ "name":"wsl", "type":"directory", "mtime":"Sun, 01 Mar 2026 10:23:56 GMT" },
{ "name":"lastsync", "type":"file", "mtime":"Mon, 16 Mar 2026 02:11:01 GMT", "size":11 },
{ "name":"lastupdate", "type":"file", "mtime":"Sun, 15 Mar 2026 23:42:58 GMT", "size":11 }
]            </div>
        </footer>
    </body>
</html>