diff --git a/dataoptions.js b/dataoptions.js index 9e9cf07..0b529b3 100644 --- a/dataoptions.js +++ b/dataoptions.js @@ -3,36 +3,36 @@ import { PLAINTEXT, LANGUAGES } from "./languages.js"; const UTF8_ENCODER = new TextEncoder(); const UTF8_DECODER = new TextDecoder(); -class DataOptionsError extends Error { } -class DecodeError extends DataOptionsError { } +class DataOptionsError extends Error {} +class DecodeError extends DataOptionsError {} /** * Data options are stored in a binary header before the payload. - * + * * The header consists of a fixed section, followed by a dynamic section. * The fixed section consists of bytes with a fixed meaning and positioning. * The dynamic section is based on the contents of the fixed section and * contains data related to the fixed section. - * + * * Fixed section: - * + * * Byte 1 * |xxx----y| * x = amount of extra bytes (other than this byte) in the header's fixed * section (uid) * y = highest bit of language ID (the rest in byte 2) - * + * * Byte 2 (+ lowest bit of byte 1) is language ID (uint), i.e. index of the * language in the LANGUAGE_NAMES list. - * + * * Byte 3 is number of bytes reserved for the page title. - * + * * Dynamic section parts: - * + * * 1. Bytes of page title (UTF-8). - * + * * --- - * + * * NOTE: If options are set to their default values, the header is minimised * to not include those bytes if possible. */ @@ -51,7 +51,7 @@ export class DataOptions { if (fixedHeaderBytes >= 2) { const languageIDLowByte = data[1]; - const languageIDHighBit = (byte1 & 0b00000001); + const languageIDHighBit = byte1 & 0b00000001; const languageID = (languageIDHighBit << 8) | languageIDLowByte; if (LANGUAGES.has(languageID)) { diff --git a/tahnaroskakori.js b/tahnaroskakori.js index cec823c..190047c 100644 --- a/tahnaroskakori.js +++ b/tahnaroskakori.js @@ -1,4 +1,8 @@ -import brotliInit, { compress, DecompressStream, BrotliStreamResult } from "./vendor/brotli_wasm.js"; +import brotliInit, { + compress, + DecompressStream, + BrotliStreamResult, +} from "./vendor/brotli_wasm.js"; import base from "./vendor/base-x.js"; import "./vendor/prism/prism.js"; import "./vendor/prism/plugins/line-numbers/prism-line-numbers.js"; @@ -7,12 +11,19 @@ import "./vendor/prism/dependencies.js"; import { waitForLoad } from "./utils.js"; import { DataOptions } from "./dataoptions.js"; import { ViewMode } from "./viewmode.js"; -import { getDependenciesForLanguage, getDepsData, LANGUAGES, LANGUAGE_NAMES, PLAINTEXT } from "./languages.js"; +import { + getDependenciesForLanguage, + getDepsData, + LANGUAGES, + LANGUAGE_NAMES, + PLAINTEXT, +} from "./languages.js"; const PROJECT_NAME = "Tahnaroskakori"; const COMPRESS_WAIT = 500; const ENCODER = new TextEncoder(); -const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789?/-._~$&+="; +const ALPHABET = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789?/-._~$&+="; const BASECODEC = base(ALPHABET); const QUALITY = 11; const MAX_URL = 2048; @@ -41,7 +52,9 @@ function setTitle() { if (dataOptions.title !== "") { document.title = dataOptions.title + TITLE_POSTFIX; } else if (currentCode !== "") { - document.title = currentCode.replace("\n", "").substring(0, TITLE_CODE_LENGTH) + TITLE_POSTFIX; + document.title = + currentCode.replace("\n", "").substring(0, TITLE_CODE_LENGTH) + + TITLE_POSTFIX; } else { document.title = PROJECT_NAME; } @@ -69,7 +82,7 @@ function renderLanguageOptions() { /** * Use Prism to highlight the current language. - * + * * The language definition will be imported if necessary. */ async function highlightLanguage() { @@ -80,9 +93,12 @@ async function highlightLanguage() { codeViewEl.classList.add(getLanguageClassName(dataOptions.language)); if (dataOptions.language !== PLAINTEXT) { - const deps = getDependenciesForLanguage(languageDependencies, dataOptions.language); + const deps = getDependenciesForLanguage( + languageDependencies, + dataOptions.language + ); for (const dep of [...deps, dataOptions.language]) { - await import(`./vendor/prism/components/prism-${dep}.js`) + await import(`./vendor/prism/components/prism-${dep}.js`); } if (viewMode === ViewMode.VIEW) { @@ -177,7 +193,9 @@ async function syncCompress() { const compressed = compress(dataWithHeader, { quality: QUALITY }); const encoded = BASECODEC.encode(compressed); - statusEl.textContent = `Length: ${dataWithHeader.length} B -> ${compressed.length} B -> ${encoded.length}/${maxHashLength()} chars`; + statusEl.textContent = `Length: ${dataWithHeader.length} B -> ${ + compressed.length + } B -> ${encoded.length}/${maxHashLength()} chars`; if (encoded.length <= maxHashLength()) { history.replaceState(null, "", `#${encoded}`); @@ -209,34 +227,42 @@ async function streamDecompress() { start(controller) { controller.enqueue(data); controller.close(); - } + }, }); const decompressStream = new DecompressStream(); const decompressionRunner = new TransformStream({ - start() { }, + start() {}, transform(chunk, controller) { - controller.enqueue(decompressStream.decompress(chunk, DECOMPRESS_CHUNK_SIZE)); + controller.enqueue( + decompressStream.decompress(chunk, DECOMPRESS_CHUNK_SIZE) + ); let slice = chunk; - while (decompressStream.result() === BrotliStreamResult.NeedsMoreOutput) { + while ( + decompressStream.result() === BrotliStreamResult.NeedsMoreOutput + ) { slice = slice.slice(decompressStream.last_input_offset()); - controller.enqueue(decompressStream.decompress(slice, DECOMPRESS_CHUNK_SIZE)); + controller.enqueue( + decompressStream.decompress(slice, DECOMPRESS_CHUNK_SIZE) + ); } }, flush(controller) { if (decompressStream.result() === BrotliStreamResult.NeedsMoreInput) { - controller.enqueue(decompressStream.decompress("", DECOMPRESS_CHUNK_SIZE)); + controller.enqueue( + decompressStream.decompress("", DECOMPRESS_CHUNK_SIZE) + ); } controller.terminate(); - } + }, }); const optionsPickerStream = new TransformStream({ firstChunk: false, - start() { }, + start() {}, transform(chunk, controller) { if (!this.firstChunk) { const rest = dataOptions.parseFrom(chunk); @@ -250,7 +276,7 @@ async function streamDecompress() { } else { controller.enqueue(chunk); } - } + }, }); const textDecoderStream = new TextDecoderStream(); @@ -265,8 +291,10 @@ async function streamDecompress() { renderCode(); // Delay stream between every chunk to avoid zip bombing - return new Promise(resolve => setTimeout(resolve, DECOMPRESS_CHUNK_TIMEOUT)); - } + return new Promise((resolve) => + setTimeout(resolve, DECOMPRESS_CHUNK_TIMEOUT) + ); + }, }); await inputStream @@ -287,7 +315,9 @@ async function streamDecompress() { */ async function languageSelected() { codeViewEl.classList.remove(getLanguageClassName(dataOptions.language)); - codeViewContentEl.classList.remove(getLanguageClassName(dataOptions.language)); + codeViewContentEl.classList.remove( + getLanguageClassName(dataOptions.language) + ); if (LANGUAGES.has(languageSelectEl.value)) { dataOptions.language = languageSelectEl.value; @@ -339,11 +369,7 @@ async function init() { renderLanguageOptions(); renderView(); - [languageDependencies,] = await Promise.all([ - getDepsData(), - brotliInit(), - ]); - + [languageDependencies] = await Promise.all([getDepsData(), brotliInit()]); codeEditEl.addEventListener("input", codeEdited); viewModeSwitcherEl.addEventListener("click", switchMode); diff --git a/utils.js b/utils.js index 6751db9..176c6b9 100644 --- a/utils.js +++ b/utils.js @@ -3,13 +3,12 @@ * @returns {Promise} */ export function waitForLoad() { - return new Promise(resolve => { + return new Promise((resolve) => { // If already loaded, fire immediately if (/complete|interactive|loaded/.test(document.readyState)) { resolve(); - } - else { - document.addEventListener('DOMContentLoaded', resolve); + } else { + document.addEventListener("DOMContentLoaded", resolve); } }); }