Inheritance: StringScanner
Exemple #1
0
        internal string MakeUniqueHeaderID(string strHeaderText, int startOffset, int length)
        {
            if (!AutoHeadingIDs)
            {
                return(null);
            }

            // Extract a pandoc style cleaned header id from the header text
            var strBase = SpanFormatter.MakeID(strHeaderText, startOffset, length);

            // If nothing left, use "section"
            if (string.IsNullOrEmpty(strBase))
            {
                strBase = "section";
            }

            // Make sure it's unique by append -n counter
            var strWithSuffix = strBase;
            var counter       = 1;

            while (_mUsedHeaderIDs.ContainsKey(strWithSuffix))
            {
                strWithSuffix = strBase + "-" + counter;
                counter++;
            }

            // Store it
            _mUsedHeaderIDs.Add(strWithSuffix, true);

            // Return it
            return(strWithSuffix);
        }
Exemple #2
0
        public void RenderLink(Markdown m, StringBuilder sb)
        {
            var sf = new SpanFormatter(m);

            sf.DisableLinks = true;
            this.Definition.RenderLink(m, sb, sf.Format(this.LinkText), this.SpecialAttributes);
        }
 // Constructor
 public Markdown()
 {
     HtmlClassFootnotes = "footnotes";
     m_StringBuilder    = new StringBuilder();
     m_StringScanner    = new StringScanner();
     m_SpanFormatter    = new SpanFormatter(this);
     m_LinkDefinitions  = new Dictionary <string, LinkDefinition>(StringComparer.CurrentCultureIgnoreCase);
     m_Footnotes        = new Dictionary <string, Block>();
     m_UsedFootnotes    = new List <Block>();
     m_UsedHeaderIDs    = new Dictionary <string, bool>();
 }
Exemple #4
0
		// Constructor
		public Markdown()
		{
			HtmlClassFootnotes = "footnotes";
			m_StringBuilder = new StringBuilder();
			m_StringScanner = new StringScanner();
			m_SpanFormatter = new SpanFormatter(this);
			m_LinkDefinitions = new Dictionary<string, LinkDefinition>(StringComparer.CurrentCultureIgnoreCase);
			m_Footnotes = new Dictionary<string, Block>();
			m_UsedFootnotes = new List<Block>();
			m_UsedHeaderIDs = new Dictionary<string, bool>();
		}
Exemple #5
0
 // Constructor
 public Markdown()
 {
     HtmlClassFootnotes = "footnotes";
     m_StringBuilder = new StringBuilder();
     m_StringBuilderFinal = new StringBuilder();
     m_StringScanner = new StringScanner();
     m_SpanFormatter = new SpanFormatter(this);
     m_LinkDefinitions = new Dictionary<string, LinkDefinition>(StringComparer.CurrentCultureIgnoreCase);
     m_Footnotes = new Dictionary<string, Block>();
     m_UsedFootnotes = new List<Block>();
     m_UsedHeaderIDs = new Dictionary<string, bool>();
     this.CreatedH2IdCollector = new List<Tuple<string, string>>();
     _tabIdCounter = 0;
 }
Exemple #6
0
 // Constructor
 public Markdown()
 {
     HtmlClassFootnotes        = "footnotes";
     m_StringBuilder           = new StringBuilder();
     m_StringBuilderFinal      = new StringBuilder();
     m_StringScanner           = new StringScanner();
     m_SpanFormatter           = new SpanFormatter(this);
     m_LinkDefinitions         = new Dictionary <string, LinkDefinition>(StringComparer.CurrentCultureIgnoreCase);
     m_Footnotes               = new Dictionary <string, Block>();
     m_UsedFootnotes           = new List <Block>();
     m_UsedHeaderIDs           = new Dictionary <string, bool>();
     this.CreatedH2IdCollector = new List <Tuple <string, string> >();
     _tabIdCounter             = 0;
 }
 // Constructor
 public Markdown()
 {
     HtmlClassFootnotes   = "footnotes";
     m_StringBuilder      = new StringBuilder();
     m_StringBuilderFinal = new StringBuilder();
     m_StringScanner      = new StringScanner();
     m_SpanFormatter      = new SpanFormatter(this);
     m_LinkDefinitions    = new Dictionary <string, LinkDefinition>(StringComparer.CurrentCultureIgnoreCase);
     m_Footnotes          = new Dictionary <string, Block>();
     m_UsedFootnotes      = new List <Block>();
     m_UsedHeaderIDs      = new Dictionary <string, bool>();
     m_FoundLinks         = new List <ILinkInfo>();
     EncodeUnsafeHtml     = true;
     ActiveRenderer       = new Formats.RenderToHtml();
 }
 public void SetUp()
 {
     m = new Markdown();
     s = new SpanFormatter(m);
 }
        // 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)
            {
                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);

            // @kamranayub: Nested images
            SpanFormatter nestedFormatter = new SpanFormatter(this.m_Markdown);

            if (link_text.Length > 2 &&
                link_text.IndexOf('!') == 0 &&
                link_text.IndexOf('[') == 1)
            {
                link_text = nestedFormatter.Format(link_text);
            }

            // 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);
                }

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

            // 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
            return(CreateToken(token_type, new LinkInfo(def, link_text)));
        }
Exemple #10
0
 public void RenderLink(Markdown m, StringBuilder sb)
 {
     var sf = new SpanFormatter(m);
     sf.DisableLinks = true;
     this.Definition.RenderLink(m, sb, sf.Format(this.LinkText), this.SpecialAttributes);
 }
 public void SetUp()
 {
     f = new SpanFormatter(new Markdown());
 }
        // Render a list of tokens to a destinatino string builder.
        private void Render(StringBuilder sb, string str)
        {
            foreach (Token t in m_Tokens)
            {
                switch (t.type)
                {
                    case TokenType.Text:
                        // Append encoded text
                        m_Markdown.HtmlEncode(sb, str, t.startOffset, t.length);
                        break;

                    case TokenType.HtmlTag:
                        // Append html as is
                        Utils.SmartHtmlEncodeAmps(sb, str, t.startOffset, t.length);
                        break;

                    case TokenType.Html:
                    case TokenType.opening_mark:
                    case TokenType.closing_mark:
                    case TokenType.internal_mark:
                        // Append html as is
                        sb.Append(str, t.startOffset, t.length);
                        break;

                    case TokenType.br:
                        sb.Append("<br />\n");
                        break;

                    case TokenType.open_em:
                        sb.Append("<em>");
                        break;

                    case TokenType.close_em:
                        sb.Append("</em>");
                        break;

                    case TokenType.open_strong:
                        sb.Append("<strong>");
                        break;

                    case TokenType.close_strong:
                        sb.Append("</strong>");
                        break;

                    case TokenType.code_span:
                        sb.Append("<code>");
                        m_Markdown.HtmlEncode(sb, str, t.startOffset, t.length);
                        sb.Append("</code>");
                        break;

                    case TokenType.link:
                    {
                        LinkInfo li = (LinkInfo)t.data;
                        var sf = new SpanFormatter(m_Markdown);
                        sf.DisableLinks = true;

                        li.def.RenderLink(m_Markdown, sb, sf.Format(li.link_text));
                        break;
                    }

                    case TokenType.img:
                    {
                        LinkInfo li = (LinkInfo)t.data;
                        li.def.RenderImg(m_Markdown, sb, li.link_text);
                        break;
                    }

                    case TokenType.footnote:
                    {
                        FootnoteReference r=(FootnoteReference)t.data;
                        sb.Append("<sup id=\"fnref:");
                        sb.Append(r.id);
                        sb.Append("\"><a href=\"#fn:");
                        sb.Append(r.id);
                        sb.Append("\" rel=\"footnote\">");
                        sb.Append(r.index + 1);
                        sb.Append("</a></sup>");
                        break;
                    }

                    case TokenType.abbreviation:
                    {
                        Abbreviation a = (Abbreviation)t.data;
                        sb.Append("<abbr");
                        if (!String.IsNullOrEmpty(a.Title))
                        {
                            sb.Append(" title=\"");
                            m_Markdown.HtmlEncode(sb, a.Title, 0, a.Title.Length);
                            sb.Append("\"");
                        }
                        sb.Append(">");
                        m_Markdown.HtmlEncode(sb, a.Abbr, 0, a.Abbr.Length);
                        sb.Append("</abbr>");
                        break;
                    }
                }

                FreeToken(t);
            }
        }
Exemple #13
0
 public void combined_18()
 {
     var fExtra = new SpanFormatter(new Markdown() { ExtraMode = true });
     Assert.AreEqual("<em>Emphasis</em>, trailing",
             fExtra.Format("_Emphasis_, trailing"));
 }
Exemple #14
0
 public void combined_17()
 {
     var fExtra = new SpanFormatter(new Markdown() { ExtraMode = true });
     Assert.AreEqual("<strong>Bold</strong> <em>Italic</em>",
             fExtra.Format("__Bold__ _Italic_"));
 }
        // 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)
                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);

            // @kamranayub: Nested images
            SpanFormatter nestedFormatter = new SpanFormatter(this.m_Markdown);

            if (link_text.Length > 2 &&
                link_text.IndexOf('!') == 0 &&
                link_text.IndexOf('[') == 1) {
                link_text = nestedFormatter.Format(link_text);
            }

            // 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;

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

            // 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
            return CreateToken(token_type, new LinkInfo(def, link_text));
        }
Exemple #16
0
        // Render a list of tokens to a destinatino string builder.
        private void Render(StringBuilder sb, string str)
        {
            foreach (Token t in m_Tokens)
            {
                switch (t.type)
                {
                case TokenType.Text:
                    // Append encoded text
                    m_Markdown.HtmlEncode(sb, str, t.startOffset, t.length);
                    break;

                case TokenType.HtmlTag:
                    // Append html as is
                    Utils.SmartHtmlEncodeAmps(sb, str, t.startOffset, t.length);
                    break;

                case TokenType.Html:
                case TokenType.opening_mark:
                case TokenType.closing_mark:
                case TokenType.internal_mark:
                    // Append html as is
                    sb.Append(str, t.startOffset, t.length);
                    break;

                case TokenType.br:
                    sb.Append("<br />\n");
                    break;

                case TokenType.open_em:
                    sb.Append("<em>");
                    break;

                case TokenType.close_em:
                    sb.Append("</em>");
                    break;

                case TokenType.open_strong:
                    sb.Append("<strong>");
                    break;

                case TokenType.close_strong:
                    sb.Append("</strong>");
                    break;

                case TokenType.code_span:
                    sb.Append("<code>");
                    m_Markdown.HtmlEncode(sb, str, t.startOffset, t.length);
                    sb.Append("</code>");
                    break;

                case TokenType.link:
                {
                    LinkInfo li = (LinkInfo)t.data;
                    var      sf = new SpanFormatter(m_Markdown);
                    sf.DisableLinks = true;

                    li.def.RenderLink(m_Markdown, sb, sf.Format(li.link_text));
                    break;
                }

                case TokenType.img:
                {
                    LinkInfo li = (LinkInfo)t.data;
                    li.def.RenderImg(m_Markdown, sb, li.link_text);
                    break;
                }

                case TokenType.footnote:
                {
                    FootnoteReference r = (FootnoteReference)t.data;
                    sb.Append("<sup id=\"fnref:");
                    sb.Append(r.id);
                    sb.Append("\"><a href=\"#fn:");
                    sb.Append(r.id);
                    sb.Append("\" rel=\"footnote\">");
                    sb.Append(r.index + 1);
                    sb.Append("</a></sup>");
                    break;
                }

                case TokenType.abbreviation:
                {
                    Abbreviation a = (Abbreviation)t.data;
                    sb.Append("<abbr");
                    if (!String.IsNullOrEmpty(a.Title))
                    {
                        sb.Append(" title=\"");
                        m_Markdown.HtmlEncode(sb, a.Title, 0, a.Title.Length);
                        sb.Append("\"");
                    }
                    sb.Append(">");
                    m_Markdown.HtmlEncode(sb, a.Abbr, 0, a.Abbr.Length);
                    sb.Append("</abbr>");
                    break;
                }
                }

                FreeToken(t);
            }
        }
Exemple #17
0
        // Render a list of tokens to a destinatino string builder.
        private void Render(StringBuilder sb, string str)
        {
            var reg  = new Regex("<([^ >]+)");
            var tags = new Stack <String>();

            foreach (Token t in m_Tokens)
            {
                switch (t.type)
                {
                case TokenType.Text:
                    // Append encoded text
                    m_Markdown.HtmlEncode(sb, str, t.startOffset, t.length);
                    break;

                case TokenType.HtmlTag:
                    // Append html as is
                    var tag    = str.Substring(t.startOffset, t.length);
                    var mtag   = reg.Match(tag).Groups[1].Value;
                    var mtag_l = mtag.ToLower();
                    if (mtag.StartsWith("/"))
                    {
                        while (tags.Count() > 0)
                        {
                            var ptag = tags.Pop();
                            if (ptag.ToLower() == mtag_l)
                            {
                                Utils.SmartHtmlEncodeAmps(sb, str, t.startOffset, t.length);
                                break;
                            }
                            else
                            {
                                sb.Append("<" + ptag + ">");
                            }
                        }
                    }
                    else
                    {
                        tags.Push("/" + mtag);
                        Utils.SmartHtmlEncodeAmps(sb, str, t.startOffset, t.length);
                    }
                    break;

                case TokenType.Html:
                case TokenType.opening_mark:
                case TokenType.closing_mark:
                case TokenType.internal_mark:
                    // Append html as is
                    sb.Append(str, t.startOffset, t.length);
                    break;

                case TokenType.br:
                    sb.Append("<br />\n");
                    break;

                case TokenType.open_em:
                    sb.Append("<em>");
                    break;

                case TokenType.close_em:
                    sb.Append("</em>");
                    break;

                case TokenType.open_strong:
                    sb.Append("<strong>");
                    break;

                case TokenType.close_strong:
                    sb.Append("</strong>");
                    break;

                case TokenType.code_span:
                    sb.Append("<code>");
                    m_Markdown.HtmlEncode(sb, str, t.startOffset, t.length);
                    sb.Append("</code>");
                    break;

                case TokenType.link:
                {
                    LinkInfo li = (LinkInfo)t.data;
                    var      sf = new SpanFormatter(m_Markdown);
                    sf.DisableLinks = true;

                    li.def.RenderLink(m_Markdown, sb, sf.Format(li.link_text));
                    break;
                }

                case TokenType.img:
                {
                    LinkInfo li = (LinkInfo)t.data;
                    li.def.RenderImg(m_Markdown, sb, li.link_text);
                    break;
                }

                case TokenType.footnote:
                {
                    FootnoteReference r = (FootnoteReference)t.data;
                    sb.Append("<sup id=\"fnref:");
                    sb.Append(r.id);
                    sb.Append("\"><a href=\"#fn:");
                    sb.Append(r.id);
                    sb.Append("\" rel=\"footnote\">");
                    sb.Append(r.index + 1);
                    sb.Append("</a></sup>");
                    break;
                }

                case TokenType.abbreviation:
                {
                    Abbreviation a = (Abbreviation)t.data;
                    sb.Append("<abbr");
                    if (!String.IsNullOrEmpty(a.Title))
                    {
                        sb.Append(" title=\"");
                        m_Markdown.HtmlEncode(sb, a.Title, 0, a.Title.Length);
                        sb.Append("\"");
                    }
                    sb.Append(">");
                    m_Markdown.HtmlEncode(sb, a.Abbr, 0, a.Abbr.Length);
                    sb.Append("</abbr>");
                    break;
                }
                }

                FreeToken(t);
            }

            while (tags.Count() > 0)
            {
                sb.Append("<" + tags.Pop() + ">");
            }
        }
Exemple #18
0
 public void InlineLinkWithoutTitleWithSpecialAttributes()
 {
     var m = GetSetupMarkdown();
     m.ExtraMode = true;
     var s = new SpanFormatter(m);
     Assert.AreEqual("pre <a href=\"url.com\" id=\"foo\" class=\"a b cl\" lang=\"nl\">link text</a> post",
     s.Format("pre [link text](url.com){#foo .a .b .cl lang=nl} post"));
 }
Exemple #19
0
 public void SetUp()
 {
     _formatter = new SpanFormatter(GetSetupMarkdown());
 }
Exemple #20
0
 public void InlineImgWithoutTitleWithSpecialAttributes()
 {
     var m = GetSetupMarkdown();
     m.ExtraMode = true;
     var s = new SpanFormatter(m);
     Assert.AreEqual("pre <img src=\"url.com/image.png\" alt=\"alt text\" id=\"foo\" class=\"a b cl\" lang=\"nl\" /> post",
             s.Format("pre ![alt text](url.com/image.png){#foo .a .b .cl lang=nl} post"));
 }
        public void SetUp()
        {
            m = new Markdown();
            m.AddLinkDefinition(new LinkDefinition("link1", "url.com", "title"));
            m.AddLinkDefinition(new LinkDefinition("link2", "url.com"));
            m.AddLinkDefinition(new LinkDefinition("img1", "url.com/image.png", "title"));
            m.AddLinkDefinition(new LinkDefinition("img2", "url.com/image.png"));

            s = new SpanFormatter(m);
        }
Exemple #22
0
        // Render a list of tokens to a destination string builder.
        private void Render(StringBuilder sb, string str)
        {
            foreach (var t in _mTokens)
            {
                switch (t.Type)
                {
                case TokenType.Text:
                    // Append encoded text
                    _mMarkdown.HtmlEncode(sb, str, t.StartOffset, t.Length);
                    break;

                case TokenType.HtmlTag:
                    // Append html as is
                    Utils.SmartHtmlEncodeAmps(sb, str, t.StartOffset, t.Length);
                    break;

                case TokenType.Html:
                case TokenType.opening_mark:
                case TokenType.closing_mark:
                case TokenType.internal_mark:
                    // Append html as is
                    sb.Append(str, t.StartOffset, t.Length);
                    break;

                case TokenType.br:
                    sb.Append("<br />\n");
                    break;

                case TokenType.open_em:
                    sb.Append("<em>");
                    break;

                case TokenType.close_em:
                    sb.Append("</em>");
                    break;

                case TokenType.open_strong:
                    sb.Append("<strong>");
                    break;

                case TokenType.close_strong:
                    sb.Append("</strong>");
                    break;

                case TokenType.code_span:
                    sb.Append("<code>");
                    _mMarkdown.HtmlEncode(sb, str, t.StartOffset, t.Length);
                    sb.Append("</code>");
                    break;

                case TokenType.link:
                {
                    var li = (LinkInfo)t.Data;
                    var sf = new SpanFormatter(_mMarkdown)
                    {
                        DisableLinks = true
                    };

                    li.Def.RenderLink(_mMarkdown, sb, sf.Format(li.LinkText));
                    break;
                }

                case TokenType.img:
                {
                    var li = (LinkInfo)t.Data;
                    li.Def.RenderImg(_mMarkdown, sb, li.LinkText);
                    break;
                }

                case TokenType.footnote:
                {
                    var r = (FootnoteReference)t.Data;
                    // ReSharper disable once StringLiteralTypo
                    sb.Append("<sup id=\"fnref:");
                    sb.Append(r.ID);
                    sb.Append("\"><a href=\"#fn:");
                    sb.Append(r.ID);
                    sb.Append("\" rel=\"footnote\">");
                    sb.Append(r.Index + 1);
                    sb.Append("</a></sup>");
                    break;
                }

                case TokenType.abbreviation:
                {
                    var a = (Abbreviation)t.Data;
                    sb.Append("<abbr");
                    if (!string.IsNullOrEmpty(a.Title))
                    {
                        sb.Append(" title=\"");
                        _mMarkdown.HtmlEncode(sb, a.Title, 0, a.Title.Length);
                        sb.Append("\"");
                    }
                    sb.Append(">");
                    _mMarkdown.HtmlEncode(sb, a.Abbr, 0, a.Abbr.Length);
                    sb.Append("</abbr>");
                    break;
                }
                }

                FreeToken(t);
            }
        }