Greasy Fork 还支持 简体中文。

Wikipedia Wikibase Enhanced

Enhance the display of Wikimedia dump files with sorting and size conversion options.

Ekde 2024/10/05. Vidu La ĝisdata versio.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Wikipedia Wikibase Enhanced
// @namespace    Wikibase
// @version      1.0
// @description  Enhance the display of Wikimedia dump files with sorting and size conversion options.
// @match        https://dumps.wikimedia.org/other/*/*
// @icon         https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://dumps.wikimedia.org/&size=256
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const switchContainer = document.createElement('div');
    switchContainer.style.position = 'fixed';
    switchContainer.style.top = '80px';
    switchContainer.style.right = '10px';
    switchContainer.style.padding = '20px';
    switchContainer.style.backgroundColor = '#ffffff';
    switchContainer.style.border = '2px solid #007bff';
    switchContainer.style.borderRadius = '10px';
    switchContainer.style.zIndex = '1000';
    switchContainer.style.boxShadow = '0 4px 10px rgba(0, 0, 0, 0.3)';
    switchContainer.style.fontFamily = 'Arial, Helvetica, sans-serif';
    switchContainer.style.fontSize = '16px';

    switchContainer.innerHTML = `
        <div style="display: flex; align-items: center; margin-bottom: 20px;">
            <label style="margin-right: 15px;">
                <input type="radio" name="sizeSwitch" value="original" checked style="transform: scale(1.5); margin-right: 10px;"> Bytes
            </label>
            <label style="margin-right: 15px;">
                <input type="radio" name="sizeSwitch" value="KB" style="transform: scale(1.5); margin-right: 10px;"> KB
            </label>
            <label style="margin-right: 15px;">
                <input type="radio" name="sizeSwitch" value="MB" style="transform: scale(1.5); margin-right: 10px;"> MB
            </label>
            <label style="margin-right: 15px;">
                <input type="radio" name="sizeSwitch" value="GB" style="transform: scale(1.5); margin-right: 10px;"> GB
            </label>
        </div>
        <div style="display: flex; align-items: center; margin-bottom: 20px;">
            <label style="margin-right: 15px;">
                <input type="radio" name="sortOption" value="none" checked style="transform: scale(1.5); margin-right: 10px;"> Sort by Name (Default)
            </label>
            <label style="margin-right: 15px;">
                <input type="radio" name="sortOption" value="size" style="transform: scale(1.5); margin-right: 10px;"> Sort by Size
            </label>
            <label style="margin-right: 15px;">
                <input type="radio" name="sortOption" value="date" style="transform: scale(1.5); margin-right: 10px;"> Sort by Date
            </label>
        </div>
        <div>
            <input type="text" id="fileSearchInput" placeholder="Search records..." style="width: 100%; padding: 10px; margin-top: 20px; border: 1px solid #ccc; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);"/>
        </div>
    `;

    document.body.appendChild(switchContainer);

    document.querySelectorAll('pre').forEach((preTag) => {
        const originalPreTagContent = preTag.innerHTML;
        const lines = preTag.innerHTML.split('\n');
        const allElements = [];
        let hasParentDirectory = false;

        function parseDate(dateString) {
            const months = {
                Jan: '01', Feb: '02', Mar: '03', Apr: '04', May: '05', Jun: '06',
                Jul: '07', Aug: '08', Sep: '09', Oct: '10', Nov: '11', Dec: '12'
            };
            const dateParts = dateString.match(/(\d{2})-(\w{3})-(\d{4}) (\d{2}):(\d{2})/);
            if (!dateParts) return null;
            const day = dateParts[1];
            const month = months[dateParts[2]];
            const year = dateParts[3];
            const hours = dateParts[4];
            const minutes = dateParts[5];
            return new Date(`${year}-${month}-${day}T${hours}:${minutes}:00`);
        }

        for (let i = 0; i < lines.length; i++) {
            const line = lines[i];
            const linkMatch = line.match(/<a\s+href="([^"]*)".*?>(.*?)<\/a>/);
            if (linkMatch) {
                const linkHref = linkMatch[1];
                const linkText = linkMatch[2];
                if (linkText === '../') {
                    hasParentDirectory = true;
                    allElements.unshift({
                        lineIndex: i,
                        linkTag: `<a href="${linkHref}">${linkText}</a>`,
                        linkText,
                        dateTime: '',
                        parsedDate: null,
                        sizeInBytes: null,
                        originalText: line,
                        isFolder: true
                    });
                    continue;
                }

                const fileMatch = line.match(/<a.+<\/a>\s+(\d{2}-\w{3}-\d{4} \d{2}:\d{2})\s+(\d+)/);
                if (fileMatch) {
                    const dateTime = fileMatch[1];
                    const sizeValue = fileMatch[2];
                    const sizeInBytes = parseInt(sizeValue, 10);
                    const parsedDate = parseDate(dateTime);
                    allElements.push({
                        lineIndex: i,
                        linkTag: `<a href="${linkHref}">${linkText}</a>`,
                        linkText,
                        dateTime,
                        parsedDate,
                        sizeInBytes,
                        originalText: line,
                        isFolder: false
                    });
                } else {
                    const folderMatch = line.match(/<a.+<\/a>\s+(\d{2}-\w{3}-\d{4} \d{2}:\d{2})/);
                    if (folderMatch) {
                        const dateTime = folderMatch[1];
                        const parsedDate = parseDate(dateTime);
                        allElements.push({
                            lineIndex: i,
                            linkTag: `<a href="${linkHref}">${linkText}</a>`,
                            linkText,
                            dateTime,
                            parsedDate,
                            sizeInBytes: null,
                            originalText: line,
                            isFolder: true
                        });
                    } else {
                        allElements.push({
                            lineIndex: i,
                            linkTag: `<a href="${linkHref}">${linkText}</a>`,
                            linkText,
                            dateTime: '',
                            parsedDate: null,
                            sizeInBytes: null,
                            originalText: line,
                            isFolder: true
                        });
                    }
                }
            }
        }

        function updateDisplay(unit) {
            const searchInput = document.getElementById('fileSearchInput').value.toLowerCase();
            const sortOption = document.querySelector('input[name="sortOption"]:checked').value;

            let updatedElements = [...allElements];

            if (searchInput) {
                updatedElements = updatedElements.filter(item => item.linkText.toLowerCase().includes(searchInput) || item.linkText === '../');
            }

            if (sortOption === 'size') {
                updatedElements.sort((a, b) => {
                    if (a.sizeInBytes === null && b.sizeInBytes === null) {
                        return 0;
                    } else if (a.sizeInBytes === null) {
                        return 1;
                    } else if (b.sizeInBytes === null) {
                        return -1;
                    } else {
                        return b.sizeInBytes - a.sizeInBytes;
                    }
                });
            } else if (sortOption === 'date') {
                updatedElements.sort((a, b) => {
                    if (a.parsedDate === null && b.parsedDate === null) {
                        return 0;
                    } else if (a.parsedDate === null) {
                        return 1;
                    } else if (b.parsedDate === null) {
                        return -1;
                    } else {
                        return b.parsedDate - a.parsedDate;
                    }
                });
            } else if (sortOption === 'none') {
                updatedElements.sort((a, b) => a.linkText.localeCompare(b.linkText));
            }

            if (hasParentDirectory) {
                const parentDirectory = updatedElements.find(item => item.linkText === '../');
                updatedElements = [parentDirectory, ...updatedElements.filter(item => item.linkText !== '../')];
            }

            updatedElements.forEach(item => {
                if (item.isFolder) {
                    item.formattedSize = '-';
                } else {
                    if (unit === 'original') {
                        item.formattedSize = item.sizeInBytes ? item.sizeInBytes.toString() : '-';
                    } else {
                        let sizeValue;
                        switch (unit) {
                            case 'KB':
                                sizeValue = (item.sizeInBytes / 1024);
                                break;
                            case 'MB':
                                sizeValue = (item.sizeInBytes / (1024 * 1024));
                                break;
                            case 'GB':
                                sizeValue = (item.sizeInBytes / (1024 * 1024 * 1024));
                                break;
                        }
                        const sizeStr = sizeValue ? sizeValue.toFixed(2) : '-';
                        item.formattedSize = sizeStr + ' ' + unit;
                    }
                }
            });

            const maxLinkTextLength = Math.max(...updatedElements.map(item => item.linkText.length));
            const maxSizeLength = Math.max(...updatedElements.map(item => item.formattedSize.length));

            const updatedLines = updatedElements.map(item => {
                const paddedLinkText = item.linkText.padEnd(maxLinkTextLength, ' ');
                const newLinkTag = `<a href="${item.linkTag.match(/href="([^"]*)"/)[1]}" style="text-decoration: none;">${paddedLinkText}</a>`;
                const dateTime = item.dateTime ? item.dateTime : ''.padEnd(20, ' ');
                const paddedFormattedSize = item.formattedSize.padEnd(maxSizeLength, ' ');

                const spacesBeforeDate = ' '.repeat(51 - paddedLinkText.length);
                const spacesBeforeSize = ' '.repeat(8);

                let line = `${newLinkTag}${spacesBeforeDate}${dateTime}${spacesBeforeSize}${paddedFormattedSize}`;
                return `<span style="display: inline;">${line}</span>`;
            });

            preTag.innerHTML = updatedLines.join('\n');
        }

        document.querySelectorAll('input[name="sizeSwitch"]').forEach((input) => {
            input.addEventListener('change', (event) => {
                updateDisplay(event.target.value);
            });
        });

        document.querySelectorAll('input[name="sortOption"]').forEach((input) => {
            input.addEventListener('change', () => {
                const selectedUnit = document.querySelector('input[name="sizeSwitch"]:checked').value;
                updateDisplay(selectedUnit);
            });
        });

        document.getElementById('fileSearchInput').addEventListener('input', () => {
            const selectedUnit = document.querySelector('input[name="sizeSwitch"]:checked').value;
            updateDisplay(selectedUnit);
        });

        const selectedUnit = document.querySelector('input[name="sizeSwitch"]:checked').value;
        updateDisplay(selectedUnit);
    });
})();