simple HTML snippet validation function

simple JS function to validate if an HTML snippet is valid HTML or if something is wrong with it

by Andreas Bernhard

HTML

<h1>simpleValidateHtmlStr(htmlStr, strictBoolean)</h1>
<ul>
  <li>checks html string tag by tag if valid</li>
  <li>trys html string to render as dom</li>
  <li>compares theoretically to be created tag count with actually rendered html dom tag count</li>
  <li>if checked 'strict', &lt;br/&gt; and empty attribute normalizations '=""' are not ignored</li>
</ul>
<p>
Returns</p>
<ul>
  <li><b>true</b> if validated html is same as entered html</li>
  <li><b>false</b> if one of the tests failes</li>
  <li><b>normalized html string</b>  if validated html is not equal to entered html - <br/> !! Note: normalized strings can be really bad !!  </li>
</ul>

<h2>
  Validating HTML snippets
</h2>
<ol id="testresults">
  <li>RESULT_STRICT (RESULT_NON_STRICT)<br>
  &nbsp;&nbsp; HTML_STR_INPUT<br>
  <span class="muted">-></span> HTML_STR_NORMALIZED</li>
</ol>

<script type="test/template">
  <h1>title</h1>
  <p>a paragraph with <b>some formatted text</b></p>
  <h2>sub title</h2>
  <div class="someclass" data-attr="some value">
    <ul>
      <li>blue</li>
      <li>red</li>
    </ul>
  </div>
</script>

<script type="test/template">
  <h1>title</h1>
  <p>a paragraph with <b>some formatted text</b></p>
  <h2>sub title</h2>
  <div class="someclass' data-attr="some value">
    broken attribute in element
  </div>
</script>

<textarea type="test/template">
  <h1>title</h1>
  <p>script block with tag-references</p>
  <script>
  	$(function(){
    	$('body').append($('<div>la di da</div>'));
    })
  </script>
</textarea>

CSS

body {
  font-family: monospace;
}

ol li {
  margin-bottom: 0.5em;
  padding-top: 0.25em;
  border-top: 1px dotted lightgray;
}

[type="test/template"]{ 
  display: none; 
}

.type-ok {
  color: green;
}

.type-error {
  color: red;
  font-weight: bold;
}

.type-warn {
  color: orange;
}

.muted {
  color: gray;
}

JavaScript

/**
 * simpleValidateHtmlStr
 * 
 * checks html string tag by tag if valid, trys html string to render as dom, compares theoretically to be created tag count with 
 * actually rendered html dom tag count
 * returns true if validated html is same as entered html
 * returns false if one of the tests failes
 * returns normalized html str if validated html is not equal to entered html
 *
 * kudos
 *	- http://www.mkyong.com/regular-expressions/how-to-validate-html-tag-with-regular-expression/
 *	- https://stackoverflow.com/questions/10026626/check-if-html-snippet-is-valid-with-javascript#14216406
 *
 * @param	htmlStr	string with html snippet
 * @param	strictBoolean if true, <br/> >> <br> and empty attribute conversion are not ignored
 * @retuns {string|boolean}
 */

function simpleValidateHtmlStr(htmlStr, strictBoolean) {
  if (typeof htmlStr !== "string")
    return false;

  var validateHtmlTag = new RegExp("<[a-z]+(\s+|\"[^\"]*\"\s?|'[^']*'\s?|[^'\">])*>", "igm"),
    sdom = document.createElement('div'),
    noSrcNoAmpHtmlStr = htmlStr
    	.replace(/ src=/igm, " svhs___src=")
      .replace(/&amp;/igm, "#svhs#amp##"),
    noSrcNoAmpIgnoreScriptContentHtmlStr = noSrcNoAmpHtmlStr
    	.replace(/\n\r?/igm, "#svhs#nl##") // temporarily remove line breaks
      .replace(/(<script[^>]*>)(.*?)(<\/script>)/igm, "$1$3")
      .replace(/#svhs#nl##/igm, "\n\r"),  // re-add line breaks
    htmlTags = noSrcNoAmpIgnoreScriptContentHtmlStr.match(/<[a-z]+[^>]*>/igm),
    htmlTagsCount = htmlTags ? htmlTags.length : 0,
    tagsAreValid, resHtmlStr;
    
    console.log(noSrcNoAmpHtmlStr, noSrcNoAmpIgnoreScriptContentHtmlStr, htmlTags);
    
  if(!strictBoolean){
  	// ignore <br/> conversions
  	noSrcNoAmpHtmlStr = noSrcNoAmpHtmlStr.replace(/<br\s*\/>/, "<br>")
  }

  if (htmlTagsCount) {
    tagsAreValid = htmlTags.reduce(function(isValid, tagStr) {
      return isValid && tagStr.match(validateHtmlTag);
    }, true);

    if (!tagsAreValid) {
      return false;
    }
  }


 ...