Commit Graph
101 Commits
Author SHA1 Message Date
fen 542d98e4d9 Fix #169: persistent full-width divider between dropdown head and body
The line between the editor head (dropdown/title area) and the editor
body only showed as the cards' own borders inside rounded corners and
read as hover-dependent and flickering. Draw an always-visible separator
that spans the full card width: border-bottom on the head card and
border-top on the editor card, with square corners on the facing edges
so the two form one continuous line. CSS only in app.css; no inline
styles or scripts, CSP unchanged.
2026-09-10 11:43:52 -05:00
fen 0e5cfcd403 Merge pull request 'Revise notification pill (#168)' (#181) from fix-168 into dev
CI / test (push) Successful in 42s
CI / docker (push) Successful in 50s
2026-09-10 16:38:08 +00:00
fen 9692531a40 Fix #167 rev: add missing .gutline CSS so gutter numbers align with wrapped lines
CI / test (pull_request) Successful in 41s
CI / docker (pull_request) Skipped
QA of PR #179 found paste-lines.js creates .gutline spans but no CSS rule
existed, so all gutter numbers rendered inline on one visual row. Stack
them one per row under .code .gutter; blank fill spans inherit it.
2026-09-10 11:35:39 -05:00
fen b801d7fb56 Revise notification pill per reopened #168: short text, smaller, side placement
CI / test (pull_request) Successful in 40s
CI / docker (pull_request) Skipped
- Pill now reads only 'Paste Created' (no combined 'Paste Created - Link Copied')
- Copy fallback toast now says 'Link Copied'
- Pill shrunk (smaller padding/font) and anchored tighter to the right side

Fixes #168
2026-09-10 11:33:45 -05:00
fen 362a59690f Merge pull request 'Clean up notification pill (#168)' (#178) from fix-168 into dev
CI / test (push) Successful in 40s
CI / docker (push) Successful in 50s
2026-09-10 16:25:56 +00:00
fen 0643ca433e Merge pull request 'Fix #167: gutter numbers realign with wrapped lines' (#179) from fix-167 into dev
CI / test (push) Successful in 39s
CI / docker (push) Successful in 49s
2026-09-10 16:25:15 +00:00
fen 6064404723 Merge remote fix-168: keep corner pill, cookie-based token flow
CI / test (pull_request) Successful in 40s
CI / docker (pull_request) Skipped
2026-09-10 11:25:15 -05:00
fen aa4d017631 Fix #168: compact corner notification pill for paste creation 2026-09-10 11:24:24 -05:00
fen dee062dfa5 Fix #167: gutter numbers track wrapped visual rows when line wrap enabled
CI / test (pull_request) Successful in 38s
CI / docker (pull_request) Skipped
2026-09-10 11:23:49 -05:00
fen 6ef0de6e19 Merge remote-tracking branch 'origin/dev' into qa178
# Conflicts:
#	internal/web/templates/paste.html
2026-09-10 11:23:47 -05:00
fen 28a79b20ea Merge pull request 'editor head: wrap toggle state and pill highlight (#166)' (#172) from fix-166 into dev
CI / test (push) Successful in 37s
CI / docker (push) Successful in 43s
2026-09-10 16:21:28 +00:00
fen 3fa2c93e22 clean up notification pill wording, size, and placement (#168)
CI / test (pull_request) Successful in 39s
CI / docker (pull_request) Skipped
2026-09-10 11:18:57 -05:00
fen bead90699d Merge pull request 'Fix #170: remove stray bar at bottom of /new page' (#177) from fix-170 into dev
CI / test (push) Successful in 33s
CI / docker (push) Successful in 37s
2026-09-10 16:18:42 +00:00
fen d7fb87f19b Fix #170: stray bar at bottom of /new page
CI / test (pull_request) Successful in 36s
CI / docker (pull_request) Skipped
#139 removed inline display:block from paste.html's created banner and
compensated with a global .created-banner { display:block } override.
That override also hit the hidden placeholder banner on /new, whose
base rule is display:none, making an empty padded bar render above the
action bar. Scope the override to .created-banner.show and mark only
the paste-view banner with the show class.
2026-09-10 11:16:30 -05:00
fen 51685f8667 file upload preview in editor on /new (#171)
- images render fitted into the editor area (object-fit contain), editor hidden
- text files load content into the editor; title placeholder convention (Python.py, Text.txt fallback)
- title auto-fills only when blank; never overwrites a typed title
- external JS + CSS classes only, CSP-safe (no inline styles/scripts)
2026-09-10 11:12:41 -05:00
fen 122c1e14f4 web: friendly Paste ID not found page for missing pastes (#173)
CI / test (pull_request) Successful in 32s
CI / docker (pull_request) Skipped
Missing or expired paste IDs (and unknown routes) now render the main
UI chrome with a 'Paste ID not found' message in a color-coded result
card instead of a bare text/JSON 404. HTTP status stays 404. No inline
scripts or styles; new CSS uses existing --err token and pill radii.
2026-09-10 11:06:52 -05:00
fen 9712926cf5 #173: render friendly 'Paste ID not found' UI instead of bare 404
Missing/expired/burned paste IDs and unknown routes now render the main
UI (topbar + centered result card) with a 'Paste ID not found' message,
returning HTTP 404 status for correctness.
2026-09-10 11:06:44 -05:00
fen 5fc5ae8aad editor head: wrap toggle state and pill highlight (#166)
CI / test (pull_request) Successful in 32s
CI / docker (pull_request) Skipped
wrap button on the new paste page looked identical whether wrap was on
or off because the btn base is already accent filled. give the toggle a
neutral off state so the accent on state is visible, matching the icon
button toggles on the paste view.

also remove the accent border on the whole language settings pill when
any child has focus. individual controls already show their own focus
rings, so the pill highlight made no sense.
2026-09-10 10:13:42 -05:00
fen 5dba356264 Merge pull request 'Settings spacing between sections (#161)' (#165) from fix-161 into dev
CI / test (push) Successful in 31s
CI / docker (push) Successful in 39s
2026-09-10 15:10:37 +00:00
fen 16cad8796f new paste tab: rework number box submenus (#157)
CI / test (pull_request) Successful in 32s
CI / docker (pull_request) Skipped
Give the custom expiry and readable N times submenus a shared boxed
container with proper padding, indent them under their parent option,
and style the number inputs and unit select with palette vars, the
existing radius scale, and the select chevron. No em dashes, no hard
coded colors in new rules.
2026-09-10 09:45:31 -05:00
fen 317ed2137a Settings: more padding between sections (#161)
CI / test (pull_request) Successful in 37s
CI / docker (pull_request) Skipped
Add margin under the dark mode toggle and between section headings
(theme/editor) on /settings via CSS classes, no inline styles (CSP).
2026-09-10 09:41:45 -05:00
fen 93fea6ad1c Merge pull request 'Fix #163: /new Create button broken (stale iscan/createCan path)' (#164) from fix-163 into dev
CI / test (push) Successful in 32s
CI / docker (push) Successful in 40s
2026-09-10 14:40:52 +00:00
fen 0787871f2b Fix #163: remove dead iscan/createCan path breaking /new Create
CI / test (pull_request) Successful in 31s
CI / docker (pull_request) Skipped
2026-09-10 09:33:49 -05:00
fen c4d55cb196 Fix #142: break long unbroken paste titles instead of forcing horizontal scroll
CI / test (pull_request) Successful in 34s
CI / docker (pull_request) Skipped
Add word-break: normal; overflow-wrap: anywhere to .paste-title-bar h1 so
a >120-char unbroken title wraps inside the title card at mobile width
instead of producing an internal + page-level horizontal scrollbar.
2026-09-10 09:33:15 -05:00
fen 5a227e2feb Merge pull request 'Fix #139: drop unsafe-inline from script-src and style-src' (#159) from fix-139 into dev
CI / test (push) Successful in 31s
CI / docker (push) Successful in 36s
2026-09-10 09:11:00 -05:00
fen 7a74ff3e74 Fix #139: drop unsafe-inline from script-src and style-src (#139)
CI / test (pull_request) Successful in 30s
CI / docker (pull_request) Skipped
- Move all inline <script> blocks (layout head/theme, topbar dark toggle,
  foot, paste, new, history, mine, settings, admin, unlock) to external
  files under internal/web/static/. Page data reaches scripts via data-*
  attributes (data-paste-id, data-default-dark) instead of template vars.
- Replace inline onclick handlers (copy, delete, stats toggle) with
  addEventListener wiring.
- Convert inline style="" attributes to CSS utility classes; swatch
  colors are now set via CSSOM/DOM APIs instead of innerHTML strings.
- script-src/style-src are now plain 'self'; img-src data: stays for the
  SVG data-URI backgrounds. Verified with headless chromium: zero CSP
  violations on all pages in dark and light presets, theme swatches,
  admin lock, tables and paste view render correctly.
2026-09-10 09:08:17 -05:00
fen b30d41b87d Wrap ON breaks long tokens mid-word; no horizontal scroll while wrap enabled (#152)
CI / test (pull_request) Successful in 30s
CI / docker (pull_request) Skipped
- codebody/editor: overflow-wrap anywhere + word-break break-all + overflow-x hidden under html[data-wrap]
- code container and mobile .float also hidden overflow with wrap on
- topbar mobile: tighten gap/padding/nav link padding so nothing overflows at 375px

Fixes #152
2026-09-10 08:51:13 -05:00
fen 521b6f8011 #138: add Secure attribute to viewer cookie (vwr)
CI / test (pull_request) Successful in 29s
CI / docker (pull_request) Skipped
2026-09-10 08:42:12 -05:00
fen 00aaafeb3c #143: set tok_<id> cookie in create handlers so the created banner can show the token (QA)
CI / test (pull_request) Successful in 29s
CI / docker (pull_request) Skipped
2026-09-10 08:37:07 -05:00
fen d7b51f02b6 Remove ?token= deletion-token path (#143)
The deletion token was accepted via the ?token= query parameter on both
DELETE /api/pastes/{id} and /redeem, and round-tripped through the paste
URL after creation. URL-carried bearer secrets leak into reverse-proxy
access logs and browser history.

- API: deletion tokens are now accepted only via the Authorization header
  (Bearer/Token/bare); query params are ignored on both endpoints
- Web create flow: token moves to the browser via a short-lived tok_<id>
  HttpOnly cookie instead of the redirect URL; the paste view reads it
  from the cookie, never from ?token=
- Web view: the delete button calls redeem() which takes the token from
  sessionStorage and sends it as an Authorization header
- Tests: correct token in query must be rejected (403/400); header path
  still deletes/redeems; extraction unit cases updated

Fixes #143
2026-09-10 08:37:07 -05:00
fen 747eba7064 Settings: dark toggle above theme list; midnight card light row on top (#132)
CI / test (pull_request) Successful in 29s
CI / docker (pull_request) Skipped
2026-09-10 08:21:49 -05:00
fen 33ccfd373a Merge pull request 'Fix invisible select chevron in all presets (#136)' (#151) from fix-136-select-chevron into dev
CI / test (push) Successful in 28s
CI / docker (push) Successful in 39s
2026-09-10 04:31:27 +00:00
fen 72dbfb1b3c Fix invisible select chevron in all presets (#136)
CI / test (pull_request) Successful in 28s
CI / docker (pull_request) Skipped
Two compounding causes:
- CSP img-src fell back to default-src (self), blocking the data: URI
  chevron image on all served pages, so no select ever painted it.
- .editor-head select used the background shorthand, wiping the
  background-image set by the later select rule.

Chevron stroke is now a per-preset --chevron token (light stroke for
dark presets, dark for light presets) instead of hardcoded #888.
CSP gains img-src 'self' data: so the data-URI icons can load.
2026-09-09 23:25:15 -05:00
fen d44e4d1587 Merge pull request 'Secrets via headers only: drop ?key= and ?password= query fallbacks (#137, #141)' (#150) from fix-137-141-drop-query-secrets into dev
CI / test (push) Successful in 27s
CI / docker (push) Successful in 38s
2026-09-10 04:23:27 +00:00
fen d013f3965f Require secrets via headers only: drop ?key= and ?password= query fallbacks (#137, #141)
CI / test (pull_request) Successful in 28s
CI / docker (pull_request) Skipped
Query strings leak into Traefik access logs, browser history, and Referer
headers. Admin key is now accepted only via X-Admin-Key; paste and can
passwords only via X-Paste-Password (or the POST unlock form). Tests
updated; new negative cases assert 401 for the query paths.
2026-09-09 23:23:10 -05:00
fen 22c66243d5 Merge fix-38-file-attachments into dev (PR #129)
CI / test (push) Successful in 28s
CI / docker (push) Successful in 36s
2026-09-09 23:20:48 -05:00
fen 98222e762f Merge pull request 'History: pagination survives search/sort, pager pinned to page bottom' (#140) from fix-133-paging into dev
CI / test (push) Successful in 28s
CI / docker (push) Successful in 34s
2026-09-10 04:14:20 +00:00
fen a95ee57000 Merge pull request 'Split new-paste editor header into title pill and settings pill (#147)' (#149) from fix-147-header-split into dev
CI / test (push) Successful in 31s
CI / docker (push) Successful in 33s
2026-09-10 04:12:05 +00:00
fen b096c2073c Merge pull request 'Fix result box wrap: word boundaries, keep long-token breaking (#135)' (#145) from fix-135-result-wrap into dev
CI / test (push) Successful in 27s
CI / docker (push) Successful in 41s
2026-09-10 04:09:13 +00:00
fen 4d50e644b9 Merge pull request 'Fix #146: untitled paste ID fallback renders as plain text like titled pastes' (#148) from fix-146-id-fallback-plain into dev
CI / test (push) Successful in 27s
CI / docker (push) Successful in 39s
2026-09-10 04:07:04 +00:00
fen 8abf821ce9 Merge pull request 'Admin lock page: replace explanatory paragraph with centered key input' (#119) from fix-admin-lock-center into dev
CI / test (push) Successful in 27s
CI / docker (push) Successful in 32s
2026-09-10 04:01:45 +00:00
fen da9039b606 Split new-paste editor header into title pill and settings pill (#147)
CI / test (pull_request) Successful in 30s
CI / docker (pull_request) Skipped
2026-09-09 22:58:41 -05:00
fen 7dc70d62f6 Fix #146: render untitled paste ID fallback as plain text like titled pastes
CI / test (pull_request) Successful in 26s
CI / docker (pull_request) Skipped
The PASTE column fallback for untitled pastes used the .slug class, which
renders as a monospace chip with a background pill. Give it a dedicated
paste-name modifier that strips the chip styling (background, padding,
radius, mono font) so the fallback looks identical to a titled paste
(var(--fg) plain text). The dedicated ID column and URL column chips keep
their existing styling. Applied to both /history and /mine tables.
2026-09-09 22:56:53 -05:00
fen 0073335875 #38 QA fix: render GetAttachmentForPaste in paste view; dedupe dark-toggle CSS
CI / test (pull_request) Successful in 27s
CI / docker (pull_request) Skipped
- renderPaste now looks up the paste's attachment and passes it as
  'Attachment' so the paste.html attachment chip/image preview renders
- remove duplicated .iconbtn.dark-toggle blocks (3x from stacked
  branches #127/#128) and duplicate mobile-media variants

Verified: go vet + go test pass; live render on :18098 shows
attachment-chip + img src=/f/id/name for a png upload (served 200
image/png) and chip-with-filename, no preview, for an html upload.
2026-09-09 22:53:39 -05:00
fen fa2e9b1bb5 History: keep pagination over filtered/sorted set, pin pager to page bottom (#133)
CI / test (pull_request) Successful in 26s
CI / docker (pull_request) Skipped
2026-09-09 22:48:25 -05:00
fen 9f4ed91b8f Fix result box wrap: word boundaries instead of break-all (#135)
CI / test (pull_request) Successful in 26s
CI / docker (pull_request) Skipped
2026-09-09 22:43:30 -05:00
fen 7cc6a9c706 Add line wrap toggle for editor and paste viewer (#130)
CI / test (pull_request) Successful in 27s
CI / docker (pull_request) Skipped
Shared client-side preference in localStorage 'palette-wrap', default
off. Toggle button on /new editor head and paste title bar, plus a Line
wrap checkbox in the settings menu; all read/write the same preference.
Active state uses the accent treatment like other toggles. No em dashes
in UI text.
2026-09-09 22:35:49 -05:00
fen 19cb8d1d45 Merge pull request 'Theme pairs with dark mode toggle, gear active state, PALETTE_DEFAULT_DARK' (#128) from fix-theme-pairs-darkmode into dev
CI / test (push) Successful in 25s
CI / docker (push) Successful in 32s
2026-09-10 03:25:35 +00:00
fen 4948ef9f1c #38 iteration 1: file attachments, 1 file per paste
CI / test (pull_request) Successful in 26s
CI / docker (pull_request) Skipped
- internal/store/blob.go: BlobStore interface + fs implementation with
  traversal-safe keys (<paste-id>/<sha256>), put/get/stat/delete
- attachments table migration (id, paste_id, filename sanitized to 255,
  mime sniffed server-side, size, sha256, created_at)
- POST /api/pastes now accepts multipart/form-data with a 'file' part;
  1 file = 1 paste: file replaces text content when both are sent
- 25 MB per-file limit enforced server-side (413 file_too_large)
- GET /f/{attachment-id}/{filename}: stored sniffed mime, nosniff,
  inline only for images/pdf, html/svg/xml forced to text/plain (#34 rule)
- paste view renders attachment chip + inline image preview
- /new: dropzone with file picker, drag-and-drop, Ctrl+V file paste,
  file chip with name/size/remove, matches pill/radius design
- tests: blob roundtrip/traversal/sanitize; multipart create (mime
  sniffing, client mime ignored, size limit, two-file reject, html/svg
  forcing, 404s, password/expiry fields)
2026-09-09 22:21:15 -05:00
fen dcf2d66a82 Theme pairs with dark mode toggle, gear active state, PALETTE_DEFAULT_DARK (#127)
CI / test (pull_request) Successful in 25s
CI / docker (pull_request) Skipped
- Collapse the 10 theme cards into 5 pairs: light swatches top row, dark bottom row
- Dark mode toggle in settings and topbar (sun/moon inline SVG)
- Toggling dark mode switches to the other variant of the selected pair
- Persist pair id in localStorage palette-theme, dark flag in palette-dark
- Head script resolves base+dark to variant; URL ?theme= accepts both ids and wins
- Settings gear highlights like nav tabs on /settings
- PALETTE_DEFAULT_DARK env var sets server default dark state (default on)
- Server-side resolution helpers + tests
2026-09-09 22:17:50 -05:00