inkyboo/index.js

213 lines
6.2 KiB
JavaScript
Raw Normal View History

const blob = new Blob(['importScripts("https://cdn.jsdelivr.net/npm/lzma@2.3.2/src/lzma_worker.min.js");']);
const lzma = new LZMA(window.URL.createObjectURL(blob));
2020-02-17 15:05:42 +00:00
let editor = null;
let select = null;
let clipboard = null;
2020-04-24 13:30:20 +00:00
let statsEl = null;
2020-02-13 15:02:17 +00:00
2020-04-27 15:03:02 +00:00
const initCodeEditor = (initialValue) => {
2020-03-09 14:54:31 +00:00
CodeMirror.modeURL = 'https://cdn.jsdelivr.net/npm/codemirror@5.52.0/mode/%N/%N.js';
2020-04-25 22:53:10 +00:00
editor = new CodeMirror(byId('editor'), {
2020-02-17 15:05:42 +00:00
lineNumbers: true,
2020-03-09 13:38:28 +00:00
theme: 'dracula',
2020-03-09 14:54:31 +00:00
readOnly: readOnly,
2020-04-27 15:03:02 +00:00
lineWrapping: false,
2020-04-22 16:50:44 +00:00
scrollbarStyle: 'simple',
2020-04-27 15:03:02 +00:00
value: initialValue,
2020-02-13 15:02:17 +00:00
});
2020-03-09 13:38:28 +00:00
if (readOnly) {
document.body.classList.add('readonly');
}
2020-04-24 13:30:20 +00:00
2020-04-25 22:53:10 +00:00
statsEl = byId('stats');
2020-04-27 15:03:02 +00:00
statsEl.innerHTML = `Length: ${initialValue.length} | Lines: ${editor['doc'].size}`;
2020-04-24 13:30:20 +00:00
editor.on('change', () => {
statsEl.innerHTML = `Length: ${editor.getValue().length} | Lines: ${editor['doc'].size}`;
});
2020-04-27 15:03:02 +00:00
initLangSelector();
2020-02-17 15:05:42 +00:00
};
2020-02-13 15:02:17 +00:00
2020-02-17 15:05:42 +00:00
const initLangSelector = () => {
2020-02-13 15:02:17 +00:00
select = new SlimSelect({
select: '#language',
2020-04-22 16:50:44 +00:00
data: CodeMirror.modeInfo.map((e) => ({
text: e.name,
value: slugify(e.name),
2020-04-22 16:50:44 +00:00
data: { mime: e.mime, mode: e.mode },
})),
2020-04-22 16:50:44 +00:00
showContent: 'down',
onChange: (e) => {
const language = e.data || { mime: null, mode: null };
editor.setOption('mode', language.mime);
CodeMirror.autoLoadMode(editor, language.mode);
2020-04-22 16:50:44 +00:00
},
2020-02-13 15:02:17 +00:00
});
2020-03-09 13:38:28 +00:00
select.set(decodeURIComponent(new URLSearchParams(window.location.search).get('lang') || 'plain-text'));
2020-02-17 15:05:42 +00:00
};
2020-02-13 15:02:17 +00:00
2020-02-17 15:05:42 +00:00
const initCode = () => {
2020-04-25 15:35:22 +00:00
const base64 = location.pathname.substr(1) || location.hash.substr(1);
2020-02-13 15:02:17 +00:00
if (base64.length === 0) {
2020-04-27 15:03:02 +00:00
initCodeEditor('');
2020-02-13 15:02:17 +00:00
return;
}
2020-02-17 15:05:42 +00:00
decompress(base64, (code, err) => {
if (err) {
alert('Failed to decompress data: ' + err);
2020-04-27 15:03:02 +00:00
initCodeEditor('');
2020-02-17 15:05:42 +00:00
return;
}
2020-04-27 15:03:02 +00:00
initCodeEditor(code);
2020-02-17 15:05:42 +00:00
});
};
const initClipboard = () => {
clipboard = new ClipboardJS('.clipboard');
clipboard.on('success', () => {
hideCopyBar(true);
});
};
2020-02-13 15:02:17 +00:00
2020-04-22 16:50:44 +00:00
const generateLink = (mode) => {
2020-04-24 13:30:20 +00:00
const data = editor.getValue();
compress(data, (base64, err) => {
2020-02-17 15:05:42 +00:00
if (err) {
alert('Failed to compress data: ' + err);
return;
}
2020-03-05 13:33:21 +00:00
const url = buildUrl(base64, mode);
2020-04-24 13:30:20 +00:00
statsEl.innerHTML = `Data length: ${data.length} | Link length: ${
url.length
} | Compression ratio: ${Math.round((100 * url.length) / data.length)}%`;
2020-02-17 15:05:42 +00:00
showCopyBar(url);
});
};
// Open the "Copy" bar and select the content
2020-04-22 16:50:44 +00:00
const showCopyBar = (dataToCopy) => {
byId('copy').classList.remove('hidden');
2020-04-25 22:53:10 +00:00
const linkInput = byId('copy-link');
2020-02-17 15:05:42 +00:00
linkInput.value = dataToCopy;
linkInput.focus();
2020-02-17 15:05:42 +00:00
linkInput.setSelectionRange(0, dataToCopy.length);
};
// Close the "Copy" bar
2020-04-22 16:50:44 +00:00
const hideCopyBar = (success) => {
2020-04-25 22:53:10 +00:00
const copyButton = byId('copy-btn');
const copyBar = byId('copy');
2020-02-17 15:05:42 +00:00
if (!success) {
2020-04-24 10:24:08 +00:00
copyBar.classList.add('hidden');
2020-02-13 15:02:17 +00:00
return;
}
2020-02-17 15:05:42 +00:00
copyButton.innerText = 'Copied !';
setTimeout(() => {
2020-04-24 10:24:08 +00:00
copyBar.classList.add('hidden');
2020-02-17 15:05:42 +00:00
copyButton.innerText = 'Copy';
}, 800);
};
const disableLineWrapping = () => {
byId('disable-line-wrapping').classList.add('hidden');
byId('enable-line-wrapping').classList.remove('hidden');
editor.setOption('lineWrapping', false);
};
const enableLineWrapping = () => {
byId('enable-line-wrapping').classList.add('hidden');
byId('disable-line-wrapping').classList.remove('hidden');
editor.setOption('lineWrapping', true);
};
2020-04-27 15:03:02 +00:00
const openInNewTab = () => {
window.open(location.href.replace('&readonly', ''));
};
2020-02-17 15:05:42 +00:00
// Build a shareable URL
2020-03-05 13:33:21 +00:00
const buildUrl = (rawData, mode) => {
2020-04-25 15:35:22 +00:00
const url = `${location.protocol}//${location.host}/` + rawData + `?lang=${encodeURIComponent(select.selected())}`;
2020-03-09 13:38:28 +00:00
if (mode === 'markdown') {
2020-04-23 16:29:59 +00:00
return `[NoPaste snippet](${url})`;
2020-03-09 13:38:28 +00:00
}
if (mode === 'iframe') {
2020-04-27 15:03:02 +00:00
const height = Math.min(editor['doc'].height + 45, 800);
return `<iframe width="100%" height="${height}" frameborder="0" src="${url}"></iframe>`;
2020-03-09 13:38:28 +00:00
}
return url;
2020-02-17 15:05:42 +00:00
};
2020-02-13 15:02:17 +00:00
2020-02-17 15:05:42 +00:00
// Transform a compressed base64 string into a plain text string
const decompress = (base64, cb) => {
2020-04-25 22:53:10 +00:00
const progressBar = byId('progress');
2020-02-17 15:41:54 +00:00
2020-02-17 15:05:42 +00:00
const req = new XMLHttpRequest();
req.open('GET', 'data:application/octet;base64,' + base64);
req.responseType = 'arraybuffer';
2020-04-22 16:50:44 +00:00
req.onload = (e) => {
2020-02-17 15:41:54 +00:00
lzma.decompress(
new Uint8Array(e.target.response),
(result, err) => {
progressBar.style.width = '0';
cb(result, err);
},
2020-04-22 16:50:44 +00:00
(progress) => {
2020-02-17 15:41:54 +00:00
progressBar.style.width = 100 * progress + '%';
}
);
2020-02-17 15:05:42 +00:00
};
req.send();
};
2020-02-13 15:02:17 +00:00
2020-02-17 15:05:42 +00:00
// Transform a plain text string into a compressed base64 string
const compress = (str, cb) => {
2020-04-25 22:53:10 +00:00
const progressBar = byId('progress');
2020-02-17 15:41:54 +00:00
lzma.compress(
str,
1,
(compressed, err) => {
if (err) {
progressBar.style.width = '0';
cb(compressed, err);
return;
}
const reader = new FileReader();
reader.onload = () => {
progressBar.style.width = '0';
cb(reader.result.substr(reader.result.indexOf(',') + 1));
};
reader.readAsDataURL(new Blob([new Uint8Array(compressed)]));
},
2020-04-22 16:50:44 +00:00
(progress) => {
2020-02-17 15:41:54 +00:00
progressBar.style.width = 100 * progress + '%';
2020-02-13 15:02:17 +00:00
}
2020-02-17 15:41:54 +00:00
);
2020-02-17 15:05:42 +00:00
};
2020-02-13 15:02:17 +00:00
2020-04-22 16:50:44 +00:00
const slugify = (str) =>
str
.toString()
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/\+/g, '-p')
.replace(/#/g, '-sharp')
.replace(/[^\w\-]+/g, '');
2020-04-25 22:53:10 +00:00
const byId = (id) => document.getElementById(id);
2020-03-09 14:54:31 +00:00
/* Only for tests purposes */
const testAllModes = () => {
for (const [index, language] of Object.entries(CodeMirror.modeInfo)) {
setTimeout(() => {
console.info(language.name);
select.set(slugify(language.name));
}, 1000 * index);
}
};
2020-04-27 15:03:02 +00:00
initCode(); // Will decode URL, create code editor, and language selector
initClipboard();