public override bool Match(InlineProcessor processor, ref StringSlice slice) { bool matchFound = slice.MatchLowercase(matchingText); if (matchFound) { int inlineStart = processor.GetSourcePosition(slice.Start, out int line, out int column); processor.Inline = new MatchingTextInline { Span = { Start = inlineStart, End = inlineStart + matchingText.Length }, Line = line, Column = column, MatchingText = matchingText }; slice.Start = inlineStart + matchingText.Length; } return(matchFound); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { // Previous char must be a whitespace or a punctuation var previousChar = slice.PeekCharExtra(-1); if (!previousChar.IsAsciiPunctuation() && !previousChar.IsWhiteSpaceOrZero()) { return(false); } List <char> pendingEmphasis; // Check that an autolink is possible in the current context if (!IsAutoLinkValidInCurrentContext(processor, out pendingEmphasis)) { return(false); } var startPosition = slice.Start; var c = slice.CurrentChar; // Precheck URL switch (c) { case 'h': if (!slice.MatchLowercase("ttp://", 1) && !slice.MatchLowercase("ttps://", 1)) { return(false); } break; case 'f': if (!slice.MatchLowercase("tp://", 1)) { return(false); } break; case 'm': if (!slice.MatchLowercase("ailto:", 1)) { return(false); } break; case 'w': if (!slice.MatchLowercase("ww.", 1) || previousChar == '/') // We won't match http:/www. or /www.xxx { return(false); } break; } // Parse URL string link; if (!LinkHelper.TryParseUrl(ref slice, out link)) { return(false); } // If we have any pending emphasis, remove any pending emphasis characters from the end of the link if (pendingEmphasis != null) { for (int i = link.Length - 1; i >= 0; i--) { if (pendingEmphasis.Contains(link[i])) { slice.Start--; } else { if (i < link.Length - 1) { link = link.Substring(0, i + 1); } break; } } } // Post-check URL switch (c) { case 'h': if (string.Equals(link, "http://", StringComparison.OrdinalIgnoreCase) || string.Equals(link, "https://", StringComparison.OrdinalIgnoreCase)) { return(false); } break; case 'f': if (string.Equals(link, "ftp://", StringComparison.OrdinalIgnoreCase)) { return(false); } break; case 'm': if (string.Equals(link, "mailto:", StringComparison.OrdinalIgnoreCase) || !link.Contains("@")) { return(false); } break; case 'w': // We require at least two . if (link.Length <= "www.x.y".Length || link.IndexOf(".", 4, StringComparison.Ordinal) < 0) { return(false); } break; } int line; int column; var inline = new LinkInline() { Span = { Start = processor.GetSourcePosition(startPosition, out line, out column), }, Line = line, Column = column, Url = c == 'w' ? "http://" + link : link, IsClosed = true, }; inline.Span.End = inline.Span.Start + link.Length - 1; inline.UrlSpan = inline.Span; inline.AppendChild(new LiteralInline() { Span = inline.Span, Line = line, Column = column, Content = new StringSlice(slice.Text, startPosition, startPosition + link.Length - 1), IsClosed = true }); processor.Inline = inline; return(true); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { // Previous char must be a whitespace or a punctuation var previousChar = slice.PeekCharExtra(-1); if (!previousChar.IsWhiteSpaceOrZero() && Options.ValidPreviousCharacters.IndexOf(previousChar) == -1) { return(false); } List <char> pendingEmphasis = _listOfCharCache.Get(); try { // Check that an autolink is possible in the current context if (!IsAutoLinkValidInCurrentContext(processor, pendingEmphasis)) { return(false); } var startPosition = slice.Start; int domainOffset = 0; var c = slice.CurrentChar; // Precheck URL switch (c) { case 'h': if (slice.MatchLowercase("ttp://", 1)) { domainOffset = 7; // http:// } else if (slice.MatchLowercase("ttps://", 1)) { domainOffset = 8; // https:// } else { return(false); } break; case 'f': if (!slice.MatchLowercase("tp://", 1)) { return(false); } domainOffset = 6; // ftp:// break; case 'm': if (!slice.MatchLowercase("ailto:", 1)) { return(false); } break; case 't': if (!slice.MatchLowercase("el:", 1)) { return(false); } domainOffset = 4; break; case 'w': if (!slice.MatchLowercase("ww.", 1)) // We won't match http:/www. or /www.xxx { return(false); } domainOffset = 4; // www. break; } // Parse URL if (!LinkHelper.TryParseUrl(ref slice, out string?link, out _, true)) { return(false); } // If we have any pending emphasis, remove any pending emphasis characters from the end of the link if (pendingEmphasis.Count > 0) { for (int i = link.Length - 1; i >= 0; i--) { if (pendingEmphasis.Contains(link[i])) { slice.Start--; } else { if (i < link.Length - 1) { link = link.Substring(0, i + 1); } break; } } } // Post-check URL switch (c) { case 'h': if (string.Equals(link, "http://", StringComparison.OrdinalIgnoreCase) || string.Equals(link, "https://", StringComparison.OrdinalIgnoreCase)) { return(false); } break; case 'f': if (string.Equals(link, "ftp://", StringComparison.OrdinalIgnoreCase)) { return(false); } break; case 't': if (string.Equals(link, "tel", StringComparison.OrdinalIgnoreCase)) { return(false); } break; case 'm': int atIndex = link.IndexOf('@'); if (atIndex == -1 || atIndex == 7) // mailto:@ - no email part { return(false); } domainOffset = atIndex + 1; break; } // Do not need to check if a telephone number is a valid domain if (c != 't' && !LinkHelper.IsValidDomain(link, domainOffset)) { return(false); } var inline = new LinkInline() { Span = { Start = processor.GetSourcePosition(startPosition, out int line, out int column), }, Line = line, Column = column, Url = c == 'w' ? ((Options.UseHttpsForWWWLinks ? "https://" : "http://") + link) : link, IsClosed = true, IsAutoLink = true, };
public override bool Match(InlineProcessor processor, ref StringSlice slice) { // Previous char must be a whitespace or a punctuation var previousChar = slice.PeekCharExtra(-1); if (!previousChar.IsWhiteSpaceOrZero() && ValidPreviousCharacters.IndexOf(previousChar) == -1) { return(false); } List <char> pendingEmphasis; // Check that an autolink is possible in the current context if (!IsAutoLinkValidInCurrentContext(processor, out pendingEmphasis)) { return(false); } var startPosition = slice.Start; int domainOffset = 0; var c = slice.CurrentChar; // Precheck URL switch (c) { case 'h': if (slice.MatchLowercase("ttp://", 1)) { domainOffset = 7; // http:// } else if (slice.MatchLowercase("ttps://", 1)) { domainOffset = 8; // https:// } else { return(false); } break; case 'f': if (!slice.MatchLowercase("tp://", 1)) { return(false); } domainOffset = 6; // ftp:// break; case 'm': if (!slice.MatchLowercase("ailto:", 1)) { return(false); } break; case 'w': if (!slice.MatchLowercase("ww.", 1)) // We won't match http:/www. or /www.xxx { return(false); } domainOffset = 4; // www. break; } // Parse URL string link; if (!LinkHelper.TryParseUrl(ref slice, out link, true)) { return(false); } // If we have any pending emphasis, remove any pending emphasis characters from the end of the link if (pendingEmphasis != null) { for (int i = link.Length - 1; i >= 0; i--) { if (pendingEmphasis.Contains(link[i])) { slice.Start--; } else { if (i < link.Length - 1) { link = link.Substring(0, i + 1); } break; } } } // Post-check URL switch (c) { case 'h': if (string.Equals(link, "http://", StringComparison.OrdinalIgnoreCase) || string.Equals(link, "https://", StringComparison.OrdinalIgnoreCase)) { return(false); } break; case 'f': if (string.Equals(link, "ftp://", StringComparison.OrdinalIgnoreCase)) { return(false); } break; case 'm': int atIndex = link.IndexOf('@'); if (atIndex == -1 || atIndex == 7) // mailto:@ - no email part { return(false); } domainOffset = atIndex + 1; break; } if (!LinkHelper.IsValidDomain(link, domainOffset)) { return(false); } int line; int column; var inline = new LinkInline() { Span = { Start = processor.GetSourcePosition(startPosition, out line, out column), }, Line = line, Column = column, Url = c == 'w' ? "http://" + link : link, IsClosed = true, IsAutoLink = true, }; var skipFromBeginning = c == 'm' ? 7 : 0; // For mailto: skip "mailto:" for content inline.Span.End = inline.Span.Start + link.Length - 1; inline.UrlSpan = inline.Span; inline.AppendChild(new LiteralInline() { Span = inline.Span, Line = line, Column = column, Content = new StringSlice(slice.Text, startPosition + skipFromBeginning, startPosition + link.Length - 1), IsClosed = true }); processor.Inline = inline; return(true); }
public override bool Match(InlineProcessor processor, ref StringSlice slice) { var previousChar = slice.PeekCharExtra(-1); if (!previousChar.IsWhiteSpaceOrZero()) { return(false); } if (!slice.MatchLowercase("std.")) { return(false); } var startPosition = slice.Start; var endOffset = 0; while (slice.Start < slice.End && !Char.IsWhiteSpace(slice.CurrentChar) && slice.CurrentChar != ';') { slice.NextChar(); } if (slice.CurrentChar == ';') { endOffset += 1; } var text = slice.Text.Substring(startPosition, (slice.Start - startPosition) + 1).TrimEnd(' ', '\n', ';', '\t', '\r'); var sections = text.Split('#', ':'); if (sections.Length == 0 || sections.Length > 3) { return(false); } string module = null; string member = null; string displayText = null; switch (sections.Length) { case 1: module = sections[0]; displayText = module; break; case 2: module = sections[0]; if (text.Contains("#")) { member = sections[1]; } else // : { displayText = sections[1]; } break; case 3: module = sections[0]; member = sections[1]; displayText = sections[2]; break; default: break; } var inlineLink = new LinkInline { Span = { Start = processor.GetSourcePosition(startPosition, out int line, out int column), },