How to use
- In Google Docs (or Word, Notion, Confluence, a web page), select the text you want and copy it with Ctrl+C.
- Click the left box and paste with Ctrl+V. The box shows the paste with its formatting; the Markdown appears on the right at once.
- Read the line under the Markdown: it lists what was unwrapped, dropped or approximated (redirect links, underline, a table with no header row).
- Copy Markdown (or Ctrl+Enter in the box) and paste into your README, wiki, issue or note. Download .md saves a file.
What a Google Docs copy really contains
Copy a paragraph in Google Docs and the clipboard holds two things: the plain words, and an HTML version of them that Docs generates on the fly. That HTML is not the tidy <strong> and <h2>a web page would use. Bold is a <span style="font-weight:700">; the whole copy sits inside a <b> tag whose style says not bold; every link goes through a google.com/url?q= redirect; a nested list is a second list placed beside the parent item with an aria-level attribute; and one bold phrase can arrive as three spans. A converter that only looks at tag names sees none of it.
This tool reads the inline styles as well as the tags, so it produces the Markdown you would have written by hand: # headings, **bold**, *italic*, ~~strikethrough~~, `code` for Courier New, real link addresses, nested bullets and numbers, tables with a header row. It says what it had to approximate. The reverse trip is Markdown to Google Docs; when the paste is going into a chat rather than a README, Markdown to Plain Text takes the result from here.
Example
Load sample fills the box with what Docs puts on the clipboard for a short launch plan: 2headings, a paragraph with bold, italic, monospace and a link, a nested list, and a table. Abridged, the HTML looks like:
<b style="font-weight:normal;" id="docs-internal-guid-…">
<h1 dir="ltr" style="…"><span style="font-size:20pt;font-family:Arial;font-weight:400;…">Q3 launch plan</span></h1>
<p dir="ltr" style="…">
<span style="font-size:11pt;font-weight:400;…">We ship on </span>
<span style="font-size:11pt;font-weight:700;…">14 October</span>
…
<a href="https://www.google.com/url?q=https://example.com/wiki/billing-v2&sa=D&source=editors&ust=…&usg=…">
<span style="…text-decoration:underline;…">rollout page</span>
</a>
</p>
…
</b>The Markdown it becomes:
# Q3 launch plan
We ship on **14 October**. The *only* blocker is the `billing-v2` flag, see the [rollout page](https://example.com/wiki/billing-v2).
## Checklist
- Freeze the release branch
- Notify **#eng-release**
- Run the migration on staging
| Owner | Status |
| --- | --- |
| Priya | On track |The status line for the sample reads: Google Docs redirect links were unwrapped to their real addresses. The table had no header row, so its first row became the header (Markdown tables need one).
Options explained
- Paste from Google Docs is a formatted box, not a plain text field, which is what lets it receive the HTML flavour of a paste. You can also type or edit in it; the Markdown follows.
- Bullet character chooses
-or*for unordered lists. Both are valid Markdown; some style guides insist on one. - Load sample inserts the Docs clipboard HTML shown above; Clear empties both sides.
- Copy Markdown and Download .md take the right-hand box as it is. Ctrl+Enter in the paste box copies.
- The status line lists every approximation: unwrapped redirect links, a first row promoted to table header, underline kept as plain text, Word list paragraphs converted by their glyph, an image with no address dropped.
Edge cases and common errors
- The Docs wrapper is not bold. Every Docs copy is wrapped in
<b style="font-weight:normal">. A tag-only converter bolds the whole document; here the style wins and<b style="font-weight:normal"><p>plain</p></b>givesplain. - One bold phrase in several spans:
Hello+world+!as three spans, the first two bold, merges into**Hello world**!, not**Hello** **world**!. - Redirect links are unwrapped.
https://www.google.com/url?q=https://example.com/a%3Fx%3D1&sa=D…becomes[link](https://example.com/a?x=1), with the address percent-decoded. - Nested lists the Docs way. A
<ul>placed beside an<li>witharia-level="2"becomes- Parent ⏎ - Child. - Monospace is code. A span in Courier New (or Consolas, Menlo, Monaco, any font family containing “mono”) becomes
`git status`. A whole paragraph in a monospace font becomes a fenced code block. - Underline has no Markdown.
<u>underlined</u>and a line-through span giveunderlined and ~~struck~~; the status line says “Underline has no Markdown equivalent; underlined text is kept as plain text.”. - Title and Subtitle styles are not headings. Docs copies them as large text, so
Document titlecomes out as a paragraph. Heading 1–6 styles do become#headings. - Markdown-significant characters are escaped so the text reads as it did:
Version 2 * 3, a_b, and #hashtagbecomesVersion 2 \* 3, a_b, and #hashtag; the asterisk is escaped, the underscore inside a word is left alone, and the hash mid-line needs nothing. - Empty paragraphs collapse. Docs emits a
<p>with an empty span for every blank line;one, two blank paragraphs,twobecomeone⏎⏎two, one blank line. - Checklists copied from Docs arrive as ☐ and ☑ characters and become
- [x] done ⏎ - [ ] todo. - Word pastes mark list items as paragraphs with a bullet glyph and an indent (
MsoListParagraph); they are converted by that glyph and indent and flagged in the status line, since Word does not say where a list starts or ends. - A paste with no formatting (from a plain text field, a terminal, or Ctrl+Shift+V) produces the words unchanged and a status line saying why.
- Size: a 300 KB paste (a long document) converts in well under a second. Comments, suggestions and footnotes are not copied by Docs, so they cannot appear here.
Do the same thing in code
In Google Docs itself
Tools → Preferences → tick "Enable Markdown"
Select text → right-click → Copy as Markdown
File → Download → Markdown (.md) # the whole documentShell (pandoc, from a downloaded .docx)
pandoc -f docx -t gfm --wrap=none document.docx -o document.mdJavaScript (browser)
// Read the HTML flavour of a paste, then convert it (turndown is the usual library).
box.addEventListener("paste", (e) => {
const html = e.clipboardData.getData("text/html");
const markdown = new TurndownService({ headingStyle: "atx" }).turndown(html);
});None of those read Docs' inline styles: pandoc works from the .docx, not the clipboard, and turndown sees the font-weight:700 span as plain text unless you add a rule for it. For raw HTML source rather than a paste, use HTML to Markdown, which runs the same converter on text you type.