Clean Word markup

When writing a web-app that accepts formatted input from users, you’ll often find that they will copy and paste text from Microsoft Word. Unfortunately, Word fills the markup with lots of unnecessary and unwanted muck. To clean this all up, I wrote the following function (directly implemented on the String prototype below):

[sourcecode language=javascript]String.implement({
sanitiseWord: function() {
var s = this.replace(/\r/g, ‘\n’).replace(/\n/g, ‘ ‘);
var rs = [];
rs.push(/ /g); // Comments
rs.push(/.+?<\/title>/g); // Title<br /> rs.push(/<(meta|link|.?o:|.?style|.?div|.?head|.?html|body|.?body|.?span|!\[)[^>]*?>/g); // Unnecessary tags<br /> rs.push(/ v:.*?=”.*?”/g); // Weird nonsense attributes<br /> rs.push(/ style=”.*?”/g); // Styles<br /> rs.push(/ class=”.*?”/g); // Classes<br /> rs.push(/( ){2,}/g); // Redundant  s<br /> rs.push(/</p> <p>(\s| )*?<\/p>/g); // Empty paragraphs<br /> rs.each(function(regex) {<br /> s = s.replace(regex, ”);<br /> });<br /> return s.replace(/\s+/g, ‘ ‘);<br /> }<br /> });[/sourcecode]</p> <p>If you’re not using MooTools, the function will look something like this:<br /> [sourcecode language=javascript]String.prototype.sanitiseWord = function() {<br /> // function body here…<br /> };[/sourcecode]</p> <h2>Usage</h2> <p>[sourcecode language=javascript]var s = “(some awful Word markup)”.sanitiseWord();[/sourcecode]</p> <p>In one of the tests I ran, the input went from around 7000 characters to just 700.</p> <h2>Example</h2> <p><iframe style="width: 100%; height: 300px" src="http://mootools.net/shell/26Jpf/embedded/"></iframe></p> <p>Some of the regular expressions I used were adapted from C# ones in <a href="http://www.codinghorror.com/blog/archives/000485.html">a post by Jeff Atwood</a>.</p> </div> <div class="wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--60)"> </div> <div class="wp-block-group alignwide is-layout-flow wp-block-group-is-layout-flow" style="margin-top:var(--wp--preset--spacing--60);margin-bottom:var(--wp--preset--spacing--60);"> <nav class="wp-block-group alignwide is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-878fe601 wp-block-group-is-layout-flex" aria-label="Post navigation" style="border-top-color:var(--wp--preset--color--accent-6);border-top-width:1px;padding-top:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--40)"> <div class="post-navigation-link-previous wp-block-post-navigation-link"><span class="wp-block-post-navigation-link__arrow-previous is-arrow-arrow" aria-hidden="true">←</span><a href="https://barryvan.com.au/2010/01/full-width-text-inputs-without-extraneous-markup-or-scripting/" rel="prev">Input elements that fill their container</a></div> <div class="post-navigation-link-next wp-block-post-navigation-link"><a href="https://barryvan.com.au/2010/01/another-new-theme/" rel="next">Another new theme</a><span class="wp-block-post-navigation-link__arrow-next is-arrow-arrow" aria-hidden="true">→</span></div> </nav> </div> <div class="wp-block-comments wp-block-comments-query-loop" style="margin-top:var(--wp--preset--spacing--70);margin-bottom:var(--wp--preset--spacing--70)"> <h2 class="wp-block-heading has-x-large-font-size">Comments</h2> <div id="respond" class="comment-respond wp-block-post-comments-form"> <h3 id="reply-title" class="comment-reply-title">Leave a Reply <small><a rel="nofollow" id="cancel-comment-reply-link" href="/2010/01/clean-word-markup/#respond" style="display:none;">Cancel reply</a></small></h3><form action="https://barryvan.com.au/wp-comments-post.php" method="post" id="commentform" class="comment-form"><p class="comment-notes"><span id="email-notes">Your email address will not be published.</span> <span class="required-field-message">Required fields are marked <span class="required">*</span></span></p><p class="comment-form-comment"><label for="comment">Comment <span class="required">*</span></label> <textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525" required></textarea></p><p class="comment-form-author"><label for="author">Name <span class="required">*</span></label> <input id="author" name="author" type="text" value="" size="30" maxlength="245" autocomplete="name" required /></p> <p class="comment-form-email"><label for="email">Email <span class="required">*</span></label> <input id="email" name="email" type="email" value="" size="30" maxlength="100" aria-describedby="email-notes" autocomplete="email" required /></p> <p class="comment-form-url"><label for="url">Website</label> <input id="url" name="url" type="url" value="" size="30" maxlength="200" autocomplete="url" /></p> <p class="form-submit wp-block-button"><input name="submit" type="submit" id="submit" class="wp-block-button__link wp-element-button" value="Post Comment" /> <input type='hidden' name='comment_post_ID' value='410' id='comment_post_ID' /> <input type='hidden' name='comment_parent' id='comment_parent' value='0' /> </p><p style="display: none;"><input type="hidden" id="akismet_comment_nonce" name="akismet_comment_nonce" value="479eb7e95e" /></p><p style="display: none !important;" class="akismet-fields-container" data-prefix="ak_"><label>Δ<textarea name="ak_hp_textarea" cols="45" rows="8" maxlength="100"></textarea></label><input type="hidden" id="ak_js_1" name="ak_js" value="180"/><script> document.getElementById( "ak_js_1" ).setAttribute( "value", ( new Date() ).getTime() ); </script> </p><input type="hidden" id="captchafree" name="captchafree" value="" /> <script type="text/javascript"> //<![CDATA[ function gethash(){ document.getElementById('captchafree').form.onsubmit = null; if(document.getElementById('submit')) document.getElementById('submit').value='Please wait...'; var mysack = new sack("https://barryvan.com.au/wp-content/plugins/wp-captcha-free/captcha-free.php"); mysack.execute = 1; mysack.method = 'POST'; mysack.onError = function() { alert('Unable to get Captcha-Free Hash!') }; mysack.setVar('post_id', 410); mysack.runAJAX(); return false; } function gothash(myhash){ document.getElementById('captchafree').value = myhash; // Workaround for Wordpress' retarded choice of naming the submit button same as a JS function name >:-( document.getElementById('submit').click(); } document.getElementById('captchafree').form.onsubmit = gethash; //]]> </script> <noscript><p><strong>Please note:</strong> JavaScript is required to post comments.</p></noscript> </form> </div><!-- #respond --> <p class="akismet_comment_form_privacy_notice">This site uses Akismet to reduce spam. <a href="https://akismet.com/privacy/" target="_blank" rel="nofollow noopener">Learn how your comment data is processed.</a></p> </div> <form id="webmention-form" class="webmention-form wp-block-webmention-form" action="https://barryvan.com.au/wp-json/webmention/1.0/endpoint" method="post"> <p class="webmention-form__source"> <label for="webmention-source">Posted a response on your own website? Share the link here:</label> <input id="webmention-source" class="webmention-source" type="url" autocomplete="url" required pattern="^https?:\/\/(.*)" name="source" placeholder="https://" aria-describedby="webmention-source-description" /> <small id="webmention-source-description">Your post must include a link to this post.</small> </p> <div class="webmention-form__submit"> <button id="webmention-submit" class="webmention-submit wp-element-button wp-block-button__link" type="submit" name="submit" value="Send Webmention">Send Webmention</button> <details class="webmention-form__help"> <summary>How does this work?</summary> <div> Write a response on your own website and include a link to this post. Then submit your response’s URL here. Your response may appear here after moderation. To update or remove it, edit or delete your original post and submit the same URL again. <a href="https://indieweb.org/Webmention">Learn more about Webmentions.</a> </div> </details> </div> <input id="webmention-format" type="hidden" name="format" value="html" /> <input id="webmention-target" type="hidden" name="target" value="https://barryvan.com.au/2010/01/clean-word-markup/" /> </form> </div> <div class="wp-block-group alignwide has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--60)"> <h2 class="wp-block-heading alignwide has-small-font-size" style="font-style:normal;font-weight:700;letter-spacing:1.4px;text-transform:uppercase">More posts</h2> <div class="wp-block-query alignwide is-layout-flow wp-block-query-is-layout-flow"> <ul class="alignfull wp-block-post-template is-layout-flow wp-container-core-post-template-is-layout-b4d04ffe wp-block-post-template-is-layout-flow"><li class="wp-block-post post-1206 post type-post status-publish format-standard has-post-thumbnail hentry category-edm category-music-downloads category-music tag-edm tag-music"> <div class="wp-block-group alignfull is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-cba70755 wp-block-group-is-layout-flex" style="border-bottom-color:var(--wp--preset--color--accent-6);border-bottom-width:1px;padding-top:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30)"> <h3 class="wp-block-post-title has-large-font-size"><a href="https://barryvan.com.au/2025/05/cant-get-through/" target="_self" >Can’t get through</a></h3> <div class="has-text-align-right wp-block-post-date"><a href="https://barryvan.com.au/2025/05/cant-get-through/"><time datetime="2025-05-17T09:01:13+08:00">2025-05-17</time></a></div> </div> </li><li class="wp-block-post post-1203 post type-post status-publish format-standard has-post-thumbnail hentry category-edm category-music-downloads category-music"> <div class="wp-block-group alignfull is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-cba70755 wp-block-group-is-layout-flex" style="border-bottom-color:var(--wp--preset--color--accent-6);border-bottom-width:1px;padding-top:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30)"> <h3 class="wp-block-post-title has-large-font-size"><a href="https://barryvan.com.au/2025/02/across-the-skies/" target="_self" >Across the skies</a></h3> <div class="has-text-align-right wp-block-post-date"><a href="https://barryvan.com.au/2025/02/across-the-skies/"><time datetime="2025-02-24T08:53:00+08:00">2025-02-24</time></a></div> </div> </li><li class="wp-block-post post-1197 post type-post status-publish format-standard has-post-thumbnail hentry category-edm category-music-downloads category-music tag-music"> <div class="wp-block-group alignfull is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-cba70755 wp-block-group-is-layout-flex" style="border-bottom-color:var(--wp--preset--color--accent-6);border-bottom-width:1px;padding-top:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30)"> <h3 class="wp-block-post-title has-large-font-size"><a href="https://barryvan.com.au/2025/02/not-enough-to-feel/" target="_self" >Not enough to feel</a></h3> <div class="has-text-align-right wp-block-post-date"><a href="https://barryvan.com.au/2025/02/not-enough-to-feel/"><time datetime="2025-02-23T08:41:00+08:00">2025-02-23</time></a></div> </div> </li><li class="wp-block-post post-1200 post type-post status-publish format-standard has-post-thumbnail hentry category-edm category-music-downloads category-music tag-edm tag-music"> <div class="wp-block-group alignfull is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-cba70755 wp-block-group-is-layout-flex" style="border-bottom-color:var(--wp--preset--color--accent-6);border-bottom-width:1px;padding-top:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30)"> <h3 class="wp-block-post-title has-large-font-size"><a href="https://barryvan.com.au/2025/02/roads-that-lead-apart/" target="_self" >Roads that lead apart</a></h3> <div class="has-text-align-right wp-block-post-date"><a href="https://barryvan.com.au/2025/02/roads-that-lead-apart/"><time datetime="2025-02-17T08:49:00+08:00">2025-02-17</time></a></div> </div> </li></ul> </div> </div> </main> <footer class="wp-block-template-part"> <div class="wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="padding-top:var(--wp--preset--spacing--60);padding-bottom:var(--wp--preset--spacing--50)"> <div class="wp-block-group alignwide is-layout-flow wp-block-group-is-layout-flow"> <div class="wp-block-group alignfull is-content-justification-space-between is-layout-flex wp-container-core-group-is-layout-cf54d0a6 wp-block-group-is-layout-flex"> <div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-794e3cfa wp-block-columns-is-layout-flex"> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:100%"><h2 class="wp-block-site-title"><a href="https://barryvan.com.au" target="_self" rel="home">barryvan</a></h2> </div> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"> <div style="height:var(--wp--preset--spacing--40);width:0px" aria-hidden="true" class="wp-block-spacer"></div> </div> </div> <div class="wp-block-group is-content-justification-space-between is-layout-flex wp-container-core-group-is-layout-bf19e0b3 wp-block-group-is-layout-flex"> <nav class="is-vertical wp-block-navigation is-layout-flex wp-container-core-navigation-is-layout-831b2db5 wp-block-navigation-is-layout-flex" aria-label=" 2"><ul class="wp-block-navigation__container is-vertical wp-block-navigation"><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Blog</span></a></li><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">About</span></a></li><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">FAQs</span></a></li><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Authors</span></a></li></ul></nav> <nav class="is-vertical wp-block-navigation is-layout-flex wp-container-core-navigation-is-layout-831b2db5 wp-block-navigation-is-layout-flex" aria-label=" 3"><ul class="wp-block-navigation__container is-vertical wp-block-navigation"><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Events</span></a></li><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Shop</span></a></li><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Patterns</span></a></li><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Themes</span></a></li></ul></nav> </div> </div> <div style="height:var(--wp--preset--spacing--70)" aria-hidden="true" class="wp-block-spacer"></div> <div class="wp-block-group alignfull is-content-justification-space-between is-layout-flex wp-container-core-group-is-layout-2ab8c7fb wp-block-group-is-layout-flex"> <p class="has-small-font-size wp-block-paragraph">Twenty Twenty-Five</p> <p class="has-small-font-size wp-block-paragraph"> Designed with <a href="https://wordpress.org" rel="nofollow">WordPress</a> </p> </div> </div> </div> </footer> </div> <script type="speculationrules"> {"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/wp-content/uploads/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/twentytwentyfive/*","/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]} </script> <script data-wp-router-options="{"loadOnClientNavigation":true}" fetchpriority="low" id="@wordpress/block-library/navigation/view-js-module" src="https://barryvan.com.au/wp-includes/js/dist/script-modules/block-library/navigation/view.min.js?ver=1bf28ded04f9f188bdcb" type="module"></script> <script defer id="akismet-frontend-js" src="https://barryvan.com.au/wp-content/plugins/akismet/_inc/akismet-frontend.js"></script> <script async data-wp-strategy="async" fetchpriority="low" id="comment-reply-js" src="https://barryvan.com.au/wp-includes/js/comment-reply.min.js"></script> </body> </html> <!-- Page optimized by LiteSpeed Cache @2026-10-24 19:35:46 --> <!-- Page cached by LiteSpeed Cache 7.9.2 on 2026-10-24 19:35:46 --> <!-- Guest Mode --> <!-- QUIC.cloud UCSS in queue -->