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) {
url = url.substring(0, url.length - trailingPunc[0]!.length);
href = href.substring(0, href.length - trailingPunc[0]!.length);
matchLength -= trailingPunc[0]!.length;
}
// 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
url = url.substring(0, url.length - entityRef[0]!.length);
href = href.substring(0, href.length - entityRef[0]!.length);
matchLength -= entityRef[0]!.length;
}
}
// The scheme http will be inserted automatically
if (!href.startsWith('http://') && !href.startsWith('https://') && !href.startsWith('ftp://')) {
href = 'http://$href';
}
final anchor = Element.text('a', escapeHtml(url));
anchor.attributes['href'] = Uri.encodeFull(href);
parser
..addNode(anchor)
..consume(matchLength);
return false;
}