25th October 2025 — Optimise paste pipeline with client-side detection, server enhancements, and admin UX #67
Resolves sluggish paste UX by adding client-side filtering, robust server processing for HTML/Markdown/URL content, and admin tools for site config management. Consolidates paste flows, DRY Puppeteer utilities, and fragment handling. 🎯
Problem:
- Pastes triggered unnecessary server round trips for plain text/trivial HTML (e.g., browser wrappers like , tags).
- No client-side distinction between significant HTML (images/links/tables) and wrappers, causing lag.
- URL pastes (view-source:/http) lacked auto-fetch/preview; fragments lacked nested row support.
- Admin site config lacked paste/copy clipboard; Puppeteer launches were duplicated.
Solution:
- Client-Side Detection (
PasteDetectionService): isSignificantHtml() filters wrappers (prioritizes tags like
// over browser patterns); hasMarkdownImages() and isLocalPath() moved client-side. Defers server calls until user confirms in prompt.
- Server Paste Pipeline: Preprocessing decodes entities, strips wrappers/anchors/CSS artifacts, normalizes
sources, resolves relatives via base URL; Turndown for HTML→Markdown cleanup (e.g., "Distance: 2.7 miles"). New APIs: /html-from-url (Puppeteer fetch with base auto-detect), /html-paste-preview//markdown-paste-preview (return markdown + rows).
- Paste UX: Prompts for base URL (suggested from config); splits images/captions into rows; preserves local paths as plain text. Added "Convert to Rows" toolbar button with row count preview (pluralized via
pluraliseWithCount).
- Admin UX: Site config header buttons for Paste (JSON textarea with validation/apply) and Copy (ClipboardService); duplicate site retained.
- Nested Rows & Actions: Config toggle "Keep Content Together"; actions menu with Unnest (previous/next outer row).
- Puppeteer DRY:
puppeteer-utils.ts centralizes launchBrowser()/deriveBaseUrl(); refactored migration routes/engine.
- Fragments: Recursive usage detection in nested rows; normalize paths (strip leading /); include both
/fragments and fragments variants; add /fragments → /admin/fragment-index redirect.
Benefits:
- Instant plain/trivial pastes (no server calls); rich content processed efficiently.
- Cleaner markdown rows; auto-base for URLs; nested row support for multi-column layouts.
- Reduced duplication; improved admin workflow (clipboard integration).
Changes:
- New:
PasteDetectionService (93 lines, 24 tests); APIs; utils; radio buttons for row placement (nested/sibling, smart default by column count).
- Updated:
markdown-editor.component.ts (paste flows, toolbar); dynamic-content-site-edit-text-row.ts (nested insertion); migrate-static-site.ts (Puppeteer); fragment-index (recursive traversal).
- Removed: Duplicate Puppeteer code; CSS artifacts in preprocessing.
Testing:
- 24 unit tests (
paste-detection.service.spec.ts, turndown-service-factory.spec.ts) pass (wrappers, tags, images, entities, anchors, CSS stripping).
- Server e2e/integration tests for previews/fetch; frontend builds succeed.
- Manual: Multi-column nested pastes, URL fetch, duplicate columns, fragment redirects.
Closes #67.