There’s a document which contains HTML tags, some of them in short form: <br> instead of <br/> and <img...> instead of <img.../>.
Make it XML valid.
Note that there can be both valid and invalid of a tag in the text.
Example:
var text = <br> <a href="#"><img src="a"></a> <br/> <br></br>'
After the replacement, the first and second tags should be closed:
text == '<br/> <a href="#"<img src="a"/></a> <br/> <br> </br>'
P.S. In other words, close BR and IMG tags which are not closed.
First solve the task in the case when there are no tags ending with <br/>. Use lookahead.
First, we solve the task without self-closing tags <br/>.
We can do assume so, because self-closing tags can be replaced with non-closing tags with one more regexp, so 2 regexps would do the job anyway.
Finding a <br> without a following </br> requires a negative lookahead:
var re = /<br>(?!</br>)/
Let’s adapt this to IMG as well:
var re = /<(br|img).*?>(?!</\1>)/

To be really peculiar, we could add \b after tag name, to ensure that <brown> (or kind of) doesn’t match:
var re = /<(br|img)\b.*?>(?!</\1>)/

Now all we need to replace it, adding a closing slash:
text.replace(/<(br|img)\b(.*?)>(?!<\/\1>)/g, '<$1$2/>')
To support tags, which are already self-closing, we match optional / and put it out of the brackets, so tag body won’t contain it:
text.replace(/<(br|img)\b(.*?)*!*\/?*/!*>(?!<\/\1>)/g, '<$1$2/>')
The regexp above excludles closing / from tag body if there is any.
Finally, the solution:
var text = '*!*<br>*/!* <a href="#">*!*<img src="a">*/!*</a> <br/> <br></br>' text = text.replace(/<(br|img)\b(.*?)\/?>(?!<\/\1>)/g, '<$1$2/>') alert(text)