Astro · TypeScript
Working
PlainPaste
Markdown in, clean plain text out, without losing your numbering
Builds clean, 77 tests, 0 vulnerabilities
Overview
Chat assistants answer in Markdown. Email clients, applicant-tracking forms and most chat boxes do not render it, so a reply that looked clean in the assistant arrives full of asterisks and hashes. PlainPaste is the step in between: paste Markdown on the left, get paste-ready text on the right.
The reason it exists rather than a two-line call to an off-the-shelf stripper: the common libraries flatten lists, so 1. 2. 3. disappears. That numbering is usually the most important thing on the page, and it is what makes a reply to a numbered questionnaire readable at all. So the parse step is stock remark, and only the writer that turns the syntax tree back into text is hand-written.
Six presets configure every setting for a destination (email, report, chat, documentation, a web form field) and load a worked sample into an empty pane. Both panes live in one workspace with a draggable divider, a fullscreen toggle and synchronised scrolling.
Stack
- Framework
- Astro 7, fully static
- Styling
- Tailwind CSS v4, tokens in @theme
- Interactivity
- Vanilla TypeScript islands, no React
- Parsing
- unified · remark-parse · remark-gfm
- Tests
- Vitest
- Hosting
- Cloudflare Pages free tier
Decisions Worth Explaining
A hand-written serialiser instead of strip-markdown
strip-markdown flattens list nodes, losing ordered-list numbering. Only the serialisation is custom; the parse is stock remark, and no HTML is produced at any point.
Nesting comes from hanging indent, not a depth counter
Each list item pushes every line after its first out by the width of its own marker. That single rule covers wrapped paragraphs and nested sub-lists, and composes to any depth. The first implementation tracked depth separately and double-indented everything.
Lossless by default
A converter that silently deletes a URL or a code block is worse than one that leaves you something to delete. Link URLs, code blocks and their language, image alt text and footnotes all survive unless you switch them off.
What Is Not Done
- Not deployed; no domain registered yet.
- Ad slots are wired and placed but unconfigured, so nothing loads.
- Tests cover the converter only; the UI wiring has no browser tests.