4
I am trying to do the following processing in a javascript string using ER (Regular Expression):
With that input: um <b>negrito<b>negrito interno</b>externo</b> aqui <b>negrito</b> <i>italico</i>.
, would like to get the tag
<b>
complete, with all its contents up to its closing pair </b>
, this being the expected result: <b>negrito<b>negrito interno</b>externo</b>
and <b>negrito</b>
.
But I’m failing to consider that a tag
can contain the same internally, and I was able to get as far as possible to this result (which does not consider the possibility of a tag
equal internally, as can be seen in the first result where it is <b>negrito<b>negrito interno</b>
instead of <b>negrito<b>negrito interno</b>externo</b>
:
var entrada = 'um <b data-remove>negrito<b>negrito interno</b>externo</b> aqui <b>negrito</b> <i>italico</i>.';
var regex = /<(b)>.*?<\/\1>/g;
// limpa DOM para imprimir
document.body.innerHTML = "";
entrada.replace(regex, function(match) {
console.log(match);
// para imprimir do DOM
document.body.appendChild(document.createTextNode(match));
document.body.appendChild(document.createElement("br"));
return match;
});
body {
white-space: pre;
font-family: monospace;
}
My knowledge of ER is limited, and has practically reached the limit in this situation. So I await some precious hint of some expert in ER, or a "Forget it’s not possible with ER =(".
Edit 2 Expected solution:
The way I look and do not know how to do would be something that was counting/accumulating the occurrences of opening tags and ignoring the closures until it is the matching closure for the opening (equivalent to the first opening tag).
If there are any questions comment!
Edit 1: My real case for better understanding of the problem:
This actual example is only intended to demonstrate the context where I am using the function in question, and why I cannot do this via jQuery or any other parser in the browser’s DOM. Because I need to leave the DOM correct, so that the CSS is applied correctly and only after the conversion to style inline I can remove what was only for the Browser to render correctly and then get the result of my expected template.
$(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 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) {
$root.each(function() {
var $item = $(this);
var style = getCssDeclared($item);
$item.css(style);
// recursive call chields
convertCssToInlineStyle($item.children());
});
}
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;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<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>
Note: In this example (real) not the problem because there are no identical tags inside tr, but I know this would be a bug I want to solve to make the tool generic.
This code is server-side (Node.js, IO.js), or you will run it in the same browser?
– user25930
@ctgPi, even Browser, client-side.
– Fernando Leal
Condemn your question. You have a lot of unnecessary information. Show only your well specified question and what you have tried. Just explain that you need it to be with Regex. No need to justify your need.
– Guill
@Guill, I was without my real example and eventually answers came very far from the solution, so I tried to add the almost complete problem to understand the context of the problem. But I will see if I remove some things that may be irrelevant to the problem in my actual code.
– Fernando Leal
@Guill, yes it works for any internal occurrence number (I’ve already edited and removed) but it’s not what you expect to look this example of your solution to my real case, I’m thinking that’s not possible =(.
– Fernando Leal
Let’s go continue this discussion in chat.
– Guill