Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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,
                };
Example #4
0
        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);
        }
Example #5
0
        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),
                },