コード例 #1
0
        // Process [link] and ![image] directives
        Token ProcessLinkOrImageOrFootnote()
        {
            // Link or image?
            TokenType token_type = SkipChar('!') ? TokenType.img : TokenType.link;

            // Opening '['
            if (!SkipChar('['))
            {
                return(null);
            }

            // Is it a foonote?
            var savepos = Position;

            if (m_Markdown.ExtraMode && token_type == TokenType.link && SkipChar('^'))
            {
                SkipLinespace();

                // Parse it
                string id;
                if (SkipFootnoteID(out id) && SkipChar(']'))
                {
                    // Look it up and create footnote reference token
                    int footnote_index = m_Markdown.ClaimFootnote(id);
                    if (footnote_index >= 0)
                    {
                        // Yes it's a footnote
                        return(CreateToken(TokenType.footnote, new FootnoteReference(footnote_index, id)));
                    }
                }

                // Rewind
                Position = savepos;
            }

            if (DisableLinks && token_type == TokenType.link)
            {
                return(null);
            }

            bool extraMode = m_Markdown.ExtraMode;

            // Find the closing square bracket, allowing for nesting, watching for
            // escapable characters
            Mark();
            int depth = 1;

            while (!Eof)
            {
                char ch = Current;
                if (ch == '[')
                {
                    depth++;
                }
                else if (ch == ']')
                {
                    depth--;
                    if (depth == 0)
                    {
                        break;
                    }
                }

                this.SkipEscapableChar(extraMode);
            }

            // Quit if end
            if (Eof)
            {
                return(null);
            }

            // Get the link text and unescape it
            string link_text = Utils.UnescapeString(Extract(), extraMode);

            // The closing ']'
            SkipForward(1);

            // Save position in case we need to rewind
            savepos = Position;

            // Inline links must follow immediately
            if (SkipChar('('))
            {
                // Extract the url and title
                var link_def = LinkDefinition.ParseLinkTarget(this, null, m_Markdown.ExtraMode);
                if (link_def == null)
                {
                    return(null);
                }

                // Closing ')'
                SkipWhitespace();
                if (!SkipChar(')'))
                {
                    return(null);
                }

                List <string> specialAttributes = null;
                if (extraMode && DoesMatch('{'))
                {
                    int end;
                    specialAttributes = Utils.StripSpecialAttributes(this.Input, this.Position, out end);
                    if (specialAttributes != null)
                    {
                        Position = end;
                    }
                }

                // Create the token
                return(CreateToken(token_type, new LinkInfo(link_def, link_text, specialAttributes)));
            }

            // Optional space or tab
            if (!SkipChar(' '))
            {
                SkipChar('\t');
            }

            // If there's line end, we're allow it and as must line space as we want
            // before the link id.
            if (Eol)
            {
                SkipEol();
                SkipLinespace();
            }

            // Reference link?
            string link_id = null;

            if (Current == '[')
            {
                // Skip the opening '['
                SkipForward(1);

                // Find the start/end of the id
                Mark();
                if (!Find(']'))
                {
                    return(null);
                }

                // Extract the id
                link_id = Extract();

                // Skip closing ']'
                SkipForward(1);
            }
            else
            {
                // Rewind to just after the closing ']'
                Position = savepos;
            }

            // Link id not specified?
            if (string.IsNullOrEmpty(link_id))
            {
                // Use the link text (implicit reference link)
                link_id = Utils.NormalizeLineEnds(link_text);

                // If the link text has carriage returns, normalize
                // to spaces
                if (!object.ReferenceEquals(link_id, link_text))
                {
                    while (link_id.Contains(" \n"))
                    {
                        link_id = link_id.Replace(" \n", "\n");
                    }
                    link_id = link_id.Replace("\n", " ");
                }
            }

            // Find the link definition abort if not defined
            var def = m_Markdown.GetLinkDefinition(link_id);

            if (def == null)
            {
                return(null);
            }

            // Create a token.
            // [FB]: Currently not supported: special attributes on reference links.
            return(CreateToken(token_type, new LinkInfo(def, link_text, null)));
        }