paste/src/routes/+page.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>