JSFiddle - React, Tailwind, and code Playground

by Fernando Leal

HTML

<div id="report">
  <table>
    <thead>
      <tr data-remove="true">
        <th>{{theadContent}}</th>
      </tr>
    </thead>
    <tbody>
      <tr data-remove="true">
        <th>{{tbodyContent}}</th>
      </tr>
    </tbody>
    <tfoot>
      <tr data-remove="true">
        <th>{{tfootContent}}</th>
      </tr>
    </tfoot>
  </table>
</div>
<div id="tools">
  <button id="btnGenerateHtmlMail">
    Gerar HTML E-mail
  </button>
  <div contenteditable="true" id="result" style="width: 99%;resize: none;border: 1px solid #ccc;padding: 0.5%;"></div>
</div>

CSS

table {
	border-collapse: collapse;
	border-spacing: 0;
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
	width: 100%;
}

table td, table th {
	padding: 8px;
	padding-top: 3px;
	padding-bottom: 3px;
	line-height: 1.428571429;
	border: 1px solid #ddd;
}

table > tfoot {
	font-weight: bold;
	text-align: center;
}

JavaScript

$(function() {
  $('#btnGenerateHtmlMail').click(function(ev) {
    var $report = $('#report');
    convertCssToInlineStyle($report);
    var reportHtml = $report.html();
    reportHtml = reportHtml
      /* remove class attribute */
      .replace(/class=('|").*?\1/g, "")
      /* remove id attribute */
      .replace(/id=('|").*?\1/g, "")
      /* remove attribute  data-render-value but retains the value*/
      .replace(/data-render-value=('|").*?\1/g, function replacer(match) {
        return match.replace(/data-render-value=('|")/, "").replace(/('|")$/, "");
      })
      /* remove comments html */
      .replace(/<!--.*?-->/g, "")
      /* remove tab, enter and whitespace */
      .replace(/\s\s+/g, ' ')
// ----->>>   // esse é o meu caso de problema, nesse exemplo não da problema pois nnão há tags iguais dentro do tr, mas sei que isso seria um bug que quero resolver para tornar a ferramenta generica
      .replace(/<(tr) data-remove="true".*?>.*?<\/\1>/g, function replacer(match) {
        console.log(match);
        return match.match(/{{.*?}}/g);
      });
    $('#result').text(reportHtml);
  });
});


/* Metódos irrelevantes para o problema */

function getCssDeclared($elem) {
  var sheets = document.styleSheets,
    o = {};
  for (var i in sheets) {
    var rules = sheets[i].rules || sheets[i].cssRules;
    for (var r in rules) {
      if ($elem.is(rules[r].selectorText)) {
        o = $.extend(o, css2json(rules[r].style), css2json($elem.attr('style')));
      }
    }
  }
  return o;
}

function css2json(css) {
  var s = {};
  if (!css)
    return s;
  if (css instanceof CSSStyleDeclaration) {
    for (var i in css) {
      if ((css[i]).toLowerCase) {
        s[(css[i]).toLowerCase()] = (css[css[i]]);
      }
    }
  } else if (typeof css == "string ") {
    css = css.split("; ");
    for (var i in css) {
      var l = css[i].split(": ");
      s[l[0].toLowerCase()] = (l[1]);
    }
  }
  return s;
}

function convertCssToInlineStyle($root) {
 ...