HTML Cleaner for Word & Google Docs Pastes

Paste a Word document, a Google Doc, or any messy markup. Word bullets turn back into a real list, bold survives, mso- styles, o:p tags, empty paragraphs go. The ledger shows what each rule removed.

Paste catcher, source, cleaned output, rules

Step 1, optional

Copy from Word, Google Docs, Excel, or a web page. Click the dashed box, press Ctrl+V or Cmd+V. The catcher reads the clipboard's HTML, which a plain textarea never sees.

Source HTML

The Word sample is release notes for the JSON beautifier, pasted the way Word 365 hands them over.

Office leftovers
Attributes
Tags, output

Copy one paragraph out of Word. The clipboard now holds a whole document: a head, an XML settings block, a stylesheet, then your sentence inside two or three spans.

Paste the result into WordPress, a Shopify description, or a help-desk article. Every span comes along. The page looks fine in the editor. The source is a mess. The font no longer matches your theme. The next person to edit the post inherits mso-fareast-font-family on every line.

The sample above is a real-shaped Word 365 paste: release notes for the Toolexe JSON beautifier, one heading, one paragraph, a bulleted list with a nested point, a contact line. 3.1 KB of source. Defaults return 13 lines of plain tags, 572 bytes, 82% lighter. The ledger under the rules shows where each change came from.

One Word paragraph, cleaned
Word wrote
<p class=MsoNormal><span style='mso-fareast-font-family:"Times New Roman"'>The
<b>JSON beautifier</b> at <a href="https://toolexe.com/json/beautifier"><span
style='color:#0563C1'>toolexe.com/json/beautifier</span></a> keeps key order when
you sort arrays.<o:p></o:p></span></p>
Cleaner kept
<p>The <strong>JSON beautifier</strong> at <a href="https://toolexe.com/json/beautifier">toolexe.com/json/beautifier</a> keeps key order when you sort arrays.</p>

Eight things Word put on your clipboard

Read the sample source top to bottom. Each item below is one line of junk, with the rule responsible for removing the line.

  1. xmlns:o plus xmlns:w on the html tag. Office namespaces. No browser reads them. Return the body only drops the html shell with the head inside.
  2. A File-List link to C:/Users/wajahat/AppData/Local/Temp/msohtmlclip1, a temp folder on the author's own disk. Shipping the link leaks a Windows username. The link goes with the head. With Return the body only unticked, Delete script, style, link, meta catches the link instead.
  3. A conditional comment, <!--[if gte mso 9]>, holding an XML settings block. Only Outlook's Word engine reads those. Inside the body, Delete comments removes the StartFragment markers plus the <![if !supportLists]> pair around each bullet. Ten comments in the sample.
  4. class=MsoNormal on every paragraph. The stylesheet behind the class stays in Word, so on your site the class points at nothing.
  5. mso- declarations inside style attributes. Browsers skip all of them. With styles kept, the office rule strips only the mso- part.
  6. <o:p></o:p> closing every paragraph. A blank line in Word is <p class=MsoNormal><o:p>&nbsp;</o:p></p>, which Delete empty elements removes.
  7. Bullets as fake paragraphs. Each bullet is a p with a negative indent, a Symbol-font middle dot, plus seven no-break spaces inside <![if !supportLists]>. Not a list.
  8. <a name="_GoBack"></a>, a bookmark Word drops at the spot you last typed. Empty, so the empty rule deletes the anchor.

Word bullets come back as a real list

Pasted Word bullets render as indented paragraphs. Screen readers announce no list. Your theme's list styles never apply. Most cleaners strip the styles, leave the paragraphs, keep the middle dot as a stray character.

The rebuild rule reads two values out of each paragraph's mso-list declaration before any style is deleted. level1 or level2 sets the nesting depth. The hidden marker text picks the tag:

In the sample, "A trailing comma gets its own message" sits at level 2, so the rebuild nests a second ul inside the "Parse errors" item.

The limit: the rule ignores the number Word started from. A list continued from an earlier section restarts at 1. I check every ordered list against the Word file before publishing. Numbering is where a paste goes wrong without any visible error.

Google Docs breaks somewhere else

Docs exports real ul plus li tags, so the list rule has nothing to rebuild. The mess sits in three other places.

A blind style purge turns every bold word in the Doc plain. Keep styled bold or italic wraps those spans in strong or em before the style rule runs:

<b style="font-weight:normal;" id="docs-internal-guid-6c1e2f0a-7fff">
<p dir="ltr" style="line-height:1.38;margin-top:0pt;">
<span style="font-size:11pt;font-family:Arial;font-weight:700;">Deadline:</span>
<span style="font-size:11pt;font-family:Arial;font-weight:400;"> Friday 18:00 UTC</span>
</p></b>
<p><strong>Deadline:</strong> Friday 18:00 UTC</p>

Paste the Docs snippet above into the source box to check the result yourself.

The order the rules run in

Ticking boxes in a different order changes nothing. The pass always runs the same sequence, because several rules read data a later rule deletes.

  1. Lists first. The rebuild needs mso-list from the style attribute.
  2. Comments, then script, style, link, meta, with on* handlers plus javascript: links.
  3. Office leftovers. The Docs wrapper has to go before b becomes strong.
  4. Styled bold or italic, then style attributes. Bold is saved from the style, then the style goes.
  5. class, id, presentational attributes.
  6. Unwrap. A span counts as bare only once its attributes are gone, so this step waits for the attribute rules.
  7. b to strong, i to em. An i with no text, such as an icon-font tag, keeps its name.
  8. Empty elements, near the end, since unwrapping exposes new empties.
  9. &nbsp; swap, then printing with or without indentation.

Pick boxes by where the HTML lands

Destination Change from defaults Reason
WordPress, Ghost, Shopify rich text None The theme styles plain tags. Inline color or font from Word fights the theme.
HTML email template Untick Delete style attributes plus presentational attributes Outlook desktop renders with Word's engine. Inline styles, table width, bgcolor, cellpadding still carry the layout there.
Static site with your own CSS Tick Delete id attributes Pasted ids such as _Toc84211 or Docs heading ids collide with your own anchors.
Page using icon fonts Untick Delete class attributes An icon tag like <i class="fa fa-check"> is nothing without the class.
Markdown next None, then HTML to Markdown Converters choke on spans. Clean tags convert line for line.
Prices, units, names Leave Swap &nbsp; off The sample's 5&nbsp;MB keeps the number glued to the unit at a line break. Word's junk no-break spaces sit in empty paragraphs plus bullet spacers, which other rules remove anyway.

What the cleaner leaves alone

Size, speed, privacy

Parsing runs in this tab through the browser's own HTML parser. Nothing reaches Toolexe. A refresh restores the Word sample, so copy the output first.

Auto-clean reruns 0.6 seconds after you stop typing, up to 500 KB of source. Above 500 KB, the page waits for the Clean button. A 150-page Word report pastes as 4 to 8 MB of HTML. Cleaning finishes, though the tab pauses for a few seconds on a mid-range laptop. Clean the document in chapters when the pause bothers you.

Wrong desk?

Use the HTML beautifier when the markup is already clean but unreadable. Indentation only, no rules. Run the HTML minifier after cleaning when bytes matter more than readability. Use HTML to Text when you want no tags at all. Check the result against the spec in the HTML validator.

Questions after the first paste

Lost bold, restarted numbering, broken images, privacy, surprise tbody tags, plain-text pastes, Excel ranges.

My bold text came out plain. Where did the bold go?

Google Docs marks bold with font-weight 700 on a span, not with a b tag. Delete style attributes removes the span style, so the bold goes with the style unless Keep styled bold or italic stays ticked. Word uses real b tags, so a Word paste keeps bold either way. Bold inside a heading is left plain on purpose, since the heading is bold already.

Why does my numbered list restart at 1?

The rebuild reads the list level from mso-list but not the number Word started from. A list Word continued from an earlier section comes out as a fresh ol starting at 1. Add a start attribute by hand, for example ol start="4", or fix the numbering in Word before you copy.

The images are broken in the preview.

Word points each image at a temp file on your own disk, a path like file:///C:/Users/you/AppData/Local/Temp/msohtmlclip1/01/clip_image002.png. No web page reads your disk, so the preview shows a broken icon. The cleaner keeps the src as written. Upload the images through your CMS, then swap each src for the uploaded address.

Is the pasted document sent to Toolexe?

No. Parsing, cleaning, preview: all three run inside this browser tab. Nothing leaves the page unless you copy or download the result yourself. A refresh brings back the Word sample, so copy your output before you reload.

The output has a tbody I never wrote. Why?

The browser parser adds a tbody to every table. The same parser closes paragraphs left open, then moves any block out of an inline tag. The cleaner prints the repaired tree. Valid HTML, though not always the exact shape of the source. Diff the two boxes when the input was hand-written.

The catcher gave me one long line full of br tags.

The source app put only plain text on the clipboard. PDF readers, terminals, some note apps behave this way. With no HTML to read, the catcher escapes the text, then turns each newline into a br. Copy from the original Word or Docs file to get formatting.

Does this clean a range copied out of Excel?

Yes. Excel pastes a table with xl65 style classes, mso-number-format styles, plus column widths on every cell. Defaults strip those. Rows, cells, colspan, rowspan stay. Number formats live in the deleted styles, so a currency column keeps the visible text but loses any Excel formatting rule.