all repos — NoPaste @ 6c1448774c463ab49752183f57fe9b43b1ce4238

Resurrected - The PussTheCat.org fork of NoPaste

index.js (view raw)

  1const blob = new Blob(['importScripts("https://cdn.jsdelivr.net/npm/lzma@2.3.2/src/lzma_worker.min.js");']);
  2const lzma = new LZMA(window.URL.createObjectURL(blob));
  3
  4let editor = null;
  5let select = null;
  6let clipboard = null;
  7
  8const init = () => {
  9    initCodeEditor();
 10    initLangSelector();
 11    initCode();
 12    initClipboard();
 13};
 14
 15const initCodeEditor = () => {
 16    const readOnly = new URLSearchParams(window.location.search).has('readonly');
 17    CodeMirror.modeURL = 'https://cdn.jsdelivr.net/npm/codemirror@5.51.0/mode/%N/%N.js';
 18    editor = new CodeMirror(document.getElementById('editor'), {
 19        lineNumbers: true,
 20        theme: 'dracula',
 21        readOnly: readOnly
 22    });
 23    if (readOnly) {
 24        document.body.classList.add('readonly');
 25    }
 26};
 27
 28const initLangSelector = () => {
 29    select = new SlimSelect({
 30        select: '#language',
 31        data: CodeMirror.modeInfo.map(e => ({
 32            text: e.name,
 33            value: slugify(e.name),
 34            data: { mime: e.mime, mode: e.mode }
 35        })),
 36        showContent: 'up',
 37        onChange: e => {
 38            const language = e.data || { mime: null, mode: null };
 39            editor.setOption('mode', language.mime);
 40            CodeMirror.autoLoadMode(editor, language.mode);
 41        }
 42    });
 43
 44    select.set(decodeURIComponent(new URLSearchParams(window.location.search).get('lang') || 'plain-text'));
 45};
 46
 47const initCode = () => {
 48    const base64 = location.hash.substr(1);
 49    if (base64.length === 0) {
 50        return;
 51    }
 52    decompress(base64, (code, err) => {
 53        if (err) {
 54            alert('Failed to decompress data: ' + err);
 55            return;
 56        }
 57        editor.setValue(code);
 58    });
 59};
 60
 61const initClipboard = () => {
 62    clipboard = new ClipboardJS('.clipboard');
 63    clipboard.on('success', () => {
 64        hideCopyBar(true);
 65    });
 66};
 67
 68const generateLink = mode => {
 69    compress(editor.getValue(), (base64, err) => {
 70        if (err) {
 71            alert('Failed to compress data: ' + err);
 72            return;
 73        }
 74        const url = buildUrl(base64, mode);
 75        showCopyBar(url);
 76    });
 77};
 78
 79// Open the "Copy" bar and select the content
 80const showCopyBar = dataToCopy => {
 81    const linkInput = document.getElementById('copy-link');
 82    linkInput.value = dataToCopy;
 83    linkInput.setSelectionRange(0, dataToCopy.length);
 84    document.getElementById('copy').style.display = 'flex';
 85};
 86
 87// Close the "Copy" bar
 88const hideCopyBar = success => {
 89    const copyButton = document.getElementById('copy-btn');
 90    const copyBar = document.getElementById('copy');
 91    if (!success) {
 92        copyBar.style.display = 'none';
 93        return;
 94    }
 95    copyButton.innerText = 'Copied !';
 96    setTimeout(() => {
 97        copyBar.style.display = 'none';
 98        copyButton.innerText = 'Copy';
 99    }, 800);
100};
101
102// Build a shareable URL
103const buildUrl = (rawData, mode) => {
104    const url =
105        `${location.protocol}//${location.host}${location.pathname}` +
106        `?lang=${encodeURIComponent(select.selected())}` +
107        (mode === 'iframe' ? '&readonly' : '') +
108        `#${rawData}`;
109    if (mode === 'markdown') {
110        return `[paste](${url})`;
111    }
112    if (mode === 'iframe') {
113        const height = document.getElementsByClassName('CodeMirror-sizer')[0].scrollHeight;
114        return `<iframe width="100%" height="${height}" frameborder="0" src="${url}"></iframe>`;
115    }
116    return url;
117};
118
119// Transform a compressed base64 string into a plain text string
120const decompress = (base64, cb) => {
121    const progressBar = document.getElementById('progress');
122
123    const req = new XMLHttpRequest();
124    req.open('GET', 'data:application/octet;base64,' + base64);
125    req.responseType = 'arraybuffer';
126    req.onload = e => {
127        lzma.decompress(
128            new Uint8Array(e.target.response),
129            (result, err) => {
130                progressBar.style.width = '0';
131                cb(result, err);
132            },
133            progress => {
134                progressBar.style.width = 100 * progress + '%';
135            }
136        );
137    };
138    req.send();
139};
140
141// Transform a plain text string into a compressed base64 string
142const compress = (str, cb) => {
143    const progressBar = document.getElementById('progress');
144
145    lzma.compress(
146        str,
147        1,
148        (compressed, err) => {
149            if (err) {
150                progressBar.style.width = '0';
151                cb(compressed, err);
152                return;
153            }
154            const reader = new FileReader();
155            reader.onload = () => {
156                progressBar.style.width = '0';
157                cb(reader.result.substr(reader.result.indexOf(',') + 1));
158            };
159            reader.readAsDataURL(new Blob([new Uint8Array(compressed)]));
160        },
161        progress => {
162            progressBar.style.width = 100 * progress + '%';
163        }
164    );
165};
166
167const slugify = str =>
168    str
169        .toString()
170        .toLowerCase()
171        .replace(/\s+/g, '-')
172        .replace(/\+/g, '-p')
173        .replace(/#/g, '-sharp')
174        .replace(/[^\w\-]+/g, '');
175
176init();