function parse()
{
if (text.indexOf('](') !== -1)
{
parseInlineLinks();
}
if (text.indexOf('<') !== -1)
{
parseAutomaticLinks();
}
if (hasReferences)
{
parseReferenceLinks();
}
}
/**
* Add an image tag for given text span
*
* @param {number} startPos Start tag position
* @param {number} endPos End tag position
* @param {number} endLen End tag length
* @param {string} linkInfo URL optionally followed by space and a title
*/
function addLinkTag(startPos, endPos, endLen, linkInfo)
{
// Give the link a slightly worse priority if this is a implicit reference and a slightly
// better priority if it's an explicit reference or an inline link or to give it precedence
// over possible BBCodes such as [b](https://en.wikipedia.org/wiki/B)
var priority = (endLen === 1) ? 1 : -1;
var tag = addTagPair('URL', startPos, 1, endPos, endLen, priority);
setLinkAttributes(tag, linkInfo, 'url');
// Overwrite the markup without touching the link's text
overwrite(startPos, 1);
overwrite(endPos, endLen);
}
/**
* Capture and return labels used in current text
*
* @return {!Object} Labels' text position as keys, lowercased text content as values
*/
function getLabels()
{
var labels = {}, m, regexp = /\[((?:[^\x17[\]]|\[[^\x17[\]]*\])*)\]/g;
while (m = regexp.exec(text))
{
labels[m.index] = m[1].toLowerCase();
}
return labels;
}
/**
* Parse automatic links markup
*/
function parseAutomaticLinks()
{
var m, regexp = /<[-+.\w]+([:@])[^\x17\s>]+?(?:>|\x1B7)/g;
while (m = regexp.exec(text))
{
// Re-escape escape sequences in automatic links
var content = decode(m[0].replace(/\x1B/g, "\\\x1B")).replace(/^<(.+)>$/, '$1'),
startPos = m.index,
endPos = startPos + m[0].length - 1,
tagName = (m[1] === ':') ? 'URL' : 'EMAIL',
attrName = tagName.toLowerCase();
addTagPair(tagName, startPos, 1, endPos, 1).setAttribute(attrName, content);
}
}
/**
* Parse inline links markup
*/
function parseInlineLinks()
{
var m, regexp = /\[(?:[^\x17[\]]|\[[^\x17[\]]*\])*\]\(( *(?:\([^\x17\s()]*\)|[^\x17\s)])*(?=[ )]) *(?:"[^\x17]*?"|'[^\x17]*?'|\([^\x17)]*\))? *)\)/g;
while (m = regexp.exec(text))
{
var linkInfo = m[1],
startPos = m.index,
endLen = 3 + linkInfo.length,
endPos = startPos + m[0].length - endLen;
addLinkTag(startPos, endPos, endLen, linkInfo);
}
}
/**
* Parse reference links markup
*/
function parseReferenceLinks()
{
var labels = getLabels(), startPos;
for (startPos in labels)
{
var id = labels[startPos],
labelPos = +startPos + 2 + id.length,
endPos = labelPos - 1,
endLen = 1;
if (text[labelPos] === ' ')
{
++labelPos;
}
if (labels[labelPos] > '' && linkReferences[labels[labelPos]])
{
id = labels[labelPos];
endLen = labelPos + 2 + id.length - endPos;
}
if (linkReferences[id])
{
addLinkTag(+startPos, endPos, endLen, linkReferences[id]);
}
}
}