# 25th October 2025 — Optimized HTML/Markdown Paste Pipeline [#67](https://github.com/nbarrett/ngx-ramblers/issues/67)
## [build 321](https://github.com/nbarrett/ngx-ramblers/actions/runs/18803315196) — [#67](https://github.com/nbarrett/ngx-ramblers/issues/67) — [commit 07644ee](https://github.com/nbarrett/ngx-ramblers/commit/07644ee)

Dramatically improved paste experience with client-side HTML detection, server-side processing enhancements, URL auto-fetch, and admin clipboard tools.

**Where to Find It**

- **Markdown Editor**: Paste HTML content, toolbar "Convert to Rows" button
- **Admin → Migration Settings**: Paste/Copy buttons for site configuration JSON
- **Fragment Index**: Recursive detection of nested row usage

**Benefits**

- **Instant Plain Pastes**: Client filters trivial HTML/browser wrappers before server call
- **Cleaner Rows**: Enhanced preprocessing removes artifacts, produces better Markdown
- **Smart URL Handling**: Paste view-source:// or http(s):// URLs to auto-fetch and convert pages
- **Base URL Suggestions**: Dialog prompts with migration config URLs for relative link resolution
- **Nested Content Support**: Choose nested/sibling placement with smart column-count defaults
- **Admin Efficiency**: Copy/paste site config JSON directly in migration settings
- **Fragment Awareness**: Recursive detection includes nested rows and normalized paths
- **Reduced Duplication**: DRY Puppeteer utilities shared across migration functions

**Technical Details**

Client-Side Detection (PasteDetectionService):
- Filter browser wrappers, trivial tags, images, links before server call
- Defer to server only after user confirms in prompt
- Toolbar "Convert to Rows" button with preview count (24 tests)
- Detect view-source:// and http(s):// URL pastes
- Auto-fetch HTML via /api/migration/html-from-url
- Auto-fill derived base URL from <base href> or URL path

Server Processing:
- Preprocess: entity decode, strip Chrome code-table wrappers
- Unwrap anchors in src/href attributes
- Normalize <img> sources (data-src/srcset fallbacks)
- Resolve relative URLs against base URL
- Post-processing: remove tags/comments, normalize &nbsp;
- Strip stray CSS/property declarations and font-family suffixes
- Collapse whitespace and blockquote artifacts
- Turndown integration via createTurndownService
- Final markdown cleanup for cleaner rows

New APIs:
- POST /api/migration/html-from-url: loads page with Puppeteer, extracts HTML, derives base URL
- POST /api/migration/html-paste-preview: returns markdown + rows for preview
- POST /api/migration/markdown-paste-preview: returns markdown + rows for insertion
- Safe fallback to fetch() when Puppeteer unavailable

UX Enhancements:
- Base URL prompt with suggestions from migration config
- Directory extraction via ensureTrailingSlash
- Paste dialog: "Split into rows" vs "Convert without splitting"
- Row placement radios: nested vs sibling (smart default by column count)
- Split images and adjacent short captions into rows
- Keep Content Together (Nested Rows) configuration toggle
- Unnest action for moving content to previous/next outer row

Admin Tools:
- Site configuration Paste/Copy buttons (JSON textarea)
- ClipboardService for reliable copy operation
- Immediate JSON apply with validation and Cancel
- Paste auto-expands the site config section
- Duplicate site action retained

Puppeteer DRY:
- New puppeteer-utils.ts centralizes launchBrowser() and deriveBaseUrl()
- Refactored migrate-static-site.ts, migrate-static-site-engine.ts, migration-routes.ts
- Shared launcher eliminates code duplication

Fragments:
- Fragment index includes nested row usages
- Normalize fragment path comparison (leading slash handling)
- Recursive usage detection
- Redirect /fragments to /admin/fragment-index

Testing:
- Comprehensive unit tests: turndown-service-factory.spec.ts
  - Tests: entity decoding, wrapper removal, anchor unwrapping
  - Relative image resolution, nbsp normalization, blockquote cleanup, CSS stripping
- Related route specs and e2e previews
- Frontend builds succeed, server tests pass
- No database schema changes