PHPIndex

This page lists files in the current directory. You can view content, get download/execute commands for Wget, Curl, or PowerShell, or filter the list using wildcards (e.g., `*.sh`).

json-tool.html
wget 'https://sme10.lists2.roe3.org/spreadsheet/tools/json-tool.html'
View Content
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JSON to URL Hash Converter</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: #1a1a2e;
            color: #eee;
            min-height: 100vh;
            padding: 20px;
        }
        .container {
            max-width: 800px;
            margin: 0 auto;
        }
        h1 {
            text-align: center;
            margin-bottom: 24px;
            font-weight: 500;
            color: #fff;
        }
        .section {
            margin-bottom: 20px;
        }
        .section-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 8px;
        }
        label {
            font-size: 14px;
            color: #aaa;
        }
        textarea {
            width: 100%;
            height: 120px;
            padding: 12px;
            font-family: 'Consolas', 'Monaco', monospace;
            font-size: 13px;
            border: 1px solid #333;
            border-radius: 6px;
            background: #0f0f1a;
            color: #eee;
            resize: vertical;
        }
        textarea:focus {
            outline: none;
            border-color: #4a9eff;
        }
        textarea[readonly] {
            background: #16162a;
            color: #ccc;
        }
        .copy-btn {
            padding: 4px 12px;
            font-size: 12px;
            background: #2a2a4a;
            color: #aaa;
            border: 1px solid #444;
            border-radius: 4px;
            cursor: pointer;
            transition: all 0.2s;
        }
        .copy-btn:hover {
            background: #3a3a5a;
            color: #fff;
        }
        .copy-btn.copied {
            background: #2a5a2a;
            color: #8f8;
            border-color: #4a4;
        }
        .stats {
            display: flex;
            gap: 20px;
            padding: 12px 16px;
            background: #16162a;
            border-radius: 6px;
            font-size: 13px;
            color: #888;
        }
        .stat {
            display: flex;
            gap: 6px;
        }
        .stat-value {
            color: #4a9eff;
            font-weight: 500;
        }
        .error {
            color: #ff6b6b;
            font-size: 13px;
            margin-top: 8px;
            display: none;
        }
        .error.visible {
            display: block;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>JSON to URL Hash Converter</h1>

        <div class="section">
            <div class="section-header">
                <label>1. Paste JSON Object</label>
            </div>
            <textarea id="input" placeholder='{"name": "example", "value": 123}'></textarea>
            <div id="error" class="error"></div>
        </div>

        <div class="section">
            <div class="section-header">
                <label>2. Stringified JSON</label>
                <button class="copy-btn" data-target="stringified">Copy</button>
            </div>
            <textarea id="stringified" readonly placeholder="Stringified output will appear here..."></textarea>
        </div>

        <div class="section">
            <div class="section-header">
                <label>3. LZString URL Hash</label>
                <button class="copy-btn" data-target="urlHash">Copy</button>
            </div>
            <textarea id="urlHash" readonly placeholder="Compressed URL hash will appear here..."></textarea>
        </div>

        <div class="stats">
            <div class="stat">Input: <span id="inputLen" class="stat-value">0</span> chars</div>
            <div class="stat">Stringified: <span id="stringLen" class="stat-value">0</span> chars</div>
            <div class="stat">Compressed: <span id="compressLen" class="stat-value">0</span> chars</div>
            <div class="stat">Ratio: <span id="ratio" class="stat-value">-</span></div>
        </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/lz-string/1.5.0/lz-string.min.js"
        integrity="sha512-qtX0GLM3qX8rxJN1gyDfcnMFFrKvixfoEOwbBib9VafR5vbChV5LeE5wSI/x+IlCkTY5ZFddFDCCfaVJJNnuKQ=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>

    <script>
        const inputEl = document.getElementById('input');
        const stringifiedEl = document.getElementById('stringified');
        const urlHashEl = document.getElementById('urlHash');
        const errorEl = document.getElementById('error');
        const inputLenEl = document.getElementById('inputLen');
        const stringLenEl = document.getElementById('stringLen');
        const compressLenEl = document.getElementById('compressLen');
        const ratioEl = document.getElementById('ratio');

        function clearOutputs() {
            stringifiedEl.value = '';
            urlHashEl.value = '';
            inputLenEl.textContent = '0';
            stringLenEl.textContent = '0';
            compressLenEl.textContent = '0';
            ratioEl.textContent = '-';
            errorEl.classList.remove('visible');
        }

        function showError(msg) {
            errorEl.textContent = msg;
            errorEl.classList.add('visible');
            stringifiedEl.value = '';
            urlHashEl.value = '';
            stringLenEl.textContent = '0';
            compressLenEl.textContent = '0';
            ratioEl.textContent = '-';
        }

        function convert() {
            const input = inputEl.value.trim();
            inputLenEl.textContent = input.length;

            if (!input) {
                clearOutputs();
                return;
            }

            try {
                const parsed = JSON.parse(input);
                const stringified = JSON.stringify(parsed);
                const compressed = LZString.compressToEncodedURIComponent(stringified);

                stringifiedEl.value = stringified;
                urlHashEl.value = compressed;
                stringLenEl.textContent = stringified.length;
                compressLenEl.textContent = compressed.length;

                const ratio = ((1 - compressed.length / stringified.length) * 100).toFixed(1);
                ratioEl.textContent = ratio + '%';

                errorEl.classList.remove('visible');
            } catch (e) {
                showError('Invalid JSON: ' + e.message);
            }
        }

        inputEl.addEventListener('input', convert);

        document.querySelectorAll('.copy-btn').forEach(btn => {
            btn.addEventListener('click', () => {
                const target = document.getElementById(btn.dataset.target);
                if (!target.value) return;

                navigator.clipboard.writeText(target.value).then(() => {
                    btn.textContent = 'Copied!';
                    btn.classList.add('copied');
                    setTimeout(() => {
                        btn.textContent = 'Copy';
                        btn.classList.remove('copied');
                    }, 1500);
                });
            });
        });
    </script>
</body>
</html>