HTML Cleaner
Visual Studio Code extension that cleans HTML copied from SharePoint, Microsoft Word, Outlook, and similar sources. It uses Cheerio for DOM parsing—never regex—to strip Office metadata, non-Latin attributes, mso-* styles, empty attributes, and empty wrapper elements.
Installation
From a VSIX
- Package the extension (see Packaging).
- In VS Code: Extensions →
⋯ → Install from VSIX…
- Select the generated
.vsix file.
From source
cd html-cleaner
npm install
npm run compile
Then press F5 in VS Code to launch an Extension Development Host with HTML Cleaner loaded.
Development
npm install
npm run watch
Open the project in VS Code and use Run → Start Debugging (or F5) to open a new window with the extension active. Set breakpoints in src/ as needed.
Project layout
| File |
Role |
src/extension.ts |
VS Code command registration and editor I/O |
src/cleaner.ts |
Orchestrates cleanup rules |
src/rules.ts |
Individual DOM cleanup rules |
src/utils.ts |
Shared helpers (non-Latin detection, etc.) |
src/types.ts |
Options and shared constants |
Building
npm install
npm run compile
Compiled JavaScript is written to out/.
Packaging
npm run package
This runs vsce package and produces a .vsix in the project root. Requires @vscode/vsce (already listed in devDependencies).
Usage
- Open an HTML file (or any editor containing HTML).
- Open the Command Palette (
Cmd+Shift+P / Ctrl+Shift+P).
- Run Clean HTML.
The extension:
- Reads the entire active document
- Cleans the HTML with Cheerio according to your settings
- Replaces the document contents
- Runs the built-in formatter (
editor.action.formatDocument)
- Shows a success notification
Settings
Defaults are true except collapseRepeatedSpaces (false):
| Setting |
Default |
Description |
htmlCleaner.removeOfficeMetadata |
true |
Remove SharePoint/Office/VML/CCP attributes, Office class names, and conditional comments |
htmlCleaner.removeNonLatinAttributes |
true |
Remove attributes whose values contain non-Latin text or emoji |
htmlCleaner.removeMSOStyles |
true |
Strip mso-* declarations from inline styles |
htmlCleaner.removeEmptyAttributes |
true |
Remove empty / whitespace / null / undefined attributes |
htmlCleaner.removeEmptyElements |
true |
Remove empty span, font, and o:p elements |
htmlCleaner.normalizeInvisibleSpaces |
true |
Replace NBSP and other invisible spaces with normal spaces |
htmlCleaner.removeZeroWidthCharacters |
true |
Remove zero-width characters (ZWSP, ZWJ, BOM, etc.) |
htmlCleaner.unwrapMetadataSpans |
true |
Unwrap Word/SharePoint metadata spans, keep their text |
htmlCleaner.removeSpaceBeforePunctuation |
true |
Remove spaces immediately before punctuation |
htmlCleaner.trimTrailingWhitespace |
true |
Trim trailing whitespace from text and output lines |
htmlCleaner.collapseRepeatedSpaces |
false |
Collapse repeated spaces without damaging indentation |
Examples
Non-Latin attributes
Before
<img src="https://example.com/html-cleaner/photo.jpg" alt="제품 사진" aria-label="こんにちは" data-description="Привет">
After
<img src="https://example.com/html-cleaner/photo.jpg">
Latin attribute values are kept:
<img src="https://example.com/html-cleaner/photo.jpg" alt="Product photo" title="Café">
Before
<div
class="MsoNormal WordSection1 ExternalClassABC content"
data-sp-permalink="https://contoso.sharepoint.com/x"
data-ogtitle="Hello"
xmlns:v="urn:schemas-microsoft-com:vml"
style="width:100%;mso-width-percent:1000;color:red">
<!--[if gte mso 9]><xml></xml><![endif]-->
<span></span>
<p>Hello world</p>
</div>
After
<div class="content" style="width:100%; color:red">
<p>Hello world</p>
</div>
Before
<p data-contrast="none">
<span data-ccp-props="{"201341983":0}">Hello world</span>
<span class="SpellE">teh</span> end .
</p>
After
<p>
Hello world
teh end.
</p>
Empty attributes and elements
Before
<a href="/page" title="" data-track=" ">
<font></font>
<span> </span>
<o:p></o:p>
Link text
</a>
After
<a href="/page" title="">
Link text
</a>
Whitelisted attributes (href, src, id, class, title, name, type, rel, target) are kept even when empty; they are only removed when their value contains non-Latin text.
License
MIT