Greasy Fork is available in English.

convertSpeedUnit

将网速单位从bit转换为Byte

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         convertSpeedUnit
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  将网速单位从bit转换为Byte
// @author       ExcuseLme
// @namespace    https://github.com/ExcuseLme
// @match        *://fast.com/*
// @icon         https://fast.com/assets/new-logo-vert-37861c.svg
// @grant        none
// @run-at       document-start
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const CONFIG = {
        targets: [
            { id: 'speed-value', type: 'value' },
            { id: 'speed-units', type: 'unit' },
            { id: 'upload-value', type: 'value' },
            { id: 'upload-units', type: 'unit' }
        ]
    };

    /**
     * 核心转换逻辑
     */
    function convertValue(raw) {
        let val = parseFloat(raw) / 8;
        if (isNaN(val)) return raw;
        // 遵循原站 Math.round 步进逻辑
        if (val < 9.95) return (Math.round(10 * val) / 10).toFixed(1);
        if (val < 100) return Math.round(val).toString();
        return (10 * Math.round(val / 10)).toString();
    }

    function convertUnit(raw) {
        return raw.replace('Kbps', 'KB/s')
                  .replace('Mbps', 'MB/s')
                  .replace('Gbps', 'GB/s');
    }

    /**
     * 同步并输出审计日志
     */
    function sync(target, original, shadow) {
        const rawText = original.innerText.trim();
        if (!rawText) return;

        let convertedText = (target.type === 'value') ? convertValue(rawText) : convertUnit(rawText);

        if (shadow.innerText !== convertedText) {
            shadow.innerText = convertedText;

            // 日志审计逻辑:仅在数值更新时输出完整链路,避免单位更新时重复输出
            if (target.type === 'value') {
                const isUpload = target.id.includes('upload');
                const unitId = isUpload ? 'upload-units' : 'speed-units';
                const rawUnit = document.getElementById(unitId)?.innerText.trim() || '';
                const convUnit = convertUnit(rawUnit);

                console.log(`%c[speedConvertScript] %c${rawText}${rawUnit} %c-> %c${convertedText}${convUnit}`,
                    "color: #00ADED; font-weight: bold;",
                    "color: #ff4757;",
                    "color: #2f3542;",
                    "color: #2ed573; font-weight: bold;");
            }
        }
    }

    /**
     * 初始化与 DOM 挂载
     */
    function processElement(target) {
        const original = document.getElementById(target.id);
        if (!original || original.dataset.hasShadow) return;

        const shadow = document.createElement(original.tagName);
        shadow.id = `shadow-${target.id}`;
        shadow.className = original.className;

        // 隐藏原件
        original.style.setProperty('display', 'none', 'important');
        original.parentNode.insertBefore(shadow, original);
        original.dataset.hasShadow = 'true';

        // 监听变动
        const observer = new MutationObserver(() => sync(target, original, shadow));
        observer.observe(original, { characterData: true, childList: true, subtree: true });

        // 初始同步
        sync(target, original, shadow);
    }

    // 全局 DOM 守卫
    const mainObserver = new MutationObserver(() => CONFIG.targets.forEach(processElement));

    const init = () => {
        if (document.body) {
            mainObserver.observe(document.body, { childList: true, subtree: true });
            CONFIG.targets.forEach(processElement);
        } else {
            setTimeout(init, 50);
        }
    };

    init();
})();