예제 #1
0
        /// <summary>
        /// Writes the specified inline element to the output stream. Does not write the child nodes, instead
        /// the <paramref name="ignoreChildNodes"/> is used to notify the caller whether it should recurse
        /// into the child nodes.
        /// </summary>
        /// <param name="inline">The inline element to be written to the output stream.</param>
        /// <param name="isOpening">Specifies whether the inline element is being opened (or started).</param>
        /// <param name="isClosing">Specifies whether the inline element is being closed. If the inline does not
        /// have child nodes, then both <paramref name="isClosing"/> and <paramref name="isOpening"/> can be
        /// <see langword="true"/> at the same time.</param>
        /// <param name="ignoreChildNodes">Instructs the caller whether to skip processing of child nodes or not.</param>
        protected virtual void WriteInline(Inline inline, bool isOpening, bool isClosing, out bool ignoreChildNodes)
        {
            if (RenderPlainTextInlines.Peek())
            {
                switch (inline.Tag)
                {
                case InlineTag.String:
                case InlineTag.Code:
                case InlineTag.RawHtml:
                    WriteEncodedHtml(inline.LiteralContentValue);
                    break;

                case InlineTag.LineBreak:
                case InlineTag.SoftBreak:
                    WriteLine();
                    break;

                case InlineTag.Image:
                    if (isOpening)
                    {
                        RenderPlainTextInlines.Push(true);
                    }

                    if (isClosing)
                    {
                        RenderPlainTextInlines.Pop();

                        if (!RenderPlainTextInlines.Peek())
                        {
                            goto useFullRendering;
                        }
                    }

                    break;

                case InlineTag.Link:
                case InlineTag.Strong:
                case InlineTag.Emphasis:
                case InlineTag.Strikethrough:
                case InlineTag.Placeholder:
                    break;

                default:
                    throw new CommonMarkException("Inline type " + inline.Tag + " is not supported.", inline);
                }

                ignoreChildNodes = false;
                return;
            }

useFullRendering:

            switch (inline.Tag)
            {
            case InlineTag.String:
                ignoreChildNodes = true;
                if (Settings.TrackSourcePosition)
                {
                    Write("<span");
                    WritePositionAttribute(inline);
                    Write('>');
                    WriteEncodedHtml(inline.LiteralContentValue);
                    Write("</span>");
                }
                else
                {
                    WriteEncodedHtml(inline.LiteralContentValue);
                }

                break;

            case InlineTag.LineBreak:
                ignoreChildNodes = true;
                WriteLine("<br />");
                break;

            case InlineTag.SoftBreak:
                ignoreChildNodes = true;
                if (Settings.RenderSoftLineBreaksAsLineBreaks)
                {
                    WriteLine("<br />");
                }
                else
                {
                    if (Settings.RenderEmptyLines)
                    {
                        _target.WriteEmptyLine();
                    }
                    else
                    {
                        WriteLine();
                    }
                }
                break;

            case InlineTag.Code:
                ignoreChildNodes = true;
                Write("<code");
                if (Settings.TrackSourcePosition)
                {
                    WritePositionAttribute(inline);
                }
                Write('>');
                WriteEncodedHtml(inline.LiteralContentValue);
                Write("</code>");
                break;

            case InlineTag.RawHtml:
                ignoreChildNodes = true;
                if (Settings.HtmlEntityEncode)
                {
                    WriteEncodedHtml(inline.LiteralContentValue);
                }
                else
                {
                    // cannot output source position for HTML blocks
                    Write(inline.LiteralContentValue);
                }
                break;

            case InlineTag.Link:
                ignoreChildNodes = false;

                if (isOpening)
                {
                    Write("<a href=\"");
                    var uriResolver = Settings.UriResolver;
                    if (uriResolver != null)
                    {
                        WriteEncodedUrl(uriResolver(inline.TargetUrl));
                    }
                    else
                    {
                        WriteEncodedUrl(inline.TargetUrl);
                    }

                    Write('\"');
                    if (inline.LiteralContentValue.Length > 0)
                    {
                        Write(" title=\"");
                        WriteEncodedHtml(inline.LiteralContentValue);
                        Write('\"');
                    }

                    if (Settings.TrackSourcePosition)
                    {
                        WritePositionAttribute(inline);
                    }

                    Write('>');
                }

                if (isClosing)
                {
                    Write("</a>");
                }

                break;

            case InlineTag.Image:
                ignoreChildNodes = false;

                if (isOpening)
                {
                    Write("<img src=\"");
                    var uriResolver = Settings.UriResolver;
                    if (uriResolver != null)
                    {
                        WriteEncodedUrl(uriResolver(inline.TargetUrl));
                    }
                    else
                    {
                        WriteEncodedUrl(inline.TargetUrl);
                    }

                    Write("\" alt=\"");

                    if (!isClosing)
                    {
                        RenderPlainTextInlines.Push(true);
                    }
                }

                if (isClosing)
                {
                    // this.RenderPlainTextInlines.Pop() is done by the plain text renderer above.

                    Write('\"');
                    if (inline.LiteralContentValue.Length > 0)
                    {
                        Write(" title=\"");
                        WriteEncodedHtml(inline.LiteralContentValue);
                        Write('\"');
                    }

                    if (Settings.TrackSourcePosition)
                    {
                        WritePositionAttribute(inline);
                    }
                    Write(" />");
                }

                break;

            case InlineTag.Strong:
                ignoreChildNodes = false;

                if (isOpening)
                {
                    Write("<strong");
                    if (Settings.TrackSourcePosition)
                    {
                        WritePositionAttribute(inline);
                    }
                    Write('>');
                }

                if (isClosing)
                {
                    Write("</strong>");
                }
                break;

            case InlineTag.Emphasis:
                ignoreChildNodes = false;

                if (isOpening)
                {
                    Write("<em");
                    if (Settings.TrackSourcePosition)
                    {
                        WritePositionAttribute(inline);
                    }
                    Write('>');
                }

                if (isClosing)
                {
                    Write("</em>");
                }
                break;

            case InlineTag.Strikethrough:
                ignoreChildNodes = false;

                if (isOpening)
                {
                    Write("<s");
                    if (Settings.TrackSourcePosition)
                    {
                        WritePositionAttribute(inline);
                    }
                    Write('>');
                }

                if (isClosing)
                {
                    Write("</s>");
                }
                break;

            case InlineTag.Placeholder:
                ignoreChildNodes = false;

                if (isOpening)
                {
                    string placeholderSubstitute = null;

                    try
                    {
                        placeholderSubstitute = (_placeholderResolver != null) ? _placeholderResolver(inline.TargetUrl) : null;
                    }
                    catch (Exception ex)
                    {
                        throw new CommonMarkException("An error occurred while resolving a placeholder.", ex);
                    }

                    if (placeholderSubstitute != null)
                    {
                        ignoreChildNodes = true;

                        if (Settings.TrackSourcePosition)
                        {
                            WritePositionAttribute(inline);
                        }
                        Write(placeholderSubstitute);
                        _endPlaceholders.Push('\0');
                    }
                    else
                    {
                        ignoreChildNodes = false;
                        Write("[");
                        _endPlaceholders.Push(']');
                    }
                }
                if (isClosing)
                {
                    var closingChar = _endPlaceholders.Pop();

                    if (closingChar != '\0')
                    {
                        Write(closingChar);
                    }
                }
                break;

            default:
                throw new CommonMarkException("Inline type " + inline.Tag + " is not supported.", inline);
            }
        }
예제 #2
0
        /// <summary>
        /// Writes the inline list to the given writer as HTML code.
        /// </summary>
        private static void InlinesToHtml(HtmlTextWriter writer, Inline inline, CommonMarkSettings settings, Stack <InlineStackEntry> stack)
        {
            var    uriResolver     = settings.UriResolver;
            bool   withinLink      = false;
            bool   stackWithinLink = false;
            bool   visitChildren;
            bool   trackPositions = settings.TrackSourcePosition;
            string stackLiteral   = null;

            while (inline != null)
            {
                visitChildren = false;

                switch (inline.Tag)
                {
                case InlineTag.String:
                    if (trackPositions)
                    {
                        writer.WriteConstant("<span");
                        PrintPosition(writer, inline);
                        writer.Write('>');
                        EscapeHtml(inline.LiteralContentValue, writer);
                        writer.WriteConstant("</span>");
                    }
                    else
                    {
                        EscapeHtml(inline.LiteralContentValue, writer);
                    }

                    break;

                case InlineTag.LineBreak:
                    writer.WriteLineConstant("<br />");
                    break;

                case InlineTag.SoftBreak:
                    if (settings.RenderSoftLineBreaksAsLineBreaks)
                    {
                        writer.WriteLineConstant("<br />");
                    }
                    else
                    {
                        if (settings.RenderEmptyLines)
                        {
                            writer.WriteEmptyLine();
                        }
                        else
                        {
                            writer.WriteLine();
                        }
                    }
                    break;

                case InlineTag.Code:
                    writer.WriteConstant("<code");
                    if (trackPositions)
                    {
                        PrintPosition(writer, inline);
                    }
                    writer.Write('>');
                    EscapeHtml(inline.LiteralContentValue, writer);
                    writer.WriteConstant("</code>");
                    break;

                case InlineTag.RawHtml:
                    if (settings.HtmlEntityEncode)
                    {
                        EscapeHtml(inline.LiteralContentValue, writer);
                    }
                    else
                    {
                        // cannot output source position for HTML blocks
                        writer.Write(inline.LiteralContentValue);
                    }
                    break;

                case InlineTag.Link:
                    if (withinLink)
                    {
                        writer.Write('[');
                        stackLiteral    = "]";
                        stackWithinLink = true;
                        visitChildren   = true;
                    }
                    else
                    {
                        writer.WriteConstant("<a href=\"");
                        if (uriResolver != null)
                        {
                            EscapeUrl(uriResolver(inline.TargetUrl), writer);
                        }
                        else
                        {
                            EscapeUrl(inline.TargetUrl, writer);
                        }

                        writer.Write('\"');
                        if (inline.LiteralContentValue.Length > 0)
                        {
                            writer.WriteConstant(" title=\"");
                            EscapeHtml(inline.LiteralContentValue, writer);
                            writer.Write('\"');
                        }

                        if (trackPositions)
                        {
                            PrintPosition(writer, inline);
                        }

                        writer.Write('>');

                        visitChildren   = true;
                        stackWithinLink = true;
                        stackLiteral    = "</a>";
                    }
                    break;

                case InlineTag.Image:
                    writer.WriteConstant("<img src=\"");
                    if (uriResolver != null)
                    {
                        EscapeUrl(uriResolver(inline.TargetUrl), writer);
                    }
                    else
                    {
                        EscapeUrl(inline.TargetUrl, writer);
                    }

                    writer.WriteConstant("\" alt=\"");
                    InlinesToPlainText(writer, inline.FirstChild, stack);
                    writer.Write('\"');
                    if (inline.LiteralContentValue.Length > 0)
                    {
                        writer.WriteConstant(" title=\"");
                        EscapeHtml(inline.LiteralContentValue, writer);
                        writer.Write('\"');
                    }

                    if (trackPositions)
                    {
                        PrintPosition(writer, inline);
                    }
                    writer.WriteConstant(" />");

                    break;

                case InlineTag.Strong:
                    writer.WriteConstant("<strong");
                    if (trackPositions)
                    {
                        PrintPosition(writer, inline);
                    }
                    writer.Write('>');
                    stackLiteral    = "</strong>";
                    stackWithinLink = withinLink;
                    visitChildren   = true;
                    break;

                case InlineTag.Emphasis:
                    writer.WriteConstant("<em");
                    if (trackPositions)
                    {
                        PrintPosition(writer, inline);
                    }
                    writer.Write('>');
                    stackLiteral    = "</em>";
                    visitChildren   = true;
                    stackWithinLink = withinLink;
                    break;

                case InlineTag.Strikethrough:
                    writer.WriteConstant("<s");
                    if (trackPositions)
                    {
                        PrintPosition(writer, inline);
                    }
                    writer.Write('>');
                    stackLiteral    = "</s>";
                    visitChildren   = true;
                    stackWithinLink = withinLink;
                    break;

                case InlineTag.Placeholder:
                    // the slim formatter will treat placeholders like literals, without applying any further processing
                    writer.Write('[');
                    if (trackPositions)
                    {
                        PrintPosition(writer, inline);
                    }
                    stackLiteral    = "]";
                    stackWithinLink = withinLink;
                    visitChildren   = true;
                    break;

                default:
                    throw new CommonMarkException("Inline type " + inline.Tag + " is not supported.", inline);
                }

                if (visitChildren)
                {
                    stack.Push(new InlineStackEntry(stackLiteral, inline.NextSibling, withinLink));

                    withinLink = stackWithinLink;
                    inline     = inline.FirstChild;
                }
                else if (inline.NextSibling != null)
                {
                    inline = inline.NextSibling;
                }
                else
                {
                    inline = null;
                }

                while (inline == null && stack.Count > 0)
                {
                    var entry = stack.Pop();
                    writer.WriteConstant(entry.Literal);
                    inline     = entry.Target;
                    withinLink = entry.IsWithinLink;
                }
            }
        }