Example #1
0
        /// <summary>
        /// Creates a new top-level document block.
        /// </summary>
        internal static Block CreateDocument(PandocMarkSettings settings)
        {
            Block e = new Block(BlockTag.Document, 0)
            {
                Document = new DocumentData(settings.ExternalReferences)
            };

            e.Top = e;
            return(e);
        }
Example #2
0
        /// <summary>Initializes a new instance of the <see cref="HtmlFormatter" /> class.</summary>
        /// <param name="target">The target text writer.</param>
        /// <param name="settings">The settings used when formatting the data.</param>
        /// <exception cref="ArgumentNullException">when <paramref name="target"/> is <see langword="null"/></exception>
        public HtmlFormatter(TextWriter target, PandocMarkSettings settings)
        {
            if (target is null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            if (settings is null)
            {
                settings = PandocMarkSettings.Default;
            }

            _target  = new HtmlTextWriter(target);
            Settings = settings;
        }
 static AbstractSyntaxTree()
 {
     CommonMarkSettings = PandocMarkSettings.Default.Clone();
     CommonMarkSettings.TrackSourcePosition = true;
 }
Example #4
0
        /// <summary>
        /// Write the block data to the given writer.
        /// </summary>
        public static void PrintBlocks(TextWriter writer, Block block, PandocMarkSettings settings)
        {
            int indent         = 0;
            var stack          = new Stack <BlockStackEntry>();
            var inlineStack    = new Stack <InlineStackEntry>();
            var buffer         = new StringBuilder();
            var trackPositions = settings.TrackSourcePosition;

            while (block != null)
            {
                writer.Write(new string(' ', indent));

                switch (block.Tag)
                {
                case BlockTag.Document:
                    writer.Write("document");
                    PrintPosition(trackPositions, writer, block);
                    break;

                case BlockTag.BlockQuote:
                    writer.Write("block_quote");
                    PrintPosition(trackPositions, writer, block);
                    break;

                case BlockTag.ListItem:
                    writer.Write("list_item");
                    PrintPosition(trackPositions, writer, block);
                    break;

                case BlockTag.List:
                    writer.Write("list");
                    PrintPosition(trackPositions, writer, block);

                    var data = block.ListData;
                    if (data.ListType == ListType.Ordered)
                    {
                        writer.Write(" (type=ordered tight={0} start={1} delim={2})",
                                     data.IsTight,
                                     data.Start,
                                     data.Delimiter);
                    }
                    else
                    {
                        writer.Write("(type=bullet tight={0} bullet_char={1})",
                                     data.IsTight,
                                     data.BulletChar);
                    }
                    break;

                case BlockTag.AtxHeading:
                    writer.Write("atx_heading");
                    PrintPosition(trackPositions, writer, block);
                    writer.Write(" (level={0})", block.Heading.Level);
                    break;

                case BlockTag.SetextHeading:
                    writer.Write("setext_heading");
                    PrintPosition(trackPositions, writer, block);
                    writer.Write(" (level={0})", block.Heading.Level);
                    break;

                case BlockTag.Paragraph:
                    writer.Write("paragraph");
                    PrintPosition(trackPositions, writer, block);
                    break;

                case BlockTag.ThematicBreak:
                    writer.Write("thematic_break");
                    PrintPosition(trackPositions, writer, block);
                    break;

                case BlockTag.IndentedCode:
                    writer.Write("indented_code {0}", FormatString(block.StringContent.ToString(buffer), buffer));
                    PrintPosition(trackPositions, writer, block);
                    writer.Write(' ');
                    writer.Write(FormatString(block.StringContent.ToString(buffer), buffer));
                    break;

                case BlockTag.FencedCode:
                    writer.Write("fenced_code");
                    PrintPosition(trackPositions, writer, block);
                    writer.Write(" length={0} info={1} {2}",
                                 block.FencedCodeData.FenceLength,
                                 FormatString(block.FencedCodeData.Info, buffer),
                                 FormatString(block.StringContent.ToString(buffer), buffer));
                    break;

                case BlockTag.HtmlBlock:
                    writer.Write("html_block");
                    PrintPosition(trackPositions, writer, block);
                    writer.Write(' ');
                    writer.Write(FormatString(block.StringContent.ToString(buffer), buffer));
                    break;

                case BlockTag.ReferenceDefinition:
                    writer.Write("reference_def");
                    PrintPosition(trackPositions, writer, block);
                    break;

                default:
                    throw new PandocMarkException("Block type " + block.Tag + " is not supported.", block);
                }

                writer.WriteLine();

                if (block.InlineContent != null)
                {
                    PrintInlines(writer, block.InlineContent, indent + 2, inlineStack, buffer, trackPositions);
                }

                if (block.FirstChild != null)
                {
                    if (block.NextSibling != null)
                    {
                        stack.Push(new BlockStackEntry(indent, block.NextSibling));
                    }

                    indent += 2;
                    block   = block.FirstChild;
                }
                else if (block.NextSibling != null)
                {
                    block = block.NextSibling;
                }
                else if (stack.Count > 0)
                {
                    var entry = stack.Pop();
                    indent = entry.Indent;
                    block  = entry.Target;
                }
                else
                {
                    block = null;
                }
            }
        }
Example #5
0
        /// <summary>
        /// Walk through the block, its children and siblings, parsing string content into inline content where appropriate.
        /// </summary>
        /// <param name="block">The document level block from which to start the processing.</param>
        /// <param name="data">Document data.</param>
        /// <param name="settings">The settings that influence how the inline parsing is performed.</param>
        public static void ProcessInlines(Block block, DocumentData data, PandocMarkSettings settings)
        {
            Stack <Inline> inlineStack       = null;
            var            stack             = new Stack <Block>();
            var            parsers           = settings.InlineParsers;
            var            specialCharacters = settings.InlineParserSpecialCharacters;
            var            subj = new Subject(data);

            StringContent sc;
            int           delta;

            while (block != null)
            {
                var tag = block.Tag;
                if (tag == BlockTag.Paragraph ||
                    tag == BlockTag.AtxHeading ||
                    tag == BlockTag.SetextHeading ||
                    (tag == BlockTag.HtmlBlock && block.HtmlBlockType == HtmlBlockType.Comment))
                {
                    sc = block.StringContent;
                    if (sc != null)
                    {
                        sc.FillSubject(subj);
                        delta = subj.Position;

                        if (tag == BlockTag.HtmlBlock)
                        {
                            block.InlineContent = InlineMethods.ParseHtmlInline(subj);
                        }
                        else
                        {
                            block.InlineContent = InlineMethods.ParseUInline(subj, parsers, specialCharacters);
                            block.StringContent = null;
                        }

                        if (sc.PositionTracker != null)
                        {
                            sc.PositionTracker.AddBlockOffset(-delta);
                            AdjustInlineSourcePosition(block.InlineContent, sc.PositionTracker, ref inlineStack);
                        }
                    }
                }

                if (block.FirstChild != null)
                {
                    if (block.NextSibling != null)
                    {
                        stack.Push(block.NextSibling);
                    }

                    block = block.FirstChild;
                }
                else if (block.NextSibling != null)
                {
                    block = block.NextSibling;
                }
                else if (stack.Count > 0)
                {
                    block = stack.Pop();
                }
                else
                {
                    block = null;
                }
            }
        }
Example #6
0
        /// <summary>
        /// Writes the inline list to the given writer as HTML code.
        /// </summary>
        private static void InlinesToHtml(HtmlTextWriter writer, Inline inline, PandocMarkSettings 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
                    {
                        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:
                    // 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("<del");
                    if (trackPositions)
                    {
                        PrintPosition(writer, inline);
                    }
                    writer.Write('>');
                    stackLiteral    = "</del>";
                    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 PandocMarkException("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 is null && stack.Count > 0)
                {
                    var entry = stack.Pop();
                    writer.WriteConstant(entry.Literal);
                    inline     = entry.Target;
                    withinLink = entry.IsWithinLink;
                }
            }
        }
Example #7
0
        private static void BlocksToHtmlInner(HtmlTextWriter writer, Block block, PandocMarkSettings settings)
        {
            var    stack       = new Stack <BlockStackEntry>();
            var    inlineStack = new Stack <InlineStackEntry>();
            bool   visitChildren;
            string stackLiteral   = null;
            bool   stackTight     = false;
            bool   tight          = false;
            bool   trackPositions = settings.TrackSourcePosition;
            int    x;

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

                switch (block.Tag)
                {
                case BlockTag.Document:
                    stackLiteral  = null;
                    stackTight    = false;
                    visitChildren = true;
                    break;

                case BlockTag.Paragraph:
                    if (tight)
                    {
                        InlinesToHtml(writer, block.InlineContent, settings, inlineStack);
                    }
                    else
                    {
                        writer.EnsureLine();
                        writer.WriteConstant("<p");
                        if (trackPositions)
                        {
                            PrintPosition(writer, block);
                        }
                        writer.Write('>');
                        InlinesToHtml(writer, block.InlineContent, settings, inlineStack);
                        writer.WriteLineConstant("</p>");
                    }
                    break;

                case BlockTag.BlockQuote:
                    writer.EnsureLine();
                    writer.WriteConstant("<blockquote");
                    if (trackPositions)
                    {
                        PrintPosition(writer, block);
                    }
                    writer.WriteLine('>');

                    stackLiteral  = "</blockquote>";
                    stackTight    = false;
                    visitChildren = true;
                    break;

                case BlockTag.ListItem:
                    writer.EnsureLine();
                    writer.WriteConstant("<li");
                    if (trackPositions)
                    {
                        PrintPosition(writer, block);
                    }
                    writer.Write('>');

                    stackLiteral  = "</li>";
                    stackTight    = tight;
                    visitChildren = true;
                    break;

                case BlockTag.List:
                    // make sure a list starts at the beginning of the line:
                    writer.EnsureLine();
                    var data = block.ListData;
                    writer.WriteConstant(data.ListType == ListType.Bullet ? "<ul" : "<ol");
                    if (data.Start != 1)
                    {
                        writer.WriteConstant(" start=\"");
                        writer.WriteConstant(data.Start.ToString(CultureInfo.InvariantCulture));
                        writer.Write('\"');
                    }
                    if (trackPositions)
                    {
                        PrintPosition(writer, block);
                    }
                    writer.WriteLine('>');

                    stackLiteral  = data.ListType == ListType.Bullet ? "</ul>" : "</ol>";
                    stackTight    = data.IsTight;
                    visitChildren = true;
                    break;

                case BlockTag.AtxHeading:
                case BlockTag.SetextHeading:
                    writer.EnsureLine();

                    x = block.Heading.Level;

                    if (trackPositions)
                    {
                        writer.WriteConstant("<h" + x.ToString(CultureInfo.InvariantCulture));
                        PrintPosition(writer, block);
                        writer.Write('>');
                        InlinesToHtml(writer, block.InlineContent, settings, inlineStack);
                        writer.WriteLineConstant(x > 0 && x < 7 ? HeadingCloserTags[x - 1] : "</h" + x.ToString(CultureInfo.InvariantCulture) + ">");
                    }
                    else
                    {
                        writer.WriteConstant(x > 0 && x < 7 ? HeadingOpenerTags[x - 1] : "<h" + x.ToString(CultureInfo.InvariantCulture) + ">");
                        InlinesToHtml(writer, block.InlineContent, settings, inlineStack);
                        writer.WriteLineConstant(x > 0 && x < 7 ? HeadingCloserTags[x - 1] : "</h" + x.ToString(CultureInfo.InvariantCulture) + ">");
                    }

                    break;

                case BlockTag.IndentedCode:
                case BlockTag.FencedCode:
                    writer.EnsureLine();
                    writer.WriteConstant("<pre><code");
                    if (trackPositions)
                    {
                        PrintPosition(writer, block);
                    }

                    var info = block.FencedCodeData?.Info;
                    if (info != null && info.Length > 0)
                    {
                        x = info.IndexOf(' ');
                        if (x == -1)
                        {
                            x = info.Length;
                        }

                        writer.WriteConstant(" class=\"language-");
                        EscapeHtml(new StringPart(info, 0, x), writer);
                        writer.Write('\"');
                    }
                    writer.Write('>');
                    EscapeHtml(block.StringContent, writer);
                    writer.WriteLineConstant("</code></pre>");
                    break;

                case BlockTag.HtmlBlock:
                    // cannot output source position for HTML blocks
                    block.StringContent.WriteTo(writer);

                    break;

                case BlockTag.ThematicBreak:
                    if (trackPositions)
                    {
                        writer.WriteConstant("<hr");
                        PrintPosition(writer, block);
                        writer.WriteLine();
                    }
                    else
                    {
                        writer.WriteLineConstant("<hr />");
                    }

                    break;

                case BlockTag.ReferenceDefinition:
                    break;

                default:
                    throw new PandocMarkException("Block type " + block.Tag + " is not supported.", block);
                }

                if (visitChildren)
                {
                    stack.Push(new BlockStackEntry(stackLiteral, block.NextSibling, tight));

                    tight = stackTight;
                    block = block.FirstChild;
                }
                else if (block.NextSibling != null)
                {
                    block = block.NextSibling;
                }
                else
                {
                    block = null;
                }

                while (block is null && stack.Count > 0)
                {
                    var entry = stack.Pop();

                    if (entry.Literal != null)
                    {
                        writer.WriteLineConstant(entry.Literal);
                    }

                    tight = entry.IsTight;
                    block = entry.Target;
                }
            }
        }
Example #8
0
        public static void BlocksToHtml(TextWriter writer, Block block, PandocMarkSettings settings)
        {
            var wrapper = new HtmlTextWriter(writer);

            BlocksToHtmlInner(wrapper, block, settings);
        }