Syntax highlighting, rate limiting, creator auto-unlock (#1, #2, #26)
CI / test (push) Successful in 19s
CI / docker (push) Skipped

#1: server-side regex highlighter (highlight.go) for go/python/js/json/bash/sql;
token span classes styled in app.css; per-line so gutter stays aligned.
#2: in-memory token-bucket rate limiter (ratelimit.go) on POST /api/pastes,
/api/guess-language and unlock POST; 429 + Retry-After + X-RateLimit headers.
#26: new-page JS POSTs the password to /{id} with ?next= after creation; the
unlock handler honors same-origin ?next= redirect so the creator lands on the
unlocked paste. POST /{id} route added.

Tests: ratelimit_test.go (burst/429, refill, unlock limit, highlight, auto-
unlock e2e); existing tests updated for per-test limiter isolation.
This commit is contained in:
2026-09-08 21:09:25 -05:00
parent 9d75d2f80d
commit 3facff3d1e
11 changed files with 511 additions and 4 deletions
+5
View File
@@ -129,6 +129,11 @@ body {
}
.code .gutter { flex-shrink: 0; }
.codebody { padding: 0 18px; white-space: pre; }
/* syntax highlight tokens (#1) */
.tok-kw { color: #c792ea; }
.tok-str { color: #a5e075; }
.tok-num { color: #f78c6c; }
.tok-com { color: #6a737d; font-style: italic; }
.footnote { display: flex; gap: 20px; padding: 10px 18px; font-size: 20.7px; color: var(--muted-fg); border-top: 1px solid var(--border); flex-wrap: wrap; }
/* history */
+11 -1
View File
@@ -162,8 +162,18 @@ async function create() {
showResult('<a href="' + url + '">' + url + '</a>', false);
$('result').dataset.token = data.deletion_token || '';
try { navigator.clipboard.writeText(url); toast('Copied'); } catch(e) {}
const dest = '/' + data.id + '?created=1&token=' + encodeURIComponent(data.deletion_token || '');
// password-protected: unlock now with the password we already have (#26)
if ($('haspw').checked && data.id) {
const fd = new FormData();
fd.append('password', $('password').value);
fd.append('next', dest);
try {
await fetch('/' + data.id, {method: 'POST', body: fd});
} catch(e) {}
}
// show the paste
location.href = '/' + data.id + '?created=1&token=' + encodeURIComponent(data.deletion_token || '');
location.href = dest;
}
$('create').addEventListener('click', create);
// reset stale result state when returning via Back (bfcache) (#28)