onMatch method
Processes match
, adding nodes to parser
and possibly advancing
parser
.
Returns whether the caller should advance parser
by match[0].length
.
Implementation
@override
bool onMatch(InlineParser parser, Match match) {
var url = match[1]!;
var href = url;
var matchLength = url.length;
if (url[0] == '>' || url.startsWith(regExpWhiteSpace)) {
url = url.substring(1, url.length - 1);
href = href.substring(1, href.length - 1);
parser.pos++;
matchLength--;
}
// Prevent accidental standard autolink matches
if (url.endsWith('>') && parser.source![parser.pos - 1] == '<') {
return false;
}
// When an autolink ends in ), we scan the entire autolink for the total
// number of parentheses. If there is a greater number of closing
// parentheses than opening ones, we don’t consider the last character
// part of the autolink, in order to facilitate including an autolink
// inside a parenthesis:
// https://github.github.com/gfm/#example-600
if (url.endsWith(')')) {
final opening = _countChars(url, '(');
final closing = _countChars(url, ')');
if (closing > opening) {
url = url.substring(0, url.length - 1);
href = href.substring(0, href.length - 1);
matchLength--;
}
}
// Trailing punctuation (specifically, ?, !, ., ,, :, *, _, and ~) will
// not be considered part of the autolink, though they may be included
// in the interior of the link:
// https://github.github.com/gfm/#example-599
final trailingPunc = regExpTrailingPunc.firstMatch(url);
if (trailingPunc != null) {
var trailingLength = trailingPunc.match.length;
url = url.substring(0, url.length - trailingLength);
href = href.substring(0, href.length - trailingLength);
matchLength -= trailingLength;
}
// If an autolink ends in a semicolon (;), we check to see if it appears
// to resemble an
// [entity reference](https://github.github.com/gfm/#entity-references);
// if the preceding text is & followed by one or more alphanumeric
// characters. If so, it is excluded from the autolink:
// https://github.github.com/gfm/#example-602
if (url.endsWith(';')) {
final entityRef = regExpEndsWithColon.firstMatch(url);
if (entityRef != null) {
// Strip out HTML entity reference
var entityRefLength = entityRef.match.length;
url = url.substring(0, url.length - entityRefLength);
href = href.substring(0, href.length - entityRefLength);
matchLength -= entityRefLength;
}
}
// The scheme http will be inserted automatically
if (!href.startsWith('http://') &&
!href.startsWith('https://') &&
!href.startsWith('ftp://')) {
href = 'http://$href';
}
final text = parser._encodeHtml ? escapeHtml(url) : url;
final anchor = Element.text('a', text);
anchor.attributes['href'] = Uri.encodeFull(href);
parser.addNode(anchor);
parser.consume(matchLength);
return false;
}