Have it test a Regex to see if a span already exists.
function() {
var link = $(this);
if(/<span/.test(link.html()))
return;
link.html(link.html().replace(/(^|[^@\w])@(\w{1,30})\b/g, '$1<span class="mention">@$2</span>'));
}
Edit:
Okay so I finally understand what you're asking and what you're trying to do. However, I didn't come up with an answer in my attempt. But I'd rather not leave you empty handed, so I'm telling you what I went through. Hopefully this will help in some way.
Attempt 1
First, you are correct on needing to change your regex. But it's not possible with a single expression. Originally my idea was to check for the ending tag. This would match @test
from <span>@test</span>@test2
.
But this doesn't account for @ between two spans: <span></span>@test<span></span>
. See the last line here https://regex101.com/r/zB3yI9/5.
To counter this, you would need to check for an opening tag right before. But what it was a nested span.... Again this is the same problem.
Attempt 2
I know now a Regex pattern isn't nearly complicated enough by itself. Instead you need to recursively traverse the DOM until you reach a simple workable string.
I wrote up a fiddle in jQuery to do this.
http://jsfiddle.net/zf63hca2/
But I ran into a problem. jQuery only sees DOM objects and not the stray text around them.
Attempt 3
So the DOM can't help you, it has to be done with Regex. The hard way. I now know why they warned me not to Regex HTML. I'd write the code but my brain is about to melt. So instead here's the details on the steps.
- Recursively find all simple expressions, remove them from the string. A simple expression is an opening and closing span without an opening between.
- Keep repeating 1 until no more matches. This will account for nesting.
- You should be finally left with a bunch of strings without span tags.
- Match for Twitter accounts and replace.
- Work backwards and put the whole thing back together.
There's a Regex API that simplifies this process. XRegExp supports chaining. The advantage is you can also get the start and end index from each match.
TL;DR
If you really want to get this to work with DOM then by all means, go for it. But as of now, it can already build multiple Twitter links as long as the provided string contains no DOM.