问题
I'm working on a bbcode example, but i cannot seem to get it to work. the regex matches all the [img] tags and make it all look wierd. I'm trying to have the option to click on the image and get it full size and when I do, everything becomes a link (when i have more than once img-tag).
Here's my text:
[img size="small" clickable="no"]img1.jpg[/img]
[img size="large" clickable="yes"]img2.jpg[/img]
Here's my source code:
var bbArray = [/\n/g,
/\[img size="(.*?)" clickable="yes"\](.*?)\[\/img\]/g,
/\[img size="(.*?)" clickable="no"\](.*?)\[\/img\]/g];
var bbReplace = ['<br>',
'<a href="'+path+'img/$2" target="_blank"><img src="'+path+'img/$1_$2?'+ new Date().getTime() +'" alt="$2"></a>',
'<img src="'+path+'img/$1_$2?'+ new Date().getTime() +'" alt="$2">'];
The operation:
for (var i = 0; i < content_text_bb.length; i++) {
content_text_bb = content_text_bb.replace(bbArray[i], bbReplace[i]);
}
the result:
<img src="localhost/img/small" clickable="no" ]img1.jpg[="" img]
[img size="large_img2.jpg?1423317485160" alt="img2.jpg">;
I'm not that familiar with regex and I really need someone to look at it, I'm lost.
回答1:
First thing first, your loop should be:
for (var i = 0; i < bbArray.length; i++) {
(not content_text_bb.length)
Secondly, the issue you have is with this size="(.*?)
. This says: match any content non-greedily till I find the first "thing-that-follow" (in this case the thing-that-follows is the first occurrence of " clickable="yes"
If you look at your input text, the search for [img size="{ANYTHING}" clickable="yes"]
means that {ANYTHING} is: small" clickable="no"]img1.jpg[/img][img size="large
and you can see how that returns your results, and breaks everything.
So, it should firstly be noted that regexps are not the best tool for language processing (plenty of posts on SO and the internet at large on the topic). In this particular case, you can fix your problem by being very specific about what you want matched.
Do NOT match "anything". If you want to match a size attribute, look for digits only. If you want to match any property value, look for "{ANYTHING_NOT_DOUBLE_QUOTES}". So, with that said, if you change bbArray to the code below, it should work in the particular example you have given us:
var bbArray = [/\n/g,
/\[img size="([^"]*)" clickable="yes"\](.*?)\[\/img\]/g,
/\[img size="([^"]*)" clickable="no"\](.*?)\[\/img\]/g];
Just to be clear: while this should work on your current input, it is by no mean robust bbcode processing. It will only match [img]
bbcode tags that have exactly one size
attribute and one clickable
attribute, in that order!! Most free-to-type bbcode out-there will have much broader variations, and this code obviously won't work on them.
回答2:
Something that may be of interest to you, Extendible BBCode Parser. An example of use.
var bbcArr = [
'[img size="small" clickable="no"]img1.jpg[/img]',
'[img size="large" clickable="yes"]img2.jpg[/img]'
];
XBBCODE.addTags({
"img": {
openTag: function(params, content) {
params = (params.match(/(\S+?=".*?")/g) || [])
.reduce(function(opts, item) {
var pair = item.match(/(\S+?)="(.*?)"/);
opts[pair[1]] = pair[2];
return opts;
}, {});
var html = '<img src="http://localhost/img/';
if (params.clickable === 'yes') {
html = '<a href="http://localhost/img/' + content +
'" alt="' + content + '">' + html;
}
if (params.size === 'small' || params.size === 'large') {
html += params.size + '/';
}
html += content + '" />';
if (params.clickable === 'yes') {
html += '</a>';
}
return html;
},
closeTag: function(params, content) {
return '';
},
displayContent: false
}
});
bbcArr.forEach(function(item) {
var result = XBBCODE.process({
text: item,
removeMisalignedTags: false,
addInLineBreaks: false
});
this.appendChild(document.createTextNode(result.html + '\n'));
}, document.getElementById('out'));
<script src="https://rawgithub.com/patorjk/Extendible-BBCode-Parser/master/xbbcode.js"></script>
<pre id="out"></pre>
来源:https://stackoverflow.com/questions/28383102/regex-doesnt-stop-matching