Mercurial
annotate mrjunejune/src/tools/latex_editor/index.js @ 273:e02e2036ef84 default tip
add Layer 2 JRPG component system
Add reusable content and window modals, an isolated component sandbox, shared cyberpunk scroll areas, production-safe cache freshness, and server-rendered JRPG panel state.
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Sat, 08 Aug 2026 02:08:08 -0700 |
| parents | 3843bb6253ac |
| children |
| rev | line source |
|---|---|
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1 (function latexEditor() { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
2 "use strict"; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
3 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
4 const SOURCE_LIMIT = 64 * 1024; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
5 const STORAGE_KEY = "mrjunejune-latex-source"; |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
6 const AUTO_COMPILE_DELAY = 500; |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
7 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
8 window.addEventListener("DOMContentLoaded", () => { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
9 const source = document.querySelector("#latexSource"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
10 const compileButton = document.querySelector("#compileButton"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
11 const resetButton = document.querySelector("#resetButton"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
12 const autoCompile = document.querySelector("#autoCompile"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
13 const status = document.querySelector("#latexStatus"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
14 const sourceSize = document.querySelector("#sourceSize"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
15 const preview = document.querySelector("#pdfPreview"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
16 const diagnostics = document.querySelector("#latexDiagnostics"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
17 const download = document.querySelector("#downloadButton"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
18 if (!source || |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
19 !compileButton || |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
20 !resetButton || |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
21 !autoCompile || |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
22 !status || |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
23 !sourceSize || |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
24 !preview || |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
25 !diagnostics || |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
26 !download) return; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
27 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
28 const defaultSource = source.value; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
29 const savedSource = localStorage.getItem(STORAGE_KEY); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
30 if (savedSource) source.value = savedSource; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
31 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
32 let currentPdfUrl = null; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
33 let compileGeneration = 0; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
34 let controller = null; |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
35 let compilePending = false; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
36 let retryDelay = 0; |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
37 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
38 const byteLength = value => new TextEncoder().encode(value).byteLength; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
39 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
40 const setStatus = (message, state) => { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
41 status.textContent = message; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
42 status.dataset.state = state; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
43 }; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
44 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
45 const updateSize = () => { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
46 const size = byteLength(source.value); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
47 sourceSize.textContent = `${size.toLocaleString()} / ${SOURCE_LIMIT.toLocaleString()} bytes`; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
48 sourceSize.dataset.overLimit = size > SOURCE_LIMIT ? "true" : "false"; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
49 return size; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
50 }; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
51 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
52 const clearPdf = () => { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
53 if (currentPdfUrl) URL.revokeObjectURL(currentPdfUrl); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
54 currentPdfUrl = null; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
55 preview.src = "about:blank"; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
56 download.removeAttribute("href"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
57 download.removeAttribute("download"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
58 download.classList.add("disabled"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
59 download.setAttribute("aria-disabled", "true"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
60 }; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
61 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
62 const showDiagnostics = message => { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
63 clearPdf(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
64 diagnostics.textContent = message; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
65 diagnostics.hidden = false; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
66 preview.hidden = true; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
67 }; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
68 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
69 const showPdf = blob => { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
70 if (currentPdfUrl) URL.revokeObjectURL(currentPdfUrl); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
71 currentPdfUrl = URL.createObjectURL(blob); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
72 diagnostics.hidden = true; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
73 preview.hidden = false; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
74 preview.src = currentPdfUrl; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
75 download.href = currentPdfUrl; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
76 download.download = "document.pdf"; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
77 download.classList.remove("disabled"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
78 download.setAttribute("aria-disabled", "false"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
79 }; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
80 |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
81 const createDebouncer = (callback, delay) => { |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
82 let timer = null; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
83 const schedule = (nextDelay = delay) => { |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
84 clearTimeout(timer); |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
85 timer = setTimeout(() => { |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
86 timer = null; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
87 callback(); |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
88 }, nextDelay); |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
89 }; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
90 schedule.cancel = () => { |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
91 clearTimeout(timer); |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
92 timer = null; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
93 }; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
94 return schedule; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
95 }; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
96 |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
97 let queueCompile; |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
98 const compile = async () => { |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
99 queueCompile.cancel(); |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
100 const generation = ++compileGeneration; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
101 const text = source.value; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
102 const size = updateSize(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
103 if (!text.trim()) { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
104 showDiagnostics("Write some LaTeX before compiling."); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
105 setStatus("Nothing to compile.", "error"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
106 return; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
107 } |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
108 if (size > SOURCE_LIMIT) { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
109 showDiagnostics("The server accepts at most 64 KiB of LaTeX source."); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
110 setStatus("Source is too large.", "error"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
111 return; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
112 } |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
113 |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
114 if (controller) { |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
115 compilePending = true; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
116 setStatus("Finishing the current PDF, then compiling your latest changes...", "working"); |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
117 return; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
118 } |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
119 |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
120 compilePending = false; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
121 const requestController = new AbortController(); |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
122 controller = requestController; |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
123 compileButton.disabled = true; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
124 setStatus("Compiling on the server...", "working"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
125 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
126 try { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
127 const response = await fetch("/api/latex/render", { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
128 method: "POST", |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
129 headers: { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
130 "Content-Type": "text/plain; charset=utf-8", |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
131 }, |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
132 body: text, |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
133 cache: "no-store", |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
134 signal: requestController.signal, |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
135 }); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
136 if (generation !== compileGeneration) return; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
137 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
138 if (!response.ok) { |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
139 if (response.status === 429) { |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
140 compilePending = true; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
141 retryDelay = 1000; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
142 setStatus("The compiler is busy. Your latest changes are queued.", "working"); |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
143 return; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
144 } |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
145 const message = await response.text(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
146 showDiagnostics(message || `Compilation failed (${response.status}).`); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
147 setStatus("Fix the LaTeX errors shown in the preview pane.", "error"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
148 return; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
149 } |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
150 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
151 const blob = await response.blob(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
152 if (blob.type !== "application/pdf" || blob.size < 5) { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
153 throw new Error("The server returned an invalid PDF."); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
154 } |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
155 showPdf(blob); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
156 setStatus( |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
157 `PDF ready (${Math.ceil(blob.size / 1024).toLocaleString()} KiB).`, |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
158 "ready", |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
159 ); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
160 } catch (error) { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
161 if (error.name === "AbortError" || generation !== compileGeneration) return; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
162 showDiagnostics(error.message || "Unable to compile this document."); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
163 setStatus("The PDF request failed.", "error"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
164 } finally { |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
165 if (controller === requestController) { |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
166 controller = null; |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
167 compileButton.disabled = false; |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
168 } |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
169 if (compilePending && !controller) { |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
170 compilePending = false; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
171 const delay = retryDelay; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
172 retryDelay = 0; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
173 queueCompile(delay); |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
174 } |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
175 } |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
176 }; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
177 |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
178 queueCompile = createDebouncer(compile, AUTO_COMPILE_DELAY); |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
179 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
180 const invalidateCompile = () => { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
181 compileGeneration++; |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
182 compilePending = false; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
183 retryDelay = 0; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
184 queueCompile.cancel(); |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
185 }; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
186 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
187 source.addEventListener("input", () => { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
188 localStorage.setItem(STORAGE_KEY, source.value); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
189 invalidateCompile(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
190 const size = updateSize(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
191 if (!source.value.trim()) { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
192 showDiagnostics("Write some LaTeX before compiling."); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
193 setStatus("Nothing to compile.", "error"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
194 return; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
195 } |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
196 if (size > SOURCE_LIMIT) { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
197 showDiagnostics("The server accepts at most 64 KiB of LaTeX source."); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
198 setStatus("Source is too large.", "error"); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
199 return; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
200 } |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
201 setStatus( |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
202 autoCompile.checked ? "Waiting to compile..." : "Changes ready to compile.", |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
203 "working", |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
204 ); |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
205 if (autoCompile.checked) queueCompile(); |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
206 }); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
207 source.addEventListener("keydown", event => { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
208 if ((event.ctrlKey || event.metaKey) && event.key === "Enter") { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
209 event.preventDefault(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
210 compile(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
211 } |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
212 }); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
213 compileButton.addEventListener("click", compile); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
214 resetButton.addEventListener("click", () => { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
215 source.value = defaultSource; |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
216 localStorage.removeItem(STORAGE_KEY); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
217 updateSize(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
218 compile(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
219 }); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
220 autoCompile.addEventListener("change", () => { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
221 if (autoCompile.checked) queueCompile(); |
|
245
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
222 else { |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
223 queueCompile.cancel(); |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
224 compilePending = false; |
|
3843bb6253ac
[tools] Debounce live LaTeX preview
MrJuneJune <me@mrjunejune.com>
parents:
244
diff
changeset
|
225 } |
|
244
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
226 }); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
227 window.addEventListener("beforeunload", () => { |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
228 if (controller) controller.abort(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
229 if (currentPdfUrl) URL.revokeObjectURL(currentPdfUrl); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
230 }); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
231 |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
232 updateSize(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
233 compile(); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
234 }); |
|
b8aa08503378
[tools] Add sandboxed online LaTeX editor
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
235 })(); |