If you want to do it with a regex, you'll have to go tag by tag while keeping track of nesting levels so that you know when to remove a closing tag and when not.
To do so simply use an array that you constantly push
/pop
to/from it the type of the tag you encounter. When you encounter an opening tag, you push
true
if it has attributes and false
if it doesn't, you then remove it if it doesn't have attributes. When you encounter a closing tag, you pop
the type of the last encountered opening tag, if it had attributes (true
), you skip to the next one, if it didn't have them (false
) you remove it.
The regex should go over the opening and the closing tags in one run while giving us info about whether its a closing or an opening one and whether it has attributes or not. To do so we use regex like so <\/?font [^\s]*?>
, we group (\/)
and ([^\s]*?)
because whether or not those groups get matched, we will know if it is a closing tag or not and if it has attributes or not respectively (for example, if we match the /
then it's a closing tag). We add in the \s*
to handle empty spaces and the resulting regex is /<(\/)?\s*font\s*([^\s]*?)\s*>/g
.
Here is the function that does the job:
function stripEmptyFonts(htmlString) {
var tagTypes = [];
return htmlString.replace(/<(\/)?\s*font\s*([^\s]*?)\s*>/g, function(match, closingSlash, attributes) {
if(!closingSlash) { // if it is an opening tag (no '/' was matched)
tagTypes.push(!!attributes); // push true to the array tagTypes if it has attributes, otherwise push false (attributes will either be a string or null, we use the double negation !! to convert it to a boolean)
return attributes ? match : ""; // remove it if it has no attributes, otherwise keep it as is (read the docs of String#replace method)
} else { // if it is a closing tag (a '/' was matched)
return tagTypes.pop() ? match : ""; // if the last tag we encounterd had attributes (pop returned true) we skip this closing tag, otherwise (pop return false) we remove it
}
});
}
Example:
function stripEmptyFonts(htmlString) {
var tagTypes = [];
return htmlString.replace(/<(\/)?\s*font\s*([^\s]*?)\s*>/g, function(match, closingSlash, attributes) {
if(!closingSlash) {
tagTypes.push(!!attributes);
return attributes ? match : "";
} else {
return tagTypes.pop() ? match : "";
}
});
}
var html = `
<font>New</font>
<font color="red">Hello <font>world</font>!</font>
<font>Hello <font color="blue">back</font>!</font>
<font>ABCD<font>EFGH<font color="black">IJKL<font>MNOP<font color="red">QRST</font>UVWX</font>YZ</font>1234</font>5678</font>`
console.log(stripEmptyFonts(html));