Beispiel #1
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, CommonMarkSettings 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)
                {
                    sc = block.StringContent;
                    if (sc != null)
                    {
                        sc.FillSubject(subj);
                        delta = subj.Position;

                        block.InlineContent = InlineMethods.parse_inlines(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;
                }
            }
        }
Beispiel #2
0
        public static void Finalize(Block b, LineInfo line)
        {
            // don't do anything if the block is already closed
            if (!b.IsOpen)
            {
                return;
            }

            b.IsOpen = false;

            if (line.IsTrackingPositions)
            {
                // HTML Blocks other than type 7 call Finalize when the last line is encountered.
                // Block types 6 and 7 calls Finalize once it finds the next empty row but that empty row is no longer considered to be part of the block.
                var includesThisLine = b.HtmlBlockType != HtmlBlockType.None && b.HtmlBlockType != HtmlBlockType.InterruptingBlock && b.HtmlBlockType != HtmlBlockType.NonInterruptingBlock;

                // (b.SourcePosition >= line.LineOffset) determines if the block started on this line.
                includesThisLine = includesThisLine || b.SourcePosition >= line.LineOffset;

                if (includesThisLine && line.Line != null)
                {
                    b.SourceLastPosition = line.CalculateOrigin(line.Line.Length, false);
                }
                else
                {
                    b.SourceLastPosition = line.CalculateOrigin(0, false);
                }
            }

#pragma warning disable 0618
            b.EndLine = (line.LineNumber > b.StartLine) ? line.LineNumber - 1 : line.LineNumber;
#pragma warning restore 0618

            switch (b.Tag)
            {
            case BlockTag.Paragraph:
                var sc = b.StringContent;
                if (!sc.StartsWith('['))
                {
                    break;
                }

                var subj = new Subject(b.Top.Document);
                sc.FillSubject(subj);
                var origPos = subj.Position;
                while (subj.Position < subj.Buffer.Length &&
                       subj.Buffer[subj.Position] == '[' &&
                       0 != InlineMethods.ParseReference(subj))
                {
                }

                if (subj.Position != origPos)
                {
                    sc.Replace(subj.Buffer, subj.Position, subj.Buffer.Length - subj.Position);

                    if (sc.PositionTracker != null)
                    {
                        sc.PositionTracker.AddBlockOffset(subj.Position - origPos);
                    }

                    if (Utilities.IsFirstLineBlank(subj.Buffer, subj.Position))
                    {
                        b.Tag = BlockTag.ReferenceDefinition;
                    }
                }

                break;

            case BlockTag.IndentedCode:
                b.StringContent.RemoveTrailingBlankLines();
                break;

            case BlockTag.FencedCode:
                // first line of contents becomes info
                var firstlinelen = b.StringContent.IndexOf('\n') + 1;
                b.FencedCodeData.Info = InlineMethods.Unescape(b.StringContent.TakeFromStart(firstlinelen, true).Trim());
                break;

            case BlockTag.List:            // determine tight/loose status
                b.ListData.IsTight = true; // tight by default
                var   item = b.FirstChild;
                Block subitem;

                while (item != null)
                {
                    // check for non-final non-empty list item ending with blank line:
                    if (item.IsLastLineBlank && item.NextSibling != null)
                    {
                        b.ListData.IsTight = false;
                        break;
                    }

                    // recurse into children of list item, to see if there are spaces between them:
                    subitem = item.FirstChild;
                    while (subitem != null)
                    {
                        if (EndsWithBlankLine(subitem) && (item.NextSibling != null || subitem.NextSibling != null))
                        {
                            b.ListData.IsTight = false;
                            break;
                        }

                        subitem = subitem.NextSibling;
                    }

                    if (!b.ListData.IsTight)
                    {
                        break;
                    }

                    item = item.NextSibling;
                }

                break;
            }
        }
Beispiel #3
0
        public static void PostProcessInlineStack(Subject subj, InlineStack first, InlineStack last, InlineStackPriority ignorePriority)
        {
            while (ignorePriority > 0)
            {
                var istack = first;
                while (istack != null)
                {
                    if (istack.Priority >= ignorePriority)
                    {
                        RemoveStackEntry(istack, subj, istack);
                    }
                    else if (0 != (istack.Flags & InlineStackFlags.Closer))
                    {
                        bool canClose;
                        var  iopener = FindMatchingOpener(istack.Previous, istack.Priority, istack.Delimiter, istack.DelimiterCount, (istack.Flags & InlineStackFlags.Opener) > 0, out canClose);
                        if (iopener != null)
                        {
                            bool retry = false;
                            if (iopener.Delimiter == '~')
                            {
                                InlineMethods.MatchInlineStack(iopener, subj, istack.DelimiterCount, istack, 0, InlineTag.Strikethrough);
                                if (istack.DelimiterCount > 1)
                                {
                                    retry = true;
                                }
                            }
                            else
                            {
                                var useDelims = InlineMethods.MatchInlineStack(iopener, subj, istack.DelimiterCount, istack, InlineTag.Emphasis, InlineTag.Strong);
                                if (istack.DelimiterCount > 0)
                                {
                                    retry = true;
                                }
                            }

                            if (retry)
                            {
                                // remove everything between opened and closer (not inclusive).
                                if (istack.Previous != null && iopener.Next != istack.Previous)
                                {
                                    RemoveStackEntry(iopener.Next, subj, istack.Previous);
                                }

                                continue;
                            }
                            // remove opener, everything in between, and the closer
                            RemoveStackEntry(iopener, subj, istack);
                        }
                        else if (!canClose)
                        {
                            // this case means that a matching opener does not exist
                            // remove the Closer flag so that a future Opener can be matched against it.
                            istack.Flags &= ~InlineStackFlags.Closer;
                        }
                    }

                    if (istack == last)
                    {
                        break;
                    }

                    istack = istack.Next;
                }

                ignorePriority--;
            }
        }