# 25th October 2025 — Optimise paste pipeline with client-side detection, server enhancements, and admin UX [#67](https://github.com/nbarrett/ngx-ramblers/issues/66)
## [build 321](https://github.com/nbarrett/ngx-ramblers/actions/runs/18803315196)
  ____
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 <meta charset>, <span> 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 <img>/<a>/<table> 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 <img> 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.
