I’m looking for a way to properly replace nested custom tags with their HTML equivalents. For example, suppose we have the following text:
This is {b:bold text}
Which should become:
This is <b>bold text</b>
I’m aware that I can – and probably should – use something like a span with a “bold” class instead of the old “b” tags, but there’s a reason I’m sticking with “b” for the purpose of this example. I may have nested tags:
This is {b:bold text and {i:italic}}
which should become:
This is <b>bold text and <i>italic</i></b>
However, I have these regexes (which I use with the replace() function):
/\{b:([\s\S]*?)\}/gm
/\{i:([\s\S]*?)\}/gm
And then the result will become:
This is <b>bold text and <i>italic</b></i>
The tags are not properly nested. Again, using spans can solve this in this case, but that won’t work with things like “ul”, “li”, “h1”, …
Greedy regexes will also cause problems if the text looks like this:
This is {b:bold text} and {i:italic}
So my current solution is to replace everything with span first, using a data-tag attribute to indicate what it should actually be, and then use jQuery to find all span nodes and replace them with the proper tags:
{h:This is a header}
becomes
<span data-tag='h1'>This is a header</span>
becomes
<h1>This is a header</h1>
It works well, but i’m wondering if there is an easier way to do this. The intermediate method feels a bit like a duct tape solution and I would like to “beautify” it.
Any suggestions?
Ditch the Regex and use one of the many templating tools out there, such as Mustache, or t.js.
EDIT: Fixed!
…but if you are avoiding such simplicities in life, here’s how to do it with a regular expression:
So you call
parseand pass it your string. It recursively parses your string until no other mark-up is found. This new one works in reverse, parsing out the items that don’t have items within, then moving outward.To implement the H1 example that you added, you could either instead us
{h1:This is the header}and add it to the(b|i)clause, or use aswitchstatement in the replace function instead of just returning $1.Here’s the JSFiddle.