116 lines
3.0 KiB
Svelte
116 lines
3.0 KiB
Svelte
<script lang="ts">
|
|
import type { Editor } from 'codemirror'
|
|
import { onMount } from 'svelte'
|
|
import { debounce } from 'lodash-es'
|
|
import * as brotli from '$lib/brotli'
|
|
import * as lzma from '$lib/lzma'
|
|
import { byId } from '$lib/utils'
|
|
import TopBar from '../components/TopBar.svelte'
|
|
import { selectedLang, shareUrl } from '../store'
|
|
|
|
let editor: Editor | null = null
|
|
const readOnly = false
|
|
|
|
let charLen = 0
|
|
let compressed: string = ''
|
|
let waiting = false
|
|
let setLanguage: (lang: string) => void
|
|
|
|
onMount(async () => {
|
|
initCodeEditor()
|
|
// extract the part in the url after the hash
|
|
const hash = window.location.hash.slice(1)
|
|
if (hash) {
|
|
// decompress the data
|
|
let decompressed: string
|
|
if (hash.startsWith('XQAAA')) {
|
|
decompressed = await lzma.decompress(hash)
|
|
} else {
|
|
decompressed = await brotli.decompress(hash)
|
|
}
|
|
// set the editor value
|
|
if (editor) {
|
|
editor.setValue(decompressed)
|
|
}
|
|
}
|
|
|
|
const lang = new URLSearchParams(window.location.search).get('l')
|
|
if (lang) {
|
|
setLanguage(lang)
|
|
}
|
|
else {
|
|
setLanguage('plt')
|
|
}
|
|
})
|
|
|
|
async function updateShareUrl() {
|
|
if (editor) {
|
|
const url = new URL(window.location.href)
|
|
compressed = await brotli.compress(editor.getValue())
|
|
if ($selectedLang) {
|
|
url.searchParams.set('l', $selectedLang)
|
|
}
|
|
url.hash = compressed
|
|
$shareUrl = url.toString()
|
|
}
|
|
}
|
|
|
|
const updateShareUrlDebounced = debounce(async () => {
|
|
updateShareUrl()
|
|
waiting = false
|
|
}, 1000)
|
|
|
|
const initCodeEditor = () => {
|
|
CodeMirror.modeURL = 'https://cdn.jsdelivr.net/npm/codemirror@5.65.5/mode/%N/%N.js'
|
|
editor = new CodeMirror(byId('editor'), {
|
|
lineNumbers: true,
|
|
theme: 'dracula',
|
|
readOnly: readOnly,
|
|
lineWrapping: false,
|
|
scrollbarStyle: 'native',
|
|
}) as Editor
|
|
|
|
if (readOnly) {
|
|
document.body.classList.add('readonly')
|
|
}
|
|
|
|
editor.on('change', async () => {
|
|
if (editor) {
|
|
waiting = true
|
|
charLen = editor.getValue().length
|
|
updateShareUrlDebounced()
|
|
}
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<div class="flex flex-col font-mono h-screen bg-gray-700">
|
|
<TopBar {editor} {updateShareUrl} bind:setLanguage />
|
|
|
|
<div id="editor" class="grow overflow-hidden" />
|
|
|
|
{editor?.getValue()}
|
|
|
|
<div id="footer" class="p-2 text-sm z-10">
|
|
Data length: {charLen}
|
|
| Link length: {waiting ? '?' : $shareUrl.length}
|
|
({waiting || !compressed.length || !charLen
|
|
? '?'
|
|
: Math.round(($shareUrl.length / charLen) * 100)}% of original)
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
:global(div.CodeMirror) {
|
|
height: 100%;
|
|
font-size: 15px;
|
|
}
|
|
#footer {
|
|
--tw-shadow: 0 -4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
--tw-shadow-colored: 0 -4px 6px -1px var(--tw-shadow-color),
|
|
0 2px 4px -2px var(--tw-shadow-color);
|
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
|
var(--tw-shadow);
|
|
}
|
|
</style>
|