Who it is for
Save API docs as Markdown with the code intact
Clean Clipper reads the language off the page: from the fence class, the parent element or the highlighter’s own markup, and writes it into the fence. On a nine-page technical corpus the tag survived in 73 of 156 fences, against 20 and 0 for the two engines compared.
Why clipped docs need cleanup
Documentation is mostly code, and code is the part most clippers drop. You save a page of framework docs or an answer you will need again, paste it into your notes, and every fence is bare: no js, no bash, no sql. The colour is gone, and with it the fastest way to tell a shell command from a JSON body at a glance.
The rest of the damage is structural. A table with a code sample in one of its cells collapses into a single line. The version picker and the “on this page” rail land in the middle of the article. The div wrapper around a code widget survives as literal markup. Repairing that by hand takes longer than writing the note from memory, which is why most people stop clipping docs and just keep a tab open until it goes stale.
The tab is the third problem. Documentation is versioned and the URL usually is not – the page you read for v4 quietly becomes v6, with a renamed flag and a removed option, and the bookmark still resolves – to different text. Nothing in your notes records which version you actually built against. A file with the URL and the page’s own date in its header answers that question a year later; a bookmark never has.
What lands in the note instead
- The fence comes out tagged. ```js, not bare – highlighting works in Obsidian, VS Code and GitHub the moment you paste.
- The language is read, not guessed. It comes from the class the site’s own highlighter left behind, so the tag is as correct as the source page.
- Tables with code in a cell stay whole: 12 of 15 kept on the technical corpus, against 7 for each engine compared.
- Reference links become
[^1]footnotes with their definitions at the end, so a spec’s citations still resolve inside the note. - Sidebars and version pickers are cut, not converted: zero leftover HTML tags across 512 measured pages.
- Extraction runs on the rendered DOM, so documentation sites built in JavaScript are captured as you see them.
- Reddit threads keep their structure and each comment’s score, which is where a good half of the real answers about a library live.
- The
extractionfield says which route was used:dom, orjsonld-articlebodywhen the page shipped its text in structured data and never rendered it.
The JSON API returns some data that looks like this:
```js
[
{ category: "Fruits", price: "$1", stocked: true, name: "Apple" },
{ category: "Vegetables", price: "$2", stocked: true, name: "Spinach" }
]
```
## Step 1: Break the UI into a component hierarchySetting it up for documentation
Six minutes once, then the shortcut does the rest. The defaults are tuned for reading articles; documentation wants a different filename, no author field and no images.
- Install the extension and pin its icon to the toolbar. Right-click the icon and choose Options to open the settings in a tab.
- Set what the icon click does to “save to folder”. That is what turns a clip into one keystroke with no window in the way. The preview window is useful while you are learning the tool and in the way afterwards.
- Choose the folder. Point it at a directory you already keep in version control, such as
docs/clipsin the repository you are working in. The browser asks for confirmation once and remembers the grant for that profile. - Set the filename template to
{domain}-{title}. Four frameworks all have a page called “Getting started”, and without the domain in the name the fourth one silently becomesgetting-started-4. - In the frontmatter section keep
sourceandextraction, and switchauthoroff. Documentation is rarely signed, and an empty field in every file is noise you will end up stripping. - Set images to skip. A screenshot of somebody else’s IDE is not searchable, and the image link points at a CDN that will move.
- Open
chrome://extensions/shortcutsand confirmAlt+Shift+Mis bound. If another extension took it, this is where you take it back.
Settings that suit a developer
These are the values worth changing from the defaults, and the reason each one matters for documentation specifically rather than for reading in general.
| Setting | Value | Why this value here |
|---|---|---|
| Icon click | Save to folder | A clip you take twenty times a day should not open a window twenty times |
| Folder | `docs/clips` inside a repo | Clips get versioned, reviewed and searched with the same tools as the code |
| Filename template | `{domain}-{title}` | Framework docs collide on titles; domains do not |
| Images | Skip | Screenshots are not greppable and their URLs rot faster than the text |
| Frontmatter | `source` and `extraction` on, `author` off | You need the URL and the route; docs pages have no byline worth keeping |
| Per-site rule | `reddit.com` → subfolder `threads` | Forum answers age differently from official docs and are worth keeping apart |
| Shortcut | `Alt+Shift+M` | Clipping without leaving the keyboard is the difference between doing it and not |
Run the migration before starting the server: ``` ./bin/migrate --env production ``` ```sql SELECT id, created_at FROM sessions WHERE expires_at < now(); ``` The second fence carried `class="language-sql"`. The first carried nothing, and is left bare rather than tagged with a guess.
Three working sessions
Pinning the version you actually built against
You are on the v4 branch of a framework’s docs, reading the page about a config flag that was renamed in v5. You press Alt+Shift+M. The file lands as example-dev-configuration-reference.md in docs/clips, with source pointing at the /v4/ URL and the page’s declared date in the header.
Eight months later the flag behaves differently in production and nobody remembers why it was set that way. The clip is in the repository, in the same commit range as the change, and it says which version of the documentation the decision was made against. The live URL now serves v6 and no longer mentions the flag at all.
The forum thread that actually solved it
The official docs describe the happy path; the fix for your case is in a Reddit thread, four comments deep, with the accepted answer sitting at 140 points below a wrong one at 30. You clip the thread. The per-site rule routes it to threads, and the comment structure comes across as nested blockquotes with each score attached.
The score is the part that matters when you read it back. A flat copy-paste of that thread loses the ordering signal entirely and you are left rereading five opinions with no way to tell which one the community agreed with.
A table of variables, straight into the pull request
The deployment guide has a table of eighteen environment variables, three of which contain a code sample in the cell. You select the table on the page, clip the selection, and paste the Markdown into the pull request description. GitHub renders it as a table because it is a GFM table, not a screenshot.
On the fifteen-table technical corpus this serialiser kept twelve tables where each of the engines compared kept seven. The cells that break generic converters are exactly these – the ones with code or a list inside.
Against the usual ways
Every one of these works, and each of them is what somebody on your team is doing right now. The third column is the honest cost – this extension included.
| How it is done now | What you get | What it costs |
|---|---|---|
| Leave the tab open | The page, exactly as it is | It closes on the next restart, and the docs are versioned under you |
| Copy and paste into the editor | Text, sometimes with the sidebar attached | Fences arrive bare, tables arrive as one line |
| Print to PDF | A fixed-layout copy of the page | Not searchable with `grep`, not diffable, cookie banner included |
| Bookmark it | A pointer, in one click | A pointer resolves to whatever the page says today |
| Another clipping extension | Markdown, with less trimming | Measured on 512 pages: 282 to 491 duplicated menu lines against 102 here |
| Clean Clipper | Markdown with tagged fences and a source header | One page at a time, no crawler, no images downloaded |
When it does not come out right
Why is my code fence bare?
Because the page did not say what language it was. Clean Clipper reads the language off the class the site’s own highlighter left behind; it does not look at the code and guess. A hand-styled sample with no class produces a bare fence, which is the honest outcome. A guessed python tag on a shell snippet is worse than no tag, because the highlighting then confidently colours the wrong things.
Why is half the guide missing?
Almost always tabs or an accordion. The extension converts what the browser has actually rendered, and a tab whose content is inserted only when you click it is not in the DOM until you do. Open the tab, expand the section, then clip – or clip once per variant. Where a site renders all tabs and hides them with CSS, all of them come across, one after another.
Why does it say there is no article?
An API playground, a search result page or a package index is mostly link labels, and the extension refuses those on purpose – if more than about a quarter of the extracted characters sit inside links, it reports “no article” instead of handing you three hundred entries. That refusal is why its share of “useful text” scores lower than engines that always return something.
What does extraction: "jsonld-articlebody" mean in my file?
That the page shipped the article text in its structured data but never finished rendering it into the DOM, so the body was read from the structured data instead. It is recorded rather than hidden because the two routes can differ – the structured-data copy is sometimes an earlier draft, and sometimes it is the only complete version. When you see that value, it is worth a glance at the original before you rely on the text.
What it does not do
It does not crawl a documentation site – one page at a time, the page you are on. It does not download images, diagrams or other binary assets – image links keep pointing at the original site. It does not guess a language for an untagged fence, so a page whose highlighter leaves no class behind produces a bare fence rather than a wrong one. And on a page with no article body – an API playground, a search result – it reports “no article” instead of handing you three hundred links.